blob: cfa60a940d3c08332b0d8842e74f96200d44dce9 [file] [log] [blame]
/* 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 <vda.linux@googlemail.com>
*
* Licensed under GPLv2, see file License in this tarball for details.
*/
#include <assert.h>
#include "busybox.h"
/* Declare <applet>_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
}