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