2 * Maybe `simple' is a misnomer.
10 * Search through the following code to see if we're just going to exit.
14 code *c=&runq->code[runq->pc];
16 if(c->f==Xpopredir || c->f==Xunlocal)
18 else if(c->f==Xsrcline || c->f==Xsrcfile)
34 a = globlist(runq->argv->words);
36 Xerror1("empty argument list");
40 pfmt(err, "%v\n", a); /* wrong, should do redirs */
45 if(strcmp(a->word, "builtin")==0){
47 pfmt(err, "builtin: empty argument list\n");
48 setstatus("empty arg list");
55 for(bp = Builtin;bp->name;bp++)
56 if(strcmp(a->word, bp->name)==0){
61 /* fork and wait is redundant */
67 Updenv(); /* necessary so changes don't go out again */
68 if((pid = execforkexec()) < 0){
73 /* interrupts don't get us out */
75 while(Waitfor(pid, 1) < 0)
89 Dup(rp->from, rp->to);
94 Dup(rp->from, rp->to);
104 searchpath(char *w, char *v)
106 static struct word nullpath = { "", 0 };
109 if(w[0] && w[0] != '/' && w[0] != '#' &&
110 (w[0] != '.' || (w[1] && w[1] != '/' && (w[1] != '.' || w[2] && w[2] != '/')))){
111 path = vlook(v)->val;
121 popword(); /* "exec" */
122 if(runq->argv->words==0){
123 Xerror1("empty argument list");
126 doredir(runq->redir);
127 Execute(runq->argv->words, searchpath(runq->argv->words->word, "path"));
137 starval = runq->argv->words;
138 runq->argv->words = 0;
140 start(func->fn, func->pc, runq->local);
141 runq->local = newvar("*", runq->local);
142 runq->local->val = starval;
143 runq->local->changed = 1;
149 /* report to /dev/wdir if it exists and we're interactive */
159 word *a = runq->argv->words;
163 setstatus("can't cd");
166 pfmt(err, "Usage: cd [directory]\n");
170 for(cdpath = searchpath(a->word, "cdpath"); cdpath; cdpath = cdpath->next){
171 if(cdpath->word[0] != '\0')
172 dir = smprint("%s/%s", cdpath->word, a->word);
174 dir = estrdup(a->word);
175 if(dochdir(dir) >= 0){
176 if(cdpath->word[0] != '\0' && strcmp(cdpath->word, ".") != 0)
177 pfmt(err, "%s\n", dir);
185 pfmt(err, "Can't cd %s: %r\n", a->word);
188 a = vlook("home")->val;
190 if(dochdir(a->word)>=0)
193 pfmt(err, "Can't cd %s: %r\n", a->word);
196 pfmt(err, "Can't cd -- $home empty\n");
205 switch(count(runq->argv->words)){
207 pfmt(err, "Usage: exit [status]\nExiting anyway\n");
209 setstatus(runq->argv->words->next->word);
220 switch(count(runq->argv->words)){
222 pfmt(err, "Usage: shift [n]\n");
223 setstatus("shift usage");
227 n = atoi(runq->argv->words->next->word);
234 for(;n>0 && star->val;--n){
236 free(star->val->word);
249 for(rp = runq->redir;rp;rp = rp->next){
264 union code rdcmds[4];
269 static int first = 1;
273 rdcmds[1].f = Xrdcmds;
274 rdcmds[2].f = Xreturn;
277 start(rdcmds, 1, runq->local);
287 if(count(runq->argv->words)<=1){
288 Xerror1("Usage: eval cmd ...");
292 cmdline = list2str(runq->argv->words->next);
293 len = strlen(cmdline);
296 execcmds(opencore(cmdline, len+1));
299 union code dotcmds[14];
310 static int first = 1;
314 dotcmds[1].f = Xmark;
315 dotcmds[2].f = Xword;
317 dotcmds[4].f = Xlocal;
318 dotcmds[5].f = Xmark;
319 dotcmds[6].f = Xword;
321 dotcmds[8].f = Xlocal;
322 dotcmds[9].f = Xrdcmds;
323 dotcmds[10].f = Xunlocal;
324 dotcmds[11].f = Xunlocal;
325 dotcmds[12].f = Xreturn;
332 if(p->argv->words && strcmp(p->argv->words->word, "-i")==0){
337 if(p->argv->words==0){
338 Xerror1("Usage: . [-i] file [arg ...]");
341 zero = estrdup(p->argv->words->word);
344 for(path = searchpath(zero, "path"); path; path = path->next){
345 if(path->word[0] != '\0')
346 file = smprint("%s/%s", path->word, zero);
348 file = estrdup(zero);
354 if(strcmp(file, "/dev/stdin")==0){ /* for sun & ucb */
361 pfmt(err, "%s: ", zero);
362 setstatus("can't open");
363 Xerror(".: can't open");
369 /* set up for a new command loop */
370 start(dotcmds, 1, (struct var *)0);
371 pushredir(RCLOSE, fd, 0);
372 runq->cmdfile = zero;
373 runq->cmdfd = openfd(fd);
378 runq->argv->words = p->argv->words;
379 /* free caller's copy of $* */
393 switch(count(runq->argv->words)){
395 setstatus(flag[(uchar)runq->argv->words->next->word[0]]?"":"flag not set");
398 letter = runq->argv->words->next->word;
399 val = runq->argv->words->next->next->word;
400 if(strlen(letter)==1){
401 if(strcmp(val, "+")==0){
402 flag[(uchar)letter[0]] = flagset;
405 if(strcmp(val, "-")==0){
406 flag[(uchar)letter[0]] = 0;
411 Xerror1("Usage: flag [letter] [+-]");
418 execwhatis(void){ /* mildly wrong -- should fork before writing */
425 a = runq->argv->words->next;
427 Xerror1("Usage: whatis name ...");
432 out->bufp = out->buf;
433 out->ebuf = &out->buf[NBUF];
438 pfmt(out, "%s=", a->word);
440 pfmt(out, "%q\n", v->val->word);
443 for(b = v->val;b && b->word;b = b->next){
444 pfmt(out, "%c%q", sep, b->word);
455 pfmt(out, "fn %q %s\n", v->name, v->fn[v->pc-1].s);
457 for(bp = Builtin;bp->name;bp++)
458 if(strcmp(a->word, bp->name)==0){
459 pfmt(out, "builtin %s\n", a->word);
463 for(path = searchpath(a->word, "path"); path;
465 if(path->word[0] != '\0')
466 file = smprint("%s/%s",
467 path->word, a->word);
469 file = estrdup(a->word);
470 if(Executable(file)){
471 pfmt(out, "%s\n", file);
478 pfmt(err, "%s: not found\n", a->word);
479 setstatus("not found");
491 switch(count(runq->argv->words)){
493 Xerror1("Usage: wait [pid]");
496 Waitfor(atoi(runq->argv->words->next->word), 0);