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