blob: bf9197759eea64f1e6268a8208bf373e98046ce9 [file] [log] [blame]
Rom Lemarchand113bd472013-01-10 15:21:18 -08001/*
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>
Rom Lemarchand0cc2cab2013-01-16 12:08:04 -080019#include <sys/socket.h>
Rom Lemarchandb58a8222013-01-09 21:31:25 -080020#include <poll.h>
Rom Lemarchand113bd472013-01-10 15:21:18 -080021#include <sys/wait.h>
22#include <stdio.h>
23#include <stdlib.h>
24#include <unistd.h>
25#include <errno.h>
26#include <fcntl.h>
27#include <libgen.h>
Rom Lemarchand0cc2cab2013-01-16 12:08:04 -080028#include <stdbool.h>
Rom Lemarchand74a7b912013-03-11 14:00:58 -070029#include <pthread.h>
Rom Lemarchand113bd472013-01-10 15:21:18 -080030
31#include <logwrap/logwrap.h>
32#include "private/android_filesystem_config.h"
33#include "cutils/log.h"
34
JP Abgralla689d132013-02-13 16:31:58 -080035#define ARRAY_SIZE(x) (sizeof(x) / sizeof(*(x)))
Rom Lemarchandb58a8222013-01-09 21:31:25 -080036
Rom Lemarchand74a7b912013-03-11 14:00:58 -070037static pthread_mutex_t fd_mutex = PTHREAD_MUTEX_INITIALIZER;
Rom Lemarchand0cc2cab2013-01-16 12:08:04 -080038
Rom Lemarchand2a46bfa2013-01-29 11:44:59 -080039#define ERROR(fmt, args...) \
Rom Lemarchand99e19662013-01-07 15:50:02 -080040do { \
Rom Lemarchand2a46bfa2013-01-29 11:44:59 -080041 fprintf(stderr, fmt, ## args); \
42 ALOG(LOG_ERROR, "logwrapper", fmt, ## args); \
Rom Lemarchand99e19662013-01-07 15:50:02 -080043} while(0)
44
Rom Lemarchand2a46bfa2013-01-29 11:44:59 -080045#define FATAL_CHILD(fmt, args...) \
Rom Lemarchand99e19662013-01-07 15:50:02 -080046do { \
Rom Lemarchand2a46bfa2013-01-29 11:44:59 -080047 ERROR(fmt, ## args); \
Rom Lemarchand99e19662013-01-07 15:50:02 -080048 _exit(-1); \
49} while(0)
Rom Lemarchand113bd472013-01-10 15:21:18 -080050
Rom Lemarchand6ad53df2013-03-20 13:46:53 -070051static int parent(const char *tag, int parent_read, pid_t pid, int *chld_sts,
52 bool logwrap) {
Rom Lemarchand0cc2cab2013-01-16 12:08:04 -080053 int status = 0;
Rom Lemarchand113bd472013-01-10 15:21:18 -080054 char buffer[4096];
Rom Lemarchandb58a8222013-01-09 21:31:25 -080055 struct pollfd poll_fds[] = {
56 [0] = {
Rom Lemarchand0cc2cab2013-01-16 12:08:04 -080057 .fd = parent_read,
58 .events = POLLIN,
59 },
Rom Lemarchandb58a8222013-01-09 21:31:25 -080060 };
Rom Lemarchand0cc2cab2013-01-16 12:08:04 -080061 int rc = 0;
Rom Lemarchand113bd472013-01-10 15:21:18 -080062
63 int a = 0; // start index of unprocessed data
64 int b = 0; // end index of unprocessed data
65 int sz;
Rom Lemarchand0cc2cab2013-01-16 12:08:04 -080066 bool found_child = false;
Rom Lemarchand113bd472013-01-10 15:21:18 -080067
68 char *btag = basename(tag);
69 if (!btag) btag = (char*) tag;
70
Rom Lemarchand0cc2cab2013-01-16 12:08:04 -080071 while (!found_child) {
Rom Lemarchand6ad53df2013-03-20 13:46:53 -070072 if (TEMP_FAILURE_RETRY(poll(poll_fds, ARRAY_SIZE(poll_fds), -1)) < 0) {
Rom Lemarchand2a46bfa2013-01-29 11:44:59 -080073 ERROR("poll failed\n");
Rom Lemarchand0cc2cab2013-01-16 12:08:04 -080074 rc = -1;
75 goto err_poll;
Rom Lemarchandb58a8222013-01-09 21:31:25 -080076 }
Rom Lemarchand113bd472013-01-10 15:21:18 -080077
Rom Lemarchand6ad53df2013-03-20 13:46:53 -070078 if (poll_fds[0].revents & POLLIN) {
79 sz = read(parent_read, &buffer[b], sizeof(buffer) - 1 - b);
Rom Lemarchandb58a8222013-01-09 21:31:25 -080080
Rom Lemarchand6ad53df2013-03-20 13:46:53 -070081 sz += b;
82 // Log one line at a time
83 for (b = 0; b < sz; b++) {
84 if (buffer[b] == '\r') {
85 buffer[b] = '\0';
86 } else if (buffer[b] == '\n') {
Rom Lemarchandb58a8222013-01-09 21:31:25 -080087 buffer[b] = '\0';
Rom Lemarchand2a46bfa2013-01-29 11:44:59 -080088 if (logwrap)
Rom Lemarchandf5200c02013-01-24 10:57:44 -080089 ALOG(LOG_INFO, btag, "%s", &buffer[a]);
Rom Lemarchand6ad53df2013-03-20 13:46:53 -070090 a = b + 1;
Rom Lemarchandb58a8222013-01-09 21:31:25 -080091 }
92 }
93
Rom Lemarchand6ad53df2013-03-20 13:46:53 -070094 if (a == 0 && b == sizeof(buffer) - 1) {
95 // buffer is full, flush
96 buffer[b] = '\0';
97 if (logwrap)
98 ALOG(LOG_INFO, btag, "%s", &buffer[a]);
99 b = 0;
100 } else if (a != b) {
101 // Keep left-overs
102 b -= a;
103 memmove(buffer, &buffer[a], b);
104 a = 0;
105 } else {
106 a = 0;
107 b = 0;
Rom Lemarchand113bd472013-01-10 15:21:18 -0800108 }
109 }
110
Rom Lemarchand6ad53df2013-03-20 13:46:53 -0700111 if (poll_fds[0].revents & POLLHUP) {
Rom Lemarchand0cc2cab2013-01-16 12:08:04 -0800112 int ret;
Rom Lemarchand113bd472013-01-10 15:21:18 -0800113
Rom Lemarchand6ad53df2013-03-20 13:46:53 -0700114 ret = waitpid(pid, &status, WNOHANG);
115 if (ret < 0) {
116 rc = errno;
117 ALOG(LOG_ERROR, "logwrap", "waitpid failed with %s\n", strerror(errno));
118 goto err_waitpid;
119 }
120 if (ret > 0) {
121 found_child = true;
Rom Lemarchandb58a8222013-01-09 21:31:25 -0800122 }
Rom Lemarchandb58a8222013-01-09 21:31:25 -0800123 }
Rom Lemarchand113bd472013-01-10 15:21:18 -0800124 }
Rom Lemarchandb58a8222013-01-09 21:31:25 -0800125
JP Abgralla689d132013-02-13 16:31:58 -0800126 if (chld_sts != NULL) {
127 *chld_sts = status;
128 } else {
129 if (WIFEXITED(status))
130 rc = WEXITSTATUS(status);
131 else
132 rc = -ECHILD;
Rom Lemarchand113bd472013-01-10 15:21:18 -0800133 }
134
JP Abgralla689d132013-02-13 16:31:58 -0800135 if (logwrap) {
136 // Flush remaining data
137 if (a != b) {
138 buffer[b] = '\0';
139 ALOG(LOG_INFO, btag, "%s", &buffer[a]);
140 }
141 if (WIFEXITED(status)) {
Rom Lemarchand2a46bfa2013-01-29 11:44:59 -0800142 if (WEXITSTATUS(status))
JP Abgralla689d132013-02-13 16:31:58 -0800143 ALOG(LOG_INFO, "logwrapper", "%s terminated by exit(%d)", btag,
144 WEXITSTATUS(status));
145 } else {
Rom Lemarchand2f34c502013-02-07 15:43:09 -0800146 if (WIFSIGNALED(status))
JP Abgralla689d132013-02-13 16:31:58 -0800147 ALOG(LOG_INFO, "logwrapper", "%s terminated by signal %d", btag,
148 WTERMSIG(status));
Rom Lemarchand2f34c502013-02-07 15:43:09 -0800149 else if (WIFSTOPPED(status))
JP Abgralla689d132013-02-13 16:31:58 -0800150 ALOG(LOG_INFO, "logwrapper", "%s stopped by signal %d", btag,
151 WSTOPSIG(status));
152 }
Rom Lemarchandb58a8222013-01-09 21:31:25 -0800153 }
Rom Lemarchandb58a8222013-01-09 21:31:25 -0800154
Rom Lemarchand6ad53df2013-03-20 13:46:53 -0700155err_waitpid:
Rom Lemarchand0cc2cab2013-01-16 12:08:04 -0800156err_poll:
157 return rc;
Rom Lemarchand113bd472013-01-10 15:21:18 -0800158}
159
Rom Lemarchand2a46bfa2013-01-29 11:44:59 -0800160static void child(int argc, char* argv[], bool logwrap) {
Rom Lemarchand113bd472013-01-10 15:21:18 -0800161 // create null terminated argv_child array
162 char* argv_child[argc + 1];
163 memcpy(argv_child, argv, argc * sizeof(char *));
164 argv_child[argc] = NULL;
165
166 if (execvp(argv_child[0], argv_child)) {
Rom Lemarchand2a46bfa2013-01-29 11:44:59 -0800167 FATAL_CHILD("executing %s failed: %s\n", argv_child[0],
Rom Lemarchand99e19662013-01-07 15:50:02 -0800168 strerror(errno));
Rom Lemarchand113bd472013-01-10 15:21:18 -0800169 }
170}
171
Rom Lemarchand2a46bfa2013-01-29 11:44:59 -0800172int android_fork_execvp(int argc, char* argv[], int *status, bool ignore_int_quit,
173 bool logwrap) {
Rom Lemarchand113bd472013-01-10 15:21:18 -0800174 pid_t pid;
Rom Lemarchand113bd472013-01-10 15:21:18 -0800175 int parent_ptty;
176 int child_ptty;
177 char *child_devname = NULL;
Rom Lemarchand75c289a2013-01-09 10:20:25 -0800178 struct sigaction intact;
179 struct sigaction quitact;
Rom Lemarchand0cc2cab2013-01-16 12:08:04 -0800180 sigset_t blockset;
181 sigset_t oldset;
Rom Lemarchand0cc2cab2013-01-16 12:08:04 -0800182 int rc = 0;
Rom Lemarchand113bd472013-01-10 15:21:18 -0800183
Rom Lemarchand74a7b912013-03-11 14:00:58 -0700184 rc = pthread_mutex_lock(&fd_mutex);
185 if (rc) {
186 ERROR("failed to lock signal_fd mutex\n");
187 goto err_lock;
188 }
189
Rom Lemarchand113bd472013-01-10 15:21:18 -0800190 /* Use ptty instead of socketpair so that STDOUT is not buffered */
191 parent_ptty = open("/dev/ptmx", O_RDWR);
192 if (parent_ptty < 0) {
Rom Lemarchand2a46bfa2013-01-29 11:44:59 -0800193 ERROR("Cannot create parent ptty\n");
Rom Lemarchand0cc2cab2013-01-16 12:08:04 -0800194 rc = -1;
195 goto err_open;
Rom Lemarchand113bd472013-01-10 15:21:18 -0800196 }
197
198 if (grantpt(parent_ptty) || unlockpt(parent_ptty) ||
199 ((child_devname = (char*)ptsname(parent_ptty)) == 0)) {
Rom Lemarchand2a46bfa2013-01-29 11:44:59 -0800200 ERROR("Problem with /dev/ptmx\n");
Rom Lemarchand0cc2cab2013-01-16 12:08:04 -0800201 rc = -1;
202 goto err_ptty;
Rom Lemarchand113bd472013-01-10 15:21:18 -0800203 }
204
Rom Lemarchand6ad53df2013-03-20 13:46:53 -0700205 child_ptty = open(child_devname, O_RDWR);
206 if (child_ptty < 0) {
207 ERROR("Cannot open child_ptty\n");
208 rc = -1;
209 goto err_child_ptty;
210 }
211
Rom Lemarchand0cc2cab2013-01-16 12:08:04 -0800212 sigemptyset(&blockset);
Rom Lemarchand75c289a2013-01-09 10:20:25 -0800213 sigaddset(&blockset, SIGINT);
214 sigaddset(&blockset, SIGQUIT);
Rom Lemarchanded179d22013-01-16 15:07:30 -0800215 pthread_sigmask(SIG_BLOCK, &blockset, &oldset);
Rom Lemarchandb58a8222013-01-09 21:31:25 -0800216
Rom Lemarchand113bd472013-01-10 15:21:18 -0800217 pid = fork();
218 if (pid < 0) {
Rom Lemarchand6ad53df2013-03-20 13:46:53 -0700219 close(child_ptty);
Rom Lemarchand2a46bfa2013-01-29 11:44:59 -0800220 ERROR("Failed to fork\n");
Rom Lemarchand0cc2cab2013-01-16 12:08:04 -0800221 rc = -1;
222 goto err_fork;
Rom Lemarchand113bd472013-01-10 15:21:18 -0800223 } else if (pid == 0) {
Rom Lemarchand74a7b912013-03-11 14:00:58 -0700224 pthread_mutex_unlock(&fd_mutex);
Rom Lemarchanded179d22013-01-16 15:07:30 -0800225 pthread_sigmask(SIG_SETMASK, &oldset, NULL);
Rom Lemarchand113bd472013-01-10 15:21:18 -0800226 close(parent_ptty);
Rom Lemarchand0cc2cab2013-01-16 12:08:04 -0800227
Rom Lemarchand113bd472013-01-10 15:21:18 -0800228 // redirect stdout and stderr
229 dup2(child_ptty, 1);
230 dup2(child_ptty, 2);
231 close(child_ptty);
232
Rom Lemarchand2a46bfa2013-01-29 11:44:59 -0800233 child(argc, argv, logwrap);
Rom Lemarchand113bd472013-01-10 15:21:18 -0800234 } else {
Rom Lemarchand6ad53df2013-03-20 13:46:53 -0700235 close(child_ptty);
Rom Lemarchand75c289a2013-01-09 10:20:25 -0800236 if (ignore_int_quit) {
Rom Lemarchand6ad53df2013-03-20 13:46:53 -0700237 struct sigaction ignact;
238
Rom Lemarchand75c289a2013-01-09 10:20:25 -0800239 memset(&ignact, 0, sizeof(ignact));
240 ignact.sa_handler = SIG_IGN;
241 sigaction(SIGINT, &ignact, &intact);
242 sigaction(SIGQUIT, &ignact, &quitact);
243 }
244
Rom Lemarchand6ad53df2013-03-20 13:46:53 -0700245 rc = parent(argv[0], parent_ptty, pid, status, logwrap);
Rom Lemarchandb58a8222013-01-09 21:31:25 -0800246 }
Rom Lemarchand0cc2cab2013-01-16 12:08:04 -0800247
Rom Lemarchand75c289a2013-01-09 10:20:25 -0800248 if (ignore_int_quit) {
249 sigaction(SIGINT, &intact, NULL);
250 sigaction(SIGQUIT, &quitact, NULL);
251 }
Rom Lemarchand0cc2cab2013-01-16 12:08:04 -0800252err_fork:
Rom Lemarchanded179d22013-01-16 15:07:30 -0800253 pthread_sigmask(SIG_SETMASK, &oldset, NULL);
Rom Lemarchand6ad53df2013-03-20 13:46:53 -0700254err_child_ptty:
Rom Lemarchand0cc2cab2013-01-16 12:08:04 -0800255err_ptty:
256 close(parent_ptty);
257err_open:
Rom Lemarchand74a7b912013-03-11 14:00:58 -0700258 pthread_mutex_unlock(&fd_mutex);
259err_lock:
Rom Lemarchand0cc2cab2013-01-16 12:08:04 -0800260 return rc;
Rom Lemarchand113bd472013-01-10 15:21:18 -0800261}