aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDenis Vlasenko <vda.linux@googlemail.com>2007-04-14 10:09:57 +0000
committerDenis Vlasenko <vda.linux@googlemail.com>2007-04-14 10:09:57 +0000
commitf5294e1f4c56afb377ada95a7757b28ad3c89086 (patch)
tree95a0c3632c8c2b20fa6b60f1e1a33e4fc4b24d4f
parent16abcd90aefae8bdb9f7d80a555982dba6ca59b5 (diff)
downloadbusybox-f5294e1f4c56afb377ada95a7757b28ad3c89086.tar.gz
hush: use NOFORK applets as appropriate. Net reduction of code size.
-rw-r--r--applets/applets.c30
-rw-r--r--findutils/xargs.c4
-rw-r--r--include/libbb.h64
-rw-r--r--libbb/vfork_daemon_rexec.c89
-rw-r--r--shell/ash.c4
-rw-r--r--shell/hush.c41
-rw-r--r--shell/lash.c7
7 files changed, 125 insertions, 114 deletions
diff --git a/applets/applets.c b/applets/applets.c
index 82a7eeea1..fb37fbea5 100644
--- a/applets/applets.c
+++ b/applets/applets.c
@@ -514,14 +514,14 @@ static void install_links(const char *busybox, int use_symbolic_links)
/* If we were called as "busybox..." */
-static int busybox_main(int argc, char **argv)
+static int busybox_main(char **argv)
{
- if (ENABLE_FEATURE_INSTALLER && argc > 1 && !strcmp(argv[1], "--install")) {
+ if (ENABLE_FEATURE_INSTALLER && argv[1] && !strcmp(argv[1], "--install")) {
int use_symbolic_links = 0;
char *busybox;
/* to use symlinks, or not to use symlinks... */
- if (argc > 2)
+ if (argv[2])
if (strcmp(argv[2], "-s") == 0)
use_symbolic_links = 1;
@@ -537,11 +537,12 @@ static int busybox_main(int argc, char **argv)
/* Deal with --help. Also print help when called with no arguments */
- if (argc == 1 || !strcmp(argv[1], "--help") ) {
- if (argc > 2) {
+ if (!argv[1] || !strcmp(argv[1], "--help") ) {
+ if (argv[2]) {
/* set name for proper "<name>: applet not found" */
applet_name = argv[2];
- run_applet_and_exit(applet_name, 2, argv);
+ argv[2] = NULL;
+ run_applet_and_exit(applet_name, argv);
} else {
const struct bb_applet *a;
int col, output_width;
@@ -582,14 +583,19 @@ static int busybox_main(int argc, char **argv)
} else {
/* we want "<argv[1]>: applet not found", not "busybox: ..." */
applet_name = argv[1];
- run_applet_and_exit(argv[1], argc - 1, argv + 1);
+ run_applet_and_exit(argv[1], argv + 1);
}
bb_error_msg_and_die("applet not found");
}
-void run_current_applet_and_exit(int argc, char **argv)
+void run_current_applet_and_exit(char **argv)
{
+ int argc = 1;
+
+ while (argv[argc])
+ argc++;
+
/* Reinit some shared global data */
optind = 1;
xfunc_error_retval = EXIT_FAILURE;
@@ -602,13 +608,13 @@ void run_current_applet_and_exit(int argc, char **argv)
exit(current_applet->main(argc, argv));
}
-void run_applet_and_exit(const char *name, int argc, char **argv)
+void run_applet_and_exit(const char *name, char **argv)
{
current_applet = find_applet_by_name(name);
if (current_applet)
- run_current_applet_and_exit(argc, argv);
+ run_current_applet_and_exit(argv);
if (!strncmp(name, "busybox", 7))
- exit(busybox_main(argc, argv));
+ exit(busybox_main(argv));
}
@@ -637,6 +643,6 @@ int main(int argc, char **argv)
if (ENABLE_LOCALE_SUPPORT && getpid() != 1)
setlocale(LC_ALL, "");
- run_applet_and_exit(applet_name, argc, argv);
+ run_applet_and_exit(applet_name, argv);
bb_error_msg_and_die("applet not found");
}
diff --git a/findutils/xargs.c b/findutils/xargs.c
index a430e5f3d..b90f44ca4 100644
--- a/findutils/xargs.c
+++ b/findutils/xargs.c
@@ -176,7 +176,7 @@ set:
}
if (!eof_str_detected) {
size_t length = (p - buf);
-
+// TODO: smarter llist_t
cur = xzalloc(sizeof(xlist_t) + length);
cur->data = memcpy(cur + 1, s, length);
cur->length = length;
@@ -247,6 +247,7 @@ static xlist_t *process_stdin(xlist_t *list_arg,
size_t length = (p - buf);
cur = xzalloc(sizeof(xlist_t) + length);
+// TODO: smarter llist_t
cur->data = memcpy(cur + 1, s, length);
cur->length = length;
/*cur->link = NULL;*/
@@ -329,6 +330,7 @@ static xlist_t *process0_stdin(xlist_t *list_arg,
size_t length = (p - buf);
cur = xzalloc(sizeof(xlist_t) + length);
+// TODO: smarter llist_t
cur->data = memcpy(cur + 1, s, length);
cur->length = length;
/*cur->link = NULL;*/
diff --git a/include/libbb.h b/include/libbb.h
index 212b048de..77f1e0a44 100644
--- a/include/libbb.h
+++ b/include/libbb.h
@@ -123,35 +123,6 @@
/* scary. better ideas? (but do *test* them first!) */
#define OFF_T_MAX ((off_t)~((off_t)1 << (sizeof(off_t)*8-1)))
-/* This structure defines protocol families and their handlers. */
-struct aftype {
- const char *name;
- const char *title;
- int af;
- int alen;
- char *(*print) (unsigned char *);
- const char *(*sprint) (struct sockaddr *, int numeric);
- int (*input) (/*int type,*/ const char *bufp, struct sockaddr *);
- void (*herror) (char *text);
- int (*rprint) (int options);
- int (*rinput) (int typ, int ext, char **argv);
-
- /* may modify src */
- int (*getmask) (char *src, struct sockaddr * mask, char *name);
-};
-
-/* This structure defines hardware protocols and their handlers. */
-struct hwtype {
- const char *name;
- const char *title;
- int type;
- int alen;
- char *(*print) (unsigned char *);
- int (*input) (const char *, struct sockaddr *);
- int (*activate) (int fd);
- int suppress_null_addr;
-};
-
/* Some useful definitions */
#undef FALSE
#define FALSE ((int) 0)
@@ -504,6 +475,7 @@ void clear_username_cache(void);
enum { USERNAME_MAX_SIZE = 16 - sizeof(int) };
+struct bb_applet;
int execable_file(const char *name);
char *find_execable(const char *filename);
int exists_execable(const char *filename);
@@ -537,6 +509,8 @@ int wait_nohang(int *wstat);
#define wait_exitcode(w) ((w) >> 8)
#define wait_stopsig(w) ((w) >> 8)
#define wait_stopped(w) (((w) & 127) == 127)
+/* Does NOT check that applet is NOFORK, just blindly runs it */
+int run_nofork_applet(const struct bb_applet *a, char **argv);
/* wait4pid(spawn(argv)) + NOFORK/NOEXEC (if configured) */
int spawn_and_wait(char **argv);
@@ -669,6 +643,33 @@ int bbunpack(char **argv,
int create_icmp_socket(void);
int create_icmp6_socket(void);
/* interface.c */
+/* This structure defines protocol families and their handlers. */
+struct aftype {
+ const char *name;
+ const char *title;
+ int af;
+ int alen;
+ char *(*print) (unsigned char *);
+ const char *(*sprint) (struct sockaddr *, int numeric);
+ int (*input) (/*int type,*/ const char *bufp, struct sockaddr *);
+ void (*herror) (char *text);
+ int (*rprint) (int options);
+ int (*rinput) (int typ, int ext, char **argv);
+
+ /* may modify src */
+ int (*getmask) (char *src, struct sockaddr * mask, char *name);
+};
+/* This structure defines hardware protocols and their handlers. */
+struct hwtype {
+ const char *name;
+ const char *title;
+ int type;
+ int alen;
+ char *(*print) (unsigned char *);
+ int (*input) (const char *, struct sockaddr *);
+ int (*activate) (int fd);
+ int suppress_null_addr;
+};
extern int interface_opt_a;
int display_interfaces(char *ifname);
const struct aftype *get_aftype(const char *name);
@@ -677,11 +678,10 @@ const struct hwtype *get_hwntype(int type);
#ifndef BUILD_INDIVIDUAL
-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_and_exit(const char *name, int argc, char **argv);
-extern void run_current_applet_and_exit(int argc, char **argv) ATTRIBUTE_NORETURN;
+extern void run_applet_and_exit(const char *name, char **argv);
+extern void run_current_applet_and_exit(char **argv) ATTRIBUTE_NORETURN;
#endif
extern int match_fstype(const struct mntent *mt, const char *fstypes);
diff --git a/libbb/vfork_daemon_rexec.c b/libbb/vfork_daemon_rexec.c
index 7dbc152e2..78f3c4ad4 100644
--- a/libbb/vfork_daemon_rexec.c
+++ b/libbb/vfork_daemon_rexec.c
@@ -100,6 +100,52 @@ int wait_pid(int *wstat, int pid)
return r;
}
+int run_nofork_applet(const struct bb_applet *a, char **argv)
+{
+ int rc, argc;
+
+ /* Save some shared globals */
+ const struct bb_applet *old_a = current_applet;
+ int old_x = xfunc_error_retval;
+ uint32_t old_m = option_mask32;
+ int old_sleep = die_sleep;
+
+ current_applet = a;
+ applet_name = a->name;
+ xfunc_error_retval = EXIT_FAILURE;
+ /*option_mask32 = 0; - not needed */
+ /* special flag for xfunc_die(). If xfunc will "die"
+ * in NOFORK applet, xfunc_die() sees negative
+ * die_sleep and longjmp here instead. */
+ die_sleep = -1;
+
+ argc = 1;
+ while (argv[argc])
+ argc++;
+
+ rc = setjmp(die_jmp);
+ if (!rc) {
+ /* Some callers (xargs)
+ * need argv untouched because they free argv[i]! */
+ char *tmp_argv[argc+1];
+ memcpy(tmp_argv, argv, (argc+1) * sizeof(tmp_argv[0]));
+ /* Finally we can call NOFORK applet's main() */
+ rc = a->main(argc, tmp_argv);
+ } else { /* xfunc died in NOFORK applet */
+ /* in case they meant to return 0... */
+ if (rc == -111)
+ rc = 0;
+ }
+
+ /* Restoring globals */
+ current_applet = old_a;
+ applet_name = old_a->name;
+ xfunc_error_retval = old_x;
+ option_mask32 = old_m;
+ die_sleep = old_sleep;
+ return rc;
+}
+
int spawn_and_wait(char **argv)
{
int rc;
@@ -111,50 +157,11 @@ int spawn_and_wait(char **argv)
|| a->noexec /* NOEXEC trick needs fork() */
#endif
)) {
- int argc = 1;
- char **pp = argv;
- while (*++pp)
- argc++;
#if BB_MMU
if (a->nofork)
#endif
{
- /* Save some shared globals */
- const struct bb_applet *old_a = current_applet;
- int old_x = xfunc_error_retval;
- uint32_t old_m = option_mask32;
- int old_sleep = die_sleep;
-
- current_applet = a;
- applet_name = a->name;
- xfunc_error_retval = EXIT_FAILURE;
- /*option_mask32 = 0; - not needed */
- /* special flag for xfunc_die(). If xfunc will "die"
- * in NOFORK applet, xfunc_die() sees negative
- * die_sleep and longjmp here instead. */
- die_sleep = -1;
-
- rc = setjmp(die_jmp);
- if (!rc) {
- /* Some callers (xargs)
- * need argv untouched because they free argv[i]! */
- char *tmp_argv[argc+1];
- memcpy(tmp_argv, argv, (argc+1) * sizeof(tmp_argv[0]));
- /* Finally we can call NOFORK applet's main() */
- rc = a->main(argc, tmp_argv);
- } else { /* xfunc died in NOFORK applet */
- /* in case they meant to return 0... */
- if (rc == -111)
- rc = 0;
- }
-
- /* Restoring globals */
- current_applet = old_a;
- applet_name = old_a->name;
- xfunc_error_retval = old_x;
- option_mask32 = old_m;
- die_sleep = old_sleep;
- return rc;
+ return run_nofork_applet(a, argv);
}
#if BB_MMU
/* MMU only */
@@ -165,7 +172,7 @@ int spawn_and_wait(char **argv)
/* child */
xfunc_error_retval = EXIT_FAILURE;
current_applet = a;
- run_current_applet_and_exit(argc, argv);
+ run_current_applet_and_exit(argv);
#endif
}
#endif /* FEATURE_PREFER_APPLETS */
diff --git a/shell/ash.c b/shell/ash.c
index 63f039df4..90936fcc0 100644
--- a/shell/ash.c
+++ b/shell/ash.c
@@ -6539,10 +6539,8 @@ tryexec(char *cmd, char **argv, char **envp)
a = find_applet_by_name(cmd);
if (a) {
if (a->noexec) {
- char **c = argv;
- while (*c) c++;
current_applet = a;
- run_current_applet_and_exit(c - argv, argv);
+ run_current_applet_and_exit(argv);
}
/* re-exec ourselves with the new arguments */
execve(CONFIG_BUSYBOX_EXEC_PATH, argv, envp);
diff --git a/shell/hush.c b/shell/hush.c
index 035919500..9362e5916 100644
--- a/shell/hush.c
+++ b/shell/hush.c
@@ -765,7 +765,7 @@ static int b_check_space(o_string *o, int len)
* in here, such as setting a maximum string length */
if (o->length + len > o->maxlen) {
char *old_data = o->data;
- /* assert (data == NULL || o->maxlen != 0); */
+ /* assert(data == NULL || o->maxlen != 0); */
o->maxlen += max(2*len, B_CHUNK);
o->data = realloc(o->data, 1 + o->maxlen);
if (o->data == NULL) {
@@ -1113,17 +1113,10 @@ static void pseudo_exec(struct child_prog *child)
* from global_argv[0], but if we are in a chroot, we may not be able
* to find ourself... */
#if ENABLE_FEATURE_SH_STANDALONE
- {
- int argc_l;
- char** argv_l = child->argv;
- char *name = child->argv[0];
-
- /* Count argc for use in a second... */
- for (argc_l = 0; *argv_l; argv_l++, argc_l++)
- continue;
- debug_printf("running applet %s\n", name);
- run_applet_and_exit(name, argc_l, child->argv);
- }
+ debug_printf("running applet %s\n", child->argv[0]);
+ run_applet_and_exit(child->argv[0], child->argv);
+// is it ok that run_applet_and_exit() does exit(), not _exit()?
+// NB: IIRC on NOMMU we are after _vfork_, not fork!
#endif
debug_printf("exec of %s\n", child->argv[0]);
execvp(child->argv[0], child->argv);
@@ -1304,6 +1297,9 @@ static int run_pipe_real(struct pipe *pi)
struct child_prog *child;
const struct built_in_command *x;
char *p;
+ /* it is not always needed, but we aim to smaller code */
+ int squirrel[] = { -1, -1, -1 };
+ int rcode;
nextin = 0;
pi->pgrp = -1;
@@ -1314,8 +1310,6 @@ static int run_pipe_real(struct pipe *pi)
*/
child = &(pi->progs[0]);
if (pi->num_progs == 1 && child->group && child->subshell == 0) {
- int squirrel[] = { -1, -1, -1 };
- int rcode;
debug_printf("non-subshell grouping\n");
setup_redirects(child, squirrel);
/* XXX could we merge code with following builtin case,
@@ -1366,15 +1360,13 @@ static int run_pipe_real(struct pipe *pi)
if (child->sp) {
char *str;
- str = make_string((child->argv + i));
+ str = make_string(child->argv + i);
parse_string_outer(str, FLAG_EXIT_FROM_LOOP | FLAG_REPARSING);
free(str);
return last_return_code;
}
for (x = bltins; x->cmd; x++) {
if (strcmp(child->argv[i], x->cmd) == 0) {
- int squirrel[] = { -1, -1, -1 };
- int rcode;
if (x->function == builtin_exec && child->argv[i+1] == NULL) {
debug_printf("magic exec\n");
setup_redirects(child, NULL);
@@ -1393,6 +1385,17 @@ static int run_pipe_real(struct pipe *pi)
return rcode;
}
}
+#if ENABLE_FEATURE_SH_STANDALONE
+ {
+ const struct bb_applet *a = find_applet_by_name(child->argv[i]);
+ if (a && a->nofork) {
+ setup_redirects(child, squirrel);
+ rcode = run_nofork_applet(a, child->argv + i);
+ restore_redirects(squirrel);
+ return rcode;
+ }
+ }
+#endif
}
for (i = 0; i < pi->num_progs; i++) {
@@ -2587,8 +2590,8 @@ int parse_stream(o_string *dest, struct p_context *ctx,
static void mapset(const char *set, int code)
{
- while (*s)
- map[(unsigned char)*s++] = code;
+ while (*set)
+ map[(unsigned char)*set++] = code;
}
static void update_ifs_map(void)
diff --git a/shell/lash.c b/shell/lash.c
index c74684bf7..6fe2ddc76 100644
--- a/shell/lash.c
+++ b/shell/lash.c
@@ -1158,12 +1158,7 @@ static int pseudo_exec(struct child_prog *child)
* /bin/foo is a symlink to busybox.
*/
if (ENABLE_FEATURE_SH_STANDALONE) {
- char **argv_l = child->argv;
- int argc_l;
-
- for (argc_l = 0; *argv_l; argv_l++, argc_l++)
- continue;
- run_applet_and_exit(child->argv[0], argc_l, child->argv);
+ run_applet_and_exit(child->argv[0], child->argv);
}
execvp(child->argv[0], child->argv);