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