#pragma prototyped
#include "defs.h"
#include <error.h>
#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);
int b_command(register int argc,char *argv[],void *extra)
{
register int n, flags=0;
register Shell_t *shp = (Shell_t*)extra;
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));
}
int b_whence(int argc,char *argv[],void *extra)
{
register int flags=0, n;
register Shell_t *shp = (Shell_t*)extra;
NOT_USED(argc);
if(*argv[0]=='t')
flags = V_FLAG;
while((n = optget(argv,sh_optwhence))) switch(n)
{
case 'a':
flags |= A_FLAG;
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;
#ifdef PATH_BFPATH
Pathcomp_t *pp;
#endif
int notrack = 1;
if(flags&Q_FLAG)
flags &= ~A_FLAG;
while(name= *argv++)
{
tofree=0;
aflag = ((flags&A_FLAG)!=0);
cp = 0;
np = 0;
#ifdef PATH_BFPATH
pp = 0;
#endif
if(flags&P_FLAG)
goto search;
if(flags&Q_FLAG)
goto bltins;
if(sh_lookup(name,shtab_reserved))
{
sfprintf(sfstdout,"%s%s\n",name,(flags&V_FLAG)?sh_translate(is_reserved):"");
if(!aflag)
continue;
aflag++;
}
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++;
}
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))
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;
}
#ifdef PATH_BFPATH
if(path_search(name,pp,2))
cp = name;
else
{
cp = stakptr(PATH_OFFSET);
if(*cp==0)
cp = 0;
else if(*cp!='/')
{
cp = path_fullname(cp);
tofree=1;
}
}
#else
if(path_search(name,cp,2))
cp = name;
else
cp = shp->lastpath;
shp->lastpath = 0;
#endif
if(flags&Q_FLAG)
r |= !cp;
else if(cp)
{
if(flags&V_FLAG)
{
if(*cp!= '/')
{
#ifdef PATH_BFPATH
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))
#else
if(!np || nv_isnull(np))
#endif
sfprintf(sfstdout,"%s%s\n",name,sh_translate(is_ufunction));
continue;
}
sfputr(sfstdout,sh_fmtq(name),' ');
if(*cp=='/' && (np=nv_search(cp,shp->bltin_tree,0)))
msg = sh_translate(is_builtver);
else if(!notrack || strchr(name,'/'))
msg = sh_translate("is");
else
msg = sh_translate(is_talias);
sfputr(sfstdout,msg,' ');
}
sfputr(sfstdout,sh_fmtq(cp),'\n');
if(tofree)
free((char*)cp);
}
else if(aflag<=1)
{
r |= 1;
if(flags&V_FLAG)
{
sfprintf(sfstdout,sh_translate(e_found),sh_fmtq(name));
sfputc(sfstdout,'\n');
}
}
}
return(r);
}