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++;
27 a = globlist(runq->argv->words);
29 Xerror1("empty argument list");
33 pfmt(err, "%v\n", a); /* wrong, should do redirs */
38 if(strcmp(a->word, "builtin")==0){
40 pfmt(err, "builtin: empty argument list\n");
41 setstatus("empty arg list");
48 for(bp = Builtin;bp->name;bp++)
49 if(strcmp(a->word, bp->name)==0){
54 /* fork and wait is redundant */
60 Updenv(); /* necessary so changes don't go out again */
61 if((pid = execforkexec()) < 0){
66 /* interrupts don't get us out */
68 while(Waitfor(pid, 1) < 0)
82 Dup(rp->from, rp->to);
87 Dup(rp->from, rp->to);
97 searchpath(char *w, char *v)
99 static struct word nullpath = { "", 0 };
102 if(w[0] && w[0] != '/' && w[0] != '#' &&
103 (w[0] != '.' || (w[1] && w[1] != '/' && (w[1] != '.' || w[2] && w[2] != '/')))){
104 path = vlook(v)->val;
114 popword(); /* "exec" */
115 if(runq->argv->words==0){
116 Xerror1("empty argument list");
119 doredir(runq->redir);
120 Execute(runq->argv->words, searchpath(runq->argv->words->word, "path"));
130 starval = runq->argv->words;
131 runq->argv->words = 0;
133 start(func->fn, func->pc, runq->local);
134 runq->local = newvar("*", runq->local);
135 runq->local->val = starval;
136 runq->local->changed = 1;
142 /* report to /dev/wdir if it exists and we're interactive */
152 word *a = runq->argv->words;
156 setstatus("can't cd");
159 pfmt(err, "Usage: cd [directory]\n");
163 for(cdpath = searchpath(a->word, "cdpath"); cdpath; cdpath = cdpath->next){
164 if(cdpath->word[0] != '\0')
165 dir = smprint("%s/%s", cdpath->word, a->word);
167 dir = estrdup(a->word);
168 if(dochdir(dir) >= 0){
169 if(cdpath->word[0] != '\0' && strcmp(cdpath->word, ".") != 0)
170 pfmt(err, "%s\n", dir);
178 pfmt(err, "Can't cd %s: %r\n", a->word);
181 a = vlook("home")->val;
183 if(dochdir(a->word)>=0)
186 pfmt(err, "Can't cd %s: %r\n", a->word);
189 pfmt(err, "Can't cd -- $home empty\n");
198 switch(count(runq->argv->words)){
200 pfmt(err, "Usage: exit [status]\nExiting anyway\n");
202 setstatus(runq->argv->words->next->word);
213 switch(count(runq->argv->words)){
215 pfmt(err, "Usage: shift [n]\n");
216 setstatus("shift usage");
220 n = atoi(runq->argv->words->next->word);
227 for(;n>0 && star->val;--n){
229 free(star->val->word);
242 for(rp = runq->redir;rp;rp = rp->next){
257 union code rdcmds[4];
262 static int first = 1;
265 rdcmds[1].f = Xrdcmds;
266 rdcmds[2].f = Xreturn;
269 start(rdcmds, 1, runq->local);
279 if(count(runq->argv->words)<=1){
280 Xerror1("Usage: eval cmd ...");
284 cmdline = list2str(runq->argv->words->next);
285 len = strlen(cmdline);
288 execcmds(opencore(cmdline, len+1));
291 union code dotcmds[14];
302 static int first = 1;
306 dotcmds[1].f = Xmark;
307 dotcmds[2].f = Xword;
309 dotcmds[4].f = Xlocal;
310 dotcmds[5].f = Xmark;
311 dotcmds[6].f = Xword;
313 dotcmds[8].f = Xlocal;
314 dotcmds[9].f = Xrdcmds;
315 dotcmds[10].f = Xunlocal;
316 dotcmds[11].f = Xunlocal;
317 dotcmds[12].f = Xreturn;
323 if(p->argv->words && strcmp(p->argv->words->word, "-i")==0){
328 if(p->argv->words==0){
329 Xerror1("Usage: . [-i] file [arg ...]");
332 zero = estrdup(p->argv->words->word);
335 for(path = searchpath(zero, "path"); path; path = path->next){
336 if(path->word[0] != '\0')
337 file = smprint("%s/%s", path->word, zero);
339 file = estrdup(zero);
345 if(strcmp(file, "/dev/stdin")==0){ /* for sun & ucb */
352 pfmt(err, "%s: ", zero);
353 setstatus("can't open");
354 Xerror(".: can't open");
357 /* set up for a new command loop */
358 start(dotcmds, 1, (struct var *)0);
359 pushredir(RCLOSE, fd, 0);
360 runq->cmdfile = zero;
361 runq->cmdfd = openfd(fd);
366 runq->argv->words = p->argv->words;
367 /* free caller's copy of $* */
381 switch(count(runq->argv->words)){
383 setstatus(flag[(uchar)runq->argv->words->next->word[0]]?"":"flag not set");
386 letter = runq->argv->words->next->word;
387 val = runq->argv->words->next->next->word;
388 if(strlen(letter)==1){
389 if(strcmp(val, "+")==0){
390 flag[(uchar)letter[0]] = flagset;
393 if(strcmp(val, "-")==0){
394 flag[(uchar)letter[0]] = 0;
399 Xerror1("Usage: flag [letter] [+-]");
406 execwhatis(void){ /* mildly wrong -- should fork before writing */
413 a = runq->argv->words->next;
415 Xerror1("Usage: whatis name ...");
420 out->bufp = out->buf;
421 out->ebuf = &out->buf[NBUF];
426 pfmt(out, "%s=", a->word);
428 pfmt(out, "%q\n", v->val->word);
431 for(b = v->val;b && b->word;b = b->next){
432 pfmt(out, "%c%q", sep, b->word);
443 pfmt(out, "fn %q %s\n", v->name, v->fn[v->pc-1].s);
445 for(bp = Builtin;bp->name;bp++)
446 if(strcmp(a->word, bp->name)==0){
447 pfmt(out, "builtin %s\n", a->word);
451 for(path = searchpath(a->word, "path"); path;
453 if(path->word[0] != '\0')
454 file = smprint("%s/%s",
455 path->word, a->word);
457 file = estrdup(a->word);
458 if(Executable(file)){
459 pfmt(out, "%s\n", file);
466 pfmt(err, "%s: not found\n", a->word);
467 setstatus("not found");
479 switch(count(runq->argv->words)){
481 Xerror1("Usage: wait [pid]");
484 Waitfor(atoi(runq->argv->words->next->word), 0);