diff options
Diffstat (limited to 'libbb')
-rw-r--r-- | libbb/Kbuild.src | 2 | ||||
-rw-r--r-- | libbb/appletlib.c | 166 | ||||
-rw-r--r-- | libbb/executable.c | 11 | ||||
-rw-r--r-- | libbb/info_msg.c | 62 | ||||
-rw-r--r-- | libbb/ubi.c | 43 | ||||
-rw-r--r-- | libbb/verror_msg.c | 29 | ||||
-rw-r--r-- | libbb/vfork_daemon_rexec.c | 3 | ||||
-rw-r--r-- | libbb/xfuncs.c | 12 | ||||
-rw-r--r-- | libbb/xfuncs_printf.c | 22 |
9 files changed, 254 insertions, 96 deletions
diff --git a/libbb/Kbuild.src b/libbb/Kbuild.src index e0898565a..0e14e351e 100644 --- a/libbb/Kbuild.src +++ b/libbb/Kbuild.src | |||
@@ -43,7 +43,7 @@ lib-y += getopt32.o | |||
43 | lib-y += get_volsize.o | 43 | lib-y += get_volsize.o |
44 | lib-y += herror_msg.o | 44 | lib-y += herror_msg.o |
45 | lib-y += human_readable.o | 45 | lib-y += human_readable.o |
46 | lib-y += info_msg.o | 46 | lib-y += inet_common.o |
47 | lib-y += inode_hash.o | 47 | lib-y += inode_hash.o |
48 | lib-y += isdirectory.o | 48 | lib-y += isdirectory.o |
49 | lib-y += last_char_is.o | 49 | lib-y += last_char_is.o |
diff --git a/libbb/appletlib.c b/libbb/appletlib.c index 1d6a4b274..b71f2dd7e 100644 --- a/libbb/appletlib.c +++ b/libbb/appletlib.c | |||
@@ -140,32 +140,127 @@ void FAST_FUNC bb_show_usage(void) | |||
140 | xfunc_die(); | 140 | xfunc_die(); |
141 | } | 141 | } |
142 | 142 | ||
143 | #if NUM_APPLETS > 8 | ||
144 | static int applet_name_compare(const void *name, const void *idx) | ||
145 | { | ||
146 | int i = (int)(ptrdiff_t)idx - 1; | ||
147 | return strcmp(name, APPLET_NAME(i)); | ||
148 | } | ||
149 | #endif | ||
150 | int FAST_FUNC find_applet_by_name(const char *name) | 143 | int FAST_FUNC find_applet_by_name(const char *name) |
151 | { | 144 | { |
152 | #if NUM_APPLETS > 8 | 145 | unsigned i, max; |
153 | /* Do a binary search to find the applet entry given the name. */ | 146 | int j; |
154 | const char *p; | 147 | const char *p; |
155 | p = bsearch(name, (void*)(ptrdiff_t)1, ARRAY_SIZE(applet_main), 1, applet_name_compare); | 148 | |
156 | /* | 149 | /* The commented-out word-at-a-time code is ~40% faster, but +160 bytes. |
157 | * if (!p) return -1; | 150 | * "Faster" here saves ~0.5 microsecond of real time - not worth it. |
158 | * ^^^^^^^^^^^^^^^^^^ the code below will do this if p == NULL :) | 151 | */ |
159 | */ | 152 | #if 0 /*BB_UNALIGNED_MEMACCESS_OK && BB_LITTLE_ENDIAN*/ |
160 | return (int)(ptrdiff_t)p - 1; | 153 | uint32_t n32; |
154 | |||
155 | /* Handle all names < 2 chars long early */ | ||
156 | if (name[0] == '\0') | ||
157 | return -1; /* "" is not a valid applet name */ | ||
158 | if (name[1] == '\0') { | ||
159 | if (!ENABLE_TEST) | ||
160 | return -1; /* 1-char name is not valid */ | ||
161 | if (name[0] != ']') | ||
162 | return -1; /* 1-char name which isn't "[" is not valid */ | ||
163 | /* applet "[" is always applet #0: */ | ||
164 | return 0; | ||
165 | } | ||
166 | #endif | ||
167 | |||
168 | p = applet_names; | ||
169 | i = 0; | ||
170 | #if KNOWN_APPNAME_OFFSETS <= 0 | ||
171 | max = NUM_APPLETS; | ||
161 | #else | 172 | #else |
162 | /* A version which does not pull in bsearch */ | 173 | max = NUM_APPLETS * KNOWN_APPNAME_OFFSETS; |
163 | int i = 0; | 174 | for (j = ARRAY_SIZE(applet_nameofs)-1; j >= 0; j--) { |
164 | const char *p = applet_names; | 175 | const char *pp = applet_names + applet_nameofs[j]; |
165 | while (i < NUM_APPLETS) { | 176 | if (strcmp(name, pp) >= 0) { |
166 | if (strcmp(name, p) == 0) | 177 | //bb_error_msg("name:'%s' >= pp:'%s'", name, pp); |
178 | p = pp; | ||
179 | i = max - NUM_APPLETS; | ||
180 | break; | ||
181 | } | ||
182 | max -= NUM_APPLETS; | ||
183 | } | ||
184 | max /= (unsigned)KNOWN_APPNAME_OFFSETS; | ||
185 | i /= (unsigned)KNOWN_APPNAME_OFFSETS; | ||
186 | //bb_error_msg("name:'%s' starting from:'%s' i:%u max:%u", name, p, i, max); | ||
187 | #endif | ||
188 | |||
189 | /* Open-coded linear search without strcmp/strlen calls for speed */ | ||
190 | |||
191 | #if 0 /*BB_UNALIGNED_MEMACCESS_OK && BB_LITTLE_ENDIAN*/ | ||
192 | /* skip "[\0" name, it's surely not it */ | ||
193 | if (ENABLE_TEST && LONE_CHAR(p, '[')) | ||
194 | i++, p += 2; | ||
195 | /* All remaining applet names in p[] are at least 2 chars long */ | ||
196 | /* name[] is also at least 2 chars long */ | ||
197 | |||
198 | n32 = (name[0] << 0) | (name[1] << 8) | (name[2] << 16); | ||
199 | while (i < max) { | ||
200 | uint32_t p32; | ||
201 | char ch; | ||
202 | |||
203 | /* Quickly check match of the first 3 bytes */ | ||
204 | move_from_unaligned32(p32, p); | ||
205 | p += 3; | ||
206 | if ((p32 & 0x00ffffff) != n32) { | ||
207 | /* Most likely case: 3 first bytes do not match */ | ||
208 | i++; | ||
209 | if ((p32 & 0x00ff0000) == '\0') | ||
210 | continue; // p[2] was NUL | ||
211 | p++; | ||
212 | if ((p32 & 0xff000000) == '\0') | ||
213 | continue; // p[3] was NUL | ||
214 | /* p[0..3] aren't matching and none is NUL, check the rest */ | ||
215 | while (*p++ != '\0') | ||
216 | continue; | ||
217 | continue; | ||
218 | } | ||
219 | |||
220 | /* Unlikely branch: first 3 bytes ([0..2]) match */ | ||
221 | if ((p32 & 0x00ff0000) == '\0') { | ||
222 | /* name is 2-byte long, it is full match */ | ||
223 | //bb_error_msg("found:'%s' i:%u", name, i); | ||
167 | return i; | 224 | return i; |
168 | p += strlen(p) + 1; | 225 | } |
226 | /* Check remaining bytes [3..NUL] */ | ||
227 | ch = (p32 >> 24); | ||
228 | j = 3; | ||
229 | while (ch == name[j]) { | ||
230 | if (ch == '\0') { | ||
231 | //bb_error_msg("found:'%s' i:%u", name, i); | ||
232 | return i; | ||
233 | } | ||
234 | ch = *++p; | ||
235 | j++; | ||
236 | } | ||
237 | /* Not a match. Skip it, including NUL */ | ||
238 | while (ch != '\0') | ||
239 | ch = *++p; | ||
240 | p++; | ||
241 | i++; | ||
242 | } | ||
243 | return -1; | ||
244 | #else | ||
245 | while (i < max) { | ||
246 | char ch; | ||
247 | j = 0; | ||
248 | /* Do we see "name\0" in applet_names[p] position? */ | ||
249 | while ((ch = *p) == name[j]) { | ||
250 | if (ch == '\0') { | ||
251 | //bb_error_msg("found:'%s' i:%u", name, i); | ||
252 | return i; /* yes */ | ||
253 | } | ||
254 | p++; | ||
255 | j++; | ||
256 | } | ||
257 | /* No. | ||
258 | * p => 1st non-matching char in applet_names[], | ||
259 | * skip to and including NUL. | ||
260 | */ | ||
261 | while (ch != '\0') | ||
262 | ch = *++p; | ||
263 | p++; | ||
169 | i++; | 264 | i++; |
170 | } | 265 | } |
171 | return -1; | 266 | return -1; |
@@ -588,6 +683,7 @@ static void install_links(const char *busybox, int use_symbolic_links, | |||
588 | * busybox.h::bb_install_loc_t, or else... */ | 683 | * busybox.h::bb_install_loc_t, or else... */ |
589 | int (*lf)(const char *, const char *); | 684 | int (*lf)(const char *, const char *); |
590 | char *fpc; | 685 | char *fpc; |
686 | const char *appname = applet_names; | ||
591 | unsigned i; | 687 | unsigned i; |
592 | int rc; | 688 | int rc; |
593 | 689 | ||
@@ -598,7 +694,7 @@ static void install_links(const char *busybox, int use_symbolic_links, | |||
598 | for (i = 0; i < ARRAY_SIZE(applet_main); i++) { | 694 | for (i = 0; i < ARRAY_SIZE(applet_main); i++) { |
599 | fpc = concat_path_file( | 695 | fpc = concat_path_file( |
600 | custom_install_dir ? custom_install_dir : install_dir[APPLET_INSTALL_LOC(i)], | 696 | custom_install_dir ? custom_install_dir : install_dir[APPLET_INSTALL_LOC(i)], |
601 | APPLET_NAME(i)); | 697 | appname); |
602 | // debug: bb_error_msg("%slinking %s to busybox", | 698 | // debug: bb_error_msg("%slinking %s to busybox", |
603 | // use_symbolic_links ? "sym" : "", fpc); | 699 | // use_symbolic_links ? "sym" : "", fpc); |
604 | rc = lf(busybox, fpc); | 700 | rc = lf(busybox, fpc); |
@@ -606,6 +702,8 @@ static void install_links(const char *busybox, int use_symbolic_links, | |||
606 | bb_simple_perror_msg(fpc); | 702 | bb_simple_perror_msg(fpc); |
607 | } | 703 | } |
608 | free(fpc); | 704 | free(fpc); |
705 | while (*appname++ != '\0') | ||
706 | continue; | ||
609 | } | 707 | } |
610 | } | 708 | } |
611 | # else | 709 | # else |
@@ -769,7 +867,7 @@ void FAST_FUNC run_applet_no_and_exit(int applet_no, char **argv) | |||
769 | 867 | ||
770 | /* Reinit some shared global data */ | 868 | /* Reinit some shared global data */ |
771 | xfunc_error_retval = EXIT_FAILURE; | 869 | xfunc_error_retval = EXIT_FAILURE; |
772 | applet_name = APPLET_NAME(applet_no); | 870 | applet_name = bb_get_last_path_component_nostrip(argv[0]); |
773 | 871 | ||
774 | /* Special case. POSIX says "test --help" | 872 | /* Special case. POSIX says "test --help" |
775 | * should be no different from e.g. "test --foo". | 873 | * should be no different from e.g. "test --foo". |
@@ -800,11 +898,14 @@ void FAST_FUNC run_applet_no_and_exit(int applet_no, char **argv) | |||
800 | 898 | ||
801 | void FAST_FUNC run_applet_and_exit(const char *name, char **argv) | 899 | void FAST_FUNC run_applet_and_exit(const char *name, char **argv) |
802 | { | 900 | { |
803 | int applet = find_applet_by_name(name); | 901 | int applet; |
804 | if (applet >= 0) | 902 | |
805 | run_applet_no_and_exit(applet, argv); | ||
806 | if (is_prefixed_with(name, "busybox")) | 903 | if (is_prefixed_with(name, "busybox")) |
807 | exit(busybox_main(argv)); | 904 | exit(busybox_main(argv)); |
905 | /* find_applet_by_name() search is more expensive, so goes second */ | ||
906 | applet = find_applet_by_name(name); | ||
907 | if (applet >= 0) | ||
908 | run_applet_no_and_exit(applet, argv); | ||
808 | } | 909 | } |
809 | 910 | ||
810 | #endif /* !defined(SINGLE_APPLET_MAIN) */ | 911 | #endif /* !defined(SINGLE_APPLET_MAIN) */ |
@@ -817,6 +918,19 @@ int lbb_main(char **argv) | |||
817 | int main(int argc UNUSED_PARAM, char **argv) | 918 | int main(int argc UNUSED_PARAM, char **argv) |
818 | #endif | 919 | #endif |
819 | { | 920 | { |
921 | #if 0 | ||
922 | /* TODO: find a use for a block of memory between end of .bss | ||
923 | * and end of page. For example, I'm getting "_end:0x812e698 2408 bytes" | ||
924 | * - more than 2k of wasted memory (in this particular build) | ||
925 | * *per each running process*! | ||
926 | * (If your linker does not generate "_end" name, weak attribute | ||
927 | * makes &_end == NULL, end_len == 0 here.) | ||
928 | */ | ||
929 | extern char _end[] __attribute__((weak)); | ||
930 | unsigned end_len = (-(int)_end) & 0xfff; | ||
931 | printf("_end:%p %u bytes\n", &_end, end_len); | ||
932 | #endif | ||
933 | |||
820 | /* Tweak malloc for reduced memory consumption */ | 934 | /* Tweak malloc for reduced memory consumption */ |
821 | #ifdef M_TRIM_THRESHOLD | 935 | #ifdef M_TRIM_THRESHOLD |
822 | /* M_TRIM_THRESHOLD is the maximum amount of freed top-most memory | 936 | /* M_TRIM_THRESHOLD is the maximum amount of freed top-most memory |
diff --git a/libbb/executable.c b/libbb/executable.c index 12a48cea3..308c525a3 100644 --- a/libbb/executable.c +++ b/libbb/executable.c | |||
@@ -97,10 +97,19 @@ int FAST_FUNC BB_EXECVP(const char *file, char *const argv[]) | |||
97 | } | 97 | } |
98 | #endif | 98 | #endif |
99 | 99 | ||
100 | int FAST_FUNC BB_EXECVP_or_die(char **argv) | 100 | void FAST_FUNC BB_EXECVP_or_die(char **argv) |
101 | { | 101 | { |
102 | BB_EXECVP(argv[0], argv); | 102 | BB_EXECVP(argv[0], argv); |
103 | /* SUSv3-mandated exit codes */ | 103 | /* SUSv3-mandated exit codes */ |
104 | xfunc_error_retval = (errno == ENOENT) ? 127 : 126; | 104 | xfunc_error_retval = (errno == ENOENT) ? 127 : 126; |
105 | bb_perror_msg_and_die("can't execute '%s'", argv[0]); | 105 | bb_perror_msg_and_die("can't execute '%s'", argv[0]); |
106 | } | 106 | } |
107 | |||
108 | /* Typical idiom for applets which exec *optional* PROG [ARGS] */ | ||
109 | void FAST_FUNC exec_prog_or_SHELL(char **argv) | ||
110 | { | ||
111 | if (argv[0]) { | ||
112 | BB_EXECVP_or_die(argv); | ||
113 | } | ||
114 | run_shell(getenv("SHELL"), /*login:*/ 1, NULL, NULL); | ||
115 | } | ||
diff --git a/libbb/info_msg.c b/libbb/info_msg.c deleted file mode 100644 index 56ca2efd4..000000000 --- a/libbb/info_msg.c +++ /dev/null | |||
@@ -1,62 +0,0 @@ | |||
1 | /* vi: set sw=4 ts=4: */ | ||
2 | /* | ||
3 | * Utility routines. | ||
4 | * | ||
5 | * Copyright (C) 1999-2004 by Erik Andersen <andersen@codepoet.org> | ||
6 | * | ||
7 | * Licensed under GPLv2 or later, see file LICENSE in this source tree. | ||
8 | */ | ||
9 | |||
10 | #include "libbb.h" | ||
11 | #if ENABLE_FEATURE_SYSLOG | ||
12 | # include <syslog.h> | ||
13 | #endif | ||
14 | |||
15 | void FAST_FUNC bb_info_msg(const char *s, ...) | ||
16 | { | ||
17 | #ifdef THIS_ONE_DOESNT_DO_SINGLE_WRITE | ||
18 | va_list p; | ||
19 | /* va_copy is used because it is not portable | ||
20 | * to use va_list p twice */ | ||
21 | va_list p2; | ||
22 | |||
23 | va_start(p, s); | ||
24 | va_copy(p2, p); | ||
25 | if (logmode & LOGMODE_STDIO) { | ||
26 | vprintf(s, p); | ||
27 | fputs(msg_eol, stdout); | ||
28 | } | ||
29 | # if ENABLE_FEATURE_SYSLOG | ||
30 | if (logmode & LOGMODE_SYSLOG) | ||
31 | vsyslog(LOG_INFO, s, p2); | ||
32 | # endif | ||
33 | va_end(p2); | ||
34 | va_end(p); | ||
35 | #else | ||
36 | int used; | ||
37 | char *msg; | ||
38 | va_list p; | ||
39 | |||
40 | if (logmode == 0) | ||
41 | return; | ||
42 | |||
43 | va_start(p, s); | ||
44 | used = vasprintf(&msg, s, p); | ||
45 | va_end(p); | ||
46 | if (used < 0) | ||
47 | return; | ||
48 | |||
49 | # if ENABLE_FEATURE_SYSLOG | ||
50 | if (logmode & LOGMODE_SYSLOG) | ||
51 | syslog(LOG_INFO, "%s", msg); | ||
52 | # endif | ||
53 | if (logmode & LOGMODE_STDIO) { | ||
54 | fflush_all(); | ||
55 | /* used = strlen(msg); - must be true already */ | ||
56 | msg[used++] = '\n'; | ||
57 | full_write(STDOUT_FILENO, msg, used); | ||
58 | } | ||
59 | |||
60 | free(msg); | ||
61 | #endif | ||
62 | } | ||
diff --git a/libbb/ubi.c b/libbb/ubi.c new file mode 100644 index 000000000..34595d797 --- /dev/null +++ b/libbb/ubi.c | |||
@@ -0,0 +1,43 @@ | |||
1 | /* vi: set sw=4 ts=4: */ | ||
2 | /* | ||
3 | * Utility routines. | ||
4 | * | ||
5 | * Copyright (C) 2016 Denys Vlasenko | ||
6 | * | ||
7 | * Licensed under GPLv2, see file LICENSE in this source tree. | ||
8 | */ | ||
9 | //kbuild:lib-y += ubi.o | ||
10 | |||
11 | #include "libbb.h" | ||
12 | |||
13 | // from ubi-media.h | ||
14 | #define UBI_MAX_VOLUME_NAME 127 | ||
15 | #define UBI_MAX_VOLUMES 128 | ||
16 | |||
17 | unsigned FAST_FUNC ubi_devnum_from_devname(const char *str) | ||
18 | { | ||
19 | unsigned ubi_devnum; | ||
20 | |||
21 | if (sscanf(str, "/dev/ubi%u", &ubi_devnum) != 1) | ||
22 | bb_error_msg_and_die("not an UBI device: '%s'", str); | ||
23 | return ubi_devnum; | ||
24 | } | ||
25 | |||
26 | int FAST_FUNC ubi_get_volid_by_name(unsigned ubi_devnum, const char *vol_name) | ||
27 | { | ||
28 | unsigned i; | ||
29 | |||
30 | for (i = 0; i < UBI_MAX_VOLUMES; i++) { | ||
31 | char buf[UBI_MAX_VOLUME_NAME + 1]; | ||
32 | char fname[sizeof("/sys/class/ubi/ubi%u_%u/name") + 2 * sizeof(int)*3]; | ||
33 | |||
34 | sprintf(fname, "/sys/class/ubi/ubi%u_%u/name", ubi_devnum, i); | ||
35 | if (open_read_close(fname, buf, sizeof(buf)) <= 0) | ||
36 | continue; | ||
37 | |||
38 | strchrnul(buf, '\n')[0] = '\0'; | ||
39 | if (strcmp(vol_name, buf) == 0) | ||
40 | return i; | ||
41 | } | ||
42 | bb_error_msg_and_die("volume '%s' not found", vol_name); | ||
43 | } | ||
diff --git a/libbb/verror_msg.c b/libbb/verror_msg.c index 0ef2a311f..22c30357b 100644 --- a/libbb/verror_msg.c +++ b/libbb/verror_msg.c | |||
@@ -20,6 +20,7 @@ const char *msg_eol = "\n"; | |||
20 | void FAST_FUNC bb_verror_msg(const char *s, va_list p, const char* strerr) | 20 | void FAST_FUNC bb_verror_msg(const char *s, va_list p, const char* strerr) |
21 | { | 21 | { |
22 | char *msg, *msg1; | 22 | char *msg, *msg1; |
23 | char stack_msg[80]; | ||
23 | int applet_len, strerr_len, msgeol_len, used; | 24 | int applet_len, strerr_len, msgeol_len, used; |
24 | 25 | ||
25 | if (!logmode) | 26 | if (!logmode) |
@@ -28,6 +29,27 @@ void FAST_FUNC bb_verror_msg(const char *s, va_list p, const char* strerr) | |||
28 | if (!s) /* nomsg[_and_die] uses NULL fmt */ | 29 | if (!s) /* nomsg[_and_die] uses NULL fmt */ |
29 | s = ""; /* some libc don't like printf(NULL) */ | 30 | s = ""; /* some libc don't like printf(NULL) */ |
30 | 31 | ||
32 | applet_len = strlen(applet_name) + 2; /* "applet: " */ | ||
33 | strerr_len = strerr ? strlen(strerr) : 0; | ||
34 | msgeol_len = strlen(msg_eol); | ||
35 | |||
36 | /* This costs ~90 bytes of code, but avoids costly | ||
37 | * malloc()[in vasprintf]+realloc()+memmove()+free() in 99% of cases. | ||
38 | * ~40% speedup. | ||
39 | */ | ||
40 | if ((int)sizeof(stack_msg) - applet_len > 0) { | ||
41 | va_list p2; | ||
42 | |||
43 | /* It is not portable to use va_list twice, need to va_copy it */ | ||
44 | va_copy(p2, p); | ||
45 | used = vsnprintf(stack_msg + applet_len, (int)sizeof(stack_msg) - applet_len, s, p2); | ||
46 | va_end(p2); | ||
47 | msg = stack_msg; | ||
48 | used += applet_len; | ||
49 | if (used < (int)sizeof(stack_msg) - 3 - msgeol_len - strerr_len) | ||
50 | goto add_pfx_and_sfx; | ||
51 | } | ||
52 | |||
31 | used = vasprintf(&msg, s, p); | 53 | used = vasprintf(&msg, s, p); |
32 | if (used < 0) | 54 | if (used < 0) |
33 | return; | 55 | return; |
@@ -37,9 +59,6 @@ void FAST_FUNC bb_verror_msg(const char *s, va_list p, const char* strerr) | |||
37 | * This is needed for e.g. httpd logging, when multiple | 59 | * This is needed for e.g. httpd logging, when multiple |
38 | * children can produce log messages simultaneously. */ | 60 | * children can produce log messages simultaneously. */ |
39 | 61 | ||
40 | applet_len = strlen(applet_name) + 2; /* "applet: " */ | ||
41 | strerr_len = strerr ? strlen(strerr) : 0; | ||
42 | msgeol_len = strlen(msg_eol); | ||
43 | /* can't use xrealloc: it calls error_msg on failure, | 62 | /* can't use xrealloc: it calls error_msg on failure, |
44 | * that may result in a recursion */ | 63 | * that may result in a recursion */ |
45 | /* +3 is for ": " before strerr and for terminating NUL */ | 64 | /* +3 is for ": " before strerr and for terminating NUL */ |
@@ -52,6 +71,7 @@ void FAST_FUNC bb_verror_msg(const char *s, va_list p, const char* strerr) | |||
52 | /* TODO: maybe use writev instead of memmoving? Need full_writev? */ | 71 | /* TODO: maybe use writev instead of memmoving? Need full_writev? */ |
53 | memmove(msg + applet_len, msg, used); | 72 | memmove(msg + applet_len, msg, used); |
54 | used += applet_len; | 73 | used += applet_len; |
74 | add_pfx_and_sfx: | ||
55 | strcpy(msg, applet_name); | 75 | strcpy(msg, applet_name); |
56 | msg[applet_len - 2] = ':'; | 76 | msg[applet_len - 2] = ':'; |
57 | msg[applet_len - 1] = ' '; | 77 | msg[applet_len - 1] = ' '; |
@@ -76,7 +96,8 @@ void FAST_FUNC bb_verror_msg(const char *s, va_list p, const char* strerr) | |||
76 | syslog(syslog_level, "%s", msg + applet_len); | 96 | syslog(syslog_level, "%s", msg + applet_len); |
77 | } | 97 | } |
78 | #endif | 98 | #endif |
79 | free(msg); | 99 | if (msg != stack_msg) |
100 | free(msg); | ||
80 | } | 101 | } |
81 | 102 | ||
82 | #ifdef VERSION_WITH_WRITEV | 103 | #ifdef VERSION_WITH_WRITEV |
diff --git a/libbb/vfork_daemon_rexec.c b/libbb/vfork_daemon_rexec.c index 2d3204507..f488f8e0c 100644 --- a/libbb/vfork_daemon_rexec.c +++ b/libbb/vfork_daemon_rexec.c | |||
@@ -118,8 +118,6 @@ int FAST_FUNC run_nofork_applet(int applet_no, char **argv) | |||
118 | 118 | ||
119 | save_nofork_data(&old); | 119 | save_nofork_data(&old); |
120 | 120 | ||
121 | applet_name = APPLET_NAME(applet_no); | ||
122 | |||
123 | xfunc_error_retval = EXIT_FAILURE; | 121 | xfunc_error_retval = EXIT_FAILURE; |
124 | 122 | ||
125 | /* In case getopt() or getopt32() was already called: | 123 | /* In case getopt() or getopt32() was already called: |
@@ -159,6 +157,7 @@ int FAST_FUNC run_nofork_applet(int applet_no, char **argv) | |||
159 | * need argv untouched because they free argv[i]! */ | 157 | * need argv untouched because they free argv[i]! */ |
160 | char *tmp_argv[argc+1]; | 158 | char *tmp_argv[argc+1]; |
161 | memcpy(tmp_argv, argv, (argc+1) * sizeof(tmp_argv[0])); | 159 | memcpy(tmp_argv, argv, (argc+1) * sizeof(tmp_argv[0])); |
160 | applet_name = tmp_argv[0]; | ||
162 | /* Finally we can call NOFORK applet's main() */ | 161 | /* Finally we can call NOFORK applet's main() */ |
163 | rc = applet_main[applet_no](argc, tmp_argv); | 162 | rc = applet_main[applet_no](argc, tmp_argv); |
164 | } else { | 163 | } else { |
diff --git a/libbb/xfuncs.c b/libbb/xfuncs.c index 206edb4a0..3f9a84ad4 100644 --- a/libbb/xfuncs.c +++ b/libbb/xfuncs.c | |||
@@ -315,3 +315,15 @@ int FAST_FUNC wait4pid(pid_t pid) | |||
315 | return WTERMSIG(status) + 0x180; | 315 | return WTERMSIG(status) + 0x180; |
316 | return 0; | 316 | return 0; |
317 | } | 317 | } |
318 | |||
319 | // Useful when we do know that pid is valid, and we just want to wait | ||
320 | // for it to exit. Not existing pid is fatal. waitpid() status is not returned. | ||
321 | int FAST_FUNC wait_for_exitstatus(pid_t pid) | ||
322 | { | ||
323 | int exit_status, n; | ||
324 | |||
325 | n = safe_waitpid(pid, &exit_status, 0); | ||
326 | if (n < 0) | ||
327 | bb_perror_msg_and_die("waitpid"); | ||
328 | return exit_status; | ||
329 | } | ||
diff --git a/libbb/xfuncs_printf.c b/libbb/xfuncs_printf.c index 73488908d..e9222f690 100644 --- a/libbb/xfuncs_printf.c +++ b/libbb/xfuncs_printf.c | |||
@@ -390,6 +390,12 @@ void FAST_FUNC xchdir(const char *path) | |||
390 | bb_perror_msg_and_die("can't change directory to '%s'", path); | 390 | bb_perror_msg_and_die("can't change directory to '%s'", path); |
391 | } | 391 | } |
392 | 392 | ||
393 | void FAST_FUNC xfchdir(int fd) | ||
394 | { | ||
395 | if (fchdir(fd)) | ||
396 | bb_perror_msg_and_die("fchdir"); | ||
397 | } | ||
398 | |||
393 | void FAST_FUNC xchroot(const char *path) | 399 | void FAST_FUNC xchroot(const char *path) |
394 | { | 400 | { |
395 | if (chroot(path)) | 401 | if (chroot(path)) |
@@ -653,3 +659,19 @@ pid_t FAST_FUNC xfork(void) | |||
653 | return pid; | 659 | return pid; |
654 | } | 660 | } |
655 | #endif | 661 | #endif |
662 | |||
663 | void FAST_FUNC xvfork_parent_waits_and_exits(void) | ||
664 | { | ||
665 | pid_t pid; | ||
666 | |||
667 | fflush_all(); | ||
668 | pid = xvfork(); | ||
669 | if (pid > 0) { | ||
670 | /* Parent */ | ||
671 | int exit_status = wait_for_exitstatus(pid); | ||
672 | if (WIFSIGNALED(exit_status)) | ||
673 | kill_myself_with_sig(WTERMSIG(exit_status)); | ||
674 | _exit(WEXITSTATUS(exit_status)); | ||
675 | } | ||
676 | /* Child continues */ | ||
677 | } | ||