1 /* 2 * Copyright (C) 2008 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 #include <string.h> 18 #include <sys/types.h> 19 #include <sys/wait.h> 20 #include <stdio.h> 21 #include <stdlib.h> 22 #include <unistd.h> 23 #include <errno.h> 24 #include <fcntl.h> 25 26 #include "private/android_filesystem_config.h" 27 #include "cutils/log.h" 28 29 int parent(const char *tag, int parent_read) { 30 int status; 31 char buffer[4096]; 32 33 int a = 0; // start index of unprocessed data 34 int b = 0; // end index of unprocessed data 35 int sz; 36 while ((sz = read(parent_read, &buffer[b], sizeof(buffer) - 1 - b)) > 0) { 37 38 sz += b; 39 // Log one line at a time 40 for (b = 0; b < sz; b++) { 41 if (buffer[b] == '\r') { 42 buffer[b] = '\0'; 43 } else if (buffer[b] == '\n') { 44 buffer[b] = '\0'; 45 46 LOG(LOG_INFO, tag, "%s", &buffer[a]); 47 a = b + 1; 48 } 49 } 50 51 if (a == 0 && b == sizeof(buffer) - 1) { 52 // buffer is full, flush 53 buffer[b] = '\0'; 54 LOG(LOG_INFO, tag, &buffer[a]); 55 b = 0; 56 } else if (a != b) { 57 // Keep left-overs 58 b -= a; 59 memmove(buffer, &buffer[a], b); 60 a = 0; 61 } else { 62 a = 0; 63 b = 0; 64 } 65 66 } 67 // Flush remaining data 68 if (a != b) { 69 buffer[b] = '\0'; 70 LOG(LOG_INFO, tag, &buffer[a]); 71 } 72 status = 0xAAAA; 73 if (wait(&status) != -1) { // Wait for child 74 if (WIFEXITED(status)) { 75 LOG(LOG_INFO, "logwrapper", "%s terminated by exit(%d)", tag, 76 WEXITSTATUS(status)); 77 return WEXITSTATUS(status); 78 } else if (WIFSIGNALED(status)) 79 LOG(LOG_INFO, "logwrapper", "%s terminated by signal %d", tag, 80 WTERMSIG(status)); 81 else if (WIFSTOPPED(status)) 82 LOG(LOG_INFO, "logwrapper", "%s stopped by signal %d", tag, 83 WSTOPSIG(status)); 84 } else 85 LOG(LOG_INFO, "logwrapper", "%s wait() failed: %s (%d)", tag, 86 strerror(errno), errno); 87 return -EAGAIN; 88 } 89 90 void child(int argc, const char**argv) { 91 // create null terminated argv_child array 92 char* argv_child[argc + 1]; 93 memcpy(argv_child, argv, argc * sizeof(char *)); 94 argv_child[argc] = NULL; 95 96 // XXX: PROTECT FROM VIKING KILLER 97 if (execv(argv_child[0], argv_child)) { 98 LOG(LOG_ERROR, "logwrapper", 99 "executing %s failed: %s", argv_child[0], strerror(errno)); 100 exit(-1); 101 } 102 } 103 104 int logwrap(int argc, const char* argv[], int background) 105 { 106 pid_t pid; 107 108 int parent_ptty; 109 int child_ptty; 110 char *child_devname = NULL; 111 112 /* Use ptty instead of socketpair so that STDOUT is not buffered */ 113 parent_ptty = open("/dev/ptmx", O_RDWR); 114 if (parent_ptty < 0) { 115 LOG(LOG_ERROR, "logwrapper", "Cannot create parent ptty"); 116 return -errno; 117 } 118 119 if (grantpt(parent_ptty) || unlockpt(parent_ptty) || 120 ((child_devname = (char*)ptsname(parent_ptty)) == 0)) { 121 LOG(LOG_ERROR, "logwrapper", "Problem with /dev/ptmx"); 122 close(parent_ptty); 123 return -1; 124 } 125 126 pid = fork(); 127 if (pid < 0) { 128 LOG(LOG_ERROR, "logwrapper", "Failed to fork"); 129 return -errno; 130 } else if (pid == 0) { 131 /* 132 * Child 133 */ 134 child_ptty = open(child_devname, O_RDWR); 135 if (child_ptty < 0) { 136 LOG(LOG_ERROR, "logwrapper", "Problem with child ptty"); 137 return -errno; 138 } 139 140 // redirect stdout and stderr 141 close(parent_ptty); 142 dup2(child_ptty, 1); 143 dup2(child_ptty, 2); 144 close(child_ptty); 145 146 if (background) { 147 int fd = open("/dev/cpuctl/bg_non_interactive/tasks", O_WRONLY); 148 149 if (fd >=0 ) { 150 char text[64]; 151 152 sprintf(text, "%d", getpid()); 153 if (write(fd, text, strlen(text)) < 0) { 154 LOG(LOG_WARN, "logwrapper", 155 "Unable to background process (%s)", strerror(errno)); 156 close(fd); 157 } 158 close(fd); 159 } else { 160 LOG(LOG_WARN, "logwrapper", 161 "Unable to background process (%s)", strerror(errno)); 162 } 163 } 164 165 child(argc, argv); 166 } else { 167 /* 168 * Parent 169 */ 170 int rc = parent(argv[0], parent_ptty); 171 close(parent_ptty); 172 return rc; 173 } 174 175 return 0; 176 } 177