option_mask32 getting trashed.
+ Calling NOEXEC applets
+
+It's the same trusty spawn_and_wait(argv). If FEATURE_PREFER_APPLETS=y,
+it does NOEXEC trick. It resets xfunc_error_retval = 1 and
+logmode = LOGMODE_STDIO in the child.
+
+
Relevant CONFIG options
FEATURE_PREFER_APPLETS
*/
int wait4pid(pid_t pid) FAST_FUNC;
int wait_for_exitstatus(pid_t pid) FAST_FUNC;
+/************************************************************************/
+/* spawn_and_wait/run_nofork_applet/run_applet_no_and_exit need to work */
+/* carefully together to reinit some global state while not disturbing */
+/* other. Be careful if you change them. Consult docs/nofork_noexec.txt */
+/************************************************************************/
/* Same as wait4pid(spawn(argv)), but with NOFORK/NOEXEC if configured: */
int spawn_and_wait(char **argv) FAST_FUNC;
/* Does NOT check that applet is NOFORK, just blindly runs it */
int run_nofork_applet(int applet_no, char **argv) FAST_FUNC;
+#ifndef BUILD_INDIVIDUAL
+extern int find_applet_by_name(const char *name) FAST_FUNC;
+extern void run_applet_no_and_exit(int a, char **argv) NORETURN FAST_FUNC;
+#endif
/* Helpers for daemonization.
*
const struct hwtype *get_hwntype(int type) FAST_FUNC;
-#ifndef BUILD_INDIVIDUAL
-extern int find_applet_by_name(const char *name) FAST_FUNC;
-extern void run_applet_no_and_exit(int a, char **argv) NORETURN FAST_FUNC;
-#endif
-
#ifdef HAVE_MNTENT_H
extern int match_fstype(const struct mntent *mt, const char *fstypes) FAST_FUNC;
extern struct mntent *find_mount_point(const char *name, int subdir_too) FAST_FUNC;
#if ENABLE_FEATURE_PREFER_APPLETS
int a = find_applet_by_name(argv[0]);
- if (a >= 0 && (APPLET_IS_NOFORK(a)
-# if BB_MMU
- || APPLET_IS_NOEXEC(a) /* NOEXEC trick needs fork() */
-# endif
- )) {
-# if BB_MMU
+ if (a >= 0) {
if (APPLET_IS_NOFORK(a))
-# endif
- {
return run_nofork_applet(a, argv);
+# if BB_MMU /* NOEXEC needs fork(), thus this is done only on MMU machines: */
+ if (APPLET_IS_NOEXEC(a)) {
+ fflush_all();
+ rc = fork();
+ if (rc) /* parent or error */
+ return wait4pid(rc);
+
+ /* child */
+ /* reset some state and run without execing */
+
+ /* msg_eol = "\n"; - no caller needs this reinited yet */
+ logmode = LOGMODE_STDIO;
+ /* die_func = NULL; - needed if the caller is a shell,
+ * init, or a NOFORK applet. But none of those call us
+ * as of yet (and that should probably always stay true).
+ */
+ /* xfunc_error_retval and applet_name are init by: */
+ run_applet_no_and_exit(a, argv);
}
-# if BB_MMU
- /* MMU only */
- /* a->noexec is true */
- rc = fork();
- if (rc) /* parent or error */
- return wait4pid(rc);
- /* child */
- xfunc_error_retval = EXIT_FAILURE;
- run_applet_no_and_exit(a, argv);
# endif
}
#endif /* FEATURE_PREFER_APPLETS */