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)
73 struct word nullpath = { "", 0};
83 Dup(rp->from, rp->to);
88 Dup(rp->from, rp->to);
101 if(strncmp(w, "/", 1)==0
102 || strncmp(w, "#", 1)==0
103 || strncmp(w, "./", 2)==0
104 || strncmp(w, "../", 3)==0
105 || (path = vlook("path")->val)==0)
113 popword(); /* "exec" */
114 if(runq->argv->words==0){
115 Xerror1("empty argument list");
118 doredir(runq->redir);
119 Execute(runq->argv->words, searchpath(runq->argv->words->word));
129 starval = runq->argv->words;
130 runq->argv->words = 0;
132 start(func->fn, func->pc, runq->local);
133 runq->local = newvar("*", runq->local);
134 runq->local->val = starval;
135 runq->local->changed = 1;
141 /* report to /dev/wdir if it exists and we're interactive */
142 if(chdir(word)<0) return -1;
144 static int wdirfd = -2;
145 if(wdirfd==-2) /* try only once */
146 wdirfd = open("/dev/wdir", OWRITE|OCEXEC);
148 write(wdirfd, word, strlen(word));
156 word *a = runq->argv->words;
160 setstatus("can't cd");
161 cdpath = vlook("cdpath")->val;
164 pfmt(err, "Usage: cd [directory]\n");
167 if(a->next->word[0]=='/' || cdpath==0)
169 for(; cdpath; cdpath = cdpath->next){
170 if(cdpath->word[0] != '\0')
171 dir = smprint("%s/%s", cdpath->word,
174 dir = estrdup(a->next->word);
176 if(dochdir(dir) >= 0){
177 if(cdpath->word[0] != '\0' &&
178 strcmp(cdpath->word, ".") != 0)
179 pfmt(err, "%s\n", dir);
187 pfmt(err, "Can't cd %s: %r\n", a->next->word);
190 a = vlook("home")->val;
192 if(dochdir(a->word)>=0)
195 pfmt(err, "Can't cd %s: %r\n", a->word);
198 pfmt(err, "Can't cd -- $home empty\n");
207 switch(count(runq->argv->words)){
209 pfmt(err, "Usage: exit [status]\nExiting anyway\n");
211 setstatus(runq->argv->words->next->word);
222 switch(count(runq->argv->words)){
224 pfmt(err, "Usage: shift [n]\n");
225 setstatus("shift usage");
229 n = atoi(runq->argv->words->next->word);
236 for(;n>0 && star->val;--n){
238 free(star->val->word);
251 for(rp = runq->redir;rp;rp = rp->next){
266 union code rdcmds[4];
271 static int first = 1;
274 rdcmds[1].f = Xrdcmds;
275 rdcmds[2].f = Xreturn;
278 start(rdcmds, 1, runq->local);
288 if(count(runq->argv->words)<=1){
289 Xerror1("Usage: eval cmd ...");
293 cmdline = list2str(runq->argv->words->next);
294 len = strlen(cmdline);
297 execcmds(opencore(cmdline, len+1));
300 union code dotcmds[14];
311 static int first = 1;
315 dotcmds[1].f = Xmark;
316 dotcmds[2].f = Xword;
318 dotcmds[4].f = Xlocal;
319 dotcmds[5].f = Xmark;
320 dotcmds[6].f = Xword;
322 dotcmds[8].f = Xlocal;
323 dotcmds[9].f = Xrdcmds;
324 dotcmds[10].f = Xunlocal;
325 dotcmds[11].f = Xunlocal;
326 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->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");
366 /* set up for a new command loop */
367 start(dotcmds, 1, (struct var *)0);
368 pushredir(RCLOSE, fd, 0);
369 runq->cmdfile = zero;
370 runq->cmdfd = openfd(fd);
375 runq->argv->words = p->argv->words;
376 /* free caller's copy of $* */
390 switch(count(runq->argv->words)){
392 setstatus(flag[(uchar)runq->argv->words->next->word[0]]?"":"flag not set");
395 letter = runq->argv->words->next->word;
396 val = runq->argv->words->next->next->word;
397 if(strlen(letter)==1){
398 if(strcmp(val, "+")==0){
399 flag[(uchar)letter[0]] = flagset;
402 if(strcmp(val, "-")==0){
403 flag[(uchar)letter[0]] = 0;
408 Xerror1("Usage: flag [letter] [+-]");
415 execwhatis(void){ /* mildly wrong -- should fork before writing */
422 a = runq->argv->words->next;
424 Xerror1("Usage: whatis name ...");
429 out->bufp = out->buf;
430 out->ebuf = &out->buf[NBUF];
435 pfmt(out, "%s=", a->word);
437 pfmt(out, "%q\n", v->val->word);
440 for(b = v->val;b && b->word;b = b->next){
441 pfmt(out, "%c%q", sep, b->word);
452 pfmt(out, "fn %q %s\n", v->name, v->fn[v->pc-1].s);
454 for(bp = Builtin;bp->name;bp++)
455 if(strcmp(a->word, bp->name)==0){
456 pfmt(out, "builtin %s\n", a->word);
460 for(path = searchpath(a->word); path;
462 if(path->word[0] != '\0')
463 file = smprint("%s/%s",
464 path->word, a->word);
466 file = estrdup(a->word);
467 if(Executable(file)){
468 pfmt(out, "%s\n", file);
475 pfmt(err, "%s: not found\n", a->word);
476 setstatus("not found");
488 switch(count(runq->argv->words)){
490 Xerror1("Usage: wait [pid]");
493 Waitfor(atoi(runq->argv->words->next->word), 0);