2 f08fdedc 2003-11-23 devnull * Maybe `simple' is a misnomer.
4 f08fdedc 2003-11-23 devnull #include "rc.h"
5 f08fdedc 2003-11-23 devnull #include "getflags.h"
6 f08fdedc 2003-11-23 devnull #include "exec.h"
7 f08fdedc 2003-11-23 devnull #include "io.h"
8 f08fdedc 2003-11-23 devnull #include "fns.h"
10 f08fdedc 2003-11-23 devnull * Search through the following code to see if we're just going to exit.
13 f08fdedc 2003-11-23 devnull exitnext(void){
14 f08fdedc 2003-11-23 devnull union code *c=&runq->code[runq->pc];
15 f08fdedc 2003-11-23 devnull while(c->f==Xpopredir) c++;
16 f08fdedc 2003-11-23 devnull return c->f==Xexit;
20 c8f53842 2007-03-26 devnull Xsimple(void)
23 c8f53842 2007-03-26 devnull thread *p = runq;
25 f08fdedc 2003-11-23 devnull struct builtin *bp;
27 f08fdedc 2003-11-23 devnull globlist();
28 c8f53842 2007-03-26 devnull a = runq->argv->words;
29 f08fdedc 2003-11-23 devnull if(a==0){
30 f08fdedc 2003-11-23 devnull Xerror1("empty argument list");
33 f08fdedc 2003-11-23 devnull if(flag['x'])
34 f08fdedc 2003-11-23 devnull pfmt(err, "%v\n", p->argv->words); /* wrong, should do redirs */
35 c8f53842 2007-03-26 devnull v = gvlook(a->word);
36 f08fdedc 2003-11-23 devnull if(v->fn)
37 f08fdedc 2003-11-23 devnull execfunc(v);
39 f08fdedc 2003-11-23 devnull if(strcmp(a->word, "builtin")==0){
40 f08fdedc 2003-11-23 devnull if(count(a)==1){
41 f08fdedc 2003-11-23 devnull pfmt(err, "builtin: empty argument list\n");
42 f08fdedc 2003-11-23 devnull setstatus("empty arg list");
43 f08fdedc 2003-11-23 devnull poplist();
46 c8f53842 2007-03-26 devnull a = a->next;
47 f08fdedc 2003-11-23 devnull popword();
49 c8f53842 2007-03-26 devnull for(bp = Builtin;bp->name;bp++)
50 f08fdedc 2003-11-23 devnull if(strcmp(a->word, bp->name)==0){
51 f08fdedc 2003-11-23 devnull (*bp->fnc)();
54 f08fdedc 2003-11-23 devnull if(exitnext()){
55 f08fdedc 2003-11-23 devnull /* fork and wait is redundant */
56 f08fdedc 2003-11-23 devnull pushword("exec");
57 f08fdedc 2003-11-23 devnull execexec();
61 f08fdedc 2003-11-23 devnull flush(err);
62 f08fdedc 2003-11-23 devnull Updenv(); /* necessary so changes don't go out again */
63 c8f53842 2007-03-26 devnull if((pid = execforkexec()) < 0){
64 f08fdedc 2003-11-23 devnull Xerror("try again");
68 c8f53842 2007-03-26 devnull /* interrupts don't get us out */
69 c8f53842 2007-03-26 devnull poplist();
70 c8f53842 2007-03-26 devnull while(Waitfor(pid, 1) < 0)
75 c8f53842 2007-03-26 devnull struct word nullpath = { "", 0};
78 c8f53842 2007-03-26 devnull doredir(redir *rp)
81 f08fdedc 2003-11-23 devnull doredir(rp->next);
82 f08fdedc 2003-11-23 devnull switch(rp->type){
83 f08fdedc 2003-11-23 devnull case ROPEN:
84 f08fdedc 2003-11-23 devnull if(rp->from!=rp->to){
85 f08fdedc 2003-11-23 devnull Dup(rp->from, rp->to);
86 f08fdedc 2003-11-23 devnull close(rp->from);
89 c8f53842 2007-03-26 devnull case RDUP:
90 c8f53842 2007-03-26 devnull Dup(rp->from, rp->to);
92 c8f53842 2007-03-26 devnull case RCLOSE:
93 c8f53842 2007-03-26 devnull close(rp->from);
100 c8f53842 2007-03-26 devnull searchpath(char *w)
102 f08fdedc 2003-11-23 devnull word *path;
103 f08fdedc 2003-11-23 devnull if(strncmp(w, "/", 1)==0
104 de39860a 2005-01-23 devnull /* || strncmp(w, "#", 1)==0 */
105 f08fdedc 2003-11-23 devnull || strncmp(w, "./", 2)==0
106 f08fdedc 2003-11-23 devnull || strncmp(w, "../", 3)==0
107 c8f53842 2007-03-26 devnull || (path = vlook("path")->val)==0)
108 f08fdedc 2003-11-23 devnull path=&nullpath;
109 f08fdedc 2003-11-23 devnull return path;
113 c8f53842 2007-03-26 devnull execexec(void)
115 f08fdedc 2003-11-23 devnull popword(); /* "exec" */
116 f08fdedc 2003-11-23 devnull if(runq->argv->words==0){
117 f08fdedc 2003-11-23 devnull Xerror1("empty argument list");
120 f08fdedc 2003-11-23 devnull doredir(runq->redir);
121 f08fdedc 2003-11-23 devnull Execute(runq->argv->words, searchpath(runq->argv->words->word));
122 f08fdedc 2003-11-23 devnull poplist();
126 c8f53842 2007-03-26 devnull execfunc(var *func)
128 f08fdedc 2003-11-23 devnull word *starval;
129 f08fdedc 2003-11-23 devnull popword();
130 c8f53842 2007-03-26 devnull starval = runq->argv->words;
131 c8f53842 2007-03-26 devnull runq->argv->words = 0;
132 f08fdedc 2003-11-23 devnull poplist();
133 362264eb 2008-08-14 rsc start(func->fn, func->pc, runq->local);
134 c8f53842 2007-03-26 devnull runq->local = newvar(strdup("*"), runq->local);
135 c8f53842 2007-03-26 devnull runq->local->val = starval;
136 c8f53842 2007-03-26 devnull runq->local->changed = 1;
140 c8f53842 2007-03-26 devnull dochdir(char *word)
142 f08fdedc 2003-11-23 devnull /* report to /dev/wdir if it exists and we're interactive */
143 f08fdedc 2003-11-23 devnull static int wdirfd = -2;
144 f08fdedc 2003-11-23 devnull if(chdir(word)<0) return -1;
145 f08fdedc 2003-11-23 devnull if(flag['i']!=0){
146 f08fdedc 2003-11-23 devnull if(wdirfd==-2) /* try only once */
147 f08fdedc 2003-11-23 devnull wdirfd = open("/dev/wdir", OWRITE|OCEXEC);
148 f08fdedc 2003-11-23 devnull if(wdirfd>=0)
149 f08fdedc 2003-11-23 devnull write(wdirfd, word, strlen(word));
151 f08fdedc 2003-11-23 devnull return 1;
155 c8f53842 2007-03-26 devnull execcd(void)
157 c8f53842 2007-03-26 devnull word *a = runq->argv->words;
158 f08fdedc 2003-11-23 devnull word *cdpath;
159 f08fdedc 2003-11-23 devnull char dir[512];
160 f08fdedc 2003-11-23 devnull setstatus("can't cd");
161 c8f53842 2007-03-26 devnull cdpath = vlook("cdpath")->val;
162 f08fdedc 2003-11-23 devnull switch(count(a)){
163 f08fdedc 2003-11-23 devnull default:
164 f08fdedc 2003-11-23 devnull pfmt(err, "Usage: cd [directory]\n");
167 c8f53842 2007-03-26 devnull if(a->next->word[0]=='/' || cdpath==0)
168 c8f53842 2007-03-26 devnull cdpath=&nullpath;
169 c8f53842 2007-03-26 devnull for(;cdpath;cdpath = cdpath->next){
170 f08fdedc 2003-11-23 devnull strcpy(dir, cdpath->word);
171 c8f53842 2007-03-26 devnull if(dir[0])
172 c8f53842 2007-03-26 devnull strcat(dir, "/");
173 f08fdedc 2003-11-23 devnull strcat(dir, a->next->word);
174 f08fdedc 2003-11-23 devnull if(dochdir(dir)>=0){
175 f08fdedc 2003-11-23 devnull if(strlen(cdpath->word)
176 f08fdedc 2003-11-23 devnull && strcmp(cdpath->word, ".")!=0)
177 f08fdedc 2003-11-23 devnull pfmt(err, "%s\n", dir);
178 f08fdedc 2003-11-23 devnull setstatus("");
182 c8f53842 2007-03-26 devnull if(cdpath==0)
183 c8f53842 2007-03-26 devnull pfmt(err, "Can't cd %s: %r\n", a->next->word);
186 c8f53842 2007-03-26 devnull a = vlook("home")->val;
187 f08fdedc 2003-11-23 devnull if(count(a)>=1){
188 f08fdedc 2003-11-23 devnull if(dochdir(a->word)>=0)
189 f08fdedc 2003-11-23 devnull setstatus("");
191 f08fdedc 2003-11-23 devnull pfmt(err, "Can't cd %s: %r\n", a->word);
194 f08fdedc 2003-11-23 devnull pfmt(err, "Can't cd -- $home empty\n");
197 f08fdedc 2003-11-23 devnull poplist();
201 c8f53842 2007-03-26 devnull execexit(void)
203 f08fdedc 2003-11-23 devnull switch(count(runq->argv->words)){
204 c8f53842 2007-03-26 devnull default:
205 c8f53842 2007-03-26 devnull pfmt(err, "Usage: exit [status]\nExiting anyway\n");
207 c8f53842 2007-03-26 devnull setstatus(runq->argv->words->next->word);
208 f08fdedc 2003-11-23 devnull case 1: Xexit();
213 c8f53842 2007-03-26 devnull execshift(void)
216 f08fdedc 2003-11-23 devnull word *a;
217 f08fdedc 2003-11-23 devnull var *star;
218 f08fdedc 2003-11-23 devnull switch(count(runq->argv->words)){
219 f08fdedc 2003-11-23 devnull default:
220 f08fdedc 2003-11-23 devnull pfmt(err, "Usage: shift [n]\n");
221 f08fdedc 2003-11-23 devnull setstatus("shift usage");
222 f08fdedc 2003-11-23 devnull poplist();
225 c8f53842 2007-03-26 devnull n = atoi(runq->argv->words->next->word);
231 c8f53842 2007-03-26 devnull star = vlook("*");
232 f08fdedc 2003-11-23 devnull for(;n && star->val;--n){
233 c8f53842 2007-03-26 devnull a = star->val->next;
234 f08fdedc 2003-11-23 devnull efree(star->val->word);
235 f08fdedc 2003-11-23 devnull efree((char *)star->val);
236 c8f53842 2007-03-26 devnull star->val = a;
237 c8f53842 2007-03-26 devnull star->changed = 1;
239 f08fdedc 2003-11-23 devnull setstatus("");
240 f08fdedc 2003-11-23 devnull poplist();
244 c8f53842 2007-03-26 devnull octal(char *s)
246 c8f53842 2007-03-26 devnull int n = 0;
247 f08fdedc 2003-11-23 devnull while(*s==' ' || *s=='\t' || *s=='\n') s++;
248 c8f53842 2007-03-26 devnull while('0'<=*s && *s<='7') n = n*8+*s++-'0';
249 f08fdedc 2003-11-23 devnull return n;
253 c8f53842 2007-03-26 devnull mapfd(int fd)
255 f08fdedc 2003-11-23 devnull redir *rp;
256 c8f53842 2007-03-26 devnull for(rp = runq->redir;rp;rp = rp->next){
257 f08fdedc 2003-11-23 devnull switch(rp->type){
258 f08fdedc 2003-11-23 devnull case RCLOSE:
259 c8f53842 2007-03-26 devnull if(rp->from==fd)
262 f08fdedc 2003-11-23 devnull case RDUP:
263 f08fdedc 2003-11-23 devnull case ROPEN:
264 c8f53842 2007-03-26 devnull if(rp->to==fd)
265 c8f53842 2007-03-26 devnull fd = rp->from;
269 f08fdedc 2003-11-23 devnull return fd;
271 f08fdedc 2003-11-23 devnull union code rdcmds[4];
274 c8f53842 2007-03-26 devnull execcmds(io *f)
276 c8f53842 2007-03-26 devnull static int first = 1;
277 f08fdedc 2003-11-23 devnull if(first){
278 c8f53842 2007-03-26 devnull rdcmds[0].i = 1;
279 c8f53842 2007-03-26 devnull rdcmds[1].f = Xrdcmds;
280 c8f53842 2007-03-26 devnull rdcmds[2].f = Xreturn;
281 c8f53842 2007-03-26 devnull first = 0;
283 f08fdedc 2003-11-23 devnull start(rdcmds, 1, runq->local);
284 c8f53842 2007-03-26 devnull runq->cmdfd = f;
285 c8f53842 2007-03-26 devnull runq->iflast = 0;
289 c8f53842 2007-03-26 devnull execeval(void)
291 f08fdedc 2003-11-23 devnull char *cmdline, *s, *t;
292 c8f53842 2007-03-26 devnull int len = 0;
293 f08fdedc 2003-11-23 devnull word *ap;
294 f08fdedc 2003-11-23 devnull if(count(runq->argv->words)<=1){
295 f08fdedc 2003-11-23 devnull Xerror1("Usage: eval cmd ...");
298 c8f53842 2007-03-26 devnull eflagok = 1;
299 c8f53842 2007-03-26 devnull for(ap = runq->argv->words->next;ap;ap = ap->next)
300 f08fdedc 2003-11-23 devnull len+=1+strlen(ap->word);
301 c8f53842 2007-03-26 devnull cmdline = emalloc(len);
302 c8f53842 2007-03-26 devnull s = cmdline;
303 c8f53842 2007-03-26 devnull for(ap = runq->argv->words->next;ap;ap = ap->next){
304 c8f53842 2007-03-26 devnull for(t = ap->word;*t;) *s++=*t++;
305 f08fdedc 2003-11-23 devnull *s++=' ';
307 f08fdedc 2003-11-23 devnull s[-1]='\n';
308 f08fdedc 2003-11-23 devnull poplist();
309 f08fdedc 2003-11-23 devnull execcmds(opencore(cmdline, len));
310 f08fdedc 2003-11-23 devnull efree(cmdline);
312 f08fdedc 2003-11-23 devnull union code dotcmds[14];
315 c8f53842 2007-03-26 devnull execdot(void)
317 c8f53842 2007-03-26 devnull int iflag = 0;
319 f08fdedc 2003-11-23 devnull list *av;
320 c8f53842 2007-03-26 devnull thread *p = runq;
321 f08fdedc 2003-11-23 devnull char *zero;
322 c8f53842 2007-03-26 devnull static int first = 1;
323 f08fdedc 2003-11-23 devnull char file[512];
324 f08fdedc 2003-11-23 devnull word *path;
325 f08fdedc 2003-11-23 devnull if(first){
326 c8f53842 2007-03-26 devnull dotcmds[0].i = 1;
327 c8f53842 2007-03-26 devnull dotcmds[1].f = Xmark;
328 c8f53842 2007-03-26 devnull dotcmds[2].f = Xword;
329 f08fdedc 2003-11-23 devnull dotcmds[3].s="0";
330 c8f53842 2007-03-26 devnull dotcmds[4].f = Xlocal;
331 c8f53842 2007-03-26 devnull dotcmds[5].f = Xmark;
332 c8f53842 2007-03-26 devnull dotcmds[6].f = Xword;
333 f08fdedc 2003-11-23 devnull dotcmds[7].s="*";
334 c8f53842 2007-03-26 devnull dotcmds[8].f = Xlocal;
335 c8f53842 2007-03-26 devnull dotcmds[9].f = Xrdcmds;
336 c8f53842 2007-03-26 devnull dotcmds[10].f = Xunlocal;
337 c8f53842 2007-03-26 devnull dotcmds[11].f = Xunlocal;
338 c8f53842 2007-03-26 devnull dotcmds[12].f = Xreturn;
339 c8f53842 2007-03-26 devnull first = 0;
342 c8f53842 2007-03-26 devnull eflagok = 1;
343 f08fdedc 2003-11-23 devnull popword();
344 f08fdedc 2003-11-23 devnull if(p->argv->words && strcmp(p->argv->words->word, "-i")==0){
345 c8f53842 2007-03-26 devnull iflag = 1;
346 f08fdedc 2003-11-23 devnull popword();
348 f08fdedc 2003-11-23 devnull /* get input file */
349 f08fdedc 2003-11-23 devnull if(p->argv->words==0){
350 f08fdedc 2003-11-23 devnull Xerror1("Usage: . [-i] file [arg ...]");
353 c8f53842 2007-03-26 devnull zero = strdup(p->argv->words->word);
354 f08fdedc 2003-11-23 devnull popword();
356 c8f53842 2007-03-26 devnull for(path = searchpath(zero);path;path = path->next){
357 f08fdedc 2003-11-23 devnull strcpy(file, path->word);
358 c8f53842 2007-03-26 devnull if(file[0])
359 c8f53842 2007-03-26 devnull strcat(file, "/");
360 f08fdedc 2003-11-23 devnull strcat(file, zero);
361 c8f53842 2007-03-26 devnull if((fd = open(file, 0))>=0) break;
362 f08fdedc 2003-11-23 devnull if(strcmp(file, "/dev/stdin")==0){ /* for sun & ucb */
363 c8f53842 2007-03-26 devnull fd = Dup1(0);
364 c8f53842 2007-03-26 devnull if(fd>=0)
368 f08fdedc 2003-11-23 devnull if(fd<0){
369 f08fdedc 2003-11-23 devnull pfmt(err, "%s: ", zero);
370 f08fdedc 2003-11-23 devnull setstatus("can't open");
371 f08fdedc 2003-11-23 devnull Xerror(".: can't open");
374 f08fdedc 2003-11-23 devnull /* set up for a new command loop */
375 f08fdedc 2003-11-23 devnull start(dotcmds, 1, (struct var *)0);
376 f08fdedc 2003-11-23 devnull pushredir(RCLOSE, fd, 0);
377 c8f53842 2007-03-26 devnull runq->cmdfile = zero;
378 c8f53842 2007-03-26 devnull runq->cmdfd = openfd(fd);
379 c8f53842 2007-03-26 devnull runq->iflag = iflag;
380 c8f53842 2007-03-26 devnull runq->iflast = 0;
381 f08fdedc 2003-11-23 devnull /* push $* value */
382 f08fdedc 2003-11-23 devnull pushlist();
383 c8f53842 2007-03-26 devnull runq->argv->words = p->argv->words;
384 f08fdedc 2003-11-23 devnull /* free caller's copy of $* */
385 c8f53842 2007-03-26 devnull av = p->argv;
386 c8f53842 2007-03-26 devnull p->argv = av->next;
387 f08fdedc 2003-11-23 devnull efree((char *)av);
388 f08fdedc 2003-11-23 devnull /* push $0 value */
389 f08fdedc 2003-11-23 devnull pushlist();
390 f08fdedc 2003-11-23 devnull pushword(zero);
395 c8f53842 2007-03-26 devnull execflag(void)
397 f08fdedc 2003-11-23 devnull char *letter, *val;
398 f08fdedc 2003-11-23 devnull switch(count(runq->argv->words)){
400 f08fdedc 2003-11-23 devnull setstatus(flag[(uchar)runq->argv->words->next->word[0]]?"":"flag not set");
403 c8f53842 2007-03-26 devnull letter = runq->argv->words->next->word;
404 c8f53842 2007-03-26 devnull val = runq->argv->words->next->next->word;
405 f08fdedc 2003-11-23 devnull if(strlen(letter)==1){
406 f08fdedc 2003-11-23 devnull if(strcmp(val, "+")==0){
407 c8f53842 2007-03-26 devnull flag[(uchar)letter[0]] = flagset;
410 f08fdedc 2003-11-23 devnull if(strcmp(val, "-")==0){
411 c8f53842 2007-03-26 devnull flag[(uchar)letter[0]] = 0;
415 f08fdedc 2003-11-23 devnull default:
416 f08fdedc 2003-11-23 devnull Xerror1("Usage: flag [letter] [+-]");
419 f08fdedc 2003-11-23 devnull poplist();
423 c8f53842 2007-03-26 devnull execwhatis(void){ /* mildly wrong -- should fork before writing */
424 f08fdedc 2003-11-23 devnull word *a, *b, *path;
426 f08fdedc 2003-11-23 devnull struct builtin *bp;
427 f08fdedc 2003-11-23 devnull char file[512];
428 f08fdedc 2003-11-23 devnull struct io out[1];
429 f08fdedc 2003-11-23 devnull int found, sep;
430 c8f53842 2007-03-26 devnull a = runq->argv->words->next;
431 f08fdedc 2003-11-23 devnull if(a==0){
432 f08fdedc 2003-11-23 devnull Xerror1("Usage: whatis name ...");
435 f08fdedc 2003-11-23 devnull setstatus("");
436 c8f53842 2007-03-26 devnull out->fd = mapfd(1);
437 c8f53842 2007-03-26 devnull out->bufp = out->buf;
438 c8f53842 2007-03-26 devnull out->ebuf = &out->buf[NBUF];
439 c8f53842 2007-03-26 devnull out->strp = 0;
440 c8f53842 2007-03-26 devnull for(;a;a = a->next){
441 c8f53842 2007-03-26 devnull v = vlook(a->word);
442 f08fdedc 2003-11-23 devnull if(v->val){
443 f08fdedc 2003-11-23 devnull pfmt(out, "%s=", a->word);
444 f08fdedc 2003-11-23 devnull if(v->val->next==0)
445 f08fdedc 2003-11-23 devnull pfmt(out, "%q\n", v->val->word);
447 f08fdedc 2003-11-23 devnull sep='(';
448 c8f53842 2007-03-26 devnull for(b = v->val;b && b->word;b = b->next){
449 f08fdedc 2003-11-23 devnull pfmt(out, "%c%q", sep, b->word);
450 f08fdedc 2003-11-23 devnull sep=' ';
452 f08fdedc 2003-11-23 devnull pfmt(out, ")\n");
454 c8f53842 2007-03-26 devnull found = 1;
457 c8f53842 2007-03-26 devnull found = 0;
458 c8f53842 2007-03-26 devnull v = gvlook(a->word);
459 c8f53842 2007-03-26 devnull if(v->fn)
460 c8f53842 2007-03-26 devnull pfmt(out, "fn %s %s\n", v->name, v->fn[v->pc-1].s);
462 c8f53842 2007-03-26 devnull for(bp = Builtin;bp->name;bp++)
463 f08fdedc 2003-11-23 devnull if(strcmp(a->word, bp->name)==0){
464 f08fdedc 2003-11-23 devnull pfmt(out, "builtin %s\n", a->word);
467 f08fdedc 2003-11-23 devnull if(!bp->name){
468 c8f53842 2007-03-26 devnull for(path = searchpath(a->word);path;path = path->next){
469 f08fdedc 2003-11-23 devnull strcpy(file, path->word);
470 c8f53842 2007-03-26 devnull if(file[0])
471 c8f53842 2007-03-26 devnull strcat(file, "/");
472 f08fdedc 2003-11-23 devnull strcat(file, a->word);
473 f08fdedc 2003-11-23 devnull if(Executable(file)){
474 f08fdedc 2003-11-23 devnull pfmt(out, "%s\n", file);
478 f08fdedc 2003-11-23 devnull if(!path && !found){
479 f08fdedc 2003-11-23 devnull pfmt(err, "%s: not found\n", a->word);
480 f08fdedc 2003-11-23 devnull setstatus("not found");
485 f08fdedc 2003-11-23 devnull poplist();
486 f08fdedc 2003-11-23 devnull flush(err);
490 c8f53842 2007-03-26 devnull execwait(void)
492 f08fdedc 2003-11-23 devnull switch(count(runq->argv->words)){
493 c8f53842 2007-03-26 devnull default:
494 c8f53842 2007-03-26 devnull Xerror1("Usage: wait [pid]");
497 c8f53842 2007-03-26 devnull Waitfor(atoi(runq->argv->words->next->word), 0);
500 c8f53842 2007-03-26 devnull Waitfor(-1, 0);
503 f08fdedc 2003-11-23 devnull poplist();