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