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