Add the POSIX options -v and -V to the 'command' builtin. Both describe the

type of their argument, if it is a shell function, an alias, a builtin, etc.
-V is more verbose than -v.

PR:	77259, 84539
This commit is contained in:
Stefan Farfeleder 2005-10-28 18:37:09 +00:00
parent df19ed6a02
commit b2f153feaf
3 changed files with 67 additions and 13 deletions

View File

@ -976,6 +976,7 @@ commandcmd(int argc, char **argv)
struct strlist *sp;
char *path;
int ch;
int cmd = -1;
for (sp = cmdenviron; sp ; sp = sp->next)
setvareq(sp->text, VEXPORT|VSTACK);
@ -983,11 +984,17 @@ commandcmd(int argc, char **argv)
optind = optreset = 1;
opterr = 0;
while ((ch = getopt(argc, argv, "p")) != -1) {
while ((ch = getopt(argc, argv, "pvV")) != -1) {
switch (ch) {
case 'p':
path = stdpath;
break;
case 'v':
cmd = TYPECMD_SMALLV;
break;
case 'V':
cmd = TYPECMD_BIGV;
break;
case '?':
default:
error("unknown option: -%c", optopt);
@ -996,6 +1003,11 @@ commandcmd(int argc, char **argv)
argc -= optind;
argv += optind;
if (cmd != -1) {
if (argc != 1)
error("wrong number of arguments");
return typecmd_impl(2, argv - 1, cmd);
}
if (argc != 0) {
old = handler;
handler = &loc;

View File

@ -705,11 +705,12 @@ unsetfunc(char *name)
}
/*
* Locate and print what a word is...
* Shared code for the following builtin commands:
* type, command -v, command -V
*/
int
typecmd(int argc, char **argv)
typecmd_impl(int argc, char **argv, int cmd)
{
struct cmdentry entry;
struct tblentry *cmdp;
@ -720,20 +721,28 @@ typecmd(int argc, char **argv)
extern char *const parsekwd[];
for (i = 1; i < argc; i++) {
out1str(argv[i]);
if (cmd != TYPECMD_SMALLV)
out1str(argv[i]);
/* First look at the keywords */
for (pp = (char **)parsekwd; *pp; pp++)
if (**pp == *argv[i] && equal(*pp, argv[i]))
break;
if (*pp) {
out1str(" is a shell keyword\n");
if (cmd == TYPECMD_SMALLV)
out1fmt("%s\n", argv[i]);
else
out1str(" is a shell keyword\n");
continue;
}
/* Then look at the aliases */
if ((ap = lookupalias(argv[i], 1)) != NULL) {
out1fmt(" is an alias for %s\n", ap->val);
if (cmd == TYPECMD_SMALLV)
out1fmt("alias %s='%s'\n", argv[i], ap->val);
else
out1fmt(" is an alias for %s\n", ap->val);
continue;
}
@ -756,29 +765,55 @@ typecmd(int argc, char **argv)
name = padvance(&path, argv[i]);
stunalloc(name);
} while (--j >= 0);
out1fmt(" is%s %s\n",
cmdp ? " a tracked alias for" : "", name);
if (cmd == TYPECMD_SMALLV)
out1fmt("%s\n", name);
else
out1fmt(" is%s %s\n",
(cmdp && cmd == TYPECMD_TYPE) ?
" a tracked alias for" : "",
name);
} else {
if (access(argv[i], X_OK) == 0)
out1fmt(" is %s\n", argv[i]);
if (access(argv[i], X_OK) == 0) {
if (cmd == TYPECMD_SMALLV)
out1fmt("%s\n", argv[i]);
else
out1fmt(" is %s\n", argv[i]);
}
else
out1fmt(": %s\n", strerror(errno));
}
break;
}
case CMDFUNCTION:
out1str(" is a shell function\n");
if (cmd == TYPECMD_SMALLV)
out1fmt("%s\n", argv[i]);
else
out1str(" is a shell function\n");
break;
case CMDBUILTIN:
out1str(" is a shell builtin\n");
if (cmd == TYPECMD_SMALLV)
out1fmt("%s\n", argv[i]);
else
out1str(" is a shell builtin\n");
break;
default:
out1str(": not found\n");
if (cmd != TYPECMD_SMALLV)
out1str(": not found\n");
error |= 127;
break;
}
}
return error;
}
/*
* Locate and print what a word is...
*/
int
typecmd(int argc, char **argv)
{
return typecmd_impl(argc, argv, TYPECMD_TYPE);
}

View File

@ -39,6 +39,12 @@
#define CMDBUILTIN 1 /* command is a shell builtin */
#define CMDFUNCTION 2 /* command is a shell function */
/* values for typecmd_impl's third parameter */
enum {
TYPECMD_SMALLV, /* command -v */
TYPECMD_BIGV, /* command -V */
TYPECMD_TYPE /* type */
};
struct cmdentry {
int cmdtype;
@ -63,5 +69,6 @@ void deletefuncs(void);
void addcmdentry(char *, struct cmdentry *);
void defun(char *, union node *);
int unsetfunc(char *);
int typecmd_impl(int, char **, int);
int typecmd(int, char **);
void clearcmdentry(int);