[RFC] redo --help parsing

Bernhard Fischer rep.nop at aon.at
Fri Jun 9 06:51:07 PDT 2006


Hi,
[post 1.2.0 stuff, probably..]

First a quick question.
IIRC there was demand to be able to emit a list of available applets
which can be parsed easily ¹).
Therefor, i'm thinking about adding the possibility to writeout the
applets by something like
$ ./busybox --list
[ [[ false lash ls sh test true
To stdout, without "busybox" and not comma separated.
I imagine this to be configurable via something like the --install
config option, just for --list.
Does that sound ok?


Now a proposal with an unfinished patchlet to show what i mean:
Currently we parse for --help in more than one place.

The attached patch
- removes this double-parsing
- moves the static busybox help banner to usage.h

   text    data     bss     dec     hex filename
   1788       0       4    1792     700 applets/applets.o.orig
    676       0       0     676     2a4 applets/busybox.o.orig
   2464       0       4    2468     9a4 (TOTALS)
   text    data     bss     dec     hex filename
   2238       0       4    2242     8c2 applets/applets.o
    121       0       0     121      79 applets/busybox.o
   2359       0       4    2363     93b (TOTALS)

function                                             old     new   delta
bb_show_usage                                         89     226    +137
.rodata                                             4268    4300     +32
run_applet_by_name                                   113      88     -25
busybox_main                                         222      32    -190
------------------------------------------------------------------------------
(add/remove: 0/0 grow/shrink: 2/2 up/down: 169/-215)          Total: -46 bytes

The functionality is the same as before (patch will be fixed to print to
stderr to match the old behaviour) except that i dropped support for
this sequence:
$ ./busybox --help ls
as it doesn't make sense, imho.
./busybox; ./busybox --help; ./ls --help; ./busybox ls --help
work as before.
Is this proposed patch something we want to have, generally?


Thanks for your time and for your comments.
Bernhard

¹) Currently doing something like this works, but is not exactly
elegant:
./busybox 2>&1 | awk \
'{if(/^Curr/){i=1;};if(((i>0)&&(!/^Currently/))&&(!/^$/)){print}}'
-------------- next part --------------
Index: include/usage.h
===================================================================
--- include/usage.h	(revision 15346)
+++ include/usage.h	(working copy)
@@ -89,6 +89,11 @@
 	"$ basename /foo/bar.txt .txt\n" \
 	"bar"
 
+#define bbconfig_trivial_usage \
+	""
+#define bbconfig_full_usage \
+	"Print the config file which built busybox"
+
 #define bunzip2_trivial_usage \
 	"[OPTION]... [FILE]"
 #define bunzip2_full_usage \
@@ -97,6 +102,16 @@
 	"\t-c\tWrite output to standard output\n" \
 	"\t-f\tForce"
 
+#define busybox_trivial_usage \
+	"[function] [arguments]...\n" \
+	"   or: [function] [arguments]...\n\n" \
+	"\tBusyBox is a multi-call binary that combines many common Unix\n" \
+	"\tutilities into a single executable.  Most people will create a\n" \
+	"\tlink to busybox for each function they wish to use and BusyBox\n" \
+	"\twill act like whatever it was invoked as!\n" \
+	"\nCurrently defined functions:"
+#define busybox_full_usage \
+	""
 #define busybox_notes_usage \
 	"Hello world!\n"
 
@@ -259,11 +274,6 @@
 	"\t-2\tSuppress lines unique to FILE2\n" \
 	"\t-3\tSuppress lines common to both files"
 
-#define bbconfig_trivial_usage \
-	""
-#define bbconfig_full_usage \
-	"Print the config file which built busybox"
-
 #define cp_trivial_usage \
 	"[OPTION]... SOURCE DEST"
 #define cp_full_usage \
Index: include/applets.h
===================================================================
--- include/applets.h	(revision 15346)
+++ include/applets.h	(working copy)
@@ -59,7 +59,7 @@
 USE_BBCONFIG(APPLET(bbconfig, _BB_DIR_BIN, _BB_SUID_NEVER))
 USE_BUNZIP2(APPLET(bunzip2, _BB_DIR_USR_BIN, _BB_SUID_NEVER))
 /* Always enabled. */
-APPLET_NOUSAGE(busybox, busybox, _BB_DIR_BIN, _BB_SUID_MAYBE)
+APPLET(busybox, _BB_DIR_BIN, _BB_SUID_MAYBE)
 USE_BUNZIP2(APPLET_ODDNAME(bzcat, bunzip2, _BB_DIR_USR_BIN, _BB_SUID_NEVER, bzcat))
 USE_CAL(APPLET(cal, _BB_DIR_USR_BIN, _BB_SUID_NEVER))
 USE_CAT(APPLET(cat, _BB_DIR_BIN, _BB_SUID_NEVER))
Index: applets/applets.c
===================================================================
--- applets/applets.c	(revision 15346)
+++ applets/applets.c	(working copy)
@@ -437,6 +437,11 @@
 #define unpack_usage_messages() usage_messages
 #endif /* ENABLE_FEATURE_COMPRESS_USAGE */
 
+/*static const char* busybox_usage(void)
+{
+	return buf;
+}
+*/
 void bb_show_usage (void)
 {
 	if (ENABLE_SHOW_USAGE) {
@@ -448,11 +453,36 @@
 			if (!*usage_string++) --i;
 
 		format_string = "%s\n\nUsage: %s %s\n\n";
-		if (*usage_string == '\b')
-			format_string = "%s\n\nNo help available.\n\n";
+		if (*usage_string == '\b') {
+				format_string = "%s\n\nNo help available.\n\n";
+		}
 		fprintf (stderr, format_string, bb_msg_full_version,
 			applet_using->name, usage_string);
+	if (!strncmp(applet_using->name, "busybox", 7)) {
+		/* emit a list of available applets */
+		const struct BB_applet *a;
+		int col = 0, output_width;
+#if 1
+		if (ENABLE_FEATURE_AUTOWIDTH) {
+			/* Obtain the terminal width.  */
+			get_terminal_width_height(0, &output_width, NULL);
+			/* leading tab and room to wrap */
+			output_width -= 20;
+		} else
+#endif
+			output_width = 60;
+
+		for(a = applets; a->name;) {
+			col += printf("%s%s", (col ? ", " : "\t"), (a++)->name);
+			if (col > output_width && a->name) {
+				printf(",\n");
+				col = 0;
+			}
+		}
+
 	}
+	printf("\n\n");
+	}
 
   exit (bb_default_error_retval);
 }
@@ -475,9 +505,12 @@
 
 void run_applet_by_name (const char *name, int argc, char **argv)
 {
+//fprintf(stderr,"run_applet_by_name='%s' argc=%d, argv='%s'\n", name,argc,argv);
+	if (name == NULL)
+		bb_show_usage();
 	if(ENABLE_FEATURE_SUID_CONFIG) parse_config_file ();
 
-	if(!strncmp(name, "busybox", 7)) busybox_main(argc, argv);
+//	if(!strncmp(name, "busybox", 7)) busybox_main(argc, argv);
 	/* Do a binary search to find the applet entry given the name. */
 	applet_using = find_applet_by_name(name);
 	if(applet_using) {
@@ -486,4 +519,5 @@
 		if(ENABLE_FEATURE_SUID) check_suid (applet_using);
 		exit ((*(applet_using->main)) (argc, argv));
 	}
+//	bb_show_usage();
 }
Index: applets/busybox.c
===================================================================
--- applets/busybox.c	(revision 15346)
+++ applets/busybox.c	(working copy)
@@ -75,7 +75,7 @@
 		if (*(s++) == '/') bb_applet_name = s;
 
 	/* Set locale for everybody except `init' */
-	if(ENABLE_LOCALE_SUPPORT && getpid() != 1)
+	if (ENABLE_LOCALE_SUPPORT && getpid() != 1)
 		setlocale(LC_ALL, "");
 
 	run_applet_by_name(bb_applet_name, argc, argv);
@@ -112,43 +112,7 @@
 		return rc;
 	}
 
-	/* Deal with --help.  (Also print help when called with no arguments) */
+	run_applet_by_name(argv[1], argc-1, argv+1);
 
-	if (argc==1 || !strcmp(argv[1],"--help") ) {
-		if (argc>2) {
-			run_applet_by_name(bb_applet_name=argv[2], 2, argv);
-		} else {
-			const struct BB_applet *a;
-			int col, output_width;
-
-			if (ENABLE_FEATURE_AUTOWIDTH) {
-				/* Obtain the terminal width.  */
-				get_terminal_width_height(0, &output_width, NULL);
-				/* leading tab and room to wrap */
-				output_width -= 20;
-			} else output_width = 60;
-
-			printf("%s\n\n"
-			       "Usage: busybox [function] [arguments]...\n"
-			       "   or: [function] [arguments]...\n\n"
-			       "\tBusyBox is a multi-call binary that combines many common Unix\n"
-			       "\tutilities into a single executable.  Most people will create a\n"
-			       "\tlink to busybox for each function they wish to use and BusyBox\n"
-			       "\twill act like whatever it was invoked as!\n"
-			       "\nCurrently defined functions:\n", bb_msg_full_version);
-
-			col=0;
-			for(a = applets; a->name;) {
-				col += printf("%s%s", (col ? ", " : "\t"), (a++)->name);
-				if (col > output_width && a->name) {
-					printf(",\n");
-					col = 0;
-				}
-			}
-			printf("\n\n");
-			exit(0);
-		}
-	} else run_applet_by_name(argv[1], argc-1, argv+1);
-
 	bb_error_msg_and_die("applet not found");
 }


More information about the busybox mailing list