bug-sysutils
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [Bug-sysutils] argp patch for chsh


From: Barry deFreese
Subject: Re: [Bug-sysutils] argp patch for chsh
Date: Mon, 31 May 2004 07:26:37 -0700
User-agent: Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.6) Gecko/20040413 Debian/1.6-5

Whoops, I was missing my .cvsrc on that last one. Here is a diff -u copy.. Sorry.


--
Barry deFreese
Debian 3.0r1 "Woody"
GNU/Hurd
Registered Linux "Newbie" #302256 - Hurd H4XX0r wannabe

"Programming today is a race between software engineers striving
to build bigger and better idiot-proof programs, and the Universe
trying to produce bigger and better idiots. So far, the Universe is
winning." Rich Cook.



Index: src/chsh.c
===================================================================
RCS file: /cvsroot/sysutils/sysutils/src/chsh.c,v
retrieving revision 1.6
diff -u -p -r1.6 chsh.c
--- src/chsh.c  27 May 2004 07:50:33 -0000      1.6
+++ src/chsh.c  31 May 2004 15:14:49 -0000
@@ -20,6 +20,7 @@
  *  Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  */
 
+#include <argp.h>
 #include <pwd.h>
 #include <errno.h>
 #include <stdio.h>
@@ -32,26 +33,72 @@
 
 #define PRG_NAME "chsh"
 
-extern int optind;
-extern char *optarg;
 extern const char *progname;
 
-/**
- * Show usage information
- */
-static void usage(void)
+const char *argp_program_bug_address = PACKAGE_BUGREPORT;
+
+static char doc[] =
+       N_("Change the login shell for the specified user."
+          "\n"
+          "If no username is specified, "
+          "the information for the current user is changed.");
+
+static char args_doc[] = N_("[USER]");
+
+static struct argp_option options[] = {
+       {"shell", 's', N_("SHELL"), 0,
+         N_("the user's login shell"), 0 },
+       {"list-shells", 'l', 0, OPTION_ARG_OPTIONAL,
+         N_("list valid login shells"), 0 },
+       { 0, 0, 0, 0, 0, 0 }
+};
+
+/* Available arguments */
+struct arguments {
+       char *user;
+       char *shell;
+       long list;
+};
+
+/* Parse a single option */
+static error_t parse_opt(int key, char *arg, struct argp_state *state)
 {
-       fprintf(stdout,
-               _("Usage: %s [OPTION]... [USER]\n"
-                 "Change the login shell for the specified user.\n"
-                 "\n"
-                 "If no username is specified, "
-                 "the information for the current user is changed.\n"
-                 "\n"
-                 "  -l, --list-shells      list valid login shells\n"
-                 "  -s, --shell=SHELL      the user's login shell\n"),
-               progname);
-       usage_help();
+       struct arguments *args = state->input;
+
+       switch (key) {
+       case 's':
+               args->shell = arg;
+
+               if (!(is_valid_shell(args->shell)) ||
+                    ((is_listed_shell(args->shell))) ) {
+                       argp_error(state, "invalid value supplied\n");
+               }
+
+               break;
+
+       case 'l':
+               args->list = 1;
+
+
+               break;
+
+       case ARGP_KEY_INIT:
+               args->user = NULL;
+               args->shell = NULL;
+               args->list = 0;
+               break;
+
+       case ARGP_KEY_ARG:
+               if (args->user)
+                       argp_usage(state);
+
+               args->user = arg;
+               break;
+
+       default:
+               return ARGP_ERR_UNKNOWN;
+       }
+       return 0;
 }
 
 /**
@@ -69,9 +116,6 @@ int main(int argc, char *argv[])
 
        int empty = 1;
 
-       int optc;
-       int opt_index;
-
        int status = 0;
 
        int isadmin = 0;
@@ -81,20 +125,26 @@ int main(int argc, char *argv[])
        char *shell = NULL;
        char *username = NULL;
 
-       struct option const options[] = {
-               { "list-shells", no_argument, 0, 'l' },
-               { "shell", required_argument, 0, 's' },
-               { "help", no_argument, 0, 'h' },
-               { "version", no_argument, 0, 'V' },
-               { 0, 0, 0, 0 }
+       /* argp parser */
+       struct argp argp = {
+               options, parse_opt, args_doc, doc, NULL, NULL, NULL
        };
 
