aboutsummaryrefslogtreecommitdiff
path: root/libbb
diff options
context:
space:
mode:
authorRon Yorston <rmy@pobox.com>2017-07-18 15:58:52 +0100
committerRon Yorston <rmy@pobox.com>2017-07-18 15:58:52 +0100
commitb680f05ad449505e3d914bebd4c8d83bf768c094 (patch)
treec08ded13d430b0e7e0104f2eb594fad190ce98a3 /libbb
parent258200ff81d5a9da54dab35acf36213eff1e399b (diff)
parent513a2457b65894b10b9fd6aa8753fca59eced08c (diff)
downloadbusybox-w32-b680f05ad449505e3d914bebd4c8d83bf768c094.tar.gz
busybox-w32-b680f05ad449505e3d914bebd4c8d83bf768c094.tar.bz2
busybox-w32-b680f05ad449505e3d914bebd4c8d83bf768c094.zip
Merge branch 'busybox' into merge
Diffstat (limited to 'libbb')
-rw-r--r--libbb/Config.src13
-rw-r--r--libbb/appletlib.c47
-rw-r--r--libbb/bb_getgroups.c47
-rw-r--r--libbb/common_bufsiz.c1
-rw-r--r--libbb/copyfd.c3
-rw-r--r--libbb/dump.c53
-rw-r--r--libbb/getopt32.c4
-rw-r--r--libbb/inet_common.c46
-rw-r--r--libbb/messages.c6
-rw-r--r--libbb/print_numbered_lines.c1
-rw-r--r--libbb/safe_write.c12
-rw-r--r--libbb/vfork_daemon_rexec.c5
12 files changed, 156 insertions, 82 deletions
diff --git a/libbb/Config.src b/libbb/Config.src
index c51640305..16c79dbf0 100644
--- a/libbb/Config.src
+++ b/libbb/Config.src
@@ -3,7 +3,7 @@
3# see scripts/kbuild/config-language.txt. 3# see scripts/kbuild/config-language.txt.
4# 4#
5 5
6menu "Busybox Library Tuning" 6comment "Library Tuning"
7 7
8INSERT 8INSERT
9 9
@@ -66,7 +66,7 @@ config FEATURE_FAST_TOP
66 bool "Faster /proc scanning code (+100 bytes)" 66 bool "Faster /proc scanning code (+100 bytes)"
67 default n # all "fast or small" options default to small 67 default n # all "fast or small" options default to small
68 help 68 help
69 This option makes top (and ps) ~20% faster (or 20% less CPU hungry), 69 This option makes top and ps ~20% faster (or 20% less CPU hungry),
70 but code size is slightly bigger. 70 but code size is slightly bigger.
71 71
72config FEATURE_ETC_NETWORKS 72config FEATURE_ETC_NETWORKS
@@ -302,13 +302,17 @@ config FEATURE_VERBOSE_CP_MESSAGE
302 default n 302 default n
303 help 303 help
304 Error messages with this feature enabled: 304 Error messages with this feature enabled:
305
305 $ cp file /does_not_exist/file 306 $ cp file /does_not_exist/file
306 cp: cannot create '/does_not_exist/file': Path does not exist 307 cp: cannot create '/does_not_exist/file': Path does not exist
307 $ cp file /vmlinuz/file 308 $ cp file /vmlinuz/file
308 cp: cannot stat '/vmlinuz/file': Path has non-directory component 309 cp: cannot stat '/vmlinuz/file': Path has non-directory component
310
309 If this feature is not enabled, they will be, respectively: 311 If this feature is not enabled, they will be, respectively:
312
310 cp: cannot create '/does_not_exist/file': No such file or directory 313 cp: cannot create '/does_not_exist/file': No such file or directory
311 cp: cannot stat '/vmlinuz/file': Not a directory 314 cp: cannot stat '/vmlinuz/file': Not a directory
315
312 This will cost you ~60 bytes. 316 This will cost you ~60 bytes.
313 317
314config FEATURE_USE_SENDFILE 318config FEATURE_USE_SENDFILE
@@ -376,7 +380,4 @@ config FEATURE_HWIB
376 bool "Support infiniband HW" 380 bool "Support infiniband HW"
377 default y 381 default y
378 help 382 help
379 Support for printing infiniband addresses in 383 Support for printing infiniband addresses in network applets.
380 network applets.
381
382endmenu
diff --git a/libbb/appletlib.c b/libbb/appletlib.c
index a31a73e90..34b73afa5 100644
--- a/libbb/appletlib.c
+++ b/libbb/appletlib.c
@@ -78,6 +78,17 @@
78#endif 78#endif
79 79
80 80
81unsigned FAST_FUNC string_array_len(char **argv)
82{
83 char **start = argv;
84
85 while (*argv)
86 argv++;
87
88 return argv - start;
89}
90
91
81#if ENABLE_SHOW_USAGE && !ENABLE_FEATURE_COMPRESS_USAGE 92#if ENABLE_SHOW_USAGE && !ENABLE_FEATURE_COMPRESS_USAGE
82static const char usage_messages[] ALIGN1 = UNPACKED_USAGE; 93static const char usage_messages[] ALIGN1 = UNPACKED_USAGE;
83#else 94#else
@@ -675,8 +686,21 @@ static void check_suid(int applet_no)
675 if (geteuid()) 686 if (geteuid())
676 bb_error_msg_and_die("must be suid to work properly"); 687 bb_error_msg_and_die("must be suid to work properly");
677 } else if (APPLET_SUID(applet_no) == BB_SUID_DROP) { 688 } else if (APPLET_SUID(applet_no) == BB_SUID_DROP) {
678 xsetgid(rgid); /* drop all privileges */ 689 /*
679 xsetuid(ruid); 690 * Drop all privileges.
691 *
692 * Don't check for errors: in normal use, they are impossible,
693 * and in special cases, exiting is harmful. Example:
694 * 'unshare --user' when user's shell is also from busybox.
695 *
696 * 'unshare --user' creates a new user namespace without any
697 * uid mappings. Thus, busybox binary is setuid nobody:nogroup
698 * within the namespace, as that is the only user. However,
699 * since no uids are mapped, calls to setgid/setuid
700 * fail (even though they would do nothing).
701 */
702 setgid(rgid);
703 setuid(ruid);
680 } 704 }
681# if ENABLE_FEATURE_SUID_CONFIG 705# if ENABLE_FEATURE_SUID_CONFIG
682 ret: ; 706 ret: ;
@@ -919,16 +943,17 @@ static int busybox_main(char **argv)
919# endif 943# endif
920 944
921# if NUM_APPLETS > 0 945# if NUM_APPLETS > 0
922void FAST_FUNC run_applet_no_and_exit(int applet_no, char **argv) 946void FAST_FUNC run_applet_no_and_exit(int applet_no, const char *name, char **argv)
923{ 947{
924 int argc = 1; 948 int argc = string_array_len(argv);
925
926 while (argv[argc])
927 argc++;
928 949
929 /* Reinit some shared global data */ 950 /* Reinit some shared global data */
930 xfunc_error_retval = EXIT_FAILURE; 951 xfunc_error_retval = EXIT_FAILURE;
931 applet_name = bb_get_last_path_component_nostrip(argv[0]); 952 /*
953 * We do not use argv[0]: do not want to repeat massaging of
954 * "-/sbin/halt" -> "halt", for example.
955 */
956 applet_name = name;
932 957
933 /* Special case. POSIX says "test --help" 958 /* Special case. POSIX says "test --help"
934 * should be no different from e.g. "test --foo". 959 * should be no different from e.g. "test --foo".
@@ -972,7 +997,7 @@ static NORETURN void run_applet_and_exit(const char *name, char **argv)
972 { 997 {
973 int applet = find_applet_by_name(name); 998 int applet = find_applet_by_name(name);
974 if (applet >= 0) 999 if (applet >= 0)
975 run_applet_no_and_exit(applet, argv); 1000 run_applet_no_and_exit(applet, name, argv);
976 } 1001 }
977# endif 1002# endif
978 1003
@@ -1058,7 +1083,11 @@ int main(int argc UNUSED_PARAM, char **argv)
1058 } 1083 }
1059 /* applet_names in this case is just "applet\0\0" */ 1084 /* applet_names in this case is just "applet\0\0" */
1060 lbb_prepare(applet_names IF_FEATURE_INDIVIDUAL(, argv)); 1085 lbb_prepare(applet_names IF_FEATURE_INDIVIDUAL(, argv));
1086# if ENABLE_BUILD_LIBBUSYBOX
1087 return SINGLE_APPLET_MAIN(string_array_len(argv), argv);
1088# else
1061 return SINGLE_APPLET_MAIN(argc, argv); 1089 return SINGLE_APPLET_MAIN(argc, argv);
1090# endif
1062 1091
1063#elif !ENABLE_BUSYBOX && NUM_APPLETS == 0 1092#elif !ENABLE_BUSYBOX && NUM_APPLETS == 0
1064 1093
diff --git a/libbb/bb_getgroups.c b/libbb/bb_getgroups.c
new file mode 100644
index 000000000..59ae53738
--- /dev/null
+++ b/libbb/bb_getgroups.c
@@ -0,0 +1,47 @@
1/*
2 * Utility routines.
3 *
4 * Copyright (C) 2017 Denys Vlasenko
5 *
6 * Licensed under GPLv2, see file LICENSE in this source tree.
7 */
8
9//kbuild:lib-y += bb_getgroups.o
10
11#include "libbb.h"
12
13gid_t* FAST_FUNC bb_getgroups(int *ngroups, gid_t *group_array)
14{
15 int n = ngroups ? *ngroups : 0;
16
17 /* getgroups may be a bit expensive, try to use it only once */
18 if (n < 32)
19 n = 32;
20
21 for (;;) {
22// FIXME: ash tries so hard to not die on OOM (when we are called from test),
23// and we spoil it with just one xrealloc here
24 group_array = xrealloc(group_array, (n+1) * sizeof(group_array[0]));
25 n = getgroups(n, group_array);
26 /*
27 * If buffer is too small, kernel does not return new_n > n.
28 * It returns -1 and EINVAL:
29 */
30 if (n >= 0) {
31 /* Terminator for bb_getgroups(NULL, NULL) usage */
32 group_array[n] = (gid_t) -1;
33 break;
34 }
35 if (errno == EINVAL) { /* too small? */
36 /* This is the way to ask kernel how big the array is */
37 n = getgroups(0, group_array);
38 continue;
39 }
40 /* Some other error (should never happen on Linux) */
41 bb_perror_msg_and_die("getgroups");
42 }
43
44 if (ngroups)
45 *ngroups = n;
46 return group_array;
47}
diff --git a/libbb/common_bufsiz.c b/libbb/common_bufsiz.c
index 2847eb57d..f1124ba0e 100644
--- a/libbb/common_bufsiz.c
+++ b/libbb/common_bufsiz.c
@@ -19,6 +19,7 @@
19//config: 19//config:
20//config: At link time, "text" is padded to a full page. At runtime, all "text" 20//config: At link time, "text" is padded to a full page. At runtime, all "text"
21//config: pages are mapped RO and executable. 21//config: pages are mapped RO and executable.
22//config:
22//config: "Data" starts on the next page boundary, but is not padded 23//config: "Data" starts on the next page boundary, but is not padded
23//config: to a full page at the end. "Bss" starts wherever "data" ends. 24//config: to a full page at the end. "Bss" starts wherever "data" ends.
24//config: At runtime, "data" pages are mapped RW and they are file-backed 25//config: At runtime, "data" pages are mapped RW and they are file-backed
diff --git a/libbb/copyfd.c b/libbb/copyfd.c
index 7e3531903..921fe3f81 100644
--- a/libbb/copyfd.c
+++ b/libbb/copyfd.c
@@ -119,8 +119,11 @@ static off_t bb_full_fd_action(int src_fd, int dst_fd, off_t size)
119 } 119 }
120 out: 120 out:
121 121
122/* some environments don't have munmap(), hide it in #if */
123#if CONFIG_FEATURE_COPYBUF_KB > 4
122 if (buffer_size > 4 * 1024) 124 if (buffer_size > 4 * 1024)
123 munmap(buffer, buffer_size); 125 munmap(buffer, buffer_size);
126#endif
124 return status ? -1 : total; 127 return status ? -1 : total;
125} 128}
126 129
diff --git a/libbb/dump.c b/libbb/dump.c
index 87c1dce13..211a1ed9e 100644
--- a/libbb/dump.c
+++ b/libbb/dump.c
@@ -58,7 +58,7 @@ static NOINLINE int bb_dump_size(FS *fs)
58 const char *p; 58 const char *p;
59 int prec; 59 int prec;
60 60
61 /* figure out the data block bb_dump_size needed for each format unit */ 61 /* figure out the data block size needed for each format unit */
62 for (cur_size = 0, fu = fs->nextfu; fu; fu = fu->nextfu) { 62 for (cur_size = 0, fu = fs->nextfu; fu; fu = fu->nextfu) {
63 if (fu->bcnt) { 63 if (fu->bcnt) {
64 cur_size += fu->bcnt * fu->reps; 64 cur_size += fu->bcnt * fu->reps;
@@ -311,20 +311,18 @@ static NOINLINE void rewrite(priv_dumper_t *dumper, FS *fs)
311 } 311 }
312} 312}
313 313
314static void do_skip(priv_dumper_t *dumper, const char *fname, int statok) 314static void do_skip(priv_dumper_t *dumper, const char *fname)
315{ 315{
316 struct stat sbuf; 316 struct stat sbuf;
317 317
318 if (statok) { 318 xfstat(STDIN_FILENO, &sbuf, fname);
319 xfstat(STDIN_FILENO, &sbuf, fname); 319 if (S_ISREG(sbuf.st_mode)
320 if (!(S_ISCHR(sbuf.st_mode) || S_ISBLK(sbuf.st_mode) || S_ISFIFO(sbuf.st_mode)) 320 && dumper->pub.dump_skip >= sbuf.st_size
321 && dumper->pub.dump_skip >= sbuf.st_size 321 ) {
322 ) { 322 /* If st_size is valid and pub.dump_skip >= st_size */
323 /* If bb_dump_size valid and pub.dump_skip >= size */ 323 dumper->pub.dump_skip -= sbuf.st_size;
324 dumper->pub.dump_skip -= sbuf.st_size; 324 dumper->address += sbuf.st_size;
325 dumper->address += sbuf.st_size; 325 return;
326 return;
327 }
328 } 326 }
329 if (fseeko(stdin, dumper->pub.dump_skip, SEEK_SET)) { 327 if (fseeko(stdin, dumper->pub.dump_skip, SEEK_SET)) {
330 bb_simple_perror_msg_and_die(fname); 328 bb_simple_perror_msg_and_die(fname);
@@ -336,29 +334,26 @@ static void do_skip(priv_dumper_t *dumper, const char *fname, int statok)
336 334
337static NOINLINE int next(priv_dumper_t *dumper) 335static NOINLINE int next(priv_dumper_t *dumper)
338{ 336{
339 int statok;
340
341 for (;;) { 337 for (;;) {
342 if (*dumper->argv) { 338 const char *fname = *dumper->argv;
343 dumper->next__done = statok = 1; 339
344 if (!(freopen(*dumper->argv, "r", stdin))) { 340 if (fname) {
345 bb_simple_perror_msg(*dumper->argv); 341 dumper->argv++;
346 dumper->exitval = 1; 342 if (NOT_LONE_DASH(fname)) {
347 ++dumper->argv; 343 if (!freopen(fname, "r", stdin)) {
348 continue; 344 bb_simple_perror_msg(fname);
345 dumper->exitval = 1;
346 continue;
347 }
349 } 348 }
350 } else { 349 } else {
351 if (dumper->next__done) 350 if (dumper->next__done)
352 return 0; /* no next file */ 351 return 0; /* no next file */
353 dumper->next__done = 1;
354//why stat of stdin is specially prohibited?
355 statok = 0;
356 } 352 }
353 dumper->next__done = 1;
357 if (dumper->pub.dump_skip) 354 if (dumper->pub.dump_skip)
358 do_skip(dumper, statok ? *dumper->argv : "stdin", statok); 355 do_skip(dumper, fname ? fname : "stdin");
359 if (*dumper->argv) 356 if (dumper->pub.dump_skip == 0)
360 ++dumper->argv;
361 if (!dumper->pub.dump_skip)
362 return 1; 357 return 1;
363 } 358 }
364 /* NOTREACHED */ 359 /* NOTREACHED */
@@ -670,7 +665,7 @@ int FAST_FUNC bb_dump_dump(dumper_t *pub_dumper, char **argv)
670 FS *tfs; 665 FS *tfs;
671 int blocksize; 666 int blocksize;
672 667
673 /* figure out the data block bb_dump_size */ 668 /* figure out the data block size */
674 blocksize = 0; 669 blocksize = 0;
675 tfs = dumper->pub.fshead; 670 tfs = dumper->pub.fshead;
676 while (tfs) { 671 while (tfs) {
diff --git a/libbb/getopt32.c b/libbb/getopt32.c
index b87b83538..80f4cc060 100644
--- a/libbb/getopt32.c
+++ b/libbb/getopt32.c
@@ -379,9 +379,7 @@ getopt32(char **argv, const char *applet_opts, ...)
379 int spec_flgs = 0; 379 int spec_flgs = 0;
380 380
381 /* skip 0: some applets cheat: they do not actually HAVE argv[0] */ 381 /* skip 0: some applets cheat: they do not actually HAVE argv[0] */
382 argc = 1; 382 argc = 1 + string_array_len(argv + 1);
383 while (argv[argc])
384 argc++;
385 383
386 va_start(p, applet_opts); 384 va_start(p, applet_opts);
387 385
diff --git a/libbb/inet_common.c b/libbb/inet_common.c
index 5b4a4a10b..04259f47b 100644
--- a/libbb/inet_common.c
+++ b/libbb/inet_common.c
@@ -11,6 +11,12 @@
11#include "libbb.h" 11#include "libbb.h"
12#include "inet_common.h" 12#include "inet_common.h"
13 13
14#if 0
15# define dbg(...) bb_error_msg(__VA_ARGS__)
16#else
17# define dbg(...) ((void)0)
18#endif
19
14int FAST_FUNC INET_resolve(const char *name, struct sockaddr_in *s_in, int hostfirst) 20int FAST_FUNC INET_resolve(const char *name, struct sockaddr_in *s_in, int hostfirst)
15{ 21{
16 struct hostent *hp; 22 struct hostent *hp;
@@ -33,9 +39,7 @@ int FAST_FUNC INET_resolve(const char *name, struct sockaddr_in *s_in, int hostf
33 } 39 }
34 /* If we expect this to be a hostname, try hostname database first */ 40 /* If we expect this to be a hostname, try hostname database first */
35 if (hostfirst) { 41 if (hostfirst) {
36#ifdef DEBUG 42 dbg("gethostbyname(%s)", name);
37 bb_error_msg("gethostbyname(%s)", name);
38#endif
39 hp = gethostbyname(name); 43 hp = gethostbyname(name);
40 if (hp) { 44 if (hp) {
41 memcpy(&s_in->sin_addr, hp->h_addr_list[0], 45 memcpy(&s_in->sin_addr, hp->h_addr_list[0],
@@ -45,9 +49,7 @@ int FAST_FUNC INET_resolve(const char *name, struct sockaddr_in *s_in, int hostf
45 } 49 }
46#if ENABLE_FEATURE_ETC_NETWORKS 50#if ENABLE_FEATURE_ETC_NETWORKS
47 /* Try the NETWORKS database to see if this is a known network. */ 51 /* Try the NETWORKS database to see if this is a known network. */
48#ifdef DEBUG 52 dbg("getnetbyname(%s)", name);
49 bb_error_msg("getnetbyname(%s)", name);
50#endif
51 np = getnetbyname(name); 53 np = getnetbyname(name);
52 if (np) { 54 if (np) {
53 s_in->sin_addr.s_addr = htonl(np->n_net); 55 s_in->sin_addr.s_addr = htonl(np->n_net);
@@ -61,8 +63,8 @@ int FAST_FUNC INET_resolve(const char *name, struct sockaddr_in *s_in, int hostf
61#ifdef DEBUG 63#ifdef DEBUG
62 res_init(); 64 res_init();
63 _res.options |= RES_DEBUG; 65 _res.options |= RES_DEBUG;
64 bb_error_msg("gethostbyname(%s)", name);
65#endif 66#endif
67 dbg("gethostbyname(%s)", name);
66 hp = gethostbyname(name); 68 hp = gethostbyname(name);
67 if (!hp) { 69 if (!hp) {
68 return -1; 70 return -1;
@@ -93,17 +95,12 @@ char* FAST_FUNC INET_rresolve(struct sockaddr_in *s_in, int numeric, uint32_t ne
93 smallint is_host; 95 smallint is_host;
94 96
95 if (s_in->sin_family != AF_INET) { 97 if (s_in->sin_family != AF_INET) {
96#ifdef DEBUG 98 dbg("rresolve: unsupported address family %d!", s_in->sin_family);
97 bb_error_msg("rresolve: unsupported address family %d!",
98 s_in->sin_family);
99#endif
100 errno = EAFNOSUPPORT; 99 errno = EAFNOSUPPORT;
101 return NULL; 100 return NULL;
102 } 101 }
103 nip = s_in->sin_addr.s_addr; 102 nip = s_in->sin_addr.s_addr;
104#ifdef DEBUG 103 dbg("rresolve: %08x mask:%08x num:%08x", (unsigned)nip, netmask, numeric);
105 bb_error_msg("rresolve: %08x mask:%08x num:%08x", (unsigned)nip, netmask, numeric);
106#endif
107 if (numeric & 0x0FFF) 104 if (numeric & 0x0FFF)
108 return xmalloc_sockaddr2dotted_noport((void*)s_in); 105 return xmalloc_sockaddr2dotted_noport((void*)s_in);
109 if (nip == INADDR_ANY) { 106 if (nip == INADDR_ANY) {
@@ -117,10 +114,8 @@ char* FAST_FUNC INET_rresolve(struct sockaddr_in *s_in, int numeric, uint32_t ne
117 pn = cache; 114 pn = cache;
118 while (pn) { 115 while (pn) {
119 if (pn->nip == nip && pn->is_host == is_host) { 116 if (pn->nip == nip && pn->is_host == is_host) {
120#ifdef DEBUG 117 dbg("rresolve: found %s %08x in cache",
121 bb_error_msg("rresolve: found %s %08x in cache",
122 (is_host ? "host" : "net"), (unsigned)nip); 118 (is_host ? "host" : "net"), (unsigned)nip);
123#endif
124 return xstrdup(pn->name); 119 return xstrdup(pn->name);
125 } 120 }
126 pn = pn->next; 121 pn = pn->next;
@@ -128,19 +123,18 @@ char* FAST_FUNC INET_rresolve(struct sockaddr_in *s_in, int numeric, uint32_t ne
128 123
129 name = NULL; 124 name = NULL;
130 if (is_host) { 125 if (is_host) {
131#ifdef DEBUG 126 dbg("sockaddr2host_noport(%08x)", (unsigned)nip);
132 bb_error_msg("sockaddr2host_noport(%08x)", (unsigned)nip);
133#endif
134 name = xmalloc_sockaddr2host_noport((void*)s_in); 127 name = xmalloc_sockaddr2host_noport((void*)s_in);
135 } else if (ENABLE_FEATURE_ETC_NETWORKS) { 128 }
129#if ENABLE_FEATURE_ETC_NETWORKS
130 else {
136 struct netent *np; 131 struct netent *np;
137#ifdef DEBUG 132 dbg("getnetbyaddr(%08x)", (unsigned)ntohl(nip));
138 bb_error_msg("getnetbyaddr(%08x)", (unsigned)ntohl(nip));
139#endif
140 np = getnetbyaddr(ntohl(nip), AF_INET); 133 np = getnetbyaddr(ntohl(nip), AF_INET);
141 if (np) 134 if (np)
142 name = xstrdup(np->n_name); 135 name = xstrdup(np->n_name);
143 } 136 }
137#endif
144 if (!name) 138 if (!name)
145 name = xmalloc_sockaddr2dotted_noport((void*)s_in); 139 name = xmalloc_sockaddr2dotted_noport((void*)s_in);
146 140
@@ -183,10 +177,8 @@ int FAST_FUNC INET6_resolve(const char *name, struct sockaddr_in6 *sin6)
183char* FAST_FUNC INET6_rresolve(struct sockaddr_in6 *sin6, int numeric) 177char* FAST_FUNC INET6_rresolve(struct sockaddr_in6 *sin6, int numeric)
184{ 178{
185 if (sin6->sin6_family != AF_INET6) { 179 if (sin6->sin6_family != AF_INET6) {
186#ifdef DEBUG 180 dbg("rresolve: unsupported address family %d!",
187 bb_error_msg("rresolve: unsupported address family %d!",
188 sin6->sin6_family); 181 sin6->sin6_family);
189#endif
190 errno = EAFNOSUPPORT; 182 errno = EAFNOSUPPORT;
191 return NULL; 183 return NULL;
192 } 184 }
diff --git a/libbb/messages.c b/libbb/messages.c
index d74c237e7..3c0b921cf 100644
--- a/libbb/messages.c
+++ b/libbb/messages.c
@@ -14,12 +14,10 @@
14 14
15/* allow version to be extended, via CFLAGS */ 15/* allow version to be extended, via CFLAGS */
16#ifndef BB_EXTRA_VERSION 16#ifndef BB_EXTRA_VERSION
17#define BB_EXTRA_VERSION BB_BT 17#define BB_EXTRA_VERSION " ("AUTOCONF_TIMESTAMP")"
18#endif 18#endif
19 19
20#define BANNER "BusyBox v" BB_VER " (" BB_EXTRA_VERSION ")" 20const char bb_banner[] ALIGN1 = "BusyBox v" BB_VER BB_EXTRA_VERSION;
21
22const char bb_banner[] ALIGN1 = BANNER;
23 21
24 22
25const char bb_msg_memory_exhausted[] ALIGN1 = "out of memory"; 23const char bb_msg_memory_exhausted[] ALIGN1 = "out of memory";
diff --git a/libbb/print_numbered_lines.c b/libbb/print_numbered_lines.c
index 702aed1ea..9a8a51440 100644
--- a/libbb/print_numbered_lines.c
+++ b/libbb/print_numbered_lines.c
@@ -24,6 +24,7 @@ void FAST_FUNC print_numbered_lines(struct number_state *ns, const char *filenam
24 fputs(ns->empty_str, stdout); 24 fputs(ns->empty_str, stdout);
25 free(line); 25 free(line);
26 } 26 }
27 ns->start = N;
27 28
28 fclose(fp); 29 fclose(fp);
29} 30}
diff --git a/libbb/safe_write.c b/libbb/safe_write.c
index 8f7628016..aad50f5e0 100644
--- a/libbb/safe_write.c
+++ b/libbb/safe_write.c
@@ -13,9 +13,17 @@ ssize_t FAST_FUNC safe_write(int fd, const void *buf, size_t count)
13{ 13{
14 ssize_t n; 14 ssize_t n;
15 15
16 do { 16 for (;;) {
17 n = write(fd, buf, count); 17 n = write(fd, buf, count);
18 } while (n < 0 && errno == EINTR); 18 if (n >= 0 || errno != EINTR)
19 break;
20 /* Some callers set errno=0, are upset when they see EINTR.
21 * Returning EINTR is wrong since we retry write(),
22 * the "error" was transient.
23 */
24 errno = 0;
25 /* repeat the write() */
26 }
19 27
20 return n; 28 return n;
21} 29}
diff --git a/libbb/vfork_daemon_rexec.c b/libbb/vfork_daemon_rexec.c
index 9ab49d0a1..4b3ed5a3b 100644
--- a/libbb/vfork_daemon_rexec.c
+++ b/libbb/vfork_daemon_rexec.c
@@ -16,6 +16,7 @@
16 */ 16 */
17 17
18#include "busybox.h" /* uses applet tables */ 18#include "busybox.h" /* uses applet tables */
19#include "NUM_APPLETS.h"
19 20
20#if !ENABLE_PLATFORM_MINGW32 21#if !ENABLE_PLATFORM_MINGW32
21/* This does a fork/exec in one call, using vfork(). Returns PID of new child, 22/* This does a fork/exec in one call, using vfork(). Returns PID of new child,
@@ -158,7 +159,7 @@ int FAST_FUNC run_nofork_applet(int applet_no, char **argv)
158int FAST_FUNC spawn_and_wait(char **argv) 159int FAST_FUNC spawn_and_wait(char **argv)
159{ 160{
160 int rc; 161 int rc;
161#if ENABLE_FEATURE_PREFER_APPLETS 162#if ENABLE_FEATURE_PREFER_APPLETS && (NUM_APPLETS > 1)
162 int a = find_applet_by_name(argv[0]); 163 int a = find_applet_by_name(argv[0]);
163 164
164 if (a >= 0) { 165 if (a >= 0) {
@@ -182,7 +183,7 @@ int FAST_FUNC spawn_and_wait(char **argv)
182 * as of yet (and that should probably always stay true). 183 * as of yet (and that should probably always stay true).
183 */ 184 */
184 /* xfunc_error_retval and applet_name are init by: */ 185 /* xfunc_error_retval and applet_name are init by: */
185 run_applet_no_and_exit(a, argv); 186 run_applet_no_and_exit(a, argv[0], argv);
186 } 187 }
187# endif 188# endif
188# endif 189# endif