xref: /titanic_50/usr/src/cmd/csh/sh.exec.c (revision 7c478bd95313f5f23a4c958a745db2134aa03244)
1*7c478bd9Sstevel@tonic-gate /*
2*7c478bd9Sstevel@tonic-gate  * Copyright 2004 Sun Microsystems, Inc.  All rights reserved.
3*7c478bd9Sstevel@tonic-gate  * Use is subject to license terms.
4*7c478bd9Sstevel@tonic-gate  */
5*7c478bd9Sstevel@tonic-gate 
6*7c478bd9Sstevel@tonic-gate /*	Copyright (c) 1983, 1984, 1985, 1986, 1987, 1988, 1989 AT&T	*/
7*7c478bd9Sstevel@tonic-gate /*	  All Rights Reserved  	*/
8*7c478bd9Sstevel@tonic-gate 
9*7c478bd9Sstevel@tonic-gate /*
10*7c478bd9Sstevel@tonic-gate  * Copyright (c) 1980 Regents of the University of California.
11*7c478bd9Sstevel@tonic-gate  * All rights reserved.  The Berkeley Software License Agreement
12*7c478bd9Sstevel@tonic-gate  * specifies the terms and conditions for redistribution.
13*7c478bd9Sstevel@tonic-gate  */
14*7c478bd9Sstevel@tonic-gate 
15*7c478bd9Sstevel@tonic-gate #pragma ident	"%Z%%M%	%I%	%E% SMI"
16*7c478bd9Sstevel@tonic-gate 
17*7c478bd9Sstevel@tonic-gate #include "sh.h"
18*7c478bd9Sstevel@tonic-gate #include <dirent.h>
19*7c478bd9Sstevel@tonic-gate #include <string.h>
20*7c478bd9Sstevel@tonic-gate #include "sh.tconst.h"
21*7c478bd9Sstevel@tonic-gate #include "sh_policy.h"
22*7c478bd9Sstevel@tonic-gate 
23*7c478bd9Sstevel@tonic-gate 
24*7c478bd9Sstevel@tonic-gate /*
25*7c478bd9Sstevel@tonic-gate  * C shell
26*7c478bd9Sstevel@tonic-gate  */
27*7c478bd9Sstevel@tonic-gate 
28*7c478bd9Sstevel@tonic-gate /*
29*7c478bd9Sstevel@tonic-gate  * System level search and execute of a command.
30*7c478bd9Sstevel@tonic-gate  * We look in each directory for the specified command name.
31*7c478bd9Sstevel@tonic-gate  * If the name contains a '/' then we execute only the full path name.
32*7c478bd9Sstevel@tonic-gate  * If there is no search path then we execute only full path names.
33*7c478bd9Sstevel@tonic-gate  */
34*7c478bd9Sstevel@tonic-gate 
35*7c478bd9Sstevel@tonic-gate /*
36*7c478bd9Sstevel@tonic-gate  * As we search for the command we note the first non-trivial error
37*7c478bd9Sstevel@tonic-gate  * message for presentation to the user.  This allows us often
38*7c478bd9Sstevel@tonic-gate  * to show that a file has the wrong mode/no access when the file
39*7c478bd9Sstevel@tonic-gate  * is not in the last component of the search path, so we must
40*7c478bd9Sstevel@tonic-gate  * go on after first detecting the error.
41*7c478bd9Sstevel@tonic-gate  */
42*7c478bd9Sstevel@tonic-gate char *exerr;			/* Execution error message */
43*7c478bd9Sstevel@tonic-gate 
44*7c478bd9Sstevel@tonic-gate 
45*7c478bd9Sstevel@tonic-gate extern DIR *opendir_();
46*7c478bd9Sstevel@tonic-gate 
47*7c478bd9Sstevel@tonic-gate 
48*7c478bd9Sstevel@tonic-gate doexec(t)
49*7c478bd9Sstevel@tonic-gate 	register struct command *t;
50*7c478bd9Sstevel@tonic-gate {
51*7c478bd9Sstevel@tonic-gate 	tchar *sav;
52*7c478bd9Sstevel@tonic-gate 	register tchar *dp, **pv, **av;
53*7c478bd9Sstevel@tonic-gate 	register struct varent *v;
54*7c478bd9Sstevel@tonic-gate 	bool slash;
55*7c478bd9Sstevel@tonic-gate 	int hashval, hashval1, i;
56*7c478bd9Sstevel@tonic-gate 	tchar *blk[2];
57*7c478bd9Sstevel@tonic-gate #ifdef TRACE
58*7c478bd9Sstevel@tonic-gate 	tprintf("TRACE- doexec()\n");
59*7c478bd9Sstevel@tonic-gate #endif
60*7c478bd9Sstevel@tonic-gate 
61*7c478bd9Sstevel@tonic-gate 	/*
62*7c478bd9Sstevel@tonic-gate 	 * Glob the command name.  If this does anything, then we
63*7c478bd9Sstevel@tonic-gate 	 * will execute the command only relative to ".".  One special
64*7c478bd9Sstevel@tonic-gate 	 * case: if there is no PATH, then we execute only commands
65*7c478bd9Sstevel@tonic-gate 	 * which start with '/'.
66*7c478bd9Sstevel@tonic-gate 	 */
67*7c478bd9Sstevel@tonic-gate 	dp = globone(t->t_dcom[0]);
68*7c478bd9Sstevel@tonic-gate 	sav = t->t_dcom[0];
69*7c478bd9Sstevel@tonic-gate 	exerr = 0; t->t_dcom[0] = dp;
70*7c478bd9Sstevel@tonic-gate 	setname(dp);
71*7c478bd9Sstevel@tonic-gate 	xfree(sav);
72*7c478bd9Sstevel@tonic-gate 	v = adrof(S_path /*"path"*/);
73*7c478bd9Sstevel@tonic-gate 	if (v == 0 && dp[0] != '/') {
74*7c478bd9Sstevel@tonic-gate 		pexerr();
75*7c478bd9Sstevel@tonic-gate 	}
76*7c478bd9Sstevel@tonic-gate 	slash = gflag;
77*7c478bd9Sstevel@tonic-gate 
78*7c478bd9Sstevel@tonic-gate 	/*
79*7c478bd9Sstevel@tonic-gate 	 * Glob the argument list, if necessary.
80*7c478bd9Sstevel@tonic-gate 	 * Otherwise trim off the quote bits.
81*7c478bd9Sstevel@tonic-gate 	 */
82*7c478bd9Sstevel@tonic-gate 	gflag = 0; av = &t->t_dcom[1];
83*7c478bd9Sstevel@tonic-gate 	tglob(av);
84*7c478bd9Sstevel@tonic-gate 	if (gflag) {
85*7c478bd9Sstevel@tonic-gate 		av = glob(av);
86*7c478bd9Sstevel@tonic-gate 		if (av == 0)
87*7c478bd9Sstevel@tonic-gate 			error("No match");
88*7c478bd9Sstevel@tonic-gate 	}
89*7c478bd9Sstevel@tonic-gate 	blk[0] = t->t_dcom[0];
90*7c478bd9Sstevel@tonic-gate 	blk[1] = 0;
91*7c478bd9Sstevel@tonic-gate 	av = blkspl(blk, av);
92*7c478bd9Sstevel@tonic-gate #ifdef VFORK
93*7c478bd9Sstevel@tonic-gate 	Vav = av;
94*7c478bd9Sstevel@tonic-gate #endif
95*7c478bd9Sstevel@tonic-gate 	trim(av);
96*7c478bd9Sstevel@tonic-gate 	slash |= any('/', av[0]);
97*7c478bd9Sstevel@tonic-gate 
98*7c478bd9Sstevel@tonic-gate 	xechoit(av);		/* Echo command if -x */
99*7c478bd9Sstevel@tonic-gate 	/*
100*7c478bd9Sstevel@tonic-gate 	 * Since all internal file descriptors are set to close on exec,
101*7c478bd9Sstevel@tonic-gate 	 * we don't need to close them explicitly here.  Just reorient
102*7c478bd9Sstevel@tonic-gate 	 * ourselves for error messages.
103*7c478bd9Sstevel@tonic-gate 	 */
104*7c478bd9Sstevel@tonic-gate 	SHIN = 0; SHOUT = 1; SHDIAG = 2; OLDSTD = 0;
105*7c478bd9Sstevel@tonic-gate 
106*7c478bd9Sstevel@tonic-gate 	/*
107*7c478bd9Sstevel@tonic-gate 	 * We must do this AFTER any possible forking (like `foo`
108*7c478bd9Sstevel@tonic-gate 	 * in glob) so that this shell can still do subprocesses.
109*7c478bd9Sstevel@tonic-gate 	 */
110*7c478bd9Sstevel@tonic-gate 	(void) sigsetmask(0);
111*7c478bd9Sstevel@tonic-gate 
112*7c478bd9Sstevel@tonic-gate 	/*
113*7c478bd9Sstevel@tonic-gate 	 * If no path, no words in path, or a / in the filename
114*7c478bd9Sstevel@tonic-gate 	 * then restrict the command search.
115*7c478bd9Sstevel@tonic-gate 	 */
116*7c478bd9Sstevel@tonic-gate 	if (v == 0 || v->vec[0] == 0 || slash)
117*7c478bd9Sstevel@tonic-gate 		pv = justabs;
118*7c478bd9Sstevel@tonic-gate 	else
119*7c478bd9Sstevel@tonic-gate 		pv = v->vec;
120*7c478bd9Sstevel@tonic-gate 	sav = strspl(S_SLASH /* "/" */, *av);		/* / command name for postpending */
121*7c478bd9Sstevel@tonic-gate #ifdef VFORK
122*7c478bd9Sstevel@tonic-gate 	Vsav = sav;
123*7c478bd9Sstevel@tonic-gate #endif
124*7c478bd9Sstevel@tonic-gate 	if (havhash)
125*7c478bd9Sstevel@tonic-gate 		hashval = hashname(*av);
126*7c478bd9Sstevel@tonic-gate 	i = 0;
127*7c478bd9Sstevel@tonic-gate #ifdef VFORK
128*7c478bd9Sstevel@tonic-gate 	hits++;
129*7c478bd9Sstevel@tonic-gate #endif
130*7c478bd9Sstevel@tonic-gate 	do {
131*7c478bd9Sstevel@tonic-gate 		if (!slash && pv[0][0] == '/' && havhash) {
132*7c478bd9Sstevel@tonic-gate 			hashval1 = hash(hashval, i);
133*7c478bd9Sstevel@tonic-gate 			if (!bit(xhash, hashval1))
134*7c478bd9Sstevel@tonic-gate 				goto cont;
135*7c478bd9Sstevel@tonic-gate 		}
136*7c478bd9Sstevel@tonic-gate 
137*7c478bd9Sstevel@tonic-gate 		if (pv[0][0] == 0 || eq(pv[0], S_DOT/*"."*/)) {	/* don't make ./xxx */
138*7c478bd9Sstevel@tonic-gate 			texec(t, *av, av);
139*7c478bd9Sstevel@tonic-gate 		} else {
140*7c478bd9Sstevel@tonic-gate 			dp = strspl(*pv, sav);
141*7c478bd9Sstevel@tonic-gate #ifdef VFORK
142*7c478bd9Sstevel@tonic-gate 			Vdp = dp;
143*7c478bd9Sstevel@tonic-gate #endif
144*7c478bd9Sstevel@tonic-gate 			texec(t, dp, av);
145*7c478bd9Sstevel@tonic-gate #ifdef VFORK
146*7c478bd9Sstevel@tonic-gate 			Vdp = 0;
147*7c478bd9Sstevel@tonic-gate #endif
148*7c478bd9Sstevel@tonic-gate 			xfree(dp);
149*7c478bd9Sstevel@tonic-gate 		}
150*7c478bd9Sstevel@tonic-gate #ifdef VFORK
151*7c478bd9Sstevel@tonic-gate 		misses++;
152*7c478bd9Sstevel@tonic-gate #endif
153*7c478bd9Sstevel@tonic-gate cont:
154*7c478bd9Sstevel@tonic-gate 		pv++;
155*7c478bd9Sstevel@tonic-gate 		i++;
156*7c478bd9Sstevel@tonic-gate 	} while (*pv);
157*7c478bd9Sstevel@tonic-gate #ifdef VFORK
158*7c478bd9Sstevel@tonic-gate 	hits--;
159*7c478bd9Sstevel@tonic-gate #endif
160*7c478bd9Sstevel@tonic-gate #ifdef VFORK
161*7c478bd9Sstevel@tonic-gate 	Vsav = 0;
162*7c478bd9Sstevel@tonic-gate 	Vav = 0;
163*7c478bd9Sstevel@tonic-gate #endif
164*7c478bd9Sstevel@tonic-gate 	xfree(sav);
165*7c478bd9Sstevel@tonic-gate 	xfree( (char *)av);
166*7c478bd9Sstevel@tonic-gate 	pexerr();
167*7c478bd9Sstevel@tonic-gate }
168*7c478bd9Sstevel@tonic-gate 
169*7c478bd9Sstevel@tonic-gate pexerr()
170*7c478bd9Sstevel@tonic-gate {
171*7c478bd9Sstevel@tonic-gate 
172*7c478bd9Sstevel@tonic-gate #ifdef TRACE
173*7c478bd9Sstevel@tonic-gate 	tprintf("TRACE- pexerr()\n");
174*7c478bd9Sstevel@tonic-gate #endif
175*7c478bd9Sstevel@tonic-gate 	/* Couldn't find the damn thing */
176*7c478bd9Sstevel@tonic-gate 	if (exerr)
177*7c478bd9Sstevel@tonic-gate 		bferr(exerr);
178*7c478bd9Sstevel@tonic-gate 	bferr("Command not found");
179*7c478bd9Sstevel@tonic-gate }
180*7c478bd9Sstevel@tonic-gate 
181*7c478bd9Sstevel@tonic-gate /*
182*7c478bd9Sstevel@tonic-gate  * Execute command f, arg list t.
183*7c478bd9Sstevel@tonic-gate  * Record error message if not found.
184*7c478bd9Sstevel@tonic-gate  * Also do shell scripts here.
185*7c478bd9Sstevel@tonic-gate  */
186*7c478bd9Sstevel@tonic-gate texec(cmd, f, t)
187*7c478bd9Sstevel@tonic-gate 	register struct command *cmd;
188*7c478bd9Sstevel@tonic-gate 	tchar *f;
189*7c478bd9Sstevel@tonic-gate 	register tchar **t;
190*7c478bd9Sstevel@tonic-gate {
191*7c478bd9Sstevel@tonic-gate 	register int	pfstatus = 0;
192*7c478bd9Sstevel@tonic-gate 	register struct	varent *v;
193*7c478bd9Sstevel@tonic-gate 	register tchar	**vp;
194*7c478bd9Sstevel@tonic-gate 	tchar		*lastsh[2];
195*7c478bd9Sstevel@tonic-gate 
196*7c478bd9Sstevel@tonic-gate #ifdef TRACE
197*7c478bd9Sstevel@tonic-gate 	tprintf("TRACE- texec()\n");
198*7c478bd9Sstevel@tonic-gate #endif
199*7c478bd9Sstevel@tonic-gate 	/* convert cfname and cargs from tchar to char */
200*7c478bd9Sstevel@tonic-gate 	tconvert(cmd, f, t);
201*7c478bd9Sstevel@tonic-gate 
202*7c478bd9Sstevel@tonic-gate 	if (pfcshflag == 1) {
203*7c478bd9Sstevel@tonic-gate 		pfstatus = secpolicy_pfexec((const char *)(cmd->cfname),
204*7c478bd9Sstevel@tonic-gate 		    cmd->cargs, (const char **)NULL);
205*7c478bd9Sstevel@tonic-gate 		if (pfstatus != NOATTRS) {
206*7c478bd9Sstevel@tonic-gate 			errno = pfstatus;
207*7c478bd9Sstevel@tonic-gate 		}
208*7c478bd9Sstevel@tonic-gate 	}
209*7c478bd9Sstevel@tonic-gate 	if ((pfcshflag == 0) || (pfstatus == NOATTRS)) {
210*7c478bd9Sstevel@tonic-gate 		execv(cmd->cfname, cmd->cargs);
211*7c478bd9Sstevel@tonic-gate 	}
212*7c478bd9Sstevel@tonic-gate 
213*7c478bd9Sstevel@tonic-gate 	/*
214*7c478bd9Sstevel@tonic-gate 	 * exec returned, free up allocations from above
215*7c478bd9Sstevel@tonic-gate 	 * tconvert(), zero cfname and cargs to prevent
216*7c478bd9Sstevel@tonic-gate 	 * duplicate free() in freesyn()
217*7c478bd9Sstevel@tonic-gate 	 */
218*7c478bd9Sstevel@tonic-gate 	xfree(cmd->cfname);
219*7c478bd9Sstevel@tonic-gate 	chr_blkfree(cmd->cargs);
220*7c478bd9Sstevel@tonic-gate 	cmd->cfname = (char *) 0;
221*7c478bd9Sstevel@tonic-gate 	cmd->cargs = (char **) 0;
222*7c478bd9Sstevel@tonic-gate 
223*7c478bd9Sstevel@tonic-gate 	switch (errno) {
224*7c478bd9Sstevel@tonic-gate 	case ENOEXEC:
225*7c478bd9Sstevel@tonic-gate 		/* check that this is not a binary file */
226*7c478bd9Sstevel@tonic-gate 		{
227*7c478bd9Sstevel@tonic-gate 			register int ff = open_(f, 0);
228*7c478bd9Sstevel@tonic-gate 			tchar ch;
229*7c478bd9Sstevel@tonic-gate 
230*7c478bd9Sstevel@tonic-gate 			if (ff != -1 && read_(ff, &ch, 1) == 1 && !isprint(ch)
231*7c478bd9Sstevel@tonic-gate 			       && !isspace(ch)) {
232*7c478bd9Sstevel@tonic-gate 				printf("Cannot execute binary file.\n");
233*7c478bd9Sstevel@tonic-gate 				Perror(f);
234*7c478bd9Sstevel@tonic-gate 				(void) close(ff);
235*7c478bd9Sstevel@tonic-gate 				unsetfd(ff);
236*7c478bd9Sstevel@tonic-gate 				return;
237*7c478bd9Sstevel@tonic-gate 			}
238*7c478bd9Sstevel@tonic-gate 			(void) close(ff);
239*7c478bd9Sstevel@tonic-gate 			unsetfd(ff);
240*7c478bd9Sstevel@tonic-gate 		}
241*7c478bd9Sstevel@tonic-gate 		/*
242*7c478bd9Sstevel@tonic-gate 		 * If there is an alias for shell, then
243*7c478bd9Sstevel@tonic-gate 		 * put the words of the alias in front of the
244*7c478bd9Sstevel@tonic-gate 		 * argument list replacing the command name.
245*7c478bd9Sstevel@tonic-gate 		 * Note no interpretation of the words at this point.
246*7c478bd9Sstevel@tonic-gate 		 */
247*7c478bd9Sstevel@tonic-gate 		v = adrof1(S_shell /*"shell"*/, &aliases);
248*7c478bd9Sstevel@tonic-gate 		if (v == 0) {
249*7c478bd9Sstevel@tonic-gate #ifdef OTHERSH
250*7c478bd9Sstevel@tonic-gate 			register int ff = open_(f, 0);
251*7c478bd9Sstevel@tonic-gate 			tchar ch;
252*7c478bd9Sstevel@tonic-gate #endif
253*7c478bd9Sstevel@tonic-gate 
254*7c478bd9Sstevel@tonic-gate 			vp = lastsh;
255*7c478bd9Sstevel@tonic-gate 			vp[0] = adrof(S_shell /*"shell"*/) ? value(S_shell /*"shell"*/) : S_SHELLPATH/*SHELLPATH*/;
256*7c478bd9Sstevel@tonic-gate 			vp[1] =  (tchar *) NULL;
257*7c478bd9Sstevel@tonic-gate #ifdef OTHERSH
258*7c478bd9Sstevel@tonic-gate 			if (ff != -1 && read_(ff, &ch, 1) == 1 && ch != '#')
259*7c478bd9Sstevel@tonic-gate 				vp[0] = S_OTHERSH/*OTHERSH*/;
260*7c478bd9Sstevel@tonic-gate 			(void) close(ff);
261*7c478bd9Sstevel@tonic-gate 			unsetfd(ff);
262*7c478bd9Sstevel@tonic-gate #endif
263*7c478bd9Sstevel@tonic-gate 		} else
264*7c478bd9Sstevel@tonic-gate 			vp = v->vec;
265*7c478bd9Sstevel@tonic-gate 		t[0] = f;
266*7c478bd9Sstevel@tonic-gate 		t = blkspl(vp, t);		/* Splice up the new arglst */
267*7c478bd9Sstevel@tonic-gate 		f = *t;
268*7c478bd9Sstevel@tonic-gate 
269*7c478bd9Sstevel@tonic-gate 		tconvert(cmd, f, t);		/* convert tchar to char */
270*7c478bd9Sstevel@tonic-gate 
271*7c478bd9Sstevel@tonic-gate 		/*
272*7c478bd9Sstevel@tonic-gate 		 * now done with tchar arg list t,
273*7c478bd9Sstevel@tonic-gate 		 * free the space calloc'd by above blkspl()
274*7c478bd9Sstevel@tonic-gate 		 */
275*7c478bd9Sstevel@tonic-gate 		xfree((char *) t);
276*7c478bd9Sstevel@tonic-gate 
277*7c478bd9Sstevel@tonic-gate 		execv(cmd->cfname, cmd->cargs);	/* exec the command */
278*7c478bd9Sstevel@tonic-gate 
279*7c478bd9Sstevel@tonic-gate 		/* exec returned, same free'ing as above */
280*7c478bd9Sstevel@tonic-gate 		xfree(cmd->cfname);
281*7c478bd9Sstevel@tonic-gate 		chr_blkfree(cmd->cargs);
282*7c478bd9Sstevel@tonic-gate 		cmd->cfname = (char *) 0;
283*7c478bd9Sstevel@tonic-gate 		cmd->cargs = (char **) 0;
284*7c478bd9Sstevel@tonic-gate 
285*7c478bd9Sstevel@tonic-gate 		/* The sky is falling, the sky is falling! */
286*7c478bd9Sstevel@tonic-gate 
287*7c478bd9Sstevel@tonic-gate 	case ENOMEM:
288*7c478bd9Sstevel@tonic-gate 		Perror(f);
289*7c478bd9Sstevel@tonic-gate 
290*7c478bd9Sstevel@tonic-gate 	case ENOENT:
291*7c478bd9Sstevel@tonic-gate 		break;
292*7c478bd9Sstevel@tonic-gate 
293*7c478bd9Sstevel@tonic-gate 	default:
294*7c478bd9Sstevel@tonic-gate 		if (exerr == 0) {
295*7c478bd9Sstevel@tonic-gate 			exerr = strerror(errno);
296*7c478bd9Sstevel@tonic-gate 			setname(f);
297*7c478bd9Sstevel@tonic-gate 		}
298*7c478bd9Sstevel@tonic-gate 	}
299*7c478bd9Sstevel@tonic-gate }
300*7c478bd9Sstevel@tonic-gate 
301*7c478bd9Sstevel@tonic-gate 
302*7c478bd9Sstevel@tonic-gate static
303*7c478bd9Sstevel@tonic-gate tconvert(cmd, fname, list)
304*7c478bd9Sstevel@tonic-gate register struct command *cmd;
305*7c478bd9Sstevel@tonic-gate register tchar *fname, **list;
306*7c478bd9Sstevel@tonic-gate {
307*7c478bd9Sstevel@tonic-gate 	register char **rc;
308*7c478bd9Sstevel@tonic-gate 	register int len;
309*7c478bd9Sstevel@tonic-gate 
310*7c478bd9Sstevel@tonic-gate 	cmd->cfname = tstostr(NULL, fname);
311*7c478bd9Sstevel@tonic-gate 
312*7c478bd9Sstevel@tonic-gate 	len = blklen(list);
313*7c478bd9Sstevel@tonic-gate 	rc = cmd->cargs = (char **)
314*7c478bd9Sstevel@tonic-gate 		calloc((u_int) (len + 1), sizeof(char **));
315*7c478bd9Sstevel@tonic-gate 	while (len--)
316*7c478bd9Sstevel@tonic-gate 		*rc++ = tstostr(NULL, *list++);
317*7c478bd9Sstevel@tonic-gate 	*rc = NULL;
318*7c478bd9Sstevel@tonic-gate }
319*7c478bd9Sstevel@tonic-gate 
320*7c478bd9Sstevel@tonic-gate 
321*7c478bd9Sstevel@tonic-gate /*ARGSUSED*/
322*7c478bd9Sstevel@tonic-gate execash(t, kp)
323*7c478bd9Sstevel@tonic-gate 	tchar **t;
324*7c478bd9Sstevel@tonic-gate 	register struct command *kp;
325*7c478bd9Sstevel@tonic-gate {
326*7c478bd9Sstevel@tonic-gate #ifdef TRACE
327*7c478bd9Sstevel@tonic-gate 	tprintf("TRACE- execash()\n");
328*7c478bd9Sstevel@tonic-gate #endif
329*7c478bd9Sstevel@tonic-gate 
330*7c478bd9Sstevel@tonic-gate 	rechist();
331*7c478bd9Sstevel@tonic-gate 	(void) signal(SIGINT, parintr);
332*7c478bd9Sstevel@tonic-gate 	(void) signal(SIGQUIT, parintr);
333*7c478bd9Sstevel@tonic-gate 	(void) signal(SIGTERM, parterm);	/* if doexec loses, screw */
334*7c478bd9Sstevel@tonic-gate 	lshift(kp->t_dcom, 1);
335*7c478bd9Sstevel@tonic-gate 	exiterr++;
336*7c478bd9Sstevel@tonic-gate 	doexec(kp);
337*7c478bd9Sstevel@tonic-gate 	/*NOTREACHED*/
338*7c478bd9Sstevel@tonic-gate }
339*7c478bd9Sstevel@tonic-gate 
340*7c478bd9Sstevel@tonic-gate xechoit(t)
341*7c478bd9Sstevel@tonic-gate 	tchar **t;
342*7c478bd9Sstevel@tonic-gate {
343*7c478bd9Sstevel@tonic-gate #ifdef TRACE
344*7c478bd9Sstevel@tonic-gate 	tprintf("TRACE- xechoit()\n");
345*7c478bd9Sstevel@tonic-gate #endif
346*7c478bd9Sstevel@tonic-gate 
347*7c478bd9Sstevel@tonic-gate 	if (adrof(S_echo /*"echo"*/)) {
348*7c478bd9Sstevel@tonic-gate 		flush();
349*7c478bd9Sstevel@tonic-gate 		haderr = 1;
350*7c478bd9Sstevel@tonic-gate 		blkpr(t), Putchar('\n');
351*7c478bd9Sstevel@tonic-gate 		haderr = 0;
352*7c478bd9Sstevel@tonic-gate 	}
353*7c478bd9Sstevel@tonic-gate }
354*7c478bd9Sstevel@tonic-gate 
355*7c478bd9Sstevel@tonic-gate /*
356*7c478bd9Sstevel@tonic-gate  * This routine called when user enters "rehash".
357*7c478bd9Sstevel@tonic-gate  * Both the path and cdpath caching arrays will
358*7c478bd9Sstevel@tonic-gate  * be rehashed, via calling dohash.  If either
359*7c478bd9Sstevel@tonic-gate  * variable is not set with a value, then dohash
360*7c478bd9Sstevel@tonic-gate  * just exits.
361*7c478bd9Sstevel@tonic-gate  */
362*7c478bd9Sstevel@tonic-gate 
363*7c478bd9Sstevel@tonic-gate dorehash()
364*7c478bd9Sstevel@tonic-gate {
365*7c478bd9Sstevel@tonic-gate 	dohash(xhash);
366*7c478bd9Sstevel@tonic-gate 	dohash(xhash2);
367*7c478bd9Sstevel@tonic-gate }
368*7c478bd9Sstevel@tonic-gate 
369*7c478bd9Sstevel@tonic-gate /*
370*7c478bd9Sstevel@tonic-gate  * Fill up caching arrays for path and cdpath
371*7c478bd9Sstevel@tonic-gate  */
372*7c478bd9Sstevel@tonic-gate dohash(cachearray)
373*7c478bd9Sstevel@tonic-gate char cachearray[];
374*7c478bd9Sstevel@tonic-gate {
375*7c478bd9Sstevel@tonic-gate 	struct stat stb;
376*7c478bd9Sstevel@tonic-gate 	DIR *dirp;
377*7c478bd9Sstevel@tonic-gate 	register struct dirent *dp;
378*7c478bd9Sstevel@tonic-gate 	register int cnt;
379*7c478bd9Sstevel@tonic-gate 	int i = 0;
380*7c478bd9Sstevel@tonic-gate 	struct varent *v;
381*7c478bd9Sstevel@tonic-gate 	tchar **pv;
382*7c478bd9Sstevel@tonic-gate 	int hashval;
383*7c478bd9Sstevel@tonic-gate 	tchar curdir_[MAXNAMLEN+1];
384*7c478bd9Sstevel@tonic-gate 
385*7c478bd9Sstevel@tonic-gate #ifdef TRACE
386*7c478bd9Sstevel@tonic-gate 	tprintf("TRACE- dohash()\n");
387*7c478bd9Sstevel@tonic-gate #endif
388*7c478bd9Sstevel@tonic-gate 	/* Caching $path */
389*7c478bd9Sstevel@tonic-gate 	if ( cachearray == xhash ) {
390*7c478bd9Sstevel@tonic-gate 		havhash = 1;
391*7c478bd9Sstevel@tonic-gate 		v = adrof(S_path /*"path"*/);
392*7c478bd9Sstevel@tonic-gate 	}else {    /* Caching $cdpath */
393*7c478bd9Sstevel@tonic-gate 		havhash2 = 1;
394*7c478bd9Sstevel@tonic-gate 		v = adrof(S_cdpath /*"cdpath"*/);
395*7c478bd9Sstevel@tonic-gate 	}
396*7c478bd9Sstevel@tonic-gate 
397*7c478bd9Sstevel@tonic-gate 	for (cnt = 0; cnt < ( HSHSIZ / 8 ); cnt++)
398*7c478bd9Sstevel@tonic-gate 		cachearray[cnt] = 0;
399*7c478bd9Sstevel@tonic-gate 	if (v == 0)
400*7c478bd9Sstevel@tonic-gate 		{
401*7c478bd9Sstevel@tonic-gate 		return;
402*7c478bd9Sstevel@tonic-gate 		}
403*7c478bd9Sstevel@tonic-gate 	for (pv = v->vec; *pv; pv++, i++) {
404*7c478bd9Sstevel@tonic-gate 		if (pv[0][0] != '/')
405*7c478bd9Sstevel@tonic-gate 			continue;
406*7c478bd9Sstevel@tonic-gate 		dirp = opendir_(*pv);
407*7c478bd9Sstevel@tonic-gate 		if (dirp == NULL)
408*7c478bd9Sstevel@tonic-gate 			continue;
409*7c478bd9Sstevel@tonic-gate 		if (fstat(dirp->dd_fd, &stb) < 0 || !isdir(stb)) {
410*7c478bd9Sstevel@tonic-gate 			unsetfd(dirp->dd_fd);
411*7c478bd9Sstevel@tonic-gate 			closedir_(dirp);
412*7c478bd9Sstevel@tonic-gate 			continue;
413*7c478bd9Sstevel@tonic-gate 		}
414*7c478bd9Sstevel@tonic-gate 		while ((dp = readdir(dirp)) != NULL) {
415*7c478bd9Sstevel@tonic-gate 			if (dp->d_ino == 0)
416*7c478bd9Sstevel@tonic-gate 				continue;
417*7c478bd9Sstevel@tonic-gate 			if (dp->d_name[0] == '.' &&
418*7c478bd9Sstevel@tonic-gate 			    (dp->d_name[1] == '\0' ||
419*7c478bd9Sstevel@tonic-gate 			     dp->d_name[1] == '.' && dp->d_name[2] == '\0'))
420*7c478bd9Sstevel@tonic-gate 				continue;
421*7c478bd9Sstevel@tonic-gate 			hashval = hash(hashname(strtots(curdir_,dp->d_name)), i);
422*7c478bd9Sstevel@tonic-gate 			bis(cachearray, hashval);
423*7c478bd9Sstevel@tonic-gate 		}
424*7c478bd9Sstevel@tonic-gate 		unsetfd(dirp->dd_fd);
425*7c478bd9Sstevel@tonic-gate 		closedir_(dirp);
426*7c478bd9Sstevel@tonic-gate 	}
427*7c478bd9Sstevel@tonic-gate }
428*7c478bd9Sstevel@tonic-gate 
429*7c478bd9Sstevel@tonic-gate dounhash()
430*7c478bd9Sstevel@tonic-gate {
431*7c478bd9Sstevel@tonic-gate 
432*7c478bd9Sstevel@tonic-gate #ifdef TRACE
433*7c478bd9Sstevel@tonic-gate 	tprintf("TRACE- dounhash()\n");
434*7c478bd9Sstevel@tonic-gate #endif
435*7c478bd9Sstevel@tonic-gate 	havhash = 0;
436*7c478bd9Sstevel@tonic-gate 	havhash2 = 0;
437*7c478bd9Sstevel@tonic-gate }
438*7c478bd9Sstevel@tonic-gate 
439*7c478bd9Sstevel@tonic-gate #ifdef VFORK
440*7c478bd9Sstevel@tonic-gate hashstat()
441*7c478bd9Sstevel@tonic-gate {
442*7c478bd9Sstevel@tonic-gate #ifdef TRACE
443*7c478bd9Sstevel@tonic-gate 	tprintf("TRACE- hashstat_()\n");
444*7c478bd9Sstevel@tonic-gate #endif
445*7c478bd9Sstevel@tonic-gate 
446*7c478bd9Sstevel@tonic-gate 	if (hits+misses)
447*7c478bd9Sstevel@tonic-gate 		printf("%d hits, %d misses, %d%%\n",
448*7c478bd9Sstevel@tonic-gate 			hits, misses, 100 * hits / (hits + misses));
449*7c478bd9Sstevel@tonic-gate }
450*7c478bd9Sstevel@tonic-gate #endif
451*7c478bd9Sstevel@tonic-gate 
452*7c478bd9Sstevel@tonic-gate /*
453*7c478bd9Sstevel@tonic-gate  * Hash a command name.
454*7c478bd9Sstevel@tonic-gate  */
455*7c478bd9Sstevel@tonic-gate hashname(cp)
456*7c478bd9Sstevel@tonic-gate 	register tchar *cp;
457*7c478bd9Sstevel@tonic-gate {
458*7c478bd9Sstevel@tonic-gate 	register long h = 0;
459*7c478bd9Sstevel@tonic-gate 
460*7c478bd9Sstevel@tonic-gate #ifdef TRACE
461*7c478bd9Sstevel@tonic-gate 	tprintf("TRACE- hashname()\n");
462*7c478bd9Sstevel@tonic-gate #endif
463*7c478bd9Sstevel@tonic-gate 	while (*cp)
464*7c478bd9Sstevel@tonic-gate 		h = hash(h, *cp++);
465*7c478bd9Sstevel@tonic-gate 	return ((int) h);
466*7c478bd9Sstevel@tonic-gate }
467