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