#define usage_messages 0
#endif /* SHOW_USAGE */
-/* Define struct BB_applet applets[] */
+/* Define struct bb_applet applets[] */
#include "applets.h"
/* The -1 arises because of the {0,NULL,0,-1} entry. */
-const unsigned short NUM_APPLETS = sizeof(applets) / sizeof(struct BB_applet) - 1;
+const unsigned short NUM_APPLETS = sizeof(applets) / sizeof(applets[0]) - 1;
-const struct BB_applet *current_applet;
+const struct bb_applet *current_applet;
const char *applet_name ATTRIBUTE_EXTERNALLY_VISIBLE;
#ifdef BB_NOMMU
bool re_execed;
/* applets[] is const, so we have to define this "override" structure */
static struct BB_suid_config {
- const struct BB_applet *m_applet;
+ const struct bb_applet *m_applet;
uid_t m_uid;
gid_t m_gid;
mode_t m_mode;
{
struct BB_suid_config *sct_head;
struct BB_suid_config *sct;
- const struct BB_applet *applet;
+ const struct bb_applet *applet;
FILE *f;
const char *errmsg;
char *s;
#if ENABLE_FEATURE_SUID
-static void check_suid(const struct BB_applet *applet)
+static void check_suid(const struct bb_applet *applet)
{
uid_t ruid = getuid(); /* real [ug]id */
uid_t rgid = getgid();
applet_name, usage_string);
}
- sleep_and_die();
+ xfunc_die();
}
static int applet_name_compare(const void *name, const void *vapplet)
{
- const struct BB_applet *applet = vapplet;
+ const struct bb_applet *applet = vapplet;
return strcmp(name, applet->name);
}
-const struct BB_applet *find_applet_by_name(const char *name)
+const struct bb_applet *find_applet_by_name(const char *name)
{
/* Do a binary search to find the applet entry given the name. */
- return bsearch(name, applets, NUM_APPLETS, sizeof(struct BB_applet),
+ return bsearch(name, applets, NUM_APPLETS, sizeof(applets[0]),
applet_name_compare);
}
#if ENABLE_FEATURE_INSTALLER
-/*
- * directory table
- * this should be consistent w/ the enum, busybox.h::Location,
- * or else...
- */
-static const char usr_bin [] = "/usr/bin";
-static const char usr_sbin[] = "/usr/sbin";
-
-static const char *const install_dir[] = {
- &usr_bin [8], /* "", equivalent to "/" for concat_path_file() */
- &usr_bin [4], /* "/bin" */
- &usr_sbin[4], /* "/sbin" */
- usr_bin,
- usr_sbin
-};
-
/* create (sym)links for each applet */
static void install_links(const char *busybox, int use_symbolic_links)
{
+ /* directory table
+ * this should be consistent w/ the enum,
+ * busybox.h::bb_install_loc_t, or else... */
+ static const char usr_bin [] = "/usr/bin";
+ static const char usr_sbin[] = "/usr/sbin";
+ static const char *const install_dir[] = {
+ &usr_bin [8], /* "", equivalent to "/" for concat_path_file() */
+ &usr_bin [4], /* "/bin" */
+ &usr_sbin[4], /* "/sbin" */
+ usr_bin,
+ usr_sbin
+ };
+
int (*lf)(const char *, const char *) = link;
char *fpc;
int i;
for (i = 0; applets[i].name != NULL; i++) {
fpc = concat_path_file(
- install_dir[applets[i].location],
+ install_dir[applets[i].install_loc],
applets[i].name);
rc = lf(busybox, fpc);
if (rc != 0 && errno != EEXIST) {
applet_name = argv[2];
run_applet_by_name(applet_name, 2, argv);
} else {
- const struct BB_applet *a;
+ const struct bb_applet *a;
int col, output_width;
output_width = 80 - sizeof("start-stop-daemon, ") - 8;
get_header_tar.o \
filter_accept_list_reassign.o
-# open_transformer uses fork. Compile it only if absolutely necessary
+# open_transformer uses fork(). Compile it only if absolutely necessary
lib-$(CONFIG_RPM) += open_transformer.o
lib-$(CONFIG_FEATURE_TAR_BZIP2) += open_transformer.o
lib-$(CONFIG_FEATURE_TAR_LZMA) += open_transformer.o
lib-$(CONFIG_FEATURE_TAR_GZIP) += open_transformer.o
lib-$(CONFIG_FEATURE_TAR_COMPRESS) += open_transformer.o
+lib-$(CONFIG_FEATURE_DEB_TAR_GZ) += open_transformer.o
+lib-$(CONFIG_FEATURE_DEB_TAR_BZ2) += open_transformer.o
+lib-$(CONFIG_FEATURE_DEB_TAR_LZMA) += open_transformer.o
lib-$(CONFIG_AR) += get_header_ar.o unpack_ar_archive.o
lib-$(CONFIG_BUNZIP2) += decompress_bunzip2.o
#include "busybox.h"
-static FILE *cmp_xfopen_input(const char * const filename)
+static FILE *cmp_xfopen_input(const char *filename)
{
FILE *fp;
fp = fopen_or_warn_stdin(filename);
if (fp)
return fp;
- sleep_and_die(); /* We already output an error message. */
+ xfunc_die(); /* We already output an error message. */
}
static const char fmt_eof[] = "cmp: EOF on %s\n";
putchar(' ');
}
+#if ENABLE_FEATURE_FANCY_ECHO
newline_ret:
+#endif
if (nflag) {
putchar('\n');
}
# define APPLET_NOFORK(name,main,l,s,name2) LINK l name
#else
- const struct BB_applet applets[] = { /* name,main,location,need_suid */
-# define APPLET(name,l,s) {#name,name##_main,l,s},
-# define APPLET_NOUSAGE(name,main,l,s) {#name,main##_main,l,s},
-# define APPLET_ODDNAME(name,main,l,s,name2) {#name,main##_main,l,s},
-# define APPLET_NOEXEC(name,main,l,s,name2) {#name,main##_main,l,s,1},
-# define APPLET_NOFORK(name,main,l,s,name2) {#name,main##_main,l,s,1,1},
+ const struct bb_applet applets[] = { /* name, main, location, need_suid */
+# define APPLET(name,l,s) { #name, name##_main USE_FEATURE_INSTALLER(,l) USE_FEATURE_SUID(,s) },
+# define APPLET_NOUSAGE(name,main,l,s) { #name, main##_main USE_FEATURE_INSTALLER(,l) USE_FEATURE_SUID(,s) },
+# define APPLET_ODDNAME(name,main,l,s,name2) { #name, main##_main USE_FEATURE_INSTALLER(,l) USE_FEATURE_SUID(,s) },
+# 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) },
+# 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) },
#endif
#if ENABLE_INSTALL_NO_USR
USE_ZCIP(APPLET(zcip, _BB_DIR_SBIN, _BB_SUID_NEVER))
#if !defined(PROTOTYPES) && !defined(MAKE_USAGE)
- { 0, NULL, 0, 0 }
+ { NULL }
};
#endif
#include "libbb.h"
+#if ENABLE_FEATURE_INSTALLER
/* order matters: used as index into "install_dir[]" in busybox.c */
-enum Location {
+typedef enum bb_install_loc_t {
_BB_DIR_ROOT = 0,
_BB_DIR_BIN,
_BB_DIR_SBIN,
_BB_DIR_USR_BIN,
_BB_DIR_USR_SBIN
-};
+} bb_install_loc_t;
+#endif
-enum SUIDRoot {
+#if ENABLE_FEATURE_SUID
+typedef enum bb_suid_t {
_BB_SUID_NEVER = 0,
_BB_SUID_MAYBE,
_BB_SUID_ALWAYS
-};
+} bb_suid_t;
+#endif
-struct BB_applet {
+struct bb_applet {
const char *name;
int (*main) (int argc, char **argv);
- __extension__ enum Location location:8;
- __extension__ enum SUIDRoot need_suid:8;
+#if ENABLE_FEATURE_INSTALLER
+ __extension__ enum bb_install_loc_t install_loc:8;
+#endif
+#if ENABLE_FEATURE_SUID
+ __extension__ enum bb_suid_t need_suid:8;
+#endif
+#if ENABLE_FEATURE_EXEC_PREFER_APPLETS
/* true if instead if fork(); exec("applet"); waitpid();
* one can do fork(); exit(applet_main(argc,argv)); waitpid(); */
unsigned char noexec;
/* true if instead if fork(); exec("applet"); waitpid();
* one can simply call applet_main(argc,argv); */
unsigned char nofork;
+#endif
};
/* Defined in applet.c */
-extern const struct BB_applet applets[];
+extern const struct bb_applet applets[];
extern const unsigned short NUM_APPLETS;
#endif /* _BB_INTERNAL_H_ */
int write_pidfile(const char *path);
#define remove_pidfile(f) ((void)unlink(f))
#else
-#define write_pidfile(f) 1
+#define write_pidfile(f) TRUE
#define remove_pidfile(f) ((void)0)
#endif
extern int die_sleep;
extern int xfunc_error_retval;
extern jmp_buf die_jmp;
-extern void sleep_and_die(void) ATTRIBUTE_NORETURN;
+extern void xfunc_die(void) ATTRIBUTE_NORETURN;
extern void bb_show_usage(void) ATTRIBUTE_NORETURN ATTRIBUTE_EXTERNALLY_VISIBLE;
extern void bb_error_msg(const char *s, ...) __attribute__ ((format (printf, 1, 2)));
extern void bb_error_msg_and_die(const char *s, ...) __attribute__ ((noreturn, format (printf, 1, 2)));
#ifndef BUILD_INDIVIDUAL
-struct BB_applet;
-extern const struct BB_applet *find_applet_by_name(const char *name);
+struct bb_applet;
+extern const struct bb_applet *find_applet_by_name(const char *name);
/* Returns only if applet is not found. */
extern void run_applet_by_name(const char *name, int argc, char **argv);
extern void run_current_applet_and_exit(int argc, char **argv) ATTRIBUTE_NORETURN;
};
#define FILEUTILS_CP_OPTSTR "pdRfils" USE_SELINUX("c")
-extern const struct BB_applet *current_applet;
+extern const struct bb_applet *current_applet;
extern const char *applet_name;
extern const char BB_BANNER[];
if (sz != -1)
bb_error_msg_and_die("short read");
/* if sz == -1, bb_copyfd_XX already complained */
- sleep_and_die();
+ xfunc_die();
}
#endif
if (sz != -1)
bb_error_msg_and_die("short read");
/* if sz == -1, bb_copyfd_XX already complained */
- sleep_and_die();
+ xfunc_die();
}
off_t bb_copyfd_eof(int fd1, int fd2)
#include "libbb.h"
int die_sleep;
+#if ENABLE_FEATURE_EXEC_PREFER_APPLETS
jmp_buf die_jmp;
+#endif
-void sleep_and_die(void)
+void xfunc_die(void)
{
if (die_sleep) {
- /* Special case: don't die, but jump */
- if (die_sleep < 0)
- longjmp(die_jmp, xfunc_error_retval);
+ if (ENABLE_FEATURE_EXEC_PREFER_APPLETS && die_sleep < 0) {
+ /* Special case. We arrive here if NOFORK applet
+ * calls xfunc, which then decides to die.
+ * We don't die, but jump instead back to caller.
+ * NOFORK applets still cannot carelessly call xfuncs:
+ * p = xmalloc(10);
+ * q = xmalloc(10); // BUG! if this dies, we leak p!
+ */
+ /* -111 means "zero" (longjmp can't pass 0)
+ * spawn_and_wait() catches -111. */
+ longjmp(die_jmp, xfunc_error_retval ? xfunc_error_retval : -111);
+ }
sleep(die_sleep);
}
exit(xfunc_error_retval);
va_start(p, s);
bb_verror_msg(s, p, NULL);
va_end(p);
- sleep_and_die();
+ xfunc_die();
}
#include "libbb.h"
-// TODO: make it safe to call from NOFORK applets
-// Currently, it can exit(0). Even if it is made to do longjmp trick
-// (see sleep_and_die internals), zero cannot be passed thru this way!
-
void fflush_stdout_and_exit(int retval)
{
if (fflush(stdout))
- sleep_and_die();
+ xfunc_die();
+
+ if (ENABLE_FEATURE_EXEC_PREFER_APPLETS && die_sleep < 0) {
+ /* We are in NOFORK applet. Do not exit() directly,
+ * but use xfunc_die() */
+ xfunc_error_retval = retval;
+ xfunc_die();
+ }
+
exit(retval);
}
* Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
*/
-#include <stdarg.h>
-#include <stdlib.h>
-
#include "libbb.h"
void bb_herror_msg_and_die(const char *s, ...)
va_start(p, s);
bb_vherror_msg(s, p);
va_end(p);
- sleep_and_die();
+ xfunc_die();
}
* Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
*/
-#include <stdio.h>
-#include <errno.h>
-#include <string.h>
-#include <stdlib.h>
#include "libbb.h"
void bb_perror_msg_and_die(const char *s, ...)
va_start(p, s);
bb_vperror_msg(s, p);
va_end(p);
- sleep_and_die();
+ xfunc_die();
}
*/
#include <paths.h>
-#include "busybox.h" /* for struct BB_applet */
+#include "busybox.h" /* for struct bb_applet */
/* This does a fork/exec in one call, using vfork(). Returns PID of new child,
* -1 for failure. Runs argv[0], searching path if that has no / in it. */
{
int rc;
- if (ENABLE_FEATURE_EXEC_PREFER_APPLETS) {
- const struct BB_applet *a = find_applet_by_name(argv[0]);
+#if ENABLE_FEATURE_EXEC_PREFER_APPLETS
+ {
+ const struct bb_applet *a = find_applet_by_name(argv[0]);
if (a && (a->nofork
#ifndef BB_NOMMU
|| a->noexec /* NOEXEC cannot be used on NOMMU */
#endif
{
int old_sleep = die_sleep;
+ int old_x = xfunc_error_retval;
die_sleep = -1; /* special flag */
- /* sleep_and_die() checks for it */
+ /* xfunc_die() checks for it */
+
rc = setjmp(die_jmp);
if (!rc) {
- const struct BB_applet *old_a = current_applet;
+ const struct bb_applet *old_a = current_applet;
current_applet = a;
applet_name = a->name;
// what else should we save/restore?
rc = a->main(argc, argv);
current_applet = old_a;
applet_name = old_a->name;
+ } else {
+ /* xfunc died in NOFORK applet */
+ if (rc == -111)
+ rc = 0;
}
+
die_sleep = old_sleep;
+ xfunc_error_retval = old_x;
return rc;
}
#ifndef BB_NOMMU /* MMU only */
run_current_applet_and_exit(argc, argv);
#endif
}
+
}
rc = spawn(argv);
w:
+#else /* !FEATURE_EXEC_PREFER_APPLETS */
+ rc = spawn(argv);
+#endif /* FEATURE_EXEC_PREFER_APPLETS */
return wait4pid(rc);
}
if (rc || !result) {
bb_error_msg("bad address '%s'", org_host);
if (ai_flags & DIE_ON_ERROR)
- sleep_and_die();
+ xfunc_die();
goto ret;
}
r = xmalloc(offsetof(len_and_sockaddr, sa) + result->ai_addrlen);
fflush(stdout);
// copyfd outputs error messages for us.
if (bb_copyfd_eof(fileno(file), 1) == -1)
- sleep_and_die();
+ xfunc_die();
fclose(file);
}
#if ENABLE_FEATURE_SH_STANDALONE_SHELL
if (strchr(cmd, '/') == NULL) {
- const struct BB_applet *a;
+ const struct bb_applet *a;
a = find_applet_by_name(cmd);
if (a) {
}
#if ENABLE_FEATURE_SH_STANDALONE_SHELL
{
- const struct BB_applet *applet = applets;
+ const struct bb_applet *applet = applets;
while (applet->name) {
col += printf("%c%s", ((col == 0) ? '\t' : ' '), applet->name);
OPT_s = 0x10, // -s
OPT_T = 0x20, // -T
OPT_u = 0x40, // -u
-#if ENABLE_GETOPT_LONG
OPT_a = 0x80, // -a
OPT_l = 0x100, // -l
-#endif
SHELL_IS_TCSH = 0x8000, /* hijack this bit for other purposes */
};