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