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