1 /* 2 * Unix versions of system-specific functions 3 * By convention, exported routines herein have names beginning with an 4 * upper case letter. 5 */ 6 #include "rc.h" 7 #include "io.h" 8 #include "exec.h" 9 #include "getflags.h" 10 #include <errno.h> 11 12 char *Rcmain = "/usr/lib/rcmain"; 13 char *Fdprefix = "/dev/fd/"; 14 15 void execfinit(void); 16 17 struct builtin Builtin[] = { 18 "cd", execcd, 19 "whatis", execwhatis, 20 "eval", execeval, 21 "exec", execexec, /* but with popword first */ 22 "exit", execexit, 23 "shift", execshift, 24 "wait", execwait, 25 "umask", execumask, 26 ".", execdot, 27 "finit", execfinit, 28 "flag", execflag, 29 0 30 }; 31 #define SEP '\1' 32 char **environp; 33 34 struct word* 35 enval(s) 36 register char *s; 37 { 38 char *t, c; 39 struct word *v; 40 for(t = s;*t && *t!=SEP;t++); 41 c=*t; 42 *t='\0'; 43 v = newword(s, c=='\0'?(struct word *)0:enval(t+1)); 44 *t = c; 45 return v; 46 } 47 48 void 49 Vinit(void) 50 { 51 extern char **environ; 52 char *s; 53 char **env = environ; 54 environp = env; 55 for(;*env;env++){ 56 for(s=*env;*s && *s!='(' && *s!='=';s++); 57 switch(*s){ 58 case '\0': 59 pfmt(err, "environment %q?\n", *env); 60 break; 61 case '=': 62 *s='\0'; 63 setvar(*env, enval(s+1)); 64 *s='='; 65 break; 66 case '(': /* ignore functions for now */ 67 break; 68 } 69 } 70 } 71 72 char **envp; 73 74 void 75 Xrdfn(void) 76 { 77 char *s; 78 int len; 79 for(;*envp;envp++){ 80 for(s=*envp;*s && *s!='(' && *s!='=';s++); 81 switch(*s){ 82 case '\0': 83 pfmt(err, "environment %q?\n", *envp); 84 break; 85 case '=': /* ignore variables */ 86 break; 87 case '(': /* Bourne again */ 88 s=*envp+3; 89 envp++; 90 len = strlen(s); 91 s[len]='\n'; 92 execcmds(opencore(s, len+1)); 93 s[len]='\0'; 94 return; 95 } 96 } 97 Xreturn(); 98 } 99 100 union code rdfns[4]; 101 102 void 103 execfinit(void) 104 { 105 static int first = 1; 106 if(first){ 107 rdfns[0].i = 1; 108 rdfns[1].f = Xrdfn; 109 rdfns[2].f = Xjump; 110 rdfns[3].i = 1; 111 first = 0; 112 } 113 Xpopm(); 114 envp = environp; 115 start(rdfns, 1, runq->local); 116 } 117 118 int 119 cmpenv(const void *aa, const void *ab) 120 { 121 char **a = aa, **b = ab; 122 123 return strcmp(*a, *b); 124 } 125 126 char ** 127 mkenv(void) 128 { 129 char **env, **ep, *p, *q; 130 struct var **h, *v; 131 struct word *a; 132 int nvar = 0, nchr = 0, sep; 133 134 /* 135 * Slightly kludgy loops look at locals then globals. 136 * locals no longer exist - geoff 137 */ 138 for(h = gvar-1; h != &gvar[NVAR]; h++) 139 for(v = h >= gvar? *h: runq->local; v ;v = v->next){ 140 if((v==vlook(v->name)) && v->val){ 141 nvar++; 142 nchr+=strlen(v->name)+1; 143 for(a = v->val;a;a = a->next) 144 nchr+=strlen(a->word)+1; 145 } 146 if(v->fn){ 147 nvar++; 148 nchr+=strlen(v->name)+strlen(v->fn[v->pc-1].s)+8; 149 } 150 } 151 env = (char **)emalloc((nvar+1)*sizeof(char *)+nchr); 152 ep = env; 153 p = (char *)&env[nvar+1]; 154 for(h = gvar-1; h != &gvar[NVAR]; h++) 155 for(v = h >= gvar? *h: runq->local;v;v = v->next){ 156 if((v==vlook(v->name)) && v->val){ 157 *ep++=p; 158 q = v->name; 159 while(*q) *p++=*q++; 160 sep='='; 161 for(a = v->val;a;a = a->next){ 162 *p++=sep; 163 sep = SEP; 164 q = a->word; 165 while(*q) *p++=*q++; 166 } 167 *p++='\0'; 168 } 169 if(v->fn){ 170 *ep++=p; 171 *p++='#'; *p++='('; *p++=')'; /* to fool Bourne */ 172 *p++='f'; *p++='n'; *p++=' '; 173 q = v->name; 174 while(*q) *p++=*q++; 175 *p++=' '; 176 q = v->fn[v->pc-1].s; 177 while(*q) *p++=*q++; 178 *p++='\0'; 179 } 180 } 181 *ep = 0; 182 qsort((void *)env, nvar, sizeof ep[0], cmpenv); 183 return env; 184 } 185 char *sigmsg[] = { 186 /* 0 normal */ 0, 187 /* 1 SIGHUP */ "Hangup", 188 /* 2 SIGINT */ 0, 189 /* 3 SIGQUIT */ "Quit", 190 /* 4 SIGILL */ "Illegal instruction", 191 /* 5 SIGTRAP */ "Trace/BPT trap", 192 /* 6 SIGIOT */ "abort", 193 /* 7 SIGEMT */ "EMT trap", 194 /* 8 SIGFPE */ "Floating exception", 195 /* 9 SIGKILL */ "Killed", 196 /* 10 SIGBUS */ "Bus error", 197 /* 11 SIGSEGV */ "Memory fault", 198 /* 12 SIGSYS */ "Bad system call", 199 /* 13 SIGPIPE */ 0, 200 /* 14 SIGALRM */ "Alarm call", 201 /* 15 SIGTERM */ "Terminated", 202 /* 16 unused */ "signal 16", 203 /* 17 SIGSTOP */ "Process stopped", 204 /* 18 unused */ "signal 18", 205 /* 19 SIGCONT */ "Process continued", 206 /* 20 SIGCHLD */ "Child death", 207 }; 208 209 void 210 Waitfor(int pid, int persist) 211 { 212 int wpid, sig; 213 struct thread *p; 214 int wstat; 215 char wstatstr[12]; 216 217 for(;;){ 218 errno = 0; 219 wpid = wait(&wstat); 220 if(errno==EINTR && persist) 221 continue; 222 if(wpid==-1) 223 break; 224 sig = wstat&0177; 225 if(sig==0177){ 226 pfmt(err, "trace: "); 227 sig = (wstat>>8)&0177; 228 } 229 if(sig>(sizeof sigmsg/sizeof sigmsg[0]) || sigmsg[sig]){ 230 if(pid!=wpid) 231 pfmt(err, "%d: ", wpid); 232 if(sig<=(sizeof sigmsg/sizeof sigmsg[0])) 233 pfmt(err, "%s", sigmsg[sig]); 234 else if(sig==0177) pfmt(err, "stopped by ptrace"); 235 else pfmt(err, "signal %d", sig); 236 if(wstat&0200)pfmt(err, " -- core dumped"); 237 pfmt(err, "\n"); 238 } 239 wstat = sig?sig+1000:(wstat>>8)&0xFF; 240 if(wpid==pid){ 241 inttoascii(wstatstr, wstat); 242 setstatus(wstatstr); 243 break; 244 } 245 else{ 246 for(p = runq->ret;p;p = p->ret) 247 if(p->pid==wpid){ 248 p->pid=-1; 249 inttoascii(p->status, wstat); 250 break; 251 } 252 } 253 } 254 } 255 256 char ** 257 mkargv(a) 258 register struct word *a; 259 { 260 char **argv = (char **)emalloc((count(a)+2)*sizeof(char *)); 261 char **argp = argv+1; /* leave one at front for runcoms */ 262 263 for(;a;a = a->next) 264 *argp++=a->word; 265 *argp = 0; 266 return argv; 267 } 268 269 void 270 Updenv(void) 271 { 272 } 273 274 void 275 Execute(struct word *args, struct word *path) 276 { 277 char *msg="not found"; 278 int txtbusy = 0; 279 char **env = mkenv(); 280 char **argv = mkargv(args); 281 char file[512]; 282 283 for(;path;path = path->next){ 284 strcpy(file, path->word); 285 if(file[0]) 286 strcat(file, "/"); 287 strcat(file, argv[1]); 288 ReExec: 289 execve(file, argv+1, env); 290 switch(errno){ 291 case ENOEXEC: 292 pfmt(err, "%s: Bourne again\n", argv[1]); 293 argv[0]="sh"; 294 argv[1] = strdup(file); 295 execve("/bin/sh", argv, env); 296 goto Bad; 297 case ETXTBSY: 298 if(++txtbusy!=5){ 299 sleep(txtbusy); 300 goto ReExec; 301 } 302 msg="text busy"; goto Bad; 303 case EACCES: 304 msg="no access"; 305 break; 306 case ENOMEM: 307 msg="not enough memory"; goto Bad; 308 case E2BIG: 309 msg="too big"; goto Bad; 310 } 311 } 312 Bad: 313 pfmt(err, "%s: %s\n", argv[1], msg); 314 efree((char *)env); 315 efree((char *)argv); 316 } 317 318 #define NDIR 14 /* should get this from param.h */ 319 320 Globsize(p) 321 register char *p; 322 { 323 int isglob = 0, globlen = NDIR+1; 324 for(;*p;p++){ 325 if(*p==GLOB){ 326 p++; 327 if(*p!=GLOB) 328 isglob++; 329 globlen+=*p=='*'?NDIR:1; 330 } 331 else 332 globlen++; 333 } 334 return isglob?globlen:0; 335 } 336 337 #include <sys/types.h> 338 #include <dirent.h> 339 340 #define NDIRLIST 50 341 342 DIR *dirlist[NDIRLIST]; 343 344 Opendir(name) 345 char *name; 346 { 347 DIR **dp; 348 for(dp = dirlist;dp!=&dirlist[NDIRLIST];dp++) 349 if(*dp==0){ 350 *dp = opendir(name); 351 return *dp?dp-dirlist:-1; 352 } 353 return -1; 354 } 355 356 int 357 Readdir(int f, char *p, int onlydirs) 358 { 359 struct dirent *dp = readdir(dirlist[f]); 360 361 if(dp==0) 362 return 0; 363 strcpy(p, dp->d_name); 364 return 1; 365 } 366 367 void 368 Closedir(int f) 369 { 370 closedir(dirlist[f]); 371 dirlist[f] = 0; 372 } 373 374 char *Signame[] = { 375 "sigexit", "sighup", "sigint", "sigquit", 376 "sigill", "sigtrap", "sigiot", "sigemt", 377 "sigfpe", "sigkill", "sigbus", "sigsegv", 378 "sigsys", "sigpipe", "sigalrm", "sigterm", 379 "sig16", "sigstop", "sigtstp", "sigcont", 380 "sigchld", "sigttin", "sigttou", "sigtint", 381 "sigxcpu", "sigxfsz", "sig26", "sig27", 382 "sig28", "sig29", "sig30", "sig31", 383 0, 384 }; 385 386 void 387 gettrap(int sig) 388 { 389 signal(sig, gettrap); 390 trap[sig]++; 391 ntrap++; 392 if(ntrap>=NSIG){ 393 pfmt(err, "rc: Too many traps (trap %d), dumping core\n", sig); 394 signal(SIGABRT, (void (*)())0); 395 kill(getpid(), SIGABRT); 396 } 397 } 398 399 void 400 Trapinit(void) 401 { 402 int i; 403 void (*sig)(); 404 405 if(1 || flag['d']){ /* wrong!!! */ 406 sig = signal(SIGINT, gettrap); 407 if(sig==SIG_IGN) 408 signal(SIGINT, SIG_IGN); 409 } 410 else{ 411 for(i = 1;i<=NSIG;i++) if(i!=SIGCHLD){ 412 sig = signal(i, gettrap); 413 if(sig==SIG_IGN) 414 signal(i, SIG_IGN); 415 } 416 } 417 } 418 419 Unlink(name) 420 char *name; 421 { 422 return unlink(name); 423 } 424 Write(fd, buf, cnt) 425 char *buf; 426 { 427 return write(fd, buf, cnt); 428 } 429 Read(fd, buf, cnt) 430 char *buf; 431 { 432 return read(fd, buf, cnt); 433 } 434 Seek(fd, cnt, whence) 435 long cnt; 436 { 437 return lseek(fd, cnt, whence); 438 } 439 Executable(file) 440 char *file; 441 { 442 return(access(file, 01)==0); 443 } 444 Creat(file) 445 char *file; 446 { 447 return creat(file, 0666); 448 } 449 Dup(a, b){ 450 return dup2(a, b); 451 } 452 Dup1(a){ 453 return dup(a); 454 } 455 /* 456 * Wrong: should go through components of a|b|c and return the maximum. 457 */ 458 void 459 Exit(char *stat) 460 { 461 int n = 0; 462 463 while(*stat){ 464 if(*stat!='|'){ 465 if(*stat<'0' || '9'<*stat) 466 exit(1); 467 else n = n*10+*stat-'0'; 468 } 469 stat++; 470 } 471 exit(n); 472 } 473 Eintr(){ 474 return errno==EINTR; 475 } 476 477 void 478 Noerror() 479 { 480 errno = 0; 481 } 482 Isatty(fd){ 483 return isatty(fd); 484 } 485 486 void 487 Abort() 488 { 489 abort(); 490 } 491 492 void 493 execumask(void) /* wrong -- should fork before writing */ 494 { 495 int m; 496 struct io out[1]; 497 switch(count(runq->argv->words)){ 498 default: 499 pfmt(err, "Usage: umask [umask]\n"); 500 setstatus("umask usage"); 501 poplist(); 502 return; 503 case 2: 504 umask(octal(runq->argv->words->next->word)); 505 break; 506 case 1: 507 umask(m = umask(0)); 508 out->fd = mapfd(1); 509 out->bufp = out->buf; 510 out->ebuf=&out->buf[NBUF]; 511 out->strp = 0; 512 pfmt(out, "%o\n", m); 513 break; 514 } 515 setstatus(""); 516 poplist(); 517 } 518 519 void 520 Memcpy(a, b, n) 521 char *a, *b; 522 { 523 memmove(a, b, n); 524 } 525 526 void* 527 Malloc(unsigned long n) 528 { 529 return (void *)malloc(n); 530 } 531 532 void 533 errstr(char *buf, int len) 534 { 535 strncpy(buf, strerror(errno), len); 536 } 537 538 int 539 needsrcquote(int c) 540 { 541 if(c <= ' ') 542 return 1; 543 if(strchr("`^#*[]=|\\?${}()'<>&;", c)) 544 return 1; 545 return 0; 546 } 547 548 int 549 rfork(int bits) 550 { 551 return fork(); 552 } 553 554 int *waitpids; 555 int nwaitpids; 556 557 void 558 addwaitpid(int pid) 559 { 560 waitpids = realloc(waitpids, (nwaitpids+1)*sizeof waitpids[0]); 561 if(waitpids == 0) 562 panic("Can't realloc %d waitpids", nwaitpids+1); 563 waitpids[nwaitpids++] = pid; 564 } 565 566 void 567 delwaitpid(int pid) 568 { 569 int r, w; 570 571 for(r=w=0; r<nwaitpids; r++) 572 if(waitpids[r] != pid) 573 waitpids[w++] = waitpids[r]; 574 nwaitpids = w; 575 } 576 577 void 578 clearwaitpids(void) 579 { 580 nwaitpids = 0; 581 } 582 583 int 584 havewaitpid(int pid) 585 { 586 int i; 587 588 for(i=0; i<nwaitpids; i++) 589 if(waitpids[i] == pid) 590 return 1; 591 return 0; 592 } 593