diff options
author | Paul Eggert <eggert@cs.ucla.edu> | 2004-09-24 23:33:39 +0000 |
---|---|---|
committer | Paul Eggert <eggert@cs.ucla.edu> | 2004-09-24 23:33:39 +0000 |
commit | 4f5ed75ee4f56c6d0dc30d88fed5119f31517a27 (patch) | |
tree | d595db212d790e8c91dcfd0266d79ed6a193ee77 | |
parent | 6ca4627b99cb62bd04d6027d3a8c220712f1b971 (diff) | |
download | coreutils-4f5ed75ee4f56c6d0dc30d88fed5119f31517a27.tar.xz |
(main): Revamp option processing to support "chmod -r -w file".
-rw-r--r-- | src/chmod.c | 64 |
1 files changed, 40 insertions, 24 deletions
diff --git a/src/chmod.c b/src/chmod.c index 884669d2a..982e09fc8 100644 --- a/src/chmod.c +++ b/src/chmod.c @@ -339,9 +339,10 @@ int main (int argc, char **argv) { struct mode_change *changes; + char *mode = NULL; + size_t mode_len = 0; + size_t mode_alloc = 0; bool ok; - int modeind = 0; /* Index of the mode argument in `argv'. */ - int thisind; bool preserve_root = false; int c; @@ -355,14 +356,11 @@ main (int argc, char **argv) recurse = force_silent = false; - while (1) + while ((c = getopt_long (argc, argv, + "Rcfvr::w::x::X::s::t::u::g::o::a::,::+::-::=::", + long_options, NULL)) + != -1) { - thisind = optind ? optind : 1; - - c = getopt_long (argc, argv, "RcfvrwxXstugoa,+-=", long_options, NULL); - if (c == -1) - break; - switch (c) { case 'r': @@ -379,15 +377,25 @@ main (int argc, char **argv) case '+': case '-': case '=': - if (modeind != 0 && modeind != thisind) - { - static char char_string[2] = {0, 0}; - char_string[0] = c; - error (EXIT_FAILURE, 0, - _("invalid character %s in mode string %s"), - quote_n (0, char_string), quote_n (1, argv[thisind])); - } - modeind = thisind; + { + /* Allocate a mode string (e.g., "-rwx") by concatenating + the argument containing this option. If a previous mode + string was given, concatenate the previous string, a + comma, and the new string (e.g., "-s,-rwx"). */ + + char const *arg = argv[optind - 1]; + size_t arg_len = strlen (arg); + size_t mode_comma_len = mode_len + !!mode_len; + size_t new_mode_len = mode_comma_len + arg_len; + if (mode_alloc <= new_mode_len) + { + mode_alloc = new_mode_len + 1; + mode = x2realloc (mode, &mode_alloc); + } + mode[mode_len] = ','; + strcpy (mode + mode_comma_len, arg); + mode_len = new_mode_len; + } break; case NO_PRESERVE_ROOT: preserve_root = false; @@ -417,12 +425,21 @@ main (int argc, char **argv) } } - if (modeind == 0 && reference_file == NULL) - modeind = optind++; + if (reference_file) + { + if (mode) + error (EXIT_FAILURE, 0, + _("cannot combine mode and --reference options")); + } + else + { + if (!mode) + mode = argv[optind++]; + } if (optind >= argc) { - if (modeind == 0 || modeind != argc - 1) + if (!mode || mode != argv[optind - 1]) error (0, 0, _("missing operand")); else error (0, 0, _("missing operand after %s"), quote (argv[argc - 1])); @@ -430,11 +447,10 @@ main (int argc, char **argv) } changes = (reference_file ? mode_create_from_ref (reference_file) - : mode_compile (argv[modeind], MODE_MASK_ALL)); + : mode_compile (mode, MODE_MASK_ALL)); if (changes == MODE_INVALID) - error (EXIT_FAILURE, 0, - _("invalid mode string: %s"), quote (argv[modeind])); + error (EXIT_FAILURE, 0, _("invalid mode: %s"), quote (mode)); else if (changes == MODE_MEMORY_EXHAUSTED) xalloc_die (); else if (changes == MODE_BAD_REFERENCE) |