1 #include "dat.h" 2 #include "fns.h" 3 #include "error.h" 4 #undef _POSIX_C_SOURCE 5 #undef getwd 6 #include <unistd.h> 7 #include <thread.h> 8 #include <time.h> 9 #include <termios.h> 10 #include <signal.h> 11 #include <pwd.h> 12 #include <sys/resource.h> 13 #include <sys/time.h> 14 15 enum 16 { 17 DELETE = 0x7F 18 }; 19 char *hosttype = "Unixware"; 20 21 static thread_key_t prdakey; 22 23 static siginfo_t siginfo; 24 25 extern int dflag; 26 27 Proc* 28 getup(void) 29 { 30 void *vp; 31 32 if (thr_getspecific(prdakey, &vp)) 33 return nil; 34 return vp; 35 } 36 37 void 38 pexit(char *msg, int t) 39 { 40 Osenv *e; 41 42 lock(&procs.l); 43 if(up->prev) 44 up->prev->next = up->next; 45 else 46 procs.head = up->next; 47 48 if(up->next) 49 up->next->prev = up->prev; 50 else 51 procs.tail = up->prev; 52 unlock(&procs.l); 53 54 /*print("pexit: %s: %s\n", up->text, msg);*/ 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 free(up->prog); 63 sema_destroy(up->os); 64 free(up->os); 65 free(up); 66 thr_exit(0); 67 } 68 69 static void * 70 tramp(void *v) 71 { 72 struct Proc *Up; 73 74 if(thr_setspecific(prdakey, v)) { 75 print("set specific data failed in tramp\n"); 76 thr_exit(0); 77 } 78 Up = v; 79 Up->sigid = thr_self(); 80 Up->func(Up->arg); 81 pexit("", 0); 82 } 83 84 void 85 kproc(char *name, void (*func)(void*), void *arg, int flags) 86 { 87 thread_t thread; 88 Proc *p; 89 Pgrp *pg; 90 Fgrp *fg; 91 Egrp *eg; 92 sema_t *sem; 93 94 p = newproc(); 95 96 sem = malloc(sizeof(*sem)); 97 if(sem == nil) 98 panic("can't allocate semaphore"); 99 sema_init(sem, 0, USYNC_THREAD, 0); 100 p->os = sem; 101 102 if(flags & KPDUPPG) { 103 pg = up->env->pgrp; 104 incref(&pg->r); 105 p->env->pgrp = pg; 106 } 107 if(flags & KPDUPFDG) { 108 fg = up->env->fgrp; 109 incref(&fg->r); 110 p->env->fgrp = fg; 111 } 112 if(flags & KPDUPENVG) { 113 eg = up->env->egrp; 114 incref(&eg->r); 115 p->env->egrp = eg; 116 } 117 118 p->env->uid = up->env->uid; 119 p->env->gid = up->env->gid; 120 kstrdup(&p->env->user, up->env->user); 121 122 strcpy(p->text, name); 123 124 p->func = func; 125 p->arg = arg; 126 127 lock(&procs.l); 128 if(procs.tail != nil) { 129 p->prev = procs.tail; 130 procs.tail->next = p; 131 } 132 else { 133 procs.head = p; 134 p->prev = nil; 135 } 136 procs.tail = p; 137 unlock(&procs.l); 138 139 if(thr_create(0, 0, &tramp, p, THR_BOUND|THR_DETACHED, &thread)) 140 panic("thr_create failed\n"); 141 thr_yield(); 142 } 143 144 /* to get pc on trap use siginfo.si_pc field and define all trap handlers 145 as printILL - have to set sa_sigaction, sa_flags not sa_handler 146 */ 147 148 static void 149 trapUSR1(void) 150 { 151 int intwait; 152 153 intwait = up->intwait; 154 up->intwait = 0; /* clear it to let proc continue in osleave */ 155 156 if(up->type != Interp) /* Used to unblock pending I/O */ 157 return; 158 159 if(intwait == 0) /* Not posted so it's a sync error */ 160 disfault(nil, Eintr); /* Should never happen */ 161 } 162 163 static void 164 trapILL(void) 165 { 166 disfault(nil, "Illegal instruction"); 167 } 168 169 static void 170 printILL(int sig, siginfo_t *siginfo, void *v) 171 { 172 panic("Illegal instruction with code=%d at address=%x, opcode=%x.\n", 173 siginfo->si_code, siginfo->si_addr,*(char*)siginfo->si_addr); 174 } 175 176 static void 177 trapBUS(void) 178 { 179 disfault(nil, "Bus error"); 180 } 181 182 static void 183 trapSEGV(void) 184 { 185 disfault(nil, "Segmentation violation"); 186 } 187 188 static void 189 trapFPE(void) 190 { 191 disfault(nil, "Floating point exception"); 192 } 193 194 void 195 oshostintr(Proc *p) 196 { 197 thr_kill(p->sigid, SIGUSR1); 198 } 199 200 void 201 osblock(void) 202 { 203 while(sema_wait(up->os)) 204 ; /* retry on signals */ 205 } 206 207 void 208 osready(Proc *p) 209 { 210 sema_post(p->os); 211 } 212 213 void 214 oslongjmp(void *regs, osjmpbuf env, int val) 215 { 216 USED(regs); 217 siglongjmp(env, val); 218 } 219 220 static struct termios tinit; 221 222 static void 223 termset(void) 224 { 225 struct termios t; 226 227 tcgetattr(0, &t); 228 tinit = t; 229 t.c_lflag &= ~(ICANON|ECHO|ISIG); 230 t.c_cc[VMIN] = 1; 231 t.c_cc[VTIME] = 0; 232 tcsetattr(0, TCSANOW, &t); 233 } 234 235 static void 236 termrestore(void) 237 { 238 tcsetattr(0, TCSANOW, &tinit); 239 } 240 241 void 242 cleanexit(int x) 243 { 244 USED(x); 245 246 if(up->intwait) { 247 up->intwait = 0; 248 return; 249 } 250 251 if(dflag == 0) 252 termrestore(); 253 exit(0); 254 } 255 256 int gidnobody= -1, uidnobody= -1; 257 258 void 259 getnobody(void) 260 { 261 struct passwd *pwd; 262 263 if (pwd=getpwnam("nobody")) { 264 uidnobody = pwd->pw_uid; 265 gidnobody = pwd->pw_gid; 266 } 267 } 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 278 void 279 libinit(char *imod) 280 { 281 struct Proc *Up; 282 struct sigaction act; 283 struct passwd *pw; 284 char sys[64]; 285 286 setsid(); 287 288 if(dflag == 0) 289 termset(); 290 291 gethostname(sys, sizeof(sys)); 292 kstrdup(&ossysname, sys); 293 getnobody(); 294 295 memset(&act, 0 , sizeof(act)); 296 act.sa_handler=trapUSR1; 297 sigaction(SIGUSR1, &act, nil); 298 /* 299 * For the correct functioning of devcmd in the 300 * face of exiting slaves 301 */ 302 signal(SIGPIPE, SIG_IGN); 303 if(signal(SIGTERM, SIG_IGN) != SIG_IGN) 304 signal(SIGTERM, cleanexit); 305 if(sflag == 0) { 306 act.sa_handler = trapBUS; 307 sigaction(SIGBUS, &act, nil); 308 act.sa_handler = trapILL; 309 sigaction(SIGILL, &act, nil); 310 act.sa_handler = trapSEGV; 311 sigaction(SIGSEGV, &act, nil); 312 act.sa_handler = trapFPE; 313 sigaction(SIGFPE, &act, nil); 314 if(signal(SIGINT, SIG_IGN) != SIG_IGN) 315 signal(SIGINT, cleanexit); 316 } else{ 317 act.sa_sigaction = printILL; 318 act.sa_flags=SA_SIGINFO; 319 sigaction(SIGILL, &act, nil); 320 } 321 322 if(thr_keycreate(&prdakey,NULL)) 323 print("keycreate failed\n"); 324 325 Up = newproc(); 326 if(thr_setspecific(prdakey,Up)) 327 panic("set specific thread data failed\n"); 328 329 pw = getpwuid(getuid()); 330 if(pw != nil) 331 kstrdup(&eve, pw->pw_name); 332 else 333 print("cannot getpwuid\n"); 334 335 up->env->uid = getuid(); 336 up->env->gid = getgid(); 337 emuinit(imod); 338 } 339 340 int 341 readkbd(void) 342 { 343 int n; 344 char buf[1]; 345 346 n = read(0, buf, sizeof(buf)); 347 if(n < 0) 348 fprint(2, "keyboard read: %s\n", strerror(errno)); 349 if(n <= 0) 350 pexit("keyboard thread", 0); 351 352 switch(buf[0]) { 353 case '\r': 354 buf[0] = '\n'; 355 break; 356 case DELETE: 357 cleanexit(0); 358 break; 359 } 360 return buf[0]; 361 } 362 363 /* 364 * Return an abitrary millisecond clock time 365 */ 366 long 367 osmillisec(void) 368 { 369 static long sec0 = 0, usec0; 370 struct timeval t; 371 372 if(gettimeofday(&t, NULL)<0) 373 return(0); 374 if(sec0==0){ 375 sec0 = t.tv_sec; 376 usec0 = t.tv_usec; 377 } 378 return((t.tv_sec-sec0)*1000+(t.tv_usec-usec0+500)/1000); 379 } 380 381 /* 382 * Return the time since the epoch in microseconds 383 * The epoch is defined at 1 Jan 1970 384 */ 385 vlong 386 osnsec(void) 387 { 388 struct timeval t; 389 390 gettimeofday(&t, nil); 391 return (vlong)t.tv_sec*1000000000L + t.tv_usec*1000; 392 } 393 394 vlong 395 osusectime(void) 396 { 397 struct timeval t; 398 399 gettimeofday(&t, nil); 400 return (vlong)t.tv_sec * 1000000 + t.tv_usec; 401 } 402 403 int 404 osmillisleep(ulong milsec) 405 { 406 struct timespec time; 407 408 time.tv_sec = milsec/1000; 409 time.tv_nsec= (milsec%1000)*1000000; 410 nanosleep(&time,nil); 411 return 0; 412 } 413 414 int 415 limbosleep(ulong milsec) 416 { 417 return osmillisleep(milsec); 418 } 419 420 void 421 osyield(void) 422 { 423 thr_yield(); 424 } 425 426 void 427 ospause(void) 428 { 429 for(;;) 430 pause(); 431 } 432 433 void 434 oslopri(void) 435 { 436 setpriority(PRIO_PROCESS, 0, getpriority(PRIO_PROCESS,0)+4); 437 } 438