|
|
1.1 root 1: #
2: /*
3: * UNIX shell
4: *
5: * S. R. Bourne
6: * Bell Telephone Laboratories
7: *
8: */
9:
10: #include "defs.h"
11:
12:
13: PROC VOID gsort();
14:
15: #define ARGMK 01
16:
17: INT errno;
18: STRING sysmsg[];
19:
20: /* fault handling */
21: #define ENOMEM 12
22: #define ENOEXEC 8
23: #define E2BIG 7
24: #define ENOENT 2
25: #define ETXTBSY 26
26:
27:
28:
29: /* service routines for `execute' */
30:
31: VOID initio(iop)
32: IOPTR iop;
33: {
34: REG STRING ion;
35: REG INT iof, fd;
36:
37: IF iop
38: THEN iof=iop->iofile;
39: ion=mactrim(iop->ioname);
40: IF *ion ANDF (flags&noexec)==0
41: THEN IF iof&IODOC
42: THEN subst(chkopen(ion),(fd=tmpfil()));
43: close(fd); fd=chkopen(tmpout); unlink(tmpout);
44: ELIF iof&IOMOV
45: THEN IF eq(minus,ion)
46: THEN fd = -1;
47: close(iof&IOUFD);
48: ELIF (fd=stoi(ion))>=USERIO
49: THEN failed(ion,badfile);
50: ELSE fd=dup(fd);
51: FI
52: ELIF (iof&IOPUT)==0
53: THEN fd=chkopen(ion);
54: ELIF flags&rshflg
55: THEN failed(ion,restricted);
56: ELIF iof&IOAPP ANDF (fd=open(ion,1))>=0
57: THEN lseek(fd, 0L, 2);
58: ELSE fd=create(ion);
59: FI
60: IF fd>=0
61: THEN rename(fd,iof&IOUFD);
62: FI
63: FI
64: initio(iop->ionxt);
65: FI
66: }
67:
68: STRING getpath(s)
69: STRING s;
70: {
71: REG STRING path;
72: IF any('/',s)
73: THEN IF flags&rshflg
74: THEN failed(s, restricted);
75: ELSE return(nullstr);
76: FI
77: ELIF (path = pathnod.namval)==0
78: THEN return(defpath);
79: ELSE return(cpystak(path));
80: FI
81: }
82:
83: INT pathopen(path, name)
84: REG STRING path, name;
85: {
86: REG UFD f;
87:
88: REP path=catpath(path,name);
89: PER (f=open(curstak(),0))<0 ANDF path DONE
90: return(f);
91: }
92:
93: STRING catpath(path,name)
94: REG STRING path;
95: STRING name;
96: {
97: /* leaves result on top of stack */
98: REG STRING scanp = path,
99: argp = locstak();
100:
101: WHILE *scanp ANDF *scanp!=COLON DO *argp++ = *scanp++ OD
102: IF scanp!=path THEN *argp++='/' FI
103: IF *scanp==COLON THEN scanp++ FI
104: path=(*scanp ? scanp : 0); scanp=name;
105: WHILE (*argp++ = *scanp++) DONE
106: return(path);
107: }
108:
109: LOCAL STRING xecmsg;
110: LOCAL STRING *xecenv;
111:
112: VOID execa(at)
113: STRING at[];
114: {
115: REG STRING path;
116: REG STRING *t = at;
117:
118: IF (flags&noexec)==0
119: THEN xecmsg=notfound; path=getpath(*t);
120: namscan(exname);
121: xecenv=setenv();
122: WHILE path=execs(path,t) DONE
123: failed(*t,xecmsg);
124: FI
125: }
126:
127: LOCAL STRING execs(ap,t)
128: STRING ap;
129: REG STRING t[];
130: {
131: REG STRING p, prefix;
132:
133: prefix=catpath(ap,t[0]);
134: trim(p=curstak());
135:
136: sigchk();
137: execve(p, &t[0] ,xecenv);
138: SWITCH errno IN
139:
140: case ENOEXEC:
141: flags=0;
142: comdiv=0; ioset=0;
143: clearup(); /* remove open files and for loop junk */
144: IF input THEN close(input) FI
145: close(output); output=2;
146: input=chkopen(p);
147:
148: /* band aid to get csh... 2/26/79 */
149: {
150: char c;
151: if (!isatty(input)) {
152: read(input, &c, 1);
153: if (c == '#')
154: gocsh(t, p, xecenv);
155: lseek(input, (long) 0, 0);
156: }
157: }
158:
159: /* set up new args */
160: setargs(t);
161: longjmp(subshell,1);
162:
163: case ENOMEM:
164: failed(p,toobig);
165:
166: case E2BIG:
167: failed(p,arglist);
168:
169: case ETXTBSY:
170: failed(p,txtbsy);
171:
172: default:
173: xecmsg=badexec;
174: case ENOENT:
175: return(prefix);
176: ENDSW
177: }
178:
179: gocsh(t, cp, xecenv)
180: register char **t, *cp, **xecenv;
181: {
182: char **newt[1000];
183: register char **p;
184: register int i;
185:
186: for (i = 0; t[i]; i++)
187: newt[i+1] = t[i];
188: newt[i+1] = 0;
189: newt[0] = "/bin/csh";
190: newt[1] = cp;
191: execve("/bin/csh", newt, xecenv);
192: }
193:
194: /* for processes to be waited for */
195: #define MAXP 20
196: LOCAL INT pwlist[MAXP];
197: LOCAL INT pwc;
198:
199: postclr()
200: {
201: REG INT *pw = pwlist;
202:
203: WHILE pw <= &pwlist[pwc]
204: DO *pw++ = 0 OD
205: pwc=0;
206: }
207:
208: VOID post(pcsid)
209: INT pcsid;
210: {
211: REG INT *pw = pwlist;
212:
213: IF pcsid
214: THEN WHILE *pw DO pw++ OD
215: IF pwc >= MAXP-1
216: THEN pw--;
217: ELSE pwc++;
218: FI
219: *pw = pcsid;
220: FI
221: }
222:
223: VOID await(i)
224: INT i;
225: {
226: INT rc=0, wx=0;
227: INT w;
228: INT ipwc = pwc;
229:
230: post(i);
231: WHILE pwc
232: DO REG INT p;
233: REG INT sig;
234: INT w_hi;
235:
236: BEGIN
237: REG INT *pw=pwlist;
238: p=wait(&w);
239: WHILE pw <= &pwlist[ipwc]
240: DO IF *pw==p
241: THEN *pw=0; pwc--;
242: ELSE pw++;
243: FI
244: OD
245: END
246:
247: IF p == -1 THEN continue FI
248:
249: w_hi = (w>>8)&LOBYTE;
250:
251: IF sig = w&0177
252: THEN IF sig == 0177 /* ptrace! return */
253: THEN prs("ptrace: ");
254: sig = w_hi;
255: FI
256: IF sysmsg[sig]
257: THEN IF i!=p ORF (flags&prompt)==0 THEN prp(); prn(p); blank() FI
258: prs(sysmsg[sig]);
259: IF w&0200 THEN prs(coredump) FI
260: FI
261: newline();
262: FI
263:
264: IF rc==0
265: THEN rc = (sig ? sig|SIGFLG : w_hi);
266: FI
267: wx |= w;
268: OD
269:
270: IF wx ANDF flags&errflg
271: THEN exitsh(rc);
272: FI
273: exitval=rc; exitset();
274: }
275:
276: BOOL nosubst;
277:
278: trim(at)
279: STRING at;
280: {
281: REG STRING p;
282: REG CHAR c;
283: REG CHAR q=0;
284:
285: IF p=at
286: THEN WHILE c = *p
287: DO *p++=c&STRIP; q |= c OD
288: FI
289: nosubst=q"E;
290: }
291:
292: STRING mactrim(s)
293: STRING s;
294: {
295: REG STRING t=macro(s);
296: trim(t);
297: return(t);
298: }
299:
300: STRING *scan(argn)
301: INT argn;
302: {
303: REG ARGPTR argp = Rcheat(gchain)&~ARGMK;
304: REG STRING *comargn, *comargm;
305:
306: comargn=getstak(BYTESPERWORD*argn+BYTESPERWORD); comargm = comargn += argn; *comargn = ENDARGS;
307:
308: WHILE argp
309: DO *--comargn = argp->argval;
310: IF argp = argp->argnxt
311: THEN trim(*comargn);
312: FI
313: IF argp==0 ORF Rcheat(argp)&ARGMK
314: THEN gsort(comargn,comargm);
315: comargm = comargn;
316: FI
317: /* Lcheat(argp) &= ~ARGMK; */
318: argp = Rcheat(argp)&~ARGMK;
319: OD
320: return(comargn);
321: }
322:
323: LOCAL VOID gsort(from,to)
324: STRING from[], to[];
325: {
326: INT k, m, n;
327: REG INT i, j;
328:
329: IF (n=to-from)<=1 THEN return FI
330:
331: FOR j=1; j<=n; j*=2 DONE
332:
333: FOR m=2*j-1; m/=2;
334: DO k=n-m;
335: FOR j=0; j<k; j++
336: DO FOR i=j; i>=0; i-=m
337: DO REG STRING *fromi; fromi = &from[i];
338: IF cf(fromi[m],fromi[0])>0
339: THEN break;
340: ELSE STRING s; s=fromi[m]; fromi[m]=fromi[0]; fromi[0]=s;
341: FI
342: OD
343: OD
344: OD
345: }
346:
347: /* Argument list generation */
348:
349: INT getarg(ac)
350: COMPTR ac;
351: {
352: REG ARGPTR argp;
353: REG INT count=0;
354: REG COMPTR c;
355:
356: IF c=ac
357: THEN argp=c->comarg;
358: WHILE argp
359: DO count += split(macro(argp->argval));
360: argp=argp->argnxt;
361: OD
362: FI
363: return(count);
364: }
365:
366: LOCAL INT split(s)
367: REG STRING s;
368: {
369: REG STRING argp;
370: REG INT c;
371: INT count=0;
372:
373: LOOP sigchk(); argp=locstak()+BYTESPERWORD;
374: WHILE (c = *s++, !any(c,ifsnod.namval) && c)
375: DO *argp++ = c OD
376: IF argp==staktop+BYTESPERWORD
377: THEN IF c
378: THEN continue;
379: ELSE return(count);
380: FI
381: ELIF c==0
382: THEN s--;
383: FI
384: IF c=expand((argp=endstak(argp))->argval,0)
385: THEN count += c;
386: ELSE /* assign(&fngnod, argp->argval); */
387: makearg(argp); count++;
388: FI
389: Lcheat(gchain) |= ARGMK;
390: POOL
391: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.