From b9a428f0c236c44a6b3f441a67bc47ad92ed173e Mon Sep 17 00:00:00 2001 From: Ben Kibbey Date: Wed, 13 Jul 2011 18:22:26 -0400 Subject: [PATCH] Use glib's command line option parser. --- configure.ac | 5 +- src/Makefile.am | 4 - src/getopt_long.c | 800 ------------------------------------------------------ src/getopt_long.h | 136 ---------- src/pwmd.c | 235 ++++++---------- 5 files changed, 86 insertions(+), 1094 deletions(-) delete mode 100644 src/getopt_long.c delete mode 100644 src/getopt_long.h diff --git a/configure.ac b/configure.ac index f8416719..6a6f4e1d 100644 --- a/configure.ac +++ b/configure.ac @@ -55,7 +55,7 @@ dnl Checks for header files. AC_HEADER_STDC AC_HEADER_SYS_WAIT AC_CHECK_HEADERS([fcntl.h stdlib.h string.h sys/time.h unistd.h libintl.h \ - locale.h syslog.h termios.h zlib.h getopt.h]) + locale.h syslog.h termios.h zlib.h]) dnl Checks for typedefs, structures, and compiler characteristics. AC_C_CONST @@ -91,8 +91,7 @@ AC_FUNC_MALLOC AC_FUNC_MEMCMP AC_FUNC_STRFTIME AC_CHECK_FUNCS([memset mkdir munmap setlocale socket strchr strerror strrchr \ - strstr strtol setrlimit mlockall getopt_long]) -AM_CONDITIONAL([NEED_GETOPT_LONG], [test "$ac_cv_func_getopt_long" != "yes"]) + strstr strtol setrlimit mlockall]) AC_DEFUN([AC_DEBUG], [ diff --git a/src/Makefile.am b/src/Makefile.am index 08e448c0..ad125d30 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -10,10 +10,6 @@ pwmd_CFLAGS = -DLOCALEDIR=\"${prefix}/share/locale\" @XML_CPPFLAGS@ \ @GLIB_CFLAGS@ @LIBGCRYPT_CFLAGS@ @GPG_ERROR_CFLAGS@ @PTH_CFLAGS@ pwmd_LDADD = ${top_builddir}/assuan/src/libassuan-pth.a -if NEED_GETOPT_LONG -pwmd_SOURCES += getopt_long.c getopt_long.h -endif - if WITH_DEBUG CPPFLAGS += -DDEBUG endif diff --git a/src/getopt_long.c b/src/getopt_long.c deleted file mode 100644 index f3366076..00000000 --- a/src/getopt_long.c +++ /dev/null @@ -1,800 +0,0 @@ - -/* Getopt for GNU - - Now part of GNU Queue. GNU Queue http://www.gnuqueue.org - - NOTE: getopt is now part of the C library, so if you don't know what - "Keep this file name-space clean" means, talk to roland@gnu.ai.mit.edu - before changing it! - - Copyright (C) 1987, 88, 89, 90, 91, 1992 Free Software Foundation, Inc. - - This program is free software; you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by the - Free Software Foundation; either version 2, or (at your option) any - later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - - This file was modified slightly by Ian Lance Taylor, June 1992, for - Taylor UUCP. */ - -//#include "queue.h" - -/* If GETOPT_COMPAT is defined, `+' as well as `--' can introduce a - long-named option. Because this is not POSIX.2 compliant, it is - being phased out. */ -#undef GETOPT_COMPAT - -/* This version of `getopt' appears to the caller like standard Unix `getopt' - but it behaves differently for the user, since it allows the user - to intersperse the options with the other arguments. - - As `getopt' works, it permutes the elements of ARGV so that, - when it is done, all the options precede everything else. Thus - all application programs are extended to handle flexible argument order. - - Setting the environment variable POSIXLY_CORRECT disables permutation. - Then the behavior is completely standard. - - GNU application programs can use a third alternative mode in which - they can distinguish the relative order of options and other arguments. */ - -#include -#include -#include -#include "getopt_long.h" - -/* For communication from `getopt' to the caller. - When `getopt' finds an option that takes an argument, - the argument value is returned here. - Also, when `ordering' is RETURN_IN_ORDER, - each non-option ARGV-element is returned here. */ - -char *optarg = 0; - -/* Index in ARGV of the next element to be scanned. - This is used for communication to and from the caller - and for communication between successive calls to `getopt'. - - On entry to `getopt', zero means this is the first call; initialize. - - When `getopt' returns EOF, this is the index of the first of the - non-option elements that the caller should itself scan. - - Otherwise, `optind' communicates from one call to the next - how much of ARGV has been scanned so far. */ - -int optind = 0; - -/* The next char to be scanned in the option-element - in which the last option character we returned was found. - This allows us to pick up the scan where we left off. - - If this is zero, or a null string, it means resume the scan - by advancing to the next ARGV-element. */ - -static char *nextchar; - -/* Callers store zero here to inhibit the error message - for unrecognized options. */ - -int opterr = 1; - -/* Describe how to deal with options that follow non-option ARGV-elements. - - If the caller did not specify anything, - the default is REQUIRE_ORDER if the environment variable - POSIXLY_CORRECT is defined, PERMUTE otherwise. - - REQUIRE_ORDER means don't recognize them as options; - stop option processing when the first non-option is seen. - This is what Unix does. - This mode of operation is selected by either setting the environment - variable POSIXLY_CORRECT, or using `+' as the first character - of the list of option characters. - - PERMUTE is the default. We permute the contents of ARGV as we scan, - so that eventually all the non-options are at the end. This allows options - to be given in any order, even with programs that were not written to - expect this. - - RETURN_IN_ORDER is an option available to programs that were written - to expect options and other ARGV-elements in any order and that care about - the ordering of the two. We describe each non-option ARGV-element - as if it were the argument of an option with character code 1. - Using `-' as the first character of the list of option characters - selects this mode of operation. - - The special argument `--' forces an end of option-scanning regardless - of the value of `ordering'. In the case of RETURN_IN_ORDER, only - `--' can cause `getopt' to return EOF with `optind' != ARGC. */ - -static enum -{ - REQUIRE_ORDER, PERMUTE, RETURN_IN_ORDER -} -ordering; - -#define my_index strchr -#define my_bcopy(src, dst, n) memcpy ((dst), (src), (n)) - -/* Handle permutation of arguments. */ - -/* Describe the part of ARGV that contains non-options that have - been skipped. `first_nonopt' is the index in ARGV of the first of them; - `last_nonopt' is the index after the last of them. */ - -static int first_nonopt; -static int last_nonopt; - -/* Exchange two adjacent subsequences of ARGV. - One subsequence is elements [first_nonopt,last_nonopt) - which contains all the non-options that have been skipped so far. - The other is elements [last_nonopt,optind), which contains all - the options processed since those non-options were skipped. - - `first_nonopt' and `last_nonopt' are relocated so that they describe - the new indices of the non-options in ARGV after they are moved. */ - -static void exchange(argv) - char **argv; -{ - size_t nonopts_size = (last_nonopt - first_nonopt) * sizeof(char *); - char **temp = (char **) malloc(nonopts_size); - - if (temp == NULL) - abort(); - - /* Interchange the two blocks of data in ARGV. */ - - my_bcopy((char *) &argv[first_nonopt], (char *) temp, nonopts_size); - my_bcopy((char *) &argv[last_nonopt], (char *) &argv[first_nonopt], - (optind - last_nonopt) * sizeof(char *)); - my_bcopy((char *) temp, (char *) &argv[first_nonopt + optind - last_nonopt], - nonopts_size); - - free(temp); - - /* Update records for the slots the non-options now occupy. */ - - first_nonopt += (optind - last_nonopt); - last_nonopt = optind; -} - -/* Scan elements of ARGV (whose length is ARGC) for option characters - given in OPTSTRING. - - If an element of ARGV starts with '-', and is not exactly "-" or "--", - then it is an option element. The characters of this element - (aside from the initial '-') are option characters. If `getopt' - is called repeatedly, it returns successively each of the option characters - from each of the option elements. - - If `getopt' finds another option character, it returns that character, - updating `optind' and `nextchar' so that the next call to `getopt' can - resume the scan with the following option character or ARGV-element. - - If there are no more option characters, `getopt' returns `EOF'. - Then `optind' is the index in ARGV of the first ARGV-element - that is not an option. (The ARGV-elements have been permuted - so that those that are not options now come last.) - - OPTSTRING is a string containing the legitimate option characters. - If an option character is seen that is not listed in OPTSTRING, - return '?' after printing an error message. If you set `opterr' to - zero, the error message is suppressed but we still return '?'. - - If a char in OPTSTRING is followed by a colon, that means it wants an arg, - so the following text in the same ARGV-element, or the text of the following - ARGV-element, is returned in `optarg'. Two colons mean an option that - wants an optional arg; if there is text in the current ARGV-element, - it is returned in `optarg', otherwise `optarg' is set to zero. - - If OPTSTRING starts with `-' or `+', it requests different methods of - handling the non-option ARGV-elements. - See the comments about RETURN_IN_ORDER and REQUIRE_ORDER, above. - - Long-named options begin with `--' instead of `-'. - Their names may be abbreviated as long as the abbreviation is unique - or is an exact match for some defined option. If they have an - argument, it follows the option name in the same ARGV-element, separated - from the option name by a `=', or else the in next ARGV-element. - When `getopt' finds a long-named option, it returns 0 if that option's - `flag' field is nonzero, the value of the option's `val' field - if the `flag' field is zero. - - The elements of ARGV aren't really const, because we permute them. - But we pretend they're const in the prototype to be compatible - with other systems. - - LONGOPTS is a vector of `struct option' terminated by an - element containing a name which is zero. - - LONGIND returns the index in LONGOPT of the long-named option found. - It is only valid when a long-named option has been found by the most - recent call. - - If LONG_ONLY is nonzero, '-' as well as '--' can introduce - long-named options. */ - -int _getopt_internal(argc, argv, optstring, longopts, longind, long_only) - int argc; - char *const *argv; - const char *optstring; - const struct option *longopts; - int *longind; - int long_only; -{ - int option_index; - - optarg = 0; - - /* Initialize the internal data when the first call is made. Start - * processing options with ARGV-element 1 (since ARGV-element 0 is the - * program name); the sequence of previously skipped non-option - * ARGV-elements is empty. */ - - if (optind == 0) - { - first_nonopt = last_nonopt = optind = 1; - - nextchar = NULL; - - /* Determine how to handle the ordering of options and nonoptions. */ - - if (optstring[0] == '-') - { - ordering = RETURN_IN_ORDER; - ++optstring; - } - else if (optstring[0] == '+') - { - ordering = REQUIRE_ORDER; - ++optstring; - } - else if (getenv("POSIXLY_CORRECT") != NULL) - ordering = REQUIRE_ORDER; - else - ordering = PERMUTE; - } - - if (nextchar == NULL || *nextchar == '\0') - { - if (ordering == PERMUTE) - { - /* If we have just processed some options following some non-options, - * exchange them so that the options come first. */ - - if (first_nonopt != last_nonopt && last_nonopt != optind) - exchange((char **) argv); - else if (last_nonopt != optind) - first_nonopt = optind; - - /* Now skip any additional non-options and extend the range of - * non-options previously skipped. */ - - while (optind < argc - && (argv[optind][0] != '-' || argv[optind][1] == '\0') -#ifdef GETOPT_COMPAT - && (longopts == NULL || argv[optind][0] != '+' - || argv[optind][1] == '\0') -#endif /* GETOPT_COMPAT */ - ) - optind++; - last_nonopt = optind; - } - - /* Special ARGV-element `--' means premature end of options. Skip it like - * a null option, then exchange with previous non-options as if it were - * an option, then skip everything else like a non-option. */ - - if (optind != argc && !strcmp(argv[optind], "--")) - { - optind++; - - if (first_nonopt != last_nonopt && last_nonopt != optind) - exchange((char **) argv); - else if (first_nonopt == last_nonopt) - first_nonopt = optind; - last_nonopt = argc; - - optind = argc; - } - - /* If we have done all the ARGV-elements, stop the scan and back over any - * non-options that we skipped and permuted. */ - - if (optind == argc) - { - /* Set the next-arg-index to point at the non-options that we - * previously skipped, so the caller will digest them. */ - if (first_nonopt != last_nonopt) - optind = first_nonopt; - return EOF; - } - - /* If we have come to a non-option and did not permute it, either stop - * the scan or describe it to the caller and pass it by. */ - - if ((argv[optind][0] != '-' || argv[optind][1] == '\0') -#ifdef GETOPT_COMPAT - && (longopts == NULL || argv[optind][0] != '+' - || argv[optind][1] == '\0') -#endif /* GETOPT_COMPAT */ - ) - { - if (ordering == REQUIRE_ORDER) - return EOF; - optarg = argv[optind++]; - return 1; - } - - /* We have found another option-ARGV-element. Start decoding its - * characters. */ - - nextchar = - (argv[optind] + 1 + (longopts != NULL && argv[optind][1] == '-')); - } - - if (longopts != NULL - && ((argv[optind][0] == '-' && (argv[optind][1] == '-' || long_only)) -#ifdef GETOPT_COMPAT - || argv[optind][0] == '+' -#endif /* GETOPT_COMPAT */ - )) - { - const struct option *p; - char *s = nextchar; - int exact = 0; - int ambig = 0; - const struct option *pfound = NULL; - int indfound = 0; - - while (*s && *s != '=') - s++; - - /* Test all options for either exact match or abbreviated matches. */ - for (p = longopts, option_index = 0; p->name; p++, option_index++) - if (!strncmp(p->name, nextchar, (size_t) (s - nextchar))) - { - if (s - nextchar == strlen(p->name)) - { - /* Exact match found. */ - pfound = p; - indfound = option_index; - exact = 1; - break; - } - else if (pfound == NULL) - { - /* First nonexact match found. */ - pfound = p; - indfound = option_index; - } - else - /* Second nonexact match found. */ - ambig = 1; - } - - if (ambig && !exact) - { - if (opterr) - fprintf(stderr, "%s: option `%s' is ambiguous\n", argv[0], - argv[optind]); - nextchar += strlen(nextchar); - optind++; - return '?'; - } - - if (pfound != NULL) - { - option_index = indfound; - optind++; - if (*s) - { - /* Don't test has_arg with >, because some C compilers don't allow it - * to be used on enums. */ - if (pfound->has_arg) - optarg = s + 1; - else - { - if (opterr) - { - if (argv[optind - 1][1] == '-') - /* --option */ - fprintf(stderr, "%s: option `--%s' doesn't allow an argument\n", - argv[0], pfound->name); - else - /* +option or -option */ - fprintf(stderr, "%s: option `%c%s' doesn't allow an argument\n", - argv[0], argv[optind - 1][0], pfound->name); - } - nextchar += strlen(nextchar); - return '?'; - } - } - else if (pfound->has_arg == 1) - { - if (optind < argc) - optarg = argv[optind++]; - else - { - if (opterr) - fprintf(stderr, "%s: option `%s' requires an argument\n", argv[0], - argv[optind - 1]); - nextchar += strlen(nextchar); - return '?'; - } - } - nextchar += strlen(nextchar); - if (longind != NULL) - *longind = option_index; - if (pfound->flag) - { - *(pfound->flag) = pfound->val; - return 0; - } - return pfound->val; - } - /* Can't find it as a long option. If this is not getopt_long_only, or - * the option starts with '--' or is not a valid short option, then it's - * an error. Otherwise interpret it as a short option. */ - if (!long_only || argv[optind][1] == '-' -#ifdef GETOPT_COMPAT - || argv[optind][0] == '+' -#endif /* GETOPT_COMPAT */ - || my_index(optstring, *nextchar) == NULL) - { - if (opterr) - { - if (argv[optind][1] == '-') - /* --option */ - fprintf(stderr, "%s: unrecognized option `--%s'\n", argv[0], - nextchar); - else - /* +option or -option */ - fprintf(stderr, "%s: unrecognized option `%c%s'\n", argv[0], - argv[optind][0], nextchar); - } - nextchar = (char *) ""; - optind++; - return '?'; - } - } - - /* Look at and handle the next option-character. */ - - { - char c = *nextchar++; - char *temp = my_index(optstring, c); - - /* Increment `optind' when we start to process its last character. */ - if (*nextchar == '\0') - ++optind; - - if (temp == NULL || c == ':') - { - if (opterr) - { - if (c < 040 || c >= 0177) - fprintf(stderr, "%s: unrecognized option, character code 0%o\n", - argv[0], (unsigned char) (c)); - else - fprintf(stderr, "%s: unrecognized option `-%c'\n", argv[0], c); - } - return '?'; - } - if (temp[1] == ':') - { - if (temp[2] == ':') - { - /* This is an option that accepts an argument optionally. */ - if (*nextchar != '\0') - { - optarg = nextchar; - optind++; - } - else - optarg = 0; - nextchar = NULL; - } - else - { - /* This is an option that requires an argument. */ - if (*nextchar != '\0') - { - optarg = nextchar; - /* If we end this ARGV-element by taking the rest as an arg, we - * must advance to the next element now. */ - optind++; - } - else if (optind == argc) - { - if (opterr) - fprintf(stderr, "%s: option `-%c' requires an argument\n", - argv[0], c); - c = '?'; - } - else - /* We already incremented `optind' once; increment it again when - * taking next ARGV-elt as argument. */ - optarg = argv[optind++]; - nextchar = NULL; - } - } - return c; - } -} - -int getopt(argc, argv, optstring) - int argc; - char *const *argv; - const char *optstring; -{ - return _getopt_internal(argc, argv, optstring, (const struct option *) 0, - (int *) 0, 0); -} - -#ifdef TEST - -/* Compile with -DTEST to make an executable for use in testing - the above definition of `getopt'. */ - -int main(argc, argv) - int argc; - char **argv; -{ - int c; - int digit_optind = 0; - - while (1) - { - int this_option_optind = optind ? optind : 1; - - c = getopt(argc, argv, "abc:d:0123456789"); - if (c == EOF) - break; - - switch (c) - { - case '0': - case '1': - case '2': - case '3': - case '4': - case '5': - case '6': - case '7': - case '8': - case '9': - if (digit_optind != 0 && digit_optind != this_option_optind) - printf("digits occur in two different argv-elements.\n"); - digit_optind = this_option_optind; - printf("option %c\n", c); - break; - - case 'a': - printf("option a\n"); - break; - - case 'b': - printf("option b\n"); - break; - - case 'c': - printf("option c with value `%s'\n", optarg); - break; - - case '?': - break; - - default: - printf("?? getopt returned character code 0%o ??\n", c); - } - } - - if (optind < argc) - { - printf("non-option ARGV-elements: "); - while (optind < argc) - printf("%s ", argv[optind++]); - printf("\n"); - } - - exit(0); -} - -#endif /* TEST */ - -/* getopt_long and getopt_long_only entry points for GNU getopt. - Copyright (C) 1987, 88, 89, 90, 91, 92, 1993 - Free Software Foundation, Inc. - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU Library General Public License - as published by the Free Software Foundation; either version 2, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Library General Public License for more details. - - You should have received a copy of the GNU Library General Public License - along with this program; if not, write to the Free Software - Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ - -#ifdef HAVE_CONFIG_H -#if defined (emacs) || defined (CONFIG_BROKETS) - -/* We use instead of "config.h" so that a compilation - using -I. -I$srcdir will use ./config.h rather than $srcdir/config.h - (which it would do because it found this file in $srcdir). */ -#include -#else -#include "config.h" -#endif -#endif - -#include "getopt_long.h" - -#ifndef __STDC__ - -/* This is a separate conditional since some stdc systems - reject `defined (const)'. */ -#ifndef const -#define const -#endif -#endif - -#include - -/* Comment out all this code if we are using the GNU C Library, and are not - actually compiling the library itself. This code is part of the GNU C - Library, but also included in many other GNU distributions. Compiling - and linking in this code is a waste when using the GNU C library - (especially if it is a shared library). Rather than having every GNU - program understand `configure --with-gnu-libc' and omit the object files, - it is simpler to just do this in the source for each such file. */ - -#if defined (_LIBC) || !defined (__GNU_LIBRARY__) - -/* This needs to come after some library #include - to get __GNU_LIBRARY__ defined. */ -#ifdef __GNU_LIBRARY__ -#include -#else -char *getenv(); -#endif - -#ifndef NULL -#define NULL 0 -#endif - -int getopt_long(argc, argv, options, long_options, opt_index) - int argc; - char *const *argv; - const char *options; - const struct option *long_options; - int *opt_index; -{ - return _getopt_internal(argc, argv, options, long_options, opt_index, 0); -} - -/* Like getopt_long, but '-' as well as '--' can indicate a long option. - If an option that starts with '-' (not '--') doesn't match a long option, - but does match a short option, it is parsed as a short option - instead. */ - -int getopt_long_only(argc, argv, options, long_options, opt_index) - int argc; - char *const *argv; - const char *options; - const struct option *long_options; - int *opt_index; -{ - return _getopt_internal(argc, argv, options, long_options, opt_index, 1); -} - -#endif /* _LIBC or not __GNU_LIBRARY__. */ - -#ifdef TEST - -#include - -int main(argc, argv) - int argc; - char **argv; -{ - int c; - int digit_optind = 0; - - while (1) - { - int this_option_optind = optind ? optind : 1; - int option_index = 0; - static struct option long_options[] = { - {"add", 1, 0, 0}, - {"append", 0, 0, 0}, - {"delete", 1, 0, 0}, - {"verbose", 0, 0, 0}, - {"create", 0, 0, 0}, - {"file", 1, 0, 0}, - {0, 0, 0, 0} - }; - - c = - getopt_long(argc, argv, "abc:d:0123456789", long_options, - &option_index); - if (c == EOF) - break; - - switch (c) - { - case 0: - printf("option %s", long_options[option_index].name); - if (optarg) - printf(" with arg %s", optarg); - printf("\n"); - break; - - case '0': - case '1': - case '2': - case '3': - case '4': - case '5': - case '6': - case '7': - case '8': - case '9': - if (digit_optind != 0 && digit_optind != this_option_optind) - printf("digits occur in two different argv-elements.\n"); - digit_optind = this_option_optind; - printf("option %c\n", c); - break; - - case 'a': - printf("option a\n"); - break; - - case 'b': - printf("option b\n"); - break; - - case 'c': - printf("option c with value `%s'\n", optarg); - break; - - case 'd': - printf("option d with value `%s'\n", optarg); - break; - - case '?': - break; - - default: - printf("?? getopt returned character code 0%o ??\n", c); - } - } - - if (optind < argc) - { - printf("non-option ARGV-elements: "); - while (optind < argc) - printf("%s ", argv[optind++]); - printf("\n"); - } - - exit(0); -} - -#endif /* TEST */ diff --git a/src/getopt_long.h b/src/getopt_long.h deleted file mode 100644 index 60fc0055..00000000 --- a/src/getopt_long.h +++ /dev/null @@ -1,136 +0,0 @@ - -/* Declarations for getopt. - Copyright (C) 1989, 1990, 1991, 1992 Free Software Foundation, Inc. - - This program is free software; you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by the - Free Software Foundation; either version 2, or (at your option) any - later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - - This file was modified slightly by Ian Lance Taylor, November 1992, - for Taylor UUCP, and again in June, 1995. */ - -#ifndef _GETOPT_H -#define _GETOPT_H 1 - -#ifdef __cplusplus -extern "C" -{ -#endif - -/* Ian Lance Taylor added the following defines for - Taylor UUCP. This avoids reported conflicts with system getopt - definitions. */ -#define getopt gnu_getopt -#define optarg gnu_optarg -#define optind gnu_optind -#define opterr gnu_opterr - -/* For communication from `getopt' to the caller. - When `getopt' finds an option that takes an argument, - the argument value is returned here. - Also, when `ordering' is RETURN_IN_ORDER, - each non-option ARGV-element is returned here. */ - - extern char *optarg; - -/* Index in ARGV of the next element to be scanned. - This is used for communication to and from the caller - and for communication between successive calls to `getopt'. - - On entry to `getopt', zero means this is the first call; initialize. - - When `getopt' returns EOF, this is the index of the first of the - non-option elements that the caller should itself scan. - - Otherwise, `optind' communicates from one call to the next - how much of ARGV has been scanned so far. */ - - extern int optind; - -/* Callers store zero here to inhibit the error message `getopt' prints - for unrecognized options. */ - - extern int opterr; - -/* Describe the long-named options requested by the application. - The LONG_OPTIONS argument to getopt_long or getopt_long_only is a vector - of `struct option' terminated by an element containing a name which is - zero. - - The field `has_arg' is: - no_argument (or 0) if the option does not take an argument, - required_argument (or 1) if the option requires an argument, - optional_argument (or 2) if the option takes an optional argument. - - If the field `flag' is not NULL, it points to a variable that is set - to the value given in the field `val' when the option is found, but - left unchanged if the option is not found. - - To have a long-named option do something other than set an `int' to - a compiled-in constant, such as set a value from `optarg', set the - option's `flag' field to zero and its `val' field to a nonzero - value (the equivalent single-letter option character, if there is - one). For long options that have a zero `flag' field, `getopt' - returns the contents of the `val' field. */ - - struct option - { - const char *name; - /* has_arg can't be an enum because some compilers complain about type - * mismatches in all the code that assumes it is an int. */ - int has_arg; - int *flag; - int val; - }; - -/* Names for the values of the `has_arg' field of `struct option'. */ - - enum _argtype - { - no_argument, - required_argument, - optional_argument - }; - -#ifndef P - -/* On some systems, includes getopt.h before P is defined by - uucp.h, and the -I arguments cause this version of getopt.h to be - included. Work around that here. */ -#define P(x) () -#define UNDEFINE_P -#endif - - extern int getopt P((int argc, char *const *argv, const char *shortopts)); - extern int getopt_long - P((int argc, char *const *argv, const char *shortopts, - const struct option * longopts, int *longind)); - extern int getopt_long_only - P((int argc, char *const *argv, const char *shortopts, - const struct option * longopts, int *longind)); - -/* Internal only. Users should not call this directly. */ - extern int _getopt_internal - P((int argc, char *const *argv, const char *shortopts, - const struct option * longopts, int *longind, int long_only)); - -#ifdef UNDEFINE_P -#undef P -#undef UNDEFINE_P -#endif - -#ifdef __cplusplus -} -#endif - -#endif /* _GETOPT_H */ diff --git a/src/pwmd.c b/src/pwmd.c index 2692fbf8..4e5b4f06 100644 --- a/src/pwmd.c +++ b/src/pwmd.c @@ -48,14 +48,6 @@ #include #include -#ifdef HAVE_GETOPT_LONG -#ifdef HAVE_GETOPT_H -#include -#endif -#else -#include "getopt_long.h" -#endif - #ifdef TM_IN_SYS_TIME #include #else @@ -254,37 +246,6 @@ void log_write(const gchar *fmt, ...) g_free(line); } -static void usage(gchar *pn, gint rc) -{ - g_fprintf(rc == EXIT_FAILURE ? stderr : stdout, N_( - "Usage: %s [options] [file1] [...]\n" - " --no-fork/-n\n" - " run as a foreground process\n" - " --rcfile/-f \n" - " load the specified rcfile (~/.pwmd/config)\n" - " --convert/-C \n" - " convert a version 1 data file to version 2\n" - " --import/-I \n" - " import an XML file\n" - " --iterations/-i\n" - " encrypt with the specified number of iterations when importing\n" - " (default is in the rcfile \"global\" section)\n" - " --key-file/-k \n" - " obtain the key from the specified file when importing or converting\n" - " --outfile/-o \n" - " output file to use when importing or converting (- for stdout)\n" - " --disable-dump/-D\n" - " disable use of the LIST, XPATH and DUMP commands\n" - " --no-pinentry/-P\n" - " disable use of pinentry\n" - " --ignore\n" - " ignore cache failures on startup\n" - " --version\n" - " --help\n" - ), pn); - exit(rc); -} - static void setup_gcrypt() { gcry_control(GCRYCTL_SET_THREAD_CBS, &gcry_threads_pth); @@ -1759,19 +1720,16 @@ static void startup_failure() int main(int argc, char *argv[]) { - gint opt; struct sockaddr_un addr; gchar buf[PATH_MAX]; gchar *socketpath = NULL, *socketdir, *socketname = NULL; gchar *socketarg = NULL; gchar *datadir = NULL; - gboolean n; - gint x; + gint n; gchar *p; gchar **cache_push = NULL; gchar *import = NULL, *keyfile = NULL; - guint64 cmd_iterations = 0; - gboolean iterations_arg = FALSE; + gint64 cmd_iterations = -1; gboolean rcfile_spec = FALSE; gint estatus = EXIT_FAILURE; gint sockfd; @@ -1779,37 +1737,43 @@ int main(int argc, char *argv[]) GMemVTable mtable = { xmalloc, xrealloc, xfree, xcalloc, NULL, NULL }; gint do_unlink = 0; gboolean secure = FALSE; - gint background = 1; + gboolean nofork = FALSE; gchar *convert = NULL; gint show_version = 0; - gint show_help = 0; gboolean force = FALSE; #ifdef WITH_PINENTRY gboolean disable_pinentry = FALSE; #endif - gint opt_index; - const struct option long_opts[] = { + GError *error = NULL; + GOptionContext *context; + GOptionEntry options[] = + { #ifdef WITH_PINENTRY - { "no-pinentry", 0, 0, 'P' }, + { "no-pinentry", 'P', 0, G_OPTION_ARG_NONE, &disable_pinentry, + "disable pinentry", NULL }, #endif - { "outfile", 1, 0, 'o' }, - { "convert", 1, 0, 'C' }, - { "no-fork", 0, 0, 'n' }, - { "disable-dump", 0, 0, 'D' }, - { "import", 1, 0, 'I' }, - { "iterations", 1, 0, 'i' }, - { "key-file", 1, 0, 'k' }, - { "rcfile", 1, 0, 'f' }, - { "version", 0, &show_version, TRUE }, - { "help", 0, &show_help, TRUE }, - { "ignore", 0, &force, TRUE }, - { 0, 0, 0, 0} + { "version", 0, 0, G_OPTION_ARG_NONE, &show_version, + "version information", NULL }, + { "no-fork", 'n', 0, G_OPTION_ARG_NONE, &nofork, + "run as a foreground process", NULL }, + { "disable-dump", 'D', 0, G_OPTION_ARG_NONE, &secure, + "disable the LIST, XPATH and DUMP commands", NULL }, + { "rcfile", 'f', 0, G_OPTION_ARG_FILENAME, &rcfile, + "load the specified rcfile (~/.pwmd/config)", "filename" }, + { "ignore", 0, 0, G_OPTION_ARG_NONE, &force, + "ignore cache failures on startup", NULL }, + { "outfile", 'o', 0, G_OPTION_ARG_FILENAME, &outfile, + "output file when importing (- for stdout)", "filename" }, + { "convert", 'C', 0, G_OPTION_ARG_FILENAME, &convert, + "convert a version 1 data file to version 2", "filename" }, + { "key-file", 'k', 0, G_OPTION_ARG_FILENAME, &keyfile, + "for decryption when converting", "filename" }, + { "import", 'I', 0, G_OPTION_ARG_FILENAME, &import, + "import an XML file", "filename" }, + { "iterations", 'i', 0, G_OPTION_ARG_INT64, &cmd_iterations, + "when importing or converting", "N" }, + { NULL } }; -#ifdef WITH_PINENTRY - const gchar *optstring = "Po:C:nDI:i:k:f:"; -#else - const gchar *optstring = "o:C:nDI:i:k:f:"; -#endif #ifndef DEBUG #ifdef HAVE_SETRLIMIT struct rlimit rl; @@ -1851,90 +1815,49 @@ int main(int argc, char *argv[]) err(EXIT_FAILURE, "%s", buf); cmdline = TRUE; + context = g_option_context_new("- Password Manager Daemon"); + g_option_context_add_main_entries(context, options, NULL); + if (!g_option_context_parse(context, &argc, &argv, &error)) + { + g_print("Option parsing failed: %s\n", error->message); + exit(EXIT_FAILURE); + } - while ((opt = getopt_long(argc, argv, optstring, long_opts, &opt_index)) != -1) { - switch (opt) { - case 0: - if (show_help) - usage(argv[0], EXIT_SUCCESS); - - if (show_version) { - printf(N_("%s\nCopyright (C) 2006-2011 %s\nReleased under the terms of the GPL v2. Use at your own risk.\n\nCompile time features:\n%s"), PACKAGE_STRING, - PACKAGE_BUGREPORT, + if (show_version) { + printf(N_("%s\nCopyright (C) 2006-2011 %s\nReleased under the terms of the GPL v2. Use at your own risk.\n\nCompile time features:\n%s"), PACKAGE_STRING, + PACKAGE_BUGREPORT, #ifdef WITH_PINENTRY - "+WITH_PINENTRY\n" + "+WITH_PINENTRY\n" #else - "-WITH_PINENTRY\n" + "-WITH_PINENTRY\n" #endif #ifdef WITH_QUALITY - "+WITH_QUALITY\n" + "+WITH_QUALITY\n" #else - "-WITH_QUALITY\n" + "-WITH_QUALITY\n" #endif #ifdef WITH_LIBACL - "+WITH_LIBACL\n" + "+WITH_LIBACL\n" #else - "-WITH_LIBACL\n" + "-WITH_LIBACL\n" #endif #ifdef DEBUG - "+DEBUG\n" + "+DEBUG\n" #else - "-DEBUG\n" + "-DEBUG\n" #endif #ifdef MEM_DEBUG - "+MEM_DEBUG\n" + "+MEM_DEBUG\n" #else - "-MEM_DEBUG\n" + "-MEM_DEBUG\n" #endif #ifdef MUTEX_DEBUG - "+MUTEX_DEBUG\n" + "+MUTEX_DEBUG\n" #else - "-MUTEX_DEBUG\n" -#endif - ); - exit(EXIT_SUCCESS); - } - break; -#ifdef WITH_PINENTRY - case 'P': - disable_pinentry = TRUE; - break; + "-MUTEX_DEBUG\n" #endif - case 'o': - outfile = optarg; - break; - case 'C': - convert = optarg; - break; - case 'n': - background = 0; - break; - case 'D': - secure = TRUE; - break; - case 'I': - import = optarg; - break; - case 'i': - cmd_iterations = strtoull(optarg, NULL, 10); - - if (cmd_iterations == G_MAXUINT64) { - log_write("%s", N_("invalid iteration count")); - usage(argv[0], EXIT_FAILURE); - } - - iterations_arg = TRUE; - break; - case 'k': - keyfile = optarg; - break; - case 'f': - rcfile = g_strdup(optarg); - rcfile_spec = TRUE; - break; - default: - usage(argv[0], EXIT_FAILURE); - } + ); + exit(EXIT_SUCCESS); } pth_mutex_init(&cn_mutex); @@ -1962,10 +1885,10 @@ int main(int argc, char *argv[]) openlog("pwmd", LOG_NDELAY|LOG_PID, LOG_DAEMON); if (g_key_file_has_key(keyfileh, "global", "priority", NULL)) { - x = g_key_file_get_integer(keyfileh, "global", "priority", NULL); + n = g_key_file_get_integer(keyfileh, "global", "priority", NULL); errno = 0; - if (setpriority(PRIO_PROCESS, 0, x) == -1) { + if (setpriority(PRIO_PROCESS, 0, n) == -1) { log_write("setpriority(): %s", pwmd_strerror(gpg_error_from_syserror())); goto do_exit; } @@ -1979,28 +1902,40 @@ int main(int argc, char *argv[]) #endif if (convert) { - if (!outfile) - usage(argv[0], EXIT_FAILURE); + if (!outfile) { + gchar *tmp = g_option_context_get_help(context, TRUE, NULL); + + fprintf(stderr, "%s", tmp); + g_free(tmp); + exit(EXIT_FAILURE); + } - opt = convert_file(convert, keyfile, outfile); + n = convert_file(convert, keyfile, outfile); g_key_file_free(keyfileh); g_free(rcfile); - exit(opt ? EXIT_FAILURE : EXIT_SUCCESS); + exit(n ? EXIT_FAILURE : EXIT_SUCCESS); } if (import) { - if (!outfile) - usage(argv[0], EXIT_FAILURE); + if (!outfile) { + gchar *tmp = g_option_context_get_help(context, TRUE, NULL); + + fprintf(stderr, "%s", tmp); + g_free(tmp); + exit(EXIT_FAILURE); + } - if (!iterations_arg) + if (cmd_iterations == -1) cmd_iterations = get_key_file_uint64("global", "iterations"); - opt = xml_import(import, outfile, keyfile, cmd_iterations); + gboolean b = xml_import(import, outfile, keyfile, cmd_iterations); g_key_file_free(keyfileh); g_free(rcfile); - exit(opt == FALSE ? EXIT_FAILURE : EXIT_SUCCESS); + exit(!b ? EXIT_FAILURE : EXIT_SUCCESS); } + g_option_context_free(context); + if ((p = g_key_file_get_string(keyfileh, "global", "socket_path", NULL)) == NULL) errx(EXIT_FAILURE, N_("%s: socket_path not defined"), rcfile); @@ -2025,11 +1960,9 @@ int main(int argc, char *argv[]) if (g_key_file_has_key(keyfileh, "global", "cache_push", NULL) == TRUE) cache_push = g_key_file_get_string_list(keyfileh, "global", "cache_push", NULL, NULL); - if (argc != optind) { - for (; optind < argc; optind++) { - if (strv_printf(&cache_push, "%s", argv[optind]) == FALSE) - errx(EXIT_FAILURE, "%s", pwmd_strerror(GPG_ERR_ENOMEM)); - } + for (n = 1; n < argc; n++) { + if (strv_printf(&cache_push, "%s", argv[n]) == FALSE) + errx(EXIT_FAILURE, "%s", pwmd_strerror(GPG_ERR_ENOMEM)); } if (strchr(socketarg, '/') == NULL) { @@ -2063,8 +1996,8 @@ int main(int argc, char *argv[]) * Set the cache entry for a file. Prompts for the password. */ if (cache_push) { - for (opt = 0; cache_push[opt]; opt++) { - if (!do_cache_push(cache_push[opt], NULL, 0) && !force) { + for (n = 0; cache_push[n]; n++) { + if (!do_cache_push(cache_push[n], NULL, 0) && !force) { g_strfreev(cache_push); startup_failure(); estatus = EXIT_FAILURE; @@ -2073,7 +2006,7 @@ int main(int argc, char *argv[]) } g_strfreev(cache_push); - log_write(background ? N_("Done. Daemonizing...") : N_("Done. Waiting for connections...")); + log_write(!nofork ? N_("Done. Daemonizing...") : N_("Done. Waiting for connections...")); } /* @@ -2145,7 +2078,7 @@ int main(int argc, char *argv[]) unsetenv("DISPLAY"); unsetenv("TERM"); - if (background) { + if (!nofork) { switch (fork()) { case -1: log_write("fork(): %s", pwmd_strerror(gpg_error_from_syserror())); -- 2.11.4.GIT