1 /*********************************************************************** 2 * * 3 * This software is part of the ast package * 4 * Copyright (c) 1982-2012 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 <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[],Shbltin_t *context) 53 { 54 register int n, flags=0; 55 register Shell_t *shp = context->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[],Shbltin_t *context) 96 { 97 register int flags=0, n; 98 register Shell_t *shp = context->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(shp,name,&pp,2+(aflag>1))) 224 { 225 cp = name; 226 if((flags&P_FLAG) && *cp!='/') 227 cp = 0; 228 } 229 else 230 { 231 cp = stakptr(PATH_OFFSET); 232 if(*cp==0) 233 cp = 0; 234 else if(*cp!='/') 235 { 236 cp = path_fullname(shp,cp); 237 tofree=1; 238 } 239 } 240 if(flags&Q_FLAG) 241 { 242 pp = 0; 243 r |= !cp; 244 } 245 else if(cp) 246 { 247 if(flags&V_FLAG) 248 { 249 if(*cp!= '/') 250 { 251 if(!np && (np=nv_search(name,shp->track_tree,0))) 252 sfprintf(sfstdout,"%s %s %s/%s\n",name,sh_translate(is_talias),path_pwd(shp,0),cp); 253 else if(!np || nv_isnull(np)) 254 sfprintf(sfstdout,"%s%s\n",name,sh_translate(is_ufunction)); 255 continue; 256 } 257 sfputr(sfstdout,sh_fmtq(name),' '); 258 /* built-in version of program */ 259 if(*cp=='/' && (np=nv_search(cp,shp->bltin_tree,0))) 260 msg = sh_translate(is_builtver); 261 /* tracked aliases next */ 262 else if(aflag>1 || !notrack || strchr(name,'/')) 263 msg = sh_translate("is"); 264 else 265 msg = sh_translate(is_talias); 266 sfputr(sfstdout,msg,' '); 267 } 268 sfputr(sfstdout,sh_fmtq(cp),'\n'); 269 if(aflag) 270 { 271 if(aflag<=1) 272 aflag++; 273 if (pp) 274 pp = pp->next; 275 } 276 else 277 pp = 0; 278 if(tofree) 279 { 280 free((char*)cp); 281 tofree = 0; 282 } 283 } 284 else if(aflag<=1) 285 { 286 r |= 1; 287 if(flags&V_FLAG) 288 errormsg(SH_DICT,ERROR_exit(0),e_found,sh_fmtq(name)); 289 } 290 } while(pp); 291 } 292 return(r); 293 } 294 295