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