os.c 8.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531
  1. #include "dat.h"
  2. #include "fns.h"
  3. #include "error.h"
  4. #undef getwd
  5. #include <signal.h>
  6. #include <sys/socket.h>
  7. #include <time.h>
  8. #include <sys/time.h>
  9. #include <termios.h>
  10. #include <sched.h>
  11. #include <pwd.h>
  12. #include <errno.h>
  13. #include <unistd.h>
  14. #include <sys/resource.h>
  15. enum
  16. {
  17. DELETE = 0x7F,
  18. NSTACKSPERALLOC = 16,
  19. X11STACK= 256*1024
  20. };
  21. char *hosttype = "FreeBSD";
  22. extern void unlockandexit(int*);
  23. extern void executeonnewstack(void*, void (*f)(void*), void*);
  24. static void *stackalloc(Proc *p, void **tos);
  25. static void stackfreeandexit(void *stack);
  26. extern int dflag;
  27. void
  28. pexit(char *msg, int t)
  29. {
  30. Osenv *e;
  31. Proc *p;
  32. void *kstack;
  33. lock(&procs.l);
  34. p = up;
  35. if(p->prev)
  36. p->prev->next = p->next;
  37. else
  38. procs.head = p->next;
  39. if(up->next)
  40. p->next->prev = p->prev;
  41. else
  42. procs.tail = p->prev;
  43. unlock(&procs.l);
  44. if(0)
  45. print("pexit: %s: %s\n", up->text, msg);
  46. e = up->env;
  47. if(e != nil) {
  48. closefgrp(e->fgrp);
  49. closepgrp(e->pgrp);
  50. closeegrp(e->egrp);
  51. closesigs(e->sigs);
  52. }
  53. kstack = p->kstack;
  54. free(p->prog);
  55. free(p);
  56. if(kstack != nil)
  57. stackfreeandexit(kstack);
  58. }
  59. void
  60. trapBUS(int signo, siginfo_t *info, void *context)
  61. {
  62. if(info)
  63. print("trapBUS: signo: %d code: %d addr: %lx\n",
  64. info->si_signo, info->si_code, info->si_addr);
  65. else
  66. print("trapBUS: no info\n");
  67. disfault(nil, "Bus error");
  68. }
  69. static void
  70. trapUSR1(int signo)
  71. {
  72. int intwait;
  73. USED(signo);
  74. intwait = up->intwait;
  75. up->intwait = 0; /* clear it to let proc continue in osleave */
  76. if(up->type != Interp) /* Used to unblock pending I/O */
  77. return;
  78. if(intwait == 0) /* Not posted so its a sync error */
  79. disfault(nil, Eintr); /* Should never happen */
  80. }
  81. static void
  82. trapUSR2(int signo)
  83. {
  84. USED(signo);
  85. /* we've done our work of interrupting sigsuspend */
  86. }
  87. static void
  88. trapILL(int signo)
  89. {
  90. disfault(nil, "Illegal instruction");
  91. }
  92. static void
  93. trapSEGV(int signo)
  94. {
  95. disfault(nil, "Segmentation violation");
  96. }
  97. static void
  98. trapFPE(int signo)
  99. {
  100. char buf[64];
  101. USED(signo);
  102. snprint(buf, sizeof(buf), "sys: fp: exception status=%.4lux", getfsr());
  103. disfault(nil, buf);
  104. }
  105. static sigset_t initmask;
  106. static void
  107. setsigs(void)
  108. {
  109. struct sigaction act;
  110. sigset_t mask;
  111. memset(&act, 0 , sizeof(act));
  112. sigemptyset(&initmask);
  113. signal(SIGPIPE, SIG_IGN); /* prevent signal when devcmd child exits */
  114. if(signal(SIGTERM, SIG_IGN) != SIG_IGN)
  115. signal(SIGTERM, cleanexit);
  116. act.sa_handler = trapUSR1;
  117. act.sa_mask = initmask;
  118. sigaction(SIGUSR1, &act, nil);
  119. act.sa_handler = trapUSR2;
  120. sigaction(SIGUSR2, &act, nil);
  121. sigemptyset(&mask);
  122. sigaddset(&mask, SIGUSR2);
  123. sigaddset(&initmask, SIGUSR2);
  124. sigprocmask(SIG_BLOCK, &mask, NULL);
  125. /*
  126. * prevent Zombies forming when any process terminates
  127. */
  128. act.sa_sigaction = 0;
  129. act.sa_flags |= SA_NOCLDWAIT;
  130. if(sigaction(SIGCHLD, &act, nil))
  131. panic("sigaction SIGCHLD");
  132. if(sflag == 0) {
  133. act.sa_sigaction = trapBUS;
  134. act.sa_flags |= SA_SIGINFO;
  135. if(sigaction(SIGBUS, &act, nil))
  136. panic("sigaction SIGBUS");
  137. act.sa_handler = trapILL;
  138. if(sigaction(SIGILL, &act, nil))
  139. panic("sigaction SIGBUS");
  140. act.sa_handler = trapSEGV;
  141. if(sigaction(SIGSEGV, &act, nil))
  142. panic("sigaction SIGSEGV");
  143. act.sa_handler = trapFPE;
  144. if(sigaction(SIGFPE, &act, nil))
  145. panic("sigaction SIGFPE");
  146. if(sigaddset(&initmask, SIGINT) == -1)
  147. panic("sigaddset");
  148. }
  149. if(sigprocmask(SIG_BLOCK, &initmask, nil)!= 0)
  150. panic("sigprocmask");
  151. }
  152. static int
  153. tramp(void *arg)
  154. {
  155. Proc *p;
  156. p = arg;
  157. p->pid = p->sigid = getpid();
  158. sigprocmask(SIG_BLOCK, &initmask, nil); /* in 5.3, rfork_thread doesn't copy from parent, contrary to docs? */
  159. (*p->func)(p->arg);
  160. pexit("{Tramp}", 0);
  161. _exit(0);
  162. }
  163. void
  164. kproc(char *name, void (*func)(void*), void *arg, int flags)
  165. {
  166. Proc *p;
  167. Pgrp *pg;
  168. Fgrp *fg;
  169. Egrp *eg;
  170. int pid;
  171. void *tos;
  172. p = newproc();
  173. if(flags & KPDUPPG) {
  174. pg = up->env->pgrp;
  175. incref(&pg->r);
  176. p->env->pgrp = pg;
  177. }
  178. if(flags & KPDUPFDG) {
  179. fg = up->env->fgrp;
  180. incref(&fg->r);
  181. p->env->fgrp = fg;
  182. }
  183. if(flags & KPDUPENVG) {
  184. eg = up->env->egrp;
  185. incref(&eg->r);
  186. p->env->egrp = eg;
  187. }
  188. p->env->uid = up->env->uid;
  189. p->env->gid = up->env->gid;
  190. kstrdup(&p->env->user, up->env->user);
  191. strcpy(p->text, name);
  192. p->func = func;
  193. p->arg = arg;
  194. lock(&procs.l);
  195. if(procs.tail != nil) {
  196. p->prev = procs.tail;
  197. procs.tail->next = p;
  198. }
  199. else {
  200. procs.head = p;
  201. p->prev = nil;
  202. }
  203. procs.tail = p;
  204. unlock(&procs.l);
  205. if(flags & KPX11){
  206. p->kstack = nil; /* never freed; also up not defined */
  207. tos = (char*)mallocz(X11STACK, 0) + X11STACK - sizeof(void*);
  208. }else
  209. p->kstack = stackalloc(p, &tos);
  210. pid = rfork_thread(RFPROC|RFMEM|RFNOWAIT, tos, tramp, p);
  211. if(pid < 0)
  212. panic("rfork");
  213. }
  214. void
  215. oshostintr(Proc *p)
  216. {
  217. kill(p->sigid, SIGUSR1);
  218. }
  219. void
  220. osblock(void)
  221. {
  222. sigset_t mask;
  223. sigprocmask(SIG_SETMASK, NULL, &mask);
  224. sigdelset(&mask, SIGUSR2);
  225. sigsuspend(&mask);
  226. }
  227. void
  228. osready(Proc *p)
  229. {
  230. if(kill(p->sigid, SIGUSR2) < 0)
  231. fprint(2, "emu: osready failed: pid %d: %s\n", p->sigid, strerror(errno));
  232. }
  233. void
  234. oslongjmp(void *regs, osjmpbuf env, int val)
  235. {
  236. USED(regs);
  237. siglongjmp(env, val);
  238. }
  239. struct termios tinit;
  240. static void
  241. termset(void)
  242. {
  243. struct termios t;
  244. tcgetattr(0, &t);
  245. tinit = t;
  246. t.c_lflag &= ~(ICANON|ECHO|ISIG);
  247. t.c_cc[VMIN] = 1;
  248. t.c_cc[VTIME] = 0;
  249. tcsetattr(0, TCSANOW, &t);
  250. }
  251. static void
  252. termrestore(void)
  253. {
  254. tcsetattr(0, TCSANOW, &tinit);
  255. }
  256. void
  257. cleanexit(int x)
  258. {
  259. USED(x);
  260. if(up->intwait) {
  261. up->intwait = 0;
  262. return;
  263. }
  264. if(dflag == 0)
  265. termrestore();
  266. kill(0, SIGKILL);
  267. exit(0);
  268. }
  269. void
  270. osreboot(char *file, char **argv)
  271. {
  272. if(dflag == 0)
  273. termrestore();
  274. execvp(file, argv);
  275. panic("reboot failure");
  276. }
  277. int gidnobody= -1, uidnobody= -1;
  278. void
  279. getnobody()
  280. {
  281. struct passwd *pwd;
  282. if(pwd = getpwnam("nobody")) {
  283. uidnobody = pwd->pw_uid;
  284. gidnobody = pwd->pw_gid;
  285. }
  286. }
  287. void
  288. libinit(char *imod)
  289. {
  290. struct passwd *pw;
  291. Proc *p;
  292. void *tos;
  293. char sys[64];
  294. setsid();
  295. gethostname(sys, sizeof(sys));
  296. kstrdup(&ossysname, sys);
  297. getnobody();
  298. if(dflag == 0)
  299. termset();
  300. setsigs();
  301. p = newproc();
  302. p->kstack = stackalloc(p, &tos);
  303. pw = getpwuid(getuid());
  304. if(pw != nil)
  305. kstrdup(&eve, pw->pw_name);
  306. else
  307. print("cannot getpwuid\n");
  308. p->env->uid = getuid();
  309. p->env->gid = getgid();
  310. executeonnewstack(tos, emuinit, imod);
  311. }
  312. int
  313. readkbd(void)
  314. {
  315. int n;
  316. char buf[1];
  317. n = read(0, buf, sizeof(buf));
  318. if(n < 0)
  319. print("keyboard close (n=%d, %s)\n", n, strerror(errno));
  320. if(n <= 0)
  321. pexit("keyboard thread", 0);
  322. switch(buf[0]) {
  323. case '\r':
  324. buf[0] = '\n';
  325. break;
  326. case DELETE:
  327. cleanexit(0);
  328. break;
  329. }
  330. return buf[0];
  331. }
  332. /*
  333. * Return an abitrary millisecond clock time
  334. */
  335. long
  336. osmillisec(void)
  337. {
  338. static long sec0 = 0, usec0;
  339. struct timeval t;
  340. if(gettimeofday(&t,(struct timezone*)0)<0)
  341. return 0;
  342. if(sec0==0) {
  343. sec0 = t.tv_sec;
  344. usec0 = t.tv_usec;
  345. }
  346. return (t.tv_sec-sec0)*1000+(t.tv_usec-usec0+500)/1000;
  347. }
  348. int
  349. limbosleep(ulong milsec)
  350. {
  351. return osmillisleep(milsec);
  352. }
  353. /*
  354. * Return the time since the epoch in nanoseconds and microseconds
  355. * The epoch is defined at 1 Jan 1970
  356. */
  357. vlong
  358. osnsec(void)
  359. {
  360. struct timeval t;
  361. gettimeofday(&t, nil);
  362. return (vlong)t.tv_sec*1000000000L + t.tv_usec*1000;
  363. }
  364. vlong
  365. osusectime(void)
  366. {
  367. struct timeval t;
  368. gettimeofday(&t, nil);
  369. return (vlong)t.tv_sec * 1000000 + t.tv_usec;
  370. }
  371. int
  372. osmillisleep(ulong milsec)
  373. {
  374. struct timespec time;
  375. time.tv_sec = milsec / 1000;
  376. time.tv_nsec = (milsec % 1000) * 1000000;
  377. nanosleep(&time, 0);
  378. return 0;
  379. }
  380. void
  381. osyield(void)
  382. {
  383. sched_yield();
  384. }
  385. void
  386. ospause(void)
  387. {
  388. for(;;)
  389. pause();
  390. }
  391. void
  392. oslopri(void)
  393. {
  394. setpriority(PRIO_PROCESS, 0, getpriority(PRIO_PROCESS,0)+4);
  395. }
  396. static struct {
  397. Lock l;
  398. void *free;
  399. } stacklist;
  400. static void
  401. _stackfree(void *stack)
  402. {
  403. *((void **)stack) = stacklist.free;
  404. stacklist.free = stack;
  405. }
  406. static void
  407. stackfreeandexit(void *stack)
  408. {
  409. lock(&stacklist.l);
  410. _stackfree(stack);
  411. unlockandexit(&stacklist.l.val);
  412. }
  413. static void *
  414. stackalloc(Proc *p, void **tos)
  415. {
  416. void *rv;
  417. lock(&stacklist.l);
  418. if (stacklist.free == 0) {
  419. int x;
  420. /*
  421. * obtain some more by using sbrk()
  422. */
  423. void *more = sbrk(KSTACK * (NSTACKSPERALLOC + 1));
  424. if (more == 0)
  425. panic("stackalloc: no more stacks");
  426. /*
  427. * align to KSTACK
  428. */
  429. more = (void *)((((unsigned long)more) + (KSTACK - 1)) & ~(KSTACK - 1));
  430. /*
  431. * free all the new stacks onto the freelist
  432. */
  433. for (x = 0; x < NSTACKSPERALLOC; x++)
  434. _stackfree((char *)more + KSTACK * x);
  435. }
  436. rv = stacklist.free;
  437. stacklist.free = *(void **)rv;
  438. unlock(&stacklist.l);
  439. *tos = rv + KSTACK - sizeof(void*);
  440. *(Proc **)rv = p;
  441. return rv;
  442. }
  443. int
  444. segflush(void *a, ulong n)
  445. {
  446. USED(a);
  447. USED(n);
  448. return 0;
  449. }