diff options
| author | "Vladimir N. Oleynik" <dzo@simtreas.ru> | 2005-10-11 14:38:01 +0000 |
|---|---|---|
| committer | "Vladimir N. Oleynik" <dzo@simtreas.ru> | 2005-10-11 14:38:01 +0000 |
| commit | 064f04e7e2b1316f7c3de1ac7dd1fc4d4e108dd5 (patch) | |
| tree | dcf88d0a287b1f154984bfc0acb292631df2f1f3 | |
| parent | ff567f7943f50b88dea14cd27636168ba2d319b5 (diff) | |
| download | busybox-w32-064f04e7e2b1316f7c3de1ac7dd1fc4d4e108dd5.tar.gz busybox-w32-064f04e7e2b1316f7c3de1ac7dd1fc4d4e108dd5.tar.bz2 busybox-w32-064f04e7e2b1316f7c3de1ac7dd1fc4d4e108dd5.zip | |
- use complementally '!' to '?' - 'ask' is best 'free' char for this.
- more long opt compatibility, can set flag for long opt struct now
- more logic: check opt-depend requires and global requires, special for 'id' and 'start-stop-daemon' applets.
| -rw-r--r-- | archival/ar.c | 2 | ||||
| -rw-r--r-- | archival/dpkg_deb.c | 2 | ||||
| -rw-r--r-- | archival/tar.c | 2 | ||||
| -rw-r--r-- | coreutils/date.c | 2 | ||||
| -rw-r--r-- | coreutils/id.c | 21 | ||||
| -rw-r--r-- | coreutils/install.c | 2 | ||||
| -rw-r--r-- | debianutils/start_stop_daemon.c | 28 | ||||
| -rw-r--r-- | libbb/getopt_ulflags.c | 108 | ||||
| -rw-r--r-- | util-linux/hwclock.c | 2 |
9 files changed, 100 insertions, 69 deletions
diff --git a/archival/ar.c b/archival/ar.c index 411a25e0a..70deb5cbb 100644 --- a/archival/ar.c +++ b/archival/ar.c | |||
| @@ -66,7 +66,7 @@ extern int ar_main(int argc, char **argv) | |||
| 66 | 66 | ||
| 67 | archive_handle = init_handle(); | 67 | archive_handle = init_handle(); |
| 68 | 68 | ||
| 69 | bb_opt_complementally = "!p~tx:t~px:x~pt"; | 69 | bb_opt_complementally = "?p~tx:t~px:x~pt"; |
| 70 | opt = bb_getopt_ulflags(argc, argv, "ptxovcr"); | 70 | opt = bb_getopt_ulflags(argc, argv, "ptxovcr"); |
| 71 | 71 | ||
| 72 | if ((opt == 0) || (optind == argc)) { | 72 | if ((opt == 0) || (optind == argc)) { |
diff --git a/archival/dpkg_deb.c b/archival/dpkg_deb.c index 1ceaa60e0..f38fb6195 100644 --- a/archival/dpkg_deb.c +++ b/archival/dpkg_deb.c | |||
| @@ -55,7 +55,7 @@ extern int dpkg_deb_main(int argc, char **argv) | |||
| 55 | control_tar_llist = llist_add_to(control_tar_llist, "control.tar.bz2"); | 55 | control_tar_llist = llist_add_to(control_tar_llist, "control.tar.bz2"); |
| 56 | #endif | 56 | #endif |
| 57 | 57 | ||
| 58 | bb_opt_complementally = "!c~efXx:e~cfXx:f~ceXx:X~cefx:x~cefX"; | 58 | bb_opt_complementally = "?c~efXx:e~cfXx:f~ceXx:X~cefx:x~cefX"; |
| 59 | opt = bb_getopt_ulflags(argc, argv, "cefXx"); | 59 | opt = bb_getopt_ulflags(argc, argv, "cefXx"); |
| 60 | 60 | ||
| 61 | if (opt & DPKG_DEB_OPT_CONTENTS) { | 61 | if (opt & DPKG_DEB_OPT_CONTENTS) { |
diff --git a/archival/tar.c b/archival/tar.c index f6750ae33..d98426748 100644 --- a/archival/tar.c +++ b/archival/tar.c | |||
| @@ -702,7 +702,7 @@ int tar_main(int argc, char **argv) | |||
| 702 | tar_handle = init_handle(); | 702 | tar_handle = init_handle(); |
| 703 | tar_handle->flags = ARCHIVE_CREATE_LEADING_DIRS | ARCHIVE_PRESERVE_DATE | ARCHIVE_EXTRACT_UNCONDITIONAL; | 703 | tar_handle->flags = ARCHIVE_CREATE_LEADING_DIRS | ARCHIVE_PRESERVE_DATE | ARCHIVE_EXTRACT_UNCONDITIONAL; |
| 704 | 704 | ||
| 705 | bb_opt_complementally = "!c~tx:t~cx:x~ct:X*:T*"; | 705 | bb_opt_complementally = "?c~tx:t~cx:x~ct:X*:T*"; |
| 706 | #ifdef CONFIG_FEATURE_TAR_LONG_OPTIONS | 706 | #ifdef CONFIG_FEATURE_TAR_LONG_OPTIONS |
| 707 | bb_applet_long_options = tar_long_options; | 707 | bb_applet_long_options = tar_long_options; |
| 708 | #endif | 708 | #endif |
diff --git a/coreutils/date.c b/coreutils/date.c index 9583a0036..5ee2c74e8 100644 --- a/coreutils/date.c +++ b/coreutils/date.c | |||
| @@ -151,7 +151,7 @@ int date_main(int argc, char **argv) | |||
| 151 | #else | 151 | #else |
| 152 | # define GETOPT_ISOFMT | 152 | # define GETOPT_ISOFMT |
| 153 | #endif | 153 | #endif |
| 154 | bb_opt_complementally = "!d~ds:s~ds"; | 154 | bb_opt_complementally = "?d~ds:s~ds"; |
| 155 | opt = bb_getopt_ulflags(argc, argv, "Rs:ud:r:" GETOPT_ISOFMT, | 155 | opt = bb_getopt_ulflags(argc, argv, "Rs:ud:r:" GETOPT_ISOFMT, |
| 156 | &date_str, &date_str, &filename | 156 | &date_str, &date_str, &filename |
| 157 | #ifdef CONFIG_FEATURE_DATE_ISOFMT | 157 | #ifdef CONFIG_FEATURE_DATE_ISOFMT |
diff --git a/coreutils/id.c b/coreutils/id.c index 28050ddf2..14497b416 100644 --- a/coreutils/id.c +++ b/coreutils/id.c | |||
| @@ -22,7 +22,7 @@ | |||
| 22 | 22 | ||
| 23 | /* BB_AUDIT SUSv3 _NOT_ compliant -- option -G is not currently supported. */ | 23 | /* BB_AUDIT SUSv3 _NOT_ compliant -- option -G is not currently supported. */ |
| 24 | /* Hacked by Tito Ragusa (C) 2004 to handle usernames of whatever length and to | 24 | /* Hacked by Tito Ragusa (C) 2004 to handle usernames of whatever length and to |
| 25 | * be more similar to GNU id. | 25 | * be more similar to GNU id. |
| 26 | */ | 26 | */ |
| 27 | 27 | ||
| 28 | #include "busybox.h" | 28 | #include "busybox.h" |
| @@ -41,10 +41,10 @@ | |||
| 41 | #define JUST_GROUP 8 | 41 | #define JUST_GROUP 8 |
| 42 | 42 | ||
| 43 | static short printf_full(unsigned int id, const char *arg, const char prefix) | 43 | static short printf_full(unsigned int id, const char *arg, const char prefix) |
| 44 | { | 44 | { |
| 45 | const char *fmt = "%cid=%u"; | 45 | const char *fmt = "%cid=%u"; |
| 46 | short status=EXIT_FAILURE; | 46 | short status=EXIT_FAILURE; |
| 47 | 47 | ||
| 48 | if(arg) { | 48 | if(arg) { |
| 49 | fmt = "%cid=%u(%s)"; | 49 | fmt = "%cid=%u(%s)"; |
| 50 | status=EXIT_SUCCESS; | 50 | status=EXIT_SUCCESS; |
| @@ -61,15 +61,14 @@ extern int id_main(int argc, char **argv) | |||
| 61 | unsigned long flags; | 61 | unsigned long flags; |
| 62 | short status; | 62 | short status; |
| 63 | 63 | ||
| 64 | bb_opt_complementally = "!u~g:g~u"; | 64 | /* Don't allow -n -r -nr -ug -rug -nug -rnug */ |
| 65 | bb_opt_complementally = "?u~g:g~u:r?ug:n?ug"; | ||
| 65 | flags = bb_getopt_ulflags(argc, argv, "rnug"); | 66 | flags = bb_getopt_ulflags(argc, argv, "rnug"); |
| 66 | 67 | ||
| 67 | /* Don't allow -n -r -nr */ | ||
| 68 | if ((flags <= 3 && flags > 0) | ||
| 69 | /* Don't allow more than one username */ | 68 | /* Don't allow more than one username */ |
| 70 | || (argc > optind + 1)) | 69 | if (argc > (optind + 1)) |
| 71 | bb_show_usage(); | 70 | bb_show_usage(); |
| 72 | 71 | ||
| 73 | /* This values could be overwritten later */ | 72 | /* This values could be overwritten later */ |
| 74 | uid = geteuid(); | 73 | uid = geteuid(); |
| 75 | gid = getegid(); | 74 | gid = getegid(); |
| @@ -77,13 +76,13 @@ extern int id_main(int argc, char **argv) | |||
| 77 | uid = getuid(); | 76 | uid = getuid(); |
| 78 | gid = getgid(); | 77 | gid = getgid(); |
| 79 | } | 78 | } |
| 80 | 79 | ||
| 81 | if(argv[optind]) { | 80 | if(argv[optind]) { |
| 82 | p=getpwnam(argv[optind]); | 81 | p=getpwnam(argv[optind]); |
| 83 | /* bb_xgetpwnam is needed because it exits on failure */ | 82 | /* bb_xgetpwnam is needed because it exits on failure */ |
| 84 | uid = bb_xgetpwnam(argv[optind]); | 83 | uid = bb_xgetpwnam(argv[optind]); |
| 85 | gid = p->pw_gid; | 84 | gid = p->pw_gid; |
| 86 | /* in this case PRINT_REAL is the same */ | 85 | /* in this case PRINT_REAL is the same */ |
| 87 | } | 86 | } |
| 88 | 87 | ||
| 89 | if(flags & (JUST_GROUP | JUST_USER)) { | 88 | if(flags & (JUST_GROUP | JUST_USER)) { |
| @@ -94,7 +93,7 @@ extern int id_main(int argc, char **argv) | |||
| 94 | } else { | 93 | } else { |
| 95 | bb_printf("%u\n",(flags & JUST_USER) ? uid : gid); | 94 | bb_printf("%u\n",(flags & JUST_USER) ? uid : gid); |
| 96 | } | 95 | } |
| 97 | /* exit */ | 96 | /* exit */ |
| 98 | bb_fflush_stdout_and_exit(EXIT_SUCCESS); | 97 | bb_fflush_stdout_and_exit(EXIT_SUCCESS); |
| 99 | } | 98 | } |
| 100 | 99 | ||
diff --git a/coreutils/install.c b/coreutils/install.c index 9fcb75405..9e5eb6037 100644 --- a/coreutils/install.c +++ b/coreutils/install.c | |||
| @@ -61,7 +61,7 @@ extern int install_main(int argc, char **argv) | |||
| 61 | int ret = EXIT_SUCCESS, flags, i, isdir; | 61 | int ret = EXIT_SUCCESS, flags, i, isdir; |
| 62 | 62 | ||
| 63 | bb_applet_long_options = install_long_options; | 63 | bb_applet_long_options = install_long_options; |
| 64 | bb_opt_complementally = "!s~d:d~s"; | 64 | bb_opt_complementally = "?s~d:d~s"; |
| 65 | /* -c exists for backwards compatability, its needed */ | 65 | /* -c exists for backwards compatability, its needed */ |
| 66 | flags = bb_getopt_ulflags(argc, argv, "cdpsg:m:o:", &gid_str, &mode_str, &uid_str); /* 'a' must be 2nd */ | 66 | flags = bb_getopt_ulflags(argc, argv, "cdpsg:m:o:", &gid_str, &mode_str, &uid_str); /* 'a' must be 2nd */ |
| 67 | 67 | ||
diff --git a/debianutils/start_stop_daemon.c b/debianutils/start_stop_daemon.c index f9310af8d..b6c463556 100644 --- a/debianutils/start_stop_daemon.c +++ b/debianutils/start_stop_daemon.c | |||
| @@ -204,18 +204,18 @@ do_stop(void) | |||
| 204 | 204 | ||
| 205 | 205 | ||
| 206 | static const struct option ssd_long_options[] = { | 206 | static const struct option ssd_long_options[] = { |
| 207 | { "stop", 0, NULL, 'K' }, | 207 | { "stop", 0, NULL, 'K' }, |
| 208 | { "start", 0, NULL, 'S' }, | 208 | { "start", 0, NULL, 'S' }, |
| 209 | { "background", 0, NULL, 'b' }, | 209 | { "background", 0, NULL, 'b' }, |
| 210 | { "quiet", 0, NULL, 'q' }, | 210 | { "quiet", 0, NULL, 'q' }, |
| 211 | { "make-pidfile", 0, NULL, 'm' }, | 211 | { "make-pidfile", 0, NULL, 'm' }, |
| 212 | { "startas", 1, NULL, 'a' }, | 212 | { "startas", 1, NULL, 'a' }, |
| 213 | { "name", 1, NULL, 'n' }, | 213 | { "name", 1, NULL, 'n' }, |
| 214 | { "signal", 1, NULL, 's' }, | 214 | { "signal", 1, NULL, 's' }, |
| 215 | { "user", 1, NULL, 'u' }, | 215 | { "user", 1, NULL, 'u' }, |
| 216 | { "exec", 1, NULL, 'x' }, | 216 | { "exec", 1, NULL, 'x' }, |
| 217 | { "pidfile", 1, NULL, 'p' }, | 217 | { "pidfile", 1, NULL, 'p' }, |
| 218 | { 0, 0, 0, 0 } | 218 | { 0, 0, 0, 0 } |
| 219 | }; | 219 | }; |
| 220 | 220 | ||
| 221 | #define SSD_CTX_STOP 1 | 221 | #define SSD_CTX_STOP 1 |
| @@ -233,17 +233,13 @@ start_stop_daemon_main(int argc, char **argv) | |||
| 233 | 233 | ||
| 234 | bb_applet_long_options = ssd_long_options; | 234 | bb_applet_long_options = ssd_long_options; |
| 235 | 235 | ||
| 236 | bb_opt_complementally = "!K~S:S~K"; | 236 | /* Check required one context option was given */ |
| 237 | bb_opt_complementally = "?:K?K:S?S:K~S:S~K"; | ||
| 237 | opt = bb_getopt_ulflags(argc, argv, "KSbqma:n:s:u:x:p:", | 238 | opt = bb_getopt_ulflags(argc, argv, "KSbqma:n:s:u:x:p:", |
| 238 | &startas, &cmdname, &signame, &userspec, &execname, &pidfile); | 239 | &startas, &cmdname, &signame, &userspec, &execname, &pidfile); |
| 239 | 240 | ||
| 240 | /* Check required one context option was given */ | 241 | |
| 241 | if ((opt & (SSD_CTX_STOP | SSD_CTX_START)) == 0) { | 242 | quiet = opt & SSD_OPT_QUIET; |
| 242 | bb_show_usage(); | ||
| 243 | } | ||
| 244 | |||
| 245 | if (opt & SSD_OPT_QUIET) | ||
| 246 | quiet = 1; | ||
| 247 | 243 | ||
| 248 | if (signame) { | 244 | if (signame) { |
| 249 | signal_nr = bb_xgetlarg(signame, 10, 0, NSIG); | 245 | signal_nr = bb_xgetlarg(signame, 10, 0, NSIG); |
diff --git a/libbb/getopt_ulflags.c b/libbb/getopt_ulflags.c index 2e2ee0b6b..5f35c583c 100644 --- a/libbb/getopt_ulflags.c +++ b/libbb/getopt_ulflags.c | |||
| @@ -197,8 +197,9 @@ Special characters: | |||
| 197 | if (flags & BB_GETOPT_ERROR) | 197 | if (flags & BB_GETOPT_ERROR) |
| 198 | bb_show_usage(); | 198 | bb_show_usage(); |
| 199 | 199 | ||
| 200 | "!" If previous point set BB_GETOPT_ERROR, don`t return and call | 200 | "?" A "ask" as the first char in a bb_opt_complementally group give: |
| 201 | previous example internally | 201 | if previous point set BB_GETOPT_ERROR, don`t return and |
| 202 | call previous example internally | ||
| 202 | 203 | ||
| 203 | "*" A star after a char in bb_opt_complementally means that the | 204 | "*" A star after a char in bb_opt_complementally means that the |
| 204 | option can occur multiple times: | 205 | option can occur multiple times: |
| @@ -218,16 +219,38 @@ Special characters: | |||
| 218 | $ grep -e user -e root /etc/passwd | 219 | $ grep -e user -e root /etc/passwd |
| 219 | root:x:0:0:root:/root:/bin/bash | 220 | root:x:0:0:root:/root:/bin/bash |
| 220 | user:x:500:500::/home/user:/bin/bash | 221 | user:x:500:500::/home/user:/bin/bash |
| 222 | |||
| 223 | "?" A "ask" between main and group options causes the second of the two | ||
| 224 | to be depending required if first is given on the command line. | ||
| 225 | For example from "id" applet: | ||
| 226 | |||
| 227 | // Don't allow -n -r -rn -ug -rug -nug -rnug | ||
| 228 | bb_opt_complementally = "?u~g:g~u:r?ug:n?ug"; | ||
| 229 | flags = bb_getopt_ulflags(argc, argv, "rnug"); | ||
| 230 | |||
| 231 | This example allowed only: | ||
| 232 | $ id; id -u; id -g; id -ru; id -nu; id -rg; id -ng; id -rnu; id -rng | ||
| 233 | |||
| 234 | "?" A "ask" between equivalent options in bb_opt_complementally means | ||
| 235 | requires this option always, checked after switch off from | ||
| 236 | complementally logic | ||
| 237 | For example from "start-stop-daemon" applet: | ||
| 238 | |||
| 239 | // Don't allow -KS -SK, but -S or -K required | ||
| 240 | bb_opt_complementally = "?:K?K:S?S:K~S:S~K"; | ||
| 241 | flags = bb_getopt_ulflags(argc, argv, "KS...); | ||
| 242 | |||
| 221 | */ | 243 | */ |
| 222 | 244 | ||
| 223 | const char *bb_opt_complementally; | 245 | const char *bb_opt_complementally; |
| 224 | 246 | ||
| 225 | typedef struct { | 247 | typedef struct { |
| 226 | unsigned char opt; | 248 | int opt; |
| 227 | char list_flg; | 249 | int list_flg; |
| 228 | unsigned long switch_on; | 250 | unsigned long switch_on; |
| 229 | unsigned long switch_off; | 251 | unsigned long switch_off; |
| 230 | unsigned long incongruously; | 252 | unsigned long incongruously; |
| 253 | unsigned long requires; | ||
| 231 | void **optarg; /* char **optarg or llist_t **optarg */ | 254 | void **optarg; /* char **optarg or llist_t **optarg */ |
| 232 | int *counter; | 255 | int *counter; |
| 233 | } t_complementally; | 256 | } t_complementally; |
| @@ -245,17 +268,20 @@ unsigned long | |||
| 245 | bb_getopt_ulflags (int argc, char **argv, const char *applet_opts, ...) | 268 | bb_getopt_ulflags (int argc, char **argv, const char *applet_opts, ...) |
| 246 | { | 269 | { |
| 247 | unsigned long flags = 0; | 270 | unsigned long flags = 0; |
| 271 | unsigned long requires = 0; | ||
| 248 | t_complementally complementally[sizeof(flags) * 8 + 1]; | 272 | t_complementally complementally[sizeof(flags) * 8 + 1]; |
| 249 | int c; | 273 | int c; |
| 250 | const unsigned char *s; | 274 | const unsigned char *s; |
| 251 | t_complementally *on_off; | 275 | t_complementally *on_off; |
| 252 | va_list p; | 276 | va_list p; |
| 253 | const struct option *l_o; | 277 | const struct option *l_o; |
| 254 | char flg_show_usage_if_error = 0; | ||
| 255 | char flg_argv_is_opts = 0; | ||
| 256 | unsigned long trigger; | 278 | unsigned long trigger; |
| 257 | char **pargv = NULL; | 279 | char **pargv = NULL; |
| 258 | 280 | ||
| 281 | #define SHOW_USAGE_IF_ERROR 1 | ||
| 282 | #define ARGV_IS_OPTS 2 | ||
| 283 | int spec_flgs = 0; | ||
| 284 | |||
| 259 | va_start (p, applet_opts); | 285 | va_start (p, applet_opts); |
| 260 | 286 | ||
| 261 | /* skip GNU extension */ | 287 | /* skip GNU extension */ |
| @@ -265,16 +291,13 @@ bb_getopt_ulflags (int argc, char **argv, const char *applet_opts, ...) | |||
| 265 | 291 | ||
| 266 | c = 0; | 292 | c = 0; |
| 267 | on_off = complementally; | 293 | on_off = complementally; |
| 294 | memset(on_off, 0, sizeof(complementally)); | ||
| 295 | |||
| 268 | for (; *s; s++) { | 296 | for (; *s; s++) { |
| 269 | if(c >= (int)(sizeof(flags)*8)) | 297 | if(c >= (int)(sizeof(flags)*8)) |
| 270 | break; | 298 | break; |
| 271 | on_off->opt = *s; | 299 | on_off->opt = *s; |
| 272 | on_off->switch_on = (1 << c); | 300 | on_off->switch_on = (1 << c); |
| 273 | on_off->list_flg = 0; | ||
| 274 | on_off->switch_off = 0; | ||
| 275 | on_off->incongruously = 0; | ||
| 276 | on_off->optarg = NULL; | ||
| 277 | on_off->counter = NULL; | ||
| 278 | if (s[1] == ':') { | 301 | if (s[1] == ':') { |
| 279 | on_off->optarg = va_arg (p, void **); | 302 | on_off->optarg = va_arg (p, void **); |
| 280 | do | 303 | do |
| @@ -284,9 +307,10 @@ bb_getopt_ulflags (int argc, char **argv, const char *applet_opts, ...) | |||
| 284 | on_off++; | 307 | on_off++; |
| 285 | c++; | 308 | c++; |
| 286 | } | 309 | } |
| 287 | on_off->opt = 0; | ||
| 288 | 310 | ||
| 289 | for(l_o = bb_applet_long_options; l_o->name; l_o++) { | 311 | for(l_o = bb_applet_long_options; l_o->name; l_o++) { |
| 312 | if(l_o->flag) | ||
| 313 | continue; | ||
| 290 | for(on_off = complementally; on_off->opt != 0; on_off++) | 314 | for(on_off = complementally; on_off->opt != 0; on_off++) |
| 291 | if(on_off->opt == l_o->val) | 315 | if(on_off->opt == l_o->val) |
| 292 | break; | 316 | break; |
| @@ -295,16 +319,8 @@ bb_getopt_ulflags (int argc, char **argv, const char *applet_opts, ...) | |||
| 295 | break; | 319 | break; |
| 296 | on_off->opt = l_o->val; | 320 | on_off->opt = l_o->val; |
| 297 | on_off->switch_on = (1 << c); | 321 | on_off->switch_on = (1 << c); |
| 298 | on_off->list_flg = 0; | ||
| 299 | on_off->switch_off = 0; | ||
| 300 | on_off->incongruously = 0; | ||
| 301 | on_off->counter = NULL; | ||
| 302 | if(l_o->has_arg != no_argument) | 322 | if(l_o->has_arg != no_argument) |
| 303 | on_off->optarg = va_arg (p, void **); | 323 | on_off->optarg = va_arg (p, void **); |
| 304 | else | ||
| 305 | on_off->optarg = NULL; | ||
| 306 | on_off++; | ||
| 307 | on_off->opt = 0; | ||
| 308 | c++; | 324 | c++; |
| 309 | } | 325 | } |
| 310 | } | 326 | } |
| @@ -318,12 +334,12 @@ bb_getopt_ulflags (int argc, char **argv, const char *applet_opts, ...) | |||
| 318 | } | 334 | } |
| 319 | if (c) | 335 | if (c) |
| 320 | continue; | 336 | continue; |
| 321 | if(*s == '!') { | 337 | if(*s == '?') { |
| 322 | flg_show_usage_if_error = '!'; | 338 | spec_flgs |= SHOW_USAGE_IF_ERROR; |
| 323 | continue; | 339 | continue; |
| 324 | } | 340 | } |
| 325 | if(*s == '-') { | 341 | if(*s == '-') { |
| 326 | flg_argv_is_opts = '-'; | 342 | spec_flgs |= ARGV_IS_OPTS; |
| 327 | continue; | 343 | continue; |
| 328 | } | 344 | } |
| 329 | for (on_off = complementally; on_off->opt; on_off++) | 345 | for (on_off = complementally; on_off->opt; on_off++) |
| @@ -331,18 +347,32 @@ bb_getopt_ulflags (int argc, char **argv, const char *applet_opts, ...) | |||
| 331 | break; | 347 | break; |
| 332 | pair = on_off; | 348 | pair = on_off; |
| 333 | for(s++; *s && *s != ':'; s++) { | 349 | for(s++; *s && *s != ':'; s++) { |
| 334 | if (*s == '-' || *s == '~') { | 350 | if (*s == '-' || *s == '~' || *s == '?') { |
| 335 | c = *s; | 351 | c = *s; |
| 336 | } else if(*s == '*') { | 352 | } else if(*s == '*') { |
| 337 | pair->list_flg++; | 353 | pair->list_flg++; |
| 338 | } else { | 354 | } else { |
| 339 | unsigned long *pair_switch = &(pair->switch_on); | 355 | unsigned long *pair_switch; |
| 340 | if(c) | 356 | |
| 341 | pair_switch = c == '-' ? &(pair->switch_off) : &(pair->incongruously); | 357 | switch(c) { |
| 358 | case '-': | ||
| 359 | pair_switch = &(pair->switch_off); | ||
| 360 | break; | ||
| 361 | case '~': | ||
| 362 | pair_switch = &(pair->incongruously); | ||
| 363 | break; | ||
| 364 | case '?': | ||
| 365 | pair_switch = &(pair->requires); | ||
| 366 | break; | ||
| 367 | default: | ||
| 368 | pair_switch = &(pair->switch_on); | ||
| 369 | } | ||
| 342 | for (on_off = complementally; on_off->opt; on_off++) | 370 | for (on_off = complementally; on_off->opt; on_off++) |
| 343 | if (on_off->opt == *s) { | 371 | if (on_off->opt == *s) { |
| 344 | if(pair_switch == &(on_off->switch_on)) | 372 | if(pair_switch == &(on_off->switch_on)) |
| 345 | on_off->counter = va_arg (p, int *); | 373 | on_off->counter = va_arg (p, int *); |
| 374 | else if(pair_switch == &(on_off->requires)) | ||
| 375 | requires |= on_off->switch_on; | ||
| 346 | else | 376 | else |
| 347 | *pair_switch |= on_off->switch_on; | 377 | *pair_switch |= on_off->switch_on; |
| 348 | break; | 378 | break; |
| @@ -353,15 +383,16 @@ bb_getopt_ulflags (int argc, char **argv, const char *applet_opts, ...) | |||
| 353 | } | 383 | } |
| 354 | 384 | ||
| 355 | while ((c = getopt_long (argc, argv, applet_opts, | 385 | while ((c = getopt_long (argc, argv, applet_opts, |
| 356 | bb_applet_long_options, NULL)) > 0) { | 386 | bb_applet_long_options, NULL)) >= 0) { |
| 357 | 387 | ||
| 358 | loop_arg_is_opt: | 388 | loop_arg_is_opt: |
| 359 | for (on_off = complementally; on_off->opt != c; on_off++) { | 389 | for (on_off = complementally; on_off->opt != c; on_off++) { |
| 360 | if(!on_off->opt) | 390 | /* c==0 if long opt have non NULL flag */ |
| 391 | if(on_off->opt == 0 && c != 0) | ||
| 361 | bb_show_usage (); | 392 | bb_show_usage (); |
| 362 | } | 393 | } |
| 363 | if(flags & on_off->incongruously) { | 394 | if(flags & on_off->incongruously) { |
| 364 | if(flg_show_usage_if_error) | 395 | if((spec_flgs & SHOW_USAGE_IF_ERROR)) |
| 365 | bb_show_usage (); | 396 | bb_show_usage (); |
| 366 | flags |= BB_GETOPT_ERROR; | 397 | flags |= BB_GETOPT_ERROR; |
| 367 | } | 398 | } |
| @@ -377,15 +408,13 @@ loop_arg_is_opt: | |||
| 377 | } else if (on_off->optarg) { | 408 | } else if (on_off->optarg) { |
| 378 | *(char **)(on_off->optarg) = optarg; | 409 | *(char **)(on_off->optarg) = optarg; |
| 379 | } | 410 | } |
| 380 | if(flg_argv_is_opts == 'p') | 411 | if(pargv != NULL) |
| 381 | break; | 412 | break; |
| 382 | } | 413 | } |
| 383 | if(flg_argv_is_opts) { | 414 | if((spec_flgs & ARGV_IS_OPTS)) { |
| 384 | /* process argv is option, for example "ps" applet */ | 415 | /* process argv is option, for example "ps" applet */ |
| 385 | if(flg_argv_is_opts == '-') { | 416 | if(pargv == NULL) |
| 386 | flg_argv_is_opts = 'p'; | ||
| 387 | pargv = argv + optind; | 417 | pargv = argv + optind; |
| 388 | } | ||
| 389 | while(*pargv) { | 418 | while(*pargv) { |
| 390 | c = **pargv; | 419 | c = **pargv; |
| 391 | if(c == '\0') { | 420 | if(c == '\0') { |
| @@ -396,6 +425,13 @@ loop_arg_is_opt: | |||
| 396 | } | 425 | } |
| 397 | } | 426 | } |
| 398 | } | 427 | } |
| 399 | 428 | /* check depending requires for given options */ | |
| 429 | for (on_off = complementally; on_off->opt; on_off++) { | ||
| 430 | if(on_off->requires && (flags & on_off->switch_on) && | ||
| 431 | (flags & on_off->requires) == 0) | ||
| 432 | bb_show_usage (); | ||
| 433 | } | ||
| 434 | if(requires && (flags & requires) == 0) | ||
| 435 | bb_show_usage (); | ||
| 400 | return flags; | 436 | return flags; |
| 401 | } | 437 | } |
diff --git a/util-linux/hwclock.c b/util-linux/hwclock.c index 45959e7a1..3021442b7 100644 --- a/util-linux/hwclock.c +++ b/util-linux/hwclock.c | |||
| @@ -209,7 +209,7 @@ static const struct option hwclock_long_options[] = { | |||
| 209 | bb_applet_long_options = hwclock_long_options; | 209 | bb_applet_long_options = hwclock_long_options; |
| 210 | #endif | 210 | #endif |
| 211 | 211 | ||
| 212 | bb_opt_complementally = "!r~ws:w~rs:s~wr:l~u:u~l"; | 212 | bb_opt_complementally = "?r~ws:w~rs:s~wr:l~u:u~l"; |
| 213 | opt = bb_getopt_ulflags(argc, argv, "lursw"); | 213 | opt = bb_getopt_ulflags(argc, argv, "lursw"); |
| 214 | 214 | ||
| 215 | /* If -u or -l wasn't given check if we are using utc */ | 215 | /* If -u or -l wasn't given check if we are using utc */ |
