[Top][All Lists]
[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 "