|
|
1.1 root 1: /*
2: * Maybe `simple' is a misnomer.
3: */
4: #include "rc.h"
5: #include "getflags.h"
6: #include "exec.h"
7: #include "io.h"
8: #include "fns.h"
9: /*
10: * Search through the following code to see if we're just going to exit.
11: */
12: exitnext(void){
13: union code *c=&runq->code[runq->pc];
14: while(c->f==Xpopredir) c++;
15: return c->f==Xexit;
16: }
17: void Xsimple(void){
18: word *a;
19: thread *p=runq;
20: var *v;
21: struct builtin *bp;
22: int pid;
23: globlist();
24: a=runq->argv->words;
25: if(a==0){
26: Xerror("empty argument list");
27: return;
28: }
29: if(flag['x'])
30: pfmt(err, "%v\n", p->argv->words); /* wrong, should do redirs */
31: v=gvlook(a->word);
32: if(v->fn)
33: execfunc(v);
34: else{
35: if(strcmp(a->word, "builtin")==0){
36: if(count(a)==1){
37: pfmt(err, "builtin: empty argument list\n");
38: setstatus("empty arg list");
39: poplist();
40: return;
41: }
42: a=a->next;
43: popword();
44: }
45: for(bp=Builtin;bp->name;bp++)
46: if(strcmp(a->word, bp->name)==0){
47: (*bp->fnc)();
48: return;
49: }
50: if(exitnext()){
51: /* fork and wait is redundant */
52: pushword("exec");
53: execexec();
54: Xexit();
55: }
56: else{
57: flush(err);
58: Updenv();
59: switch(pid=fork()){
60: case -1:
61: Xperror("try again");
62: return;
63: case 0:
64: pushword("exec");
65: execexec();
66: Exit("can't exec");
67: default:
68: poplist();
69: /* interrupts don't get us out */
70: while(Waitfor(pid, 1) < 0)
71: ;
72: }
73: }
74: }
75: }
76: struct word nullpath={ "", 0};
77: void doredir(redir *rp)
78: {
79: if(rp){
80: doredir(rp->next);
81: switch(rp->type){
82: case ROPEN:
83: if(rp->from!=rp->to){
84: Dup(rp->from, rp->to);
85: close(rp->from);
86: }
87: break;
88: case RDUP: Dup(rp->from, rp->to); break;
89: case RCLOSE: close(rp->from); break;
90: }
91: }
92: }
93: word *searchpath(char *w){
94: word *path;
95: if(strncmp(w, "/", 1)==0
96: || strncmp(w, "#", 1)==0
97: || strncmp(w, "./", 2)==0
98: || strncmp(w, "../", 3)==0
99: || (path=vlook("path")->val)==0)
100: path=&nullpath;
101: return path;
102: }
103: void execexec(void){
104: word *path;
105: popword(); /* "exec" */
106: if(runq->argv->words==0){
107: Xerror("empty argument list");
108: return;
109: }
110: doredir(runq->redir);
111: Execute(runq->argv->words, searchpath(runq->argv->words->word));
112: poplist();
113: }
114: void execfunc(var *func)
115: {
116: word *starval;
117: popword();
118: starval=runq->argv->words;
119: runq->argv->words=0;
120: poplist();
121: start(func->fn, func->pc, (struct var *)0);
122: runq->local=newvar(strdup("*"), runq->local);
123: runq->local->val=starval;
124: runq->local->changed=1;
125: }
126: void execcd(void){
127: word *a=runq->argv->words;
128: word *cdpath;
129: char dir[512];
130: setstatus("can't cd");
131: cdpath=vlook("cdpath")->val;
132: switch(count(a)){
133: default:
134: pfmt(err, "Usage: cd [directory]\n");
135: break;
136: case 2:
137: if(a->next->word[0]=='/' || cdpath==0) cdpath=&nullpath;
138: for(;cdpath;cdpath=cdpath->next){
139: strcpy(dir, cdpath->word);
140: if(dir[0]) strcat(dir, "/");
141: strcat(dir, a->next->word);
142: if(chdir(dir)>=0){
143: if(strlen(cdpath->word)
144: && strcmp(cdpath->word, ".")!=0)
145: pfmt(err, "%s\n", dir);
146: setstatus("");
147: break;
148: }
149: }
150: if(cdpath==0) pfmt(err, "Can't cd %s\n", a->next->word);
151: break;
152: case 1:
153: a=vlook("home")->val;
154: if(count(a)>=1){
155: if(chdir(a->word)>=0)
156: setstatus("");
157: else
158: pfmt(err, "Can't cd %s\n", a->word);
159: }
160: else
161: pfmt(err, "Can't cd -- $home empty\n");
162: break;
163: }
164: poplist();
165: }
166: void execexit(void){
167: switch(count(runq->argv->words)){
168: default: pfmt(err, "Usage: exit [status]\nExiting anyway\n");
169: case 2: setstatus(runq->argv->words->next->word);
170: case 1: Xexit();
171: }
172: }
173: void execshift(void){
174: int n;
175: word *a;
176: var *star;
177: switch(count(runq->argv->words)){
178: default:
179: pfmt(err, "Usage: shift [n]\n");
180: setstatus("shift usage");
181: poplist();
182: return;
183: case 2: n=atoi(runq->argv->words->next->word); break;
184: case 1: n=1; break;
185: }
186: star=vlook("*");
187: for(;n && star->val;--n){
188: a=star->val->next;
189: efree(star->val->word);
190: efree((char *)star->val);
191: star->val=a;
192: star->changed=1;
193: }
194: setstatus("");
195: poplist();
196: }
197: int octal(char *s)
198: {
199: int n=0;
200: while(*s==' ' || *s=='\t' || *s=='\n') s++;
201: while('0'<=*s && *s<='7') n=n*8+*s++-'0';
202: return n;
203: }
204: int mapfd(int fd)
205: {
206: redir *rp;
207: for(rp=runq->redir;rp;rp=rp->next){
208: switch(rp->type){
209: case RCLOSE:
210: if(rp->from==fd) fd=-1;
211: break;
212: case RDUP:
213: case ROPEN:
214: if(rp->to==fd) fd=rp->from;
215: break;
216: }
217: }
218: return fd;
219: }
220: union code rdcmds[4];
221: void execcmds(io *f)
222: {
223: static int first=1;
224: if(first){
225: rdcmds[0].i=1;
226: rdcmds[1].f=Xrdcmds;
227: rdcmds[2].f=Xreturn;
228: first=0;
229: }
230: start(rdcmds, 1, runq->local);
231: runq->cmdfd=f;
232: runq->iflast=0;
233: }
234: void execeval(void){
235: char *cmdline, *s, *t;
236: int len=0;
237: word *ap;
238: if(count(runq->argv->words)<=1){
239: Xerror("Usage: eval cmd ...");
240: return;
241: }
242: eflagok=1;
243: for(ap=runq->argv->words->next;ap;ap=ap->next)
244: len+=1+strlen(ap->word);
245: cmdline=emalloc(len);
246: s=cmdline;
247: for(ap=runq->argv->words->next;ap;ap=ap->next){
248: for(t=ap->word;*t;) *s++=*t++;
249: *s++=' ';
250: }
251: s[-1]='\n';
252: poplist();
253: execcmds(opencore(cmdline, len));
254: efree(cmdline);
255: }
256: union code dotcmds[14];
257: void execdot(void){
258: int iflag=0;
259: int fd;
260: list *av;
261: thread *p=runq;
262: char *zero;
263: static int first=1;
264: char file[512];
265: word *path;
266: if(first){
267: dotcmds[0].i=1;
268: dotcmds[1].f=Xmark;
269: dotcmds[2].f=Xword;
270: dotcmds[3].s="0";
271: dotcmds[4].f=Xlocal;
272: dotcmds[5].f=Xmark;
273: dotcmds[6].f=Xword;
274: dotcmds[7].s="*";
275: dotcmds[8].f=Xlocal;
276: dotcmds[9].f=Xrdcmds;
277: dotcmds[10].f=Xunlocal;
278: dotcmds[11].f=Xunlocal;
279: dotcmds[12].f=Xreturn;
280: first=0;
281: }
282: else
283: eflagok=1;
284: popword();
285: if(p->argv->words && strcmp(p->argv->words->word, "-i")==0){
286: iflag=1;
287: popword();
288: }
289: /* get input file */
290: if(p->argv->words==0){
291: Xerror("Usage: . [-i] file [arg ...]");
292: return;
293: }
294: zero=strdup(p->argv->words->word);
295: popword();
296: strcpy(file, "**No file name**");
297: for(path=searchpath(zero);path;path=path->next){
298: strcpy(file, path->word);
299: if(file[0]) strcat(file, "/");
300: strcat(file, zero);
301: if((fd=open(file, 0))>=0) break;
302: if(strcmp(file, "/dev/stdin")==0){ /* for sun & ucb */
303: fd=Dup1(0);
304: if(fd>=0) break;
305: }
306: }
307: if(fd<0){
308: Xperror(file);
309: return;
310: }
311: /* set up for a new command loop */
312: start(dotcmds, 1, (struct var *)0);
313: pushredir(RCLOSE, fd, 0);
314: runq->cmdfile=zero;
315: runq->cmdfd=openfd(fd);
316: runq->iflag=iflag;
317: runq->iflast=0;
318: /* push $* value */
319: pushlist();
320: runq->argv->words=p->argv->words;
321: /* free caller's copy of $* */
322: av=p->argv;
323: p->argv=av->next;
324: efree((char *)av);
325: /* push $0 value */
326: pushlist();
327: pushword(zero);
328: ndot++;
329: }
330: void execflag(void){
331: char *letter, *val;
332: switch(count(runq->argv->words)){
333: case 2:
334: setstatus(flag[runq->argv->words->next->word[0]]?"":"flag not set");
335: break;
336: case 3:
337: letter=runq->argv->words->next->word;
338: val=runq->argv->words->next->next->word;
339: if(strlen(letter)==1){
340: if(strcmp(val, "+")==0){
341: flag[letter[0]]=flagset;
342: break;
343: }
344: if(strcmp(val, "-")==0){
345: flag[letter[0]]=0;
346: break;
347: }
348: }
349: default:
350: Xerror("Usage: flag [letter] [+-]");
351: return;
352: }
353: poplist();
354: }
355: void execwhatis(void){ /* mildly wrong -- should fork before writing */
356: word *a, *b, *path;
357: var *v;
358: struct builtin *bp;
359: char file[512];
360: struct io out[1];
361: int found, sep;
362: a=runq->argv->words->next;
363: if(a==0){
364: Xerror("Usage: whatis name ...");
365: return;
366: }
367: setstatus("");
368: out->fd=mapfd(1);
369: out->bufp=out->buf;
370: out->ebuf=&out->buf[NBUF];
371: out->strp=0;
372: for(;a;a=a->next){
373: v=vlook(a->word);
374: if(v->val){
375: pfmt(out, "%s=", a->word);
376: if(v->val->next==0)
377: pfmt(out, "%q\n", v->val->word);
378: else{
379: sep='(';
380: for(b=v->val;b && b->word;b=b->next){
381: pfmt(out, "%c%q", sep, b->word);
382: sep=' ';
383: }
384: pfmt(out, ")\n");
385: }
386: found=1;
387: }
388: else
389: found=0;
390: v=gvlook(a->word);
391: if(v->fn) pfmt(out, "fn %s %s\n", v->name, v->fn[v->pc-1].s);
392: else{
393: for(bp=Builtin;bp->name;bp++)
394: if(strcmp(a->word, bp->name)==0){
395: pfmt(out, "builtin %s\n", a->word);
396: break;
397: }
398: if(!bp->name){
399: for(path=searchpath(a->word);path;path=path->next){
400: strcpy(file, path->word);
401: if(file[0]) strcat(file, "/");
402: strcat(file, a->word);
403: if(Executable(file)){
404: pfmt(out, "%s\n", file);
405: break;
406: }
407: }
408: if(!path && !found){
409: pfmt(err, "%s: not found\n", a->word);
410: setstatus("not found");
411: }
412: }
413: }
414: }
415: poplist();
416: flush(err);
417: }
418: void execwait(void){
419: switch(count(runq->argv->words)){
420: default: Xerror("Usage: wait [pid]"); return;
421: case 2: Waitfor(atoi(runq->argv->words->next->word), 0); break;
422: case 1: Waitfor(-1, 0); break;
423: }
424: poplist();
425: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.