1 /*********************************************************************** 2 * * 3 * This software is part of the ast package * 4 * Copyright (c) 1982-2009 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 */ 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 */ 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 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