Date: Wed, 22 Mar 2000 00:17:03 -0500 (EST) From: Brian Fundakowski Feldman <green@FreeBSD.org> To: Brian Somers <brian@FreeBSD.org> Cc: cvs-committers@FreeBSD.org, cvs-all@FreeBSD.org Subject: Re: cvs commit: src/usr.sbin/ppp exec.c Message-ID: <Pine.BSF.4.21.0003220010290.20622-100000@green.dyndns.org> In-Reply-To: <Pine.BSF.4.21.0003212327250.11563-100000@green.dyndns.org>
next in thread | previous in thread | raw e-mail | index | archive | help
On Tue, 21 Mar 2000, Brian Fundakowski Feldman wrote:
> On Tue, 21 Mar 2000, Brian Somers wrote:
>
> > FWIW:
> > I tried to implement this by doing a pipe(), setting the
> > write desciptors close-on-exec flag in the child and writing
> > errno to the descriptor if the exec() fails. The parent can
> > then ``if (read()) got errno else exec worked''.
> >
> > This didn't work though - the child could write() to fd[1] on
> > exec failure, but the parent got 0 trying to read() from fd[0] !
> > Is this a bug in execve() ?
I don't get that problem, exactly, since the parent gets the right
read for me, not 0. It's not an easy problem you're trying to
solve, and I wish I could think of a better way than this. Why do
you really care the difference between exec failing and the program
which was execed failing?
Here's a much better example of how it's possible to do what you want:
{"/home/green"}$ ./bar
Hey, dad! Lemme exec something impossible.
Child exec failed (4186).
Okay, I'll exec something good now.
hello
Child exec succeeded.
#include <sys/types.h>
#include <sys/time.h>
#include <err.h>
#include <stdio.h>
#include <unistd.h>
int
main() {
fd_set readset;
struct timeval tv;
int pipes[2];
int error, i;
char data[sizeof(int)];
char *const impossible[] = { "/", NULL };
char *const echo[] = { "echo", "hello", NULL };
error = pipe(pipes);
if (error != 0)
err(1, "pipe");
switch (fork()) {
default:
for (i = 0; i < 2; i++) {
FD_ZERO(&readset);
FD_SET(pipes[0], &readset);
tv.tv_sec = 0;
tv.tv_usec = 100000;
error = select(pipes[0] + 1, &readset, NULL, NULL, &tv);
switch (error) {
case -1:
err(1, "select");
case 0:
printf("Child exec succeeded.\n");
break;
case 1:
if (read(pipes[0], data, sizeof(data)) !=
sizeof(data))
err(1, "parent read");
printf("Child exec failed (%d).\n",
*(int *)data);
}
}
exit(0);
case -1:
err(1, "fork");
case 0:
setsid();
printf("Hey, dad! Lemme exec something impossible.\n");
(void)execve(*impossible, impossible, NULL);
*(int *)data = 4186;
if (write(pipes[1], data, sizeof(data)) != sizeof(data))
err(1, "child write");
printf("Okay, I'll exec something good now.\n");
if (execve("/bin/echo", echo, NULL) != 0)
err(1, "execve");
exit(0);
}
}
--
Brian Fundakowski Feldman \ FreeBSD: The Power to Serve! /
green@FreeBSD.org `------------------------------'
To Unsubscribe: send mail to majordomo@FreeBSD.org
with "unsubscribe cvs-all" in the body of the message
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?Pine.BSF.4.21.0003220010290.20622-100000>
