/* vi: set sw=4 ts=4: */ /* * Support for main() which needs to end up in libbusybox, not busybox, * if one builds libbusybox. * * Copyright (C) 2007 Denys Vlasenko * * Licensed under GPLv2, see file License in this tarball for details. */ #include #include "busybox.h" /* Declare _main() */ #define PROTOTYPES #include "applets.h" #undef PROTOTYPES #if ENABLE_SHOW_USAGE && !ENABLE_FEATURE_COMPRESS_USAGE /* Define usage_messages[] */ static const char usage_messages[] ALIGN1 = "" #define MAKE_USAGE #include "usage.h" #include "applets.h" ; #undef MAKE_USAGE #else #define usage_messages 0 #endif /* SHOW_USAGE */ /* Define struct bb_applet applets[] */ #include "applets.h" #if ENABLE_FEATURE_SH_STANDALONE /* -1 because last entry is NULL */ const unsigned short NUM_APPLETS = ARRAY_SIZE(applets) - 1; #endif #if ENABLE_FEATURE_COMPRESS_USAGE #include "usage_compressed.h" #include "unarchive.h" static const char *unpack_usage_messages(void) { char *outbuf = NULL; bunzip_data *bd; int i; i = start_bunzip(&bd, /* src_fd: */ -1, /* inbuf: */ packed_usage, /* len: */ sizeof(packed_usage)); /* read_bunzip can longjmp to start_bunzip, and ultimately * end up here with i != 0 on read data errors! Not trivial */ if (!i) { /* Cannot use xmalloc: will leak bd in NOFORK case! */ outbuf = malloc_or_warn(SIZEOF_usage_messages); if (outbuf) read_bunzip(bd, outbuf, SIZEOF_usage_messages); } dealloc_bunzip(bd); return outbuf; } #define dealloc_usage_messages(s) free(s) #else #define unpack_usage_messages() usage_messages #define dealloc_usage_messages(s) ((void)(s)) #endif /* FEATURE_COMPRESS_USAGE */ void bb_show_usage(void) { if (ENABLE_SHOW_USAGE) { const char *format_string; const char *p; const char *usage_string = p = unpack_usage_messages(); const struct bb_applet *ap = find_applet_by_name(applet_name); int i; if (!ap) /* never happens, paranoia */ xfunc_die(); i = ap - applets; while (i) { while (*p++) continue; i--; } fprintf(stderr, "%s multi-call binary\n", bb_banner); format_string = "\nUsage: %s %s\n\n"; if (*p == '\b') format_string = "\nNo help available.\n\n"; fprintf(stderr, format_string, applet_name, p); dealloc_usage_messages((char*)usage_string); } xfunc_die(); } static int applet_name_compare(const void *name, const void *vapplet) { const struct bb_applet *applet = vapplet; return strcmp(name, applet->name); } const struct bb_applet *find_applet_by_name(const char *name) { /* Do a binary search to find the applet entry given the name. */ return bsearch(name, applets, ARRAY_SIZE(applets)-1, sizeof(applets[0]), applet_name_compare); } #ifdef __GLIBC__ /* Make it reside in R/W memory: */ int *const bb_errno __attribute__ ((section (".data"))); #endif void bbox_prepare_main(char **argv) { #ifdef __GLIBC__ (*(int **)&bb_errno) = __errno_location(); #endif /* Set locale for everybody except 'init' */ if (ENABLE_LOCALE_SUPPORT && getpid() != 1) setlocale(LC_ALL, ""); #if ENABLE_FEATURE_INDIVIDUAL /* Redundant for busybox (run_applet_and_exit covers that case) * but needed for "individual applet" mode */ if (argv[1] && strcmp(argv[1], "--help") == 0) bb_show_usage(); #endif }