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