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