1 /***********************************************************************
2 *                                                                      *
3 *               This software is part of the ast package               *
4 *          Copyright (c) 1982-2014 AT&T Intellectual Property          *
5 *                      and is licensed under the                       *
6 *                 Eclipse Public License, Version 1.0                  *
7 *                    by AT&T Intellectual Property                     *
8 *                                                                      *
9 *                A copy of the License is available at                 *
10 *          http://www.eclipse.org/org/documents/epl-v10.html           *
11 *         (with md5 checksum b35adb5213ca9657e911e9befb180842)         *
12 *                                                                      *
13 *              Information and Software Systems Research               *
14 *                            AT&T Research                             *
15 *                           Florham Park NJ                            *
16 *                                                                      *
17 *                    David Korn <dgkorn@gmail.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 #define Q_FLAG	040
44 #define T_FLAG	0100
45 
46 static int whence(Shell_t *,char**, int);
47 
48 /*
49  * command is called with argc==0 when checking for -V or -v option
50  * In this case return 0 when -v or -V or unknown option, otherwise
51  *   the shift count to the command is returned
52  */
b_command(register int argc,char * argv[],Shbltin_t * context)53 int	b_command(register int argc,char *argv[],Shbltin_t *context)
54 {
55 	register int n, flags=0;
56 	register Shell_t *shp = context->shp;
57 	opt_info.index = opt_info.offset = 0;
58 	while((n = optget(argv,sh_optcommand))) switch(n)
59 	{
60 	    case 'p':
61 		if(sh_isoption(shp,SH_RESTRICTED))
62 			 errormsg(SH_DICT,ERROR_exit(1),e_restricted,"-p");
63 		sh_onstate(shp,SH_DEFPATH);
64 		break;
65 	    case 'v':
66 		flags |= X_FLAG;
67 		break;
68 	    case 'V':
69 		flags |= V_FLAG;
70 		break;
71 	    case 'x':
72 		shp->xargexit = 1;
73 		break;
74 	    case ':':
75 		if(argc==0)
76 			return(0);
77 		errormsg(SH_DICT,2, "%s", opt_info.arg);
78 		break;
79 	    case '?':
80 		if(argc==0)
81 			return(0);
82 		errormsg(SH_DICT,ERROR_usage(2), "%s", opt_info.arg);
83 		break;
84 	}
85 	if(argc==0)
86 		return(flags?0:opt_info.index);
87 	argv += opt_info.index;
88 	if(error_info.errors || !*argv)
89 		errormsg(SH_DICT,ERROR_usage(2),"%s", optusage((char*)0));
90 	return(whence(shp,argv, flags));
91 }
92 
93 /*
94  *  for the whence command
95  */
b_whence(int argc,char * argv[],Shbltin_t * context)96 int	b_whence(int argc,char *argv[],Shbltin_t *context)
97 {
98 	register int flags=0, n;
99 	register Shell_t *shp = context->shp;
100 	NOT_USED(argc);
101 	if(*argv[0]=='t')
102 		flags = V_FLAG;
103 	while((n = optget(argv,sh_optwhence))) switch(n)
104 	{
105 	    case 't':
106 		flags |= T_FLAG;
107 		break;
108 	    case 'a':
109 		flags |= A_FLAG;
110 		/* FALL THRU */
111 	    case 'v':
112 		flags |= V_FLAG;
113 		break;
114 	    case 'f':
115 		flags |= F_FLAG;
116 		break;
117 	    case 'P':
118 	    case 'p':
119 		flags |= P_FLAG;
120 		flags &= ~V_FLAG;
121 		break;
122 	    case 'q':
123 		flags |= Q_FLAG;
124 		break;
125 	    case ':':
126 		errormsg(SH_DICT,2, "%s", opt_info.arg);
127 		break;
128 	    case '?':
129 		errormsg(SH_DICT,ERROR_usage(2), "%s", opt_info.arg);
130 		break;
131 	}
132 	argv += opt_info.index;
133 	if(error_info.errors || !*argv)
134 		errormsg(SH_DICT,ERROR_usage(2),optusage((char*)0));
135 	if(flags&T_FLAG)
136 		flags &= ~V_FLAG;
137 	return(whence(shp, argv, flags));
138 }
139 
whence(Shell_t * shp,char ** argv,register int flags)140 static int whence(Shell_t *shp,char **argv, register int flags)
141 {
142 	register const char *name;
143 	register Namval_t *np;
144 	register const char *cp;
145 	register int aflag,r=0;
146 	register const char *msg;
147 	int	tofree;
148 	Dt_t *root;
149 	Namval_t *nq;
150 	char *notused;
151 	Pathcomp_t *pp=0;
152 	int notrack = 1;
153 	if(flags&Q_FLAG)
154 		flags &= ~A_FLAG;
155 	while(name= *argv++)
156 	{
157 		tofree=0;
158 		aflag = ((flags&A_FLAG)!=0);
159 		cp = 0;
160 		np = 0;
161 		if(flags&P_FLAG)
162 			goto search;
163 		if(flags&Q_FLAG)
164 			goto bltins;
165 		/* reserved words first */
166 		if(sh_lookup(name,shtab_reserved))
167 		{
168 			if(flags&T_FLAG)
169 				sfprintf(sfstdout,"%s\n","keyword");
170 			else
171 				sfprintf(sfstdout,"%s%s\n",name,(flags&V_FLAG)?sh_translate(is_reserved):"");
172 			if(!aflag)
173 				continue;
174 			aflag++;
175 		}
176 		/* non-tracked aliases */
177 		if((np=nv_search(name,shp->alias_tree,0))
178 			&& !nv_isnull(np) && !(notrack=nv_isattr(np,NV_TAGGED))
179 			&& (cp=nv_getval(np)))
180 		{
181 			if(flags&V_FLAG)
182 			{
183 				if(nv_isattr(np,NV_EXPORT))
184 					msg = sh_translate(is_xalias);
185 				else
186 					msg = sh_translate(is_alias);
187 				sfprintf(sfstdout,msg,name);
188 			}
189 			if(flags&T_FLAG)
190 				sfputr(sfstdout,"alias",'\n');
191 			else
192 				sfputr(sfstdout,sh_fmtq(cp),'\n');
193 			if(!aflag)
194 				continue;
195 			cp = 0;
196 			aflag++;
197 		}
198 		/* built-ins and functions next */
199 	bltins:
200 		root = (flags&F_FLAG)?shp->bltin_tree:shp->fun_tree;
201 		if(np= nv_bfsearch(name, root, &nq, &notused))
202 		{
203 			if(is_abuiltin(np) && nv_isnull(np))
204 				goto search;
205 			cp = "";
206 			if(flags&(V_FLAG|T_FLAG))
207 			{
208 				if(nv_isnull(np))
209 					cp = is_ufunction;
210 				else if(is_abuiltin(np))
211 				{
212 					if(nv_isattr(np,BLT_SPC))
213 						cp = is_spcbuiltin;
214 					else
215 						cp = is_builtin;
216 				}
217 				else
218 					cp = is_function;
219 			}
220 			if(flags&Q_FLAG)
221 				continue;
222 			if(flags&T_FLAG)
223 			{
224 				if(cp==is_function || cp==is_ufunction)
225 					cp = "function";
226 				else  if(*name=='/')
227 					cp = "file";
228 				else
229 					cp = "builtin";
230 				sfputr(sfstdout,cp,'\n');
231 			}
232 			else
233 				sfprintf(sfstdout,"%s%s\n",name,sh_translate(cp));
234 			if(!aflag)
235 				continue;
236 			cp = 0;
237 			aflag++;
238 		}
239 	search:
240 		if(sh_isstate(shp,SH_DEFPATH))
241 		{
242 			cp=0;
243 			notrack=1;
244 		}
245 		do
246 		{
247 			if(path_search(shp,name,&pp,2+(aflag>1)))
248 			{
249 				cp = name;
250 				if((flags&P_FLAG) && *cp!='/')
251 					cp = 0;
252 			}
253 			else
254 			{
255 				cp = stakptr(PATH_OFFSET);
256 				if(*cp==0)
257 					cp = 0;
258 				else if(*cp!='/')
259 				{
260 					cp = path_fullname(shp,cp);
261 					tofree=1;
262 				}
263 			}
264 			if(flags&Q_FLAG)
265 			{
266 				pp = 0;
267 				r |= !cp;
268 			}
269 			else if(cp)
270 			{
271 				if(flags&V_FLAG)
272 				{
273 					if(*cp!= '/')
274 					{
275 						if(!np && (np=nv_search(name,shp->track_tree,0)))
276 							sfprintf(sfstdout,"%s %s %s/%s\n",name,sh_translate(is_talias),path_pwd(shp,0),cp);
277 						else if(!np || nv_isnull(np))
278 							sfprintf(sfstdout,"%s%s\n",name,sh_translate(is_ufunction));
279 						continue;
280 					}
281 					sfputr(sfstdout,sh_fmtq(name),' ');
282 					/* built-in version of program */
283 					if(*cp=='/' && (np=nv_search(cp,shp->bltin_tree,0)))
284 						msg = sh_translate(is_builtver);
285 					/* tracked aliases next */
286 					else if(aflag>1 || !notrack || strchr(name,'/'))
287 						msg = sh_translate("is");
288 					else
289 						msg = sh_translate(is_talias);
290 					sfputr(sfstdout,msg,' ');
291 				}
292 				if(flags&T_FLAG)
293 					sfputr(sfstdout,"file",'\n');
294 				else
295 					sfputr(sfstdout,sh_fmtq(cp),'\n');
296 				if(aflag)
297 				{
298 					if(aflag<=1)
299 						aflag++;
300 					if (pp)
301 						pp = pp->next;
302 				}
303 				else
304 					pp = 0;
305 				if(tofree)
306 				{
307 					free((char*)cp);
308 					tofree = 0;
309 				}
310 			}
311 			else if(aflag<=1)
312 			{
313 				r |= 1;
314 				if(flags&V_FLAG)
315 					 errormsg(SH_DICT,ERROR_exit(0),e_found,sh_fmtq(name));
316 			}
317 		} while(pp);
318 	}
319 	return(r);
320 }
321 
322