xref: /onnv-gate/usr/src/cmd/sh/hashserv.c (revision 9369:4df685ccc8c1)
10Sstevel@tonic-gate /*
20Sstevel@tonic-gate  * CDDL HEADER START
30Sstevel@tonic-gate  *
40Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
52256Sna195498  * Common Development and Distribution License (the "License").
62256Sna195498  * You may not use this file except in compliance with the License.
70Sstevel@tonic-gate  *
80Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
90Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
100Sstevel@tonic-gate  * See the License for the specific language governing permissions
110Sstevel@tonic-gate  * and limitations under the License.
120Sstevel@tonic-gate  *
130Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
140Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
150Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
160Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
170Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
180Sstevel@tonic-gate  *
190Sstevel@tonic-gate  * CDDL HEADER END
200Sstevel@tonic-gate  */
21527Schin 
22527Schin /*
23*9369SNobutomo.Nakano@Sun.COM  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
24527Schin  * Use is subject to license terms.
25527Schin  */
26527Schin 
270Sstevel@tonic-gate /*	Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T	*/
280Sstevel@tonic-gate /*	  All Rights Reserved  	*/
290Sstevel@tonic-gate 
300Sstevel@tonic-gate /*
310Sstevel@tonic-gate  *	UNIX shell
320Sstevel@tonic-gate  */
330Sstevel@tonic-gate 
340Sstevel@tonic-gate #include	"hash.h"
350Sstevel@tonic-gate #include	"defs.h"
360Sstevel@tonic-gate #include	<sys/types.h>
370Sstevel@tonic-gate #include	<sys/stat.h>
380Sstevel@tonic-gate #include	<errno.h>
390Sstevel@tonic-gate 
400Sstevel@tonic-gate #define		EXECUTE		01
410Sstevel@tonic-gate 
420Sstevel@tonic-gate static unsigned char	cost;
430Sstevel@tonic-gate static int	dotpath;
440Sstevel@tonic-gate static int	multrel;
450Sstevel@tonic-gate static struct entry	relcmd;
460Sstevel@tonic-gate 
470Sstevel@tonic-gate static int	argpath();
48527Schin static void pr_path(unsigned char *, int);
490Sstevel@tonic-gate 
500Sstevel@tonic-gate short
pathlook(com,flg,arg)510Sstevel@tonic-gate pathlook(com, flg, arg)
520Sstevel@tonic-gate 	unsigned char	*com;
530Sstevel@tonic-gate 	int		flg;
54527Schin 	struct argnod	*arg;
550Sstevel@tonic-gate {
56527Schin 	unsigned char	*name = com;
57527Schin 	ENTRY		*h;
580Sstevel@tonic-gate 
590Sstevel@tonic-gate 	ENTRY		hentry;
600Sstevel@tonic-gate 	int		count = 0;
610Sstevel@tonic-gate 	int		i;
620Sstevel@tonic-gate 	int		pathset = 0;
630Sstevel@tonic-gate 	int		oldpath = 0;
640Sstevel@tonic-gate 	struct namnod	*n;
650Sstevel@tonic-gate 
660Sstevel@tonic-gate 
670Sstevel@tonic-gate 
680Sstevel@tonic-gate 	hentry.data = 0;
690Sstevel@tonic-gate 
700Sstevel@tonic-gate 	if (any('/', name))
710Sstevel@tonic-gate 		return(COMMAND);
720Sstevel@tonic-gate 
730Sstevel@tonic-gate 	h = hfind(name);
740Sstevel@tonic-gate 
750Sstevel@tonic-gate 
760Sstevel@tonic-gate 	if (h)
770Sstevel@tonic-gate 	{
780Sstevel@tonic-gate 		if (h->data & (BUILTIN | FUNCTION))
790Sstevel@tonic-gate 		{
800Sstevel@tonic-gate 			if (flg)
810Sstevel@tonic-gate 				h->hits++;
820Sstevel@tonic-gate 			return(h->data);
830Sstevel@tonic-gate 		}
840Sstevel@tonic-gate 
850Sstevel@tonic-gate 		if (arg && (pathset = argpath(arg)))
860Sstevel@tonic-gate 			return(PATH_COMMAND);
870Sstevel@tonic-gate 
880Sstevel@tonic-gate 		if ((h->data & DOT_COMMAND) == DOT_COMMAND)
890Sstevel@tonic-gate 		{
900Sstevel@tonic-gate 			if (multrel == 0 && hashdata(h->data) > dotpath)
910Sstevel@tonic-gate 				oldpath = hashdata(h->data);
920Sstevel@tonic-gate 			else
930Sstevel@tonic-gate 				oldpath = dotpath;
940Sstevel@tonic-gate 
950Sstevel@tonic-gate 			h->data = 0;
960Sstevel@tonic-gate 			goto pathsrch;
970Sstevel@tonic-gate 		}
980Sstevel@tonic-gate 
990Sstevel@tonic-gate 		if (h->data & (COMMAND | REL_COMMAND))
1000Sstevel@tonic-gate 		{
1010Sstevel@tonic-gate 			if (flg)
1020Sstevel@tonic-gate 				h->hits++;
1030Sstevel@tonic-gate 			return(h->data);
1040Sstevel@tonic-gate 		}
1050Sstevel@tonic-gate 
1060Sstevel@tonic-gate 		h->data = 0;
1070Sstevel@tonic-gate 		h->cost = 0;
1080Sstevel@tonic-gate 	}
1090Sstevel@tonic-gate 
1100Sstevel@tonic-gate 	if (i = syslook(name, commands, no_commands))
1110Sstevel@tonic-gate 	{
1120Sstevel@tonic-gate 		hentry.data = (BUILTIN | i);
1130Sstevel@tonic-gate 		count = 1;
1140Sstevel@tonic-gate 	}
1150Sstevel@tonic-gate 	else
1160Sstevel@tonic-gate 	{
1170Sstevel@tonic-gate 		if (arg && (pathset = argpath(arg)))
1180Sstevel@tonic-gate 			return(PATH_COMMAND);
1190Sstevel@tonic-gate pathsrch:
1200Sstevel@tonic-gate 			count = findpath(name, oldpath);
1210Sstevel@tonic-gate 	}
1220Sstevel@tonic-gate 
1230Sstevel@tonic-gate 	if (count > 0)
1240Sstevel@tonic-gate 	{
1250Sstevel@tonic-gate 		if (h == 0)
1260Sstevel@tonic-gate 		{
1270Sstevel@tonic-gate 			hentry.cost = 0;
1280Sstevel@tonic-gate 			hentry.key = make(name);
1290Sstevel@tonic-gate 			h = henter(hentry);
1300Sstevel@tonic-gate 		}
1310Sstevel@tonic-gate 
1320Sstevel@tonic-gate 		if (h->data == 0)
1330Sstevel@tonic-gate 		{
1340Sstevel@tonic-gate 			if (count < dotpath)
1350Sstevel@tonic-gate 				h->data = COMMAND | count;
1360Sstevel@tonic-gate 			else
1370Sstevel@tonic-gate 			{
1380Sstevel@tonic-gate 				h->data = REL_COMMAND | count;
1390Sstevel@tonic-gate 				h->next = relcmd.next;
1400Sstevel@tonic-gate 				relcmd.next = h;
1410Sstevel@tonic-gate 			}
1420Sstevel@tonic-gate 		}
1430Sstevel@tonic-gate 
1440Sstevel@tonic-gate 
1450Sstevel@tonic-gate 		h->hits = flg;
1460Sstevel@tonic-gate 		h->cost += cost;
1470Sstevel@tonic-gate 		return(h->data);
1480Sstevel@tonic-gate 	}
1490Sstevel@tonic-gate 	else
1500Sstevel@tonic-gate 	{
1510Sstevel@tonic-gate 		return(-count);
1520Sstevel@tonic-gate 	}
1530Sstevel@tonic-gate }
1540Sstevel@tonic-gate 
1550Sstevel@tonic-gate 
1560Sstevel@tonic-gate static void
zapentry(h)1570Sstevel@tonic-gate zapentry(h)
1580Sstevel@tonic-gate 	ENTRY *h;
1590Sstevel@tonic-gate {
1600Sstevel@tonic-gate 	h->data &= HASHZAP;
1610Sstevel@tonic-gate }
1620Sstevel@tonic-gate 
1630Sstevel@tonic-gate void
zaphash()1640Sstevel@tonic-gate zaphash()
1650Sstevel@tonic-gate {
1660Sstevel@tonic-gate 	hscan(zapentry);
1670Sstevel@tonic-gate 	relcmd.next = 0;
1680Sstevel@tonic-gate }
1690Sstevel@tonic-gate 
1700Sstevel@tonic-gate void
zapcd()1710Sstevel@tonic-gate zapcd()
1720Sstevel@tonic-gate {
1730Sstevel@tonic-gate 	ENTRY *ptr = relcmd.next;
1740Sstevel@tonic-gate 
1750Sstevel@tonic-gate 	while (ptr)
1760Sstevel@tonic-gate 	{
1770Sstevel@tonic-gate 		ptr->data |= CDMARK;
1780Sstevel@tonic-gate 		ptr = ptr->next;
1790Sstevel@tonic-gate 	}
1800Sstevel@tonic-gate 	relcmd.next = 0;
1810Sstevel@tonic-gate }
1820Sstevel@tonic-gate 
1830Sstevel@tonic-gate 
1840Sstevel@tonic-gate static void
hashout(h)1850Sstevel@tonic-gate hashout(h)
1860Sstevel@tonic-gate 	ENTRY *h;
1870Sstevel@tonic-gate {
1880Sstevel@tonic-gate 	sigchk();
1890Sstevel@tonic-gate 
1900Sstevel@tonic-gate 	if (hashtype(h->data) == NOTFOUND)
1910Sstevel@tonic-gate 		return;
1920Sstevel@tonic-gate 
1930Sstevel@tonic-gate 	if (h->data & (BUILTIN | FUNCTION))
1940Sstevel@tonic-gate 		return;
1950Sstevel@tonic-gate 
1960Sstevel@tonic-gate 	prn_buff(h->hits);
1970Sstevel@tonic-gate 
1980Sstevel@tonic-gate 	if (h->data & REL_COMMAND)
1990Sstevel@tonic-gate 		prc_buff('*');
2000Sstevel@tonic-gate 
2010Sstevel@tonic-gate 
2020Sstevel@tonic-gate 	prc_buff(TAB);
2030Sstevel@tonic-gate 	prn_buff(h->cost);
2040Sstevel@tonic-gate 	prc_buff(TAB);
2050Sstevel@tonic-gate 
2060Sstevel@tonic-gate 	pr_path(h->key, hashdata(h->data));
2070Sstevel@tonic-gate 	prc_buff(NL);
2080Sstevel@tonic-gate }
2090Sstevel@tonic-gate 
2100Sstevel@tonic-gate void
hashpr()2110Sstevel@tonic-gate hashpr()
2120Sstevel@tonic-gate {
2132256Sna195498 	prs_buff(_gettext("hits	cost	command\n"));
2140Sstevel@tonic-gate 	hscan(hashout);
2150Sstevel@tonic-gate }
2160Sstevel@tonic-gate 
217527Schin void
set_dotpath(void)218527Schin set_dotpath(void)
2190Sstevel@tonic-gate {
220527Schin 	unsigned char	*path;
221527Schin 	int		cnt = 1;
2220Sstevel@tonic-gate 
2230Sstevel@tonic-gate 	dotpath = 10000;
2240Sstevel@tonic-gate 	path = getpath("");
2250Sstevel@tonic-gate 
2260Sstevel@tonic-gate 	while (path && *path)
2270Sstevel@tonic-gate 	{
2280Sstevel@tonic-gate 		if (*path == '/')
2290Sstevel@tonic-gate 			cnt++;
2300Sstevel@tonic-gate 		else
2310Sstevel@tonic-gate 		{
2320Sstevel@tonic-gate 			if (dotpath == 10000)
2330Sstevel@tonic-gate 				dotpath = cnt;
2340Sstevel@tonic-gate 			else
2350Sstevel@tonic-gate 			{
2360Sstevel@tonic-gate 				multrel = 1;
2370Sstevel@tonic-gate 				return;
2380Sstevel@tonic-gate 			}
2390Sstevel@tonic-gate 		}
2400Sstevel@tonic-gate 
2410Sstevel@tonic-gate 		path = nextpath(path);
2420Sstevel@tonic-gate 	}
2430Sstevel@tonic-gate 
2440Sstevel@tonic-gate 	multrel = 0;
2450Sstevel@tonic-gate }
2460Sstevel@tonic-gate 
247527Schin void
hash_func(unsigned char * name)248527Schin hash_func(unsigned char *name)
2490Sstevel@tonic-gate {
2500Sstevel@tonic-gate 	ENTRY	*h;
2510Sstevel@tonic-gate 	ENTRY	hentry;
2520Sstevel@tonic-gate 
2530Sstevel@tonic-gate 	h = hfind(name);
2540Sstevel@tonic-gate 
2550Sstevel@tonic-gate 	if (h)
2560Sstevel@tonic-gate 		h->data = FUNCTION;
2570Sstevel@tonic-gate 	else
2580Sstevel@tonic-gate 	{
2590Sstevel@tonic-gate 		hentry.data = FUNCTION;
2600Sstevel@tonic-gate 		hentry.key = make(name);
2610Sstevel@tonic-gate 		hentry.cost = 0;
2620Sstevel@tonic-gate 		hentry.hits = 0;
2630Sstevel@tonic-gate 		henter(hentry);
2640Sstevel@tonic-gate 	}
2650Sstevel@tonic-gate }
2660Sstevel@tonic-gate 
267527Schin void
func_unhash(unsigned char * name)268527Schin func_unhash(unsigned char *name)
2690Sstevel@tonic-gate {
2700Sstevel@tonic-gate 	ENTRY 	*h;
2710Sstevel@tonic-gate 	int i;
2720Sstevel@tonic-gate 
2730Sstevel@tonic-gate 	h = hfind(name);
2740Sstevel@tonic-gate 
2750Sstevel@tonic-gate 	if (h && (h->data & FUNCTION)) {
2760Sstevel@tonic-gate 		if(i = syslook(name, commands, no_commands))
2770Sstevel@tonic-gate 			h->data = (BUILTIN|i);
2780Sstevel@tonic-gate 		else
2790Sstevel@tonic-gate 			h->data = NOTFOUND;
2800Sstevel@tonic-gate 	}
2810Sstevel@tonic-gate }
2820Sstevel@tonic-gate 
2830Sstevel@tonic-gate 
2840Sstevel@tonic-gate short
hash_cmd(name)2850Sstevel@tonic-gate hash_cmd(name)
2860Sstevel@tonic-gate 	unsigned char *name;
2870Sstevel@tonic-gate {
2880Sstevel@tonic-gate 	ENTRY	*h;
2890Sstevel@tonic-gate 
2900Sstevel@tonic-gate 	if (any('/', name))
2910Sstevel@tonic-gate 		return(COMMAND);
2920Sstevel@tonic-gate 
2930Sstevel@tonic-gate 	h = hfind(name);
2940Sstevel@tonic-gate 
2950Sstevel@tonic-gate 	if (h)
2960Sstevel@tonic-gate 	{
2970Sstevel@tonic-gate 		if (h->data & (BUILTIN | FUNCTION))
2980Sstevel@tonic-gate 			return(h->data);
2990Sstevel@tonic-gate 		else if ((h->data & REL_COMMAND) == REL_COMMAND)
3000Sstevel@tonic-gate 		{ /* unlink h from relative command list */
3010Sstevel@tonic-gate 			ENTRY *ptr = &relcmd;
3020Sstevel@tonic-gate 			while(ptr-> next != h)
3030Sstevel@tonic-gate 				ptr = ptr->next;
3040Sstevel@tonic-gate 			ptr->next = h->next;
3050Sstevel@tonic-gate 		}
3060Sstevel@tonic-gate 		zapentry(h);
3070Sstevel@tonic-gate 	}
3080Sstevel@tonic-gate 
3090Sstevel@tonic-gate 	return(pathlook(name, 0, 0));
3100Sstevel@tonic-gate }
3110Sstevel@tonic-gate 
3120Sstevel@tonic-gate 
3130Sstevel@tonic-gate /*
3140Sstevel@tonic-gate  * Return 0 if found, 1 if not.
3150Sstevel@tonic-gate  */
316527Schin int
what_is_path(unsigned char * name)317527Schin what_is_path(unsigned char *name)
3180Sstevel@tonic-gate {
319527Schin 	ENTRY	*h;
320527Schin 	int	cnt;
3210Sstevel@tonic-gate 	short	hashval;
3220Sstevel@tonic-gate 
3230Sstevel@tonic-gate 	h = hfind(name);
3240Sstevel@tonic-gate 
3250Sstevel@tonic-gate 	prs_buff(name);
3260Sstevel@tonic-gate 	if (h)
3270Sstevel@tonic-gate 	{
3280Sstevel@tonic-gate 		hashval = hashdata(h->data);
3290Sstevel@tonic-gate 
3300Sstevel@tonic-gate 		switch (hashtype(h->data))
3310Sstevel@tonic-gate 		{
3320Sstevel@tonic-gate 			case BUILTIN:
3332256Sna195498 				prs_buff(_gettext(" is a shell builtin\n"));
3340Sstevel@tonic-gate 				return (0);
3350Sstevel@tonic-gate 
3360Sstevel@tonic-gate 			case FUNCTION:
3370Sstevel@tonic-gate 			{
3380Sstevel@tonic-gate 				struct namnod *n = lookup(name);
339*9369SNobutomo.Nakano@Sun.COM 				struct fndnod *f = fndptr(n->namenv);
3400Sstevel@tonic-gate 
3412256Sna195498 				prs_buff(_gettext(" is a function\n"));
3420Sstevel@tonic-gate 				prs_buff(name);
3430Sstevel@tonic-gate 				prs_buff("(){\n");
344*9369SNobutomo.Nakano@Sun.COM 				if (f != NULL)
345*9369SNobutomo.Nakano@Sun.COM 					prf(f->fndval);
3460Sstevel@tonic-gate 				prs_buff("\n}\n");
3470Sstevel@tonic-gate 				return (0);
3480Sstevel@tonic-gate 			}
3490Sstevel@tonic-gate 
3500Sstevel@tonic-gate 			case REL_COMMAND:
3510Sstevel@tonic-gate 			{
3520Sstevel@tonic-gate 				short hash;
3530Sstevel@tonic-gate 
3540Sstevel@tonic-gate 				if ((h->data & DOT_COMMAND) == DOT_COMMAND)
3550Sstevel@tonic-gate 				{
3560Sstevel@tonic-gate 					hash = pathlook(name, 0, 0);
3570Sstevel@tonic-gate 					if (hashtype(hash) == NOTFOUND)
3580Sstevel@tonic-gate 					{
3592256Sna195498 						prs_buff(_gettext(" not"
3602256Sna195498 						    " found\n"));
3610Sstevel@tonic-gate 						return (1);
3620Sstevel@tonic-gate 					}
3630Sstevel@tonic-gate 					else
3640Sstevel@tonic-gate 						hashval = hashdata(hash);
3650Sstevel@tonic-gate 				}
3660Sstevel@tonic-gate 			}
3670Sstevel@tonic-gate 
3680Sstevel@tonic-gate 			case COMMAND:
3692256Sna195498 				prs_buff(_gettext(" is hashed ("));
3700Sstevel@tonic-gate 				pr_path(name, hashval);
3710Sstevel@tonic-gate 				prs_buff(")\n");
3720Sstevel@tonic-gate 				return (0);
3730Sstevel@tonic-gate 		}
3740Sstevel@tonic-gate 	}
3750Sstevel@tonic-gate 
3760Sstevel@tonic-gate 	if (syslook(name, commands, no_commands))
3770Sstevel@tonic-gate 	{
3782256Sna195498 		prs_buff(_gettext(" is a shell builtin\n"));
3790Sstevel@tonic-gate 		return (0);
3800Sstevel@tonic-gate 	}
3810Sstevel@tonic-gate 
3820Sstevel@tonic-gate 	if ((cnt = findpath(name, 0)) > 0)
3830Sstevel@tonic-gate 	{
3842256Sna195498 		prs_buff(_gettext(" is "));
3850Sstevel@tonic-gate 		pr_path(name, cnt);
3860Sstevel@tonic-gate 		prc_buff(NL);
3870Sstevel@tonic-gate 		return (0);
3880Sstevel@tonic-gate 	}
3890Sstevel@tonic-gate 	else
3900Sstevel@tonic-gate 	{
3912256Sna195498 		prs_buff(_gettext(" not found\n"));
3920Sstevel@tonic-gate 		return (1);
3930Sstevel@tonic-gate 	}
3940Sstevel@tonic-gate }
3950Sstevel@tonic-gate 
396527Schin int
findpath(unsigned char * name,int oldpath)397527Schin findpath(unsigned char *name, int oldpath)
3980Sstevel@tonic-gate {
399527Schin 	unsigned char 	*path;
400527Schin 	int	count = 1;
4010Sstevel@tonic-gate 
4020Sstevel@tonic-gate 	unsigned char	*p;
4030Sstevel@tonic-gate 	int	ok = 1;
4040Sstevel@tonic-gate 	int 	e_code = 1;
4050Sstevel@tonic-gate 
4060Sstevel@tonic-gate 	cost = 0;
4070Sstevel@tonic-gate 	path = getpath(name);
4080Sstevel@tonic-gate 
4090Sstevel@tonic-gate 	if (oldpath)
4100Sstevel@tonic-gate 	{
4110Sstevel@tonic-gate 		count = dotpath;
4120Sstevel@tonic-gate 		while (--count)
4130Sstevel@tonic-gate 			path = nextpath(path);
4140Sstevel@tonic-gate 
4150Sstevel@tonic-gate 		if (oldpath > dotpath)
4160Sstevel@tonic-gate 		{
4170Sstevel@tonic-gate 			catpath(path, name);
4180Sstevel@tonic-gate 			p = curstak();
4190Sstevel@tonic-gate 			cost = 1;
4200Sstevel@tonic-gate 
4210Sstevel@tonic-gate 			if ((ok = chk_access(p, S_IEXEC, 1)) == 0)
4220Sstevel@tonic-gate 				return(dotpath);
4230Sstevel@tonic-gate 			else
4240Sstevel@tonic-gate 				return(oldpath);
4250Sstevel@tonic-gate 		}
4260Sstevel@tonic-gate 		else
4270Sstevel@tonic-gate 			count = dotpath;
4280Sstevel@tonic-gate 	}
4290Sstevel@tonic-gate 
4300Sstevel@tonic-gate 	while (path)
4310Sstevel@tonic-gate 	{
4320Sstevel@tonic-gate 		path = catpath(path, name);
4330Sstevel@tonic-gate 		cost++;
4340Sstevel@tonic-gate 		p = curstak();
4350Sstevel@tonic-gate 
4360Sstevel@tonic-gate 		if ((ok = chk_access(p, S_IEXEC, 1)) == 0)
4370Sstevel@tonic-gate 			break;
4380Sstevel@tonic-gate 		else
4390Sstevel@tonic-gate 			e_code = max(e_code, ok);
4400Sstevel@tonic-gate 
4410Sstevel@tonic-gate 		count++;
4420Sstevel@tonic-gate 	}
4430Sstevel@tonic-gate 
4440Sstevel@tonic-gate 	return(ok ? -e_code : count);
4450Sstevel@tonic-gate }
4460Sstevel@tonic-gate 
4470Sstevel@tonic-gate /*
4480Sstevel@tonic-gate  * Determine if file given by name is accessible with permissions
4490Sstevel@tonic-gate  * given by mode.
4500Sstevel@tonic-gate  * Regflag argument non-zero means not to consider
4510Sstevel@tonic-gate  * a non-regular file as executable.
4520Sstevel@tonic-gate  */
4530Sstevel@tonic-gate 
454527Schin int
chk_access(unsigned char * name,mode_t mode,int regflag)455527Schin chk_access(unsigned char *name, mode_t mode, int regflag)
4560Sstevel@tonic-gate {
4570Sstevel@tonic-gate 	static int flag;
4580Sstevel@tonic-gate 	static uid_t euid;
4590Sstevel@tonic-gate 	struct stat statb;
4600Sstevel@tonic-gate 	mode_t ftype;
4610Sstevel@tonic-gate 
4620Sstevel@tonic-gate 	if(flag == 0) {
4630Sstevel@tonic-gate 		euid = geteuid();
4640Sstevel@tonic-gate 		flag = 1;
4650Sstevel@tonic-gate 	}
4660Sstevel@tonic-gate 	ftype = statb.st_mode & S_IFMT;
4670Sstevel@tonic-gate 	if (stat((char *)name, &statb) == 0) {
4680Sstevel@tonic-gate 		ftype = statb.st_mode & S_IFMT;
4690Sstevel@tonic-gate 		if(mode == S_IEXEC && regflag && ftype != S_IFREG)
4700Sstevel@tonic-gate 			return(2);
4710Sstevel@tonic-gate 		if(access((char *)name, 010|(mode>>6)) == 0) {
4720Sstevel@tonic-gate 			if(euid == 0) {
4730Sstevel@tonic-gate 				if (ftype != S_IFREG || mode != S_IEXEC)
4740Sstevel@tonic-gate 					return(0);
4750Sstevel@tonic-gate 		    		/* root can execute file as long as it has execute
4760Sstevel@tonic-gate 			   	permission for someone */
4770Sstevel@tonic-gate 				if (statb.st_mode & (S_IEXEC|(S_IEXEC>>3)|(S_IEXEC>>6)))
4780Sstevel@tonic-gate 					return(0);
4790Sstevel@tonic-gate 				return(3);
4800Sstevel@tonic-gate 			}
4810Sstevel@tonic-gate 			return(0);
4820Sstevel@tonic-gate 		}
4830Sstevel@tonic-gate 	}
4840Sstevel@tonic-gate 	return(errno == EACCES ? 3 : 1);
4850Sstevel@tonic-gate }
4860Sstevel@tonic-gate 
487527Schin static void
pr_path(unsigned char * name,int count)488527Schin pr_path(unsigned char *name, int count)
4890Sstevel@tonic-gate {
490527Schin 	unsigned char	*path;
4910Sstevel@tonic-gate 
4920Sstevel@tonic-gate 	path = getpath(name);
4930Sstevel@tonic-gate 
4940Sstevel@tonic-gate 	while (--count && path)
4950Sstevel@tonic-gate 		path = nextpath(path, name);
4960Sstevel@tonic-gate 
4970Sstevel@tonic-gate 	catpath(path, name);
4980Sstevel@tonic-gate 	prs_buff(curstak());
4990Sstevel@tonic-gate }
5000Sstevel@tonic-gate 
5010Sstevel@tonic-gate 
502527Schin static int
argpath(struct argnod * arg)503527Schin argpath(struct argnod *arg)
5040Sstevel@tonic-gate {
505527Schin 	unsigned char 	*s;
506527Schin 	unsigned char	*start;
5070Sstevel@tonic-gate 
5080Sstevel@tonic-gate 	while (arg)
5090Sstevel@tonic-gate 	{
5100Sstevel@tonic-gate 		s = arg->argval;
5110Sstevel@tonic-gate 		start = s;
5120Sstevel@tonic-gate 
5130Sstevel@tonic-gate 		if (letter(*s))
5140Sstevel@tonic-gate 		{
5150Sstevel@tonic-gate 			while (alphanum(*s))
5160Sstevel@tonic-gate 				s++;
5170Sstevel@tonic-gate 
5180Sstevel@tonic-gate 			if (*s == '=')
5190Sstevel@tonic-gate 			{
5200Sstevel@tonic-gate 				*s = 0;
5210Sstevel@tonic-gate 
5220Sstevel@tonic-gate 				if (eq(start, pathname))
5230Sstevel@tonic-gate 				{
5240Sstevel@tonic-gate 					*s = '=';
5250Sstevel@tonic-gate 					return(1);
5260Sstevel@tonic-gate 				}
5270Sstevel@tonic-gate 				else
5280Sstevel@tonic-gate 					*s = '=';
5290Sstevel@tonic-gate 			}
5300Sstevel@tonic-gate 		}
5310Sstevel@tonic-gate 		arg = arg->argnxt;
5320Sstevel@tonic-gate 	}
5330Sstevel@tonic-gate 
5340Sstevel@tonic-gate 	return(0);
5350Sstevel@tonic-gate }
536