- new bb_opt_complementally syntax, use [-:?] only - 'free' chars

- new bb_getopt_ulflags features: check max and min args, convert first argv to options special for ar and tar applets
- use bb_default_error_retval for env applet
This commit is contained in:
"Vladimir N. Oleynik" 2005-10-14 09:56:52 +00:00
parent 8c7a7e6e63
commit f704b27b5b
15 changed files with 153 additions and 114 deletions

View File

@ -68,16 +68,9 @@ extern int ar_main(int argc, char **argv)
archive_handle = init_handle();
/* Prepend '-' to the first argument if required */
if (argv[1][0] != '-')
argv[1] = bb_xasprintf("-%s", argv[1]);
bb_opt_complementally = "?p~tx:t~px:x~pt";
bb_opt_complementally = "--:p:t:x:-1:?:p--tx:t--px:x--pt";
opt = bb_getopt_ulflags(argc, argv, "ptxovcr");
if ((opt == 0) || (optind == argc)) {
bb_show_usage();
}
if (opt & AR_CTX_PRINT) {
archive_handle->action_data = data_extract_to_stdout;
}

View File

@ -55,7 +55,7 @@ extern int dpkg_deb_main(int argc, char **argv)
control_tar_llist = llist_add_to(control_tar_llist, "control.tar.bz2");
#endif
bb_opt_complementally = "?c~efXx:e~cfXx:f~ceXx:X~cefx:x~cefX";
bb_opt_complementally = "?c--efXx:e--cfXx:f--ceXx:X--cefx:x--cefX";
opt = bb_getopt_ulflags(argc, argv, "cefXx");
if (opt & DPKG_DEB_OPT_CONTENTS) {

View File

@ -690,18 +690,16 @@ int tar_main(int argc, char **argv)
unsigned long opt;
unsigned long ctx_flag = 0;
/* Prepend '-' to the first argument if required */
if (argv[1][0] != '-')
argv[1] = bb_xasprintf("-%s", argv[1]);
/* Initialise default values */
tar_handle = init_handle();
tar_handle->flags = ARCHIVE_CREATE_LEADING_DIRS | ARCHIVE_PRESERVE_DATE | ARCHIVE_EXTRACT_UNCONDITIONAL;
/* Prepend '-' to the first argument if required */
#ifdef CONFIG_FEATURE_TAR_CREATE
bb_opt_complementally = "?:c?c:t?t:x?x:c~tx:t~cx:x~ct:X*:T*";
bb_opt_complementally = "--:-1:X::T::c:t:x:?:c--tx:t--cx:x--ct";
#else
bb_opt_complementally = "?:t?t:x?x:t~x:x~t:X*:T*";
bb_opt_complementally = "--:-1:X::T::t:x:?:t--x:x--t";
#endif
#ifdef CONFIG_FEATURE_TAR_LONG_OPTIONS
bb_applet_long_options = tar_long_options;

View File

@ -294,7 +294,7 @@ extern int cut_main(int argc, char **argv)
unsigned long opt;
char *sopt, *sdopt;
bb_opt_complementally = "b~bcf:c~bcf:f~bcf";
bb_opt_complementally = "b--bcf:c--bcf:f--bcf";
opt = bb_getopt_ulflags(argc, argv, optstring, &sopt, &sopt, &sopt, &sdopt);
part = opt & (OPT_BYTE_FLGS|OPT_CHAR_FLGS|OPT_FIELDS_FLGS);
if(part == 0)

View File

@ -149,7 +149,7 @@ int date_main(int argc, char **argv)
#else
# define GETOPT_ISOFMT
#endif
bb_opt_complementally = "?d~s:s~d";
bb_opt_complementally = "?:d--s:s--d";
opt = bb_getopt_ulflags(argc, argv, "Rs:ud:r:" GETOPT_ISOFMT,
&date_str, &date_str, &filename
#ifdef CONFIG_FEATURE_DATE_ISOFMT

View File

@ -38,7 +38,7 @@
* - correct "-" option usage
* - multiple "-u unsetenv" support
* - GNU long option support
* - save errno after exec failed before bb_perror_msg()
* - use bb_default_error_retval
*/
@ -65,7 +65,7 @@ extern int env_main(int argc, char** argv)
llist_t *unset_env = NULL;
extern char **environ;
bb_opt_complementally = "u*";
bb_opt_complementally = "u::";
bb_applet_long_options = env_long_options;
opt = bb_getopt_ulflags(argc, argv, "+iu:", &unset_env);
@ -93,12 +93,10 @@ extern int env_main(int argc, char** argv)
}
if (*argv) {
int er;
execvp(*argv, argv);
er = errno;
bb_perror_msg("%s", *argv); /* Avoid multibyte problems. */
return (er == ENOENT) ? 127 : 126; /* SUSv3-mandated exit codes. */
/* SUSv3-mandated exit codes. */
bb_default_error_retval = (errno == ENOENT) ? 127 : 126;
bb_perror_msg_and_die("%s", *argv);
}
for (ep = environ; *ep; ep++) {

View File

@ -62,12 +62,9 @@ extern int id_main(int argc, char **argv)
short status;
/* Don't allow -n -r -nr -ug -rug -nug -rnug */
bb_opt_complementally = "?u~g:g~u:r?ug:n?ug";
flags = bb_getopt_ulflags(argc, argv, "rnug");
/* Don't allow more than one username */
if (argc > (optind + 1))
bb_show_usage();
bb_opt_complementally = "?1:?:u--g:g--u:r?ug:n?ug";
flags = bb_getopt_ulflags(argc, argv, "rnug");
/* This values could be overwritten later */
uid = geteuid();

View File

@ -61,7 +61,7 @@ extern int install_main(int argc, char **argv)
int ret = EXIT_SUCCESS, flags, i, isdir;
bb_applet_long_options = install_long_options;
bb_opt_complementally = "?s~d:d~s";
bb_opt_complementally = "?:s--d:d--s";
/* -c exists for backwards compatability, its needed */
flags = bb_getopt_ulflags(argc, argv, "cdpsg:m:o:", &gid_str, &mode_str, &uid_str); /* 'a' must be 2nd */

View File

@ -234,9 +234,9 @@ start_stop_daemon_main(int argc, char **argv)
bb_applet_long_options = ssd_long_options;
/* Check required one context option was given */
bb_opt_complementally = "?:K?K:S?S:K~S:S~K";
bb_opt_complementally = "K:S:?:K--S:S--K";
opt = bb_getopt_ulflags(argc, argv, "KSbqma:n:s:u:x:p:",
&startas, &cmdname, &signame, &userspec, &execname, &pidfile);
&startas, &cmdname, &signame, &userspec, &execname, &pidfile);
quiet = opt & SSD_OPT_QUIET;

View File

@ -264,7 +264,7 @@ extern int grep_main(int argc, char **argv)
char *slines_before;
char *Copt;
bb_opt_complementally = "H-h:e*:f*:C-AB";
bb_opt_complementally = "H-h:e::f::C-AB";
opt = bb_getopt_ulflags(argc, argv,
GREP_OPTS GREP_OPT_CONTEXT OPT_EGREP,
&pattern_head, &fopt,
@ -299,7 +299,7 @@ extern int grep_main(int argc, char **argv)
}
#else
/* with auto sanity checks */
bb_opt_complementally = "H-h:e*:f*:c-n:q-n:l-n";
bb_opt_complementally = "H-h:e::f::c-n:q-n:l-n";
opt = bb_getopt_ulflags(argc, argv, GREP_OPTS OPT_EGREP,
&pattern_head, &fopt);
#endif

View File

@ -66,7 +66,7 @@ bb_getopt_ulflags (int argc, char **argv, const char *applet_opts, ...)
&pointer_to_arg_for_c, &pointer_to_arg_for_d);
The type of the pointer (char* or llist_t *) may be controlled
by the "*" special character that is set in the external string
by the "::" special separator that is set in the external string
bb_opt_complementally (see below for more info).
static const struct option bb_default_long_options[]
@ -127,13 +127,13 @@ const char *bb_opt_complementally
w_counter is a pointer to an integer. It has to be passed to
bb_getopt_ulflags() after all other option argument sinks.
For example: accept multiple -v to indicate the level of verbosity and
for each -b optarg, add optarg to my_b. Finally, if b is given, turn off
c and vice versa:
For example: accept multiple -v to indicate the level of verbosity
and for each -b optarg, add optarg to my_b. Finally, if b is given,
turn off c and vice versa:
llist_t *my_b = NULL;
int verbose_level = 0;
bb_opt_complementally = "vv:b*:b-c:c-b";
bb_opt_complementally = "vv:b::b-c:c-b";
f = bb_getopt_ulflags(argc, argv, "vb:c", &my_b, &verbose_level);
if((f & 2)) // -c after -b unset this -b flag
while (my_b) { dosomething_with(my_b->data) ; my_b = my_b->link; }
@ -164,15 +164,14 @@ Special characters:
opt = bb_getopt_ulflags(argc, argv, "sd:x", &smax_print_depth);
if (opt & 2) {
max_print_depth = bb_xgetularg10_bnd(smax_print_depth,
0, INT_MAX);
max_print_depth = atoi(smax_print_depth);
}
if(opt & 4)
printf("Detected odd -x usaging\n");
"-" A minus as the first char in a bb_opt_complementally group means to
convert the arguments as option.
For example:
"-" A dash as the first char in a bb_opt_complementally group means to
convert the arguments as option. Next char for this case can`t set
[0-9], recomended use ':' or end of line. For example:
bb_opt_complementally = "-:w-x:x-w";
bb_getopt_ulflags(argc, argv, "wx");
@ -180,7 +179,10 @@ Special characters:
Allows any arguments to be given without a dash (./program w x)
as well as with a dash (./program -x). Why unset -w see above.
"~" A tilde between two options, or between an option and a group
"-N" A dash as the first char in a bb_opt_complementally group with
number 0-9 as one char is means check minimal arguments required.
"--" A double dash between two options, or between an option and a group
of options, means that they are mutually exclusive. Unlike
the "-" case above, an error will be forced if the options
are used together.
@ -189,7 +191,7 @@ Special characters:
The cut applet must have only one type of list specified, so
-b, -c and -f are mutally exclusive and should raise an error
if specified together. In this case you must set
bb_opt_complementally = "b~cf:c~bf:f~bc". If two of the
bb_opt_complementally = "b--cf:c--bf:f--bc". If two of the
mutually exclusive options are found, bb_getopt_ulflags's
return value will have the error flag set (BB_GETOPT_ERROR) so
that we can check for it:
@ -199,9 +201,13 @@ Special characters:
"?" A "ask" as the first char in a bb_opt_complementally group give:
if previous point set BB_GETOPT_ERROR, don`t return and
call previous example internally
call previous example internally. Next char for this case can`t
set to [0-9], recomended use ':' or end of line.
"*" A star after a char in bb_opt_complementally means that the
"?N" A "ask" as the first char in a bb_opt_complementally group with
number 0-9 as one char is means check maximal arguments possible.
"::" A double colon after a char in bb_opt_complementally means that the
option can occur multiple times:
For example:
@ -213,33 +219,45 @@ Special characters:
(this pointer must be initializated to NULL if the list is empty
as required by *llist_add_to(llist_t *old_head, char *new_item).)
bb_opt_complementally = "e*";
bb_opt_complementally = "e::";
bb_getopt_ulflags(argc, argv, "e:", &patterns);
$ grep -e user -e root /etc/passwd
root:x:0:0:root:/root:/bin/bash
user:x:500:500::/home/user:/bin/bash
"--" A double dash as the first char in a bb_opt_complementally group
means make first argv[1] as option always as may be added -, special
for "ar" and "tar" applets.
"?" A "ask" between main and group options causes the second of the two
to be depending required if first is given on the command line.
to be depending required as or if first is given on the command line.
For example from "id" applet:
// Don't allow -n -r -rn -ug -rug -nug -rnug
bb_opt_complementally = "?u~g:g~u:r?ug:n?ug";
bb_opt_complementally = "r?ug:n?ug:?u--g:g--u";
flags = bb_getopt_ulflags(argc, argv, "rnug");
This example allowed only:
$ id; id -u; id -g; id -ru; id -nu; id -rg; id -ng; id -rnu; id -rng
"?" A "ask" between equivalent options in bb_opt_complementally means
requires this option always, checked after switch off from
complementally logic
"X" A one options in bb_opt_complementally group means
requires this option always with "or" logic if more one specified,
checked after switch off from complementally logic.
For example from "start-stop-daemon" applet:
// Don't allow -KS -SK, but -S or -K required
bb_opt_complementally = "?:K?K:S?S:K~S:S~K";
bb_opt_complementally = "K:S:?K--S:S--K";
flags = bb_getopt_ulflags(argc, argv, "KS...);
"x--x" give error if double or more used -x option
Don`t forget ':' store. For example "?322-22-23X-x-a" interpretet as
"?3:22:-2:2-2:2-3Xa:2--x": max args is 3, count -2 usaged, min args is 2,
-2 option triggered, unset -3 and -X and -a if -2 any usaged, give error if
after -2 the -x option usaged.
*/
const char *bb_opt_complementally;
@ -277,22 +295,25 @@ bb_getopt_ulflags (int argc, char **argv, const char *applet_opts, ...)
const struct option *l_o;
unsigned long trigger;
char **pargv = NULL;
int min_arg = 0;
int max_arg = -1;
#define SHOW_USAGE_IF_ERROR 1
#define ARGV_IS_OPTS 2
#define SHOW_USAGE_IF_ERROR 1
#define ALL_ARGV_IS_OPTS 2
#define FIRST_ARGV_IS_OPT 4
#define FREE_FIRST_ARGV_IS_OPT 8
int spec_flgs = 0;
va_start (p, applet_opts);
/* skip GNU extension */
s = applet_opts;
if(*s == '+' || *s == '-')
s++;
c = 0;
on_off = complementally;
memset(on_off, 0, sizeof(complementally));
/* skip GNU extension */
s = applet_opts;
if(*s == '+' || *s == '-')
s++;
for (; *s; s++) {
if(c >= (int)(sizeof(flags)*8))
break;
@ -324,68 +345,86 @@ bb_getopt_ulflags (int argc, char **argv, const char *applet_opts, ...)
c++;
}
}
c = 0;
for (s = bb_opt_complementally; s && *s; s++) {
t_complementally *pair;
unsigned long *pair_switch;
if (*s == ':') {
c = 0;
continue;
}
if (c)
if (*s == ':')
continue;
c = s[1];
if(*s == '?') {
spec_flgs |= SHOW_USAGE_IF_ERROR;
if(c < '0' || c > '9') {
spec_flgs |= SHOW_USAGE_IF_ERROR;
} else {
max_arg = c - '0';
s++;
}
continue;
}
if(*s == '-') {
spec_flgs |= ARGV_IS_OPTS;
if(c < '0' || c > '9') {
if(c == '-') {
spec_flgs |= FIRST_ARGV_IS_OPT;
s++;
} else
spec_flgs |= ALL_ARGV_IS_OPTS;
} else {
min_arg = c - '0';
s++;
}
continue;
}
for (on_off = complementally; on_off->opt; on_off++)
if (on_off->opt == *s)
break;
if(c == ':' && s[2] == ':') {
on_off->list_flg++;
continue;
}
if(c == ':' || c == '\0') {
requires |= on_off->switch_on;
continue;
}
if(c == *s) {
on_off->counter = va_arg (p, int *);
s++;
}
pair = on_off;
pair_switch = &(pair->switch_on);
for(s++; *s && *s != ':'; s++) {
if (*s == '-' || *s == '~' || *s == '?') {
c = *s;
} else if(*s == '*') {
pair->list_flg++;
} else {
unsigned long *pair_switch;
switch(c) {
case '-':
pair_switch = &(pair->switch_off);
break;
case '~':
if(*s == '?') {
pair_switch = &(pair->requires);
} else if (*s == '-') {
if(pair_switch == &(pair->switch_off))
pair_switch = &(pair->incongruously);
break;
case '?':
pair_switch = &(pair->requires);
break;
default:
pair_switch = &(pair->switch_on);
}
else
pair_switch = &(pair->switch_off);
} else {
for (on_off = complementally; on_off->opt; on_off++)
if (on_off->opt == *s) {
if(pair_switch == &(on_off->switch_on))
on_off->counter = va_arg (p, int *);
else if(pair_switch == &(on_off->requires))
requires |= on_off->switch_on;
else
*pair_switch |= on_off->switch_on;
*pair_switch |= on_off->switch_on;
break;
}
}
}
s--;
}
va_end (p);
#if defined(CONFIG_AR) || defined(CONFIG_TAR)
if((spec_flgs & FIRST_ARGV_IS_OPT)) {
if(argv[1] && argv[1][0] != '-' && argv[1][0] != '\0') {
argv[1] = bb_xasprintf("-%s", argv[1]);
if(ENABLE_FEATURE_CLEAN_UP)
spec_flgs |= FREE_FIRST_ARGV_IS_OPT;
}
}
#endif
while ((c = getopt_long (argc, argv, applet_opts,
bb_applet_long_options, NULL)) >= 0) {
#ifdef CONFIG_PS
loop_arg_is_opt:
#endif
for (on_off = complementally; on_off->opt != c; on_off++) {
/* c==0 if long opt have non NULL flag */
if(on_off->opt == 0 && c != 0)
@ -408,10 +447,14 @@ loop_arg_is_opt:
} else if (on_off->optarg) {
*(char **)(on_off->optarg) = optarg;
}
#ifdef CONFIG_PS
if(pargv != NULL)
break;
#endif
}
if((spec_flgs & ARGV_IS_OPTS)) {
#ifdef CONFIG_PS
if((spec_flgs & ALL_ARGV_IS_OPTS)) {
/* process argv is option, for example "ps" applet */
if(pargv == NULL)
pargv = argv + optind;
@ -425,6 +468,13 @@ loop_arg_is_opt:
}
}
}
#endif
#if (defined(CONFIG_AR) || defined(CONFIG_TAR)) && \
defined(CONFIG_FEATURE_CLEAN_UP)
if((spec_flgs & FREE_FIRST_ARGV_IS_OPT))
free(argv[1]);
#endif
/* check depending requires for given options */
for (on_off = complementally; on_off->opt; on_off++) {
if(on_off->requires && (flags & on_off->switch_on) &&
@ -433,5 +483,8 @@ loop_arg_is_opt:
}
if(requires && (flags & requires) == 0)
bb_show_usage ();
argc -= optind;
if(argc < min_arg || (max_arg >= 0 && argc > max_arg))
bb_show_usage ();
return flags;
}

