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