mirror of
https://github.com/sheumann/hush.git
synced 2025-01-18 07:31:34 +00:00
factor out NOFORK/NOEXEC code from find. Use it for xargs too.
This commit is contained in:
parent
1b4b2cb20e
commit
cd7001f705
@ -238,37 +238,19 @@ ACTF(inum)
|
|||||||
ACTF(exec)
|
ACTF(exec)
|
||||||
{
|
{
|
||||||
int i, rc;
|
int i, rc;
|
||||||
char *argv[ap->exec_argc+1];
|
char *argv[ap->exec_argc + 1];
|
||||||
for (i = 0; i < ap->exec_argc; i++)
|
for (i = 0; i < ap->exec_argc; i++)
|
||||||
argv[i] = subst(ap->exec_argv[i], ap->subst_count[i], fileName);
|
argv[i] = subst(ap->exec_argv[i], ap->subst_count[i], fileName);
|
||||||
argv[i] = NULL; /* terminate the list */
|
argv[i] = NULL; /* terminate the list */
|
||||||
|
|
||||||
if (ENABLE_FEATURE_EXEC_PREFER_APPLETS) {
|
rc = spawn_and_wait(argv);
|
||||||
const struct BB_applet *a = find_applet_by_name(argv[0]);
|
|
||||||
if (a) {
|
|
||||||
if (a->nofork) {
|
|
||||||
rc = a->main(ap->exec_argc, argv);
|
|
||||||
goto f;
|
|
||||||
}
|
|
||||||
#ifndef BB_NOMMU
|
|
||||||
if (a->noexec) {
|
|
||||||
rc = fork();
|
|
||||||
if (rc) goto w;
|
|
||||||
current_applet = a;
|
|
||||||
run_current_applet_and_exit(ap->exec_argc, argv);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
}
|
|
||||||
rc = spawn(argv);
|
|
||||||
w:
|
|
||||||
rc = wait4pid(rc);
|
|
||||||
if (rc < 0)
|
if (rc < 0)
|
||||||
bb_perror_msg("%s", argv[0]);
|
bb_perror_msg("%s", argv[0]);
|
||||||
f:
|
|
||||||
for (i = 0; i < ap->exec_argc; i++)
|
i = 0;
|
||||||
free(argv[i]);
|
while (argv[i])
|
||||||
return rc == 0; /* return 1 if success */
|
free(argv[i++]);
|
||||||
|
return rc == 0; /* return 1 if exitcode 0 */
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -48,47 +48,32 @@
|
|||||||
This function has special algorithm.
|
This function has special algorithm.
|
||||||
Don't use fork and include to main!
|
Don't use fork and include to main!
|
||||||
*/
|
*/
|
||||||
static int xargs_exec(char *const *args)
|
static int xargs_exec(char **args)
|
||||||
{
|
{
|
||||||
pid_t p;
|
|
||||||
volatile int exec_errno = 0; /* shared vfork stack */
|
|
||||||
int status;
|
int status;
|
||||||
|
|
||||||
p = vfork();
|
status = spawn_and_wait(args);
|
||||||
if (p < 0)
|
if (status < 0) {
|
||||||
bb_perror_msg_and_die("vfork");
|
|
||||||
|
|
||||||
if (p == 0) {
|
|
||||||
/* vfork -- child */
|
|
||||||
BB_EXECVP(args[0], args);
|
|
||||||
exec_errno = errno; /* set error to shared stack */
|
|
||||||
_exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* vfork -- parent */
|
|
||||||
while (wait(&status) == (pid_t) -1)
|
|
||||||
if (errno != EINTR)
|
|
||||||
break;
|
|
||||||
if (exec_errno) {
|
|
||||||
errno = exec_errno;
|
|
||||||
bb_perror_msg("%s", args[0]);
|
bb_perror_msg("%s", args[0]);
|
||||||
return exec_errno == ENOENT ? 127 : 126;
|
return errno == ENOENT ? 127 : 126;
|
||||||
}
|
}
|
||||||
if (WEXITSTATUS(status) == 255) {
|
if (status == 255) {
|
||||||
bb_error_msg("%s: exited with status 255; aborting", args[0]);
|
bb_error_msg("%s: exited with status 255; aborting", args[0]);
|
||||||
return 124;
|
return 124;
|
||||||
}
|
}
|
||||||
|
/* Huh? I think we won't see this, ever. We don't wait with WUNTRACED!
|
||||||
if (WIFSTOPPED(status)) {
|
if (WIFSTOPPED(status)) {
|
||||||
bb_error_msg("%s: stopped by signal %d",
|
bb_error_msg("%s: stopped by signal %d",
|
||||||
args[0], WSTOPSIG(status));
|
args[0], WSTOPSIG(status));
|
||||||
return 125;
|
return 125;
|
||||||
}
|
}
|
||||||
if (WIFSIGNALED(status)) {
|
*/
|
||||||
|
if (status >= 1000) {
|
||||||
bb_error_msg("%s: terminated by signal %d",
|
bb_error_msg("%s: terminated by signal %d",
|
||||||
args[0], WTERMSIG(status));
|
args[0], status - 1000);
|
||||||
return 125;
|
return 125;
|
||||||
}
|
}
|
||||||
if (WEXITSTATUS(status))
|
if (status)
|
||||||
return 123;
|
return 123;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -269,17 +269,6 @@ char *xrealloc_getcwd_or_warn(char *cwd);
|
|||||||
char *xmalloc_readlink_or_warn(const char *path);
|
char *xmalloc_readlink_or_warn(const char *path);
|
||||||
char *xmalloc_realpath(const char *path);
|
char *xmalloc_realpath(const char *path);
|
||||||
|
|
||||||
/* Unlike waitpid, waits ONLY for one process,
|
|
||||||
* It's safe to pass negative 'pids' from failed [v]fork -
|
|
||||||
* wait4pid will return -1 and ECHILD in errno.
|
|
||||||
* IOW: rc = wait4pid(spawn(argv));
|
|
||||||
* if (rc < 0) bb_perror_msg("%s", argv[0]);
|
|
||||||
* if (rc > 0) bb_error_msg("exit code: %d", rc);
|
|
||||||
*/
|
|
||||||
extern int wait4pid(int pid);
|
|
||||||
extern int wait_pid(int *wstat, int pid);
|
|
||||||
extern int wait_nohang(int *wstat);
|
|
||||||
//TODO: signal(sid, f) is the same? then why?
|
|
||||||
extern void sig_catch(int,void (*)(int));
|
extern void sig_catch(int,void (*)(int));
|
||||||
//#define sig_ignore(s) (sig_catch((s), SIG_IGN))
|
//#define sig_ignore(s) (sig_catch((s), SIG_IGN))
|
||||||
//#define sig_uncatch(s) (sig_catch((s), SIG_DFL))
|
//#define sig_uncatch(s) (sig_catch((s), SIG_DFL))
|
||||||
@ -288,10 +277,6 @@ extern void sig_unblock(int);
|
|||||||
/* UNUSED: extern void sig_blocknone(void); */
|
/* UNUSED: extern void sig_blocknone(void); */
|
||||||
extern void sig_pause(void);
|
extern void sig_pause(void);
|
||||||
|
|
||||||
#define wait_crashed(w) ((w) & 127)
|
|
||||||
#define wait_exitcode(w) ((w) >> 8)
|
|
||||||
#define wait_stopsig(w) ((w) >> 8)
|
|
||||||
#define wait_stopped(w) (((w) & 127) == 127)
|
|
||||||
|
|
||||||
|
|
||||||
void xsetgid(gid_t gid);
|
void xsetgid(gid_t gid);
|
||||||
@ -528,6 +513,25 @@ int bb_execvp(const char *file, char *const argv[]);
|
|||||||
/* NOMMU friendy fork+exec */
|
/* NOMMU friendy fork+exec */
|
||||||
pid_t spawn(char **argv);
|
pid_t spawn(char **argv);
|
||||||
pid_t xspawn(char **argv);
|
pid_t xspawn(char **argv);
|
||||||
|
|
||||||
|
/* Unlike waitpid, waits ONLY for one process,
|
||||||
|
* It's safe to pass negative 'pids' from failed [v]fork -
|
||||||
|
* wait4pid will return -1 and ECHILD in errno.
|
||||||
|
* IOW: rc = wait4pid(spawn(argv));
|
||||||
|
* if (rc < 0) bb_perror_msg("%s", argv[0]);
|
||||||
|
* if (rc > 0) bb_error_msg("exit code: %d", rc);
|
||||||
|
*/
|
||||||
|
int wait_pid(int *wstat, int pid);
|
||||||
|
int wait_nohang(int *wstat);
|
||||||
|
int wait4pid(int pid);
|
||||||
|
//TODO: signal(sid, f) is the same? then why?
|
||||||
|
#define wait_crashed(w) ((w) & 127)
|
||||||
|
#define wait_exitcode(w) ((w) >> 8)
|
||||||
|
#define wait_stopsig(w) ((w) >> 8)
|
||||||
|
#define wait_stopped(w) (((w) & 127) == 127)
|
||||||
|
/* wait4pid(spawn(argv)) + NOFORK/NOEXEC (if configured) */
|
||||||
|
int spawn_and_wait(char **argv);
|
||||||
|
|
||||||
/* Helpers for daemonization.
|
/* Helpers for daemonization.
|
||||||
*
|
*
|
||||||
* bb_daemonize(flags) = daemonize, does not compile on NOMMU
|
* bb_daemonize(flags) = daemonize, does not compile on NOMMU
|
||||||
@ -573,6 +577,7 @@ void bb_daemonize_or_rexec(int flags, char **argv);
|
|||||||
void bb_sanitize_stdio(void);
|
void bb_sanitize_stdio(void);
|
||||||
|
|
||||||
|
|
||||||
|
// TODO: always error out?
|
||||||
enum { BB_GETOPT_ERROR = 0x80000000 };
|
enum { BB_GETOPT_ERROR = 0x80000000 };
|
||||||
extern const char *opt_complementary;
|
extern const char *opt_complementary;
|
||||||
#if ENABLE_GETOPT_LONG
|
#if ENABLE_GETOPT_LONG
|
||||||
|
@ -16,7 +16,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include <paths.h>
|
#include <paths.h>
|
||||||
#include "libbb.h"
|
#include "busybox.h" /* for struct BB_applet */
|
||||||
|
|
||||||
/* 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. */
|
||||||
@ -72,7 +72,8 @@ int wait4pid(int pid)
|
|||||||
int status;
|
int status;
|
||||||
|
|
||||||
if (pid <= 0) {
|
if (pid <= 0) {
|
||||||
/*errno = ECHILD; -- wrong. we expect errno to be set from failed exec */
|
/*errno = ECHILD; -- wrong. */
|
||||||
|
/* we expect errno to be already set from failed [v]fork/exec */
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
if (waitpid(pid, &status, 0) == -1)
|
if (waitpid(pid, &status, 0) == -1)
|
||||||
@ -80,7 +81,7 @@ int wait4pid(int pid)
|
|||||||
if (WIFEXITED(status))
|
if (WIFEXITED(status))
|
||||||
return WEXITSTATUS(status);
|
return WEXITSTATUS(status);
|
||||||
if (WIFSIGNALED(status))
|
if (WIFSIGNALED(status))
|
||||||
return WTERMSIG(status) + 10000;
|
return WTERMSIG(status) + 1000;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -99,6 +100,41 @@ int wait_pid(int *wstat, int pid)
|
|||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int spawn_and_wait(char **argv)
|
||||||
|
{
|
||||||
|
int rc;
|
||||||
|
|
||||||
|
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 argc = 1;
|
||||||
|
char **pp = argv;
|
||||||
|
while (*++pp)
|
||||||
|
argc++;
|
||||||
|
#ifdef BB_NOMMU
|
||||||
|
return a->main(argc, argv);
|
||||||
|
#else
|
||||||
|
if (a->nofork)
|
||||||
|
return a->main(argc, argv);
|
||||||
|
/* a->noexec is true */
|
||||||
|
rc = fork();
|
||||||
|
if (rc)
|
||||||
|
goto w;
|
||||||
|
/* child */
|
||||||
|
current_applet = a;
|
||||||
|
run_current_applet_and_exit(argc, argv);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
}
|
||||||
|
rc = spawn(argv);
|
||||||
|
w:
|
||||||
|
return wait4pid(rc);
|
||||||
|
}
|
||||||
|
|
||||||
#if 0 //ndef BB_NOMMU
|
#if 0 //ndef BB_NOMMU
|
||||||
// Die with an error message if we can't daemonize.
|
// Die with an error message if we can't daemonize.
|
||||||
void xdaemon(int nochdir, int noclose)
|
void xdaemon(int nochdir, int noclose)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user