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 a = runq->argv->words;
30 Xerror1("empty argument list");
34 pfmt(err, "%v\n", p->argv->words); /* wrong, should do redirs */
39 if(strcmp(a->word, "builtin")==0){
41 pfmt(err, "builtin: empty argument list\n");
42 setstatus("empty arg list");
49 for(bp = Builtin;bp->name;bp++)
50 if(strcmp(a->word, bp->name)==0){
55 /* fork and wait is redundant */
62 Updenv(); /* necessary so changes don't go out again */
63 if((pid = execforkexec()) < 0){
68 /* interrupts don't get us out */
70 while(Waitfor(pid, 1) < 0)
75 struct word nullpath = { "", 0};
85 Dup(rp->from, rp->to);
90 Dup(rp->from, rp->to);
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)
115 popword(); /* "exec" */
116 if(runq->argv->words==0){
117 Xerror1("empty argument list");
120 doredir(runq->redir);
121 Execute(runq->argv->words, searchpath(runq->argv->words->word));
130 starval = runq->argv->words;
131 runq->argv->words = 0;
133 start(func->fn, func->pc, runq->local);
134 runq->local = newvar(strdup("*"), runq->local);
135 runq->local->val = starval;
136 runq->local->changed = 1;
142 /* report to /dev/wdir if it exists and we're interactive */
143 static int wdirfd = -2;
144 if(chdir(word)<0) return -1;
146 if(wdirfd==-2) /* try only once */
147 wdirfd = open("/dev/wdir", OWRITE|OCEXEC);
149 write(wdirfd, word, strlen(word));
157 word *a = runq->argv->words;
161 setstatus("can't cd");
162 cdpath = vlook("cdpath")->val;
165 pfmt(err, "Usage: cd [directory]\n");
168 if(a->next->word[0]=='/' || cdpath==0)
170 for(; cdpath; cdpath = cdpath->next){
171 if(cdpath->word[0] != '\0')
172 dir = smprint("%s/%s", cdpath->word,
175 dir = strdup(a->next->word);
177 if(dochdir(dir) >= 0){
178 if(cdpath->word[0] != '\0' &&
179 strcmp(cdpath->word, ".") != 0)
180 pfmt(err, "%s\n", dir);
188 pfmt(err, "Can't cd %s: %r\n", a->next->word);
191 a = vlook("home")->val;
193 if(dochdir(a->word)>=0)
196 pfmt(err, "Can't cd %s: %r\n", a->word);
199 pfmt(err, "Can't cd -- $home empty\n");
208 switch(count(runq->argv->words)){
210 pfmt(err, "Usage: exit [status]\nExiting anyway\n");
212 setstatus(runq->argv->words->next->word);
223 switch(count(runq->argv->words)){
225 pfmt(err, "Usage: shift [n]\n");
226 setstatus("shift usage");
230 n = atoi(runq->argv->words->next->word);
237 for(;n && star->val;--n){
239 efree(star->val->word);
240 efree((char *)star->val);
252 while(*s==' ' || *s=='\t' || *s=='\n') s++;
253 while('0'<=*s && *s<='7') n = n*8+*s++-'0';
261 for(rp = runq->redir;rp;rp = rp->next){
276 union code rdcmds[4];
281 static int first = 1;
284 rdcmds[1].f = Xrdcmds;
285 rdcmds[2].f = Xreturn;
288 start(rdcmds, 1, runq->local);
296 char *cmdline, *s, *t;
299 if(count(runq->argv->words)<=1){
300 Xerror1("Usage: eval cmd ...");
304 for(ap = runq->argv->words->next;ap;ap = ap->next)
305 len+=1+strlen(ap->word);
306 cmdline = emalloc(len);
308 for(ap = runq->argv->words->next;ap;ap = ap->next){
309 for(t = ap->word;*t;) *s++=*t++;
314 execcmds(opencore(cmdline, len));
317 union code dotcmds[14];
328 static int first = 1;
332 dotcmds[1].f = Xmark;
333 dotcmds[2].f = Xword;
335 dotcmds[4].f = Xlocal;
336 dotcmds[5].f = Xmark;
337 dotcmds[6].f = Xword;
339 dotcmds[8].f = Xlocal;
340 dotcmds[9].f = Xrdcmds;
341 dotcmds[10].f = Xunlocal;
342 dotcmds[11].f = Xunlocal;
343 dotcmds[12].f = Xreturn;
349 if(p->argv->words && strcmp(p->argv->words->word, "-i")==0){
354 if(p->argv->words==0){
355 Xerror1("Usage: . [-i] file [arg ...]");
358 zero = strdup(p->argv->words->word);
361 for(path = searchpath(zero); path; path = path->next){
362 if(path->word[0] != '\0')
363 file = smprint("%s/%s", path->word, zero);
371 if(strcmp(file, "/dev/stdin")==0){ /* for sun & ucb */
378 pfmt(err, "%s: ", zero);
379 setstatus("can't open");
380 Xerror(".: can't open");
383 /* set up for a new command loop */
384 start(dotcmds, 1, (struct var *)0);
385 pushredir(RCLOSE, fd, 0);
386 runq->cmdfile = zero;
387 runq->cmdfd = openfd(fd);
392 runq->argv->words = p->argv->words;
393 /* free caller's copy of $* */
407 switch(count(runq->argv->words)){
409 setstatus(flag[(uchar)runq->argv->words->next->word[0]]?"":"flag not set");
412 letter = runq->argv->words->next->word;
413 val = runq->argv->words->next->next->word;
414 if(strlen(letter)==1){
415 if(strcmp(val, "+")==0){
416 flag[(uchar)letter[0]] = flagset;
419 if(strcmp(val, "-")==0){
420 flag[(uchar)letter[0]] = 0;
425 Xerror1("Usage: flag [letter] [+-]");
432 execwhatis(void){ /* mildly wrong -- should fork before writing */
439 a = runq->argv->words->next;
441 Xerror1("Usage: whatis name ...");
446 out->bufp = out->buf;
447 out->ebuf = &out->buf[NBUF];
452 pfmt(out, "%s=", a->word);
454 pfmt(out, "%q\n", v->val->word);
457 for(b = v->val;b && b->word;b = b->next){
458 pfmt(out, "%c%q", sep, b->word);
469 pfmt(out, "fn %q %s\n", v->name, v->fn[v->pc-1].s);
471 for(bp = Builtin;bp->name;bp++)
472 if(strcmp(a->word, bp->name)==0){
473 pfmt(out, "builtin %s\n", a->word);
477 for(path = searchpath(a->word); path;
479 if(path->word[0] != '\0')
480 file = smprint("%s/%s",
481 path->word, a->word);
483 file = strdup(a->word);
484 if(Executable(file)){
485 pfmt(out, "%s\n", file);
492 pfmt(err, "%s: not found\n", a->word);
493 setstatus("not found");
505 switch(count(runq->argv->words)){
507 Xerror1("Usage: wait [pid]");
510 Waitfor(atoi(runq->argv->words->next->word), 0);