1 /* Link with -lfpe. See man pages for fpc 2 * and /usr/include/sigfpe.h, sys/fpu.h. 3 */ 4 #include "dat.h" 5 #include "fns.h" 6 #include "error.h" 7 #include <time.h> 8 #include <ulocks.h> 9 #include <termios.h> 10 #include <sigfpe.h> 11 #include <sys/prctl.h> 12 #include <sys/fpu.h> 13 #include <sys/cachectl.h> 14 #undef _POSIX_SOURCE /* SGI incompetence */ 15 #include <signal.h> 16 #define _BSD_TIME 17 /* for gettimeofday(), which isn't POSIX, 18 * but is fairly common 19 */ 20 #include <sys/time.h> 21 #define _POSIX_SOURCE 22 #include <pwd.h> 23 24 extern int rebootargc; 25 extern char** rebootargv; 26 27 int gidnobody = -1; 28 int uidnobody = -1; 29 Proc** Xup; 30 31 #define MAXSPROC 30000 /* max procs == MAXPID */ 32 static int sproctbl[MAXSPROC]; 33 34 enum 35 { 36 KSTACK = 64*1024, 37 DELETE = 0x7F 38 }; 39 char *hosttype = "Irix"; 40 char *cputype = "mips"; 41 42 extern int dflag; 43 44 void 45 pexit(char *msg, int t) 46 { 47 Osenv *e; 48 49 lock(&procs.l); 50 if(up->prev) 51 up->prev->next = up->next; 52 else 53 procs.head = up->next; 54 55 if(up->next) 56 up->next->prev = up->prev; 57 else 58 procs.tail = up->prev; 59 60 sproctbl[getpid()] = -1; 61 62 unlock(&procs.l); 63 64 /* print("pexit: %s: %s\n", up->text, msg); /**/ 65 e = up->env; 66 if(e != nil) { 67 closefgrp(e->fgrp); 68 closepgrp(e->pgrp); 69 closeegrp(e->egrp); 70 closesigs(e->sigs); 71 } 72 free(up->prog); 73 free(up); 74 exit(0); 75 } 76 77 static void 78 tramp(void *p, size_t stacksz) 79 { 80 up = p; 81 up->sigid = getpid(); 82 up->func(up->arg); 83 pexit("", 0); 84 } 85 86 void 87 kproc(char *name, void (*func)(void*), void *arg, int flags) 88 { 89 Proc *p; 90 Pgrp *pg; 91 Fgrp *fg; 92 Egrp *eg; 93 int pid; 94 int id; 95 int i; 96 97 p = newproc(); 98 99 if(flags & KPDUPPG) { 100 pg = up->env->pgrp; 101 incref(&pg->r); 102 p->env->pgrp = pg; 103 } 104 if(flags & KPDUPFDG) { 105 fg = up->env->fgrp; 106 incref(&fg->r); 107 p->env->fgrp = fg; 108 } 109 if(flags & KPDUPENVG) { 110 eg = up->env->egrp; 111 incref(&eg->r); 112 p->env->egrp = eg; 113 } 114 115 p->env->uid = up->env->uid; 116 p->env->gid = up->env->gid; 117 kstrdup(&p->env->user, up->env->user); 118 119 strcpy(p->text, name); 120 121 p->func = func; 122 p->arg = arg; 123 124 lock(&procs.l); 125 if(procs.tail != nil) { 126 p->prev = procs.tail; 127 procs.tail->next = p; 128 } 129 else { 130 procs.head = p; 131 p->prev = nil; 132 } 133 procs.tail = p; 134 135 for(i = 1; i < MAXSPROC; i++) { 136 if(sproctbl[i] == -1) { 137 break; 138 } 139 } 140 141 if(i==MAXSPROC) 142 return -1; 143 144 sproctbl[i] = -i - 1; /* temporary hold of table index outside of lock */ 145 146 unlock(&procs.l); 147 148 pid = sprocsp(tramp, PR_SALL, p, 0, KSTACK); 149 150 if(pid >= 0) 151 sproctbl[i] = pid; 152 else 153 sproctbl[i] = -1; 154 } 155 156 void 157 osblock(void) 158 { 159 blockproc(up->sigid); 160 } 161 162 void 163 osready(Proc *p) 164 { 165 unblockproc(p->sigid); 166 } 167 168 void 169 trapUSR1(void) 170 { 171 int intwait; 172 173 intwait = up->intwait; 174 up->intwait = 0; /* clear it to let proc continue in osleave */ 175 176 if(up->type != Interp) /* Used to unblock pending I/O */ 177 return; 178 179 if(intwait == 0) /* Not posted so it's a sync error */ 180 disfault(nil, Eintr); /* Should never happen */ 181 } 182 183 void 184 trapILL(void) 185 { 186 disfault(nil, "Illegal instruction"); 187 } 188 189 void 190 trapBUS(void) 191 { 192 disfault(nil, "Bus error"); 193 } 194 195 void 196 trapSEGV(void) 197 { 198 disfault(nil, "Segmentation violation"); 199 } 200 201 /* 202 * This is not a signal handler but rather a vector from real/FPcontrol-Irix.c 203 */ 204 void 205 trapFPE(unsigned exception[5], int value[2]) 206 { 207 disfault(nil, "Floating point exception"); 208 } 209 210 void 211 oshostintr(Proc *p) 212 { 213 kill(p->sigid, SIGUSR1); 214 } 215 216 void 217 oslongjmp(void *regs, osjmpbuf env, int val) 218 { 219 USED(regs); 220 siglongjmp(env, val); 221 } 222 223 static struct termios tinit; 224 225 static void 226 termset(void) 227 { 228 struct termios t; 229 230 tcgetattr(0, &t); 231 tinit = t; 232 t.c_lflag &= ~(ICANON|ECHO|ISIG); 233 t.c_cc[VMIN] = 1; 234 t.c_cc[VTIME] = 0; 235 tcsetattr(0, TCSANOW, &t); 236 } 237 238 static void 239 termrestore(void) 240 { 241 tcsetattr(0, TCSANOW, &tinit); 242 243 /* if(sproctbl[0] < 0) 244 panic("corrupt sproc tbl"); 245 246 kill(sproctbl[0], SIGUSR2); 247 sginap(10000); */ 248 } 249 250 void 251 trapUSR2(void) 252 { 253 int i; 254 255 for(i = MAXSPROC - 1; i > 0; i--) { 256 if(sproctbl[i] != -1) 257 kill(sproctbl[i], SIGKILL); 258 sproctbl[i] = -1; 259 } 260 261 execvp(rebootargv[0], rebootargv); 262 panic("reboot failure"); 263 } 264 265 void 266 cleanexit(int x) 267 { 268 USED(x); 269 270 if(up->intwait) { 271 up->intwait = 0; 272 return; 273 } 274 275 if(dflag == 0) 276 termrestore(); 277 kill(0, SIGKILL); 278 exit(0); 279 } 280 281 void 282 getnobody(void) 283 { 284 struct passwd *pwd; 285 286 pwd = getpwnam("nobody"); 287 if(pwd != nil) { 288 uidnobody = pwd->pw_uid; 289 gidnobody = pwd->pw_gid; 290 } 291 } 292 293 void 294 osreboot(char *file, char **argv) 295 { 296 if(dflag == 0) 297 termrestore(); 298 execvp(file, argv); 299 panic("reboot failure"); 300 } 301 302 void 303 libinit(char *imod) 304 { 305 struct sigaction act; 306 struct passwd *pw; 307 int i; 308 char sys[64]; 309 310 setsid(); 311 312 for(i=0; i<MAXSPROC; i++) 313 sproctbl[i] = -1; 314 315 sproctbl[0] = getpid(); 316 317 gethostname(sys, sizeof(sys)); 318 kstrdup(&ossysname, sys); 319 320 if(dflag == 0) 321 termset(); 322 323 if(signal(SIGTERM, SIG_IGN) != SIG_IGN) 324 signal(SIGTERM, cleanexit); 325 if(signal(SIGINT, SIG_IGN) != SIG_IGN) 326 signal(SIGINT, cleanexit); 327 signal(SIGUSR2, trapUSR2); 328 /* For the correct functioning of devcmd in the 329 * face of exiting slaves 330 */ 331 signal(SIGCLD, SIG_IGN); 332 signal(SIGPIPE, SIG_IGN); 333 memset(&act, 0 , sizeof(act)); 334 act.sa_handler=trapUSR1; 335 sigaction(SIGUSR1, &act, nil); 336 if(sflag == 0) { 337 act.sa_handler=trapBUS; 338 sigaction(SIGBUS, &act, nil); 339 act.sa_handler=trapILL; 340 sigaction(SIGILL, &act, nil); 341 act.sa_handler=trapSEGV; 342 sigaction(SIGSEGV, &act, nil); 343 } 344 345 if(usconfig(CONF_INITUSERS, 1000) < 0) 346 panic("usconfig"); 347 348 Xup = (Proc**)PRDA->usr_prda.fill; 349 up = newproc(); 350 351 pw = getpwuid(getuid()); 352 if(pw != nil) { 353 if (strlen(pw->pw_name) + 1 <= KNAMELEN) 354 strcpy(eve, pw->pw_name); 355 else 356 print("pw_name too long\n"); 357 } 358 else 359 print("cannot getpwuid\n"); 360 361 /* after setting up, since this takes locks */ 362 getnobody(); 363 up->env->uid = getuid(); 364 up->env->gid = getgid(); 365 emuinit(imod); 366 } 367 368 int 369 readkbd(void) 370 { 371 int n; 372 char buf[1]; 373 374 n = read(0, buf, sizeof(buf)); 375 if(n < 0) 376 fprint(2, "keyboard read error: %s\n", strerror(errno)); 377 if(n <= 0) 378 pexit("keyboard thread", 0); 379 switch(buf[0]) { 380 case '\r': 381 buf[0] = '\n'; 382 break; 383 case DELETE: 384 cleanexit(0); 385 break; 386 } 387 return buf[0]; 388 } 389 390 int 391 segflush(void *a, ulong n) 392 { 393 cacheflush(a, n, BCACHE); 394 return 0; 395 } 396 397 /* 398 * Return an abitrary millisecond clock time 399 */ 400 long 401 osmillisec(void) 402 { 403 static long sec0 = 0, usec0; 404 struct timeval t; 405 406 if(gettimeofday(&t,(struct timezone*)0)<0) 407 return(0); 408 if(sec0==0){ 409 sec0 = t.tv_sec; 410 usec0 = t.tv_usec; 411 } 412 return((t.tv_sec-sec0)*1000+(t.tv_usec-usec0+500)/1000); 413 } 414 415 /* 416 * Return the time since the epoch in nanoseconds and microseconds 417 * The epoch is defined at 1 Jan 1970 418 */ 419 vlong 420 osnsec(void) 421 { 422 struct timeval t; 423 424 gettimeofday(&t, nil); 425 return (vlong)t.tv_sec*1000000000L + t.tv_usec*1000; 426 } 427 428 vlong 429 osusectime(void) 430 { 431 struct timeval t; 432 433 gettimeofday(&t, nil); 434 return (vlong)t.tv_sec * 1000000 + t.tv_usec; 435 } 436 437 int 438 osmillisleep(ulong milsec) 439 { 440 static int tick; 441 442 /* 443 * Posix-conforming CLK_TCK implementations tend to call sysconf, 444 * and we don't need the overhead. 445 */ 446 if(tick == 0) 447 tick = CLK_TCK; 448 sginap((tick*milsec)/1000); 449 return 0; 450 } 451 452 int 453 limbosleep(ulong milsec) 454 { 455 return osmillisleep(milsec); 456 } 457 458 void 459 osyield(void) 460 { 461 sginap(0); 462 } 463 464 void 465 ospause(void) 466 { 467 for(;;) 468 pause(); 469 } 470 471 void 472 oslopri(void) 473 { 474 nice(2); 475 } 476