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>