149e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat/*
249e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat * Copyright (C) 2008 The Android Open Source Project
349e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat *
449e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat * Licensed under the Apache License, Version 2.0 (the "License");
549e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat * you may not use this file except in compliance with the License.
649e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat * You may obtain a copy of the License at
749e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat *
849e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat *      http://www.apache.org/licenses/LICENSE-2.0
949e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat *
1049e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat * Unless required by applicable law or agreed to in writing, software
1149e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat * distributed under the License is distributed on an "AS IS" BASIS,
1249e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1349e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat * See the License for the specific language governing permissions and
1449e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat * limitations under the License.
1549e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat */
1649e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat
1749e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat#include <string.h>
1849e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat#include <sys/types.h>
1949e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat#include <sys/wait.h>
2049e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat#include <stdio.h>
2149e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat#include <stdlib.h>
2249e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat#include <unistd.h>
2349e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat#include <errno.h>
2449e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat#include <fcntl.h>
2549e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat
2649e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat#include "private/android_filesystem_config.h"
2749e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat#include "cutils/log.h"
281b4807b19aab60d725078258967d6a8627013a66Glenn Kasten#include "cutils/sched_policy.h"
2949e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat
3049e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehatint parent(const char *tag, int parent_read) {
3149e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat    int status;
3249e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat    char buffer[4096];
3349e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat
3449e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat    int a = 0;  // start index of unprocessed data
3549e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat    int b = 0;  // end index of unprocessed data
3649e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat    int sz;
3749e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat    while ((sz = read(parent_read, &buffer[b], sizeof(buffer) - 1 - b)) > 0) {
3849e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat
3949e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat        sz += b;
4049e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat        // Log one line at a time
4149e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat        for (b = 0; b < sz; b++) {
4249e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat            if (buffer[b] == '\r') {
4349e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat                buffer[b] = '\0';
4449e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat            } else if (buffer[b] == '\n') {
4549e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat                buffer[b] = '\0';
4649e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat
478c4873319a77c54cc198a4e5f4429099ff9da4f7Steve Block                ALOG(LOG_INFO, tag, "%s", &buffer[a]);
4849e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat                a = b + 1;
4949e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat            }
5049e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat        }
5149e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat
5249e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat        if (a == 0 && b == sizeof(buffer) - 1) {
5349e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat            // buffer is full, flush
5449e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat            buffer[b] = '\0';
558c4873319a77c54cc198a4e5f4429099ff9da4f7Steve Block            ALOG(LOG_INFO, tag, "%s", &buffer[a]);
5649e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat            b = 0;
5749e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat        } else if (a != b) {
5849e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat            // Keep left-overs
5949e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat            b -= a;
6049e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat            memmove(buffer, &buffer[a], b);
6149e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat            a = 0;
6249e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat        } else {
6349e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat            a = 0;
6449e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat            b = 0;
6549e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat        }
6649e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat
6749e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat    }
6849e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat    // Flush remaining data
6949e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat    if (a != b) {
7049e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat        buffer[b] = '\0';
718c4873319a77c54cc198a4e5f4429099ff9da4f7Steve Block        ALOG(LOG_INFO, tag, "%s", &buffer[a]);
7249e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat    }
7349e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat    status = 0xAAAA;
7449e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat    if (wait(&status) != -1) {  // Wait for child
7549e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat        if (WIFEXITED(status)) {
761b15d463d4816fc084767cbeda3ee69ff5527545Brad Fitzpatrick            if (WEXITSTATUS(status) != 0) {
778c4873319a77c54cc198a4e5f4429099ff9da4f7Steve Block                ALOG(LOG_INFO, "logwrapper", "%s terminated by exit(%d)", tag,
781b15d463d4816fc084767cbeda3ee69ff5527545Brad Fitzpatrick                        WEXITSTATUS(status));
791b15d463d4816fc084767cbeda3ee69ff5527545Brad Fitzpatrick            }
8049e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat            return WEXITSTATUS(status);
8149e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat        } else if (WIFSIGNALED(status))
828c4873319a77c54cc198a4e5f4429099ff9da4f7Steve Block            ALOG(LOG_INFO, "logwrapper", "%s terminated by signal %d", tag,
8349e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat                    WTERMSIG(status));
8449e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat        else if (WIFSTOPPED(status))
858c4873319a77c54cc198a4e5f4429099ff9da4f7Steve Block            ALOG(LOG_INFO, "logwrapper", "%s stopped by signal %d", tag,
8649e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat                    WSTOPSIG(status));
8749e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat    } else
888c4873319a77c54cc198a4e5f4429099ff9da4f7Steve Block        ALOG(LOG_INFO, "logwrapper", "%s wait() failed: %s (%d)", tag,
8949e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat                strerror(errno), errno);
9049e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat    return -EAGAIN;
9149e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat}
9249e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat
9349e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehatvoid child(int argc, const char**argv) {
9449e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat    // create null terminated argv_child array
9549e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat    char* argv_child[argc + 1];
9649e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat    memcpy(argv_child, argv, argc * sizeof(char *));
9749e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat    argv_child[argc] = NULL;
9849e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat
9949e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat    // XXX: PROTECT FROM VIKING KILLER
10049e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat    if (execv(argv_child[0], argv_child)) {
1018c4873319a77c54cc198a4e5f4429099ff9da4f7Steve Block        ALOG(LOG_ERROR, "logwrapper",
10249e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat            "executing %s failed: %s", argv_child[0], strerror(errno));
10349e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat        exit(-1);
10449e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat    }
10549e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat}
10649e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat
10749e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehatint logwrap(int argc, const char* argv[], int background)
10849e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat{
10949e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat    pid_t pid;
11049e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat
11149e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat    int parent_ptty;
11249e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat    int child_ptty;
11349e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat    char *child_devname = NULL;
11449e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat
11549e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat    /* Use ptty instead of socketpair so that STDOUT is not buffered */
11649e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat    parent_ptty = open("/dev/ptmx", O_RDWR);
11749e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat    if (parent_ptty < 0) {
1188c4873319a77c54cc198a4e5f4429099ff9da4f7Steve Block        ALOG(LOG_ERROR, "logwrapper", "Cannot create parent ptty");
1198c4873319a77c54cc198a4e5f4429099ff9da4f7Steve Block        return -errno;
12049e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat    }
12149e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat
12249e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat    if (grantpt(parent_ptty) || unlockpt(parent_ptty) ||
12349e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat            ((child_devname = (char*)ptsname(parent_ptty)) == 0)) {
1248c940ef7dbd423cadc92982b44a65ed1014389e2San Mehat        close(parent_ptty);
1258c4873319a77c54cc198a4e5f4429099ff9da4f7Steve Block        ALOG(LOG_ERROR, "logwrapper", "Problem with /dev/ptmx");
1268c4873319a77c54cc198a4e5f4429099ff9da4f7Steve Block        return -1;
12749e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat    }
12849e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat
12949e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat    pid = fork();
13049e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat    if (pid < 0) {
1311b15d463d4816fc084767cbeda3ee69ff5527545Brad Fitzpatrick        close(parent_ptty);
1328c4873319a77c54cc198a4e5f4429099ff9da4f7Steve Block        ALOG(LOG_ERROR, "logwrapper", "Failed to fork");
13349e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat        return -errno;
13449e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat    } else if (pid == 0) {
1358c940ef7dbd423cadc92982b44a65ed1014389e2San Mehat        /*
1368c940ef7dbd423cadc92982b44a65ed1014389e2San Mehat         * Child
1378c940ef7dbd423cadc92982b44a65ed1014389e2San Mehat         */
13849e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat        child_ptty = open(child_devname, O_RDWR);
13949e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat        if (child_ptty < 0) {
1401b15d463d4816fc084767cbeda3ee69ff5527545Brad Fitzpatrick            close(parent_ptty);
1418c4873319a77c54cc198a4e5f4429099ff9da4f7Steve Block            ALOG(LOG_ERROR, "logwrapper", "Problem with child ptty");
14249e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat            return -errno;
14349e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat        }
14449e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat
14549e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat        // redirect stdout and stderr
14649e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat        close(parent_ptty);
14749e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat        dup2(child_ptty, 1);
14849e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat        dup2(child_ptty, 2);
14949e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat        close(child_ptty);
15049e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat
15149e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat        if (background) {
1521b4807b19aab60d725078258967d6a8627013a66Glenn Kasten            int err = set_sched_policy(getpid(), SP_BACKGROUND);
1531b4807b19aab60d725078258967d6a8627013a66Glenn Kasten            if (err < 0) {
1548c4873319a77c54cc198a4e5f4429099ff9da4f7Steve Block                ALOG(LOG_WARN, "logwrapper",
1551b4807b19aab60d725078258967d6a8627013a66Glenn Kasten                    "Unable to background process (%s)", strerror(-err));
15649e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat            }
15749e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat        }
15849e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat
15949e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat        child(argc, argv);
16049e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat    } else {
1618c940ef7dbd423cadc92982b44a65ed1014389e2San Mehat        /*
1628c940ef7dbd423cadc92982b44a65ed1014389e2San Mehat         * Parent
1638c940ef7dbd423cadc92982b44a65ed1014389e2San Mehat         */
1648c940ef7dbd423cadc92982b44a65ed1014389e2San Mehat        int rc = parent(argv[0], parent_ptty);
1658c940ef7dbd423cadc92982b44a65ed1014389e2San Mehat        close(parent_ptty);
1668c940ef7dbd423cadc92982b44a65ed1014389e2San Mehat        return rc;
16749e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat    }
16849e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat
16949e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat    return 0;
17049e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat}
171