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 int 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 return(thread); 143 } 144 145 /* to get pc on trap use siginfo.si_pc field and define all trap handlers 146 as printILL - have to set sa_sigaction, sa_flags not sa_handler 147 */ 148 149 static void 150 trapUSR1(void) 151 { 152 int intwait; 153 154 intwait = up->intwait; 155 up->intwait = 0; /* clear it to let proc continue in osleave */ 156 157 if(up->type != Interp) /* Used to unblock pending I/O */ 158 return; 159 160 if(intwait == 0) /* Not posted so it's a sync error */ 161 disfault(nil, Eintr); /* Should never happen */ 162 } 163 164 static void 165 trapILL(void) 166 { 167 disfault(nil, "Illegal instruction"); 168 } 169 170 static void 171 printILL(int sig, siginfo_t *siginfo, void *v) 172 { 173 panic("Illegal instruction with code=%d at address=%x, opcode=%x.\n", 174 siginfo->si_code, siginfo->si_addr,*(char*)siginfo->si_addr); 175 } 176 177 static void 178 trapBUS(void) 179 { 180 disfault(nil, "Bus error"); 181 } 182 183 static void 184 trapSEGV(void) 185 { 186 disfault(nil, "Segmentation violation"); 187 } 188 189 static void 190 trapFPE(void) 191 { 192 disfault(nil, "Floating point exception"); 193 } 194 195 void 196 oshostintr(Proc *p) 197 { 198 thr_kill(p->sigid, SIGUSR1); 199 } 200 201 void 202 osblock(void) 203 { 204 while(sema_wait(up->os)) 205 ; /* retry on signals */ 206 } 207 208 void 209 osready(Proc *p) 210 { 211 sema_post(p->os); 212 } 213 214 void 215 oslongjmp(void *regs, osjmpbuf env, int val) 216 { 217 USED(regs); 218 siglongjmp(env, val); 219 } 220 221 static struct termios tinit; 222 223 static void 224 termset(void) 225 { 226 struct termios t; 227 228 tcgetattr(0, &t); 229 tinit = t; 230 t.c_lflag &= ~(ICANON|ECHO|ISIG); 231 t.c_cc[VMIN] = 1; 232 t.c_cc[VTIME] = 0; 233 tcsetattr(0, TCSANOW, &t); 234 } 235 236 static void 237 termrestore(void) 238 { 239 tcsetattr(0, TCSANOW, &tinit); 240 } 241 242 void 243 cleanexit(int x) 244 { 245 USED(x); 246 247 if(up->intwait) { 248 up->intwait = 0; 249 return; 250 } 251 252 if(dflag == 0) 253 termrestore(); 254 exit(0); 255 } 256 257 int gidnobody= -1, uidnobody= -1; 258 259 void 260 getnobody(void) 261 { 262 struct passwd *pwd; 263 264 if (pwd=getpwnam("nobody")) { 265 uidnobody = pwd->pw_uid; 266 gidnobody = pwd->pw_gid; 267 } 268 } 269 270 void 271 osreboot(char *file, char **argv) 272 { 273 if(dflag == 0) 274 termrestore(); 275 execvp(file, argv); 276 panic("reboot failure"); 277 } 278 279 void 280 libinit(char *imod) 281 { 282 struct Proc *Up; 283 struct sigaction act; 284 struct passwd *pw; 285 char sys[64]; 286 287 setsid(); 288 289 if(dflag == 0) 290 termset(); 291 292 gethostname(sys, sizeof(sys)); 293 kstrdup(&ossysname, sys); 294 getnobody(); 295 296 memset(&act, 0 , sizeof(act)); 297 act.sa_handler=trapUSR1; 298 sigaction(SIGUSR1, &act, nil); 299 /* 300 * For the correct functioning of devcmd in the 301 * face of exiting slaves 302 */ 303 signal(SIGPIPE, SIG_IGN); 304 if(signal(SIGTERM, SIG_IGN) != SIG_IGN) 305 signal(SIGTERM, cleanexit); 306 if(sflag == 0) { 307 act.sa_handler = trapBUS; 308 sigaction(SIGBUS, &act, nil); 309 act.sa_handler = trapILL; 310 sigaction(SIGILL, &act, nil); 311 act.sa_handler = trapSEGV; 312 sigaction(SIGSEGV, &act, nil); 313 act.sa_handler = trapFPE; 314 sigaction(SIGFPE, &act, nil); 315 if(signal(SIGINT, SIG_IGN) != SIG_IGN) 316 signal(SIGINT, cleanexit); 317 } else{ 318 act.sa_sigaction = printILL; 319 act.sa_flags=SA_SIGINFO; 320 sigaction(SIGILL, &act, nil); 321 } 322 323 if(thr_keycreate(&prdakey,NULL)) 324 print("keycreate failed\n"); 325 326 Up = newproc(); 327 if(thr_setspecific(prdakey,Up)) 328 panic("set specific thread data failed\n"); 329 330 pw = getpwuid(getuid()); 331 if(pw != nil) 332 kstrdup(&eve, pw->pw_name); 333 else 334 print("cannot getpwuid\n"); 335 336 up->env->uid = getuid(); 337 up->env->gid = getgid(); 338 emuinit(imod); 339 } 340 341 int 342 readkbd(void) 343 { 344 int n; 345 char buf[1]; 346 347 n = read(0, buf, sizeof(buf)); 348 if(n < 0) 349 fprint(2, "keyboard read: %s\n", strerror(errno)); 350 if(n <= 0) 351 pexit("keyboard thread", 0); 352 353 switch(buf[0]) { 354 case '\r': 355 buf[0] = '\n'; 356 break; 357 case DELETE: 358 cleanexit(0); 359 break; 360 } 361 return buf[0]; 362 } 363 364 /* 365 * Return an abitrary millisecond clock time 366 */ 367 long 368 osmillisec(void) 369 { 370 static long sec0 = 0, usec0; 371 struct timeval t; 372 373 if(gettimeofday(&t, NULL)<0) 374 return(0); 375 if(sec0==0){ 376 sec0 = t.tv_sec; 377 usec0 = t.tv_usec; 378 } 379 return((t.tv_sec-sec0)*1000+(t.tv_usec-usec0+500)/1000); 380 } 381 382 /* 383 * Return the time since the epoch in microseconds 384 * The epoch is defined at 1 Jan 1970 385 */ 386 vlong 387 osnsec(void) 388 { 389 struct timeval t; 390 391 gettimeofday(&t, nil); 392 return (vlong)t.tv_sec*1000000000L + t.tv_usec*1000; 393 } 394 395 vlong 396 osusectime(void) 397 { 398 struct timeval t; 399 400 gettimeofday(&t, nil); 401 return (vlong)t.tv_sec * 1000000 + t.tv_usec; 402 } 403 404 int 405 osmillisleep(ulong milsec) 406 { 407 struct timespec time; 408 409 time.tv_sec = milsec/1000; 410 time.tv_nsec= (milsec%1000)*1000000; 411 nanosleep(&time,nil); 412 return 0; 413 } 414 415 int 416 limbosleep(ulong milsec) 417 { 418 return osmillisleep(milsec); 419 } 420 421 void 422 osyield(void) 423 { 424 thr_yield(); 425 } 426 427 void 428 ospause(void) 429 { 430 for(;;) 431 pause(); 432 } 433 434 void 435 oslopri(void) 436 { 437 setpriority(PRIO_PROCESS, 0, getpriority(PRIO_PROCESS,0)+4); 438 } 439