xref: /csrg-svn/local/toolchest/ksh/sh/service.c (revision 35161)
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