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