View File

@ -965,7 +965,7 @@ traceroute_main(int argc, char *argv[])
opterr = 0;
#ifdef CONFIG_FEATURE_TRACEROUTE_SOURCE_ROUTE
bb_opt_complementally = "x-x:g*";
bb_opt_complementally = "x-x:g::";
#else
bb_opt_complementally = "x-x";
#endif

View File

@ -177,23 +177,25 @@ int wget_main(int argc, char **argv)
struct sockaddr_in s_in;
llist_t *headers_llist = NULL;
FILE *sfp = NULL; /* socket to web/ftp server */
FILE *dfp = NULL; /* socket to ftp server (data) */
char *fname_out = NULL; /* where to direct output (-O) */
int do_continue = 0; /* continue a prev transfer (-c) */
long beg_range = 0L; /* range at which continue begins */
int got_clen = 0; /* got content-length: from server */
FILE *output; /* socket to web server */
int quiet_flag = FALSE; /* Be verry, verry quiet... */
int use_proxy = 1; /* Use proxies if env vars are set */
FILE *sfp = NULL; /* socket to web/ftp server */
FILE *dfp = NULL; /* socket to ftp server (data) */
char *fname_out = NULL; /* where to direct output (-O) */
int do_continue = 0; /* continue a prev transfer (-c) */
long beg_range = 0L; /* range at which continue begins */
int got_clen = 0; /* got content-length: from server */
FILE *output; /* socket to web server */
int quiet_flag = FALSE; /* Be verry, verry quiet... */
int use_proxy = 1; /* Use proxies if env vars are set */
char *proxy_flag = "on"; /* Use proxies if env vars are set */
/*
* Crack command line.
*/
bb_opt_complementally = "\203*";
bb_opt_complementally = "-1:\203::";
bb_applet_long_options = wget_long_options;
opt = bb_getopt_ulflags(argc, argv, "cq\213O:\203:P:Y:", &fname_out, &headers_llist, &dir_prefix, &proxy_flag);
opt = bb_getopt_ulflags(argc, argv, "cq\213O:\203:P:Y:",
&fname_out, &headers_llist,
&dir_prefix, &proxy_flag);
if (opt & WGET_OPT_CONTINUE) {
++do_continue;
}
@ -218,9 +220,7 @@ int wget_main(int argc, char **argv)
headers_llist = headers_llist->link;
}
}
if (argc - optind != 1)
bb_show_usage();
parse_url(argv[optind], &target);
server.host = target.host;
server.port = target.port;

View File

@ -49,7 +49,7 @@ extern int pidof_main(int argc, char **argv)
unsigned long int opt;
#if ENABLE_FEATURE_PIDOF_OMIT
llist_t *omits = NULL; /* list of pids to omit */
bb_opt_complementally = _OMIT_COMPL("o*");
bb_opt_complementally = _OMIT_COMPL("o::");
#endif
/* do unconditional option parsing */

View File

@ -209,7 +209,7 @@ static const struct option hwclock_long_options[] = {
bb_applet_long_options = hwclock_long_options;
#endif
bb_opt_complementally = "?r~ws:w~rs:s~wr:l~u:u~l";
bb_opt_complementally = "?:r--ws:w--rs:s--wr:l--u:u--l";
opt = bb_getopt_ulflags(argc, argv, "lursw");
/* If -u or -l wasn't given check if we are using utc */