[BusyBox] vfork_daemon_rexec
Russ Dill
Russ.Dill at asu.edu
Tue Nov 25 22:19:45 UTC 2003
On Tue, 2003-11-25 at 05:47, Vladimir N. Oleynik wrote:
> Russ,
>
> >>>(btw, vfork_daemon_rexec doesn't work for me, it just says
> >>>f: applet not found)
> >>
> >>Have your argv[0] valid name?
> >
> >
> > char **vfork_args;
> > int a = 0;
> >
> > vfork_args = xcalloc(sizeof(char *), argc + 3);
> > while(*argv) {
> > vfork_args[a++] = *argv;
> > argv++;
> > }
> > vfork_args[a] = foreground_opt;
> > execvp("/proc/self/exe", vfork_args);
>
> > vfork_args[0] = "/bin/busybox";
> > execv(vfork_args[0], vfork_args);
>
> Ok. This two line must change to one line (not tested, only idea):
> execv("bin/busybox", vfork_args);
>
> > bb_perror_msg_and_die("execv %s", vfork_args[0]);
> >
> > argv[0] will always be /bin/busybox. argv[1] will probably be foreground
> > op. (execvp falls through since /proc/self/exe isn't implemented)
> >
> > thus the command would be:
> >
> > /bin/busybox -f
>
> busybox applet is not daemon and don`t call vfork_rexec().
> Your argv[0] must have daemon name always or this strange problem.
This is the behavior with inetd. Thats what the code does. It fails the
execvp, then proceeds to set argv[0] to /bin/busybox (overwriting the
string inetd), and sets argv[1] to -f. busybox then sees argv[0] as
busybox, so it looks to agrv[1] to find the applet name. It finds -f.
There are a lot of other problems as well. All the applets using
vfork_daemon_rexec also call daemon, which returns after a failed fork
on uclinux (does nothing). A working vfork_daemon_rexec might look like
this:
void vfork_daemon_rexec(int nochdir, int noclose,
int argc, char **argv, char *foreground_opt)
{
int fd;
char **vfork_args;
int a = 0;
if (setsid() == -1)
return(-1);
if (!nochdir)
chdir("/");
if (!noclose && (fd = open(_PATH_DEVNULL, O_RDWR, 0)) != -1) {
dup2(fd, STDIN_FILENO);
dup2(fd, STDOUT_FILENO);
dup2(fd, STDERR_FILENO);
if (fd > 2)
close(fd);
}
vfork_args = xcalloc(sizeof(char *), argc + 3);
vfork_args[a++] = "/bin/busybox";
while(*argv) {
vfork_args[a++] = *argv;
argv++;
}
vfork_args[a++] = foreground_opt;
vfork_args[a] = NULL;
switch (vfork()) {
case 0: /* child */
/* Make certain we are not a session leader, or else we
* might reacquire a controlling terminal */
if (vfork())
_exit(0);
execv(vfork_args[0], vfork_args);
bb_perror_msg_and_die("execv %s", vfork_args[0]);
case -1: /* error */
bb_perror_msg_and_die("vfork");
default: /* parent */
exit(0);
}
}
--
Russ Dill <Russ.Dill at asu.edu>
More information about the busybox
mailing list