]> granicus.if.org Git - sudo/commitdiff
Move argument parsing into parse_args.c
authorTodd C. Miller <Todd.Miller@courtesan.com>
Fri, 4 Jun 2010 20:31:11 +0000 (16:31 -0400)
committerTodd C. Miller <Todd.Miller@courtesan.com>
Fri, 4 Jun 2010 20:31:11 +0000 (16:31 -0400)
--HG--
branch : 1.7

Makefile.in
parse_args.c [new file with mode: 0644]
sudo.c
sudo.h
sudo_usage.h.in

index 6143ff6afc3162fa2d6d3a4b3b1af48af216dea3..7259c3606935cdbd7ae1c447bdd43ccfe0f0b8e3 100644 (file)
@@ -107,12 +107,12 @@ SRCS = aix.c alias.c alloc.c audit.c boottime.c bsm_audit.c check.c \
        find_path.c fnmatch.c getcwd.c getprogname.c getspwuid.c gettime.c \
        glob.c goodpath.c gram.c gram.y interfaces.c iolog.c isblank.c lbuf.c \
        ldap.c list.c logging.c match.c mksiglist.c mkstemp.c memrchr.c \
-       nanosleep.c parse.c pwutil.c pty.c set_perms.c sigaction.c snprintf.c \
-       strcasecmp.c strerror.c strlcat.c strlcpy.c strsignal.c sudo.c \
-       sudo_noexec.c sudo_edit.c sudo_nss.c term.c testsudoers.c tgetpass.c \
-       toke.c toke.l tsgetgrpw.c utimes.c vasgroups.c visudo.c zero_bytes.c \
-       redblack.c selinux.c sesh.c sudoreplay.c getdate.c getdate.y getline.c \
-       timestr.c $(AUTH_SRCS)
+       nanosleep.c parse.c parse_args.c pwutil.c pty.c set_perms.c \
+       sigaction.c snprintf.c strcasecmp.c strerror.c strlcat.c strlcpy.c \
+       strsignal.c sudo.c sudo_noexec.c sudo_edit.c sudo_nss.c term.c \
+       testsudoers.c tgetpass.c toke.c toke.l tsgetgrpw.c utimes.c \
+       vasgroups.c visudo.c zero_bytes.c redblack.c selinux.c sesh.c \
+       sudoreplay.c getdate.c getdate.y getline.c timestr.c $(AUTH_SRCS)
 
 AUTH_SRCS = auth/afs.c auth/aix_auth.c auth/bsdauth.c auth/dce.c auth/fwtk.c \
            auth/kerb4.c auth/kerb5.c auth/pam.c auth/passwd.c auth/rfc1938.c \
@@ -133,8 +133,8 @@ COMMON_OBJS = alias.o alloc.o defaults.o error.o getline.o gram.o \
 
 SUDO_OBJS = $(AUTH_OBJS) @SUDO_OBJS@ audit.o boottime.o check.o env.o \
            exec.o getspwuid.o gettime.o goodpath.o fileops.o find_path.o \
-           interfaces.o lbuf.o logging.o parse.o set_perms.o sudo.o \
-           sudo_edit.o sudo_nss.o tgetpass.o
+           interfaces.o lbuf.o logging.o parse.o parse_args.o set_perms.o \
+           sudo.o sudo_edit.o sudo_nss.o tgetpass.o
 
 VISUDO_OBJS = visudo.o fileops.o gettime.o goodpath.o find_path.o
 
@@ -323,6 +323,8 @@ nanosleep.o: $(srcdir)/nanosleep.c $(srcdir)/compat.h config.h
        $(CC) -c $(CPPFLAGS) $(CFLAGS) $(DEFS) $(OPTIONS) $(srcdir)/nanosleep.c
 parse.o: $(srcdir)/parse.c $(SUDODEP) $(srcdir)/parse.h $(srcdir)/list.h $(devdir)/gram.h
        $(CC) -c $(CPPFLAGS) $(CFLAGS) $(DEFS) $(OPTIONS) $(srcdir)/parse.c
+parse_args.o: $(srcdir)/parse_args.c $(SUDODEP)
+       $(CC) -c $(CPPFLAGS) $(CFLAGS) $(DEFS) $(OPTIONS) $(srcdir)/parse_args.c
 pwutil.o: $(srcdir)/pwutil.c $(SUDODEP)
        $(CC) -c $(CPPFLAGS) $(CFLAGS) $(DEFS) $(OPTIONS) $(srcdir)/pwutil.c
 pty.o: $(srcdir)/pty.c $(SUDODEP)
