|
|
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, 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, xecenv)
180: register char **t, **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: execve("/bin/csh", newt, xecenv);
191: }
192:
193: /* for processes to be waited for */
194: #define MAXP 20
195: LOCAL INT pwlist[MAXP];
196: LOCAL INT pwc;
197:
198: postclr()
199: {
200: REG INT *pw = pwlist;
201:
202: WHILE pw <= &pwlist[pwc]
203: DO *pw++ = 0 OD
204: pwc=0;
205: }
206:
207: VOID post(pcsid)
208: INT pcsid;
209: {
210: REG INT *pw = pwlist;
211:
212: IF pcsid
213: THEN WHILE *pw DO pw++ OD
214: IF pwc >= MAXP-1
215: THEN pw--;
216: ELSE pwc++;
217: FI
218: *pw = pcsid;
219: FI
220: }
221:
222: VOID await(i)
223: INT i;
224: {
225: INT rc=0, wx=0;
226: INT w;
227: INT ipwc = pwc;
228:
229: post(i);
230: WHILE pwc
231: DO REG INT p;
232: REG INT sig;
233: INT w_hi;
234:
235: BEGIN
236: REG INT *pw=pwlist;
237: p=wait(&w);
238: WHILE pw <= &pwlist[ipwc]
239: DO IF *pw==p
240: THEN *pw=0; pwc--;
241: ELSE pw++;
242: FI
243: OD
244: END
245:
246: IF p == -1 THEN continue FI
247:
248: w_hi = (w>>8)&LOBYTE;
249:
250: IF sig = w&0177
251: THEN IF sig == 0177 /* ptrace! return */
252: THEN prs("ptrace: ");
253: sig = w_hi;
254: FI
255: IF sysmsg[sig]
256: THEN IF i!=p ORF (flags&prompt)==0 THEN prp(); prn(p); blank() FI
257: prs(sysmsg[sig]);
258: IF w&0200 THEN prs(coredump) FI
259: FI
260: newline();
261: FI
262:
263: IF rc==0
264: THEN rc = (sig ? sig|SIGFLG : w_hi);
265: FI
266: wx |= w;
267: OD
268:
269: IF wx ANDF flags&errflg
270: THEN exitsh(rc);
271: FI
272: exitval=rc; exitset();
273: }
274:
275: BOOL nosubst;
276:
277: trim(at)
278: STRING at;
279: {
280: REG STRING p;
281: REG CHAR c;
282: REG CHAR q=0;
283:
284: IF p=at
285: THEN WHILE c = *p
286: DO *p++=c&STRIP; q |= c OD
287: FI
288: nosubst=q"E;
289: }
290:
291: STRING mactrim(s)
292: STRING s;
293: {
294: REG STRING t=macro(s);
295: trim(t);
296: return(t);
297: }
298:
299: STRING *scan(argn)
300: INT argn;
301: {
302: REG ARGPTR argp = Rcheat(gchain)&~ARGMK;
303: REG STRING *comargn, *comargm;
304:
305: comargn=getstak(BYTESPERWORD*argn+BYTESPERWORD); comargm = comargn += argn; *comargn = ENDARGS;
306:
307: WHILE argp
308: DO *--comargn = argp->argval;
309: IF argp = argp->argnxt
310: THEN trim(*comargn);
311: FI
312: IF argp==0 ORF Rcheat(argp)&ARGMK
313: THEN gsort(comargn,comargm);
314: comargm = comargn;
315: FI
316: /* Lcheat(argp) &= ~ARGMK; */
317: argp = Rcheat(argp)&~ARGMK;
318: OD
319: return(comargn);
320: }
321:
322: LOCAL VOID gsort(from,to)
323: STRING from[], to[];
324: {
325: INT k, m, n;
326: REG INT i, j;
327:
328: IF (n=to-from)<=1 THEN return FI
329:
330: FOR j=1; j<=n; j*=2 DONE
331:
332: FOR m=2*j-1; m/=2;
333: DO k=n-m;
334: FOR j=0; j<k; j++
335: DO FOR i=j; i>=0; i-=m
336: DO REG STRING *fromi; fromi = &from[i];
337: IF cf(fromi[m],fromi[0])>0
338: THEN break;
339: ELSE STRING s; s=fromi[m]; fromi[m]=fromi[0]; fromi[0]=s;
340: FI
341: OD
342: OD
343: OD
344: }
345:
346: /* Argument list generation */
347:
348: INT getarg(ac)
349: COMPTR ac;
350: {
351: REG ARGPTR argp;
352: REG INT count=0;
353: REG COMPTR c;
354:
355: IF c=ac
356: THEN argp=c->comarg;
357: WHILE argp
358: DO count += split(macro(argp->argval));
359: argp=argp->argnxt;
360: OD
361: FI
362: return(count);
363: }
364:
365: LOCAL INT split(s)
366: REG STRING s;
367: {
368: REG STRING argp;
369: REG INT c;
370: INT count=0;
371:
372: LOOP sigchk(); argp=locstak()+BYTESPERWORD;
373: WHILE (c = *s++, !any(c,ifsnod.namval) && c)
374: DO *argp++ = c OD
375: IF argp==staktop+BYTESPERWORD
376: THEN IF c
377: THEN continue;
378: ELSE return(count);
379: FI
380: ELIF c==0
381: THEN s--;
382: FI
383: IF c=expand((argp=endstak(argp))->argval,0)
384: THEN count += c;
385: ELSE /* assign(&fngnod, argp->argval); */
386: makearg(argp); count++;
387: FI
388: Lcheat(gchain) |= ARGMK;
389: POOL
390: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.