logwrapper.c revision 8c4873319a77c54cc198a4e5f4429099ff9da4f7
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"
2849e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat
2949e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehatint parent(const char *tag, int parent_read) {
3049e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat    int status;
3149e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat    char buffer[4096];
3249e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat
3349e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat    int a = 0;  // start index of unprocessed data
3449e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat    int b = 0;  // end index of unprocessed data
3549e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat    int sz;
3649e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat    while ((sz = read(parent_read, &buffer[b], sizeof(buffer) - 1 - b)) > 0) {
3749e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat
3849e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat        sz += b;
3949e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat        // Log one line at a time
4049e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat        for (b = 0; b < sz; b++) {
4149e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat            if (buffer[b] == '\r') {
4249e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat                buffer[b] = '\0';
4349e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat            } else if (buffer[b] == '\n') {
4449e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat                buffer[b] = '\0';
4549e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat
468c4873319a77c54cc198a4e5f4429099ff9da4f7Steve Block                ALOG(LOG_INFO, tag, "%s", &buffer[a]);
4749e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat                a = b + 1;
4849e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat            }
4949e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat        }
5049e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat
5149e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat        if (a == 0 && b == sizeof(buffer) - 1) {
5249e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat            // buffer is full, flush
5349e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat            buffer[b] = '\0';
548c4873319a77c54cc198a4e5f4429099ff9da4f7Steve Block            ALOG(LOG_INFO, tag, "%s", &buffer[a]);
5549e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat            b = 0;
5649e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat        } else if (a != b) {
5749e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat            // Keep left-overs
5849e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat            b -= a;
5949e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat            memmove(buffer, &buffer[a], b);
6049e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat            a = 0;
6149e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat        } else {
6249e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat            a = 0;
6349e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat            b = 0;
6449e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat        }
6549e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat
6649e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat    }
6749e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat    // Flush remaining data
6849e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat    if (a != b) {
6949e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat        buffer[b] = '\0';
708c4873319a77c54cc198a4e5f4429099ff9da4f7Steve Block        ALOG(LOG_INFO, tag, "%s", &buffer[a]);
7149e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat    }
7249e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat    status = 0xAAAA;
7349e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat    if (wait(&status) != -1) {  // Wait for child
7449e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat        if (WIFEXITED(status)) {
751b15d463d4816fc084767cbeda3ee69ff5527545Brad Fitzpatrick            if (WEXITSTATUS(status) != 0) {
768c4873319a77c54cc198a4e5f4429099ff9da4f7Steve Block                ALOG(LOG_INFO, "logwrapper", "%s terminated by exit(%d)", tag,
771b15d463d4816fc084767cbeda3ee69ff5527545Brad Fitzpatrick                        WEXITSTATUS(status));
781b15d463d4816fc084767cbeda3ee69ff5527545Brad Fitzpatrick            }
7949e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat            return WEXITSTATUS(status);
8049e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat        } else if (WIFSIGNALED(status))
818c4873319a77c54cc198a4e5f4429099ff9da4f7Steve Block            ALOG(LOG_INFO, "logwrapper", "%s terminated by signal %d", tag,
8249e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat                    WTERMSIG(status));
8349e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat        else if (WIFSTOPPED(status))
848c4873319a77c54cc198a4e5f4429099ff9da4f7Steve Block            ALOG(LOG_INFO, "logwrapper", "%s stopped by signal %d", tag,
8549e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat                    WSTOPSIG(status));
8649e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat    } else
878c4873319a77c54cc198a4e5f4429099ff9da4f7Steve Block        ALOG(LOG_INFO, "logwrapper", "%s wait() failed: %s (%d)", tag,
8849e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat                strerror(errno), errno);
8949e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat    return -EAGAIN;
9049e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat}
9149e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat
9249e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehatvoid child(int argc, const char**argv) {
9349e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat    // create null terminated argv_child array
9449e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat    char* argv_child[argc + 1];
9549e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat    memcpy(argv_child, argv, argc * sizeof(char *));
9649e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat    argv_child[argc] = NULL;
9749e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat
9849e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat    // XXX: PROTECT FROM VIKING KILLER
9949e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat    if (execv(argv_child[0], argv_child)) {
1008c4873319a77c54cc198a4e5f4429099ff9da4f7Steve Block        ALOG(LOG_ERROR, "logwrapper",
10149e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat            "executing %s failed: %s", argv_child[0], strerror(errno));
10249e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat        exit(-1);
10349e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat    }
10449e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat}
10549e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat
10649e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehatint logwrap(int argc, const char* argv[], int background)
10749e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat{
10849e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat    pid_t pid;
10949e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat
11049e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat    int parent_ptty;
11149e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat    int child_ptty;
11249e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat    char *child_devname = NULL;
11349e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat
11449e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat    /* Use ptty instead of socketpair so that STDOUT is not buffered */
11549e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat    parent_ptty = open("/dev/ptmx", O_RDWR);
11649e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat    if (parent_ptty < 0) {
1178c4873319a77c54cc198a4e5f4429099ff9da4f7Steve Block        ALOG(LOG_ERROR, "logwrapper", "Cannot create parent ptty");
1188c4873319a77c54cc198a4e5f4429099ff9da4f7Steve Block        return -errno;
11949e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat    }
12049e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat
12149e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat    if (grantpt(parent_ptty) || unlockpt(parent_ptty) ||
12249e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat            ((child_devname = (char*)ptsname(parent_ptty)) == 0)) {
1238c940ef7dbd423cadc92982b44a65ed1014389e2San Mehat        close(parent_ptty);
1248c4873319a77c54cc198a4e5f4429099ff9da4f7Steve Block        ALOG(LOG_ERROR, "logwrapper", "Problem with /dev/ptmx");
1258c4873319a77c54cc198a4e5f4429099ff9da4f7Steve Block        return -1;
12649e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat    }
12749e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat
12849e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat    pid = fork();
12949e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat    if (pid < 0) {
1301b15d463d4816fc084767cbeda3ee69ff5527545Brad Fitzpatrick        close(parent_ptty);
1318c4873319a77c54cc198a4e5f4429099ff9da4f7Steve Block        ALOG(LOG_ERROR, "logwrapper", "Failed to fork");
13249e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat        return -errno;
13349e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat    } else if (pid == 0) {
1348c940ef7dbd423cadc92982b44a65ed1014389e2San Mehat        /*
1358c940ef7dbd423cadc92982b44a65ed1014389e2San Mehat         * Child
1368c940ef7dbd423cadc92982b44a65ed1014389e2San Mehat         */
13749e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat        child_ptty = open(child_devname, O_RDWR);
13849e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat        if (child_ptty < 0) {
1391b15d463d4816fc084767cbeda3ee69ff5527545Brad Fitzpatrick            close(parent_ptty);
1408c4873319a77c54cc198a4e5f4429099ff9da4f7Steve Block            ALOG(LOG_ERROR, "logwrapper", "Problem with child ptty");
14149e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat            return -errno;
14249e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat        }
14349e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat
14449e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat        // redirect stdout and stderr
14549e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat        close(parent_ptty);
14649e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat        dup2(child_ptty, 1);
14749e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat        dup2(child_ptty, 2);
14849e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat        close(child_ptty);
14949e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat
15049e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat        if (background) {
15149e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat            int fd = open("/dev/cpuctl/bg_non_interactive/tasks", O_WRONLY);
1521b15d463d4816fc084767cbeda3ee69ff5527545Brad Fitzpatrick            if (fd >= 0) {
15349e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat                char text[64];
15449e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat                sprintf(text, "%d", getpid());
15549e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat                if (write(fd, text, strlen(text)) < 0) {
1568c4873319a77c54cc198a4e5f4429099ff9da4f7Steve Block                    ALOG(LOG_WARN, "logwrapper",
15749e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat                        "Unable to background process (%s)", strerror(errno));
15849e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat                }
15949e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat                close(fd);
16049e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat            } else {
1618c4873319a77c54cc198a4e5f4429099ff9da4f7Steve Block                ALOG(LOG_WARN, "logwrapper",
16249e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat                    "Unable to background process (%s)", strerror(errno));
16349e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat            }
16449e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat        }
16549e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat
16649e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat        child(argc, argv);
16749e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat    } else {
1688c940ef7dbd423cadc92982b44a65ed1014389e2San Mehat        /*
1698c940ef7dbd423cadc92982b44a65ed1014389e2San Mehat         * Parent
1708c940ef7dbd423cadc92982b44a65ed1014389e2San Mehat         */
1718c940ef7dbd423cadc92982b44a65ed1014389e2San Mehat        int rc = parent(argv[0], parent_ptty);
1728c940ef7dbd423cadc92982b44a65ed1014389e2San Mehat        close(parent_ptty);
1738c940ef7dbd423cadc92982b44a65ed1014389e2San Mehat        return rc;
17449e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat    }
17549e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat
17649e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat    return 0;
17749e2bce5b74129c26a35e25d4693cbfe98c4688eSan Mehat}
178