void Exit(char *stat) { Updenv(); setstatus(stat); exits(truestatus()?"":getstatus()); }
void Xsimple(void) { word *a; thread *p = runq; var *v; struct builtin *bp; int pid; globlist(); a = runq->argv->words; if(a==0){ Xerror1("empty argument list"); return; } if(flag['x']) pfmt(err, "%v\n", p->argv->words); /* wrong, should do redirs */ v = gvlook(a->word); if(v->fn) execfunc(v); else{ if(strcmp(a->word, "builtin")==0){ if(count(a)==1){ pfmt(err, "builtin: empty argument list\n"); setstatus("empty arg list"); poplist(); return; } a = a->next; popword(); } for(bp = Builtin;bp->name;bp++) if(strcmp(a->word, bp->name)==0){ (*bp->fnc)(); return; } if(exitnext()){ /* fork and wait is redundant */ pushword("exec"); execexec(); Xexit(); } else{ flush(err); Updenv(); /* necessary so changes don't go out again */ if((pid = execforkexec()) < 0){ Xerror("try again"); return; } /* interrupts don't get us out */ poplist(); while(Waitfor(pid, 1) < 0) ; } } }
void Execute(word *args, word *path) { char **argv = mkargv(args); char file[1024], errstr[1024]; int nc; Updenv(); errstr[0] = '\0'; for(;path;path = path->next){ nc = strlen(path->word); if(nc < sizeof file - 1){ /* 1 for / */ strcpy(file, path->word); if(file[0]){ strcat(file, "/"); nc++; } if(nc + strlen(argv[1]) < sizeof file){ strcat(file, argv[1]); exec(file, argv+1); rerrstr(errstr, sizeof errstr); /* * if file exists and is executable, exec should * have worked, unless it's a directory or an * executable for another architecture. in * particular, if it failed due to lack of * swap/vm (e.g., arg. list too long) or other * allocation failure, stop searching and print * the reason for failure. */ if (strstr(errstr, " allocat") != nil || strstr(errstr, " full") != nil) break; } else werrstr("command name too long"); } } pfmt(err, "%s: %s\n", argv[1], errstr); efree((char *)argv); }