diff --git a/parse_args.c b/parse_args.c
new file mode 100644 (file)
index 0000000..8c51c5e
--- /dev/null
@@ -0,0 +1,370 @@
+/*
+ * Copyright (c) 1993-1996, 1998-2010 Todd C. Miller <Todd.Miller@courtesan.com>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ * Sponsored in part by the Defense Advanced Research Projects
+ * Agency (DARPA) and Air Force Research Laboratory, Air Force
+ * Materiel Command, USAF, under agreement number F39502-99-1-0512.
+ */
+
+#include <config.h>
+
+#include <sys/types.h>
+#include <sys/param.h>
+
+#include <stdio.h>
+#ifdef STDC_HEADERS
+# include <stdlib.h>
+# include <stddef.h>
+#else
+# ifdef HAVE_STDLIB_H
+#  include <stdlib.h>
+# endif
+#endif /* STDC_HEADERS */
+#ifdef HAVE_STRING_H
+# if defined(HAVE_MEMORY_H) && !defined(STDC_HEADERS)
+#  include <memory.h>
+# endif
+# include <string.h>
+#else
+# ifdef HAVE_STRINGS_H
+#  include <strings.h>
+# endif
+#endif /* HAVE_STRING_H */
+#ifdef HAVE_UNISTD_H
+# include <unistd.h>
+#endif /* HAVE_UNISTD_H */
+#include <pwd.h>
+#include <grp.h>
+
+#include <sudo_usage.h>
+#include "sudo.h"
+#include "lbuf.h"
+
+/*
+ * Local functions
+ */
+static void usage_excl                 __P((int))
+                                           __attribute__((__noreturn__));
+
+/*
+ * For sudo.c
+ */
+extern int NewArgc;
+extern char **NewArgv;
+extern int user_closefrom;
+extern char *runas_user;
+extern char *runas_group;
+
+/* For getopt(3) */
+extern char *optarg;
+extern int optind;
+
+#ifdef HAVE_BSD_AUTH_H
+char *login_style;
+#endif /* HAVE_BSD_AUTH_H */
+
+/*
+ * 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).
+ */
+int
+parse_args(argc, argv)
+    int argc;
+    char **argv;
+{
+    int mode = 0;              /* what mode is sudo to be run in? */
+    int flags = 0;             /* mode flags */
+    int valid_flags, ch;
+
+    /* First, check to see if we were invoked as "sudoedit". */
+    if (strcmp(getprogname(), "sudoedit") == 0)
+       mode = MODE_EDIT;
+
+    /* Returns true if the last option string was "--" */
+#define got_end_of_args        (optind > 1 && argv[optind - 1][0] == '-' && \
+           argv[optind - 1][1] == '-' && argv[optind - 1][2] == '\0')
+
+    /* Returns true if next option is an environment variable */
+#define is_envar (optind < argc && argv[optind][0] != '/' && \
+           strchr(argv[optind], '=') != NULL)
+
+    /* Flags allowed when running a command */
+    valid_flags = MODE_BACKGROUND|MODE_PRESERVE_ENV|MODE_RESET_HOME|
+                 MODE_LOGIN_SHELL|MODE_INVALIDATE|MODE_NONINTERACTIVE|
+                 MODE_PRESERVE_GROUPS|MODE_SHELL;
+    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:HhiKkLlnPp:r:Sst:U:u:Vv")) != -1) {
+           switch (ch) {
+               case 'A':
+                   SET(tgetpass_flags, TGP_ASKPASS);
+                   break;
+#ifdef HAVE_BSD_AUTH_H
+               case 'a':
+                   login_style = optarg;
+                   break;
+#endif
+               case 'b':
+                   SET(flags, MODE_BACKGROUND);
+                   break;
+               case 'C':
+                   if ((user_closefrom = atoi(optarg)) < 3) {
+                       warningx("the argument to -C must be at least 3");
+                       usage(1);
+                   }
+                   break;
+#ifdef HAVE_LOGIN_CAP_H
+               case 'c':
+                   login_class = optarg;
+                   def_use_loginclass = TRUE;
+                   break;
+#endif
+               case 'E':
+                   SET(flags, MODE_PRESERVE_ENV);
+                   break;
+               case 'e':
+                   if (mode && mode != MODE_EDIT)
+                       usage_excl(1);
+                   mode = MODE_EDIT;
+                   valid_flags = MODE_INVALIDATE|MODE_NONINTERACTIVE;
+                   break;
+               case 'g':
+                   runas_group = optarg;
+                   break;
+               case 'H':
+                   SET(flags, MODE_RESET_HOME);
+                   break;
+               case 'h':
+                   if (mode && mode != MODE_HELP) {
+                       if (strcmp(getprogname(), "sudoedit") != 0)
+                           usage_excl(1);
+                   }
+                   mode = MODE_HELP;
+                   valid_flags = 0;
+                   break;
+               case 'i':
+                   SET(flags, MODE_LOGIN_SHELL);
+                   def_env_reset = TRUE;
+                   break;
+               case 'k':
+                   SET(flags, MODE_INVALIDATE);
+                   break;
+               case 'K':
+                   if (mode && mode != MODE_KILL)
+                       usage_excl(1);
+                   mode = MODE_KILL;
+                   valid_flags = 0;
+                   break;
+               case 'L':
+                   if (mode && mode != MODE_LISTDEFS)
+                       usage_excl(1);
+                   mode = MODE_LISTDEFS;
+                   valid_flags = MODE_INVALIDATE|MODE_NONINTERACTIVE;
+                   break;
+               case 'l':
+                   if (mode) {
+                       if (mode == MODE_LIST)
+                           long_list = 1;
+                       else
+                           usage_excl(1);
+                   }
+                   mode = MODE_LIST;
+                   valid_flags = MODE_INVALIDATE|MODE_NONINTERACTIVE;
+                   break;
+               case 'n':
+                   SET(flags, MODE_NONINTERACTIVE);
+                   break;
+               case 'P':
+                   SET(flags, MODE_PRESERVE_GROUPS);
+                   break;
+               case 'p':
+                   user_prompt = optarg;
+                   def_passprompt_override = TRUE;
+                   break;
+#ifdef HAVE_SELINUX
+               case 'r':
+                   user_role = optarg;
+                   break;
+               case 't':
+                   user_type = optarg;
+                   break;
+#endif
+               case 'S':
+                   SET(tgetpass_flags, TGP_STDIN);
+                   break;
+               case 's':
+                   SET(flags, MODE_SHELL);
+                   break;
+               case 'U':
+                   if ((list_pw = sudo_getpwnam(optarg)) == NULL)
+                       errorx(1, "unknown user: %s", optarg);
+                   break;
+               case 'u':
+                   runas_user = optarg;
+                   break;
+               case 'v':
+                   if (mode && mode != MODE_VALIDATE)
+                       usage_excl(1);
+                   mode = MODE_VALIDATE;
+                   valid_flags = MODE_INVALIDATE|MODE_NONINTERACTIVE;
+                   break;
+               case 'V':
+                   if (mode && mode != MODE_VERSION)
+                       usage_excl(1);
+                   mode = MODE_VERSION;
+                   valid_flags = 0;
+                   break;
+               default:
+                   usage(1);
+           }
+       } else if (!got_end_of_args && is_envar) {
+           struct list_member *ev;
+
+           /* Store environment variable. */
+           ev = emalloc(sizeof(*ev));
+           ev->value = argv[optind];
+           ev->next = sudo_user.env_vars;
+           sudo_user.env_vars = ev;
+
+           /* Crank optind and resume getopt. */
+           optind++;
+       } else {
+           /* Not an option or an environment variable -- we're done. */
+           break;
+       }
+    }
+
+    NewArgc = argc - optind;
+    NewArgv = argv + optind;
+
+    if (!mode) {
+       /* Defer -k mode setting until we know whether it is a flag or not */
+       if (ISSET(flags, MODE_INVALIDATE) && NewArgc == 0) {
+           mode = MODE_INVALIDATE;     /* -k by itself */
+           CLR(flags, MODE_INVALIDATE);
+           valid_flags = 0;
+       } else {
+           mode = MODE_RUN;            /* running a command */
+       }
+    }
+
+    if (NewArgc > 0 && mode == MODE_LIST)
+       mode = MODE_CHECK;
+
+    if (ISSET(flags, MODE_LOGIN_SHELL)) {
+       if (ISSET(flags, MODE_SHELL)) {
+           warningx("you may not specify both the `-i' and `-s' options");
+           usage(1);
+       }
+       if (ISSET(flags, MODE_PRESERVE_ENV)) {
+           warningx("you may not specify both the `-i' and `-E' options");
+           usage(1);
+       }
+       SET(flags, MODE_SHELL);
+    }
+    if ((flags & valid_flags) != flags)
+       usage(1);
+    if (mode == MODE_EDIT &&
+       (ISSET(flags, MODE_PRESERVE_ENV) || sudo_user.env_vars != NULL)) {
+       if (ISSET(mode, MODE_PRESERVE_ENV))
+           warningx("the `-E' option is not valid in edit mode");
+       if (sudo_user.env_vars != NULL)
+           warningx("you may not specify environment variables in edit mode");
+       usage(1);
+    }
+    if ((runas_user != NULL || runas_group != NULL) &&
+       !ISSET(mode, MODE_EDIT | MODE_RUN | MODE_CHECK | MODE_VALIDATE)) {
+       usage(1);
+    }
+    if (list_pw != NULL && mode != MODE_LIST && mode != MODE_CHECK) {
+       warningx("the `-U' option may only be used with the `-l' option");
+       usage(1);
+    }
+    if (ISSET(tgetpass_flags, TGP_STDIN) && ISSET(tgetpass_flags, TGP_ASKPASS)) {
+       warningx("the `-A' and `-S' options may not be used together");
+       usage(1);
+    }
+    if ((NewArgc == 0 && mode == MODE_EDIT) ||
+       (NewArgc > 0 && !ISSET(mode, MODE_RUN | MODE_EDIT | MODE_CHECK)))
+       usage(1);
+    if (NewArgc == 0 && mode == MODE_RUN && !ISSET(flags, MODE_SHELL))
+       SET(flags, (MODE_IMPLIED_SHELL | MODE_SHELL));
+
+    return(mode | flags);
+}
+
+static int
+usage_out(buf)
+    const char *buf;
+{
+    return fputs(buf, stderr);
+}
+
+/*
+ * Give usage message and exit.
+ * The actual usage strings are in sudo_usage.h for configure substitution.
+ */
+void
+usage(exit_val)
+    int exit_val;
+{
+    struct lbuf lbuf;
+    char *uvec[6];
+    int i, ulen;
+
+    /*
+     * Use usage vectors appropriate to the progname.
+     */
+    if (strcmp(getprogname(), "sudoedit") == 0) {
+       uvec[0] = SUDO_USAGE5 + 3;
+       uvec[1] = NULL;
+    } else {
+       uvec[0] = SUDO_USAGE1;
+       uvec[1] = SUDO_USAGE2;
+       uvec[2] = SUDO_USAGE3;
+       uvec[3] = SUDO_USAGE4;
+       uvec[4] = SUDO_USAGE5;
+       uvec[5] = NULL;
+    }
+
+    /*
+     * Print usage and wrap lines as needed, depending on the
+     * tty width.
+     */
+    ulen = (int)strlen(getprogname()) + 8;
+    lbuf_init(&lbuf, usage_out, ulen, NULL);
+    for (i = 0; uvec[i] != NULL; i++) {
+       lbuf_append(&lbuf, "usage: ", getprogname(), uvec[i], NULL);
+       lbuf_print(&lbuf);
+    }
+    lbuf_destroy(&lbuf);
+    exit(exit_val);
+}
+
+/*
+ * Tell which options are mutually exclusive and exit.
+ */
+static void
+usage_excl(exit_val)
+    int exit_val;
+{
+    warningx("Only one of the -e, -h, -i, -K, -l, -s, -v or -V options may be specified");
+    usage(exit_val);
+}
diff --git a/sudo.c b/sudo.c
index 4f04c4f1b6d6c63957d95a6726b9254a0a655e61..8d91e414859e4bef4694406cd4d31c7d74e704c0 100644 (file)
--- a/sudo.c
+++ b/sudo.c
  */
 static void init_vars                  __P((int, char **));
 static int set_cmnd                    __P((int));
