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