blob: 626c25a8f97ddf59bf35ff74f7c68380736fb44b [file] [log] [blame]
Denis Vlasenkoac7d0e32007-10-08 19:32:12 +00001/* vi: set sw=4 ts=4: */
2/*
3 * Support for main() which needs to end up in libbusybox, not busybox,
4 * if one builds libbusybox.
5 *
6 * Copyright (C) 2007 Denys Vlasenko <vda.linux@googlemail.com>
7 *
8 * Licensed under GPLv2, see file License in this tarball for details.
9 */
10
11#include <assert.h>
12#include "busybox.h"
13
14
15/* Declare <applet>_main() */
16#define PROTOTYPES
17#include "applets.h"
18#undef PROTOTYPES
19
20#if ENABLE_SHOW_USAGE && !ENABLE_FEATURE_COMPRESS_USAGE
21/* Define usage_messages[] */
22static const char usage_messages[] ALIGN1 = ""
23#define MAKE_USAGE
24#include "usage.h"
25#include "applets.h"
26;
27#undef MAKE_USAGE
28#else
29#define usage_messages 0
30#endif /* SHOW_USAGE */
31
32/* Define struct bb_applet applets[] */
33#include "applets.h"
34
35#if ENABLE_FEATURE_SH_STANDALONE
36/* -1 because last entry is NULL */
37const unsigned short NUM_APPLETS = ARRAY_SIZE(applets) - 1;
38#endif
39
40
41#if ENABLE_FEATURE_COMPRESS_USAGE
42
43#include "usage_compressed.h"
44#include "unarchive.h"
45
46static const char *unpack_usage_messages(void)
47{
48 char *outbuf = NULL;
49 bunzip_data *bd;
50 int i;
51
52 i = start_bunzip(&bd,
53 /* src_fd: */ -1,
54 /* inbuf: */ packed_usage,
55 /* len: */ sizeof(packed_usage));
56 /* read_bunzip can longjmp to start_bunzip, and ultimately
57 * end up here with i != 0 on read data errors! Not trivial */
58 if (!i) {
59 /* Cannot use xmalloc: will leak bd in NOFORK case! */
60 outbuf = malloc_or_warn(SIZEOF_usage_messages);
61 if (outbuf)
62 read_bunzip(bd, outbuf, SIZEOF_usage_messages);
63 }
64 dealloc_bunzip(bd);
65 return outbuf;
66}
67#define dealloc_usage_messages(s) free(s)
68
69#else
70
71#define unpack_usage_messages() usage_messages
72#define dealloc_usage_messages(s) ((void)(s))
73
74#endif /* FEATURE_COMPRESS_USAGE */
75
76
77void bb_show_usage(void)
78{
79 if (ENABLE_SHOW_USAGE) {
80 const char *format_string;
81 const char *p;
82 const char *usage_string = p = unpack_usage_messages();
83 const struct bb_applet *ap = find_applet_by_name(applet_name);
84 int i;
85
86 if (!ap) /* never happens, paranoia */
87 xfunc_die();
88
89 i = ap - applets;
90 while (i) {
91 while (*p++) continue;
92 i--;
93 }
94
95 fprintf(stderr, "%s multi-call binary\n", bb_banner);
96 format_string = "\nUsage: %s %s\n\n";
97 if (*p == '\b')
98 format_string = "\nNo help available.\n\n";
99 fprintf(stderr, format_string, applet_name, p);
100 dealloc_usage_messages((char*)usage_string);
101 }
102 xfunc_die();
103}
104
105
106static int applet_name_compare(const void *name, const void *vapplet)
107{
108 const struct bb_applet *applet = vapplet;
109
110 return strcmp(name, applet->name);
111}
112
113const struct bb_applet *find_applet_by_name(const char *name)
114{
115 /* Do a binary search to find the applet entry given the name. */
116 return bsearch(name, applets, ARRAY_SIZE(applets)-1, sizeof(applets[0]),
117 applet_name_compare);
118}
119
120
121#ifdef __GLIBC__
122/* Make it reside in R/W memory: */
123int *const bb_errno __attribute__ ((section (".data")));
124#endif
125
126void bbox_prepare_main(char **argv)
127{
128#ifdef __GLIBC__
129 (*(int **)&bb_errno) = __errno_location();
130#endif
131
132 /* Set locale for everybody except 'init' */
133 if (ENABLE_LOCALE_SUPPORT && getpid() != 1)
134 setlocale(LC_ALL, "");
135
136 /* Redundant for busybox, but needed for individual applets */
137 if (argv[1] && strcmp(argv[1], "--help") == 0)
138 bb_show_usage();
139}