/*********************************************************************** * * * This software is part of the ast package * * Copyright (c) 1982-2008 AT&T Intellectual Property * * and is licensed under the * * Common Public License, Version 1.0 * * by AT&T Intellectual Property * * * * A copy of the License is available at * * http://www.opensource.org/licenses/cpl1.0.txt * * (with md5 checksum 059e8cd6165cb4c31e351f2b69388fd9) * * * * Information and Software Systems Research * * AT&T Research * * Florham Park NJ * * * * David Korn * * * ***********************************************************************/ #pragma prototyped /* * command [-pvVx] name [arg...] * whence [-afvp] name... * * David Korn * AT&T Labs * */ #include "defs.h" #include #include "shtable.h" #include "name.h" #include "path.h" #include "shlex.h" #include "builtins.h" #define P_FLAG 1 #define V_FLAG 2 #define A_FLAG 4 #define F_FLAG 010 #define X_FLAG 020 #define Q_FLAG 040 static int whence(Shell_t *,char**, int); /* * command is called with argc==0 when checking for -V or -v option * In this case return 0 when -v or -V or unknown option, otherwise * the shift count to the command is returned */ int b_command(register int argc,char *argv[],void *extra) { register int n, flags=0; register Shell_t *shp = ((Shbltin_t*)extra)->shp; opt_info.index = opt_info.offset = 0; while((n = optget(argv,sh_optcommand))) switch(n) { case 'p': if(sh_isoption(SH_RESTRICTED)) errormsg(SH_DICT,ERROR_exit(1),e_restricted,"-p"); sh_onstate(SH_DEFPATH); break; case 'v': flags |= X_FLAG; break; case 'V': flags |= V_FLAG; break; case 'x': shp->xargexit = 1; break; case ':': if(argc==0) return(0); errormsg(SH_DICT,2, "%s", opt_info.arg); break; case '?': if(argc==0) return(0); errormsg(SH_DICT,ERROR_usage(2), "%s", opt_info.arg); break; } if(argc==0) return(flags?0:opt_info.index); argv += opt_info.index; if(error_info.errors || !*argv) errormsg(SH_DICT,ERROR_usage(2),"%s", optusage((char*)0)); return(whence(shp,argv, flags)); } /* * for the whence command */ int b_whence(int argc,char *argv[],void *extra) { register int flags=0, n; register Shell_t *shp = ((Shbltin_t*)extra)->shp; NOT_USED(argc); if(*argv[0]=='t') flags = V_FLAG; while((n = optget(argv,sh_optwhence))) switch(n) { case 'a': flags |= A_FLAG; /* FALL THRU */ case 'v': flags |= V_FLAG; break; case 'f': flags |= F_FLAG; break; case 'p': flags |= P_FLAG; flags &= ~V_FLAG; break; case 'q': flags |= Q_FLAG; break; case ':': errormsg(SH_DICT,2, "%s", opt_info.arg); break; case '?': errormsg(SH_DICT,ERROR_usage(2), "%s", opt_info.arg); break; } argv += opt_info.index; if(error_info.errors || !*argv) errormsg(SH_DICT,ERROR_usage(2),optusage((char*)0)); return(whence(shp, argv, flags)); } static int whence(Shell_t *shp,char **argv, register int flags) { register const char *name; register Namval_t *np; register const char *cp; register int aflag,r=0; register const char *msg; int tofree; Dt_t *root; Namval_t *nq; char *notused; Pathcomp_t *pp=0; int notrack = 1; if(flags&Q_FLAG) flags &= ~A_FLAG; while(name= *argv++) { tofree=0; aflag = ((flags&A_FLAG)!=0); cp = 0; np = 0; if(flags&P_FLAG) goto search; if(flags&Q_FLAG) goto bltins; /* reserved words first */ if(sh_lookup(name,shtab_reserved)) { sfprintf(sfstdout,"%s%s\n",name,(flags&V_FLAG)?sh_translate(is_reserved):""); if(!aflag) continue; aflag++; } /* non-tracked aliases */ if((np=nv_search(name,shp->alias_tree,0)) && !nv_isnull(np) && !(notrack=nv_isattr(np,NV_TAGGED)) && (cp=nv_getval(np))) { if(flags&V_FLAG) { if(nv_isattr(np,NV_EXPORT)) msg = sh_translate(is_xalias); else msg = sh_translate(is_alias); sfprintf(sfstdout,msg,name); } sfputr(sfstdout,sh_fmtq(cp),'\n'); if(!aflag) continue; cp = 0; aflag++; } /* built-ins and functions next */ bltins: root = (flags&F_FLAG)?shp->bltin_tree:shp->fun_tree; if(np= nv_bfsearch(name, root, &nq, ¬used)) { if(is_abuiltin(np) && nv_isnull(np)) goto search; cp = ""; if(flags&V_FLAG) { if(nv_isnull(np)) cp = sh_translate(is_ufunction); else if(is_abuiltin(np)) { if(nv_isattr(np,BLT_SPC)) cp = sh_translate(is_spcbuiltin); else cp = sh_translate(is_builtin); } else cp = sh_translate(is_function); } if(flags&Q_FLAG) continue; sfprintf(sfstdout,"%s%s\n",name,cp); if(!aflag) continue; cp = 0; aflag++; } search: if(sh_isstate(SH_DEFPATH)) { cp=0; notrack=1; } do { if(path_search(name,&pp,2+(aflag>1))) cp = name; else { cp = stakptr(PATH_OFFSET); if(*cp==0) cp = 0; else if(*cp!='/') { cp = path_fullname(cp); tofree=1; } } if(flags&Q_FLAG) r |= !cp; else if(cp) { if(flags&V_FLAG) { if(*cp!= '/') { if(!np && (np=nv_search(name,shp->track_tree,0))) sfprintf(sfstdout,"%s %s %s/%s\n",name,sh_translate(is_talias),path_pwd(0),cp); else if(!np || nv_isnull(np)) sfprintf(sfstdout,"%s%s\n",name,sh_translate(is_ufunction)); continue; } sfputr(sfstdout,sh_fmtq(name),' '); /* built-in version of program */ if(*cp=='/' && (np=nv_search(cp,shp->bltin_tree,0))) msg = sh_translate(is_builtver); /* tracked aliases next */ else if(aflag>1 || !notrack || strchr(name,'/')) msg = sh_translate("is"); else msg = sh_translate(is_talias); sfputr(sfstdout,msg,' '); } sfputr(sfstdout,sh_fmtq(cp),'\n'); if(aflag) { if(aflag<=1) aflag++; if (pp) pp = pp->next; } else pp = 0; if(tofree) free((char*)cp); } else if(aflag<=1) { r |= 1; if(flags&V_FLAG) errormsg(SH_DICT,ERROR_exit(0),e_found,sh_fmtq(name)); } } while(pp); } return(r); }