39fb3966dc75461f473b55d88c1516b6980f7bd8
[busybox-power] / debian / patches / applets-fallback.patch
1 --- a/shell/ash.c
2 +++ b/shell/ash.c
3 @@ -7394,23 +7394,8 @@ static int builtinloc = -1;     /* index
4  
5  
6  static void
7 -tryexec(IF_FEATURE_SH_STANDALONE(int applet_no,) char *cmd, char **argv, char **envp)
8 +tryexec(char *cmd, char **argv, char **envp)
9  {
10 -#if ENABLE_FEATURE_SH_STANDALONE
11 -       if (applet_no >= 0) {
12 -               if (APPLET_IS_NOEXEC(applet_no)) {
13 -                       clearenv();
14 -                       while (*envp)
15 -                               putenv(*envp++);
16 -                       run_applet_no_and_exit(applet_no, argv);
17 -               }
18 -               /* re-exec ourselves with the new arguments */
19 -               execve(bb_busybox_exec_path, argv, envp);
20 -               /* If they called chroot or otherwise made the binary no longer
21 -                * executable, fall through */
22 -       }
23 -#endif
24 -
25   repeat:
26  #ifdef SYSV
27         do {
28 @@ -7471,30 +7456,21 @@ shellexec(char **argv, const char *path,
29         int e;
30         char **envp;
31         int exerrno;
32 -       int applet_no = -1; /* used only by FEATURE_SH_STANDALONE */
33  
34         clearredir(/*drop:*/ 1);
35         envp = listvars(VEXPORT, VUNSET, /*end:*/ NULL);
36 -       if (strchr(argv[0], '/') != NULL
37 -#if ENABLE_FEATURE_SH_STANDALONE
38 -        || (applet_no = find_applet_by_name(argv[0])) >= 0
39 -#endif
40 -       ) {
41 -               tryexec(IF_FEATURE_SH_STANDALONE(applet_no,) argv[0], argv, envp);
42 -               if (applet_no >= 0) {
43 -                       /* We tried execing ourself, but it didn't work.
44 -                        * Maybe /proc/self/exe doesn't exist?
45 -                        * Try $PATH search.
46 -                        */
47 -                       goto try_PATH;
48 -               }
49 +       if (strchr(argv[0], '/') != NULL) {
50 +               tryexec(argv[0], argv, envp);
51                 e = errno;
52         } else {
53 - try_PATH:
54 +#if ENABLE_FEATURE_SH_STANDALONE
55 +               bb_execv_applet(argv[0], argv, envp);
56 +#endif
57 +
58                 e = ENOENT;
59                 while ((cmdname = path_advance(&path, argv[0])) != NULL) {
60                         if (--idx < 0 && pathopt == NULL) {
61 -                               tryexec(IF_FEATURE_SH_STANDALONE(-1,) cmdname, argv, envp);
62 +                               tryexec(cmdname, argv, envp);
63                                 if (errno != ENOENT && errno != ENOTDIR)
64                                         e = errno;
65                         }
66 --- a/libbb/execable.c
67 +++ b/libbb/execable.c
68 @@ -9,6 +9,9 @@
69  
70  #include "libbb.h"
71  
72 +#include <alloca.h>
73 +#include <stdarg.h>
74 +
75  /* check if path points to an executable file;
76   * return 1 if found;
77   * return 0 otherwise;
78 @@ -68,13 +71,60 @@ int FAST_FUNC exists_execable(const char
79  }
80  
81  #if ENABLE_FEATURE_PREFER_APPLETS
82 +int FAST_FUNC bb_execv_applet(const char *name, char *const argv[], char *const envp[])
83 +{
84 +       const char **path = bb_busybox_exec_paths;
85 +
86 +       errno = ENOENT;
87 +
88 +       if (find_applet_by_name(name) < 0)
89 +               return -1;
90 +
91 +       for (; *path; ++path)
92 +               execve(*path, argv, envp);
93 +
94 +       return -1;
95 +}
96 +
97  /* just like the real execvp, but try to launch an applet named 'file' first */
98  int FAST_FUNC BB_EXECVP(const char *file, char *const argv[])
99  {
100 -       if (find_applet_by_name(file) >= 0)
101 -               execvp(bb_busybox_exec_path, argv);
102 +       int ret = bb_execv_applet(file, argv, environ);
103 +       if (errno != ENOENT)
104 +               return ret;
105 +
106         return execvp(file, argv);
107  }
108 +
109 +int FAST_FUNC bb_execlp(const char *file, const char *arg, ...)
110 +{
111 +#define INITIAL_ARGV_MAX 16
112 +       size_t argv_max = INITIAL_ARGV_MAX;
113 +       const char **argv = malloc(argv_max * sizeof (const char *));
114 +       va_list args;
115 +       unsigned int i = 0;
116 +       int ret;
117 +
118 +       va_start (args, arg);
119 +       while (argv[i++] != NULL) {
120 +               if (i == argv_max) {
121 +                       const char **nptr;
122 +                       argv_max *= 2;
123 +                       nptr = realloc (argv, argv_max * sizeof (const char *));
124 +                       if (nptr == NULL)
125 +                               return -1;
126 +                       argv = nptr;
127 +               }
128 +
129 +               argv[i] = va_arg (args, const char *);
130 +       }
131 +       va_end (args);
132 +
133 +       ret = bb_execvp(file, (char *const *)argv);
134 +       free(argv);
135 +
136 +       return ret;
137 +}
138  #endif
139  
140  int FAST_FUNC BB_EXECVP_or_die(char **argv)
141 --- a/libbb/messages.c
142 +++ b/libbb/messages.c
143 @@ -36,6 +36,15 @@ const char bb_msg_standard_output[] ALIG
144  const char bb_hexdigits_upcase[] ALIGN1 = "0123456789ABCDEF";
145  
146  const char bb_busybox_exec_path[] ALIGN1 = CONFIG_BUSYBOX_EXEC_PATH;
147 +const char *bb_busybox_exec_paths[] ALIGN1 = {
148 +#ifdef __linux__
149 +       "/proc/self/exe",
150 +#endif
151 +#ifdef CONFIG_BUSYBOX_EXEC_PATH
152 +       CONFIG_BUSYBOX_EXEC_PATH,
153 +#endif
154 +       NULL
155 +};
156  const char bb_default_login_shell[] ALIGN1 = LIBBB_DEFAULT_LOGIN_SHELL;
157  /* util-linux manpage says /sbin:/bin:/usr/sbin:/usr/bin,
158   * but I want to save a few bytes here. Check libbb.h before changing! */
159 --- a/include/libbb.h
160 +++ b/include/libbb.h   2012-04-22 19:29:26.095992610 +0200
161 @@ -903,13 +903,11 @@ int exists_execable(const char *filename
162   * but it may exec busybox and call applet instead of searching PATH.
163   */
164  #if ENABLE_FEATURE_PREFER_APPLETS
165 -int BB_EXECVP(const char *file, char *const argv[]) FAST_FUNC;
166 -#define BB_EXECLP(prog,cmd,...) \
167 -       do { \
168 -               if (find_applet_by_name(prog) >= 0) \
169 -                       execlp(bb_busybox_exec_path, cmd, __VA_ARGS__); \
170 -               execlp(prog, cmd, __VA_ARGS__); \
171 -       } while (0)
172 +int bb_execv_applet(const char *name, char *const argv[], char *const envp[]) FAST_FUNC;
173 +int bb_execvp(const char *file, char *const argv[]) FAST_FUNC;
174 +int bb_execlp(const char *file, const char *arg, ...) FAST_FUNC;
175 +#define BB_EXECVP(prog,cmd)     bb_execvp(prog,cmd)
176 +#define BB_EXECLP(prog,cmd,...) bb_execlp(prog,cmd, __VA_ARGS__)
177  #else
178  #define BB_EXECVP(prog,cmd)     execvp(prog,cmd)
179  #define BB_EXECLP(prog,cmd,...) execlp(prog,cmd,__VA_ARGS__)
180 @@ -1725,6 +1723,7 @@ extern const char bb_path_wtmp_file[];
181  
182  #define bb_dev_null "/dev/null"
183  extern const char bb_busybox_exec_path[];
184 +extern const char *bb_busybox_exec_paths[];
185  /* util-linux manpage says /sbin:/bin:/usr/sbin:/usr/bin,
186   * but I want to save a few bytes here */
187  extern const char bb_PATH_root_path[]; /* "PATH=/sbin:/usr/sbin:/bin:/usr/bin" */
188 --- a/Config.in
189 +++ b/Config.in
190 @@ -432,13 +432,10 @@ config FEATURE_PREFER_APPLETS
191  
192  config BUSYBOX_EXEC_PATH
193         string "Path to BusyBox executable"
194 -       default "/proc/self/exe"
195 +       default "/bin/busybox"
196         help
197           When Busybox applets need to run other busybox applets, BusyBox
198 -         sometimes needs to exec() itself. When the /proc filesystem is
199 -         mounted, /proc/self/exe always points to the currently running
200 -         executable. If you haven't got /proc, set this to wherever you
201 -         want to run BusyBox from.
202 +         sometimes needs to exec() itself.
203  
204  # These are auto-selected by other options
205  
206 --- a/coreutils/chroot.c
207 +++ b/coreutils/chroot.c
208 @@ -40,5 +40,7 @@ int chroot_main(int argc UNUSED_PARAM, c
209                 /*argv[2] = NULL; - already is */
210         }
211  
212 -       BB_EXECVP_or_die(argv);
213 +       execvp(argv[0], argv);
214 +       xfunc_error_retval = (errno == ENOENT) ? 127 : 126;
215 +       bb_perror_msg_and_die("can't execute '%s'", argv[0]);
216  }