1*35161Smarc /*
2*35161Smarc
3*35161Smarc * Copyright (c) 1984, 1985, 1986 AT&T
4*35161Smarc * All Rights Reserved
5*35161Smarc
6*35161Smarc * THIS IS UNPUBLISHED PROPRIETARY SOURCE
7*35161Smarc * CODE OF AT&T.
8*35161Smarc * The copyright notice above does not
9*35161Smarc * evidence any actual or intended
10*35161Smarc * publication of such source code.
11*35161Smarc
12*35161Smarc */
13*35161Smarc /* @(#)service.c 1.1 */
14*35161Smarc /*
15*35161Smarc * UNIX shell
16*35161Smarc *
17*35161Smarc * S. R. Bourne
18*35161Smarc * Rewritten by David Korn
19*35161Smarc * AT&T Bell Laboratories
20*35161Smarc *
21*35161Smarc */
22*35161Smarc
23*35161Smarc #include <errno.h>
24*35161Smarc #include <sys/types.h>
25*35161Smarc #include <sys/stat.h>
26*35161Smarc #include "flags.h"
27*35161Smarc #include "defs.h"
28*35161Smarc #include "sym.h"
29*35161Smarc #include "io.h"
30*35161Smarc #include "name.h"
31*35161Smarc #include "brkincr.h"
32*35161Smarc #include "mode.h"
33*35161Smarc #include "stak.h"
34*35161Smarc #include "shtype.h"
35*35161Smarc #include "builtins.h"
36*35161Smarc #include "jobs.h"
37*35161Smarc
38*35161Smarc #ifndef BSD_4_2
39*35161Smarc # ifdef BSD
40*35161Smarc # define fcntl(a,b,c) dup2(a,b)
41*35161Smarc # endif /* BSD */
42*35161Smarc #endif /* BSD_4_2 */
43*35161Smarc
44*35161Smarc FILE *pathopen();
45*35161Smarc char *getpath();
46*35161Smarc char *fullname();
47*35161Smarc int initio();
48*35161Smarc void exfunct();
49*35161Smarc #ifndef JOBS
50*35161Smarc void postclr();
51*35161Smarc int post();
52*35161Smarc void await();
53*35161Smarc #endif /* JOBS */
54*35161Smarc
55*35161Smarc extern void arg_clear();
56*35161Smarc extern DOLPTR arg_new();
57*35161Smarc extern void arg_set();
58*35161Smarc extern void arg_reset();
59*35161Smarc extern char *catpath();
60*35161Smarc extern FILE *chkopen();
61*35161Smarc extern STKPTR cpystak();
62*35161Smarc extern FILE *create();
63*35161Smarc extern void exitsh();
64*35161Smarc extern void failed();
65*35161Smarc extern NAMPTR findnod();
66*35161Smarc extern void free();
67*35161Smarc extern void gscan_some();
68*35161Smarc extern char *itos();
69*35161Smarc extern STKPTR locstak();
70*35161Smarc extern void mac_subst();
71*35161Smarc extern char *mactrim();
72*35161Smarc extern void mem_scope();
73*35161Smarc extern void mem_unscope();
74*35161Smarc extern char *movstr();
75*35161Smarc extern void p_setout();
76*35161Smarc extern void p_flush();
77*35161Smarc extern void p_prp();
78*35161Smarc #ifdef JOBS
79*35161Smarc extern void postclr();
80*35161Smarc #endif /* JOBS */
81*35161Smarc extern char *qvalup();
82*35161Smarc extern char *realias();
83*35161Smarc extern void rmlocal();
84*35161Smarc extern char **setenv();
85*35161Smarc extern void setlist();
86*35161Smarc extern char *simple();
87*35161Smarc extern char *strchr();
88*35161Smarc extern FILE *tmp_open();
89*35161Smarc extern void trim();
90*35161Smarc extern char *valup();
91*35161Smarc
92*35161Smarc static char *prune();
93*35161Smarc #ifndef VFORK
94*35161Smarc static void exscript();
95*35161Smarc #endif /* VFORK */
96*35161Smarc static char *execs();
97*35161Smarc
98*35161Smarc #define LOBYTE 0377
99*35161Smarc #ifdef u370
100*35161Smarc #define MAXP 75
101*35161Smarc #else
102*35161Smarc #define MAXP 32
103*35161Smarc #endif /* u370 */
104*35161Smarc #define MAXDEPTH (32*sizeof(int)) /* maximum levels of recursion */
105*35161Smarc
106*35161Smarc
107*35161Smarc #ifndef JOBS
108*35161Smarc static int maxpost; /* highest number running process */
109*35161Smarc static int numpost; /* number of running processes */
110*35161Smarc
111*35161Smarc /* for processes to be waited for */
112*35161Smarc static struct process pwlist[MAXP];
113*35161Smarc #endif /* JOBS */
114*35161Smarc static char *xecmsg;
115*35161Smarc static char **xecenv;
116*35161Smarc #ifdef VFORK
117*35161Smarc NAMPTR lookup();
118*35161Smarc #endif /* VFORK */
119*35161Smarc
120*35161Smarc
121*35161Smarc /*
122*35161Smarc * service routines for `execute'
123*35161Smarc * flag > 0 if files are to be restored
124*35161Smarc * flag < 0 if files are to be closed on exec
125*35161Smarc */
126*35161Smarc
initio(iop,flag)127*35161Smarc int initio(iop,flag)
128*35161Smarc IOPTR iop;
129*35161Smarc {
130*35161Smarc register char *ion;
131*35161Smarc register int iof;
132*35161Smarc register FILE *fd;
133*35161Smarc char fname[TMPSIZ];
134*35161Smarc int fn;
135*35161Smarc int mark = MARK;
136*35161Smarc int indx = topfd;
137*35161Smarc if(flag<0)
138*35161Smarc mark = 0;
139*35161Smarc for(;iop;iop=iop->ionxt)
140*35161Smarc {
141*35161Smarc iof=iop->iofile;
142*35161Smarc if(flag>0)
143*35161Smarc {
144*35161Smarc /* save current file descriptor */
145*35161Smarc savefd(iof&IOUFD,indx);
146*35161Smarc }
147*35161Smarc ion=mactrim(iop->ioname,1);
148*35161Smarc if(*ion && is_option(NOEXEC)==0)
149*35161Smarc {
150*35161Smarc if(iof&IODOC)
151*35161Smarc {
152*35161Smarc fd = tmp_open(fname);
153*35161Smarc unlink(fname);
154*35161Smarc mac_subst(chkopen(ion),fd);
155*35161Smarc }
156*35161Smarc else if(iof&IOMOV)
157*35161Smarc {
158*35161Smarc if(eq(minus,ion))
159*35161Smarc {
160*35161Smarc fclose(file_fd(iof&IOUFD));
161*35161Smarc fd = NULL;
162*35161Smarc }
163*35161Smarc else if(((fn=atoi(ion))>=USERIO) ||
164*35161Smarc (fd=fdopen(dup(fn),(iof&IOPUT)?"w+":"r")) == NULL)
165*35161Smarc failed(ion,badfile);
166*35161Smarc }
167*35161Smarc else if((iof&IOPUT)==0)
168*35161Smarc {
169*35161Smarc fd=chkopen(ion);
170*35161Smarc }
171*35161Smarc else if(is_option(RSHFLG))
172*35161Smarc failed(ion,restricted);
173*35161Smarc else if((iof&IOAPP) == 0 || (fd=fdopen(open(ion,1),"a"))==NULL)
174*35161Smarc {
175*35161Smarc if((fd=create(ion)) == NULL)
176*35161Smarc failed(ion,badcreate);
177*35161Smarc }
178*35161Smarc if(fd!=NULL)
179*35161Smarc frenumber(fd,(iof&IOUFD)|mark);
180*35161Smarc }
181*35161Smarc }
182*35161Smarc return(indx);
183*35161Smarc }
184*35161Smarc
185*35161Smarc /*
186*35161Smarc * given <s> return a colon separated list of directories to search on the stack
187*35161Smarc * This routine adds names to the tracked alias list, if possible, and returns
188*35161Smarc * a reduced path string for tracked aliases
189*35161Smarc */
190*35161Smarc
getpath(s)191*35161Smarc char *getpath(s)
192*35161Smarc char *s;
193*35161Smarc {
194*35161Smarc register char *path;
195*35161Smarc register NAMPTR np;
196*35161Smarc if(strchr(s,'/'))
197*35161Smarc return(nullstr);
198*35161Smarc path = qvalup(PATHNOD);
199*35161Smarc if(path==NULL)
200*35161Smarc path = defpath;
201*35161Smarc path = cpystak(path);
202*35161Smarc /* track alias if possible */
203*35161Smarc np=findnod(s,alias,CHK_FOR);
204*35161Smarc if(np==NULL && is_option(HASHALL) && (np=findnod(s,alias,CHK_FOR|1)))
205*35161Smarc attrib(np, N_EXPORT|NO_ALIAS|T_FLAG);
206*35161Smarc if(np && attest(np,T_FLAG))
207*35161Smarc {
208*35161Smarc if(attest(np,NO_ALIAS))
209*35161Smarc {
210*35161Smarc /* don't bother to look up alias if forked */
211*35161Smarc if(states&FORKED)
212*35161Smarc return(path);
213*35161Smarc /* if realias fails then a search won't find anything */
214*35161Smarc if(realias(np)==NIL)
215*35161Smarc return(nullstr);
216*35161Smarc }
217*35161Smarc /* tracked alias use reduced path */
218*35161Smarc path = prune(path,valup(np));
219*35161Smarc }
220*35161Smarc return(path);
221*35161Smarc }
222*35161Smarc
pathopen(name)223*35161Smarc FILE *pathopen(name)
224*35161Smarc register char *name;
225*35161Smarc {
226*35161Smarc register char *path;
227*35161Smarc register int n;
228*35161Smarc struct stat statb;
229*35161Smarc if(strchr(name,'/'))
230*35161Smarc {
231*35161Smarc if(is_option(RSHFLG))
232*35161Smarc failed(name, restricted);
233*35161Smarc else
234*35161Smarc path = nullstr;
235*35161Smarc }
236*35161Smarc else
237*35161Smarc {
238*35161Smarc path = qvalup(PATHNOD);
239*35161Smarc if(path==NULL)
240*35161Smarc path = defpath;
241*35161Smarc path = cpystak(path);
242*35161Smarc }
243*35161Smarc do
244*35161Smarc {
245*35161Smarc path=catpath(path,name);
246*35161Smarc if((n = open(curstak(),0)) >= 0)
247*35161Smarc {
248*35161Smarc if(fstat(n,&statb)<0 || (statb.st_mode&S_IFMT)!=S_IFREG)
249*35161Smarc {
250*35161Smarc close(n);
251*35161Smarc n = -1;
252*35161Smarc }
253*35161Smarc }
254*35161Smarc }
255*35161Smarc while( n<0 && path);
256*35161Smarc return(fdopen(n,"r"));
257*35161Smarc }
258*35161Smarc
259*35161Smarc
260*35161Smarc /*
261*35161Smarc * do a path search and find the full pathname of file name
262*35161Smarc * if name is not a simple name, then name is a tracked alias
263*35161Smarc */
264*35161Smarc
fullname(fname)265*35161Smarc char *fullname(fname)
266*35161Smarc char *fname;
267*35161Smarc {
268*35161Smarc register char *name;
269*35161Smarc register int f;
270*35161Smarc register char *path;
271*35161Smarc if(*fname!='/')
272*35161Smarc name=fname;
273*35161Smarc else
274*35161Smarc name = simple(fname);
275*35161Smarc path = getpath(name);
276*35161Smarc do
277*35161Smarc {
278*35161Smarc path=catpath(path,name);
279*35161Smarc if((f=access(curstak(),1))>=0)
280*35161Smarc {
281*35161Smarc if(!ftype(curstak(),S_IFMT,S_IFREG))
282*35161Smarc f = -1;
283*35161Smarc }
284*35161Smarc }
285*35161Smarc while(f<0 && path);
286*35161Smarc return(f<0?0:curstak());
287*35161Smarc }
288*35161Smarc
catpath(path,name)289*35161Smarc char *catpath(path,name)
290*35161Smarc register char *path;
291*35161Smarc char * name;
292*35161Smarc {
293*35161Smarc /* leaves result on top of stack */
294*35161Smarc register char *scanp = path;
295*35161Smarc register char *argp = locstak();
296*35161Smarc while(*scanp && *scanp!=':')
297*35161Smarc *argp++ = *scanp++;
298*35161Smarc if(scanp!=path)
299*35161Smarc {
300*35161Smarc *argp++= '/';
301*35161Smarc /* position past ":" unless a trailing colon after pathname */
302*35161Smarc if(*scanp && *++scanp==0)
303*35161Smarc scanp--;
304*35161Smarc }
305*35161Smarc else
306*35161Smarc while(*scanp == ':')
307*35161Smarc scanp++;
308*35161Smarc path=(*scanp ? scanp : 0);
309*35161Smarc scanp=name;
310*35161Smarc while((*argp++ = *scanp++));
311*35161Smarc staktop = argp;
312*35161Smarc return(path);
313*35161Smarc }
314*35161Smarc
315*35161Smarc
execa(at,local)316*35161Smarc void execa(at,local)
317*35161Smarc char * at[];
318*35161Smarc ARGPTR local; /* local environment modification */
319*35161Smarc {
320*35161Smarc register char *path = nullstr;
321*35161Smarc register char **t = at;
322*35161Smarc if(is_option(NOEXEC)==0)
323*35161Smarc {
324*35161Smarc xecmsg=notfound;
325*35161Smarc #ifdef VFORK
326*35161Smarc if(local)
327*35161Smarc mem_scope(local);
328*35161Smarc xecenv=setenv();
329*35161Smarc #else
330*35161Smarc setlist(local,N_EXPORT);
331*35161Smarc xecenv=setenv();
332*35161Smarc #endif /* VFORK */
333*35161Smarc if(strchr(t[0],'/'))
334*35161Smarc {
335*35161Smarc /* name containing / not allowed for restricted shell */
336*35161Smarc if(is_option(RSHFLG))
337*35161Smarc failed(t[0],restricted);
338*35161Smarc }
339*35161Smarc else
340*35161Smarc path=getpath(*t);
341*35161Smarc #ifdef VFORK
342*35161Smarc if(local)
343*35161Smarc mem_unscope();
344*35161Smarc #endif /* VFORK */
345*35161Smarc /* insert _= onto stack in front of pathname */
346*35161Smarc *--xecenv = stakbot;
347*35161Smarc *stakbot++ = '_';
348*35161Smarc *stakbot++ = '=';
349*35161Smarc while(path=execs(path,t));
350*35161Smarc failed(*t,xecmsg);
351*35161Smarc }
352*35161Smarc }
353*35161Smarc
354*35161Smarc /*
355*35161Smarc * This routine constructs a short path consisting of all
356*35161Smarc * Relative directories up to the directory of fullname <name>
357*35161Smarc */
prune(path,fullname)358*35161Smarc static char *prune(path,fullname)
359*35161Smarc register char *path;
360*35161Smarc char *fullname;
361*35161Smarc {
362*35161Smarc register char *p = path;
363*35161Smarc register char *s;
364*35161Smarc int n = 1;
365*35161Smarc char *base;
366*35161Smarc char *inpath = path;
367*35161Smarc if(fullname==NULL || *fullname != '/' || *path==0)
368*35161Smarc return(path);
369*35161Smarc base = simple(fullname);
370*35161Smarc do
371*35161Smarc {
372*35161Smarc /* a null path means current directory */
373*35161Smarc if(*path == ':')
374*35161Smarc {
375*35161Smarc *p++ = ':';
376*35161Smarc path++;
377*35161Smarc continue;
378*35161Smarc }
379*35161Smarc s = path;
380*35161Smarc path=catpath(path,base);
381*35161Smarc if(*s != '/' || (n=strcmp(curstak(),fullname))==0)
382*35161Smarc {
383*35161Smarc /* position p past end of path */
384*35161Smarc while(*s && *s!=':')
385*35161Smarc *p++ = *s++;
386*35161Smarc if(n==0)
387*35161Smarc {
388*35161Smarc *p = 0;
389*35161Smarc return(inpath);
390*35161Smarc }
391*35161Smarc *p++ = ':';
392*35161Smarc }
393*35161Smarc }
394*35161Smarc while(path);
395*35161Smarc /* if there is no match just return path */
396*35161Smarc path = qvalup(PATHNOD);
397*35161Smarc if(path==NULL)
398*35161Smarc path = defpath;
399*35161Smarc strcpy(inpath,path);
400*35161Smarc return(inpath);
401*35161Smarc }
402*35161Smarc
403*35161Smarc #ifdef XENIX
404*35161Smarc /*
405*35161Smarc * This code takes care of a bug in the XENIX exec routine
406*35161Smarc * Contributed by Pat Wood
407*35161Smarc */
ex_xenix(file)408*35161Smarc static ex_xenix(file)
409*35161Smarc char *file;
410*35161Smarc {
411*35161Smarc struct stat stats;
412*35161Smarc register int fd;
413*35161Smarc unsigned short magic;
414*35161Smarc if((fd = open(file,0)) == -1) /* can't read, so can't be shell prog */
415*35161Smarc return(1);
416*35161Smarc read(fd, &magic, sizeof(magic));
417*35161Smarc if(magic == 01006) /* magic for xenix executable */
418*35161Smarc {
419*35161Smarc close(fd);
420*35161Smarc return(1);
421*35161Smarc }
422*35161Smarc fstat(fd, &stats);
423*35161Smarc close(fd);
424*35161Smarc errno = ENOEXEC;
425*35161Smarc if(!geteuid())
426*35161Smarc {
427*35161Smarc if(!(stats.st_mode & 0111))
428*35161Smarc errno = EACCES;
429*35161Smarc return(0);
430*35161Smarc }
431*35161Smarc if((geteuid() == stats.st_uid))
432*35161Smarc {
433*35161Smarc if(!(stats.st_mode & 0100))
434*35161Smarc errno = EACCES;
435*35161Smarc return(0);
436*35161Smarc }
437*35161Smarc if((getegid() == stats.st_gid))
438*35161Smarc {
439*35161Smarc if(!(stats.st_mode & 0010))
440*35161Smarc errno = EACCES;
441*35161Smarc return(0);
442*35161Smarc }
443*35161Smarc if(!(stats.st_mode & 0001))
444*35161Smarc errno = EACCES;
445*35161Smarc return(0);
446*35161Smarc }
447*35161Smarc #endif /* XENIX */
448*35161Smarc
execs(ap,t)449*35161Smarc static char *execs(ap,t)
450*35161Smarc char * ap;
451*35161Smarc register char **t;
452*35161Smarc {
453*35161Smarc register char *p, *prefix;
454*35161Smarc prefix=catpath(ap,t[0]);
455*35161Smarc trim(p=curstak());
456*35161Smarc p_flush();
457*35161Smarc if(trapnote&SIGSET)
458*35161Smarc exitsh(SIGFAIL);
459*35161Smarc #ifdef XENIX
460*35161Smarc if(ex_xenix(p))
461*35161Smarc #endif /* XENIX */
462*35161Smarc execve(p, &t[0] ,xecenv);
463*35161Smarc switch(errno)
464*35161Smarc {
465*35161Smarc case ENOEXEC:
466*35161Smarc #ifdef VFORK
467*35161Smarc {
468*35161Smarc /* this code handles the !# interpreter name convention */
469*35161Smarc char iname[256];
470*35161Smarc #ifdef SUID_EXEC
471*35161Smarc /* check if file cannot open for read or script is setuid/setgid */
472*35161Smarc static char name[] = "/tmp/euidXXXXXX";
473*35161Smarc register int n;
474*35161Smarc register int euserid;
475*35161Smarc struct stat statb;
476*35161Smarc if((n=open(p,0)) >= 0)
477*35161Smarc {
478*35161Smarc if(fstat(n,&statb)==0)
479*35161Smarc {
480*35161Smarc if((statb.st_mode&(S_ISUID|S_ISGID))==0)
481*35161Smarc goto openok;
482*35161Smarc }
483*35161Smarc close(n);
484*35161Smarc }
485*35161Smarc if((euserid=geteuid()) != userid)
486*35161Smarc {
487*35161Smarc strcpy(name+9,itos(getpid()));
488*35161Smarc /* create a suid open file with owner equal effective uid */
489*35161Smarc if((n=creat(name,04100)) < 0)
490*35161Smarc goto fail;
491*35161Smarc unlink(name);
492*35161Smarc /* make sure that file has right owner */
493*35161Smarc if(fstat(n,&statb)<0 || statb.st_uid != euserid)
494*35161Smarc goto fail;
495*35161Smarc if(n!=10)
496*35161Smarc {
497*35161Smarc close(10);
498*35161Smarc fcntl(n,0,10);
499*35161Smarc close(n);
500*35161Smarc }
501*35161Smarc }
502*35161Smarc *--t = p;
503*35161Smarc execve(suid_exec,t,xecenv);
504*35161Smarc fail:
505*35161Smarc failed(p, badopen);
506*35161Smarc openok:
507*35161Smarc close(n);
508*35161Smarc #endif SUID_EXEC
509*35161Smarc /* get name returns the interpreter name */
510*35161Smarc if(get_shell(p, iname)<0)
511*35161Smarc failed(p, badexec);
512*35161Smarc t--;
513*35161Smarc t[0] = iname;
514*35161Smarc execve(iname, t, xecenv);
515*35161Smarc if(access(iname,0)==0)
516*35161Smarc xecmsg=badexec;
517*35161Smarc failed(iname, xecmsg);
518*35161Smarc }
519*35161Smarc #else
520*35161Smarc exscript(p,t);
521*35161Smarc #endif /* VFORK */
522*35161Smarc
523*35161Smarc case ENOMEM:
524*35161Smarc failed(p,toobig);
525*35161Smarc
526*35161Smarc case E2BIG:
527*35161Smarc failed(p,arglist);
528*35161Smarc
529*35161Smarc case ETXTBSY:
530*35161Smarc failed(p,txtbsy);
531*35161Smarc
532*35161Smarc default:
533*35161Smarc if(access(p,0)==0)
534*35161Smarc xecmsg=badexec;
535*35161Smarc case ENOENT:
536*35161Smarc return(prefix);
537*35161Smarc }
538*35161Smarc }
539*35161Smarc
540*35161Smarc /*
541*35161Smarc * File is executable but not machine code.
542*35161Smarc * Assume file is a Shell script and execute it.
543*35161Smarc */
544*35161Smarc
545*35161Smarc
exscript(p,t)546*35161Smarc static void exscript(p,t)
547*35161Smarc register char *p;
548*35161Smarc register char *t[];
549*35161Smarc {
550*35161Smarc char *savet;
551*35161Smarc flags=0;
552*35161Smarc states = 0;
553*35161Smarc comdiv=0;
554*35161Smarc ioset=0;
555*35161Smarc arg_clear(); /* remove open files and for loop junk */
556*35161Smarc postclr();
557*35161Smarc if(fileno(input))
558*35161Smarc fclose(input);
559*35161Smarc p_flush();
560*35161Smarc standout= stdout;
561*35161Smarc setbuf(stdin,(char*)_sibuf);
562*35161Smarc #ifdef SUID_EXEC
563*35161Smarc /* check if file cannot open for read or script is setuid/setgid */
564*35161Smarc {
565*35161Smarc static char name[] = "/tmp/euidXXXXXX";
566*35161Smarc register int n;
567*35161Smarc register int euserid;
568*35161Smarc struct stat statb;
569*35161Smarc if((n=open(p,0)) >= 0)
570*35161Smarc {
571*35161Smarc if(fstat(n,&statb)==0)
572*35161Smarc {
573*35161Smarc if((statb.st_mode&(S_ISUID|S_ISGID))==0)
574*35161Smarc goto openok;
575*35161Smarc }
576*35161Smarc close(n);
577*35161Smarc }
578*35161Smarc if((euserid=geteuid()) != userid)
579*35161Smarc {
580*35161Smarc strcpy(name+9,itos(getpid()));
581*35161Smarc /* create a suid open file with owner equal effective uid */
582*35161Smarc if((n=creat(name,04100)) < 0)
583*35161Smarc goto fail;
584*35161Smarc unlink(name);
585*35161Smarc /* make sure that file has right owner */
586*35161Smarc if(fstat(n,&statb)<0 || statb.st_uid != euserid)
587*35161Smarc goto fail;
588*35161Smarc if(n!=10)
589*35161Smarc {
590*35161Smarc close(10);
591*35161Smarc fcntl(n,0,10);
592*35161Smarc close(n);
593*35161Smarc }
594*35161Smarc }
595*35161Smarc savet = *--t;
596*35161Smarc *t = p;
597*35161Smarc execve(suid_exec,t,xecenv);
598*35161Smarc fail:
599*35161Smarc /*
600*35161Smarc * The following code is just for compatibility
601*35161Smarc * It should be replaced with the line failed(p,badexec);
602*35161Smarc */
603*35161Smarc n = open(p,0);
604*35161Smarc if(n < 0)
605*35161Smarc failed(p, badopen);
606*35161Smarc *t++ = savet;
607*35161Smarc close(10);
608*35161Smarc
609*35161Smarc openok:
610*35161Smarc input = fdopen(n,"r");
611*35161Smarc }
612*35161Smarc #else
613*35161Smarc input = chkopen(p);
614*35161Smarc #endif /* SUID_EXEC */
615*35161Smarc #ifdef ACCT
616*35161Smarc preacct(p) ; /* reset accounting */
617*35161Smarc #endif /* ACCT */
618*35161Smarc gscan_some(rmlocal,namep,N_EXPORT,0); /* remove local variables*/
619*35161Smarc gscan_some(rmlocal,alias,N_EXPORT,0); /* remove local aliases*/
620*35161Smarc gscan_some(rmlocal,prnames,N_EXPORT,0); /* remove local functions*/
621*35161Smarc if(attest(IFSNOD,N_EXPORT)==0)
622*35161Smarc assign(IFSNOD,sptbnl);
623*35161Smarc /* set up new args */
624*35161Smarc arg_set(t);
625*35161Smarc longjmp(subshell,1);
626*35161Smarc }
627*35161Smarc
628*35161Smarc /*
629*35161Smarc * The following routine is used to execute shell functions and command subs
630*35161Smarc * when com!=NULL $* is saved and restored
631*35161Smarc */
632*35161Smarc
exfunct(t,com,execflg,envlist)633*35161Smarc void exfunct(t,com,execflg,envlist)
634*35161Smarc TREPTR t;
635*35161Smarc register char *com[];
636*35161Smarc register unsigned execflg;
637*35161Smarc ARGPTR envlist;
638*35161Smarc {
639*35161Smarc /* execute user defined function */
640*35161Smarc register char *trap;
641*35161Smarc jmp_buf retbuf;
642*35161Smarc jmp_buf *savreturn = freturn;
643*35161Smarc DOLPTR argsav=0;
644*35161Smarc int mode;
645*35161Smarc DOLPTR savargfor;
646*35161Smarc char *savtrap0 = trapcom[0];
647*35161Smarc char *savtrap1 = trapcom[MAXTRAP];
648*35161Smarc SHFILE savstandin;
649*35161Smarc struct State savst;
650*35161Smarc savst = st;
651*35161Smarc loopcnt = 0;
652*35161Smarc if(com)
653*35161Smarc {
654*35161Smarc mem_scope(envlist);
655*35161Smarc if(execflg&EXECPR)
656*35161Smarc on_option(EXECPR);
657*35161Smarc else
658*35161Smarc off_option(EXECPR);
659*35161Smarc execflg &= ~EXECPR;
660*35161Smarc cmdadr = com[0];
661*35161Smarc trapcom[MAXTRAP] = 0;
662*35161Smarc argsav = arg_new(com,&savargfor);
663*35161Smarc }
664*35161Smarc freturn = (jmp_buf*)retbuf;
665*35161Smarc if((mode=setjmp(retbuf)) == 0)
666*35161Smarc {
667*35161Smarc states |= FUNCTION;
668*35161Smarc if(fn_depth++ > MAXDEPTH)
669*35161Smarc longjmp(*freturn,2);
670*35161Smarc else
671*35161Smarc execute(t,execflg);
672*35161Smarc }
673*35161Smarc fn_depth--;
674*35161Smarc freturn = savreturn;
675*35161Smarc if(com)
676*35161Smarc {
677*35161Smarc mem_unscope();
678*35161Smarc arg_reset(argsav,savargfor);
679*35161Smarc trapcom[MAXTRAP] = savtrap1;
680*35161Smarc trapnote = 0;
681*35161Smarc }
682*35161Smarc savstandin = standin;
683*35161Smarc st = savst;
684*35161Smarc while((savstandin != standin) && pop(0));
685*35161Smarc if(mode == 2)
686*35161Smarc {
687*35161Smarc if(fn_depth==0)
688*35161Smarc failed(com[0],recursive);
689*35161Smarc else
690*35161Smarc longjmp(*freturn,2);
691*35161Smarc }
692*35161Smarc if(com && (trap=trapcom[0]) && (savtrap0!=trap))
693*35161Smarc {
694*35161Smarc trapcom[0] = savtrap0;
695*35161Smarc execexp(trap,(FILE*)0);
696*35161Smarc free(trap);
697*35161Smarc }
698*35161Smarc }
699*35161Smarc
700*35161Smarc #ifndef JOBS
701*35161Smarc /*
702*35161Smarc * These routines have been moved to jobs.c when compiling with JOBS option
703*35161Smarc */
704*35161Smarc
705*35161Smarc /*
706*35161Smarc * Initialize the process posting array
707*35161Smarc */
postclr()708*35161Smarc void postclr()
709*35161Smarc {
710*35161Smarc register struct process *pw = pwlist;
711*35161Smarc while(pw < &pwlist[maxpost])
712*35161Smarc (pw++)->p_pid = 0;
713*35161Smarc numpost=0;
714*35161Smarc maxpost=0;
715*35161Smarc }
716*35161Smarc
post(pcsid)717*35161Smarc int post(pcsid)
718*35161Smarc int pcsid;
719*35161Smarc {
720*35161Smarc register struct process *pw = pwlist;
721*35161Smarc if(pcsid)
722*35161Smarc {
723*35161Smarc while(pw->p_pid)
724*35161Smarc pw++;
725*35161Smarc if(numpost >= MAXP-1)
726*35161Smarc pw--;
727*35161Smarc else
728*35161Smarc numpost++;
729*35161Smarc if(numpost > maxpost)
730*35161Smarc maxpost = numpost;
731*35161Smarc pw->p_pid = pcsid;
732*35161Smarc if(numpost >= MAXP-1)
733*35161Smarc await(0,0);
734*35161Smarc return(pw-pwlist);
735*35161Smarc }
736*35161Smarc return(-1);
737*35161Smarc }
738*35161Smarc
await(i,bckg)739*35161Smarc void await(i, bckg)
740*35161Smarc int i, bckg;
741*35161Smarc {
742*35161Smarc int rc=0, wx=0;
743*35161Smarc int w;
744*35161Smarc post(i);
745*35161Smarc while(numpost)
746*35161Smarc {
747*35161Smarc register int p;
748*35161Smarc register int sig;
749*35161Smarc int w_hi;
750*35161Smarc int found = 0;
751*35161Smarc {
752*35161Smarc register struct process *pw=pwlist;
753*35161Smarc errno = 0;
754*35161Smarc p=wait(&w);
755*35161Smarc if((p== -1) && bckg && errno==EINTR)
756*35161Smarc break;
757*35161Smarc while(pw <= &pwlist[maxpost])
758*35161Smarc {
759*35161Smarc if(pw->p_pid==p)
760*35161Smarc {
761*35161Smarc if(p==cpid)
762*35161Smarc {
763*35161Smarc cpid = 0;
764*35161Smarc cpipe[1] = NULL;
765*35161Smarc }
766*35161Smarc pw->p_pid=0;
767*35161Smarc numpost--;
768*35161Smarc found++;
769*35161Smarc }
770*35161Smarc else
771*35161Smarc pw++;
772*35161Smarc }
773*35161Smarc }
774*35161Smarc if(p == -1)
775*35161Smarc {
776*35161Smarc if(bckg)
777*35161Smarc {
778*35161Smarc register struct process *pw =pwlist;
779*35161Smarc while(pw <= &pwlist[maxpost] && i != pw->p_pid)
780*35161Smarc pw++;
781*35161Smarc if(i == pw->p_pid)
782*35161Smarc {
783*35161Smarc pw->p_pid = 0;
784*35161Smarc numpost--;
785*35161Smarc }
786*35161Smarc }
787*35161Smarc continue;
788*35161Smarc }
789*35161Smarc w_hi = (w>>8)&LOBYTE;
790*35161Smarc if(sig = w&0177)
791*35161Smarc {
792*35161Smarc p_setout(stderr);
793*35161Smarc if(sig == 0177 /* ptrace! return */)
794*35161Smarc {
795*35161Smarc fputs(ptrace,output);
796*35161Smarc sig = w_hi;
797*35161Smarc }
798*35161Smarc #ifdef apollo
799*35161Smarc if(*sysmsg[sig])
800*35161Smarc #else
801*35161Smarc if(sysmsg[sig])
802*35161Smarc #endif /* apollo */
803*35161Smarc {
804*35161Smarc if(i!=p || (states&PROMPT)==0)
805*35161Smarc {
806*35161Smarc p_prp(itos(p),SP);
807*35161Smarc }
808*35161Smarc fputs(sysmsg[sig],output);
809*35161Smarc if(w&HIGHBIT)
810*35161Smarc fputs(coredump,output);
811*35161Smarc }
812*35161Smarc newline();
813*35161Smarc }
814*35161Smarc wx |= w;
815*35161Smarc if(p == i)
816*35161Smarc {
817*35161Smarc rc = (sig ? sig|SIGFLG : w_hi);
818*35161Smarc break;
819*35161Smarc }
820*35161Smarc }
821*35161Smarc exitval=rc;
822*35161Smarc exitset();
823*35161Smarc }
824*35161Smarc #endif /* JOBS */
825*35161Smarc
826*35161Smarc #ifdef ACCT
827*35161Smarc #include <acctdef.h>
828*35161Smarc #include <sys/acct.h>
829*35161Smarc #include <sys/times.h>
830*35161Smarc
831*35161Smarc static int compress();
832*35161Smarc
833*35161Smarc struct acct sabuf;
834*35161Smarc struct tms buffer;
835*35161Smarc extern long times();
836*35161Smarc static long before;
837*35161Smarc static char *SHACCT; /* 0 environment variable SHACCT not set so never acct
838*35161Smarc ptr to SHACCT value if set, so acct if shell procedure*/
839*35161Smarc static shaccton; /* 0 implies do not write record on exit
840*35161Smarc 1 implies write acct record on exit
841*35161Smarc */
842*35161Smarc /*
843*35161Smarc * initialize accounting, i.e., see if SHACCT variable set
844*35161Smarc */
initacct()845*35161Smarc void initacct()
846*35161Smarc {
847*35161Smarc
848*35161Smarc SHACCT = valup(ACCTNOD);
849*35161Smarc }
850*35161Smarc /*
851*35161Smarc * suspend accounting unitl turned on by preacct()
852*35161Smarc */
suspacct()853*35161Smarc void suspacct()
854*35161Smarc {
855*35161Smarc shaccton=0;
856*35161Smarc }
857*35161Smarc
preacct(cmdname)858*35161Smarc int preacct(cmdname)
859*35161Smarc char *cmdname;
860*35161Smarc {
861*35161Smarc char * strncpy();
862*35161Smarc if(SHACCT)
863*35161Smarc {
864*35161Smarc sabuf.ac_btime = time((long *)0);
865*35161Smarc before = times(&buffer);
866*35161Smarc sabuf.ac_uid = getuid();
867*35161Smarc sabuf.ac_gid = getgid();
868*35161Smarc strncpy(sabuf.ac_comm, (char*)simple(cmdname),
869*35161Smarc sizeof(sabuf.ac_comm));
870*35161Smarc shaccton = 1;
871*35161Smarc }
872*35161Smarc }
873*35161Smarc #include <fcntl.h>
doacct()874*35161Smarc void doacct()
875*35161Smarc {
876*35161Smarc int fd;
877*35161Smarc long after;
878*35161Smarc
879*35161Smarc if(shaccton)
880*35161Smarc {
881*35161Smarc after = times(&buffer);
882*35161Smarc sabuf.ac_utime = compress(buffer.tms_utime + buffer.tms_cutime);
883*35161Smarc sabuf.ac_stime = compress(buffer.tms_stime + buffer.tms_cstime);
884*35161Smarc sabuf.ac_etime = compress( after - before);
885*35161Smarc fd = open( SHACCT , O_WRONLY | O_APPEND | O_CREAT,0666);
886*35161Smarc write(fd, &sabuf, sizeof( sabuf ));
887*35161Smarc close( fd);
888*35161Smarc }
889*35161Smarc }
890*35161Smarc
891*35161Smarc /*
892*35161Smarc * Produce a pseudo-floating point representation
893*35161Smarc * with 3 bits base-8 exponent, 13 bits fraction.
894*35161Smarc */
compress(t)895*35161Smarc static int compress(t)
896*35161Smarc register time_t t;
897*35161Smarc {
898*35161Smarc register int exp = 0, rund = 0;
899*35161Smarc
900*35161Smarc while (t >= 8192)
901*35161Smarc {
902*35161Smarc exp++;
903*35161Smarc rund = t&04;
904*35161Smarc t >>= 3;
905*35161Smarc }
906*35161Smarc if (rund)
907*35161Smarc {
908*35161Smarc t++;
909*35161Smarc if (t >= 8192)
910*35161Smarc {
911*35161Smarc t >>= 3;
912*35161Smarc exp++;
913*35161Smarc }
914*35161Smarc }
915*35161Smarc return((exp<<13) + t);
916*35161Smarc }
917*35161Smarc #endif /* ACCT */
918*35161Smarc
919