-static int parse_args                  __P((int, char **));
 static void initial_setup              __P((void));
 static void set_loginclass             __P((struct passwd *));
 static void set_project                        __P((struct passwd *));
 static void set_runasgr                        __P((char *));
 static void set_runaspw                        __P((char *));
 static void show_version               __P((void));
-static void usage                      __P((int))
-                                           __attribute__((__noreturn__));
-static void usage_excl                 __P((int))
-                                           __attribute__((__noreturn__));
 static struct passwd *get_authpw       __P((void));
 extern int sudo_edit                   __P((int, char **, char **));
 extern void rebuild_env                        __P((int, int));
@@ -137,7 +132,7 @@ int run_command __P((const char *path, char *argv[], char *envp[], uid_t uid));
 int Argc, NewArgc;
 char **Argv, **NewArgv;
 char *prev_user;
-static int user_closefrom = -1;
+int user_closefrom = -1;
 struct sudo_user sudo_user;
 struct passwd *auth_pw, *list_pw;
 struct interface *interfaces;
@@ -154,12 +149,9 @@ static struct rlimit corelimit;
 #ifdef HAVE_LOGIN_CAP_H
 login_cap_t *lc;
 #endif /* HAVE_LOGIN_CAP_H */
-#ifdef HAVE_BSD_AUTH_H
-char *login_style;
-#endif /* HAVE_BSD_AUTH_H */
 sigaction_t saved_sa_int, saved_sa_quit, saved_sa_tstp;
