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, ¬used))
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