logwrapper.c revision 37dc4a51774b9c8a95205cb825eae6753170a851
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 46d18304287dbabc7835be771400b85d4ae8b63de6San Mehat LOG(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'; 54d18304287dbabc7835be771400b85d4ae8b63de6San Mehat LOG(LOG_INFO, tag, &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'; 70d18304287dbabc7835be771400b85d4ae8b63de6San Mehat LOG(LOG_INFO, tag, &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) { 76a1992c9ff3e0d180c1f3042658ab9671d61a2fb8San Mehat LOG(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)) 81d18304287dbabc7835be771400b85d4ae8b63de6San Mehat LOG(LOG_INFO, "logwrapper", "%s terminated by signal %d", tag, 82d18304287dbabc7835be771400b85d4ae8b63de6San Mehat WTERMSIG(status)); 83d18304287dbabc7835be771400b85d4ae8b63de6San Mehat else if (WIFSTOPPED(status)) 84d18304287dbabc7835be771400b85d4ae8b63de6San Mehat LOG(LOG_INFO, "logwrapper", "%s stopped by signal %d", tag, 85d18304287dbabc7835be771400b85d4ae8b63de6San Mehat WSTOPSIG(status)); 86d18304287dbabc7835be771400b85d4ae8b63de6San Mehat } else 87d18304287dbabc7835be771400b85d4ae8b63de6San Mehat LOG(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)) { 100d18304287dbabc7835be771400b85d4ae8b63de6San Mehat LOG(LOG_ERROR, "logwrapper", 101d18304287dbabc7835be771400b85d4ae8b63de6San Mehat "executing %s failed: %s", argv_child[0], strerror(errno)); 102d18304287dbabc7835be771400b85d4ae8b63de6San Mehat exit(-1); 103d18304287dbabc7835be771400b85d4ae8b63de6San Mehat } 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; 112d18304287dbabc7835be771400b85d4ae8b63de6San Mehat char *child_devname = NULL; 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) { 117d18304287dbabc7835be771400b85d4ae8b63de6San Mehat LOG(LOG_ERROR, "logwrapper", "Cannot create parent ptty"); 118d18304287dbabc7835be771400b85d4ae8b63de6San Mehat return -errno; 119d18304287dbabc7835be771400b85d4ae8b63de6San Mehat } 120d18304287dbabc7835be771400b85d4ae8b63de6San Mehat 121d18304287dbabc7835be771400b85d4ae8b63de6San Mehat if (grantpt(parent_ptty) || unlockpt(parent_ptty) || 122d18304287dbabc7835be771400b85d4ae8b63de6San Mehat ((child_devname = (char*)ptsname(parent_ptty)) == 0)) { 12337dc4a51774b9c8a95205cb825eae6753170a851Robert Greenwalt close(parent_ptty); 124d18304287dbabc7835be771400b85d4ae8b63de6San Mehat LOG(LOG_ERROR, "logwrapper", "Problem with /dev/ptmx"); 125d18304287dbabc7835be771400b85d4ae8b63de6San Mehat return -1; 126d18304287dbabc7835be771400b85d4ae8b63de6San Mehat } 127d18304287dbabc7835be771400b85d4ae8b63de6San Mehat 128d18304287dbabc7835be771400b85d4ae8b63de6San Mehat pid = fork(); 129d18304287dbabc7835be771400b85d4ae8b63de6San Mehat if (pid < 0) { 13037dc4a51774b9c8a95205cb825eae6753170a851Robert Greenwalt close(parent_ptty); 131d18304287dbabc7835be771400b85d4ae8b63de6San Mehat LOG(LOG_ERROR, "logwrapper", "Failed to fork"); 132d18304287dbabc7835be771400b85d4ae8b63de6San Mehat return -errno; 133d18304287dbabc7835be771400b85d4ae8b63de6San Mehat } else if (pid == 0) { 134d18304287dbabc7835be771400b85d4ae8b63de6San Mehat child_ptty = open(child_devname, O_RDWR); 135d18304287dbabc7835be771400b85d4ae8b63de6San Mehat if (child_ptty < 0) { 13637dc4a51774b9c8a95205cb825eae6753170a851Robert Greenwalt close(parent_ptty); 137d18304287dbabc7835be771400b85d4ae8b63de6San Mehat LOG(LOG_ERROR, "logwrapper", "Problem with child ptty"); 138d18304287dbabc7835be771400b85d4ae8b63de6San Mehat return -errno; 139d18304287dbabc7835be771400b85d4ae8b63de6San Mehat } 140d18304287dbabc7835be771400b85d4ae8b63de6San Mehat // redirect stdout and stderr 141d18304287dbabc7835be771400b85d4ae8b63de6San Mehat close(parent_ptty); 142d18304287dbabc7835be771400b85d4ae8b63de6San Mehat dup2(child_ptty, 1); 143d18304287dbabc7835be771400b85d4ae8b63de6San Mehat dup2(child_ptty, 2); 144d18304287dbabc7835be771400b85d4ae8b63de6San Mehat close(child_ptty); 145d18304287dbabc7835be771400b85d4ae8b63de6San Mehat 146d18304287dbabc7835be771400b85d4ae8b63de6San Mehat if (background) { 147d18304287dbabc7835be771400b85d4ae8b63de6San Mehat int fd = open("/dev/cpuctl/bg_non_interactive/tasks", O_WRONLY); 148d18304287dbabc7835be771400b85d4ae8b63de6San Mehat 149d18304287dbabc7835be771400b85d4ae8b63de6San Mehat if (fd >=0 ) { 150d18304287dbabc7835be771400b85d4ae8b63de6San Mehat char text[64]; 151d18304287dbabc7835be771400b85d4ae8b63de6San Mehat 152d18304287dbabc7835be771400b85d4ae8b63de6San Mehat sprintf(text, "%d", getpid()); 153d18304287dbabc7835be771400b85d4ae8b63de6San Mehat if (write(fd, text, strlen(text)) < 0) { 154d18304287dbabc7835be771400b85d4ae8b63de6San Mehat LOG(LOG_WARN, "logwrapper", 155d18304287dbabc7835be771400b85d4ae8b63de6San Mehat "Unable to background process (%s)", strerror(errno)); 156d18304287dbabc7835be771400b85d4ae8b63de6San Mehat close(fd); 157d18304287dbabc7835be771400b85d4ae8b63de6San Mehat } 158d18304287dbabc7835be771400b85d4ae8b63de6San Mehat close(fd); 159d18304287dbabc7835be771400b85d4ae8b63de6San Mehat } else { 160d18304287dbabc7835be771400b85d4ae8b63de6San Mehat LOG(LOG_WARN, "logwrapper", 161d18304287dbabc7835be771400b85d4ae8b63de6San Mehat "Unable to background process (%s)", strerror(errno)); 162d18304287dbabc7835be771400b85d4ae8b63de6San Mehat } 163d18304287dbabc7835be771400b85d4ae8b63de6San Mehat } 164d18304287dbabc7835be771400b85d4ae8b63de6San Mehat child(argc, argv); 165d18304287dbabc7835be771400b85d4ae8b63de6San Mehat } else { 16637dc4a51774b9c8a95205cb825eae6753170a851Robert Greenwalt int retValue = parent(argv[0], parent_ptty); 16737dc4a51774b9c8a95205cb825eae6753170a851Robert Greenwalt close(parent_ptty); 16837dc4a51774b9c8a95205cb825eae6753170a851Robert Greenwalt return retValue; 169d18304287dbabc7835be771400b85d4ae8b63de6San Mehat } 170d18304287dbabc7835be771400b85d4ae8b63de6San Mehat 171d18304287dbabc7835be771400b85d4ae8b63de6San Mehat return 0; 172d18304287dbabc7835be771400b85d4ae8b63de6San Mehat} 173