-static char *runas_user;
-static char *runas_group;
+char *runas_user;
+char *runas_group;
 static struct sudo_nss_list *snl;
 static int sudo_mode;
 
@@ -926,241 +918,6 @@ run_command(const char *path, char *argv[], char *envp[], uid_t uid)
     return(exitcode);
 }
 
-/*
- * 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
-parse_args(argc, argv)
-    int argc;
-    char **argv;
-{
-    int mode = 0;              /* what mode is sudo to be run in? */
-    int flags = 0;             /* mode flags */
-    int valid_flags, ch;
-
-    /* First, check to see if we were invoked as "sudoedit". */
-    if (strcmp(getprogname(), "sudoedit") == 0)
-       mode = MODE_EDIT;
-
-    /* Returns true if the last option string was "--" */
-#define got_end_of_args        (optind > 1 && argv[optind - 1][0] == '-' && \
-           argv[optind - 1][1] == '-' && argv[optind - 1][2] == '\0')
-
-    /* Returns true if next option is an environment variable */
-#define is_envar (optind < argc && argv[optind][0] != '/' && \
-           strchr(argv[optind], '=') != NULL)
-
-    /* Flags allowed when running a command */
-    valid_flags = MODE_BACKGROUND|MODE_PRESERVE_ENV|MODE_RESET_HOME|
-                 MODE_LOGIN_SHELL|MODE_INVALIDATE|MODE_NONINTERACTIVE|
-                 MODE_PRESERVE_GROUPS|MODE_SHELL;
-    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:HhiKkLlnPp:r:Sst:U:u:Vv")) != -1) {
-           switch (ch) {
-               case 'A':
-                   SET(tgetpass_flags, TGP_ASKPASS);
-                   break;
-#ifdef HAVE_BSD_AUTH_H
-               case 'a':
-                   login_style = optarg;
-                   break;
-#endif
-               case 'b':
-                   SET(flags, MODE_BACKGROUND);
-                   break;
-               case 'C':
-                   if ((user_closefrom = atoi(optarg)) < 3) {
-                       warningx("the argument to -C must be at least 3");
-                       usage(1);
-                   }
-                   break;
-#ifdef HAVE_LOGIN_CAP_H
-               case 'c':
-                   login_class = optarg;
-                   def_use_loginclass = TRUE;
-                   break;
-#endif
-               case 'E':
-                   SET(flags, MODE_PRESERVE_ENV);
-                   break;
-               case 'e':
-                   if (mode && mode != MODE_EDIT)
-                       usage_excl(1);
-                   mode = MODE_EDIT;
-                   valid_flags = MODE_INVALIDATE|MODE_NONINTERACTIVE;
-                   break;
-               case 'g':
-                   runas_group = optarg;
-                   break;
-               case 'H':
-                   SET(flags, MODE_RESET_HOME);
-                   break;
-               case 'h':
-                   if (mode && mode != MODE_HELP) {
-                       if (strcmp(getprogname(), "sudoedit") != 0)
-                           usage_excl(1);
-                   }
-                   mode = MODE_HELP;
-                   valid_flags = 0;
-                   break;
-               case 'i':
-                   SET(flags, MODE_LOGIN_SHELL);
-                   def_env_reset = TRUE;
-                   break;
-               case 'k':
-                   SET(flags, MODE_INVALIDATE);
-                   break;
-               case 'K':
-                   if (mode && mode != MODE_KILL)
-                       usage_excl(1);
-                   mode = MODE_KILL;
-                   valid_flags = 0;
-                   break;
-               case 'L':
-                   if (mode && mode != MODE_LISTDEFS)
-                       usage_excl(1);
-                   mode = MODE_LISTDEFS;
-                   valid_flags = MODE_INVALIDATE|MODE_NONINTERACTIVE;
-                   break;
-               case 'l':
-                   if (mode) {
-                       if (mode == MODE_LIST)
-                           long_list = 1;
-                       else
-                           usage_excl(1);
-                   }
-                   mode = MODE_LIST;
-                   valid_flags = MODE_INVALIDATE|MODE_NONINTERACTIVE;
-                   break;
-               case 'n':
-                   SET(flags, MODE_NONINTERACTIVE);
-                   break;
-               case 'P':
-                   SET(flags, MODE_PRESERVE_GROUPS);
-                   break;
-               case 'p':
-                   user_prompt = optarg;
-                   def_passprompt_override = TRUE;
-                   break;
-#ifdef HAVE_SELINUX
-               case 'r':
-                   user_role = optarg;
-                   break;
-               case 't':
-                   user_type = optarg;
-                   break;
-#endif
-               case 'S':
-                   SET(tgetpass_flags, TGP_STDIN);
-                   break;
-               case 's':
-                   SET(flags, MODE_SHELL);
-                   break;
-               case 'U':
-                   if ((list_pw = sudo_getpwnam(optarg)) == NULL)
-                       errorx(1, "unknown user: %s", optarg);
-                   break;
-               case 'u':
-                   runas_user = optarg;
-                   break;
-               case 'v':
-                   if (mode && mode != MODE_VALIDATE)
-                       usage_excl(1);
-                   mode = MODE_VALIDATE;
-                   valid_flags = MODE_INVALIDATE|MODE_NONINTERACTIVE;
-                   break;
-               case 'V':
-                   if (mode && mode != MODE_VERSION)
-                       usage_excl(1);
-                   mode = MODE_VERSION;
-                   valid_flags = 0;
-                   break;
-               default:
-                   usage(1);
-           }
-       } else if (!got_end_of_args && is_envar) {
-           struct list_member *ev;
-
-           /* Store environment variable. */
-           ev = emalloc(sizeof(*ev));
-           ev->value = argv[optind];
-           ev->next = sudo_user.env_vars;
-           sudo_user.env_vars = ev;
-
-           /* Crank optind and resume getopt. */
-           optind++;
-       } else {
-           /* Not an option or an environment variable -- we're done. */
-           break;
-       }
-    }
-
-    NewArgc = argc - optind;
-    NewArgv = argv + optind;
-
-    if (!mode) {
-       /* Defer -k mode setting until we know whether it is a flag or not */
-       if (ISSET(flags, MODE_INVALIDATE) && NewArgc == 0) {
-           mode = MODE_INVALIDATE;     /* -k by itself */
-           CLR(flags, MODE_INVALIDATE);
-           valid_flags = 0;
-       } else {
-           mode = MODE_RUN;            /* running a command */
-       }
-    }
-
-    if (NewArgc > 0 && mode == MODE_LIST)
-       mode = MODE_CHECK;
-
-    if (ISSET(flags, MODE_LOGIN_SHELL)) {
-       if (ISSET(flags, MODE_SHELL)) {
-           warningx("you may not specify both the `-i' and `-s' options");
-           usage(1);
-       }
-       if (ISSET(flags, MODE_PRESERVE_ENV)) {
-           warningx("you may not specify both the `-i' and `-E' options");
-           usage(1);
-       }
-       SET(flags, MODE_SHELL);
-    }
-    if ((flags & valid_flags) != flags)
-       usage(1);
-    if (mode == MODE_EDIT &&
-       (ISSET(flags, MODE_PRESERVE_ENV) || sudo_user.env_vars != NULL)) {
-       if (ISSET(mode, MODE_PRESERVE_ENV))
-           warningx("the `-E' option is not valid in edit mode");
-       if (sudo_user.env_vars != NULL)
-           warningx("you may not specify environment variables in edit mode");
-       usage(1);
-    }
-    if ((runas_user != NULL || runas_group != NULL) &&
-       !ISSET(mode, MODE_EDIT | MODE_RUN | MODE_CHECK | MODE_VALIDATE)) {
-       usage(1);
-    }
-    if (list_pw != NULL && mode != MODE_LIST && mode != MODE_CHECK) {
-       warningx("the `-U' option may only be used with the `-l' option");
-       usage(1);
-    }
-    if (ISSET(tgetpass_flags, TGP_STDIN) && ISSET(tgetpass_flags, TGP_ASKPASS)) {
-       warningx("the `-A' and `-S' options may not be used together");
-       usage(1);
-    }
-    if ((NewArgc == 0 && mode == MODE_EDIT) ||
-       (NewArgc > 0 && !ISSET(mode, MODE_RUN | MODE_EDIT | MODE_CHECK)))
-       usage(1);
-    if (NewArgc == 0 && mode == MODE_RUN && !ISSET(flags, MODE_SHELL))
-       SET(flags, (MODE_IMPLIED_SHELL | MODE_SHELL));
-
-    return(mode | flags);
-}
-
 /*
  * Open sudoers and sanity check mode/owner/type.
  * Returns a handle to the sudoers file or NULL on error.
@@ -1556,62 +1313,3 @@ show_version()
     }
     exit(0);
 }
-
-/*
- * Tell which options are mutually exclusive and exit.
- */
-static void
-usage_excl(exit_val)
-    int exit_val;
-{
-    warningx("Only one of the -e, -h, -i, -K, -l, -s, -v or -V options may be specified");
-    usage(exit_val);
-}
-
-static int
-usage_out(buf)
-    const char *buf;
-{
-    return fputs(buf, stderr);
-}
-
-/*
- * Give usage message and exit.
- * The actual usage strings are in sudo_usage.h for configure substitution.
- */
-static void
-usage(exit_val)
-    int exit_val;
-{
-    struct lbuf lbuf;
-    char *uvec[6];
-    int i, ulen;
-
-    /*
-     * Use usage vectors appropriate to the progname.
-     */
-    if (strcmp(getprogname(), "sudoedit") == 0) {
-       uvec[0] = SUDO_USAGE5 + 3;
-       uvec[1] = NULL;
-    } else {
-       uvec[0] = SUDO_USAGE1;
-       uvec[1] = SUDO_USAGE2;
-       uvec[2] = SUDO_USAGE3;
-       uvec[3] = SUDO_USAGE4;
-       uvec[4] = SUDO_USAGE5;
-       uvec[5] = NULL;
-    }
-
-    /*
-     * Print usage and wrap lines as needed, depending on the
-     * tty width.
-     */
-    ulen = (int)strlen(getprogname()) + 8;
-    lbuf_init(&lbuf, usage_out, ulen, NULL);
-    for (i = 0; uvec[i] != NULL; i++) {
-       lbuf_append(&lbuf, "usage: ", getprogname(), uvec[i], NULL);
-       lbuf_print(&lbuf);
-    }
-    lbuf_destroy(&lbuf);
-    exit(exit_val);
-}
diff --git a/sudo.h b/sudo.h
index 3a615e72ed13419803cbb1c8da72d299d61b3323..91d454402d7b344d682c73fec721b8d79a955700 100644 (file)
--- a/sudo.h
+++ b/sudo.h
@@ -293,6 +293,7 @@ char *get_timestr __P((time_t, int));
 int get_boottime __P((struct timeval *));
 int user_in_group __P((struct passwd *, const char *));
 int exec_setup __P((void));
+int parse_args __P((int, char **));
 YY_DECL;
 
 /* exec.c */
index aeccc21ed3fdbe415b36086cabbfa9ac41d04cc9..018156da3c206db858bc143d3b14c05e35500535 100644 (file)
@@ -19,6 +19,8 @@
 #ifndef _SUDO_USAGE_H
 #define _SUDO_USAGE_H
 
+void usage __P((int)) __attribute__((__noreturn__));
+
 /*
  * Usage strings for sudo.  These are here because we
  * need to be able to substitute values from configure.