PageRenderTime 40ms CodeModel.GetById 13ms RepoModel.GetById 0ms app.codeStats 0ms

/usr/brasil/emu/OpenBSD/os.c

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