1) bb_opt_complementaly -> bb_opt_complementally
2) better support long options
3) new flag '!' for bb_opt_complementally: produce bb_show_usage() if BB_GETOPT_ERROR internally
diff --git a/libbb/getopt_ulflags.c b/libbb/getopt_ulflags.c
index 6197e8d..44c8e1a 100644
--- a/libbb/getopt_ulflags.c
+++ b/libbb/getopt_ulflags.c
@@ -2,7 +2,7 @@
 /*
  * universal getopt_ulflags implementation for busybox
  *
- * Copyright (C) 2003  Vladimir Oleynik  <dzo@simtreas.ru>
+ * Copyright (C) 2003-2005  Vladimir Oleynik  <dzo@simtreas.ru>
  *
  * 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
@@ -31,158 +31,152 @@
 unsigned long
 bb_getopt_ulflags (int argc, char **argv, const char *applet_opts, ...)
 
-          The command line options must be declared in const char
-          *applet_opts as a string of chars, for example:
+	The command line options must be declared in const char
+	*applet_opts as a string of chars, for example:
 
-          flags = bb_getopt_ulflags(argc, argv, "rnug");
+	flags = bb_getopt_ulflags(argc, argv, "rnug");
 
-          If one of the given options is found, a flag value is added to
-          the return value (an unsigned long).
+	If one of the given options is found, a flag value is added to
+	the return value (an unsigned long).
 
-          The flag value is determined by the position of the char in
-          applet_opts string.  For example, in the above case:
+	The flag value is determined by the position of the char in
+	applet_opts string.  For example, in the above case:
 
-          flags = bb_getopt_ulflags(argc, argv, "rnug");
+	flags = bb_getopt_ulflags(argc, argv, "rnug");
 
-          "r" will add 1    (bit 1 : 0x01)
-          "n" will add 2    (bit 2 : 0x02)
-          "u  will add 4    (bit 3 : 0x03)
-          "g" will add 8    (bit 4 : 0x04)
+	"r" will add 1    (bit 1 : 0x01)
+	"n" will add 2    (bit 2 : 0x02)
+	"u  will add 4    (bit 3 : 0x03)
+	"g" will add 8    (bit 4 : 0x04)
 
-           and so on.  You can also look at the return value as a bit 
-           field and each option sets one of bits.
+	 and so on.  You can also look at the return value as a bit
+	 field and each option sets one of bits.
 
-   ":"     If one of the options requires an argument, then add a ":"
-           after the char in applet_opts and provide a pointer to store
-           the argument.  For example:
+ ":"    If one of the options requires an argument, then add a ":"
+	after the char in applet_opts and provide a pointer to store
+	the argument.  For example:
 
-           char *pointer_to_arg_for_a;
-           char *pointer_to_arg_for_b;
-           char *pointer_to_arg_for_c;
-           char *pointer_to_arg_for_d;
+	char *pointer_to_arg_for_a;
+	char *pointer_to_arg_for_b;
+	char *pointer_to_arg_for_c;
+	char *pointer_to_arg_for_d;
 
-           flags = bb_getopt_ulflags(argc, argv, "a:b:c:d:",
-                            &pointer_to_arg_for_a, &pointer_to_arg_for_b,
-                            &pointer_to_arg_for_c, &pointer_to_arg_for_d);
+	flags = bb_getopt_ulflags(argc, argv, "a:b:c:d:",
+			 &pointer_to_arg_for_a, &pointer_to_arg_for_b,
+			 &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
-           bb_opt_complementaly (see below for more info).
+	The type of the pointer (char* or llist_t *) may be controlled
+	by the "*" special character that is set in the external string
+	bb_opt_complementally (see below for more info).
 
 static const struct option bb_default_long_options[]
 
-           This struct allows you to define long options.  The syntax for
-           declaring the array is just like that of getopt's longopts.
+	This struct allows you to define long options.  The syntax for
+	declaring the array is just like that of getopt's longopts.
+	(see getopt(3))
 
-           static const struct option applet_long_options[] = {
-                   { "verbose", 0, 0, "v" },
-                   { 0, 0, 0, 0 }
-           };
-           bb_applet_long_options = applet_long_options;
+	static const struct option applet_long_options[] = {
+		{ "verbose", 0, 0, v },
+		{ 0, 0, 0, 0 }
+	};
+	bb_applet_long_options = applet_long_options;
 
-           The first parameter is the long option name that you would pass
-           to the applet (without the dashes).
+	The last argument (val) can undefined from applet_opts.
+	If you use this, then:
+	- return bit have next position after short options
+	- if has_arg is not "no_argument", use ptr for arg also
+	- bb_opt_complementally have effects for this too
 
-           The second field determines whether the option has an argument.
-           You can set this to 0, 1, or 2, or you can use the long named
-           defines of no_argument, required_argument, and optional_argument.
+	Note: a good applet will make long options configurable via the
+	config process and not a required feature.  The current standard
+	is to name the config option CONFIG_FEATURE_<applet>_LONG_OPTIONS.
 
-           The third argument is used only when the long option does not 
-           have a corresponding short option.  In that case, it should be 
-           an integer pointer.  Otherwise (and normally), it should just
-           bet set to NULL.
+const char *bb_opt_complementally
 
-           The last argument is the corresponding short option (if there
-           is one of course).
+ ":"    The colon (":") is used to separate groups of two or more chars
+	and/or groups of chars and special characters (stating some
+	conditions to be checked).
 
-           Note: a good applet will make long options configurable via the
-           config process and not a required feature.  The current standard
-           is to name the config option CONFIG_FEATURE_<applet>_LONG_OPTIONS.
+ "abc"  If groups of two or more chars are specified, the first char
+	is the main option and the other chars are secondary options.
+	Their flags will be turned on if the main option is found even
+	if they are not specifed on the command line.  For example:
 
-const char *bb_opt_complementaly
+	bb_opt_complementally = "abc";
 
-   ":"     The colon (":") is used to separate groups of two or more chars
-           and/or groups of chars and special characters (stating some
-           conditions to be checked).
+	flags = bb_getopt_ulflags(argc, argv, "abcd")
 
-   "abc"   If groups of two or more chars are specified, the first char
-           is the main option and the other chars are secondary options.
-           Their flags will be turned on if the main option is found even
-           if they are not specifed on the command line.  For example:
-
-           bb_opt_complementaly = "abc";
-
-           flags = bb_getopt_ulflags(argc, argv, "abcd")
-
-           If getopt() finds "-a" on the command line, then
-           bb_getopt_ulflags's return value will be as if "-a -b -c" were
-           found.
+	If getopt() finds "-a" on the command line, then
+	bb_getopt_ulflags's return value will be as if "-a -b -c" were
+	found.
 
 Special characters:
 
-   "-"     A dash between two options causes the second of the two
-           to be unset (and ignored) if it is given on the command line.
+ "-"    A dash between two options causes the second of the two
+	to be unset (and ignored) if it is given on the command line.
 
-           For example:
-           The du applet has the options "-s" and "-d depth".  If
-           bb_getopt_ulflags finds -s, then -d is unset or if it finds -d
-           then -s is unset.  (Note:  busybox implements the GNU
-           "--max-depth" option as "-d".)  To obtain this behavior, you 
-           set bb_opt_complementaly = "s-d:d-s".  Only one flag value is 
-           added to bb_getopt_ulflags's return value depending on the 
-           position of the options on the command line.  If one of the 
-           two options requires an argument pointer (":" in applet_opts 
-           as in "d:") optarg is set accordingly.
+	For example:
+	The du applet has the options "-s" and "-d depth".  If
+	bb_getopt_ulflags finds -s, then -d is unset or if it finds -d
+	then -s is unset.  (Note:  busybox implements the GNU
+	"--max-depth" option as "-d".)  To obtain this behavior, you
+	set bb_opt_complementally = "s-d:d-s".  Only one flag value is
+	added to bb_getopt_ulflags's return value depending on the
+	position of the options on the command line.  If one of the
+	two options requires an argument pointer (":" in applet_opts
+	as in "d:") optarg is set accordingly.
 
-           char *smax_print_depth;
+	char *smax_print_depth;
 
-           bb_opt_complementaly = "s-d:d-s";
-           opt = bb_getopt_ulflags(argc, argv, "sd:", &smax_print_depth);
+	bb_opt_complementally = "s-d:d-s";
+	opt = bb_getopt_ulflags(argc, argv, "sd:", &smax_print_depth);
 
-           if (opt & 2) {
-                    max_print_depth = bb_xgetularg10_bnd(smax_print_depth,
-                                0, INT_MAX);
-           }
+	if (opt & 2) {
+		 max_print_depth = bb_xgetularg10_bnd(smax_print_depth,
+			     0, INT_MAX);
+	}
 
-   "~"     A tilde 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.
+ "~"    A tilde 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.
 
-           For example:
-           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_complementaly = "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:
+	For example:
+	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
+	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:
 
-           if (flags & BB_GETOPT_ERROR)
-                   bb_show_usage();
+	if (flags & BB_GETOPT_ERROR)
+		bb_show_usage();
 
-   "*"     A star after a char in bb_opt_complementaly means that the
-           option can occur multiple times:
+ "!"    If previous point set BB_GETOPT_ERROR, don`t return and call
+	previous example internally
 
-           For example:
-           The grep applet can have one or more "-e pattern" arguments.
-           In this case you should use bb_getopt_ulflags() as follows:
+ "*"    A star after a char in bb_opt_complementally means that the
+	option can occur multiple times:
 
-           llist_t *patterns = NULL;
+	For example:
+	The grep applet can have one or more "-e pattern" arguments.
+	In this case you should use bb_getopt_ulflags() as follows:
 
-           (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).)
+	llist_t *patterns = NULL;
 
-           bb_opt_complementaly = "e*";
+	(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_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
+	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
 */
 
