Research V7 development
[unix-history] / usr / src / cmd / sh / service.c
CommitLineData
7c658c65
B
1#
2/*
3 * UNIX shell
4 *
5 * S. R. Bourne
6 * Bell Telephone Laboratories
7 *
8 */
9
10#include "defs.h"
11
12
13PROC VOID gsort();
14
15#define ARGMK 01
16
17INT errno;
18STRING 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
31VOID 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
68STRING 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
83INT 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
93STRING 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
109LOCAL STRING xecmsg;
110LOCAL STRING *xecenv;
111
112VOID 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
127LOCAL 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 /* set up new args */
149 setargs(t);
150 longjmp(subshell,1);
151
152 case ENOMEM:
153 failed(p,toobig);
154
155 case E2BIG:
156 failed(p,arglist);
157
158 case ETXTBSY:
159 failed(p,txtbsy);
160
161 default:
162 xecmsg=badexec;
163 case ENOENT:
164 return(prefix);
165 ENDSW
166}
167
168/* for processes to be waited for */
169#define MAXP 20
170LOCAL INT pwlist[MAXP];
171LOCAL INT pwc;
172
173postclr()
174{
175 REG INT *pw = pwlist;
176
177 WHILE pw <= &pwlist[pwc]
178 DO *pw++ = 0 OD
179 pwc=0;
180}
181
182VOID post(pcsid)
183 INT pcsid;
184{
185 REG INT *pw = pwlist;
186
187 IF pcsid
188 THEN WHILE *pw DO pw++ OD
189 IF pwc >= MAXP-1
190 THEN pw--;
191 ELSE pwc++;
192 FI
193 *pw = pcsid;
194 FI
195}
196
197VOID await(i)
198 INT i;
199{
200 INT rc=0, wx=0;
201 INT w;
202 INT ipwc = pwc;
203
204 post(i);
205 WHILE pwc
206 DO REG INT p;
207 REG INT sig;
208 INT w_hi;
209
210 BEGIN
211 REG INT *pw=pwlist;
212 p=wait(&w);
213 WHILE pw <= &pwlist[ipwc]
214 DO IF *pw==p
215 THEN *pw=0; pwc--;
216 ELSE pw++;
217 FI
218 OD
219 END
220
221 IF p == -1 THEN continue FI
222
223 w_hi = (w>>8)&LOBYTE;
224
225 IF sig = w&0177
226 THEN IF sig == 0177 /* ptrace! return */
227 THEN prs("ptrace: ");
228 sig = w_hi;
229 FI
230 IF sysmsg[sig]
231 THEN IF i!=p ORF (flags&prompt)==0 THEN prp(); prn(p); blank() FI
232 prs(sysmsg[sig]);
233 IF w&0200 THEN prs(coredump) FI
234 FI
235 newline();
236 FI
237
238 IF rc==0
239 THEN rc = (sig ? sig|SIGFLG : w_hi);
240 FI
241 wx |= w;
242 OD
243
244 IF wx ANDF flags&errflg
245 THEN exitsh(rc);
246 FI
247 exitval=rc; exitset();
248}
249
250BOOL nosubst;
251
252trim(at)
253 STRING at;
254{
255 REG STRING p;
256 REG CHAR c;
257 REG CHAR q=0;
258
259 IF p=at
260 THEN WHILE c = *p
261 DO *p++=c&STRIP; q |= c OD
262 FI
263 nosubst=q&QUOTE;
264}
265
266STRING mactrim(s)
267 STRING s;
268{
269 REG STRING t=macro(s);
270 trim(t);
271 return(t);
272}
273
274STRING *scan(argn)
275 INT argn;
276{
277 REG ARGPTR argp = Rcheat(gchain)&~ARGMK;
278 REG STRING *comargn, *comargm;
279
280 comargn=getstak(BYTESPERWORD*argn+BYTESPERWORD); comargm = comargn += argn; *comargn = ENDARGS;
281
282 WHILE argp
283 DO *--comargn = argp->argval;
284 IF argp = argp->argnxt
285 THEN trim(*comargn);
286 FI
287 IF argp==0 ORF Rcheat(argp)&ARGMK
288 THEN gsort(comargn,comargm);
289 comargm = comargn;
290 FI
291 /* Lcheat(argp) &= ~ARGMK; */
292 argp = Rcheat(argp)&~ARGMK;
293 OD
294 return(comargn);
295}
296
297LOCAL VOID gsort(from,to)
298 STRING from[], to[];
299{
300 INT k, m, n;
301 REG INT i, j;
302
303 IF (n=to-from)<=1 THEN return FI
304
305 FOR j=1; j<=n; j*=2 DONE
306
307 FOR m=2*j-1; m/=2;
308 DO k=n-m;
309 FOR j=0; j<k; j++
310 DO FOR i=j; i>=0; i-=m
311 DO REG STRING *fromi; fromi = &from[i];
312 IF cf(fromi[m],fromi[0])>0
313 THEN break;
314 ELSE STRING s; s=fromi[m]; fromi[m]=fromi[0]; fromi[0]=s;
315 FI
316 OD
317 OD
318 OD
319}
320
321/* Argument list generation */
322
323INT getarg(ac)
324 COMPTR ac;
325{
326 REG ARGPTR argp;
327 REG INT count=0;
328 REG COMPTR c;
329
330 IF c=ac
331 THEN argp=c->comarg;
332 WHILE argp
333 DO count += split(macro(argp->argval));
334 argp=argp->argnxt;
335 OD
336 FI
337 return(count);
338}
339
340LOCAL INT split(s)
341 REG STRING s;
342{
343 REG STRING argp;
344 REG INT c;
345 INT count=0;
346
347 LOOP sigchk(); argp=locstak()+BYTESPERWORD;
348 WHILE (c = *s++, !any(c,ifsnod.namval) && c)
349 DO *argp++ = c OD
350 IF argp==staktop+BYTESPERWORD
351 THEN IF c
352 THEN continue;
353 ELSE return(count);
354 FI
355 ELIF c==0
356 THEN s--;
357 FI
358 IF c=expand((argp=endstak(argp))->argval,0)
359 THEN count += c;
360 ELSE /* assign(&fngnod, argp->argval); */
361 makearg(argp); count++;
362 FI
363 Lcheat(gchain) |= ARGMK;
364 POOL
365}