2 * Maybe `simple' is a misnomer.
10 * Search through the following code to see if we're just going to exit.
14 union code *c=&runq->code[runq->pc];
15 while(c->f==Xpopredir) c++;
28 Xerror1("empty argument list");
32 pfmt(err, "%v\n", p->argv->words); /* wrong, should do redirs */
37 if(strcmp(a->word, "builtin")==0){
39 pfmt(err, "builtin: empty argument list\n");
40 setstatus("empty arg list");
47 for(bp=Builtin;bp->name;bp++)
48 if(strcmp(a->word, bp->name)==0){
53 /* fork and wait is redundant */
60 Updenv(); /* necessary so changes don't go out again */
69 strcpy(buf, "can't exec: ");
71 errstr(buf+n, ERRMAX-n);
76 /* interrupts don't get us out */
77 while(Waitfor(pid, 1) < 0)
84 struct word nullpath={ "", 0};
85 void doredir(redir *rp)
92 Dup(rp->from, rp->to);
96 case RDUP: Dup(rp->from, rp->to); break;
97 case RCLOSE: close(rp->from); break;
101 word *searchpath(char *w){
103 if(strncmp(w, "/", 1)==0
104 || strncmp(w, "#", 1)==0
105 || strncmp(w, "./", 2)==0
106 || strncmp(w, "../", 3)==0
107 || (path=vlook("path")->val)==0)
112 popword(); /* "exec" */
113 if(runq->argv->words==0){
114 Xerror1("empty argument list");
117 doredir(runq->redir);
118 Execute(runq->argv->words, searchpath(runq->argv->words->word));
121 void execfunc(var *func)
125 starval=runq->argv->words;
128 start(func->fn, func->pc, (struct var *)0);
129 runq->local=newvar(strdup("*"), runq->local);
130 runq->local->val=starval;
131 runq->local->changed=1;
133 int dochdir(char *word){
134 /* report to /dev/wdir if it exists and we're interactive */
135 static int wdirfd = -2;
136 if(chdir(word)<0) return -1;
138 if(wdirfd==-2) /* try only once */
139 wdirfd = open("/dev/wdir", OWRITE|OCEXEC);
141 write(wdirfd, word, strlen(word));
146 word *a=runq->argv->words;
149 setstatus("can't cd");
150 cdpath=vlook("cdpath")->val;
153 pfmt(err, "Usage: cd [directory]\n");
156 if(a->next->word[0]=='/' || cdpath==0) cdpath=&nullpath;
157 for(;cdpath;cdpath=cdpath->next){
158 strcpy(dir, cdpath->word);
159 if(dir[0]) strcat(dir, "/");
160 strcat(dir, a->next->word);
162 if(strlen(cdpath->word)
163 && strcmp(cdpath->word, ".")!=0)
164 pfmt(err, "%s\n", dir);
169 if(cdpath==0) pfmt(err, "Can't cd %s: %r\n", a->next->word);
172 a=vlook("home")->val;
174 if(dochdir(a->word)>=0)
177 pfmt(err, "Can't cd %s: %r\n", a->word);
180 pfmt(err, "Can't cd -- $home empty\n");
186 switch(count(runq->argv->words)){
187 default: pfmt(err, "Usage: exit [status]\nExiting anyway\n");
188 case 2: setstatus(runq->argv->words->next->word);
192 void execshift(void){
196 switch(count(runq->argv->words)){
198 pfmt(err, "Usage: shift [n]\n");
199 setstatus("shift usage");
202 case 2: n=atoi(runq->argv->words->next->word); break;
206 for(;n && star->val;--n){
208 efree(star->val->word);
209 efree((char *)star->val);
219 while(*s==' ' || *s=='\t' || *s=='\n') s++;
220 while('0'<=*s && *s<='7') n=n*8+*s++-'0';
226 for(rp=runq->redir;rp;rp=rp->next){
229 if(rp->from==fd) fd=-1;
233 if(rp->to==fd) fd=rp->from;
239 union code rdcmds[4];
249 start(rdcmds, 1, runq->local);
254 char *cmdline, *s, *t;
257 if(count(runq->argv->words)<=1){
258 Xerror1("Usage: eval cmd ...");
262 for(ap=runq->argv->words->next;ap;ap=ap->next)
263 len+=1+strlen(ap->word);
264 cmdline=emalloc(len);
266 for(ap=runq->argv->words->next;ap;ap=ap->next){
267 for(t=ap->word;*t;) *s++=*t++;
272 execcmds(opencore(cmdline, len));
275 union code dotcmds[14];
295 dotcmds[9].f=Xrdcmds;
296 dotcmds[10].f=Xunlocal;
297 dotcmds[11].f=Xunlocal;
298 dotcmds[12].f=Xreturn;
304 if(p->argv->words && strcmp(p->argv->words->word, "-i")==0){
309 if(p->argv->words==0){
310 Xerror1("Usage: . [-i] file [arg ...]");
313 zero=strdup(p->argv->words->word);
316 for(path=searchpath(zero);path;path=path->next){
317 strcpy(file, path->word);
318 if(file[0]) strcat(file, "/");
320 if((fd=open(file, 0))>=0) break;
321 if(strcmp(file, "/dev/stdin")==0){ /* for sun & ucb */
327 pfmt(err, "%s: ", zero);
328 setstatus("can't open");
329 Xerror(".: can't open");
332 /* set up for a new command loop */
333 start(dotcmds, 1, (struct var *)0);
334 pushredir(RCLOSE, fd, 0);
336 runq->cmdfd=openfd(fd);
341 runq->argv->words=p->argv->words;
342 /* free caller's copy of $* */
353 switch(count(runq->argv->words)){
355 setstatus(flag[(uchar)runq->argv->words->next->word[0]]?"":"flag not set");
358 letter=runq->argv->words->next->word;
359 val=runq->argv->words->next->next->word;
360 if(strlen(letter)==1){
361 if(strcmp(val, "+")==0){
362 flag[(uchar)letter[0]]=flagset;
365 if(strcmp(val, "-")==0){
366 flag[(uchar)letter[0]]=0;
371 Xerror1("Usage: flag [letter] [+-]");
376 void execwhatis(void){ /* mildly wrong -- should fork before writing */
383 a=runq->argv->words->next;
385 Xerror1("Usage: whatis name ...");
391 out->ebuf=&out->buf[NBUF];
396 pfmt(out, "%s=", a->word);
398 pfmt(out, "%q\n", v->val->word);
401 for(b=v->val;b && b->word;b=b->next){
402 pfmt(out, "%c%q", sep, b->word);
412 if(v->fn) pfmt(out, "fn %s %s\n", v->name, v->fn[v->pc-1].s);
414 for(bp=Builtin;bp->name;bp++)
415 if(strcmp(a->word, bp->name)==0){
416 pfmt(out, "builtin %s\n", a->word);
420 for(path=searchpath(a->word);path;path=path->next){
421 strcpy(file, path->word);
422 if(file[0]) strcat(file, "/");
423 strcat(file, a->word);
424 if(Executable(file)){
425 pfmt(out, "%s\n", file);
430 pfmt(err, "%s: not found\n", a->word);
431 setstatus("not found");
440 switch(count(runq->argv->words)){
441 default: Xerror1("Usage: wait [pid]"); return;
442 case 2: Waitfor(atoi(runq->argv->words->next->word), 0); break;
443 case 1: Waitfor(-1, 0); break;