Use getopt() to parse the command line. We need to be able to
intersperse env variables and options yet still honor "--"" which complicates things slightly.
This commit is contained in:
145
sudo.c
145
sudo.c
@@ -157,6 +157,10 @@ static char *runas_user;
|
|||||||
static char *runas_group;
|
static char *runas_group;
|
||||||
static struct sudo_nss_list *snl;
|
static struct sudo_nss_list *snl;
|
||||||
|
|
||||||
|
/* For getopt(3) */
|
||||||
|
extern char *optarg;
|
||||||
|
extern int optind;
|
||||||
|
|
||||||
int
|
int
|
||||||
main(argc, argv, envp)
|
main(argc, argv, envp)
|
||||||
int argc;
|
int argc;
|
||||||
@@ -803,7 +807,9 @@ set_cmnd(sudo_mode)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Command line argument parsing, can't use getopt(3) due to optional args.
|
* Command line argument parsing.
|
||||||
|
* Sets NewArgc and NewArgv which corresponds to the argc/argv we'll use
|
||||||
|
* for the command to be run (if we are running one).
|
||||||
*/
|
*/
|
||||||
static int
|
static int
|
||||||
parse_args(argc, argv)
|
parse_args(argc, argv)
|
||||||
@@ -812,9 +818,7 @@ parse_args(argc, argv)
|
|||||||
{
|
{
|
||||||
int rval = MODE_RUN; /* what mode is sudo to be run in? */
|
int rval = MODE_RUN; /* what mode is sudo to be run in? */
|
||||||
int excl = 0; /* exclusive arg, no others allowed */
|
int excl = 0; /* exclusive arg, no others allowed */
|
||||||
|
int ch;
|
||||||
NewArgv = argv + 1;
|
|
||||||
NewArgc = argc - 1;
|
|
||||||
|
|
||||||
/* First, check to see if we were invoked as "sudoedit". */
|
/* First, check to see if we were invoked as "sudoedit". */
|
||||||
if (strcmp(getprogname(), "sudoedit") == 0) {
|
if (strcmp(getprogname(), "sudoedit") == 0) {
|
||||||
@@ -823,83 +827,51 @@ parse_args(argc, argv)
|
|||||||
} else
|
} else
|
||||||
rval = MODE_RUN;
|
rval = MODE_RUN;
|
||||||
|
|
||||||
while (NewArgc > 0) {
|
/* Returns true if the last option string was "--" */
|
||||||
if (NewArgv[0][0] == '-') {
|
#define got_end_of_args (optind > 1 && argv[optind - 1][0] == '-' && \
|
||||||
if (NewArgv[0][1] != '\0' && NewArgv[0][2] != '\0' &&
|
argv[optind - 1][1] == '-' && argv[optind - 1][2] == '\0')
|
||||||
NewArgv[0][2] != 'l') {
|
|
||||||
warningx("please use single character options");
|
|
||||||
usage(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
switch (NewArgv[0][1]) {
|
/* Returns true if next option is an environment variable */
|
||||||
|
#define is_envar (optind < argc && argv[optind][0] != '/' && \
|
||||||
|
strchr(argv[optind], '=') != NULL)
|
||||||
|
|
||||||
|
for (;;) {
|
||||||
|
/*
|
||||||
|
* We disable arg permutation for GNU getopt().
|
||||||
|
* Some trickiness is required to allow environment variables
|
||||||
|
* to be interspersed with command line options.
|
||||||
|
*/
|
||||||
|
if ((ch = getopt(argc, argv, "+Aa:bC:c:Eeg:HhiKkLlPp:r:Sst:Uu:Vv")) != -1) {
|
||||||
|
switch (ch) {
|
||||||
case 'A':
|
case 'A':
|
||||||
SET(tgetpass_flags, TGP_ASKPASS);
|
SET(tgetpass_flags, TGP_ASKPASS);
|
||||||
break;
|
break;
|
||||||
case 'p':
|
case 'p':
|
||||||
/* Must have an associated prompt. */
|
user_prompt = optarg;
|
||||||
if (NewArgv[1] == NULL)
|
|
||||||
usage(1);
|
|
||||||
|
|
||||||
user_prompt = NewArgv[1];
|
|
||||||
def_passprompt_override = TRUE;
|
def_passprompt_override = TRUE;
|
||||||
|
|
||||||
NewArgc--;
|
|
||||||
NewArgv++;
|
|
||||||
break;
|
break;
|
||||||
case 'u':
|
case 'u':
|
||||||
/* Must have an associated runas user. */
|
runas_user = optarg;
|
||||||
if (NewArgv[1] == NULL)
|
|
||||||
usage(1);
|
|
||||||
|
|
||||||
runas_user = NewArgv[1];
|
|
||||||
|
|
||||||
NewArgc--;
|
|
||||||
NewArgv++;
|
|
||||||
break;
|
break;
|
||||||
case 'g':
|
case 'g':
|
||||||
/* Must have an associated runas group. */
|
runas_group = optarg;
|
||||||
if (NewArgv[1] == NULL)
|
|
||||||
usage(1);
|
|
||||||
|
|
||||||
runas_group = NewArgv[1];
|
|
||||||
|
|
||||||
NewArgc--;
|
|
||||||
NewArgv++;
|
|
||||||
break;
|
break;
|
||||||
#ifdef HAVE_BSD_AUTH_H
|
#ifdef HAVE_BSD_AUTH_H
|
||||||
case 'a':
|
case 'a':
|
||||||
/* Must have an associated authentication style. */
|
login_style = optarg;
|
||||||
if (NewArgv[1] == NULL)
|
|
||||||
usage(1);
|
|
||||||
|
|
||||||
login_style = NewArgv[1];
|
|
||||||
|
|
||||||
NewArgc--;
|
|
||||||
NewArgv++;
|
|
||||||
break;
|
break;
|
||||||
#endif
|
#endif
|
||||||
#ifdef HAVE_LOGIN_CAP_H
|
#ifdef HAVE_LOGIN_CAP_H
|
||||||
case 'c':
|
case 'c':
|
||||||
/* Must have an associated login class. */
|
login_class = optarg;
|
||||||
if (NewArgv[1] == NULL)
|
|
||||||
usage(1);
|
|
||||||
|
|
||||||
login_class = NewArgv[1];
|
|
||||||
def_use_loginclass = TRUE;
|
def_use_loginclass = TRUE;
|
||||||
|
|
||||||
NewArgc--;
|
|
||||||
NewArgv++;
|
|
||||||
break;
|
break;
|
||||||
#endif
|
#endif
|
||||||
case 'C':
|
case 'C':
|
||||||
if (NewArgv[1] == NULL)
|
if ((user_closefrom = atoi(optarg)) < 3) {
|
||||||
usage(1);
|
|
||||||
if ((user_closefrom = atoi(NewArgv[1])) < 3) {
|
|
||||||
warningx("the argument to -C must be at least 3");
|
warningx("the argument to -C must be at least 3");
|
||||||
usage(1);
|
usage(1);
|
||||||
}
|
}
|
||||||
NewArgc--;
|
|
||||||
NewArgv++;
|
|
||||||
break;
|
break;
|
||||||
case 'b':
|
case 'b':
|
||||||
SET(rval, MODE_BACKGROUND);
|
SET(rval, MODE_BACKGROUND);
|
||||||
@@ -943,10 +915,10 @@ parse_args(argc, argv)
|
|||||||
break;
|
break;
|
||||||
case 'l':
|
case 'l':
|
||||||
rval = MODE_LIST;
|
rval = MODE_LIST;
|
||||||
if (excl && excl != 'l')
|
if (excl == 'l')
|
||||||
usage_excl(1);
|
|
||||||
if (NewArgv[0][2] == 'l' || excl == 'l')
|
|
||||||
long_list = 1;
|
long_list = 1;
|
||||||
|
else if (excl)
|
||||||
|
usage_excl(1);
|
||||||
excl = 'l';
|
excl = 'l';
|
||||||
break;
|
break;
|
||||||
case 'V':
|
case 'V':
|
||||||
@@ -977,65 +949,42 @@ parse_args(argc, argv)
|
|||||||
SET(tgetpass_flags, TGP_STDIN);
|
SET(tgetpass_flags, TGP_STDIN);
|
||||||
break;
|
break;
|
||||||
case 'U':
|
case 'U':
|
||||||
/* Must have an associated list user. */
|
if ((list_pw = sudo_getpwnam(optarg)) == NULL)
|
||||||
if (NewArgv[1] == NULL)
|
errorx(1, "unknown user: %s", optarg);
|
||||||
usage(1);
|
|
||||||
if ((list_pw = sudo_getpwnam(NewArgv[1])) == NULL)
|
|
||||||
errorx(1, "unknown user: %s", NewArgv[1]);
|
|
||||||
NewArgc--;
|
|
||||||
NewArgv++;
|
|
||||||
break;
|
break;
|
||||||
case 'E':
|
case 'E':
|
||||||
SET(rval, MODE_PRESERVE_ENV);
|
SET(rval, MODE_PRESERVE_ENV);
|
||||||
break;
|
break;
|
||||||
#ifdef HAVE_SELINUX
|
#ifdef HAVE_SELINUX
|
||||||
case 'r':
|
case 'r':
|
||||||
/* Must have an associated SELinux role. */
|
user_role = optarg;
|
||||||
if (NewArgv[1] == NULL)
|
|
||||||
usage(1);
|
|
||||||
|
|
||||||
user_role = NewArgv[1];
|
|
||||||
|
|
||||||
NewArgc--;
|
|
||||||
NewArgv++;
|
|
||||||
break;
|
break;
|
||||||
case 't':
|
case 't':
|
||||||
/* Must have an associated SELinux type. */
|
user_type = optarg;
|
||||||
if (NewArgv[1] == NULL)
|
|
||||||
usage(1);
|
|
||||||
|
|
||||||
user_type = NewArgv[1];
|
|
||||||
|
|
||||||
NewArgc--;
|
|
||||||
NewArgv++;
|
|
||||||
break;
|
break;
|
||||||
#endif
|
#endif
|
||||||
case '-':
|
|
||||||
NewArgc--;
|
|
||||||
NewArgv++;
|
|
||||||
goto args_done;
|
|
||||||
case '\0':
|
|
||||||
warningx("`-' requires an argument");
|
|
||||||
usage(1);
|
|
||||||
default:
|
default:
|
||||||
warningx("illegal option `%s'", NewArgv[0]);
|
|
||||||
usage(1);
|
usage(1);
|
||||||
}
|
}
|
||||||
} else if (NewArgv[0][0] != '/' && strchr(NewArgv[0], '=') != NULL) {
|
} else if (!got_end_of_args && is_envar) {
|
||||||
/* Could be an environment variable. */
|
|
||||||
struct list_member *ev;
|
struct list_member *ev;
|
||||||
|
|
||||||
|
/* Store environment variable. */
|
||||||
ev = emalloc(sizeof(*ev));
|
ev = emalloc(sizeof(*ev));
|
||||||
ev->value = NewArgv[0];
|
ev->value = argv[optind];
|
||||||
ev->next = sudo_user.env_vars;
|
ev->next = sudo_user.env_vars;
|
||||||
sudo_user.env_vars = ev;
|
sudo_user.env_vars = ev;
|
||||||
|
|
||||||
|
/* Crank optind and resume getopt. */
|
||||||
|
optind++;
|
||||||
} else {
|
} else {
|
||||||
/* Not an arg */
|
/* Not an option or an environment variable -- we're done. */
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
NewArgc--;
|
|
||||||
NewArgv++;
|
|
||||||
}
|
}
|
||||||
args_done:
|
|
||||||
|
NewArgc = argc - optind;
|
||||||
|
NewArgv = argv + optind;
|
||||||
|
|
||||||
if (NewArgc > 0 && rval == MODE_LIST)
|
if (NewArgc > 0 && rval == MODE_LIST)
|
||||||
rval = MODE_CHECK;
|
rval = MODE_CHECK;
|
||||||
|
Reference in New Issue
Block a user