-const char *bb_opt_complementaly;
+const char *bb_opt_complementally;
 
 typedef struct {
 	unsigned char opt;
@@ -191,12 +185,12 @@
 	unsigned long switch_off;
 	unsigned long incongruously;
 	void **optarg;               /* char **optarg or llist_t **optarg */
-} t_complementaly;
+} t_complementally;
 
 /* You can set bb_applet_long_options for parse called long options */
 
 static const struct option bb_default_long_options[] = {
-/*	{ "help", 0, NULL, '?' }, */
+/*      { "help", 0, NULL, '?' }, */
 	{ 0, 0, 0, 0 }
 };
 
@@ -206,11 +200,13 @@
 bb_getopt_ulflags (int argc, char **argv, const char *applet_opts, ...)
 {
 	unsigned long flags = 0;
-	t_complementaly complementaly[sizeof(flags) * 8 + 1];
+	t_complementally complementally[sizeof(flags) * 8 + 1];
 	int c;
 	const unsigned char *s;
-	t_complementaly *on_off;
+	t_complementally *on_off;
 	va_list p;
+	const struct option *l_o;
+	char flg_show_usage_if_error = 0;
 
 	va_start (p, applet_opts);
 
@@ -220,7 +216,7 @@
 		s++;
 
 	c = 0;
-	on_off = complementaly;
+	on_off = complementally;
 	for (; *s; s++) {
 		if(c >= (sizeof(flags)*8))
 			break;
@@ -240,9 +236,31 @@
 		c++;
 	}
 	on_off->opt = 0;
+
+	for(l_o = bb_applet_long_options; l_o->name; l_o++) {
+		for(on_off = complementally; on_off->opt != 0; on_off++)
+			if(on_off->opt == l_o->val)
+				break;
+		if(on_off->opt == 0) {
+			if(c >= (sizeof(flags)*8))
+				break;
+			on_off->opt = l_o->val;
+			on_off->switch_on = (1 << c);
+			on_off->list_flg = 0;
+			on_off->switch_off = 0;
+			on_off->incongruously = 0;
+			if(l_o->has_arg != no_argument)
+				on_off->optarg = va_arg (p, void **);
+			else
+				on_off->optarg = NULL;
+			on_off++;
+			on_off->opt = 0;
+			c++;
+		}
+	}
 	c = 0;
-	for (s = bb_opt_complementaly; s && *s; s++) {
-		t_complementaly *pair;
+	for (s = bb_opt_complementally; s && *s; s++) {
+		t_complementally *pair;
 
 		if (*s == ':') {
 			c = 0;
@@ -250,7 +268,11 @@
 		}
 		if (c)
 			continue;
-		for (on_off = complementaly; on_off->opt; on_off++)
+		if(*s == '!') {
+			flg_show_usage_if_error = '!';
+			continue;
+		}
+		for (on_off = complementally; on_off->opt; on_off++)
 			if (on_off->opt == *s)
 				break;
 		pair = on_off;
@@ -263,7 +285,7 @@
 				unsigned long *pair_switch = &(pair->switch_on);
 				if(c)
 					pair_switch = c == '-' ? &(pair->switch_off) : &(pair->incongruously);
-				for (on_off = complementaly; on_off->opt; on_off++)
+				for (on_off = complementally; on_off->opt; on_off++)
 					if (on_off->opt == *s) {
 						*pair_switch |= on_off->switch_on;
 						break;
@@ -274,13 +296,16 @@
 	}
 
 	while ((c = getopt_long (argc, argv, applet_opts,
-	                         bb_applet_long_options, NULL)) > 0) {
-		for (on_off = complementaly; on_off->opt != c; on_off++) {
+				 bb_applet_long_options, NULL)) > 0) {
+		for (on_off = complementally; on_off->opt != c; on_off++) {
 			if(!on_off->opt)
 				bb_show_usage ();
 		}
-		if(flags & on_off->incongruously)
+		if(flags & on_off->incongruously) {
+			if(flg_show_usage_if_error)
+				bb_show_usage ();
 			flags |= BB_GETOPT_ERROR;
+		}
 		flags &= ~on_off->switch_off;
 		flags |= on_off->switch_on;
 		if(on_off->list_flg) {