diff --git a/applets/applet_tables.c b/applets/applet_tables.c index 35b099eb4..17135ddc1 100644 --- a/applets/applet_tables.c +++ b/applets/applet_tables.c @@ -47,6 +47,7 @@ int main(int argc, char **argv) { int i; int ofs; + unsigned MAX_APPLET_NAME_LEN = 1; qsort(applets, NUM_APPLETS, sizeof(applets[0]), cmp_name); @@ -71,18 +72,21 @@ int main(int argc, char **argv) puts("/* This is a generated file, don't edit */\n"); + printf("#define NUM_APPLETS %u\n", NUM_APPLETS); if (NUM_APPLETS == 1) { printf("#define SINGLE_APPLET_STR \"%s\"\n", applets[0].name); - printf("#define SINGLE_APPLET_MAIN %s_main\n\n", applets[0].name); + printf("#define SINGLE_APPLET_MAIN %s_main\n", applets[0].name); } - puts("const char applet_names[] ALIGN1 = \"\""); + puts("\nconst char applet_names[] ALIGN1 = \"\""); for (i = 0; i < NUM_APPLETS; i++) { printf("\"%s\" \"\\0\"\n", applets[i].name); + if (MAX_APPLET_NAME_LEN < strlen(applets[i].name)) + MAX_APPLET_NAME_LEN = strlen(applets[i].name); } puts(";"); - puts("int (*const applet_main[])(int argc, char **argv) = {"); + puts("\nint (*const applet_main[])(int argc, char **argv) = {"); for (i = 0; i < NUM_APPLETS; i++) { printf("%s_main,\n", applets[i].main); } @@ -113,8 +117,10 @@ int main(int argc, char **argv) printf("0x%02x,\n", v); i++; } - puts("};"); + puts("};\n"); #endif + printf("#define MAX_APPLET_NAME_LEN %u\n", MAX_APPLET_NAME_LEN); + return 0; } diff --git a/libbb/appletlib.c b/libbb/appletlib.c index a48a26003..ed7d3912b 100644 --- a/libbb/appletlib.c +++ b/libbb/appletlib.c @@ -12,6 +12,21 @@ * Licensed under GPLv2 or later, see file License in this tarball for details. */ +/* We are trying to not use printf, this benefits the case when selected + * applets are really simple. Example: + * + * $ ./busybox + * ... + * Currently defined functions: + * basename, false, true + * + * $ size busybox + * text data bss dec hex filename + * 4473 52 72 4597 11f5 busybox + * + * FEATURE_INSTALLER or FEATURE_SUID will still link printf routines in. :( + */ + #include #include "busybox.h" @@ -81,6 +96,11 @@ static const char *unpack_usage_messages(void) #endif /* FEATURE_COMPRESS_USAGE */ +static void full_write2_str(const char *str) +{ + full_write(2, str, strlen(str)); +} + void bb_show_usage(void) { if (ENABLE_SHOW_USAGE) { @@ -90,18 +110,14 @@ void bb_show_usage(void) const char *usage_string = p = unpack_usage_messages(); if (*p == '\b') { - write(2, "\nNo help available.\n\n", - sizeof("\nNo help available.\n\n") - 1); + full_write2_str("\nNo help available.\n\n"); } else { - write(2, "\nUsage: "SINGLE_APPLET_STR" ", - sizeof("\nUsage: "SINGLE_APPLET_STR" ") - 1); - write(2, p, strlen(p)); - write(2, "\n\n", 2); + full_write2_str("\nUsage: "SINGLE_APPLET_STR" "); + full_write2_str(p); + full_write2_str("\n\n"); } dealloc_usage_messages((char*)usage_string); #else -// TODO: in this case, stdio is sucked in by busybox_main() anyway... - const char *format_string; const char *p; const char *usage_string = p = unpack_usage_messages(); int ap = find_applet_by_name(applet_name); @@ -112,32 +128,52 @@ void bb_show_usage(void) while (*p++) continue; ap--; } - fprintf(stderr, "%s multi-call binary\n", bb_banner); - format_string = "\nUsage: %s %s\n\n"; + full_write2_str(bb_banner); + full_write2_str(" multi-call binary\n"); if (*p == '\b') - format_string = "\nNo help available.\n\n"; - fprintf(stderr, format_string, applet_name, p); + full_write2_str("\nNo help available.\n\n"); + else { + full_write2_str("\nUsage: "); + full_write2_str(applet_name); + full_write2_str(" "); + full_write2_str(p); + full_write2_str("\n\n"); + } dealloc_usage_messages((char*)usage_string); #endif } xfunc_die(); } - +#if NUM_APPLETS > 8 /* NB: any char pointer will work as well, not necessarily applet_names */ static int applet_name_compare(const void *name, const void *v) { int i = (const char *)v - applet_names; return strcmp(name, APPLET_NAME(i)); } +#endif int find_applet_by_name(const char *name) { +#if NUM_APPLETS > 8 /* Do a binary search to find the applet entry given the name. */ const char *p; p = bsearch(name, applet_names, ARRAY_SIZE(applet_main), 1, applet_name_compare); if (!p) return -1; return p - applet_names; +#else + /* A version which does not pull in bsearch */ + int i = 0; + const char *p = applet_names; + while (i < NUM_APPLETS) { + if (strcmp(name, p) == 0) + return i; + p += strlen(p) + 1; + i++; + } + return -1; +#endif } @@ -604,10 +640,11 @@ static int busybox_main(char **argv) get_terminal_width_height(0, &output_width, NULL); } /* leading tab and room to wrap */ - output_width -= sizeof("start-stop-daemon, ") + 8; + output_width -= MAX_APPLET_NAME_LEN + 8; - printf("%s multi-call binary\n", bb_banner); /* reuse const string... */ - printf("Copyright (C) 1998-2007 Erik Andersen, Rob Landley, Denys Vlasenko\n" + full_write2_str(bb_banner); /* reuse const string... */ + full_write2_str(" multi-call binary\n" + "Copyright (C) 1998-2007 Erik Andersen, Rob Landley, Denys Vlasenko\n" "and others. Licensed under GPLv2.\n" "See source distribution for full notice.\n" "\n" @@ -623,14 +660,18 @@ static int busybox_main(char **argv) col = 0; a = applet_names; while (*a) { + int len; if (col > output_width) { - puts(","); + full_write2_str(",\n"); col = 0; } - col += printf("%s%s", (col ? ", " : "\t"), a); - a += strlen(a) + 1; + full_write2_str(col ? ", " : "\t"); + full_write2_str(a); + len = strlen(a); + col += len + 2; + a += len + 1; } - puts("\n"); + full_write2_str("\n\n"); return 0; } @@ -659,7 +700,11 @@ static int busybox_main(char **argv) * "#!/bin/busybox"-style wrappers */ applet_name = bb_get_last_path_component_nostrip(argv[0]); run_applet_and_exit(applet_name, argv); - bb_error_msg_and_die("applet not found"); + + /*bb_error_msg_and_die("applet not found"); - sucks in printf */ + full_write2_str(applet_name); + full_write2_str(": applet not found\n"); + xfunc_die(); } void run_applet_no_and_exit(int applet_no, char **argv) @@ -701,7 +746,8 @@ int main(int argc ATTRIBUTE_UNUSED, char **argv) { #if ENABLE_FEATURE_INDIVIDUAL /* Only one applet is selected by the user! */ - lbb_prepare(SINGLE_APPLET_STR USE_FEATURE_INDIVIDUAL(, argv)); + /* applet_names in this case is just "applet\0\0" */ + lbb_prepare(applet_names USE_FEATURE_INDIVIDUAL(, argv)); return SINGLE_APPLET_MAIN(argc, argv); #else lbb_prepare("busybox" USE_FEATURE_INDIVIDUAL(, argv)); @@ -721,6 +767,10 @@ int main(int argc ATTRIBUTE_UNUSED, char **argv) parse_config_file(); /* ...maybe, if FEATURE_SUID_CONFIG */ run_applet_and_exit(applet_name, argv); - bb_error_msg_and_die("applet not found"); + + /*bb_error_msg_and_die("applet not found"); - sucks in printf */ + full_write2_str(applet_name); + full_write2_str(": applet not found\n"); + xfunc_die(); #endif }