+ pid = fork();
+ if (pid) {
+ if ((-1 != pid) && (-1 != channel[1])) {
+ int child_errno = 0;
+ int bytes = sizeof(int);
+ int n;
+ char *p = (char*)&child_errno;
+ close(channel[1]);
+ /* Try to read child errno from channel. */
+ while ((bytes > 0) &&
+ (n = read(channel[0], p, bytes))) {
+ if (-1 == n) {
+ if (EINTR == errno) {
+ continue;
+ } else {
+ break;
+ }
+ } else {
+ bytes -= n;
+ p += n;
+ }
+ }
+ close(channel[0]);
+ if (child_errno) {
+ int status;
+ waitpid(pid, &status, 0);
+ /* Our convention to tell Lisp that it was the exec or
+ chdir that failed, not the fork. */
+ /* FIXME: there are other values waitpid(2) can return. */
+ if (WIFEXITED(status)) {
+ pid = -WEXITSTATUS(status);
+ }
+ errno = child_errno;
+ }
+ }