Home | History | Annotate | Download | only in bltins
      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 (at) 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, &notused))
    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