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 itoa(wstatstr, wstat); 207 setstatus(wstatstr); 208 break; 209 } 210 else{ 211 for(p=runq->ret;p;p=p->ret) 212 if(p->pid==wpid){ 213 p->pid=-1; 214 itoa(p->status, wstat); 215 break; 216 } 217 } 218 } 219 } 220 char **mkargv(a) 221 register struct word *a; 222 { 223 char **argv=(char **)emalloc((count(a)+2)*sizeof(char *)); 224 register char **argp=argv+1; /* leave one at front for runcoms */ 225 for(;a;a=a->next) *argp++=a->word; 226 *argp=0; 227 return argv; 228 } 229 Updenv(){} 230 Execute(args, path) 231 register struct word *args, *path; 232 { 233 register char *msg="not found"; 234 register int txtbusy=0; 235 char **env=mkenv(); 236 char **argv=mkargv(args); 237 char file[512]; 238 for(;path;path=path->next){ 239 strcpy(file, path->word); 240 if(file[0]) strcat(file, "/"); 241 strcat(file, argv[1]); 242 ReExec: 243 execve(file, argv+1, env); 244 switch(errno){ 245 case ENOEXEC: 246 pfmt(err, "%s: Bourne again\n", argv[1]); 247 argv[0]="sh"; 248 argv[1]=strdup(file); 249 execve("/bin/sh", argv, env); 250 goto Bad; 251 case ETXTBSY: 252 if(++txtbusy!=5){ 253 sleep(txtbusy); 254 goto ReExec; 255 } 256 msg="text busy"; goto Bad; 257 case EACCES: msg="no access"; break; 258 case ENOMEM: msg="not enough memory"; goto Bad; 259 case E2BIG: msg="too big"; goto Bad; 260 } 261 } 262 Bad: 263 pfmt(err, "%s: %s\n", argv[1], msg); 264 efree((char *)env); 265 efree((char *)argv); 266 } 267 #define NDIR 14 /* should get this from param.h */ 268 Globsize(p) 269 register char *p; 270 { 271 int isglob=0, globlen=NDIR+1; 272 for(;*p;p++){ 273 if(*p==GLOB){ 274 p++; 275 if(*p!=GLOB) isglob++; 276 globlen+=*p=='*'?NDIR:1; 277 } 278 else 279 globlen++; 280 } 281 return isglob?globlen:0; 282 } 283 #include <sys/types.h> 284 #include <ndir.h> 285 #define NDIRLIST 50 286 DIR *dirlist[NDIRLIST]; 287 Opendir(name) 288 char *name; 289 { 290 register DIR **dp; 291 for(dp=dirlist;dp!=&dirlist[NDIRLIST];dp++) 292 if(*dp==0){ 293 *dp=opendir(name); 294 return *dp?dp-dirlist:-1; 295 } 296 return -1; 297 } 298 Readdir(f, p, onlydirs) 299 register int f; 300 register char *p; 301 register int onlydirs; /* ignored, just advisory */ 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