1*4887Schin /***********************************************************************
2*4887Schin *                                                                      *
3*4887Schin *               This software is part of the ast package               *
4*4887Schin *           Copyright (c) 1982-2007 AT&T Knowledge Ventures            *
5*4887Schin *                      and is licensed under the                       *
6*4887Schin *                  Common Public License, Version 1.0                  *
7*4887Schin *                      by AT&T Knowledge Ventures                      *
8*4887Schin *                                                                      *
9*4887Schin *                A copy of the License is available at                 *
10*4887Schin *            http://www.opensource.org/licenses/cpl1.0.txt             *
11*4887Schin *         (with md5 checksum 059e8cd6165cb4c31e351f2b69388fd9)         *
12*4887Schin *                                                                      *
13*4887Schin *              Information and Software Systems Research               *
14*4887Schin *                            AT&T Research                             *
15*4887Schin *                           Florham Park NJ                            *
16*4887Schin *                                                                      *
17*4887Schin *                  David Korn <dgk@research.att.com>                   *
18*4887Schin *                                                                      *
19*4887Schin ***********************************************************************/
20*4887Schin #pragma prototyped
21*4887Schin /*
22*4887Schin  * command [-pvVx] name [arg...]
23*4887Schin  * whence [-afvp] name...
24*4887Schin  *
25*4887Schin  *   David Korn
26*4887Schin  *   AT&T Labs
27*4887Schin  *
28*4887Schin  */
29*4887Schin 
30*4887Schin #include	"defs.h"
31*4887Schin #include	<error.h>
32*4887Schin #include	"shtable.h"
33*4887Schin #include	"name.h"
34*4887Schin #include	"path.h"
35*4887Schin #include	"shlex.h"
36*4887Schin #include	"builtins.h"
37*4887Schin 
38*4887Schin #define P_FLAG	1
39*4887Schin #define V_FLAG	2
40*4887Schin #define A_FLAG	4
41*4887Schin #define F_FLAG	010
42*4887Schin #define X_FLAG	020
43*4887Schin 
44*4887Schin static int whence(Shell_t *,char**, int);
45*4887Schin 
46*4887Schin /*
47*4887Schin  * command is called with argc==0 when checking for -V or -v option
48*4887Schin  * In this case return 0 when -v or -V or unknown option, otherwise
49*4887Schin  *   the shift count to the command is returned
50*4887Schin  */
51*4887Schin int	b_command(register int argc,char *argv[],void *extra)
52*4887Schin {
53*4887Schin 	register int n, flags=0;
54*4887Schin 	register Shell_t *shp = (Shell_t*)extra;
55*4887Schin 	opt_info.index = opt_info.offset = 0;
56*4887Schin 	while((n = optget(argv,sh_optcommand))) switch(n)
57*4887Schin 	{
58*4887Schin 	    case 'p':
59*4887Schin 		if(sh_isoption(SH_RESTRICTED))
60*4887Schin 			 errormsg(SH_DICT,ERROR_exit(1),e_restricted,"-p");
61*4887Schin 		sh_onstate(SH_DEFPATH);
62*4887Schin 		break;
63*4887Schin 	    case 'v':
64*4887Schin 		flags |= X_FLAG;
65*4887Schin 		break;
66*4887Schin 	    case 'V':
67*4887Schin 		flags |= V_FLAG;
68*4887Schin 		break;
69*4887Schin 	    case 'x':
70*4887Schin 		shp->xargexit = 1;
71*4887Schin 		break;
72*4887Schin 	    case ':':
73*4887Schin 		if(argc==0)
74*4887Schin 			return(0);
75*4887Schin 		errormsg(SH_DICT,2, "%s", opt_info.arg);
76*4887Schin 		break;
77*4887Schin 	    case '?':
78*4887Schin 		if(argc==0)
79*4887Schin 			return(0);
80*4887Schin 		errormsg(SH_DICT,ERROR_usage(2), "%s", opt_info.arg);
81*4887Schin 		break;
82*4887Schin 	}
83*4887Schin 	if(argc==0)
84*4887Schin 		return(flags?0:opt_info.index);
85*4887Schin 	argv += opt_info.index;
86*4887Schin 	if(error_info.errors || !*argv)
87*4887Schin 		errormsg(SH_DICT,ERROR_usage(2),"%s", optusage((char*)0));
88*4887Schin 	return(whence(shp,argv, flags));
89*4887Schin }
90*4887Schin 
91*4887Schin /*
92*4887Schin  *  for the whence command
93*4887Schin  */
94*4887Schin int	b_whence(int argc,char *argv[],void *extra)
95*4887Schin {
96*4887Schin 	register int flags=0, n;
97*4887Schin 	register Shell_t *shp = (Shell_t*)extra;
98*4887Schin 	NOT_USED(argc);
99*4887Schin 	if(*argv[0]=='t')
100*4887Schin 		flags = V_FLAG;
101*4887Schin 	while((n = optget(argv,sh_optwhence))) switch(n)
102*4887Schin 	{
103*4887Schin 	    case 'a':
104*4887Schin 		flags |= A_FLAG;
105*4887Schin 		/* FALL THRU */
106*4887Schin 	    case 'v':
107*4887Schin 		flags |= V_FLAG;
108*4887Schin 		break;
109*4887Schin 	    case 'f':
110*4887Schin 		flags |= F_FLAG;
111*4887Schin 		break;
112*4887Schin 	    case 'p':
113*4887Schin 		flags |= P_FLAG;
114*4887Schin 		break;
115*4887Schin 	    case ':':
116*4887Schin 		errormsg(SH_DICT,2, "%s", opt_info.arg);
117*4887Schin 		break;
118*4887Schin 	    case '?':
119*4887Schin 		errormsg(SH_DICT,ERROR_usage(2), "%s", opt_info.arg);
120*4887Schin 		break;
121*4887Schin 	}
122*4887Schin 	argv += opt_info.index;
123*4887Schin 	if(error_info.errors || !*argv)
124*4887Schin 		errormsg(SH_DICT,ERROR_usage(2),optusage((char*)0));
125*4887Schin 	return(whence(shp, argv, flags));
126*4887Schin }
127*4887Schin 
128*4887Schin static int whence(Shell_t *shp,char **argv, register int flags)
129*4887Schin {
130*4887Schin 	register const char *name;
131*4887Schin 	register Namval_t *np;
132*4887Schin 	register const char *cp;
133*4887Schin 	register int aflag,r=0;
134*4887Schin 	register const char *msg;
135*4887Schin 	int	tofree;
136*4887Schin 	Dt_t *root;
137*4887Schin 	Namval_t *nq;
138*4887Schin 	char *notused;
139*4887Schin #ifdef PATH_BFPATH
140*4887Schin 	Pathcomp_t *pp;
141*4887Schin #endif
142*4887Schin 	int notrack = 1;
143*4887Schin 	while(name= *argv++)
144*4887Schin 	{
145*4887Schin 		tofree=0;
146*4887Schin 		aflag = ((flags&A_FLAG)!=0);
147*4887Schin 		cp = 0;
148*4887Schin 		np = 0;
149*4887Schin #ifdef PATH_BFPATH
150*4887Schin 		pp = 0;
151*4887Schin #endif
152*4887Schin 		if(flags&P_FLAG)
153*4887Schin 			goto search;
154*4887Schin 		/* reserved words first */
155*4887Schin 		if(sh_lookup(name,shtab_reserved))
156*4887Schin 		{
157*4887Schin 			sfprintf(sfstdout,"%s%s\n",name,(flags&V_FLAG)?sh_translate(is_reserved):"");
158*4887Schin 			if(!aflag)
159*4887Schin 				continue;
160*4887Schin 			aflag++;
161*4887Schin 		}
162*4887Schin 		/* non-tracked aliases */
163*4887Schin 		if((np=nv_search(name,shp->alias_tree,0))
164*4887Schin 			&& !nv_isnull(np) && !(notrack=nv_isattr(np,NV_TAGGED))
165*4887Schin 			&& (cp=nv_getval(np)))
166*4887Schin 		{
167*4887Schin 			if(flags&V_FLAG)
168*4887Schin 			{
169*4887Schin 				if(nv_isattr(np,NV_EXPORT))
170*4887Schin 					msg = sh_translate(is_xalias);
171*4887Schin 				else
172*4887Schin 					msg = sh_translate(is_alias);
173*4887Schin 				sfprintf(sfstdout,msg,name);
174*4887Schin 			}
175*4887Schin 			sfputr(sfstdout,sh_fmtq(cp),'\n');
176*4887Schin 			if(!aflag)
177*4887Schin 				continue;
178*4887Schin 			cp = 0;
179*4887Schin 			aflag++;
180*4887Schin 		}
181*4887Schin 		/* built-ins and functions next */
182*4887Schin 		root = (flags&F_FLAG)?shp->bltin_tree:shp->fun_tree;
183*4887Schin 		if(np= nv_bfsearch(name, root, &nq, &notused))
184*4887Schin 		{
185*4887Schin 			if(is_abuiltin(np) && nv_isnull(np))
186*4887Schin 				goto search;
187*4887Schin 			cp = "";
188*4887Schin 			if(flags&V_FLAG)
189*4887Schin 			{
190*4887Schin 				if(nv_isnull(np))
191*4887Schin 					cp = sh_translate(is_ufunction);
192*4887Schin 				else if(is_abuiltin(np))
193*4887Schin 					cp = sh_translate(is_builtin);
194*4887Schin 				else
195*4887Schin 					cp = sh_translate(is_function);
196*4887Schin 			}
197*4887Schin 			sfprintf(sfstdout,"%s%s\n",name,cp);
198*4887Schin 			if(!aflag)
199*4887Schin 				continue;
200*4887Schin 			cp = 0;
201*4887Schin 			aflag++;
202*4887Schin 		}
203*4887Schin 	search:
204*4887Schin 		if(sh_isstate(SH_DEFPATH))
205*4887Schin 		{
206*4887Schin 			cp=0;
207*4887Schin 			notrack=1;
208*4887Schin 		}
209*4887Schin #ifdef PATH_BFPATH
210*4887Schin 		if(path_search(name,pp,2))
211*4887Schin 			cp = name;
212*4887Schin 		else
213*4887Schin 		{
214*4887Schin 			cp = stakptr(PATH_OFFSET);
215*4887Schin 			if(*cp==0)
216*4887Schin 				cp = 0;
217*4887Schin 			else if(*cp!='/')
218*4887Schin 			{
219*4887Schin 				cp = path_fullname(cp);
220*4887Schin 				tofree=1;
221*4887Schin 			}
222*4887Schin 		}
223*4887Schin #else
224*4887Schin 		if(path_search(name,cp,2))
225*4887Schin 			cp = name;
226*4887Schin 		else
227*4887Schin 			cp = shp->lastpath;
228*4887Schin 		shp->lastpath = 0;
229*4887Schin #endif
230*4887Schin 		if(cp)
231*4887Schin 		{
232*4887Schin 			if(flags&V_FLAG)
233*4887Schin 			{
234*4887Schin 				if(*cp!= '/')
235*4887Schin 				{
236*4887Schin #ifdef PATH_BFPATH
237*4887Schin 					if(!np && (np=nv_search(name,shp->track_tree,0)))
238*4887Schin 						sfprintf(sfstdout,"%s %s %s/%s\n",name,sh_translate(is_talias),path_pwd(0),cp);
239*4887Schin 					else if(!np || nv_isnull(np))
240*4887Schin #else
241*4887Schin 					if(!np || nv_isnull(np))
242*4887Schin #endif
243*4887Schin 						sfprintf(sfstdout,"%s%s\n",name,sh_translate(is_ufunction));
244*4887Schin 					continue;
245*4887Schin 				}
246*4887Schin 				sfputr(sfstdout,sh_fmtq(name),' ');
247*4887Schin 				/* built-in version of program */
248*4887Schin 				if(*cp=='/' && (np=nv_search(cp,shp->bltin_tree,0)))
249*4887Schin 					msg = sh_translate(is_builtver);
250*4887Schin 				/* tracked aliases next */
251*4887Schin 				else if(!notrack || strchr(name,'/'))
252*4887Schin 					msg = sh_translate("is");
253*4887Schin 				else
254*4887Schin 					msg = sh_translate(is_talias);
255*4887Schin 				sfputr(sfstdout,msg,' ');
256*4887Schin 			}
257*4887Schin 			sfputr(sfstdout,sh_fmtq(cp),'\n');
258*4887Schin 			if(tofree)
259*4887Schin 				free((char*)cp);
260*4887Schin 		}
261*4887Schin 		else if(aflag<=1)
262*4887Schin 		{
263*4887Schin 			r |= 1;
264*4887Schin 			if(flags&V_FLAG)
265*4887Schin 			{
266*4887Schin 				sfprintf(sfstdout,sh_translate(e_found),sh_fmtq(name));
267*4887Schin 				sfputc(sfstdout,'\n');
268*4887Schin 			}
269*4887Schin 		}
270*4887Schin 	}
271*4887Schin 	return(r);
272*4887Schin }
273*4887Schin 
274