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:
parent
df19ed6a02
commit
b2f153feaf
@ -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;
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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);
|
||||
|
Loading…
Reference in New Issue
Block a user