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