aboutsummaryrefslogtreecommitdiff
path: root/libbb
diff options
context:
space:
mode:
authorRon Yorston <rmy@pobox.com>2015-10-13 14:45:51 +0100
committerRon Yorston <rmy@pobox.com>2015-10-13 14:45:51 +0100
commit8e509f11bceeec419abc718300bef7422d1fee4c (patch)
treefdfbc752ad94102e3613a5d7254f14a93eaf7f56 /libbb
parent420f5edfe7676fe6e7cddbbf15c04649d096e422 (diff)
parent4d0c1ea4784c9844f8468d97ca5c26d3c70f9921 (diff)
downloadbusybox-w32-8e509f11bceeec419abc718300bef7422d1fee4c.tar.gz
busybox-w32-8e509f11bceeec419abc718300bef7422d1fee4c.tar.bz2
busybox-w32-8e509f11bceeec419abc718300bef7422d1fee4c.zip
Merge branch 'busybox' into merge
Diffstat (limited to 'libbb')
-rw-r--r--libbb/auto_string.c23
-rw-r--r--libbb/bb_askpass.c6
-rw-r--r--libbb/bbunit.c31
-rw-r--r--libbb/compare_string_array.c59
-rw-r--r--libbb/fflush_stdout_and_exit.c13
-rw-r--r--libbb/hash_md5_sha.c16
-rw-r--r--libbb/human_readable.c9
-rw-r--r--libbb/messages.c2
-rw-r--r--libbb/parse_mode.c16
-rw-r--r--libbb/printable_string.c10
-rw-r--r--libbb/procps.c4
-rw-r--r--libbb/udp_io.c4
-rw-r--r--libbb/vfork_daemon_rexec.c39
-rw-r--r--libbb/xconnect.c25
-rw-r--r--libbb/xfunc_die.c26
15 files changed, 162 insertions, 121 deletions
diff --git a/libbb/auto_string.c b/libbb/auto_string.c
new file mode 100644
index 000000000..ae940069a
--- /dev/null
+++ b/libbb/auto_string.c
@@ -0,0 +1,23 @@
1/* vi: set sw=4 ts=4: */
2/*
3 * Utility routines.
4 *
5 * Copyright (C) 2015 Denys Vlasenko
6 *
7 * Licensed under GPLv2, see file LICENSE in this source tree.
8 */
9//kbuild:lib-y += auto_string.o
10
11#include "libbb.h"
12
13char* FAST_FUNC auto_string(char *str)
14{
15 static char *saved[4];
16 static uint8_t cur_saved; /* = 0 */
17
18 free(saved[cur_saved]);
19 saved[cur_saved] = str;
20 cur_saved = (cur_saved + 1) & (ARRAY_SIZE(saved)-1);
21
22 return str;
23}
diff --git a/libbb/bb_askpass.c b/libbb/bb_askpass.c
index 1927ba9e9..c2580b9eb 100644
--- a/libbb/bb_askpass.c
+++ b/libbb/bb_askpass.c
@@ -1,7 +1,6 @@
1/* vi: set sw=4 ts=4: */ 1/* vi: set sw=4 ts=4: */
2/* 2/*
3 * Ask for a password 3 * Ask for a password
4 * I use a static buffer in this function. Plan accordingly.
5 * 4 *
6 * Copyright (C) 1999-2004 by Erik Andersen <andersen@codepoet.org> 5 * Copyright (C) 1999-2004 by Erik Andersen <andersen@codepoet.org>
7 * 6 *
@@ -23,8 +22,8 @@ char* FAST_FUNC bb_ask(const int fd, int timeout, const char *prompt)
23{ 22{
24 /* Was static char[BIGNUM] */ 23 /* Was static char[BIGNUM] */
25 enum { sizeof_passwd = 128 }; 24 enum { sizeof_passwd = 128 };
26 static char *passwd;
27 25
26 char *passwd;
28 char *ret; 27 char *ret;
29 int i; 28 int i;
30 struct sigaction sa, oldsa; 29 struct sigaction sa, oldsa;
@@ -62,8 +61,7 @@ char* FAST_FUNC bb_ask(const int fd, int timeout, const char *prompt)
62 alarm(timeout); 61 alarm(timeout);
63 } 62 }
64 63
65 if (!passwd) 64 passwd = auto_string(xmalloc(sizeof_passwd));
66 passwd = xmalloc(sizeof_passwd);
67 ret = passwd; 65 ret = passwd;
68 i = 0; 66 i = 0;
69 while (1) { 67 while (1) {
diff --git a/libbb/bbunit.c b/libbb/bbunit.c
index 4c692d59f..db67b1081 100644
--- a/libbb/bbunit.c
+++ b/libbb/bbunit.c
@@ -17,8 +17,6 @@
17 17
18#include "libbb.h" 18#include "libbb.h"
19 19
20#define WANT_TIMING 0
21
22static llist_t *tests = NULL; 20static llist_t *tests = NULL;
23static unsigned tests_registered = 0; 21static unsigned tests_registered = 0;
24static int test_retval; 22static int test_retval;
@@ -34,57 +32,34 @@ void bbunit_settestfailed(void)
34 test_retval = -1; 32 test_retval = -1;
35} 33}
36 34
37#if WANT_TIMING
38static void timeval_diff(struct timeval* res,
39 const struct timeval* x,
40 const struct timeval* y)
41{
42 long udiff = x->tv_usec - y->tv_usec;
43
44 res->tv_sec = x->tv_sec - y->tv_sec - (udiff < 0);
45 res->tv_usec = (udiff >= 0 ? udiff : udiff + 1000000);
46}
47#endif
48
49int unit_main(int argc UNUSED_PARAM, char **argv UNUSED_PARAM) MAIN_EXTERNALLY_VISIBLE; 35int unit_main(int argc UNUSED_PARAM, char **argv UNUSED_PARAM) MAIN_EXTERNALLY_VISIBLE;
50int unit_main(int argc UNUSED_PARAM, char **argv UNUSED_PARAM) 36int unit_main(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
51{ 37{
52 unsigned tests_run = 0; 38 unsigned tests_run = 0;
53 unsigned tests_failed = 0; 39 unsigned tests_failed = 0;
54#if WANT_TIMING
55 struct timeval begin;
56 struct timeval end;
57 struct timeval time_spent;
58 gettimeofday(&begin, NULL);
59#endif
60 40
61 bb_error_msg("Running %d test(s)...", tests_registered); 41 bb_error_msg("Running %d test(s)...", tests_registered);
62 for (;;) { 42 for (;;) {
63 struct bbunit_listelem* el = llist_pop(&tests); 43 struct bbunit_listelem* el = llist_pop(&tests);
64 if (!el) 44 if (!el)
65 break; 45 break;
46
66 bb_error_msg("Case: [%s]", el->name); 47 bb_error_msg("Case: [%s]", el->name);
67 test_retval = 0; 48 test_retval = 0;
68 el->testfunc(); 49 el->testfunc();
50
69 if (test_retval < 0) { 51 if (test_retval < 0) {
70 bb_error_msg("[ERROR] [%s]: TEST FAILED", el->name); 52 bb_error_msg("[ERROR] [%s]: TEST FAILED", el->name);
71 tests_failed++; 53 tests_failed++;
72 } 54 }
73 tests_run++; 55 tests_run++;
74 el = el->next;
75 } 56 }
76 57
77#if WANT_TIMING
78 gettimeofday(&end, NULL);
79 timeval_diff(&time_spent, &end, &begin);
80 bb_error_msg("Elapsed time %u.%06u seconds",
81 (int)time_spent.tv_sec,
82 (int)time_spent.tv_usec);
83#endif
84 if (tests_failed > 0) { 58 if (tests_failed > 0) {
85 bb_error_msg("[ERROR] %u test(s) FAILED", tests_failed); 59 bb_error_msg("[ERROR] %u test(s) FAILED", tests_failed);
86 return EXIT_FAILURE; 60 return EXIT_FAILURE;
87 } 61 }
62
88 bb_error_msg("All tests passed"); 63 bb_error_msg("All tests passed");
89 return EXIT_SUCCESS; 64 return EXIT_SUCCESS;
90} 65}
diff --git a/libbb/compare_string_array.c b/libbb/compare_string_array.c
index e24815a03..2f51237a3 100644
--- a/libbb/compare_string_array.c
+++ b/libbb/compare_string_array.c
@@ -5,6 +5,11 @@
5 5
6#include "libbb.h" 6#include "libbb.h"
7 7
8/*
9 * Return NULL if string is not prefixed with key. Return pointer to the
10 * first character in string after the prefix key. If key is an empty string,
11 * return pointer to the beginning of string.
12 */
8char* FAST_FUNC is_prefixed_with(const char *string, const char *key) 13char* FAST_FUNC is_prefixed_with(const char *string, const char *key)
9{ 14{
10#if 0 /* Two passes over key - probably slower */ 15#if 0 /* Two passes over key - probably slower */
@@ -23,6 +28,26 @@ char* FAST_FUNC is_prefixed_with(const char *string, const char *key)
23#endif 28#endif
24} 29}
25 30
31/*
32 * Return NULL if string is not suffixed with key. Return pointer to the
33 * beginning of prefix key in string. If key is an empty string return pointer
34 * to the end of string.
35 */
36char* FAST_FUNC is_suffixed_with(const char *string, const char *key)
37{
38 size_t key_len = strlen(key);
39 ssize_t len_diff = strlen(string) - key_len;
40
41 if (len_diff >= 0) {
42 string += len_diff;
43 if (strcmp(string, key) == 0) {
44 return (char*)string;
45 }
46 }
47
48 return NULL;
49}
50
26/* returns the array index of the string */ 51/* returns the array index of the string */
27/* (index of first match is returned, or -1) */ 52/* (index of first match is returned, or -1) */
28int FAST_FUNC index_in_str_array(const char *const string_array[], const char *key) 53int FAST_FUNC index_in_str_array(const char *const string_array[], const char *key)
@@ -110,3 +135,37 @@ smallint FAST_FUNC yesno(const char *str)
110 return ret / 3; 135 return ret / 3;
111} 136}
112#endif 137#endif
138
139#if ENABLE_UNIT_TEST
140
141BBUNIT_DEFINE_TEST(is_prefixed_with)
142{
143 BBUNIT_ASSERT_STREQ(" bar", is_prefixed_with("foo bar", "foo"));
144 BBUNIT_ASSERT_STREQ("bar", is_prefixed_with("foo bar", "foo "));
145 BBUNIT_ASSERT_STREQ("", is_prefixed_with("foo", "foo"));
146 BBUNIT_ASSERT_STREQ("foo", is_prefixed_with("foo", ""));
147 BBUNIT_ASSERT_STREQ("", is_prefixed_with("", ""));
148
149 BBUNIT_ASSERT_NULL(is_prefixed_with("foo", "bar foo"));
150 BBUNIT_ASSERT_NULL(is_prefixed_with("foo foo", "bar"));
151 BBUNIT_ASSERT_NULL(is_prefixed_with("", "foo"));
152
153 BBUNIT_ENDTEST;
154}
155
156BBUNIT_DEFINE_TEST(is_suffixed_with)
157{
158 BBUNIT_ASSERT_STREQ("bar", is_suffixed_with("foo bar", "bar"));
159 BBUNIT_ASSERT_STREQ("foo", is_suffixed_with("foo", "foo"));
160 BBUNIT_ASSERT_STREQ("", is_suffixed_with("foo", ""));
161 BBUNIT_ASSERT_STREQ("", is_suffixed_with("", ""));
162 BBUNIT_ASSERT_STREQ("foo", is_suffixed_with("barfoofoo", "foo"));
163
164 BBUNIT_ASSERT_NULL(is_suffixed_with("foo", "bar foo"));
165 BBUNIT_ASSERT_NULL(is_suffixed_with("foo foo", "bar"));
166 BBUNIT_ASSERT_NULL(is_suffixed_with("", "foo"));
167
168 BBUNIT_ENDTEST;
169}
170
171#endif /* ENABLE_UNIT_TEST */
diff --git a/libbb/fflush_stdout_and_exit.c b/libbb/fflush_stdout_and_exit.c
index 9ad5dbf96..b4bed865f 100644
--- a/libbb/fflush_stdout_and_exit.c
+++ b/libbb/fflush_stdout_and_exit.c
@@ -15,15 +15,10 @@
15 15
16void FAST_FUNC fflush_stdout_and_exit(int retval) 16void FAST_FUNC fflush_stdout_and_exit(int retval)
17{ 17{
18 xfunc_error_retval = retval;
18 if (fflush(stdout)) 19 if (fflush(stdout))
19 bb_perror_msg_and_die(bb_msg_standard_output); 20 bb_perror_msg_and_die(bb_msg_standard_output);
20 21 /* In case we are in NOFORK applet. Do not exit() directly,
21 if (ENABLE_FEATURE_PREFER_APPLETS && die_sleep < 0) { 22 * but use xfunc_die() */
22 /* We are in NOFORK applet. Do not exit() directly, 23 xfunc_die();
23 * but use xfunc_die() */
24 xfunc_error_retval = retval;
25 xfunc_die();
26 }
27
28 exit(retval);
29} 24}
diff --git a/libbb/hash_md5_sha.c b/libbb/hash_md5_sha.c
index 1f63ccdee..d08c6b2f7 100644
--- a/libbb/hash_md5_sha.c
+++ b/libbb/hash_md5_sha.c
@@ -137,7 +137,7 @@ static void FAST_FUNC md5_process_block64(md5_ctx_t *ctx)
137#if MD5_SMALL > 0 137#if MD5_SMALL > 0
138 /* Before we start, one word to the strange constants. 138 /* Before we start, one word to the strange constants.
139 They are defined in RFC 1321 as 139 They are defined in RFC 1321 as
140 T[i] = (int)(4294967296.0 * fabs(sin(i))), i=1..64 140 T[i] = (int)(2^32 * fabs(sin(i))), i=1..64
141 */ 141 */
142 static const uint32_t C_array[] = { 142 static const uint32_t C_array[] = {
143 /* round 1 */ 143 /* round 1 */
@@ -213,7 +213,7 @@ static void FAST_FUNC md5_process_block64(md5_ctx_t *ctx)
213 case 2: 213 case 2:
214 temp += FH(B, C, D); 214 temp += FH(B, C, D);
215 break; 215 break;
216 case 3: 216 default: /* case 3 */
217 temp += FI(B, C, D); 217 temp += FI(B, C, D);
218 } 218 }
219 temp += words[(int) (*pp++)] + *pc++; 219 temp += words[(int) (*pp++)] + *pc++;
@@ -277,10 +277,6 @@ static void FAST_FUNC md5_process_block64(md5_ctx_t *ctx)
277 277
278#else /* MD5_SMALL == 0 or 1 */ 278#else /* MD5_SMALL == 0 or 1 */
279 279
280 uint32_t A_save = A;
281 uint32_t B_save = B;
282 uint32_t C_save = C;
283 uint32_t D_save = D;
284# if MD5_SMALL == 1 280# if MD5_SMALL == 1
285 const uint32_t *pc; 281 const uint32_t *pc;
286 const char *pp; 282 const char *pp;
@@ -425,10 +421,10 @@ static void FAST_FUNC md5_process_block64(md5_ctx_t *ctx)
425# undef OP 421# undef OP
426# endif 422# endif
427 /* Add checksum to the starting values */ 423 /* Add checksum to the starting values */
428 ctx->hash[0] = A_save + A; 424 ctx->hash[0] += A;
429 ctx->hash[1] = B_save + B; 425 ctx->hash[1] += B;
430 ctx->hash[2] = C_save + C; 426 ctx->hash[2] += C;
431 ctx->hash[3] = D_save + D; 427 ctx->hash[3] += D;
432#endif 428#endif
433} 429}
434#undef FF 430#undef FF
diff --git a/libbb/human_readable.c b/libbb/human_readable.c
index 0b2eb777e..5c7fc076f 100644
--- a/libbb/human_readable.c
+++ b/libbb/human_readable.c
@@ -37,8 +37,6 @@ const char* FAST_FUNC make_human_readable_str(unsigned long long val,
37 '\0', 'K', 'M', 'G', 'T', 'P', 'E', 'Z', 'Y' 37 '\0', 'K', 'M', 'G', 'T', 'P', 'E', 'Z', 'Y'
38 }; 38 };
39 39
40 static char *str;
41
42 unsigned frac; /* 0..9 - the fractional digit */ 40 unsigned frac; /* 0..9 - the fractional digit */
43 const char *u; 41 const char *u;
44 const char *fmt; 42 const char *fmt;
@@ -81,12 +79,7 @@ const char* FAST_FUNC make_human_readable_str(unsigned long long val,
81#endif 79#endif
82 } 80 }
83 81
84 if (!str) { 82 return auto_string(xasprintf(fmt, val, frac, *u));
85 /* sufficient for any width of val */
86 str = xmalloc(sizeof(val)*3 + 2 + 3);
87 }
88 sprintf(str, fmt, val, frac, *u);
89 return str;
90} 83}
91 84
92 85
diff --git a/libbb/messages.c b/libbb/messages.c
index ef42b30d7..108cb0285 100644
--- a/libbb/messages.c
+++ b/libbb/messages.c
@@ -45,7 +45,7 @@ const char bb_PATH_root_path[] ALIGN1 =
45 "PATH=/sbin:/usr/sbin:/bin:/usr/bin" BB_ADDITIONAL_PATH; 45 "PATH=/sbin:/usr/sbin:/bin:/usr/bin" BB_ADDITIONAL_PATH;
46 46
47 47
48const int const_int_1 = 1; 48//const int const_int_1 = 1;
49/* explicitly = 0, otherwise gcc may make it a common variable 49/* explicitly = 0, otherwise gcc may make it a common variable
50 * and it will end up in bss */ 50 * and it will end up in bss */
51const int const_int_0 = 0; 51const int const_int_0 = 0;
diff --git a/libbb/parse_mode.c b/libbb/parse_mode.c
index 5a4e1c579..bddd39bca 100644
--- a/libbb/parse_mode.c
+++ b/libbb/parse_mode.c
@@ -15,7 +15,7 @@
15 15
16#define FILEMODEBITS (S_ISUID | S_ISGID | S_ISVTX | S_IRWXU | S_IRWXG | S_IRWXO) 16#define FILEMODEBITS (S_ISUID | S_ISGID | S_ISVTX | S_IRWXU | S_IRWXG | S_IRWXO)
17 17
18int FAST_FUNC bb_parse_mode(const char *s, mode_t *current_mode) 18int FAST_FUNC bb_parse_mode(const char *s, unsigned current_mode)
19{ 19{
20 static const mode_t who_mask[] = { 20 static const mode_t who_mask[] = {
21 S_ISUID | S_ISGID | S_ISVTX | S_IRWXU | S_IRWXG | S_IRWXO, /* a */ 21 S_ISUID | S_ISGID | S_ISVTX | S_IRWXU | S_IRWXG | S_IRWXO, /* a */
@@ -46,13 +46,12 @@ int FAST_FUNC bb_parse_mode(const char *s, mode_t *current_mode)
46 46
47 tmp = strtoul(s, &e, 8); 47 tmp = strtoul(s, &e, 8);
48 if (*e || (tmp > 07777U)) { /* Check range and trailing chars. */ 48 if (*e || (tmp > 07777U)) { /* Check range and trailing chars. */
49 return 0; 49 return -1;
50 } 50 }
51 *current_mode = tmp; 51 return tmp;
52 return 1;
53 } 52 }
54 53
55 new_mode = *current_mode; 54 new_mode = current_mode;
56 55
57 /* Note: we allow empty clauses, and hence empty modes. 56 /* Note: we allow empty clauses, and hence empty modes.
58 * We treat an empty mode as no change to perms. */ 57 * We treat an empty mode as no change to perms. */
@@ -71,7 +70,7 @@ int FAST_FUNC bb_parse_mode(const char *s, mode_t *current_mode)
71 if (*p == *s) { 70 if (*p == *s) {
72 wholist |= who_mask[(int)(p-who_chars)]; 71 wholist |= who_mask[(int)(p-who_chars)];
73 if (!*++s) { 72 if (!*++s) {
74 return 0; 73 return -1;
75 } 74 }
76 goto WHO_LIST; 75 goto WHO_LIST;
77 } 76 }
@@ -80,7 +79,7 @@ int FAST_FUNC bb_parse_mode(const char *s, mode_t *current_mode)
80 do { /* Process action list. */ 79 do { /* Process action list. */
81 if ((*s != '+') && (*s != '-')) { 80 if ((*s != '+') && (*s != '-')) {
82 if (*s != '=') { 81 if (*s != '=') {
83 return 0; 82 return -1;
84 } 83 }
85 /* Since op is '=', clear all bits corresponding to the 84 /* Since op is '=', clear all bits corresponding to the
86 * wholist, or all file bits if wholist is empty. */ 85 * wholist, or all file bits if wholist is empty. */
@@ -145,6 +144,5 @@ int FAST_FUNC bb_parse_mode(const char *s, mode_t *current_mode)
145 } while (*s && (*s != ',')); 144 } while (*s && (*s != ','));
146 } 145 }
147 146
148 *current_mode = new_mode; 147 return new_mode;
149 return 1;
150} 148}
diff --git a/libbb/printable_string.c b/libbb/printable_string.c
index 3e768d0b9..e638a178e 100644
--- a/libbb/printable_string.c
+++ b/libbb/printable_string.c
@@ -11,9 +11,6 @@
11 11
12const char* FAST_FUNC printable_string(uni_stat_t *stats, const char *str) 12const char* FAST_FUNC printable_string(uni_stat_t *stats, const char *str)
13{ 13{
14 static char *saved[4];
15 static unsigned cur_saved; /* = 0 */
16
17 char *dst; 14 char *dst;
18 const char *s; 15 const char *s;
19 16
@@ -56,10 +53,5 @@ const char* FAST_FUNC printable_string(uni_stat_t *stats, const char *str)
56 } 53 }
57 } 54 }
58#endif 55#endif
59 56 return auto_string(dst);
60 free(saved[cur_saved]);
61 saved[cur_saved] = dst;
62 cur_saved = (cur_saved + 1) & (ARRAY_SIZE(saved)-1);
63
64 return dst;
65} 57}
diff --git a/libbb/procps.c b/libbb/procps.c
index 32dae43e3..5a4ea59d0 100644
--- a/libbb/procps.c
+++ b/libbb/procps.c
@@ -284,7 +284,6 @@ int FAST_FUNC procps_read_smaps(pid_t pid, struct smaprec *total,
284} 284}
285#endif 285#endif
286 286
287void BUG_comm_size(void);
288procps_status_t* FAST_FUNC procps_scan(procps_status_t* sp, int flags) 287procps_status_t* FAST_FUNC procps_scan(procps_status_t* sp, int flags)
289{ 288{
290 if (!sp) 289 if (!sp)
@@ -386,8 +385,7 @@ procps_status_t* FAST_FUNC procps_scan(procps_status_t* sp, int flags)
386 /*if (!cp || cp[1] != ' ') 385 /*if (!cp || cp[1] != ' ')
387 continue;*/ 386 continue;*/
388 cp[0] = '\0'; 387 cp[0] = '\0';
389 if (sizeof(sp->comm) < 16) 388 BUILD_BUG_ON(sizeof(sp->comm) < 16);
390 BUG_comm_size();
391 comm1 = strchr(buf, '('); 389 comm1 = strchr(buf, '(');
392 /*if (comm1)*/ 390 /*if (comm1)*/
393 safe_strncpy(sp->comm, comm1 + 1, sizeof(sp->comm)); 391 safe_strncpy(sp->comm, comm1 + 1, sizeof(sp->comm));
diff --git a/libbb/udp_io.c b/libbb/udp_io.c
index 7985a9723..a32af9bd2 100644
--- a/libbb/udp_io.c
+++ b/libbb/udp_io.c
@@ -16,10 +16,10 @@ void FAST_FUNC
16socket_want_pktinfo(int fd UNUSED_PARAM) 16socket_want_pktinfo(int fd UNUSED_PARAM)
17{ 17{
18#ifdef IP_PKTINFO 18#ifdef IP_PKTINFO
19 setsockopt(fd, IPPROTO_IP, IP_PKTINFO, &const_int_1, sizeof(int)); 19 setsockopt_1(fd, IPPROTO_IP, IP_PKTINFO);
20#endif 20#endif
21#if ENABLE_FEATURE_IPV6 && defined(IPV6_PKTINFO) 21#if ENABLE_FEATURE_IPV6 && defined(IPV6_PKTINFO)
22 setsockopt(fd, IPPROTO_IPV6, IPV6_PKTINFO, &const_int_1, sizeof(int)); 22 setsockopt_1(fd, IPPROTO_IPV6, IPV6_PKTINFO);
23#endif 23#endif
24} 24}
25 25
diff --git a/libbb/vfork_daemon_rexec.c b/libbb/vfork_daemon_rexec.c
index de4d14fce..2d3204507 100644
--- a/libbb/vfork_daemon_rexec.c
+++ b/libbb/vfork_daemon_rexec.c
@@ -71,28 +71,44 @@ pid_t FAST_FUNC xspawn(char **argv)
71} 71}
72 72
73#if ENABLE_FEATURE_PREFER_APPLETS 73#if ENABLE_FEATURE_PREFER_APPLETS
74static jmp_buf die_jmp;
75static void jump(void)
76{
77 /* Special case. We arrive here if NOFORK applet
78 * calls xfunc, which then decides to die.
79 * We don't die, but jump instead back to caller.
80 * NOFORK applets still cannot carelessly call xfuncs:
81 * p = xmalloc(10);
82 * q = xmalloc(10); // BUG! if this dies, we leak p!
83 */
84 /* | 0x100 allows to pass zero exitcode (longjmp can't pass 0).
85 * This works because exitcodes are bytes,
86 * run_nofork_applet() ensures that by "& 0xff" */
87 longjmp(die_jmp, xfunc_error_retval | 0x100);
88}
89
74struct nofork_save_area { 90struct nofork_save_area {
75 jmp_buf die_jmp; 91 jmp_buf die_jmp;
92 void (*die_func)(void);
76 const char *applet_name; 93 const char *applet_name;
77 uint32_t option_mask32; 94 uint32_t option_mask32;
78 int die_sleep;
79 uint8_t xfunc_error_retval; 95 uint8_t xfunc_error_retval;
80}; 96};
81static void save_nofork_data(struct nofork_save_area *save) 97static void save_nofork_data(struct nofork_save_area *save)
82{ 98{
83 memcpy(&save->die_jmp, &die_jmp, sizeof(die_jmp)); 99 memcpy(&save->die_jmp, &die_jmp, sizeof(die_jmp));
100 save->die_func = die_func;
84 save->applet_name = applet_name; 101 save->applet_name = applet_name;
85 save->xfunc_error_retval = xfunc_error_retval;
86 save->option_mask32 = option_mask32; 102 save->option_mask32 = option_mask32;
87 save->die_sleep = die_sleep; 103 save->xfunc_error_retval = xfunc_error_retval;
88} 104}
89static void restore_nofork_data(struct nofork_save_area *save) 105static void restore_nofork_data(struct nofork_save_area *save)
90{ 106{
91 memcpy(&die_jmp, &save->die_jmp, sizeof(die_jmp)); 107 memcpy(&die_jmp, &save->die_jmp, sizeof(die_jmp));
108 die_func = save->die_func;
92 applet_name = save->applet_name; 109 applet_name = save->applet_name;
93 xfunc_error_retval = save->xfunc_error_retval;
94 option_mask32 = save->option_mask32; 110 option_mask32 = save->option_mask32;
95 die_sleep = save->die_sleep; 111 xfunc_error_retval = save->xfunc_error_retval;
96} 112}
97 113
98int FAST_FUNC run_nofork_applet(int applet_no, char **argv) 114int FAST_FUNC run_nofork_applet(int applet_no, char **argv)
@@ -135,11 +151,8 @@ int FAST_FUNC run_nofork_applet(int applet_no, char **argv)
135 while (argv[argc]) 151 while (argv[argc])
136 argc++; 152 argc++;
137 153
138 /* Special flag for xfunc_die(). If xfunc will "die" 154 /* If xfunc "dies" in NOFORK applet, die_func longjmp's here instead */
139 * in NOFORK applet, xfunc_die() sees negative 155 die_func = jump;
140 * die_sleep and longjmp here instead. */
141 die_sleep = -1;
142
143 rc = setjmp(die_jmp); 156 rc = setjmp(die_jmp);
144 if (!rc) { 157 if (!rc) {
145 /* Some callers (xargs) 158 /* Some callers (xargs)
@@ -148,10 +161,8 @@ int FAST_FUNC run_nofork_applet(int applet_no, char **argv)
148 memcpy(tmp_argv, argv, (argc+1) * sizeof(tmp_argv[0])); 161 memcpy(tmp_argv, argv, (argc+1) * sizeof(tmp_argv[0]));
149 /* Finally we can call NOFORK applet's main() */ 162 /* Finally we can call NOFORK applet's main() */
150 rc = applet_main[applet_no](argc, tmp_argv); 163 rc = applet_main[applet_no](argc, tmp_argv);
151 } else { /* xfunc died in NOFORK applet */ 164 } else {
152 /* in case they meant to return 0... */ 165 /* xfunc died in NOFORK applet */
153 if (rc == -2222)
154 rc = 0;
155 } 166 }
156 167
157 /* Restoring some globals */ 168 /* Restoring some globals */
diff --git a/libbb/xconnect.c b/libbb/xconnect.c
index 442482a8b..0a4d8f128 100644
--- a/libbb/xconnect.c
+++ b/libbb/xconnect.c
@@ -14,13 +14,34 @@
14#include <sys/un.h> 14#include <sys/un.h>
15#include "libbb.h" 15#include "libbb.h"
16 16
17int FAST_FUNC setsockopt_int(int fd, int level, int optname, int optval)
18{
19 return setsockopt(fd, level, optname, &optval, sizeof(int));
20}
21int FAST_FUNC setsockopt_1(int fd, int level, int optname)
22{
23 return setsockopt_int(fd, level, optname, 1);
24}
25int FAST_FUNC setsockopt_SOL_SOCKET_int(int fd, int optname, int optval)
26{
27 return setsockopt_int(fd, SOL_SOCKET, optname, optval);
28}
29int FAST_FUNC setsockopt_SOL_SOCKET_1(int fd, int optname)
30{
31 return setsockopt_SOL_SOCKET_int(fd, optname, 1);
32}
33
17void FAST_FUNC setsockopt_reuseaddr(int fd) 34void FAST_FUNC setsockopt_reuseaddr(int fd)
18{ 35{
19 setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &const_int_1, sizeof(const_int_1)); 36 setsockopt_SOL_SOCKET_1(fd, SO_REUSEADDR);
20} 37}
21int FAST_FUNC setsockopt_broadcast(int fd) 38int FAST_FUNC setsockopt_broadcast(int fd)
22{ 39{
23 return setsockopt(fd, SOL_SOCKET, SO_BROADCAST, &const_int_1, sizeof(const_int_1)); 40 return setsockopt_SOL_SOCKET_1(fd, SO_BROADCAST);
41}
42int FAST_FUNC setsockopt_keepalive(int fd)
43{
44 return setsockopt_SOL_SOCKET_1(fd, SO_KEEPALIVE);
24} 45}
25 46
26#ifdef SO_BINDTODEVICE 47#ifdef SO_BINDTODEVICE
diff --git a/libbb/xfunc_die.c b/libbb/xfunc_die.c
index 204e5e49d..73f7998e5 100644
--- a/libbb/xfunc_die.c
+++ b/libbb/xfunc_die.c
@@ -7,34 +7,16 @@
7 * Licensed under GPLv2, see file LICENSE in this source tree. 7 * Licensed under GPLv2, see file LICENSE in this source tree.
8 */ 8 */
9 9
10/* Keeping it separate allows to NOT suck in stdio for VERY small applets. 10/* Keeping it separate allows to NOT pull in stdio for VERY small applets.
11 * Try building busybox with only "true" enabled... */ 11 * Try building busybox with only "true" enabled... */
12 12
13#include "libbb.h" 13#include "libbb.h"
14 14
15int die_sleep; 15void (*die_func)(void);
16#if ENABLE_FEATURE_PREFER_APPLETS || ENABLE_HUSH
17jmp_buf die_jmp;
18#endif
19 16
20void FAST_FUNC xfunc_die(void) 17void FAST_FUNC xfunc_die(void)
21{ 18{
22 if (die_sleep) { 19 if (die_func)
23 if ((ENABLE_FEATURE_PREFER_APPLETS || ENABLE_HUSH) 20 die_func();
24 && die_sleep < 0
25 ) {
26 /* Special case. We arrive here if NOFORK applet
27 * calls xfunc, which then decides to die.
28 * We don't die, but jump instead back to caller.
29 * NOFORK applets still cannot carelessly call xfuncs:
30 * p = xmalloc(10);
31 * q = xmalloc(10); // BUG! if this dies, we leak p!
32 */
33 /* -2222 means "zero" (longjmp can't pass 0)
34 * run_nofork_applet() catches -2222. */
35 longjmp(die_jmp, xfunc_error_retval ? xfunc_error_retval : -2222);
36 }
37 sleep(die_sleep);
38 }
39 exit(xfunc_error_retval); 21 exit(xfunc_error_retval);
40} 22}