logwrapper.c revision 5ea0c05a1e7d8e664b808aa1bb1efd08fdb2fb13
1d18304287dbabc7835be771400b85d4ae8b63de6San Mehat/*
2d18304287dbabc7835be771400b85d4ae8b63de6San Mehat * Copyright (C) 2008 The Android Open Source Project
3d18304287dbabc7835be771400b85d4ae8b63de6San Mehat *
4d18304287dbabc7835be771400b85d4ae8b63de6San Mehat * Licensed under the Apache License, Version 2.0 (the "License");
5d18304287dbabc7835be771400b85d4ae8b63de6San Mehat * you may not use this file except in compliance with the License.
6d18304287dbabc7835be771400b85d4ae8b63de6San Mehat * You may obtain a copy of the License at
7d18304287dbabc7835be771400b85d4ae8b63de6San Mehat *
8d18304287dbabc7835be771400b85d4ae8b63de6San Mehat *      http://www.apache.org/licenses/LICENSE-2.0
9d18304287dbabc7835be771400b85d4ae8b63de6San Mehat *
10d18304287dbabc7835be771400b85d4ae8b63de6San Mehat * Unless required by applicable law or agreed to in writing, software
11d18304287dbabc7835be771400b85d4ae8b63de6San Mehat * distributed under the License is distributed on an "AS IS" BASIS,
12d18304287dbabc7835be771400b85d4ae8b63de6San Mehat * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13d18304287dbabc7835be771400b85d4ae8b63de6San Mehat * See the License for the specific language governing permissions and
14d18304287dbabc7835be771400b85d4ae8b63de6San Mehat * limitations under the License.
15d18304287dbabc7835be771400b85d4ae8b63de6San Mehat */
16d18304287dbabc7835be771400b85d4ae8b63de6San Mehat
17d18304287dbabc7835be771400b85d4ae8b63de6San Mehat#include <string.h>
18d18304287dbabc7835be771400b85d4ae8b63de6San Mehat#include <sys/types.h>
19d18304287dbabc7835be771400b85d4ae8b63de6San Mehat#include <sys/wait.h>
20d18304287dbabc7835be771400b85d4ae8b63de6San Mehat#include <stdio.h>
21d18304287dbabc7835be771400b85d4ae8b63de6San Mehat#include <stdlib.h>
22d18304287dbabc7835be771400b85d4ae8b63de6San Mehat#include <unistd.h>
23d18304287dbabc7835be771400b85d4ae8b63de6San Mehat#include <errno.h>
24d18304287dbabc7835be771400b85d4ae8b63de6San Mehat#include <fcntl.h>
25d18304287dbabc7835be771400b85d4ae8b63de6San Mehat
26d18304287dbabc7835be771400b85d4ae8b63de6San Mehat#include "private/android_filesystem_config.h"
27d18304287dbabc7835be771400b85d4ae8b63de6San Mehat#include "cutils/log.h"
28d18304287dbabc7835be771400b85d4ae8b63de6San Mehat
29d18304287dbabc7835be771400b85d4ae8b63de6San Mehatint parent(const char *tag, int parent_read) {
30d18304287dbabc7835be771400b85d4ae8b63de6San Mehat    int status;
31d18304287dbabc7835be771400b85d4ae8b63de6San Mehat    char buffer[4096];
32d18304287dbabc7835be771400b85d4ae8b63de6San Mehat
33d18304287dbabc7835be771400b85d4ae8b63de6San Mehat    int a = 0;  // start index of unprocessed data
34d18304287dbabc7835be771400b85d4ae8b63de6San Mehat    int b = 0;  // end index of unprocessed data
35d18304287dbabc7835be771400b85d4ae8b63de6San Mehat    int sz;
36d18304287dbabc7835be771400b85d4ae8b63de6San Mehat    while ((sz = read(parent_read, &buffer[b], sizeof(buffer) - 1 - b)) > 0) {
37d18304287dbabc7835be771400b85d4ae8b63de6San Mehat
38d18304287dbabc7835be771400b85d4ae8b63de6San Mehat        sz += b;
39d18304287dbabc7835be771400b85d4ae8b63de6San Mehat        // Log one line at a time
40d18304287dbabc7835be771400b85d4ae8b63de6San Mehat        for (b = 0; b < sz; b++) {
41d18304287dbabc7835be771400b85d4ae8b63de6San Mehat            if (buffer[b] == '\r') {
42d18304287dbabc7835be771400b85d4ae8b63de6San Mehat                buffer[b] = '\0';
43d18304287dbabc7835be771400b85d4ae8b63de6San Mehat            } else if (buffer[b] == '\n') {
44d18304287dbabc7835be771400b85d4ae8b63de6San Mehat                buffer[b] = '\0';
45d18304287dbabc7835be771400b85d4ae8b63de6San Mehat
46bf91ebf2e205cca5660c1c9306cc10b4fac653e7Steve Block                ALOG(LOG_INFO, tag, "%s", &buffer[a]);
47d18304287dbabc7835be771400b85d4ae8b63de6San Mehat                a = b + 1;
48d18304287dbabc7835be771400b85d4ae8b63de6San Mehat            }
49d18304287dbabc7835be771400b85d4ae8b63de6San Mehat        }
50d18304287dbabc7835be771400b85d4ae8b63de6San Mehat
51d18304287dbabc7835be771400b85d4ae8b63de6San Mehat        if (a == 0 && b == sizeof(buffer) - 1) {
52d18304287dbabc7835be771400b85d4ae8b63de6San Mehat            // buffer is full, flush
53d18304287dbabc7835be771400b85d4ae8b63de6San Mehat            buffer[b] = '\0';
54bf91ebf2e205cca5660c1c9306cc10b4fac653e7Steve Block            ALOG(LOG_INFO, tag, "%s", &buffer[a]);
55d18304287dbabc7835be771400b85d4ae8b63de6San Mehat            b = 0;
56d18304287dbabc7835be771400b85d4ae8b63de6San Mehat        } else if (a != b) {
57d18304287dbabc7835be771400b85d4ae8b63de6San Mehat            // Keep left-overs
58d18304287dbabc7835be771400b85d4ae8b63de6San Mehat            b -= a;
59d18304287dbabc7835be771400b85d4ae8b63de6San Mehat            memmove(buffer, &buffer[a], b);
60d18304287dbabc7835be771400b85d4ae8b63de6San Mehat            a = 0;
61d18304287dbabc7835be771400b85d4ae8b63de6San Mehat        } else {
62d18304287dbabc7835be771400b85d4ae8b63de6San Mehat            a = 0;
63d18304287dbabc7835be771400b85d4ae8b63de6San Mehat            b = 0;
64d18304287dbabc7835be771400b85d4ae8b63de6San Mehat        }
65d18304287dbabc7835be771400b85d4ae8b63de6San Mehat
66d18304287dbabc7835be771400b85d4ae8b63de6San Mehat    }
67d18304287dbabc7835be771400b85d4ae8b63de6San Mehat    // Flush remaining data
68d18304287dbabc7835be771400b85d4ae8b63de6San Mehat    if (a != b) {
69d18304287dbabc7835be771400b85d4ae8b63de6San Mehat        buffer[b] = '\0';
70bf91ebf2e205cca5660c1c9306cc10b4fac653e7Steve Block        ALOG(LOG_INFO, tag, "%s", &buffer[a]);
71d18304287dbabc7835be771400b85d4ae8b63de6San Mehat    }
72d18304287dbabc7835be771400b85d4ae8b63de6San Mehat    status = 0xAAAA;
73d18304287dbabc7835be771400b85d4ae8b63de6San Mehat    if (wait(&status) != -1) {  // Wait for child
74d18304287dbabc7835be771400b85d4ae8b63de6San Mehat        if (WIFEXITED(status)) {
75a1992c9ff3e0d180c1f3042658ab9671d61a2fb8San Mehat            if (WEXITSTATUS(status) != 0) {
76bf91ebf2e205cca5660c1c9306cc10b4fac653e7Steve Block                ALOG(LOG_INFO, "logwrapper", "%s terminated by exit(%d)", tag,
77a1992c9ff3e0d180c1f3042658ab9671d61a2fb8San Mehat                        WEXITSTATUS(status));
78a1992c9ff3e0d180c1f3042658ab9671d61a2fb8San Mehat            }
79d18304287dbabc7835be771400b85d4ae8b63de6San Mehat            return WEXITSTATUS(status);
80d18304287dbabc7835be771400b85d4ae8b63de6San Mehat        } else if (WIFSIGNALED(status))
81bf91ebf2e205cca5660c1c9306cc10b4fac653e7Steve Block            ALOG(LOG_INFO, "logwrapper", "%s terminated by signal %d", tag,
82d18304287dbabc7835be771400b85d4ae8b63de6San Mehat                    WTERMSIG(status));
83d18304287dbabc7835be771400b85d4ae8b63de6San Mehat        else if (WIFSTOPPED(status))
84bf91ebf2e205cca5660c1c9306cc10b4fac653e7Steve Block            ALOG(LOG_INFO, "logwrapper", "%s stopped by signal %d", tag,
85d18304287dbabc7835be771400b85d4ae8b63de6San Mehat                    WSTOPSIG(status));
86d18304287dbabc7835be771400b85d4ae8b63de6San Mehat    } else
87bf91ebf2e205cca5660c1c9306cc10b4fac653e7Steve Block        ALOG(LOG_INFO, "logwrapper", "%s wait() failed: %s (%d)", tag,
88d18304287dbabc7835be771400b85d4ae8b63de6San Mehat                strerror(errno), errno);
89d18304287dbabc7835be771400b85d4ae8b63de6San Mehat    return -EAGAIN;
90d18304287dbabc7835be771400b85d4ae8b63de6San Mehat}
91d18304287dbabc7835be771400b85d4ae8b63de6San Mehat
92d18304287dbabc7835be771400b85d4ae8b63de6San Mehatvoid child(int argc, const char**argv) {
93d18304287dbabc7835be771400b85d4ae8b63de6San Mehat    // create null terminated argv_child array
94d18304287dbabc7835be771400b85d4ae8b63de6San Mehat    char* argv_child[argc + 1];
95d18304287dbabc7835be771400b85d4ae8b63de6San Mehat    memcpy(argv_child, argv, argc * sizeof(char *));
96d18304287dbabc7835be771400b85d4ae8b63de6San Mehat    argv_child[argc] = NULL;
97d18304287dbabc7835be771400b85d4ae8b63de6San Mehat
98d18304287dbabc7835be771400b85d4ae8b63de6San Mehat    // XXX: PROTECT FROM VIKING KILLER
99d18304287dbabc7835be771400b85d4ae8b63de6San Mehat    if (execv(argv_child[0], argv_child)) {
100bf91ebf2e205cca5660c1c9306cc10b4fac653e7Steve Block        ALOG(LOG_ERROR, "logwrapper",
101d18304287dbabc7835be771400b85d4ae8b63de6San Mehat            "executing %s failed: %s", argv_child[0], strerror(errno));
102d18304287dbabc7835be771400b85d4ae8b63de6San Mehat    }
103e7732280e7af281d35f90d7794a31a7f6e10f185Brad Fitzpatrick    _exit(1);
104d18304287dbabc7835be771400b85d4ae8b63de6San Mehat}
105d18304287dbabc7835be771400b85d4ae8b63de6San Mehat
106d18304287dbabc7835be771400b85d4ae8b63de6San Mehatint logwrap(int argc, const char* argv[], int background)
107d18304287dbabc7835be771400b85d4ae8b63de6San Mehat{
108d18304287dbabc7835be771400b85d4ae8b63de6San Mehat    pid_t pid;
109d18304287dbabc7835be771400b85d4ae8b63de6San Mehat
110d18304287dbabc7835be771400b85d4ae8b63de6San Mehat    int parent_ptty;
111d18304287dbabc7835be771400b85d4ae8b63de6San Mehat    int child_ptty;
112e7732280e7af281d35f90d7794a31a7f6e10f185Brad Fitzpatrick    char child_devname[64];  // same size as libc/unistd/ptsname_r.c
113d18304287dbabc7835be771400b85d4ae8b63de6San Mehat
114d18304287dbabc7835be771400b85d4ae8b63de6San Mehat    /* Use ptty instead of socketpair so that STDOUT is not buffered */
115d18304287dbabc7835be771400b85d4ae8b63de6San Mehat    parent_ptty = open("/dev/ptmx", O_RDWR);
116d18304287dbabc7835be771400b85d4ae8b63de6San Mehat    if (parent_ptty < 0) {
117bf91ebf2e205cca5660c1c9306cc10b4fac653e7Steve Block        ALOG(LOG_ERROR, "logwrapper", "Cannot create parent ptty");
118bf91ebf2e205cca5660c1c9306cc10b4fac653e7Steve Block        return -errno;
119d18304287dbabc7835be771400b85d4ae8b63de6San Mehat    }
120d18304287dbabc7835be771400b85d4ae8b63de6San Mehat
121d18304287dbabc7835be771400b85d4ae8b63de6San Mehat    if (grantpt(parent_ptty) || unlockpt(parent_ptty) ||
122e7732280e7af281d35f90d7794a31a7f6e10f185Brad Fitzpatrick            ptsname_r(parent_ptty, child_devname, sizeof(child_devname))) {
12337dc4a51774b9c8a95205cb825eae6753170a851Robert Greenwalt        close(parent_ptty);
124bf91ebf2e205cca5660c1c9306cc10b4fac653e7Steve Block        ALOG(LOG_ERROR, "logwrapper", "Problem with /dev/ptmx");
125bf91ebf2e205cca5660c1c9306cc10b4fac653e7Steve Block        return -1;
126d18304287dbabc7835be771400b85d4ae8b63de6San Mehat    }
127d18304287dbabc7835be771400b85d4ae8b63de6San Mehat
128d18304287dbabc7835be771400b85d4ae8b63de6San Mehat    pid = fork();
129d18304287dbabc7835be771400b85d4ae8b63de6San Mehat    if (pid < 0) {
13037dc4a51774b9c8a95205cb825eae6753170a851Robert Greenwalt        close(parent_ptty);
131bf91ebf2e205cca5660c1c9306cc10b4fac653e7Steve Block        ALOG(LOG_ERROR, "logwrapper", "Failed to fork");
132d18304287dbabc7835be771400b85d4ae8b63de6San Mehat        return -errno;
133d18304287dbabc7835be771400b85d4ae8b63de6San Mehat    } else if (pid == 0) {
134faabd3d839d1503aa4ed82442fbff29ba0c70897Brad Fitzpatrick        /*
135faabd3d839d1503aa4ed82442fbff29ba0c70897Brad Fitzpatrick         * Child
136faabd3d839d1503aa4ed82442fbff29ba0c70897Brad Fitzpatrick         */
137d18304287dbabc7835be771400b85d4ae8b63de6San Mehat        child_ptty = open(child_devname, O_RDWR);
138d18304287dbabc7835be771400b85d4ae8b63de6San Mehat        if (child_ptty < 0) {
13937dc4a51774b9c8a95205cb825eae6753170a851Robert Greenwalt            close(parent_ptty);
140bf91ebf2e205cca5660c1c9306cc10b4fac653e7Steve Block            ALOG(LOG_ERROR, "logwrapper", "Problem with child ptty");
141e7732280e7af281d35f90d7794a31a7f6e10f185Brad Fitzpatrick            _exit(errno < 128 ? errno : 1);  // XXX lame
142d18304287dbabc7835be771400b85d4ae8b63de6San Mehat        }
143faabd3d839d1503aa4ed82442fbff29ba0c70897Brad Fitzpatrick
144d18304287dbabc7835be771400b85d4ae8b63de6San Mehat        // redirect stdout and stderr
145d18304287dbabc7835be771400b85d4ae8b63de6San Mehat        close(parent_ptty);
146d18304287dbabc7835be771400b85d4ae8b63de6San Mehat        dup2(child_ptty, 1);
147d18304287dbabc7835be771400b85d4ae8b63de6San Mehat        dup2(child_ptty, 2);
148d18304287dbabc7835be771400b85d4ae8b63de6San Mehat        close(child_ptty);
149d18304287dbabc7835be771400b85d4ae8b63de6San Mehat
150d18304287dbabc7835be771400b85d4ae8b63de6San Mehat        if (background) {
151d18304287dbabc7835be771400b85d4ae8b63de6San Mehat            int fd = open("/dev/cpuctl/bg_non_interactive/tasks", O_WRONLY);
152faabd3d839d1503aa4ed82442fbff29ba0c70897Brad Fitzpatrick            if (fd >= 0) {
153d18304287dbabc7835be771400b85d4ae8b63de6San Mehat                char text[64];
154d18304287dbabc7835be771400b85d4ae8b63de6San Mehat                sprintf(text, "%d", getpid());
155d18304287dbabc7835be771400b85d4ae8b63de6San Mehat                if (write(fd, text, strlen(text)) < 0) {
156bf91ebf2e205cca5660c1c9306cc10b4fac653e7Steve Block                    ALOG(LOG_WARN, "logwrapper",
157d18304287dbabc7835be771400b85d4ae8b63de6San Mehat                        "Unable to background process (%s)", strerror(errno));
158d18304287dbabc7835be771400b85d4ae8b63de6San Mehat                }
159d18304287dbabc7835be771400b85d4ae8b63de6San Mehat                close(fd);
160d18304287dbabc7835be771400b85d4ae8b63de6San Mehat            } else {
161bf91ebf2e205cca5660c1c9306cc10b4fac653e7Steve Block                ALOG(LOG_WARN, "logwrapper",
162d18304287dbabc7835be771400b85d4ae8b63de6San Mehat                    "Unable to background process (%s)", strerror(errno));
163d18304287dbabc7835be771400b85d4ae8b63de6San Mehat            }
164d18304287dbabc7835be771400b85d4ae8b63de6San Mehat        }
165faabd3d839d1503aa4ed82442fbff29ba0c70897Brad Fitzpatrick
166d18304287dbabc7835be771400b85d4ae8b63de6San Mehat        child(argc, argv);
167d18304287dbabc7835be771400b85d4ae8b63de6San Mehat    } else {
168faabd3d839d1503aa4ed82442fbff29ba0c70897Brad Fitzpatrick        /*
169faabd3d839d1503aa4ed82442fbff29ba0c70897Brad Fitzpatrick         * Parent
170faabd3d839d1503aa4ed82442fbff29ba0c70897Brad Fitzpatrick         */
171faabd3d839d1503aa4ed82442fbff29ba0c70897Brad Fitzpatrick        int rc = parent(argv[0], parent_ptty);
17237dc4a51774b9c8a95205cb825eae6753170a851Robert Greenwalt        close(parent_ptty);
173faabd3d839d1503aa4ed82442fbff29ba0c70897Brad Fitzpatrick        return rc;
174d18304287dbabc7835be771400b85d4ae8b63de6San Mehat    }
175d18304287dbabc7835be771400b85d4ae8b63de6San Mehat
176d18304287dbabc7835be771400b85d4ae8b63de6San Mehat    return 0;
177d18304287dbabc7835be771400b85d4ae8b63de6San Mehat}
1789e5e0ce62e88ddf9a09798eda51b0c270d354c8eJP Abgrall
1799e5e0ce62e88ddf9a09798eda51b0c270d354c8eJP Abgrall/*
1809e5e0ce62e88ddf9a09798eda51b0c270d354c8eJP Abgrall * The following is based off of bionic/libc/unistd/system.c with
1819e5e0ce62e88ddf9a09798eda51b0c270d354c8eJP Abgrall *  modifications to avoid calling /system/bin/sh -c
1829e5e0ce62e88ddf9a09798eda51b0c270d354c8eJP Abgrall */
1839e5e0ce62e88ddf9a09798eda51b0c270d354c8eJP Abgrallextern char **environ;
1849e5e0ce62e88ddf9a09798eda51b0c270d354c8eJP Abgrallint system_nosh(const char *command)
1859e5e0ce62e88ddf9a09798eda51b0c270d354c8eJP Abgrall{
1869e5e0ce62e88ddf9a09798eda51b0c270d354c8eJP Abgrall    pid_t pid;
1879e5e0ce62e88ddf9a09798eda51b0c270d354c8eJP Abgrall    sig_t intsave, quitsave;
1889e5e0ce62e88ddf9a09798eda51b0c270d354c8eJP Abgrall    sigset_t mask, omask;
1899e5e0ce62e88ddf9a09798eda51b0c270d354c8eJP Abgrall    int pstat;
1909e5e0ce62e88ddf9a09798eda51b0c270d354c8eJP Abgrall    char buffer[255];
1919e5e0ce62e88ddf9a09798eda51b0c270d354c8eJP Abgrall    char *argp[32];
1929e5e0ce62e88ddf9a09798eda51b0c270d354c8eJP Abgrall    char *next = buffer;
1939e5e0ce62e88ddf9a09798eda51b0c270d354c8eJP Abgrall    char *tmp;
1949e5e0ce62e88ddf9a09798eda51b0c270d354c8eJP Abgrall    int i = 0;
1959e5e0ce62e88ddf9a09798eda51b0c270d354c8eJP Abgrall
1969e5e0ce62e88ddf9a09798eda51b0c270d354c8eJP Abgrall    if (!command)           /* just checking... */
1979e5e0ce62e88ddf9a09798eda51b0c270d354c8eJP Abgrall        return(1);
1989e5e0ce62e88ddf9a09798eda51b0c270d354c8eJP Abgrall
1999e5e0ce62e88ddf9a09798eda51b0c270d354c8eJP Abgrall    /*
2009e5e0ce62e88ddf9a09798eda51b0c270d354c8eJP Abgrall     * The command to argp splitting is from code that was
2019e5e0ce62e88ddf9a09798eda51b0c270d354c8eJP Abgrall     * reverted in Change: 11b4e9b2
2029e5e0ce62e88ddf9a09798eda51b0c270d354c8eJP Abgrall     */
2039e5e0ce62e88ddf9a09798eda51b0c270d354c8eJP Abgrall    if (strnlen(buffer, sizeof(buffer) - 1) == sizeof(buffer) - 1) {
2045ea0c05a1e7d8e664b808aa1bb1efd08fdb2fb13Steve Block        ALOGE("command line too long while processing: %s", command);
2059e5e0ce62e88ddf9a09798eda51b0c270d354c8eJP Abgrall        errno = E2BIG;
2069e5e0ce62e88ddf9a09798eda51b0c270d354c8eJP Abgrall        return -1;
2079e5e0ce62e88ddf9a09798eda51b0c270d354c8eJP Abgrall    }
2089e5e0ce62e88ddf9a09798eda51b0c270d354c8eJP Abgrall    strcpy(buffer, command); // Command len is already checked.
2099e5e0ce62e88ddf9a09798eda51b0c270d354c8eJP Abgrall    while ((tmp = strsep(&next, " "))) {
2109e5e0ce62e88ddf9a09798eda51b0c270d354c8eJP Abgrall        argp[i++] = tmp;
2119e5e0ce62e88ddf9a09798eda51b0c270d354c8eJP Abgrall        if (i == 32) {
2125ea0c05a1e7d8e664b808aa1bb1efd08fdb2fb13Steve Block            ALOGE("argument overflow while processing: %s", command);
2139e5e0ce62e88ddf9a09798eda51b0c270d354c8eJP Abgrall            errno = E2BIG;
2149e5e0ce62e88ddf9a09798eda51b0c270d354c8eJP Abgrall            return -1;
2159e5e0ce62e88ddf9a09798eda51b0c270d354c8eJP Abgrall        }
2169e5e0ce62e88ddf9a09798eda51b0c270d354c8eJP Abgrall    }
2179e5e0ce62e88ddf9a09798eda51b0c270d354c8eJP Abgrall    argp[i] = NULL;
2189e5e0ce62e88ddf9a09798eda51b0c270d354c8eJP Abgrall
2199e5e0ce62e88ddf9a09798eda51b0c270d354c8eJP Abgrall
2209e5e0ce62e88ddf9a09798eda51b0c270d354c8eJP Abgrall    sigemptyset(&mask);
2219e5e0ce62e88ddf9a09798eda51b0c270d354c8eJP Abgrall    sigaddset(&mask, SIGCHLD);
2229e5e0ce62e88ddf9a09798eda51b0c270d354c8eJP Abgrall    sigprocmask(SIG_BLOCK, &mask, &omask);
2239e5e0ce62e88ddf9a09798eda51b0c270d354c8eJP Abgrall    switch (pid = vfork()) {
2249e5e0ce62e88ddf9a09798eda51b0c270d354c8eJP Abgrall    case -1:                        /* error */
2259e5e0ce62e88ddf9a09798eda51b0c270d354c8eJP Abgrall        sigprocmask(SIG_SETMASK, &omask, NULL);
2269e5e0ce62e88ddf9a09798eda51b0c270d354c8eJP Abgrall        return(-1);
2279e5e0ce62e88ddf9a09798eda51b0c270d354c8eJP Abgrall    case 0:                                 /* child */
2289e5e0ce62e88ddf9a09798eda51b0c270d354c8eJP Abgrall        sigprocmask(SIG_SETMASK, &omask, NULL);
2299e5e0ce62e88ddf9a09798eda51b0c270d354c8eJP Abgrall        execve(argp[0], argp, environ);
2309e5e0ce62e88ddf9a09798eda51b0c270d354c8eJP Abgrall        _exit(127);
2319e5e0ce62e88ddf9a09798eda51b0c270d354c8eJP Abgrall    }
2329e5e0ce62e88ddf9a09798eda51b0c270d354c8eJP Abgrall
2339e5e0ce62e88ddf9a09798eda51b0c270d354c8eJP Abgrall    intsave = (sig_t)  bsd_signal(SIGINT, SIG_IGN);
2349e5e0ce62e88ddf9a09798eda51b0c270d354c8eJP Abgrall    quitsave = (sig_t) bsd_signal(SIGQUIT, SIG_IGN);
2359e5e0ce62e88ddf9a09798eda51b0c270d354c8eJP Abgrall    pid = waitpid(pid, (int *)&pstat, 0);
2369e5e0ce62e88ddf9a09798eda51b0c270d354c8eJP Abgrall    sigprocmask(SIG_SETMASK, &omask, NULL);
2379e5e0ce62e88ddf9a09798eda51b0c270d354c8eJP Abgrall    (void)bsd_signal(SIGINT, intsave);
2389e5e0ce62e88ddf9a09798eda51b0c270d354c8eJP Abgrall    (void)bsd_signal(SIGQUIT, quitsave);
2399e5e0ce62e88ddf9a09798eda51b0c270d354c8eJP Abgrall    return (pid == -1 ? -1 : pstat);
2409e5e0ce62e88ddf9a09798eda51b0c270d354c8eJP Abgrall}
241