aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDenis Vlasenko <vda.linux@googlemail.com>2007-04-10 21:38:30 +0000
committerDenis Vlasenko <vda.linux@googlemail.com>2007-04-10 21:38:30 +0000
commit335b63d8d1876ce4e172ebcc9d64544785682244 (patch)
tree14183fd728ce51ae10baee70f7d8f72c39d30649
parent07c394e69b0cfa7cd30e97ffc6edb0d857905f45 (diff)
downloadbusybox-w32-335b63d8d1876ce4e172ebcc9d64544785682244.tar.gz
busybox-w32-335b63d8d1876ce4e172ebcc9d64544785682244.tar.bz2
busybox-w32-335b63d8d1876ce4e172ebcc9d64544785682244.zip
make a few struct bb_applet members conditional
rename sllep_and_die -> xfunc_die make fflush_stdout_and_exit NOFORK-safe fix some buglets found by randomconfig
-rw-r--r--applets/applets.c53
-rw-r--r--archival/libunarchive/Kbuild5
-rw-r--r--coreutils/cmp.c4
-rw-r--r--coreutils/echo.c2
-rw-r--r--include/applets.h14
-rw-r--r--include/busybox.h26
-rw-r--r--include/libbb.h10
-rw-r--r--libbb/copyfd.c4
-rw-r--r--libbb/error_msg_and_die.c21
-rw-r--r--libbb/fflush_stdout_and_exit.c14
-rw-r--r--libbb/herror_msg_and_die.c5
-rw-r--r--libbb/perror_msg_and_die.c6
-rw-r--r--libbb/vfork_daemon_rexec.c23
-rw-r--r--libbb/xconnect.c2
-rw-r--r--libbb/xfuncs.c2
-rw-r--r--shell/ash.c2
-rw-r--r--shell/msh.c2
-rw-r--r--util-linux/getopt.c2
18 files changed, 114 insertions, 83 deletions
diff --git a/applets/applets.c b/applets/applets.c
index 66f2b821d..3441a7886 100644
--- a/applets/applets.c
+++ b/applets/applets.c
@@ -43,13 +43,13 @@ static const char usage_messages[] =
43#define usage_messages 0 43#define usage_messages 0
44#endif /* SHOW_USAGE */ 44#endif /* SHOW_USAGE */
45 45
46/* Define struct BB_applet applets[] */ 46/* Define struct bb_applet applets[] */
47#include "applets.h" 47#include "applets.h"
48/* The -1 arises because of the {0,NULL,0,-1} entry. */ 48/* The -1 arises because of the {0,NULL,0,-1} entry. */
49const unsigned short NUM_APPLETS = sizeof(applets) / sizeof(struct BB_applet) - 1; 49const unsigned short NUM_APPLETS = sizeof(applets) / sizeof(applets[0]) - 1;
50 50
51 51
52const struct BB_applet *current_applet; 52const struct bb_applet *current_applet;
53const char *applet_name ATTRIBUTE_EXTERNALLY_VISIBLE; 53const char *applet_name ATTRIBUTE_EXTERNALLY_VISIBLE;
54#ifdef BB_NOMMU 54#ifdef BB_NOMMU
55bool re_execed; 55bool re_execed;
@@ -61,7 +61,7 @@ bool re_execed;
61 61
62/* applets[] is const, so we have to define this "override" structure */ 62/* applets[] is const, so we have to define this "override" structure */
63static struct BB_suid_config { 63static struct BB_suid_config {
64 const struct BB_applet *m_applet; 64 const struct bb_applet *m_applet;
65 uid_t m_uid; 65 uid_t m_uid;
66 gid_t m_gid; 66 gid_t m_gid;
67 mode_t m_mode; 67 mode_t m_mode;
@@ -130,7 +130,7 @@ static void parse_config_file(void)
130{ 130{
131 struct BB_suid_config *sct_head; 131 struct BB_suid_config *sct_head;
132 struct BB_suid_config *sct; 132 struct BB_suid_config *sct;
133 const struct BB_applet *applet; 133 const struct bb_applet *applet;
134 FILE *f; 134 FILE *f;
135 const char *errmsg; 135 const char *errmsg;
136 char *s; 136 char *s;
@@ -329,7 +329,7 @@ static void parse_config_file(void)
329 329
330 330
331#if ENABLE_FEATURE_SUID 331#if ENABLE_FEATURE_SUID
332static void check_suid(const struct BB_applet *applet) 332static void check_suid(const struct bb_applet *applet)
333{ 333{
334 uid_t ruid = getuid(); /* real [ug]id */ 334 uid_t ruid = getuid(); /* real [ug]id */
335 uid_t rgid = getgid(); 335 uid_t rgid = getgid();
@@ -464,45 +464,42 @@ void bb_show_usage(void)
464 applet_name, usage_string); 464 applet_name, usage_string);
465 } 465 }
466 466
467 sleep_and_die(); 467 xfunc_die();
468} 468}
469 469
470 470
471static int applet_name_compare(const void *name, const void *vapplet) 471static int applet_name_compare(const void *name, const void *vapplet)
472{ 472{
473 const struct BB_applet *applet = vapplet; 473 const struct bb_applet *applet = vapplet;
474 474
475 return strcmp(name, applet->name); 475 return strcmp(name, applet->name);
476} 476}
477 477
478const struct BB_applet *find_applet_by_name(const char *name) 478const struct bb_applet *find_applet_by_name(const char *name)
479{ 479{
480 /* Do a binary search to find the applet entry given the name. */ 480 /* Do a binary search to find the applet entry given the name. */
481 return bsearch(name, applets, NUM_APPLETS, sizeof(struct BB_applet), 481 return bsearch(name, applets, NUM_APPLETS, sizeof(applets[0]),
482 applet_name_compare); 482 applet_name_compare);
483} 483}
484 484
485 485
486#if ENABLE_FEATURE_INSTALLER 486#if ENABLE_FEATURE_INSTALLER
487/*
488 * directory table
489 * this should be consistent w/ the enum, busybox.h::Location,
490 * or else...
491 */
492static const char usr_bin [] = "/usr/bin";
493static const char usr_sbin[] = "/usr/sbin";
494
495static const char *const install_dir[] = {
496 &usr_bin [8], /* "", equivalent to "/" for concat_path_file() */
497 &usr_bin [4], /* "/bin" */
498 &usr_sbin[4], /* "/sbin" */
499 usr_bin,
500 usr_sbin
501};
502
503/* create (sym)links for each applet */ 487/* create (sym)links for each applet */
504static void install_links(const char *busybox, int use_symbolic_links) 488static void install_links(const char *busybox, int use_symbolic_links)
505{ 489{
490 /* directory table
491 * this should be consistent w/ the enum,
492 * busybox.h::bb_install_loc_t, or else... */
493 static const char usr_bin [] = "/usr/bin";
494 static const char usr_sbin[] = "/usr/sbin";
495 static const char *const install_dir[] = {
496 &usr_bin [8], /* "", equivalent to "/" for concat_path_file() */
497 &usr_bin [4], /* "/bin" */
498 &usr_sbin[4], /* "/sbin" */
499 usr_bin,
500 usr_sbin
501 };
502
506 int (*lf)(const char *, const char *) = link; 503 int (*lf)(const char *, const char *) = link;
507 char *fpc; 504 char *fpc;
508 int i; 505 int i;
@@ -513,7 +510,7 @@ static void install_links(const char *busybox, int use_symbolic_links)
513 510
514 for (i = 0; applets[i].name != NULL; i++) { 511 for (i = 0; applets[i].name != NULL; i++) {
515 fpc = concat_path_file( 512 fpc = concat_path_file(
516 install_dir[applets[i].location], 513 install_dir[applets[i].install_loc],
517 applets[i].name); 514 applets[i].name);
518 rc = lf(busybox, fpc); 515 rc = lf(busybox, fpc);
519 if (rc != 0 && errno != EEXIST) { 516 if (rc != 0 && errno != EEXIST) {
@@ -557,7 +554,7 @@ static int busybox_main(int argc, char **argv)
557 applet_name = argv[2]; 554 applet_name = argv[2];
558 run_applet_by_name(applet_name, 2, argv); 555 run_applet_by_name(applet_name, 2, argv);
559 } else { 556 } else {
560 const struct BB_applet *a; 557 const struct bb_applet *a;
561 int col, output_width; 558 int col, output_width;
562 559
563 output_width = 80 - sizeof("start-stop-daemon, ") - 8; 560 output_width = 80 - sizeof("start-stop-daemon, ") - 8;
diff --git a/archival/libunarchive/Kbuild b/archival/libunarchive/Kbuild
index 010043c4c..412a2332d 100644
--- a/archival/libunarchive/Kbuild
+++ b/archival/libunarchive/Kbuild
@@ -35,12 +35,15 @@ DPKG_FILES:= \
35 get_header_tar.o \ 35 get_header_tar.o \
36 filter_accept_list_reassign.o 36 filter_accept_list_reassign.o
37 37
38# open_transformer uses fork. Compile it only if absolutely necessary 38# open_transformer uses fork(). Compile it only if absolutely necessary
39lib-$(CONFIG_RPM) += open_transformer.o 39lib-$(CONFIG_RPM) += open_transformer.o
40lib-$(CONFIG_FEATURE_TAR_BZIP2) += open_transformer.o 40lib-$(CONFIG_FEATURE_TAR_BZIP2) += open_transformer.o
41lib-$(CONFIG_FEATURE_TAR_LZMA) += open_transformer.o 41lib-$(CONFIG_FEATURE_TAR_LZMA) += open_transformer.o
42lib-$(CONFIG_FEATURE_TAR_GZIP) += open_transformer.o 42lib-$(CONFIG_FEATURE_TAR_GZIP) += open_transformer.o
43lib-$(CONFIG_FEATURE_TAR_COMPRESS) += open_transformer.o 43lib-$(CONFIG_FEATURE_TAR_COMPRESS) += open_transformer.o
44lib-$(CONFIG_FEATURE_DEB_TAR_GZ) += open_transformer.o
45lib-$(CONFIG_FEATURE_DEB_TAR_BZ2) += open_transformer.o
46lib-$(CONFIG_FEATURE_DEB_TAR_LZMA) += open_transformer.o
44 47
45lib-$(CONFIG_AR) += get_header_ar.o unpack_ar_archive.o 48lib-$(CONFIG_AR) += get_header_ar.o unpack_ar_archive.o
46lib-$(CONFIG_BUNZIP2) += decompress_bunzip2.o 49lib-$(CONFIG_BUNZIP2) += decompress_bunzip2.o
diff --git a/coreutils/cmp.c b/coreutils/cmp.c
index c70f8822d..80fab0b90 100644
--- a/coreutils/cmp.c
+++ b/coreutils/cmp.c
@@ -23,14 +23,14 @@
23 23
24#include "busybox.h" 24#include "busybox.h"
25 25
26static FILE *cmp_xfopen_input(const char * const filename) 26static FILE *cmp_xfopen_input(const char *filename)
27{ 27{
28 FILE *fp; 28 FILE *fp;
29 29
30 fp = fopen_or_warn_stdin(filename); 30 fp = fopen_or_warn_stdin(filename);
31 if (fp) 31 if (fp)
32 return fp; 32 return fp;
33 sleep_and_die(); /* We already output an error message. */ 33 xfunc_die(); /* We already output an error message. */
34} 34}
35 35
36static const char fmt_eof[] = "cmp: EOF on %s\n"; 36static const char fmt_eof[] = "cmp: EOF on %s\n";
diff --git a/coreutils/echo.c b/coreutils/echo.c
index 2ee5002ba..2de19c2e3 100644
--- a/coreutils/echo.c
+++ b/coreutils/echo.c
@@ -107,7 +107,9 @@ int bb_echo(char **argv)
107 putchar(' '); 107 putchar(' ');
108 } 108 }
109 109
110#if ENABLE_FEATURE_FANCY_ECHO
110 newline_ret: 111 newline_ret:
112#endif
111 if (nflag) { 113 if (nflag) {
112 putchar('\n'); 114 putchar('\n');
113 } 115 }
diff --git a/include/applets.h b/include/applets.h
index b59d33183..d05299b69 100644
--- a/include/applets.h
+++ b/include/applets.h
@@ -52,12 +52,12 @@ s - suid type:
52# define APPLET_NOFORK(name,main,l,s,name2) LINK l name 52# define APPLET_NOFORK(name,main,l,s,name2) LINK l name
53 53
54#else 54#else
55 const struct BB_applet applets[] = { /* name,main,location,need_suid */ 55 const struct bb_applet applets[] = { /* name, main, location, need_suid */
56# define APPLET(name,l,s) {#name,name##_main,l,s}, 56# define APPLET(name,l,s) { #name, name##_main USE_FEATURE_INSTALLER(,l) USE_FEATURE_SUID(,s) },
57# define APPLET_NOUSAGE(name,main,l,s) {#name,main##_main,l,s}, 57# define APPLET_NOUSAGE(name,main,l,s) { #name, main##_main USE_FEATURE_INSTALLER(,l) USE_FEATURE_SUID(,s) },
58# define APPLET_ODDNAME(name,main,l,s,name2) {#name,main##_main,l,s}, 58# define APPLET_ODDNAME(name,main,l,s,name2) { #name, main##_main USE_FEATURE_INSTALLER(,l) USE_FEATURE_SUID(,s) },
59# define APPLET_NOEXEC(name,main,l,s,name2) {#name,main##_main,l,s,1}, 59# define APPLET_NOEXEC(name,main,l,s,name2) { #name, main##_main USE_FEATURE_INSTALLER(,l) USE_FEATURE_SUID(,s) USE_FEATURE_EXEC_PREFER_APPLETS(,1) },
60# define APPLET_NOFORK(name,main,l,s,name2) {#name,main##_main,l,s,1,1}, 60# define APPLET_NOFORK(name,main,l,s,name2) { #name, main##_main USE_FEATURE_INSTALLER(,l) USE_FEATURE_SUID(,s) USE_FEATURE_EXEC_PREFER_APPLETS(,1 ,1) },
61#endif 61#endif
62 62
63#if ENABLE_INSTALL_NO_USR 63#if ENABLE_INSTALL_NO_USR
@@ -355,7 +355,7 @@ USE_GUNZIP(APPLET_ODDNAME(zcat, gunzip, _BB_DIR_BIN, _BB_SUID_NEVER, zcat))
355USE_ZCIP(APPLET(zcip, _BB_DIR_SBIN, _BB_SUID_NEVER)) 355USE_ZCIP(APPLET(zcip, _BB_DIR_SBIN, _BB_SUID_NEVER))
356 356
357#if !defined(PROTOTYPES) && !defined(MAKE_USAGE) 357#if !defined(PROTOTYPES) && !defined(MAKE_USAGE)
358 { 0, NULL, 0, 0 } 358 { NULL }
359}; 359};
360#endif 360#endif
361 361
diff --git a/include/busybox.h b/include/busybox.h
index 6f4808778..380de9ab8 100644
--- a/include/busybox.h
+++ b/include/busybox.h
@@ -9,26 +9,35 @@
9 9
10#include "libbb.h" 10#include "libbb.h"
11 11
12#if ENABLE_FEATURE_INSTALLER
12/* order matters: used as index into "install_dir[]" in busybox.c */ 13/* order matters: used as index into "install_dir[]" in busybox.c */
13enum Location { 14typedef enum bb_install_loc_t {
14 _BB_DIR_ROOT = 0, 15 _BB_DIR_ROOT = 0,
15 _BB_DIR_BIN, 16 _BB_DIR_BIN,
16 _BB_DIR_SBIN, 17 _BB_DIR_SBIN,
17 _BB_DIR_USR_BIN, 18 _BB_DIR_USR_BIN,
18 _BB_DIR_USR_SBIN 19 _BB_DIR_USR_SBIN
19}; 20} bb_install_loc_t;
21#endif
20 22
21enum SUIDRoot { 23#if ENABLE_FEATURE_SUID
24typedef enum bb_suid_t {
22 _BB_SUID_NEVER = 0, 25 _BB_SUID_NEVER = 0,
23 _BB_SUID_MAYBE, 26 _BB_SUID_MAYBE,
24 _BB_SUID_ALWAYS 27 _BB_SUID_ALWAYS
25}; 28} bb_suid_t;
29#endif
26 30
27struct BB_applet { 31struct bb_applet {
28 const char *name; 32 const char *name;
29 int (*main) (int argc, char **argv); 33 int (*main) (int argc, char **argv);
30 __extension__ enum Location location:8; 34#if ENABLE_FEATURE_INSTALLER
31 __extension__ enum SUIDRoot need_suid:8; 35 __extension__ enum bb_install_loc_t install_loc:8;
36#endif
37#if ENABLE_FEATURE_SUID
38 __extension__ enum bb_suid_t need_suid:8;
39#endif
40#if ENABLE_FEATURE_EXEC_PREFER_APPLETS
32 /* true if instead if fork(); exec("applet"); waitpid(); 41 /* true if instead if fork(); exec("applet"); waitpid();
33 * one can do fork(); exit(applet_main(argc,argv)); waitpid(); */ 42 * one can do fork(); exit(applet_main(argc,argv)); waitpid(); */
34 unsigned char noexec; 43 unsigned char noexec;
@@ -36,10 +45,11 @@ struct BB_applet {
36 /* true if instead if fork(); exec("applet"); waitpid(); 45 /* true if instead if fork(); exec("applet"); waitpid();
37 * one can simply call applet_main(argc,argv); */ 46 * one can simply call applet_main(argc,argv); */
38 unsigned char nofork; 47 unsigned char nofork;
48#endif
39}; 49};
40 50
41/* Defined in applet.c */ 51/* Defined in applet.c */
42extern const struct BB_applet applets[]; 52extern const struct bb_applet applets[];
43extern const unsigned short NUM_APPLETS; 53extern const unsigned short NUM_APPLETS;
44 54
45#endif /* _BB_INTERNAL_H_ */ 55#endif /* _BB_INTERNAL_H_ */
diff --git a/include/libbb.h b/include/libbb.h
index 3919524bc..6fff441c5 100644
--- a/include/libbb.h
+++ b/include/libbb.h
@@ -608,7 +608,7 @@ llist_t *llist_rev(llist_t *list);
608int write_pidfile(const char *path); 608int write_pidfile(const char *path);
609#define remove_pidfile(f) ((void)unlink(f)) 609#define remove_pidfile(f) ((void)unlink(f))
610#else 610#else
611#define write_pidfile(f) 1 611#define write_pidfile(f) TRUE
612#define remove_pidfile(f) ((void)0) 612#define remove_pidfile(f) ((void)0)
613#endif 613#endif
614 614
@@ -623,7 +623,7 @@ extern smallint logmode;
623extern int die_sleep; 623extern int die_sleep;
624extern int xfunc_error_retval; 624extern int xfunc_error_retval;
625extern jmp_buf die_jmp; 625extern jmp_buf die_jmp;
626extern void sleep_and_die(void) ATTRIBUTE_NORETURN; 626extern void xfunc_die(void) ATTRIBUTE_NORETURN;
627extern void bb_show_usage(void) ATTRIBUTE_NORETURN ATTRIBUTE_EXTERNALLY_VISIBLE; 627extern void bb_show_usage(void) ATTRIBUTE_NORETURN ATTRIBUTE_EXTERNALLY_VISIBLE;
628extern void bb_error_msg(const char *s, ...) __attribute__ ((format (printf, 1, 2))); 628extern void bb_error_msg(const char *s, ...) __attribute__ ((format (printf, 1, 2)));
629extern void bb_error_msg_and_die(const char *s, ...) __attribute__ ((noreturn, format (printf, 1, 2))); 629extern void bb_error_msg_and_die(const char *s, ...) __attribute__ ((noreturn, format (printf, 1, 2)));
@@ -670,8 +670,8 @@ const struct hwtype *get_hwntype(int type);
670 670
671 671
672#ifndef BUILD_INDIVIDUAL 672#ifndef BUILD_INDIVIDUAL
673struct BB_applet; 673struct bb_applet;
674extern const struct BB_applet *find_applet_by_name(const char *name); 674extern const struct bb_applet *find_applet_by_name(const char *name);
675/* Returns only if applet is not found. */ 675/* Returns only if applet is not found. */
676extern void run_applet_by_name(const char *name, int argc, char **argv); 676extern void run_applet_by_name(const char *name, int argc, char **argv);
677extern void run_current_applet_and_exit(int argc, char **argv) ATTRIBUTE_NORETURN; 677extern void run_current_applet_and_exit(int argc, char **argv) ATTRIBUTE_NORETURN;
@@ -880,7 +880,7 @@ enum { /* DO NOT CHANGE THESE VALUES! cp.c, mv.c, install.c depend on them. */
880}; 880};
881 881
882#define FILEUTILS_CP_OPTSTR "pdRfils" USE_SELINUX("c") 882#define FILEUTILS_CP_OPTSTR "pdRfils" USE_SELINUX("c")
883extern const struct BB_applet *current_applet; 883extern const struct bb_applet *current_applet;
884extern const char *applet_name; 884extern const char *applet_name;
885extern const char BB_BANNER[]; 885extern const char BB_BANNER[];
886 886
diff --git a/libbb/copyfd.c b/libbb/copyfd.c
index e0596d5f6..aa8fbb967 100644
--- a/libbb/copyfd.c
+++ b/libbb/copyfd.c
@@ -74,7 +74,7 @@ void complain_copyfd_and_die(off_t sz)
74 if (sz != -1) 74 if (sz != -1)
75 bb_error_msg_and_die("short read"); 75 bb_error_msg_and_die("short read");
76 /* if sz == -1, bb_copyfd_XX already complained */ 76 /* if sz == -1, bb_copyfd_XX already complained */
77 sleep_and_die(); 77 xfunc_die();
78} 78}
79#endif 79#endif
80 80
@@ -94,7 +94,7 @@ void bb_copyfd_exact_size(int fd1, int fd2, off_t size)
94 if (sz != -1) 94 if (sz != -1)
95 bb_error_msg_and_die("short read"); 95 bb_error_msg_and_die("short read");
96 /* if sz == -1, bb_copyfd_XX already complained */ 96 /* if sz == -1, bb_copyfd_XX already complained */
97 sleep_and_die(); 97 xfunc_die();
98} 98}
99 99
100off_t bb_copyfd_eof(int fd1, int fd2) 100off_t bb_copyfd_eof(int fd1, int fd2)
diff --git a/libbb/error_msg_and_die.c b/libbb/error_msg_and_die.c
index 39178a3ce..4a9049364 100644
--- a/libbb/error_msg_and_die.c
+++ b/libbb/error_msg_and_die.c
@@ -10,14 +10,25 @@
10#include "libbb.h" 10#include "libbb.h"
11 11
12int die_sleep; 12int die_sleep;
13#if ENABLE_FEATURE_EXEC_PREFER_APPLETS
13jmp_buf die_jmp; 14jmp_buf die_jmp;
15#endif
14 16
15void sleep_and_die(void) 17void xfunc_die(void)
16{ 18{
17 if (die_sleep) { 19 if (die_sleep) {
18 /* Special case: don't die, but jump */ 20 if (ENABLE_FEATURE_EXEC_PREFER_APPLETS && die_sleep < 0) {
19 if (die_sleep < 0) 21 /* Special case. We arrive here if NOFORK applet
20 longjmp(die_jmp, xfunc_error_retval); 22 * calls xfunc, which then decides to die.
23 * We don't die, but jump instead back to caller.
24 * NOFORK applets still cannot carelessly call xfuncs:
25 * p = xmalloc(10);
26 * q = xmalloc(10); // BUG! if this dies, we leak p!
27 */
28 /* -111 means "zero" (longjmp can't pass 0)
29 * spawn_and_wait() catches -111. */
30 longjmp(die_jmp, xfunc_error_retval ? xfunc_error_retval : -111);
31 }
21 sleep(die_sleep); 32 sleep(die_sleep);
22 } 33 }
23 exit(xfunc_error_retval); 34 exit(xfunc_error_retval);
@@ -30,5 +41,5 @@ void bb_error_msg_and_die(const char *s, ...)
30 va_start(p, s); 41 va_start(p, s);
31 bb_verror_msg(s, p, NULL); 42 bb_verror_msg(s, p, NULL);
32 va_end(p); 43 va_end(p);
33 sleep_and_die(); 44 xfunc_die();
34} 45}
diff --git a/libbb/fflush_stdout_and_exit.c b/libbb/fflush_stdout_and_exit.c
index ae68222b4..d79827f45 100644
--- a/libbb/fflush_stdout_and_exit.c
+++ b/libbb/fflush_stdout_and_exit.c
@@ -13,13 +13,17 @@
13 13
14#include "libbb.h" 14#include "libbb.h"
15 15
16// TODO: make it safe to call from NOFORK applets
17// Currently, it can exit(0). Even if it is made to do longjmp trick
18// (see sleep_and_die internals), zero cannot be passed thru this way!
19
20void fflush_stdout_and_exit(int retval) 16void fflush_stdout_and_exit(int retval)
21{ 17{
22 if (fflush(stdout)) 18 if (fflush(stdout))
23 sleep_and_die(); 19 xfunc_die();
20
21 if (ENABLE_FEATURE_EXEC_PREFER_APPLETS && die_sleep < 0) {
22 /* We are in NOFORK applet. Do not exit() directly,
23 * but use xfunc_die() */
24 xfunc_error_retval = retval;
25 xfunc_die();
26 }
27
24 exit(retval); 28 exit(retval);
25} 29}
diff --git a/libbb/herror_msg_and_die.c b/libbb/herror_msg_and_die.c
index a7a22caf7..8c77378d7 100644
--- a/libbb/herror_msg_and_die.c
+++ b/libbb/herror_msg_and_die.c
@@ -7,9 +7,6 @@
7 * Licensed under GPLv2 or later, see file LICENSE in this tarball for details. 7 * Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
8 */ 8 */
9 9
10#include <stdarg.h>
11#include <stdlib.h>
12
13#include "libbb.h" 10#include "libbb.h"
14 11
15void bb_herror_msg_and_die(const char *s, ...) 12void bb_herror_msg_and_die(const char *s, ...)
@@ -19,5 +16,5 @@ void bb_herror_msg_and_die(const char *s, ...)
19 va_start(p, s); 16 va_start(p, s);
20 bb_vherror_msg(s, p); 17 bb_vherror_msg(s, p);
21 va_end(p); 18 va_end(p);
22 sleep_and_die(); 19 xfunc_die();
23} 20}
diff --git a/libbb/perror_msg_and_die.c b/libbb/perror_msg_and_die.c
index 7521e7157..3a06b654b 100644
--- a/libbb/perror_msg_and_die.c
+++ b/libbb/perror_msg_and_die.c
@@ -7,10 +7,6 @@
7 * Licensed under GPLv2 or later, see file LICENSE in this tarball for details. 7 * Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
8 */ 8 */
9 9
10#include <stdio.h>
11#include <errno.h>
12#include <string.h>
13#include <stdlib.h>
14#include "libbb.h" 10#include "libbb.h"
15 11
16void bb_perror_msg_and_die(const char *s, ...) 12void bb_perror_msg_and_die(const char *s, ...)
@@ -20,5 +16,5 @@ void bb_perror_msg_and_die(const char *s, ...)
20 va_start(p, s); 16 va_start(p, s);
21 bb_vperror_msg(s, p); 17 bb_vperror_msg(s, p);
22 va_end(p); 18 va_end(p);
23 sleep_and_die(); 19 xfunc_die();
24} 20}
diff --git a/libbb/vfork_daemon_rexec.c b/libbb/vfork_daemon_rexec.c
index 286ee2678..dabd1a6d6 100644
--- a/libbb/vfork_daemon_rexec.c
+++ b/libbb/vfork_daemon_rexec.c
@@ -16,7 +16,7 @@
16 */ 16 */
17 17
18#include <paths.h> 18#include <paths.h>
19#include "busybox.h" /* for struct BB_applet */ 19#include "busybox.h" /* for struct bb_applet */
20 20
21/* This does a fork/exec in one call, using vfork(). Returns PID of new child, 21/* This does a fork/exec in one call, using vfork(). Returns PID of new child,
22 * -1 for failure. Runs argv[0], searching path if that has no / in it. */ 22 * -1 for failure. Runs argv[0], searching path if that has no / in it. */
@@ -104,8 +104,9 @@ int spawn_and_wait(char **argv)
104{ 104{
105 int rc; 105 int rc;
106 106
107 if (ENABLE_FEATURE_EXEC_PREFER_APPLETS) { 107#if ENABLE_FEATURE_EXEC_PREFER_APPLETS
108 const struct BB_applet *a = find_applet_by_name(argv[0]); 108 {
109 const struct bb_applet *a = find_applet_by_name(argv[0]);
109 if (a && (a->nofork 110 if (a && (a->nofork
110#ifndef BB_NOMMU 111#ifndef BB_NOMMU
111 || a->noexec /* NOEXEC cannot be used on NOMMU */ 112 || a->noexec /* NOEXEC cannot be used on NOMMU */
@@ -120,19 +121,27 @@ int spawn_and_wait(char **argv)
120#endif 121#endif
121 { 122 {
122 int old_sleep = die_sleep; 123 int old_sleep = die_sleep;
124 int old_x = xfunc_error_retval;
123 die_sleep = -1; /* special flag */ 125 die_sleep = -1; /* special flag */
124 /* sleep_and_die() checks for it */ 126 /* xfunc_die() checks for it */
127
125 rc = setjmp(die_jmp); 128 rc = setjmp(die_jmp);
126 if (!rc) { 129 if (!rc) {
127 const struct BB_applet *old_a = current_applet; 130 const struct bb_applet *old_a = current_applet;
128 current_applet = a; 131 current_applet = a;
129 applet_name = a->name; 132 applet_name = a->name;
130// what else should we save/restore? 133// what else should we save/restore?
131 rc = a->main(argc, argv); 134 rc = a->main(argc, argv);
132 current_applet = old_a; 135 current_applet = old_a;
133 applet_name = old_a->name; 136 applet_name = old_a->name;
137 } else {
138 /* xfunc died in NOFORK applet */
139 if (rc == -111)
140 rc = 0;
134 } 141 }
142
135 die_sleep = old_sleep; 143 die_sleep = old_sleep;
144 xfunc_error_retval = old_x;
136 return rc; 145 return rc;
137 } 146 }
138#ifndef BB_NOMMU /* MMU only */ 147#ifndef BB_NOMMU /* MMU only */
@@ -145,9 +154,13 @@ int spawn_and_wait(char **argv)
145 run_current_applet_and_exit(argc, argv); 154 run_current_applet_and_exit(argc, argv);
146#endif 155#endif
147 } 156 }
157
148 } 158 }
149 rc = spawn(argv); 159 rc = spawn(argv);
150 w: 160 w:
161#else /* !FEATURE_EXEC_PREFER_APPLETS */
162 rc = spawn(argv);
163#endif /* FEATURE_EXEC_PREFER_APPLETS */
151 return wait4pid(rc); 164 return wait4pid(rc);
152} 165}
153 166
diff --git a/libbb/xconnect.c b/libbb/xconnect.c
index 8466325c7..e7d510678 100644
--- a/libbb/xconnect.c
+++ b/libbb/xconnect.c
@@ -166,7 +166,7 @@ USE_FEATURE_IPV6(sa_family_t af,)
166 if (rc || !result) { 166 if (rc || !result) {
167 bb_error_msg("bad address '%s'", org_host); 167 bb_error_msg("bad address '%s'", org_host);
168 if (ai_flags & DIE_ON_ERROR) 168 if (ai_flags & DIE_ON_ERROR)
169 sleep_and_die(); 169 xfunc_die();
170 goto ret; 170 goto ret;
171 } 171 }
172 r = xmalloc(offsetof(len_and_sockaddr, sa) + result->ai_addrlen); 172 r = xmalloc(offsetof(len_and_sockaddr, sa) + result->ai_addrlen);
diff --git a/libbb/xfuncs.c b/libbb/xfuncs.c
index fa4a15236..b9d013a24 100644
--- a/libbb/xfuncs.c
+++ b/libbb/xfuncs.c
@@ -476,7 +476,7 @@ void xprint_and_close_file(FILE *file)
476 fflush(stdout); 476 fflush(stdout);
477 // copyfd outputs error messages for us. 477 // copyfd outputs error messages for us.
478 if (bb_copyfd_eof(fileno(file), 1) == -1) 478 if (bb_copyfd_eof(fileno(file), 1) == -1)
479 sleep_and_die(); 479 xfunc_die();
480 480
481 fclose(file); 481 fclose(file);
482} 482}
diff --git a/shell/ash.c b/shell/ash.c
index f98fc4178..b4278424a 100644
--- a/shell/ash.c
+++ b/shell/ash.c
@@ -6533,7 +6533,7 @@ tryexec(char *cmd, char **argv, char **envp)
6533 6533
6534#if ENABLE_FEATURE_SH_STANDALONE_SHELL 6534#if ENABLE_FEATURE_SH_STANDALONE_SHELL
6535 if (strchr(cmd, '/') == NULL) { 6535 if (strchr(cmd, '/') == NULL) {
6536 const struct BB_applet *a; 6536 const struct bb_applet *a;
6537 6537
6538 a = find_applet_by_name(cmd); 6538 a = find_applet_by_name(cmd);
6539 if (a) { 6539 if (a) {
diff --git a/shell/msh.c b/shell/msh.c
index 3a5c85050..23a7c0498 100644
--- a/shell/msh.c
+++ b/shell/msh.c
@@ -3197,7 +3197,7 @@ static int dohelp(struct op *t)
3197 } 3197 }
3198#if ENABLE_FEATURE_SH_STANDALONE_SHELL 3198#if ENABLE_FEATURE_SH_STANDALONE_SHELL
3199 { 3199 {
3200 const struct BB_applet *applet = applets; 3200 const struct bb_applet *applet = applets;
3201 3201
3202 while (applet->name) { 3202 while (applet->name) {
3203 col += printf("%c%s", ((col == 0) ? '\t' : ' '), applet->name); 3203 col += printf("%c%s", ((col == 0) ? '\t' : ' '), applet->name);
diff --git a/util-linux/getopt.c b/util-linux/getopt.c
index fefa02206..85a1d4410 100644
--- a/util-linux/getopt.c
+++ b/util-linux/getopt.c
@@ -51,10 +51,8 @@ enum {
51 OPT_s = 0x10, // -s 51 OPT_s = 0x10, // -s
52 OPT_T = 0x20, // -T 52 OPT_T = 0x20, // -T
53 OPT_u = 0x40, // -u 53 OPT_u = 0x40, // -u
54#if ENABLE_GETOPT_LONG
55 OPT_a = 0x80, // -a 54 OPT_a = 0x80, // -a
56 OPT_l = 0x100, // -l 55 OPT_l = 0x100, // -l
57#endif
58 SHELL_IS_TCSH = 0x8000, /* hijack this bit for other purposes */ 56 SHELL_IS_TCSH = 0x8000, /* hijack this bit for other purposes */
59}; 57};
60 58