reorganize applet table. Eliminates pointers to names.
Should be a big win for libbusybox. busybox wins too: text data bss dec hex filename 776524 929 9100 786553 c0079 busybox_old 775903 929 9100 785932 bfe0c busybox_unstripped
This commit is contained in:
parent
79c6904faf
commit
1aa7e477b1
2
Makefile
2
Makefile
@ -928,6 +928,8 @@ MRPROPER_FILES += .config .config.old include/asm .version .old_version \
|
|||||||
include/autoconf.h \
|
include/autoconf.h \
|
||||||
include/bbconfigopts.h \
|
include/bbconfigopts.h \
|
||||||
include/usage_compressed.h \
|
include/usage_compressed.h \
|
||||||
|
include/applet_tables.h \
|
||||||
|
applets/usage \
|
||||||
.kernelrelease Module.symvers tags TAGS cscope*
|
.kernelrelease Module.symvers tags TAGS cscope*
|
||||||
|
|
||||||
# clean - Delete most, but leave enough to build external modules
|
# clean - Delete most, but leave enough to build external modules
|
||||||
|
@ -8,7 +8,7 @@ obj-y :=
|
|||||||
obj-y += applets.o
|
obj-y += applets.o
|
||||||
|
|
||||||
hostprogs-y:=
|
hostprogs-y:=
|
||||||
hostprogs-y += usage
|
hostprogs-y += usage applet_tables
|
||||||
|
|
||||||
always:= $(hostprogs-y)
|
always:= $(hostprogs-y)
|
||||||
|
|
||||||
@ -19,7 +19,15 @@ quiet_cmd_gen_usage_compressed = GEN include/usage_compressed.h
|
|||||||
|
|
||||||
HOSTCFLAGS_usage.o = -I$(srctree)/include
|
HOSTCFLAGS_usage.o = -I$(srctree)/include
|
||||||
|
|
||||||
applets/applets.o: include/usage_compressed.h
|
applets/applets.o: include/usage_compressed.h include/applet_tables.h
|
||||||
|
|
||||||
applets/usage: .config $(srctree)/applets/usage_compressed
|
applets/usage: .config $(srctree)/applets/usage_compressed
|
||||||
|
|
||||||
include/usage_compressed.h: applets/usage $(srctree)/applets/usage_compressed
|
include/usage_compressed.h: applets/usage $(srctree)/applets/usage_compressed
|
||||||
$(call cmd,gen_usage_compressed)
|
$(call cmd,gen_usage_compressed)
|
||||||
|
|
||||||
|
# Two-stage file creation, to avoid having target file still created
|
||||||
|
# in case applet_tables fails
|
||||||
|
include/applet_tables.h: applets/applet_tables
|
||||||
|
applets/applet_tables >include/applet_tables.h.tmp
|
||||||
|
mv include/applet_tables.h.tmp include/applet_tables.h
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
/*
|
/*
|
||||||
* Stub for linking busybox binary against libbusybox.
|
* Stub for linking busybox binary against libbusybox.
|
||||||
*
|
*
|
||||||
* Copyright (C) 2007 Denis Vlasenko
|
* Copyright (C) 2007 Denys Vlasenko <vda.linux@googlemail.com>
|
||||||
*
|
*
|
||||||
* Licensed under GPLv2, see file License in this tarball for details.
|
* Licensed under GPLv2, see file License in this tarball for details.
|
||||||
*/
|
*/
|
||||||
|
@ -59,12 +59,12 @@ s - suid type:
|
|||||||
# define APPLET_NOFORK(name,main,l,s,name2) LINK l name
|
# define APPLET_NOFORK(name,main,l,s,name2) LINK l name
|
||||||
|
|
||||||
#else
|
#else
|
||||||
const struct bb_applet applets[] = { /* name, main, location, need_suid */
|
static 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(name,l,s) { #name, #name, l, s },
|
||||||
# define APPLET_NOUSAGE(name,main,l,s) { #name, main##_main USE_FEATURE_INSTALLER(,l) USE_FEATURE_SUID(,s) },
|
# define APPLET_NOUSAGE(name,main,l,s) { #name, #main, l, s },
|
||||||
# define APPLET_ODDNAME(name,main,l,s,name2) { #name, main##_main USE_FEATURE_INSTALLER(,l) USE_FEATURE_SUID(,s) },
|
# define APPLET_ODDNAME(name,main,l,s,name2) { #name, #main, l, s },
|
||||||
# define APPLET_NOEXEC(name,main,l,s,name2) { #name, main##_main USE_FEATURE_INSTALLER(,l) USE_FEATURE_SUID(,s) USE_FEATURE_PREFER_APPLETS(,1) },
|
# define APPLET_NOEXEC(name,main,l,s,name2) { #name, #main, l, s, 1 },
|
||||||
# define APPLET_NOFORK(name,main,l,s,name2) { #name, main##_main USE_FEATURE_INSTALLER(,l) USE_FEATURE_SUID(,s) USE_FEATURE_PREFER_APPLETS(,1 ,1) },
|
# define APPLET_NOFORK(name,main,l,s,name2) { #name, #main, l, s, 1, 1 },
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if ENABLE_INSTALL_NO_USR
|
#if ENABLE_INSTALL_NO_USR
|
||||||
@ -385,7 +385,6 @@ USE_GUNZIP(APPLET_ODDNAME(zcat, gunzip, _BB_DIR_BIN, _BB_SUID_NEVER, zcat))
|
|||||||
USE_ZCIP(APPLET(zcip, _BB_DIR_SBIN, _BB_SUID_NEVER))
|
USE_ZCIP(APPLET(zcip, _BB_DIR_SBIN, _BB_SUID_NEVER))
|
||||||
|
|
||||||
#if !defined(PROTOTYPES) && !defined(NAME_MAIN_CNAME) && !defined(MAKE_USAGE)
|
#if !defined(PROTOTYPES) && !defined(NAME_MAIN_CNAME) && !defined(MAKE_USAGE)
|
||||||
{ NULL }
|
|
||||||
};
|
};
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -9,8 +9,7 @@
|
|||||||
|
|
||||||
#include "libbb.h"
|
#include "libbb.h"
|
||||||
|
|
||||||
#if ENABLE_FEATURE_INSTALLER
|
/* order matters: used as index into "install_dir[]" in appletlib.c */
|
||||||
/* order matters: used as index into "install_dir[]" in busybox.c */
|
|
||||||
typedef enum bb_install_loc_t {
|
typedef enum bb_install_loc_t {
|
||||||
_BB_DIR_ROOT = 0,
|
_BB_DIR_ROOT = 0,
|
||||||
_BB_DIR_BIN,
|
_BB_DIR_BIN,
|
||||||
@ -18,41 +17,42 @@ typedef enum bb_install_loc_t {
|
|||||||
_BB_DIR_USR_BIN,
|
_BB_DIR_USR_BIN,
|
||||||
_BB_DIR_USR_SBIN
|
_BB_DIR_USR_SBIN
|
||||||
} bb_install_loc_t;
|
} bb_install_loc_t;
|
||||||
#endif
|
|
||||||
|
|
||||||
#if ENABLE_FEATURE_SUID
|
|
||||||
typedef enum bb_suid_t {
|
typedef enum bb_suid_t {
|
||||||
_BB_SUID_NEVER = 0,
|
_BB_SUID_NEVER = 0,
|
||||||
_BB_SUID_MAYBE,
|
_BB_SUID_MAYBE,
|
||||||
_BB_SUID_ALWAYS
|
_BB_SUID_ALWAYS
|
||||||
} bb_suid_t;
|
} bb_suid_t;
|
||||||
|
|
||||||
|
|
||||||
|
/* Defined in appletlib.c (by including generated applet_tables.h) */
|
||||||
|
/* Keep in sync with applets/applet_tables.c! */
|
||||||
|
extern const char applet_names[];
|
||||||
|
extern int (*const applet_mains[])(int argc, char **argv);
|
||||||
|
|
||||||
|
#if ENABLE_FEATURE_INSTALLER || ENABLE_FEATURE_PREFER_APPLETS
|
||||||
|
extern const uint32_t applet_nameofs[];
|
||||||
|
#else
|
||||||
|
extern const uint16_t applet_nameofs[];
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
struct bb_applet {
|
|
||||||
const char *name;
|
|
||||||
int (*main) (int argc, char **argv);
|
|
||||||
#if ENABLE_FEATURE_INSTALLER
|
|
||||||
__extension__ enum bb_install_loc_t install_loc:8;
|
|
||||||
#endif
|
|
||||||
#if ENABLE_FEATURE_SUID
|
#if ENABLE_FEATURE_SUID
|
||||||
__extension__ enum bb_suid_t need_suid:8;
|
#define APPLET_NAME(i) (applet_names + (applet_nameofs[i] & 0x3fff))
|
||||||
|
#define APPLET_SUID(i) ((applet_nameofs[i] >> 14) & 0x3)
|
||||||
|
#else
|
||||||
|
#define APPLET_NAME(i) (applet_names + (applet_nameofs[i] & 0xffff))
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if ENABLE_FEATURE_INSTALLER
|
||||||
|
#define APPLET_INSTALL_LOC(i) ((applet_nameofs[i] >> 16) & 0x7)
|
||||||
|
#endif
|
||||||
|
|
||||||
#if ENABLE_FEATURE_PREFER_APPLETS
|
#if ENABLE_FEATURE_PREFER_APPLETS
|
||||||
/* true if instead of fork(); exec("applet"); waitpid();
|
#define APPLET_IS_NOFORK(i) (applet_nameofs[i] & (1 << 19))
|
||||||
* one can do fork(); exit(applet_main(argc,argv)); waitpid(); */
|
#define APPLET_IS_NOEXEC(i) (applet_nameofs[i] & (1 << 20))
|
||||||
unsigned char noexec;
|
|
||||||
/* Even nicer */
|
|
||||||
/* true if instead of fork(); exec("applet"); waitpid();
|
|
||||||
* one can simply call applet_main(argc,argv); */
|
|
||||||
unsigned char nofork;
|
|
||||||
#endif
|
#endif
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/* Defined in appletlib.c */
|
|
||||||
extern const struct bb_applet applets[];
|
|
||||||
extern const unsigned short NUM_APPLETS;
|
|
||||||
|
|
||||||
/* Length of these names has effect on size of libbusybox
|
/* Length of these names has effect on size of libbusybox
|
||||||
* and "individual" binaries. Keep them short.
|
* and "individual" binaries. Keep them short.
|
||||||
*/
|
*/
|
||||||
|
@ -550,7 +550,6 @@ void clear_username_cache(void);
|
|||||||
enum { USERNAME_MAX_SIZE = 16 - sizeof(int) };
|
enum { USERNAME_MAX_SIZE = 16 - sizeof(int) };
|
||||||
|
|
||||||
|
|
||||||
struct bb_applet;
|
|
||||||
int execable_file(const char *name);
|
int execable_file(const char *name);
|
||||||
char *find_execable(const char *filename);
|
char *find_execable(const char *filename);
|
||||||
int exists_execable(const char *filename);
|
int exists_execable(const char *filename);
|
||||||
@ -562,7 +561,7 @@ int exists_execable(const char *filename);
|
|||||||
int bb_execvp(const char *file, char *const argv[]);
|
int bb_execvp(const char *file, char *const argv[]);
|
||||||
#define BB_EXECVP(prog,cmd) bb_execvp(prog,cmd)
|
#define BB_EXECVP(prog,cmd) bb_execvp(prog,cmd)
|
||||||
#define BB_EXECLP(prog,cmd,...) \
|
#define BB_EXECLP(prog,cmd,...) \
|
||||||
execlp((find_applet_by_name(prog)) ? CONFIG_BUSYBOX_EXEC_PATH : prog, \
|
execlp((find_applet_by_name(prog) >= 0) ? CONFIG_BUSYBOX_EXEC_PATH : prog, \
|
||||||
cmd, __VA_ARGS__)
|
cmd, __VA_ARGS__)
|
||||||
#else
|
#else
|
||||||
#define BB_EXECVP(prog,cmd) execvp(prog,cmd)
|
#define BB_EXECVP(prog,cmd) execvp(prog,cmd)
|
||||||
@ -600,8 +599,8 @@ struct nofork_save_area {
|
|||||||
void save_nofork_data(struct nofork_save_area *save);
|
void save_nofork_data(struct nofork_save_area *save);
|
||||||
void restore_nofork_data(struct nofork_save_area *save);
|
void restore_nofork_data(struct nofork_save_area *save);
|
||||||
/* Does NOT check that applet is NOFORK, just blindly runs it */
|
/* Does NOT check that applet is NOFORK, just blindly runs it */
|
||||||
int run_nofork_applet(const struct bb_applet *a, char **argv);
|
int run_nofork_applet(int applet_no, char **argv);
|
||||||
int run_nofork_applet_prime(struct nofork_save_area *old, const struct bb_applet *a, char **argv);
|
int run_nofork_applet_prime(struct nofork_save_area *old, int applet_no, char **argv);
|
||||||
|
|
||||||
/* Helpers for daemonization.
|
/* Helpers for daemonization.
|
||||||
*
|
*
|
||||||
@ -786,10 +785,10 @@ const struct hwtype *get_hwntype(int type);
|
|||||||
|
|
||||||
|
|
||||||
#ifndef BUILD_INDIVIDUAL
|
#ifndef BUILD_INDIVIDUAL
|
||||||
extern const struct bb_applet *find_applet_by_name(const char *name);
|
extern int find_applet_by_name(const char *name);
|
||||||
/* Returns only if applet is not found. */
|
/* Returns only if applet is not found. */
|
||||||
extern void run_applet_and_exit(const char *name, char **argv);
|
extern void run_applet_and_exit(const char *name, char **argv);
|
||||||
extern void run_appletstruct_and_exit(const struct bb_applet *a, char **argv) ATTRIBUTE_NORETURN;
|
extern void run_applet_no_and_exit(int a, char **argv) ATTRIBUTE_NORETURN;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
extern int match_fstype(const struct mntent *mt, const char *fstypes);
|
extern int match_fstype(const struct mntent *mt, const char *fstypes);
|
||||||
|
@ -33,13 +33,9 @@ static const char usage_messages[] ALIGN1 = ""
|
|||||||
#define usage_messages 0
|
#define usage_messages 0
|
||||||
#endif /* SHOW_USAGE */
|
#endif /* SHOW_USAGE */
|
||||||
|
|
||||||
/* Define struct bb_applet applets[] */
|
|
||||||
#include "applets.h"
|
|
||||||
|
|
||||||
#if ENABLE_FEATURE_SH_STANDALONE
|
/* Include generated applet names, pointers to <apllet>_main, etc */
|
||||||
/* -1 because last entry is NULL */
|
#include "applet_tables.h"
|
||||||
const unsigned short NUM_APPLETS = ARRAY_SIZE(applets) - 1;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
#if ENABLE_FEATURE_COMPRESS_USAGE
|
#if ENABLE_FEATURE_COMPRESS_USAGE
|
||||||
@ -84,16 +80,14 @@ void bb_show_usage(void)
|
|||||||
const char *format_string;
|
const char *format_string;
|
||||||
const char *p;
|
const char *p;
|
||||||
const char *usage_string = p = unpack_usage_messages();
|
const char *usage_string = p = unpack_usage_messages();
|
||||||
const struct bb_applet *ap = find_applet_by_name(applet_name);
|
int ap = find_applet_by_name(applet_name);
|
||||||
int i;
|
|
||||||
|
|
||||||
if (!ap) /* never happens, paranoia */
|
if (ap < 0) /* never happens, paranoia */
|
||||||
xfunc_die();
|
xfunc_die();
|
||||||
|
|
||||||
i = ap - applets;
|
while (ap) {
|
||||||
while (i) {
|
|
||||||
while (*p++) continue;
|
while (*p++) continue;
|
||||||
i--;
|
ap--;
|
||||||
}
|
}
|
||||||
|
|
||||||
fprintf(stderr, "%s multi-call binary\n", bb_banner);
|
fprintf(stderr, "%s multi-call binary\n", bb_banner);
|
||||||
@ -107,18 +101,22 @@ void bb_show_usage(void)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static int applet_name_compare(const void *name, const void *vapplet)
|
static int applet_name_compare(const void *name, const void *v)
|
||||||
{
|
{
|
||||||
const struct bb_applet *applet = vapplet;
|
int i = (const char *)v - applet_names;
|
||||||
|
return strcmp(name, APPLET_NAME(i));
|
||||||
return strcmp(name, applet->name);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const struct bb_applet *find_applet_by_name(const char *name)
|
int find_applet_by_name(const char *name)
|
||||||
{
|
{
|
||||||
|
const char *p;
|
||||||
/* Do a binary search to find the applet entry given the name. */
|
/* Do a binary search to find the applet entry given the name. */
|
||||||
return bsearch(name, applets, ARRAY_SIZE(applets)-1, sizeof(applets[0]),
|
|
||||||
applet_name_compare);
|
/* NB: any char pointer will work as well, not necessarily applet_names */
|
||||||
|
p = bsearch(name, applet_names, ARRAY_SIZE(applet_mains), 1, applet_name_compare);
|
||||||
|
if (!p)
|
||||||
|
return -1;
|
||||||
|
return p - applet_names;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -166,7 +164,7 @@ USE_FEATURE_SUID(static uid_t ruid;) /* real uid */
|
|||||||
|
|
||||||
/* applets[] is const, so we have to define this "override" structure */
|
/* applets[] is const, so we have to define this "override" structure */
|
||||||
static struct BB_suid_config {
|
static struct BB_suid_config {
|
||||||
const struct bb_applet *m_applet;
|
int m_applet;
|
||||||
uid_t m_uid;
|
uid_t m_uid;
|
||||||
gid_t m_gid;
|
gid_t m_gid;
|
||||||
mode_t m_mode;
|
mode_t m_mode;
|
||||||
@ -232,7 +230,7 @@ static void parse_config_file(void)
|
|||||||
{
|
{
|
||||||
struct BB_suid_config *sct_head;
|
struct BB_suid_config *sct_head;
|
||||||
struct BB_suid_config *sct;
|
struct BB_suid_config *sct;
|
||||||
const struct bb_applet *applet;
|
int applet_no;
|
||||||
FILE *f;
|
FILE *f;
|
||||||
const char *errmsg;
|
const char *errmsg;
|
||||||
char *s;
|
char *s;
|
||||||
@ -343,14 +341,14 @@ static void parse_config_file(void)
|
|||||||
* applet is currently built in and ignore it otherwise.
|
* applet is currently built in and ignore it otherwise.
|
||||||
* Note: this can hide config file bugs which only pop
|
* Note: this can hide config file bugs which only pop
|
||||||
* up when the busybox configuration is changed. */
|
* up when the busybox configuration is changed. */
|
||||||
applet = find_applet_by_name(s);
|
applet_no = find_applet_by_name(s);
|
||||||
if (applet) {
|
if (applet_no >= 0) {
|
||||||
/* Note: We currently don't check for duplicates!
|
/* Note: We currently don't check for duplicates!
|
||||||
* The last config line for each applet will be the
|
* The last config line for each applet will be the
|
||||||
* one used since we insert at the head of the list.
|
* one used since we insert at the head of the list.
|
||||||
* I suppose this could be considered a feature. */
|
* I suppose this could be considered a feature. */
|
||||||
sct = xmalloc(sizeof(struct BB_suid_config));
|
sct = xmalloc(sizeof(struct BB_suid_config));
|
||||||
sct->m_applet = applet;
|
sct->m_applet = applet_no;
|
||||||
sct->m_mode = 0;
|
sct->m_mode = 0;
|
||||||
sct->m_next = sct_head;
|
sct->m_next = sct_head;
|
||||||
sct_head = sct;
|
sct_head = sct;
|
||||||
@ -441,7 +439,7 @@ static inline void parse_config_file(void)
|
|||||||
|
|
||||||
|
|
||||||
#if ENABLE_FEATURE_SUID
|
#if ENABLE_FEATURE_SUID
|
||||||
static void check_suid(const struct bb_applet *applet)
|
static void check_suid(int applet_no)
|
||||||
{
|
{
|
||||||
gid_t rgid; /* real gid */
|
gid_t rgid; /* real gid */
|
||||||
|
|
||||||
@ -456,7 +454,7 @@ static void check_suid(const struct bb_applet *applet)
|
|||||||
mode_t m;
|
mode_t m;
|
||||||
|
|
||||||
for (sct = suid_config; sct; sct = sct->m_next) {
|
for (sct = suid_config; sct; sct = sct->m_next) {
|
||||||
if (sct->m_applet == applet)
|
if (sct->m_applet == applet_no)
|
||||||
goto found;
|
goto found;
|
||||||
}
|
}
|
||||||
goto check_need_suid;
|
goto check_need_suid;
|
||||||
@ -504,12 +502,12 @@ static void check_suid(const struct bb_applet *applet)
|
|||||||
#endif
|
#endif
|
||||||
check_need_suid:
|
check_need_suid:
|
||||||
#endif
|
#endif
|
||||||
if (applet->need_suid == _BB_SUID_ALWAYS) {
|
if (APPLET_SUID(applet_no) == _BB_SUID_ALWAYS) {
|
||||||
/* Real uid is not 0. If euid isn't 0 too, suid bit
|
/* Real uid is not 0. If euid isn't 0 too, suid bit
|
||||||
* is most probably not set on our executable */
|
* is most probably not set on our executable */
|
||||||
if (geteuid())
|
if (geteuid())
|
||||||
bb_error_msg_and_die("must be suid to work properly");
|
bb_error_msg_and_die("must be suid to work properly");
|
||||||
} else if (applet->need_suid == _BB_SUID_NEVER) {
|
} else if (APPLET_SUID(applet_no) == _BB_SUID_NEVER) {
|
||||||
xsetgid(rgid); /* drop all privileges */
|
xsetgid(rgid); /* drop all privileges */
|
||||||
xsetuid(ruid);
|
xsetuid(ruid);
|
||||||
}
|
}
|
||||||
@ -536,18 +534,19 @@ static void install_links(const char *busybox, int use_symbolic_links)
|
|||||||
usr_sbin
|
usr_sbin
|
||||||
};
|
};
|
||||||
|
|
||||||
int (*lf)(const char *, const char *) = link;
|
int (*lf)(const char *, const char *);
|
||||||
char *fpc;
|
char *fpc;
|
||||||
int i;
|
int i;
|
||||||
int rc;
|
int rc;
|
||||||
|
|
||||||
|
lf = link;
|
||||||
if (use_symbolic_links)
|
if (use_symbolic_links)
|
||||||
lf = symlink;
|
lf = symlink;
|
||||||
|
|
||||||
for (i = 0; applets[i].name != NULL; i++) {
|
for (i = 0; i < ARRAY_SIZE(applet_mains); i++) {
|
||||||
fpc = concat_path_file(
|
fpc = concat_path_file(
|
||||||
install_dir[applets[i].install_loc],
|
install_dir[APPLET_INSTALL_LOC(i)],
|
||||||
applets[i].name);
|
APPLET_NAME(i));
|
||||||
rc = lf(busybox, fpc);
|
rc = lf(busybox, fpc);
|
||||||
if (rc != 0 && errno != EEXIST) {
|
if (rc != 0 && errno != EEXIST) {
|
||||||
bb_simple_perror_msg(fpc);
|
bb_simple_perror_msg(fpc);
|
||||||
@ -564,7 +563,7 @@ static int busybox_main(char **argv)
|
|||||||
{
|
{
|
||||||
if (!argv[1]) {
|
if (!argv[1]) {
|
||||||
/* Called without arguments */
|
/* Called without arguments */
|
||||||
const struct bb_applet *a;
|
const char *a;
|
||||||
int col, output_width;
|
int col, output_width;
|
||||||
help:
|
help:
|
||||||
output_width = 80;
|
output_width = 80;
|
||||||
@ -588,14 +587,14 @@ static int busybox_main(char **argv)
|
|||||||
"\twill act like whatever it was invoked as!\n"
|
"\twill act like whatever it was invoked as!\n"
|
||||||
"\nCurrently defined functions:\n");
|
"\nCurrently defined functions:\n");
|
||||||
col = 0;
|
col = 0;
|
||||||
a = applets;
|
a = applet_names;
|
||||||
while (a->name) {
|
while (*a) {
|
||||||
if (col > output_width) {
|
if (col > output_width) {
|
||||||
puts(",");
|
puts(",");
|
||||||
col = 0;
|
col = 0;
|
||||||
}
|
}
|
||||||
col += printf("%s%s", (col ? ", " : "\t"), a->name);
|
col += printf("%s%s", (col ? ", " : "\t"), a);
|
||||||
a++;
|
a += strlen(a) + 1;
|
||||||
}
|
}
|
||||||
puts("\n");
|
puts("\n");
|
||||||
return 0;
|
return 0;
|
||||||
@ -629,7 +628,7 @@ static int busybox_main(char **argv)
|
|||||||
bb_error_msg_and_die("applet not found");
|
bb_error_msg_and_die("applet not found");
|
||||||
}
|
}
|
||||||
|
|
||||||
void run_appletstruct_and_exit(const struct bb_applet *applet, char **argv)
|
void run_applet_no_and_exit(int applet_no, char **argv)
|
||||||
{
|
{
|
||||||
int argc = 1;
|
int argc = 1;
|
||||||
|
|
||||||
@ -640,19 +639,19 @@ void run_appletstruct_and_exit(const struct bb_applet *applet, char **argv)
|
|||||||
optind = 1;
|
optind = 1;
|
||||||
xfunc_error_retval = EXIT_FAILURE;
|
xfunc_error_retval = EXIT_FAILURE;
|
||||||
|
|
||||||
applet_name = applet->name;
|
applet_name = APPLET_NAME(applet_no);
|
||||||
if (argc == 2 && !strcmp(argv[1], "--help"))
|
if (argc == 2 && !strcmp(argv[1], "--help"))
|
||||||
bb_show_usage();
|
bb_show_usage();
|
||||||
if (ENABLE_FEATURE_SUID)
|
if (ENABLE_FEATURE_SUID)
|
||||||
check_suid(applet);
|
check_suid(applet_no);
|
||||||
exit(applet->main(argc, argv));
|
exit(applet_mains[applet_no](argc, argv));
|
||||||
}
|
}
|
||||||
|
|
||||||
void run_applet_and_exit(const char *name, char **argv)
|
void run_applet_and_exit(const char *name, char **argv)
|
||||||
{
|
{
|
||||||
const struct bb_applet *applet = find_applet_by_name(name);
|
int applet = find_applet_by_name(name);
|
||||||
if (applet)
|
if (applet >= 0)
|
||||||
run_appletstruct_and_exit(applet, argv);
|
run_applet_no_and_exit(applet, argv);
|
||||||
if (!strncmp(name, "busybox", 7))
|
if (!strncmp(name, "busybox", 7))
|
||||||
exit(busybox_main(argv));
|
exit(busybox_main(argv));
|
||||||
}
|
}
|
||||||
|
@ -65,7 +65,7 @@ int exists_execable(const char *filename)
|
|||||||
*/
|
*/
|
||||||
int bb_execvp(const char *file, char *const argv[])
|
int bb_execvp(const char *file, char *const argv[])
|
||||||
{
|
{
|
||||||
return execvp(find_applet_by_name(file) ? bb_busybox_exec_path : file,
|
return execvp(find_applet_by_name(file) >= 0 ? bb_busybox_exec_path : file,
|
||||||
argv);
|
argv);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
@ -16,7 +16,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include <paths.h>
|
#include <paths.h>
|
||||||
#include "busybox.h" /* for struct bb_applet */
|
#include "busybox.h" /* uses applet tables */
|
||||||
|
|
||||||
/* This does a fork/exec in one call, using vfork(). Returns PID of new child,
|
/* 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. */
|
* -1 for failure. Runs argv[0], searching path if that has no / in it. */
|
||||||
@ -120,11 +120,11 @@ void restore_nofork_data(struct nofork_save_area *save)
|
|||||||
die_sleep = save->die_sleep;
|
die_sleep = save->die_sleep;
|
||||||
}
|
}
|
||||||
|
|
||||||
int run_nofork_applet_prime(struct nofork_save_area *old, const struct bb_applet *a, char **argv)
|
int run_nofork_applet_prime(struct nofork_save_area *old, int applet_no, char **argv)
|
||||||
{
|
{
|
||||||
int rc, argc;
|
int rc, argc;
|
||||||
|
|
||||||
applet_name = a->name;
|
applet_name = APPLET_NAME(applet_no);
|
||||||
xfunc_error_retval = EXIT_FAILURE;
|
xfunc_error_retval = EXIT_FAILURE;
|
||||||
/*option_mask32 = 0; - not needed */
|
/*option_mask32 = 0; - not needed */
|
||||||
/* special flag for xfunc_die(). If xfunc will "die"
|
/* special flag for xfunc_die(). If xfunc will "die"
|
||||||
@ -143,7 +143,7 @@ int run_nofork_applet_prime(struct nofork_save_area *old, const struct bb_applet
|
|||||||
char *tmp_argv[argc+1];
|
char *tmp_argv[argc+1];
|
||||||
memcpy(tmp_argv, argv, (argc+1) * sizeof(tmp_argv[0]));
|
memcpy(tmp_argv, argv, (argc+1) * sizeof(tmp_argv[0]));
|
||||||
/* Finally we can call NOFORK applet's main() */
|
/* Finally we can call NOFORK applet's main() */
|
||||||
rc = a->main(argc, tmp_argv);
|
rc = applet_mains[applet_no](argc, tmp_argv);
|
||||||
} else { /* xfunc died in NOFORK applet */
|
} else { /* xfunc died in NOFORK applet */
|
||||||
/* in case they meant to return 0... */
|
/* in case they meant to return 0... */
|
||||||
if (rc == -2222)
|
if (rc == -2222)
|
||||||
@ -155,13 +155,13 @@ int run_nofork_applet_prime(struct nofork_save_area *old, const struct bb_applet
|
|||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
int run_nofork_applet(const struct bb_applet *a, char **argv)
|
int run_nofork_applet(int applet_no, char **argv)
|
||||||
{
|
{
|
||||||
struct nofork_save_area old;
|
struct nofork_save_area old;
|
||||||
|
|
||||||
/* Saving globals */
|
/* Saving globals */
|
||||||
save_nofork_data(&old);
|
save_nofork_data(&old);
|
||||||
return run_nofork_applet_prime(&old, a, argv);
|
return run_nofork_applet_prime(&old, applet_no, argv);
|
||||||
}
|
}
|
||||||
#endif /* FEATURE_PREFER_APPLETS */
|
#endif /* FEATURE_PREFER_APPLETS */
|
||||||
|
|
||||||
@ -169,15 +169,15 @@ int spawn_and_wait(char **argv)
|
|||||||
{
|
{
|
||||||
int rc;
|
int rc;
|
||||||
#if ENABLE_FEATURE_PREFER_APPLETS
|
#if ENABLE_FEATURE_PREFER_APPLETS
|
||||||
const struct bb_applet *a = find_applet_by_name(argv[0]);
|
int a = find_applet_by_name(argv[0]);
|
||||||
|
|
||||||
if (a && (a->nofork
|
if (a >= 0 && (APPLET_IS_NOFORK(a)
|
||||||
#if BB_MMU
|
#if BB_MMU
|
||||||
|| a->noexec /* NOEXEC trick needs fork() */
|
|| APPLET_IS_NOEXEC(a) /* NOEXEC trick needs fork() */
|
||||||
#endif
|
#endif
|
||||||
)) {
|
)) {
|
||||||
#if BB_MMU
|
#if BB_MMU
|
||||||
if (a->nofork)
|
if (APPLET_IS_NOFORK(a))
|
||||||
#endif
|
#endif
|
||||||
{
|
{
|
||||||
return run_nofork_applet(a, argv);
|
return run_nofork_applet(a, argv);
|
||||||
@ -190,7 +190,7 @@ int spawn_and_wait(char **argv)
|
|||||||
return wait4pid(rc);
|
return wait4pid(rc);
|
||||||
/* child */
|
/* child */
|
||||||
xfunc_error_retval = EXIT_FAILURE;
|
xfunc_error_retval = EXIT_FAILURE;
|
||||||
run_appletstruct_and_exit(a, argv);
|
run_applet_no_and_exit(a, argv);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
#endif /* FEATURE_PREFER_APPLETS */
|
#endif /* FEATURE_PREFER_APPLETS */
|
||||||
|
30
shell/ash.c
30
shell/ash.c
@ -53,7 +53,7 @@
|
|||||||
#if DEBUG
|
#if DEBUG
|
||||||
#define _GNU_SOURCE
|
#define _GNU_SOURCE
|
||||||
#endif
|
#endif
|
||||||
#include "busybox.h" /* for struct bb_applet */
|
#include "busybox.h" /* for applet_names */
|
||||||
#include <paths.h>
|
#include <paths.h>
|
||||||
#include <setjmp.h>
|
#include <setjmp.h>
|
||||||
#include <fnmatch.h>
|
#include <fnmatch.h>
|
||||||
@ -6479,12 +6479,10 @@ tryexec(char *cmd, char **argv, char **envp)
|
|||||||
|
|
||||||
#if ENABLE_FEATURE_SH_STANDALONE
|
#if ENABLE_FEATURE_SH_STANDALONE
|
||||||
if (strchr(cmd, '/') == NULL) {
|
if (strchr(cmd, '/') == NULL) {
|
||||||
const struct bb_applet *a;
|
int a = find_applet_by_name(cmd);
|
||||||
|
if (a >= 0) {
|
||||||
a = find_applet_by_name(cmd);
|
if (APPLET_IS_NOEXEC(a))
|
||||||
if (a) {
|
run_applet_no_and_exit(a, argv);
|
||||||
if (a->noexec)
|
|
||||||
run_appletstruct_and_exit(a, argv);
|
|
||||||
/* re-exec ourselves with the new arguments */
|
/* re-exec ourselves with the new arguments */
|
||||||
execve(bb_busybox_exec_path, argv, envp);
|
execve(bb_busybox_exec_path, argv, envp);
|
||||||
/* If they called chroot or otherwise made the binary no longer
|
/* If they called chroot or otherwise made the binary no longer
|
||||||
@ -6539,7 +6537,7 @@ shellexec(char **argv, const char *path, int idx)
|
|||||||
envp = environment();
|
envp = environment();
|
||||||
if (strchr(argv[0], '/')
|
if (strchr(argv[0], '/')
|
||||||
#if ENABLE_FEATURE_SH_STANDALONE
|
#if ENABLE_FEATURE_SH_STANDALONE
|
||||||
|| find_applet_by_name(argv[0])
|
|| find_applet_by_name(argv[0]) >= 0
|
||||||
#endif
|
#endif
|
||||||
) {
|
) {
|
||||||
tryexec(argv[0], argv, envp);
|
tryexec(argv[0], argv, envp);
|
||||||
@ -11117,7 +11115,7 @@ find_command(char *name, struct cmdentry *entry, int act, const char *path)
|
|||||||
}
|
}
|
||||||
|
|
||||||
#if ENABLE_FEATURE_SH_STANDALONE
|
#if ENABLE_FEATURE_SH_STANDALONE
|
||||||
if (find_applet_by_name(name)) {
|
if (find_applet_by_name(name) >= 0) {
|
||||||
entry->cmdtype = CMDNORMAL;
|
entry->cmdtype = CMDNORMAL;
|
||||||
entry->u.index = -1;
|
entry->u.index = -1;
|
||||||
return;
|
return;
|
||||||
@ -11298,11 +11296,15 @@ helpcmd(int argc, char **argv)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
#if ENABLE_FEATURE_SH_STANDALONE
|
#if ENABLE_FEATURE_SH_STANDALONE
|
||||||
for (i = 0; i < NUM_APPLETS; i++) {
|
{
|
||||||
col += out1fmt("%c%s", ((col == 0) ? '\t' : ' '), applets[i].name);
|
const char *a = applet_names;
|
||||||
if (col > 60) {
|
while (*a) {
|
||||||
out1fmt("\n");
|
col += out1fmt("%c%s", ((col == 0) ? '\t' : ' '), a);
|
||||||
col = 0;
|
if (col > 60) {
|
||||||
|
out1fmt("\n");
|
||||||
|
col = 0;
|
||||||
|
}
|
||||||
|
a += strlen(a) + 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
16
shell/hush.c
16
shell/hush.c
@ -83,7 +83,7 @@
|
|||||||
|
|
||||||
extern char **environ; /* This is in <unistd.h>, but protected with __USE_GNU */
|
extern char **environ; /* This is in <unistd.h>, but protected with __USE_GNU */
|
||||||
|
|
||||||
#include "busybox.h" /* for struct bb_applet */
|
#include "busybox.h" /* for APPLET_IS_NOFORK/NOEXEC */
|
||||||
|
|
||||||
|
|
||||||
#if !BB_MMU
|
#if !BB_MMU
|
||||||
@ -1464,12 +1464,12 @@ static void pseudo_exec_argv(char **argv)
|
|||||||
/* Check if the command matches any busybox applets */
|
/* Check if the command matches any busybox applets */
|
||||||
#if ENABLE_FEATURE_SH_STANDALONE
|
#if ENABLE_FEATURE_SH_STANDALONE
|
||||||
if (strchr(argv[0], '/') == NULL) {
|
if (strchr(argv[0], '/') == NULL) {
|
||||||
const struct bb_applet *a = find_applet_by_name(argv[0]);
|
int a = find_applet_by_name(argv[0]);
|
||||||
if (a) {
|
if (a >= 0) {
|
||||||
if (a->noexec) {
|
if (APPLET_IS_NOEXEC(a)) {
|
||||||
debug_printf_exec("running applet '%s'\n", argv[0]);
|
debug_printf_exec("running applet '%s'\n", argv[0]);
|
||||||
// is it ok that run_appletstruct_and_exit() does exit(), not _exit()?
|
// is it ok that run_applet_no_and_exit() does exit(), not _exit()?
|
||||||
run_appletstruct_and_exit(a, argv);
|
run_applet_no_and_exit(a, argv);
|
||||||
}
|
}
|
||||||
/* re-exec ourselves with the new arguments */
|
/* re-exec ourselves with the new arguments */
|
||||||
debug_printf_exec("re-execing applet '%s'\n", argv[0]);
|
debug_printf_exec("re-execing applet '%s'\n", argv[0]);
|
||||||
@ -1855,8 +1855,8 @@ static int run_pipe_real(struct pipe *pi)
|
|||||||
}
|
}
|
||||||
#if ENABLE_FEATURE_SH_STANDALONE
|
#if ENABLE_FEATURE_SH_STANDALONE
|
||||||
{
|
{
|
||||||
const struct bb_applet *a = find_applet_by_name(argv[i]);
|
int a = find_applet_by_name(argv[i]);
|
||||||
if (a && a->nofork) {
|
if (a >= 0 && APPLET_IS_NOFORK(a)) {
|
||||||
setup_redirects(child, squirrel);
|
setup_redirects(child, squirrel);
|
||||||
save_nofork_data(&nofork_save);
|
save_nofork_data(&nofork_save);
|
||||||
argv_expanded = argv + i;
|
argv_expanded = argv + i;
|
||||||
|
@ -23,7 +23,7 @@
|
|||||||
#include <getopt.h>
|
#include <getopt.h>
|
||||||
#include <glob.h>
|
#include <glob.h>
|
||||||
|
|
||||||
#include "busybox.h" /* for struct bb_applet */
|
#include "libbb.h"
|
||||||
|
|
||||||
#define expand_t glob_t
|
#define expand_t glob_t
|
||||||
|
|
||||||
@ -1253,8 +1253,8 @@ static int run_command(struct job *newjob, int inbg, int outpipe[2])
|
|||||||
}
|
}
|
||||||
#if ENABLE_FEATURE_SH_STANDALONE
|
#if ENABLE_FEATURE_SH_STANDALONE
|
||||||
{
|
{
|
||||||
const struct bb_applet *a = find_applet_by_name(child->argv[i]);
|
int a = find_applet_by_name(child->argv[i]);
|
||||||
if (a && a->nofork) {
|
if (a >= 0 && APPLET_IS_NOFORK(a)) {
|
||||||
setup_redirects(child, squirrel);
|
setup_redirects(child, squirrel);
|
||||||
rcode = run_nofork_applet(a, child->argv + i);
|
rcode = run_nofork_applet(a, child->argv + i);
|
||||||
restore_redirects(squirrel);
|
restore_redirects(squirrel);
|
||||||
|
16
shell/msh.c
16
shell/msh.c
@ -45,9 +45,9 @@
|
|||||||
# define NOT_LONE_DASH(s) ((s)[0] != '-' || (s)[1])
|
# define NOT_LONE_DASH(s) ((s)[0] != '-' || (s)[1])
|
||||||
# define LONE_CHAR(s,c) ((s)[0] == (c) && !(s)[1])
|
# define LONE_CHAR(s,c) ((s)[0] == (c) && !(s)[1])
|
||||||
# define ATTRIBUTE_NORETURN __attribute__ ((__noreturn__))
|
# define ATTRIBUTE_NORETURN __attribute__ ((__noreturn__))
|
||||||
static char *find_applet_by_name(const char *applet)
|
static int find_applet_by_name(const char *applet)
|
||||||
{
|
{
|
||||||
return NULL;
|
return -1;
|
||||||
}
|
}
|
||||||
static char *utoa_to_buf(unsigned n, char *buf, unsigned buflen)
|
static char *utoa_to_buf(unsigned n, char *buf, unsigned buflen)
|
||||||
{
|
{
|
||||||
@ -83,7 +83,7 @@ static char *itoa(int n)
|
|||||||
return local_buf;
|
return local_buf;
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
# include "busybox.h"
|
# include "busybox.h" /* for applet_names */
|
||||||
extern char **environ;
|
extern char **environ;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@ -3057,7 +3057,7 @@ static const char *rexecve(char *c, char **v, char **envp)
|
|||||||
char *name = c;
|
char *name = c;
|
||||||
|
|
||||||
if (ENABLE_FEATURE_SH_STANDALONE) {
|
if (ENABLE_FEATURE_SH_STANDALONE) {
|
||||||
if (find_applet_by_name(name)) {
|
if (find_applet_by_name(name) >= 0) {
|
||||||
/* We have to exec here since we vforked. Running
|
/* We have to exec here since we vforked. Running
|
||||||
* run_applet_and_exit() won't work and bad things
|
* run_applet_and_exit() won't work and bad things
|
||||||
* will happen. */
|
* will happen. */
|
||||||
@ -3188,15 +3188,15 @@ static int dohelp(struct op *t)
|
|||||||
}
|
}
|
||||||
#if ENABLE_FEATURE_SH_STANDALONE
|
#if ENABLE_FEATURE_SH_STANDALONE
|
||||||
{
|
{
|
||||||
const struct bb_applet *applet = applets;
|
const char *applet = applet_names;
|
||||||
|
|
||||||
while (applet->name) {
|
while (*applet) {
|
||||||
col += printf("%c%s", ((col == 0) ? '\t' : ' '), applet->name);
|
col += printf("%c%s", ((col == 0) ? '\t' : ' '), applet);
|
||||||
if (col > 60) {
|
if (col > 60) {
|
||||||
bb_putchar('\n');
|
bb_putchar('\n');
|
||||||
col = 0;
|
col = 0;
|
||||||
}
|
}
|
||||||
applet++;
|
applet += strlen(applet) + 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
Loading…
Reference in New Issue
Block a user