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