+       struct arguments args;
+
+       argp_program_version_hook = version;    
+
        errno = 0;
 
        /* Initialise support for locales, and set the program-name */
        if ((status = init_locales(PRG_NAME)))
                goto EXIT;
 
+       set_author_information(_("Written by David Weinehall.\n"));
+
+       /* Parse command line */
+       argp_parse(&argp, argc, argv, 0, 0, &args);
+
        /* Check if the caller has root privileges */
        if ((status = is_useradmin())) {
                if (status == EPERM) {
@@ -109,72 +159,25 @@ int main(int argc, char *argv[])
                isadmin = 1;
        }
 
-       /* Parse the command-line options */
-       while ((optc = getopt_long(argc, argv, "ls:",
-                                  options, &opt_index)) != -1) {
-               switch (optc) {
-               case 'l':
-                       fprintf(stdout, _("Valid login shells:\n\n"));
-
-                       setusershell();
-
-                       while ((shell = getusershell()))
-                               fprintf(stdout, "%s\n", shell);
-
-                       endusershell();
-
-                       break;
-
-               case 's':
-                       if (!(shell = strdup(optarg))) {
-                               fprintf(stderr,
-                                       _("%s: `%s' failed; %s\n"),
-                                       progname, "strdup()", strerror(errno));
-                               status = errno;
-                               goto EXIT;
-                       }
-
-                       if ((status = is_valid_shell(shell)) ||
-                           (!isadmin && (status = is_listed_shell(shell)))) {
-                               fprintf(stderr,
-                                       _("%s: invalid value supplied to "
-                                         "`%s'\n"),
-                                       progname, "-s | --shell");
-                               goto EXIT;
-                       }
-
-                       break;
-
-               case 'h':
-                       usage();
-                       goto EXIT;
+       /* If --list-shell is supplied, just list the available shells and exit
+        */
+       if (args.list) {
+               fprintf(stdout, _("\nValid login shells:\n\n"));
 
-               case 'V':
-                       version();
-                       goto EXIT;
+               setusershell();
 
-               default:
-                       usage();
-                       status = EINVAL;
-                       goto EXIT;
-               }
-       }
+               while ((shell = getusershell()))
+                       fprintf(stdout, "%s\n", shell);
 
-       /* Make sure we get the correct number of arguments */
-       if ((argc - optind) > 1) {
-               fprintf(stderr,
-                       _("%s: too many arguments\n"
-                         "Try `%s --help' for more information.\n"),
-                       progname, progname);
-               status = EINVAL;
+               endusershell();
                goto EXIT;
        }
 
        /* If an argument is supplied, it is the name
         * of the user to change the login shell for
         */
-       if (optind != argc) {
-               if (!(username = strdup(argv[optind]))) {
+       if (args.user) {
+               if (!(username = strdup(args.user))) {
                        fprintf(stderr,
                                _("%s: `%s' failed; %s\n"),
                                progname, "strdup()", strerror(errno));
@@ -183,6 +186,18 @@ int main(int argc, char *argv[])
                }
        }
 
+       /* If a shell was entered as an arg, make a copy
+         * for consistency with interactive mode
+         */
+       if (args.shell) {
+               if (!(shell = strdup(args.shell))) {
+                       fprintf(stderr, _("%s: `%s' failed; %s\n"),
+                               progname, "strdup()", strerror(errno));
+                       status = errno;
+                       goto EXIT;
+               }
+       }
+
        /* Unless the user requests to change information about himself,
         * or calls the program as root, deny the request
         */
@@ -248,7 +263,7 @@ int main(int argc, char *argv[])
         */
 
        /* If we have no options, enter interactive mode */
-       if (optind == 1) {
+       if (argc == 1) {
                fprintf(stdout,
                        _("Changing the login shell for `%s'\n"
                          "Enter the new value, or press enter to keep "

reply via email to

[Prev in Thread] Current Thread [Next in Thread]