From owner-cvs-all Tue Mar 21 22: 3:59 2000 Delivered-To: cvs-all@freebsd.org Received: from 1Cust102.tnt1.washington.dc.da.uu.net (localhost [127.0.0.1]) by hub.freebsd.org (Postfix) with ESMTP id ED4F237BCCD; Tue, 21 Mar 2000 22:03:48 -0800 (PST) (envelope-from green@FreeBSD.org) Date: Wed, 22 Mar 2000 01:03:46 -0500 (EST) From: Brian Fundakowski Feldman X-Sender: green@green.dyndns.org To: Brian Somers Cc: cvs-committers@FreeBSD.org, cvs-all@FreeBSD.org Subject: Ultimate Re: cvs commit: src/usr.sbin/ppp exec.c In-Reply-To: Message-ID: MIME-Version: 1.0 Content-Type: TEXT/PLAIN; charset=US-ASCII Sender: owner-cvs-all@FreeBSD.ORG Precedence: bulk X-Loop: FreeBSD.ORG > > 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() ? Finally! I have what I think is exactly what you want. Here's the test output: {"/home/green"}$ cc -DCASEONE -O -o bar bar.c {"/home/green"}$ ./bar Hey, dad! Lemme exec something impossible. Wait completed for pid 22969. Child exec failed (13). {"/home/green"}$ cc -UCASEONE -O -o bar bar.c {"/home/green"}$ ./bar Okay, I'll exec something good now. Wait completed for pid 22976. Child exec succeeded, exited with status 42. #include #include #include #include #include #include #include #include int main() { int pipes[2]; int error, i; fd_set readset; struct timeval tv = { 0, 0 }; int status; char data[sizeof(int)]; char *const impossible[] = { "/", NULL }; char *const test[] = { "sh", "-c", "exit 42", NULL }; error = pipe(pipes); if (error != 0) err(1, "pipe"); if (fcntl(pipes[0], F_SETFD, 1) != 0 || fcntl(pipes[1], F_SETFD, 1) != 0) err(1, "fcntl"); switch (fork()) { default: error = wait(&status); if (error == -1) err(1, "wait"); printf("Wait completed for pid %d.\n", error); FD_ZERO(&readset); FD_SET(pipes[0], &readset); error = select(pipes[0] + 1, &readset, NULL, NULL, &tv); switch (error) { case -1: err(1, "select"); case 0: printf("Child exec succeeded, "); if (WIFEXITED(status)) printf("exited with status %d.\n", WEXITSTATUS(status)); else if (WIFSIGNALED(status)) printf("exited on signal %d.\n", WTERMSIG(status)); else printf("stoped on signal %d.\n", WSTOPSIG(status)); 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: #ifdef CASEONE printf("Hey, dad! Lemme exec something impossible.\n"); (void)execve(*impossible, impossible, NULL); *(int *)data = errno; if (write(pipes[1], data, sizeof(data)) != sizeof(data)) err(1, "child write"); #else printf("Okay, I'll exec something good now.\n"); if (execve("/bin/sh", test, NULL) != 0) err(1, "execve"); #endif 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