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