diff options
author | Denis Vlasenko <vda.linux@googlemail.com> | 2007-10-08 19:32:12 +0000 |
---|---|---|
committer | Denis Vlasenko <vda.linux@googlemail.com> | 2007-10-08 19:32:12 +0000 |
commit | ac7d0e375e9ea6241b3ebca67b8cdb5128327535 (patch) | |
tree | 597583c807c38817606e6966522063a4de3f128d | |
parent | 642a52d65e239c43f38ed6e98994191f24290490 (diff) | |
download | busybox-w32-ac7d0e375e9ea6241b3ebca67b8cdb5128327535.tar.gz busybox-w32-ac7d0e375e9ea6241b3ebca67b8cdb5128327535.tar.bz2 busybox-w32-ac7d0e375e9ea6241b3ebca67b8cdb5128327535.zip |
add libbb/appletlib.c
-rw-r--r-- | libbb/appletlib.c | 139 |
1 files changed, 139 insertions, 0 deletions
diff --git a/libbb/appletlib.c b/libbb/appletlib.c new file mode 100644 index 000000000..626c25a8f --- /dev/null +++ b/libbb/appletlib.c | |||
@@ -0,0 +1,139 @@ | |||
1 | /* 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[] */ | ||
22 | static 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 */ | ||
37 | const 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 | |||
46 | static 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 | |||
77 | void 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 | |||
106 | static 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 | |||
113 | const 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: */ | ||
123 | int *const bb_errno __attribute__ ((section (".data"))); | ||
124 | #endif | ||
125 | |||
126 | void 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 | } | ||