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) 299 register int f; 300 register char *p; 301 { 302 struct direct *dp=readdir(dirlist[f]); 303 if(dp==0) return 0; 304 strcpy(p, dp->d_name); 305 return 1; 306 } 307 Closedir(f){ 308 closedir(dirlist[f]); 309 dirlist[f]=0; 310 } 311 char *Signame[]={ 312 "sigexit", "sighup", "sigint", "sigquit", 313 "sigill", "sigtrap", "sigiot", "sigemt", 314 "sigfpe", "sigkill", "sigbus", "sigsegv", 315 "sigsys", "sigpipe", "sigalrm", "sigterm", 316 "sig16", "sigstop", "sigtstp", "sigcont", 317 "sigchld", "sigttin", "sigttou", "sigtint", 318 "sigxcpu", "sigxfsz", "sig26", "sig27", 319 "sig28", "sig29", "sig30", "sig31", 320 0, 321 }; 322 int gettrap(sig){ 323 signal(sig, gettrap); 324 trap[sig]++; 325 ntrap++; 326 if(ntrap>=NSIG){ 327 pfmt(err, "rc: Too many traps (trap %d), dumping core\n", sig); 328 signal(SIGIOT, (int (*)())0); 329 kill(getpid(), SIGIOT); 330 } 331 } 332 Trapinit(){ 333 register int i; 334 register int (*sig)(); 335 if(1 || flag['d']){ /* wrong!!! */ 336 sig=signal(SIGINT, gettrap); 337 if(sig==SIG_IGN) signal(SIGINT, SIG_IGN); 338 } 339 else{ 340 for(i=1;i<=NSIG;i++) if(i!=SIGCHLD){ 341 sig=signal(i, gettrap); 342 if(sig==SIG_IGN) signal(i, SIG_IGN); 343 } 344 } 345 } 346 Unlink(name) 347 char *name; 348 { 349 return unlink(name); 350 } 351 Write(fd, buf, cnt) 352 char *buf; 353 { 354 return write(fd, buf, cnt); 355 } 356 Read(fd, buf, cnt) 357 char *buf; 358 { 359 return read(fd, buf, cnt); 360 } 361 Seek(fd, cnt, whence) 362 long cnt; 363 { 364 return lseek(fd, cnt, whence); 365 } 366 Executable(file) 367 char *file; 368 { 369 return(access(file, 01)==0); 370 } 371 Creat(file) 372 char *file; 373 { 374 return creat(file, 0666); 375 } 376 Dup(a, b){ 377 return dup2(a, b); 378 } 379 Dup1(a){ 380 return dup(a); 381 } 382 /* 383 * Wrong: should go through components of a|b|c and return the maximum. 384 */ 385 Exit(stat) 386 register char *stat; 387 { 388 register int n=0; 389 while(*stat){ 390 if(*stat!='|'){ 391 if(*stat<'0' || '9'<*stat) exit(1); 392 else n=n*10+*stat-'0'; 393 } 394 stat++; 395 } 396 exit(n); 397 } 398 Eintr(){ 399 return errno==EINTR; 400 } 401 Noerror(){ 402 errno=0; 403 } 404 Isatty(fd){ 405 return isatty(fd); 406 } 407 Abort(){ 408 abort(); 409 } 410 execumask(){ /* wrong -- should fork before writing */ 411 register int m; 412 struct io out[1]; 413 switch(count(runq->argv->words)){ 414 default: 415 pfmt(err, "Usage: umask [umask]\n"); 416 setstatus("umask usage"); 417 poplist(); 418 return; 419 case 2: umask(octal(runq->argv->words->next->word)); break; 420 case 1: 421 umask(m=umask(0)); 422 out->fd=mapfd(1); 423 out->bufp=out->buf; 424 out->ebuf=&out->buf[NBUF]; 425 out->strp=0; 426 pfmt(out, "%o\n", m); 427 break; 428 } 429 setstatus(""); 430 poplist(); 431 } 432 Memcpy(a, b, n) 433 char *a, *b; 434 { 435 memmove(a, b, n); 436 } 437 void *Malloc(n){ 438 return (void *)malloc(n); 439 } 440