xref: /aosp_15_r20/system/logging/logwrapper/logwrap.cpp (revision 598139dc91b21518d67c408eaea2644226490971)
1*598139dcSAndroid Build Coastguard Worker /*
2*598139dcSAndroid Build Coastguard Worker  * Copyright (C) 2008 The Android Open Source Project
3*598139dcSAndroid Build Coastguard Worker  *
4*598139dcSAndroid Build Coastguard Worker  * Licensed under the Apache License, Version 2.0 (the "License");
5*598139dcSAndroid Build Coastguard Worker  * you may not use this file except in compliance with the License.
6*598139dcSAndroid Build Coastguard Worker  * You may obtain a copy of the License at
7*598139dcSAndroid Build Coastguard Worker  *
8*598139dcSAndroid Build Coastguard Worker  *      http://www.apache.org/licenses/LICENSE-2.0
9*598139dcSAndroid Build Coastguard Worker  *
10*598139dcSAndroid Build Coastguard Worker  * Unless required by applicable law or agreed to in writing, software
11*598139dcSAndroid Build Coastguard Worker  * distributed under the License is distributed on an "AS IS" BASIS,
12*598139dcSAndroid Build Coastguard Worker  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*598139dcSAndroid Build Coastguard Worker  * See the License for the specific language governing permissions and
14*598139dcSAndroid Build Coastguard Worker  * limitations under the License.
15*598139dcSAndroid Build Coastguard Worker  */
16*598139dcSAndroid Build Coastguard Worker 
17*598139dcSAndroid Build Coastguard Worker #include <errno.h>
18*598139dcSAndroid Build Coastguard Worker #include <fcntl.h>
19*598139dcSAndroid Build Coastguard Worker #include <libgen.h>
20*598139dcSAndroid Build Coastguard Worker #include <poll.h>
21*598139dcSAndroid Build Coastguard Worker #include <pthread.h>
22*598139dcSAndroid Build Coastguard Worker #include <stdio.h>
23*598139dcSAndroid Build Coastguard Worker #include <stdlib.h>
24*598139dcSAndroid Build Coastguard Worker #include <string.h>
25*598139dcSAndroid Build Coastguard Worker #include <sys/socket.h>
26*598139dcSAndroid Build Coastguard Worker #include <sys/types.h>
27*598139dcSAndroid Build Coastguard Worker #include <sys/wait.h>
28*598139dcSAndroid Build Coastguard Worker #include <unistd.h>
29*598139dcSAndroid Build Coastguard Worker 
30*598139dcSAndroid Build Coastguard Worker #include <algorithm>
31*598139dcSAndroid Build Coastguard Worker 
32*598139dcSAndroid Build Coastguard Worker #include <android-base/macros.h>
33*598139dcSAndroid Build Coastguard Worker #include <cutils/klog.h>
34*598139dcSAndroid Build Coastguard Worker #include <log/log.h>
35*598139dcSAndroid Build Coastguard Worker #include <logwrap/logwrap.h>
36*598139dcSAndroid Build Coastguard Worker 
37*598139dcSAndroid Build Coastguard Worker static pthread_mutex_t fd_mutex = PTHREAD_MUTEX_INITIALIZER;
38*598139dcSAndroid Build Coastguard Worker // Protected by fd_mutex.  These signals must be blocked while modifying as well.
39*598139dcSAndroid Build Coastguard Worker static pid_t child_pid;
40*598139dcSAndroid Build Coastguard Worker static struct sigaction old_int;
41*598139dcSAndroid Build Coastguard Worker static struct sigaction old_quit;
42*598139dcSAndroid Build Coastguard Worker static struct sigaction old_hup;
43*598139dcSAndroid Build Coastguard Worker 
44*598139dcSAndroid Build Coastguard Worker #define ERROR(fmt, args...)                         \
45*598139dcSAndroid Build Coastguard Worker     do {                                            \
46*598139dcSAndroid Build Coastguard Worker         fprintf(stderr, fmt, ##args);               \
47*598139dcSAndroid Build Coastguard Worker         ALOG(LOG_ERROR, "logwrapper", fmt, ##args); \
48*598139dcSAndroid Build Coastguard Worker     } while (0)
49*598139dcSAndroid Build Coastguard Worker 
50*598139dcSAndroid Build Coastguard Worker #define FATAL_CHILD(fmt, args...) \
51*598139dcSAndroid Build Coastguard Worker     do {                          \
52*598139dcSAndroid Build Coastguard Worker         ERROR(fmt, ##args);       \
53*598139dcSAndroid Build Coastguard Worker         _exit(-1);                \
54*598139dcSAndroid Build Coastguard Worker     } while (0)
55*598139dcSAndroid Build Coastguard Worker 
56*598139dcSAndroid Build Coastguard Worker #define MAX_KLOG_TAG 16
57*598139dcSAndroid Build Coastguard Worker 
58*598139dcSAndroid Build Coastguard Worker /* This is a simple buffer that holds up to the first beginning_buf->buf_size
59*598139dcSAndroid Build Coastguard Worker  * bytes of output from a command.
60*598139dcSAndroid Build Coastguard Worker  */
61*598139dcSAndroid Build Coastguard Worker #define BEGINNING_BUF_SIZE 0x1000
62*598139dcSAndroid Build Coastguard Worker struct beginning_buf {
63*598139dcSAndroid Build Coastguard Worker     char* buf;
64*598139dcSAndroid Build Coastguard Worker     size_t alloc_len;
65*598139dcSAndroid Build Coastguard Worker     /* buf_size is the usable space, which is one less than the allocated size */
66*598139dcSAndroid Build Coastguard Worker     size_t buf_size;
67*598139dcSAndroid Build Coastguard Worker     size_t used_len;
68*598139dcSAndroid Build Coastguard Worker };
69*598139dcSAndroid Build Coastguard Worker 
70*598139dcSAndroid Build Coastguard Worker /* This is a circular buf that holds up to the last ending_buf->buf_size bytes
71*598139dcSAndroid Build Coastguard Worker  * of output from a command after the first beginning_buf->buf_size bytes
72*598139dcSAndroid Build Coastguard Worker  * (which are held in beginning_buf above).
73*598139dcSAndroid Build Coastguard Worker  */
74*598139dcSAndroid Build Coastguard Worker #define ENDING_BUF_SIZE 0x1000
75*598139dcSAndroid Build Coastguard Worker struct ending_buf {
76*598139dcSAndroid Build Coastguard Worker     char* buf;
77*598139dcSAndroid Build Coastguard Worker     ssize_t alloc_len;
78*598139dcSAndroid Build Coastguard Worker     /* buf_size is the usable space, which is one less than the allocated size */
79*598139dcSAndroid Build Coastguard Worker     ssize_t buf_size;
80*598139dcSAndroid Build Coastguard Worker     ssize_t used_len;
81*598139dcSAndroid Build Coastguard Worker     /* read and write offsets into the circular buffer */
82*598139dcSAndroid Build Coastguard Worker     int read;
83*598139dcSAndroid Build Coastguard Worker     int write;
84*598139dcSAndroid Build Coastguard Worker };
85*598139dcSAndroid Build Coastguard Worker 
86*598139dcSAndroid Build Coastguard Worker /* A structure to hold all the abbreviated buf data */
87*598139dcSAndroid Build Coastguard Worker struct abbr_buf {
88*598139dcSAndroid Build Coastguard Worker     struct beginning_buf b_buf;
89*598139dcSAndroid Build Coastguard Worker     struct ending_buf e_buf;
90*598139dcSAndroid Build Coastguard Worker     int beginning_buf_full;
91*598139dcSAndroid Build Coastguard Worker };
92*598139dcSAndroid Build Coastguard Worker 
93*598139dcSAndroid Build Coastguard Worker /* Collect all the various bits of info needed for logging in one place. */
94*598139dcSAndroid Build Coastguard Worker struct log_info {
95*598139dcSAndroid Build Coastguard Worker     int log_target;
96*598139dcSAndroid Build Coastguard Worker     char klog_fmt[MAX_KLOG_TAG * 2];
97*598139dcSAndroid Build Coastguard Worker     const char* btag;
98*598139dcSAndroid Build Coastguard Worker     bool abbreviated;
99*598139dcSAndroid Build Coastguard Worker     FILE* fp;
100*598139dcSAndroid Build Coastguard Worker     struct abbr_buf a_buf;
101*598139dcSAndroid Build Coastguard Worker };
102*598139dcSAndroid Build Coastguard Worker 
103*598139dcSAndroid Build Coastguard Worker /* Forware declaration */
104*598139dcSAndroid Build Coastguard Worker static void add_line_to_abbr_buf(struct abbr_buf* a_buf, char* linebuf, int linelen);
105*598139dcSAndroid Build Coastguard Worker 
106*598139dcSAndroid Build Coastguard Worker /* Return 0 on success, and 1 when full */
add_line_to_linear_buf(struct beginning_buf * b_buf,char * line,ssize_t line_len)107*598139dcSAndroid Build Coastguard Worker static int add_line_to_linear_buf(struct beginning_buf* b_buf, char* line, ssize_t line_len) {
108*598139dcSAndroid Build Coastguard Worker     int full = 0;
109*598139dcSAndroid Build Coastguard Worker 
110*598139dcSAndroid Build Coastguard Worker     if ((line_len + b_buf->used_len) > b_buf->buf_size) {
111*598139dcSAndroid Build Coastguard Worker         full = 1;
112*598139dcSAndroid Build Coastguard Worker     } else {
113*598139dcSAndroid Build Coastguard Worker         /* Add to the end of the buf */
114*598139dcSAndroid Build Coastguard Worker         memcpy(b_buf->buf + b_buf->used_len, line, line_len);
115*598139dcSAndroid Build Coastguard Worker         b_buf->used_len += line_len;
116*598139dcSAndroid Build Coastguard Worker     }
117*598139dcSAndroid Build Coastguard Worker 
118*598139dcSAndroid Build Coastguard Worker     return full;
119*598139dcSAndroid Build Coastguard Worker }
120*598139dcSAndroid Build Coastguard Worker 
add_line_to_circular_buf(struct ending_buf * e_buf,char * line,ssize_t line_len)121*598139dcSAndroid Build Coastguard Worker static void add_line_to_circular_buf(struct ending_buf* e_buf, char* line, ssize_t line_len) {
122*598139dcSAndroid Build Coastguard Worker     ssize_t free_len;
123*598139dcSAndroid Build Coastguard Worker     ssize_t needed_space;
124*598139dcSAndroid Build Coastguard Worker     int cnt;
125*598139dcSAndroid Build Coastguard Worker 
126*598139dcSAndroid Build Coastguard Worker     if (e_buf->buf == nullptr) {
127*598139dcSAndroid Build Coastguard Worker         return;
128*598139dcSAndroid Build Coastguard Worker     }
129*598139dcSAndroid Build Coastguard Worker 
130*598139dcSAndroid Build Coastguard Worker     if (line_len > e_buf->buf_size) {
131*598139dcSAndroid Build Coastguard Worker         return;
132*598139dcSAndroid Build Coastguard Worker     }
133*598139dcSAndroid Build Coastguard Worker 
134*598139dcSAndroid Build Coastguard Worker     free_len = e_buf->buf_size - e_buf->used_len;
135*598139dcSAndroid Build Coastguard Worker 
136*598139dcSAndroid Build Coastguard Worker     if (line_len > free_len) {
137*598139dcSAndroid Build Coastguard Worker         /* remove oldest entries at read, and move read to make
138*598139dcSAndroid Build Coastguard Worker          * room for the new string */
139*598139dcSAndroid Build Coastguard Worker         needed_space = line_len - free_len;
140*598139dcSAndroid Build Coastguard Worker         e_buf->read = (e_buf->read + needed_space) % e_buf->buf_size;
141*598139dcSAndroid Build Coastguard Worker         e_buf->used_len -= needed_space;
142*598139dcSAndroid Build Coastguard Worker     }
143*598139dcSAndroid Build Coastguard Worker 
144*598139dcSAndroid Build Coastguard Worker     /* Copy the line into the circular buffer, dealing with possible
145*598139dcSAndroid Build Coastguard Worker      * wraparound.
146*598139dcSAndroid Build Coastguard Worker      */
147*598139dcSAndroid Build Coastguard Worker     cnt = std::min(line_len, e_buf->buf_size - e_buf->write);
148*598139dcSAndroid Build Coastguard Worker     memcpy(e_buf->buf + e_buf->write, line, cnt);
149*598139dcSAndroid Build Coastguard Worker     if (cnt < line_len) {
150*598139dcSAndroid Build Coastguard Worker         memcpy(e_buf->buf, line + cnt, line_len - cnt);
151*598139dcSAndroid Build Coastguard Worker     }
152*598139dcSAndroid Build Coastguard Worker     e_buf->used_len += line_len;
153*598139dcSAndroid Build Coastguard Worker     e_buf->write = (e_buf->write + line_len) % e_buf->buf_size;
154*598139dcSAndroid Build Coastguard Worker }
155*598139dcSAndroid Build Coastguard Worker 
156*598139dcSAndroid Build Coastguard Worker /* Log directly to the specified log */
do_log_line(struct log_info * log_info,const char * line)157*598139dcSAndroid Build Coastguard Worker static void do_log_line(struct log_info* log_info, const char* line) {
158*598139dcSAndroid Build Coastguard Worker     if (log_info->log_target & LOG_KLOG) {
159*598139dcSAndroid Build Coastguard Worker         klog_write(6, log_info->klog_fmt, line);
160*598139dcSAndroid Build Coastguard Worker     }
161*598139dcSAndroid Build Coastguard Worker     if (log_info->log_target & LOG_ALOG) {
162*598139dcSAndroid Build Coastguard Worker         ALOG(LOG_INFO, log_info->btag, "%s", line);
163*598139dcSAndroid Build Coastguard Worker     }
164*598139dcSAndroid Build Coastguard Worker     if (log_info->fp) {
165*598139dcSAndroid Build Coastguard Worker         fprintf(log_info->fp, "%s\n", line);
166*598139dcSAndroid Build Coastguard Worker     }
167*598139dcSAndroid Build Coastguard Worker }
168*598139dcSAndroid Build Coastguard Worker 
169*598139dcSAndroid Build Coastguard Worker /* Log to either the abbreviated buf, or directly to the specified log
170*598139dcSAndroid Build Coastguard Worker  * via do_log_line() above.
171*598139dcSAndroid Build Coastguard Worker  */
log_line(struct log_info * log_info,char * line,int len)172*598139dcSAndroid Build Coastguard Worker static void log_line(struct log_info* log_info, char* line, int len) {
173*598139dcSAndroid Build Coastguard Worker     if (log_info->abbreviated) {
174*598139dcSAndroid Build Coastguard Worker         add_line_to_abbr_buf(&log_info->a_buf, line, len);
175*598139dcSAndroid Build Coastguard Worker     } else {
176*598139dcSAndroid Build Coastguard Worker         do_log_line(log_info, line);
177*598139dcSAndroid Build Coastguard Worker     }
178*598139dcSAndroid Build Coastguard Worker }
179*598139dcSAndroid Build Coastguard Worker 
180*598139dcSAndroid Build Coastguard Worker /*
181*598139dcSAndroid Build Coastguard Worker  * The kernel will take a maximum of 1024 bytes in any single write to
182*598139dcSAndroid Build Coastguard Worker  * the kernel logging device file, so find and print each line one at
183*598139dcSAndroid Build Coastguard Worker  * a time.  The allocated size for buf should be at least 1 byte larger
184*598139dcSAndroid Build Coastguard Worker  * than buf_size (the usable size of the buffer) to make sure there is
185*598139dcSAndroid Build Coastguard Worker  * room to temporarily stuff a null byte to terminate a line for logging.
186*598139dcSAndroid Build Coastguard Worker  */
print_buf_lines(struct log_info * log_info,char * buf,int buf_size)187*598139dcSAndroid Build Coastguard Worker static void print_buf_lines(struct log_info* log_info, char* buf, int buf_size) {
188*598139dcSAndroid Build Coastguard Worker     char* line_start;
189*598139dcSAndroid Build Coastguard Worker     char c;
190*598139dcSAndroid Build Coastguard Worker     int i;
191*598139dcSAndroid Build Coastguard Worker 
192*598139dcSAndroid Build Coastguard Worker     line_start = buf;
193*598139dcSAndroid Build Coastguard Worker     for (i = 0; i < buf_size; i++) {
194*598139dcSAndroid Build Coastguard Worker         if (*(buf + i) == '\n') {
195*598139dcSAndroid Build Coastguard Worker             /* Found a line ending, print the line and compute new line_start */
196*598139dcSAndroid Build Coastguard Worker             /* Save the next char and replace with \0 */
197*598139dcSAndroid Build Coastguard Worker             c = *(buf + i + 1);
198*598139dcSAndroid Build Coastguard Worker             *(buf + i + 1) = '\0';
199*598139dcSAndroid Build Coastguard Worker             do_log_line(log_info, line_start);
200*598139dcSAndroid Build Coastguard Worker             /* Restore the saved char */
201*598139dcSAndroid Build Coastguard Worker             *(buf + i + 1) = c;
202*598139dcSAndroid Build Coastguard Worker             line_start = buf + i + 1;
203*598139dcSAndroid Build Coastguard Worker         } else if (*(buf + i) == '\0') {
204*598139dcSAndroid Build Coastguard Worker             /* The end of the buffer, print the last bit */
205*598139dcSAndroid Build Coastguard Worker             do_log_line(log_info, line_start);
206*598139dcSAndroid Build Coastguard Worker             break;
207*598139dcSAndroid Build Coastguard Worker         }
208*598139dcSAndroid Build Coastguard Worker     }
209*598139dcSAndroid Build Coastguard Worker     /* If the buffer was completely full, and didn't end with a newline, just
210*598139dcSAndroid Build Coastguard Worker      * ignore the partial last line.
211*598139dcSAndroid Build Coastguard Worker      */
212*598139dcSAndroid Build Coastguard Worker }
213*598139dcSAndroid Build Coastguard Worker 
init_abbr_buf(struct abbr_buf * a_buf)214*598139dcSAndroid Build Coastguard Worker static void init_abbr_buf(struct abbr_buf* a_buf) {
215*598139dcSAndroid Build Coastguard Worker     char* new_buf;
216*598139dcSAndroid Build Coastguard Worker 
217*598139dcSAndroid Build Coastguard Worker     memset(a_buf, 0, sizeof(struct abbr_buf));
218*598139dcSAndroid Build Coastguard Worker     new_buf = static_cast<char*>(malloc(BEGINNING_BUF_SIZE));
219*598139dcSAndroid Build Coastguard Worker     if (new_buf) {
220*598139dcSAndroid Build Coastguard Worker         a_buf->b_buf.buf = new_buf;
221*598139dcSAndroid Build Coastguard Worker         a_buf->b_buf.alloc_len = BEGINNING_BUF_SIZE;
222*598139dcSAndroid Build Coastguard Worker         a_buf->b_buf.buf_size = BEGINNING_BUF_SIZE - 1;
223*598139dcSAndroid Build Coastguard Worker     }
224*598139dcSAndroid Build Coastguard Worker     new_buf = static_cast<char*>(malloc(ENDING_BUF_SIZE));
225*598139dcSAndroid Build Coastguard Worker     if (new_buf) {
226*598139dcSAndroid Build Coastguard Worker         a_buf->e_buf.buf = new_buf;
227*598139dcSAndroid Build Coastguard Worker         a_buf->e_buf.alloc_len = ENDING_BUF_SIZE;
228*598139dcSAndroid Build Coastguard Worker         a_buf->e_buf.buf_size = ENDING_BUF_SIZE - 1;
229*598139dcSAndroid Build Coastguard Worker     }
230*598139dcSAndroid Build Coastguard Worker }
231*598139dcSAndroid Build Coastguard Worker 
free_abbr_buf(struct abbr_buf * a_buf)232*598139dcSAndroid Build Coastguard Worker static void free_abbr_buf(struct abbr_buf* a_buf) {
233*598139dcSAndroid Build Coastguard Worker     free(a_buf->b_buf.buf);
234*598139dcSAndroid Build Coastguard Worker     free(a_buf->e_buf.buf);
235*598139dcSAndroid Build Coastguard Worker }
236*598139dcSAndroid Build Coastguard Worker 
add_line_to_abbr_buf(struct abbr_buf * a_buf,char * linebuf,int linelen)237*598139dcSAndroid Build Coastguard Worker static void add_line_to_abbr_buf(struct abbr_buf* a_buf, char* linebuf, int linelen) {
238*598139dcSAndroid Build Coastguard Worker     if (!a_buf->beginning_buf_full) {
239*598139dcSAndroid Build Coastguard Worker         a_buf->beginning_buf_full = add_line_to_linear_buf(&a_buf->b_buf, linebuf, linelen);
240*598139dcSAndroid Build Coastguard Worker     }
241*598139dcSAndroid Build Coastguard Worker     if (a_buf->beginning_buf_full) {
242*598139dcSAndroid Build Coastguard Worker         add_line_to_circular_buf(&a_buf->e_buf, linebuf, linelen);
243*598139dcSAndroid Build Coastguard Worker     }
244*598139dcSAndroid Build Coastguard Worker }
245*598139dcSAndroid Build Coastguard Worker 
print_abbr_buf(struct log_info * log_info)246*598139dcSAndroid Build Coastguard Worker static void print_abbr_buf(struct log_info* log_info) {
247*598139dcSAndroid Build Coastguard Worker     struct abbr_buf* a_buf = &log_info->a_buf;
248*598139dcSAndroid Build Coastguard Worker 
249*598139dcSAndroid Build Coastguard Worker     /* Add the abbreviated output to the kernel log */
250*598139dcSAndroid Build Coastguard Worker     if (a_buf->b_buf.alloc_len) {
251*598139dcSAndroid Build Coastguard Worker         print_buf_lines(log_info, a_buf->b_buf.buf, a_buf->b_buf.used_len);
252*598139dcSAndroid Build Coastguard Worker     }
253*598139dcSAndroid Build Coastguard Worker 
254*598139dcSAndroid Build Coastguard Worker     /* Print an ellipsis to indicate that the buffer has wrapped or
255*598139dcSAndroid Build Coastguard Worker      * is full, and some data was not logged.
256*598139dcSAndroid Build Coastguard Worker      */
257*598139dcSAndroid Build Coastguard Worker     if (a_buf->e_buf.used_len == a_buf->e_buf.buf_size) {
258*598139dcSAndroid Build Coastguard Worker         do_log_line(log_info, "...\n");
259*598139dcSAndroid Build Coastguard Worker     }
260*598139dcSAndroid Build Coastguard Worker 
261*598139dcSAndroid Build Coastguard Worker     if (a_buf->e_buf.used_len == 0) {
262*598139dcSAndroid Build Coastguard Worker         return;
263*598139dcSAndroid Build Coastguard Worker     }
264*598139dcSAndroid Build Coastguard Worker 
265*598139dcSAndroid Build Coastguard Worker     /* Simplest way to print the circular buffer is allocate a second buf
266*598139dcSAndroid Build Coastguard Worker      * of the same size, and memcpy it so it's a simple linear buffer,
267*598139dcSAndroid Build Coastguard Worker      * and then cal print_buf_lines on it */
268*598139dcSAndroid Build Coastguard Worker     if (a_buf->e_buf.read < a_buf->e_buf.write) {
269*598139dcSAndroid Build Coastguard Worker         /* no wrap around, just print it */
270*598139dcSAndroid Build Coastguard Worker         print_buf_lines(log_info, a_buf->e_buf.buf + a_buf->e_buf.read, a_buf->e_buf.used_len);
271*598139dcSAndroid Build Coastguard Worker     } else {
272*598139dcSAndroid Build Coastguard Worker         /* The circular buffer will always have at least 1 byte unused,
273*598139dcSAndroid Build Coastguard Worker          * so by allocating alloc_len here we will have at least
274*598139dcSAndroid Build Coastguard Worker          * 1 byte of space available as required by print_buf_lines().
275*598139dcSAndroid Build Coastguard Worker          */
276*598139dcSAndroid Build Coastguard Worker         char* nbuf = static_cast<char*>(malloc(a_buf->e_buf.alloc_len));
277*598139dcSAndroid Build Coastguard Worker         if (!nbuf) {
278*598139dcSAndroid Build Coastguard Worker             return;
279*598139dcSAndroid Build Coastguard Worker         }
280*598139dcSAndroid Build Coastguard Worker         int first_chunk_len = a_buf->e_buf.buf_size - a_buf->e_buf.read;
281*598139dcSAndroid Build Coastguard Worker         memcpy(nbuf, a_buf->e_buf.buf + a_buf->e_buf.read, first_chunk_len);
282*598139dcSAndroid Build Coastguard Worker         /* copy second chunk */
283*598139dcSAndroid Build Coastguard Worker         memcpy(nbuf + first_chunk_len, a_buf->e_buf.buf, a_buf->e_buf.write);
284*598139dcSAndroid Build Coastguard Worker         print_buf_lines(log_info, nbuf, first_chunk_len + a_buf->e_buf.write);
285*598139dcSAndroid Build Coastguard Worker         free(nbuf);
286*598139dcSAndroid Build Coastguard Worker     }
287*598139dcSAndroid Build Coastguard Worker }
288*598139dcSAndroid Build Coastguard Worker 
289*598139dcSAndroid Build Coastguard Worker static void signal_handler(int signal_num);
290*598139dcSAndroid Build Coastguard Worker 
block_signals(sigset_t * oldset)291*598139dcSAndroid Build Coastguard Worker static void block_signals(sigset_t* oldset) {
292*598139dcSAndroid Build Coastguard Worker     sigset_t blockset;
293*598139dcSAndroid Build Coastguard Worker 
294*598139dcSAndroid Build Coastguard Worker     sigemptyset(&blockset);
295*598139dcSAndroid Build Coastguard Worker     sigaddset(&blockset, SIGINT);
296*598139dcSAndroid Build Coastguard Worker     sigaddset(&blockset, SIGQUIT);
297*598139dcSAndroid Build Coastguard Worker     sigaddset(&blockset, SIGHUP);
298*598139dcSAndroid Build Coastguard Worker     pthread_sigmask(SIG_BLOCK, &blockset, oldset);
299*598139dcSAndroid Build Coastguard Worker }
300*598139dcSAndroid Build Coastguard Worker 
unblock_signals(sigset_t * oldset)301*598139dcSAndroid Build Coastguard Worker static void unblock_signals(sigset_t* oldset) {
302*598139dcSAndroid Build Coastguard Worker     pthread_sigmask(SIG_SETMASK, oldset, nullptr);
303*598139dcSAndroid Build Coastguard Worker }
304*598139dcSAndroid Build Coastguard Worker 
setup_signal_handlers(pid_t pid)305*598139dcSAndroid Build Coastguard Worker static void setup_signal_handlers(pid_t pid) {
306*598139dcSAndroid Build Coastguard Worker     struct sigaction handler = {.sa_handler = signal_handler};
307*598139dcSAndroid Build Coastguard Worker 
308*598139dcSAndroid Build Coastguard Worker     child_pid = pid;
309*598139dcSAndroid Build Coastguard Worker     sigaction(SIGINT, &handler, &old_int);
310*598139dcSAndroid Build Coastguard Worker     sigaction(SIGQUIT, &handler, &old_quit);
311*598139dcSAndroid Build Coastguard Worker     sigaction(SIGHUP, &handler, &old_hup);
312*598139dcSAndroid Build Coastguard Worker }
313*598139dcSAndroid Build Coastguard Worker 
restore_signal_handlers()314*598139dcSAndroid Build Coastguard Worker static void restore_signal_handlers() {
315*598139dcSAndroid Build Coastguard Worker     sigaction(SIGINT, &old_int, nullptr);
316*598139dcSAndroid Build Coastguard Worker     sigaction(SIGQUIT, &old_quit, nullptr);
317*598139dcSAndroid Build Coastguard Worker     sigaction(SIGHUP, &old_hup, nullptr);
318*598139dcSAndroid Build Coastguard Worker     child_pid = 0;
319*598139dcSAndroid Build Coastguard Worker }
320*598139dcSAndroid Build Coastguard Worker 
signal_handler(int signal_num)321*598139dcSAndroid Build Coastguard Worker static void signal_handler(int signal_num) {
322*598139dcSAndroid Build Coastguard Worker     if (child_pid == 0 || kill(child_pid, signal_num) != 0) {
323*598139dcSAndroid Build Coastguard Worker         restore_signal_handlers();
324*598139dcSAndroid Build Coastguard Worker         raise(signal_num);
325*598139dcSAndroid Build Coastguard Worker     }
326*598139dcSAndroid Build Coastguard Worker }
327*598139dcSAndroid Build Coastguard Worker 
parent(const char * tag,int parent_read,pid_t pid,int * chld_sts,int log_target,bool abbreviated,const char * file_path,bool forward_signals)328*598139dcSAndroid Build Coastguard Worker static int parent(const char* tag, int parent_read, pid_t pid, int* chld_sts, int log_target,
329*598139dcSAndroid Build Coastguard Worker                   bool abbreviated, const char* file_path, bool forward_signals) {
330*598139dcSAndroid Build Coastguard Worker     int status = 0;
331*598139dcSAndroid Build Coastguard Worker     char buffer[4096];
332*598139dcSAndroid Build Coastguard Worker     struct pollfd poll_fds[] = {
333*598139dcSAndroid Build Coastguard Worker             {
334*598139dcSAndroid Build Coastguard Worker                     .fd = parent_read,
335*598139dcSAndroid Build Coastguard Worker                     .events = POLLIN,
336*598139dcSAndroid Build Coastguard Worker             },
337*598139dcSAndroid Build Coastguard Worker     };
338*598139dcSAndroid Build Coastguard Worker     int rc = 0;
339*598139dcSAndroid Build Coastguard Worker     int fd;
340*598139dcSAndroid Build Coastguard Worker 
341*598139dcSAndroid Build Coastguard Worker     struct log_info log_info = {};
342*598139dcSAndroid Build Coastguard Worker 
343*598139dcSAndroid Build Coastguard Worker     int a = 0;  // start index of unprocessed data
344*598139dcSAndroid Build Coastguard Worker     int b = 0;  // end index of unprocessed data
345*598139dcSAndroid Build Coastguard Worker     int sz;
346*598139dcSAndroid Build Coastguard Worker     bool found_child = false;
347*598139dcSAndroid Build Coastguard Worker     // There is a very small chance that opening child_ptty in the child will fail, but in this case
348*598139dcSAndroid Build Coastguard Worker     // POLLHUP will not be generated below.  Therefore, we use a 1 second timeout for poll() until
349*598139dcSAndroid Build Coastguard Worker     // we receive a message from child_ptty.  If this times out, we call waitpid() with WNOHANG to
350*598139dcSAndroid Build Coastguard Worker     // check the status of the child process and exit appropriately if it has terminated.
351*598139dcSAndroid Build Coastguard Worker     bool received_messages = false;
352*598139dcSAndroid Build Coastguard Worker     char tmpbuf[256];
353*598139dcSAndroid Build Coastguard Worker 
354*598139dcSAndroid Build Coastguard Worker     log_info.btag = basename(tag);
355*598139dcSAndroid Build Coastguard Worker     if (!log_info.btag) {
356*598139dcSAndroid Build Coastguard Worker         log_info.btag = tag;
357*598139dcSAndroid Build Coastguard Worker     }
358*598139dcSAndroid Build Coastguard Worker 
359*598139dcSAndroid Build Coastguard Worker     if (abbreviated && (log_target == LOG_NONE)) {
360*598139dcSAndroid Build Coastguard Worker         abbreviated = 0;
361*598139dcSAndroid Build Coastguard Worker     }
362*598139dcSAndroid Build Coastguard Worker     if (abbreviated) {
363*598139dcSAndroid Build Coastguard Worker         init_abbr_buf(&log_info.a_buf);
364*598139dcSAndroid Build Coastguard Worker     }
365*598139dcSAndroid Build Coastguard Worker 
366*598139dcSAndroid Build Coastguard Worker     if (log_target & LOG_KLOG) {
367*598139dcSAndroid Build Coastguard Worker         snprintf(log_info.klog_fmt, sizeof(log_info.klog_fmt), "<6>%.*s: %%s\n", MAX_KLOG_TAG,
368*598139dcSAndroid Build Coastguard Worker                  log_info.btag);
369*598139dcSAndroid Build Coastguard Worker     }
370*598139dcSAndroid Build Coastguard Worker 
371*598139dcSAndroid Build Coastguard Worker     if ((log_target & LOG_FILE) && !file_path) {
372*598139dcSAndroid Build Coastguard Worker         /* No file_path specified, clear the LOG_FILE bit */
373*598139dcSAndroid Build Coastguard Worker         log_target &= ~LOG_FILE;
374*598139dcSAndroid Build Coastguard Worker     }
375*598139dcSAndroid Build Coastguard Worker 
376*598139dcSAndroid Build Coastguard Worker     if (log_target & LOG_FILE) {
377*598139dcSAndroid Build Coastguard Worker         fd = open(file_path, O_WRONLY | O_CREAT | O_CLOEXEC, 0664);
378*598139dcSAndroid Build Coastguard Worker         if (fd < 0) {
379*598139dcSAndroid Build Coastguard Worker             ERROR("Cannot log to file %s\n", file_path);
380*598139dcSAndroid Build Coastguard Worker             log_target &= ~LOG_FILE;
381*598139dcSAndroid Build Coastguard Worker         } else {
382*598139dcSAndroid Build Coastguard Worker             lseek(fd, 0, SEEK_END);
383*598139dcSAndroid Build Coastguard Worker             log_info.fp = fdopen(fd, "a");
384*598139dcSAndroid Build Coastguard Worker         }
385*598139dcSAndroid Build Coastguard Worker     }
386*598139dcSAndroid Build Coastguard Worker 
387*598139dcSAndroid Build Coastguard Worker     log_info.log_target = log_target;
388*598139dcSAndroid Build Coastguard Worker     log_info.abbreviated = abbreviated;
389*598139dcSAndroid Build Coastguard Worker 
390*598139dcSAndroid Build Coastguard Worker     while (!found_child) {
391*598139dcSAndroid Build Coastguard Worker         int timeout = received_messages ? -1 : 1000;
392*598139dcSAndroid Build Coastguard Worker         if (TEMP_FAILURE_RETRY(poll(poll_fds, arraysize(poll_fds), timeout)) < 0) {
393*598139dcSAndroid Build Coastguard Worker             ERROR("poll failed\n");
394*598139dcSAndroid Build Coastguard Worker             rc = -1;
395*598139dcSAndroid Build Coastguard Worker             goto err_poll;
396*598139dcSAndroid Build Coastguard Worker         }
397*598139dcSAndroid Build Coastguard Worker 
398*598139dcSAndroid Build Coastguard Worker         if (poll_fds[0].revents & POLLIN) {
399*598139dcSAndroid Build Coastguard Worker             received_messages = true;
400*598139dcSAndroid Build Coastguard Worker             sz = TEMP_FAILURE_RETRY(read(parent_read, &buffer[b], sizeof(buffer) - 1 - b));
401*598139dcSAndroid Build Coastguard Worker 
402*598139dcSAndroid Build Coastguard Worker             sz += b;
403*598139dcSAndroid Build Coastguard Worker             // Log one line at a time
404*598139dcSAndroid Build Coastguard Worker             for (b = 0; b < sz; b++) {
405*598139dcSAndroid Build Coastguard Worker                 if (buffer[b] == '\r') {
406*598139dcSAndroid Build Coastguard Worker                     if (abbreviated) {
407*598139dcSAndroid Build Coastguard Worker                         /* The abbreviated logging code uses newline as
408*598139dcSAndroid Build Coastguard Worker                          * the line separator.  Lucikly, the pty layer
409*598139dcSAndroid Build Coastguard Worker                          * helpfully cooks the output of the command
410*598139dcSAndroid Build Coastguard Worker                          * being run and inserts a CR before NL.  So
411*598139dcSAndroid Build Coastguard Worker                          * I just change it to NL here when doing
412*598139dcSAndroid Build Coastguard Worker                          * abbreviated logging.
413*598139dcSAndroid Build Coastguard Worker                          */
414*598139dcSAndroid Build Coastguard Worker                         buffer[b] = '\n';
415*598139dcSAndroid Build Coastguard Worker                     } else {
416*598139dcSAndroid Build Coastguard Worker                         buffer[b] = '\0';
417*598139dcSAndroid Build Coastguard Worker                     }
418*598139dcSAndroid Build Coastguard Worker                 } else if (buffer[b] == '\n') {
419*598139dcSAndroid Build Coastguard Worker                     buffer[b] = '\0';
420*598139dcSAndroid Build Coastguard Worker                     log_line(&log_info, &buffer[a], b - a);
421*598139dcSAndroid Build Coastguard Worker                     a = b + 1;
422*598139dcSAndroid Build Coastguard Worker                 }
423*598139dcSAndroid Build Coastguard Worker             }
424*598139dcSAndroid Build Coastguard Worker 
425*598139dcSAndroid Build Coastguard Worker             if (a == 0 && b == sizeof(buffer) - 1) {
426*598139dcSAndroid Build Coastguard Worker                 // buffer is full, flush
427*598139dcSAndroid Build Coastguard Worker                 buffer[b] = '\0';
428*598139dcSAndroid Build Coastguard Worker                 log_line(&log_info, &buffer[a], b - a);
429*598139dcSAndroid Build Coastguard Worker                 b = 0;
430*598139dcSAndroid Build Coastguard Worker             } else if (a != b) {
431*598139dcSAndroid Build Coastguard Worker                 // Keep left-overs
432*598139dcSAndroid Build Coastguard Worker                 b -= a;
433*598139dcSAndroid Build Coastguard Worker                 memmove(buffer, &buffer[a], b);
434*598139dcSAndroid Build Coastguard Worker                 a = 0;
435*598139dcSAndroid Build Coastguard Worker             } else {
436*598139dcSAndroid Build Coastguard Worker                 a = 0;
437*598139dcSAndroid Build Coastguard Worker                 b = 0;
438*598139dcSAndroid Build Coastguard Worker             }
439*598139dcSAndroid Build Coastguard Worker         }
440*598139dcSAndroid Build Coastguard Worker 
441*598139dcSAndroid Build Coastguard Worker         if (!received_messages || (poll_fds[0].revents & POLLHUP)) {
442*598139dcSAndroid Build Coastguard Worker             int ret;
443*598139dcSAndroid Build Coastguard Worker             sigset_t oldset;
444*598139dcSAndroid Build Coastguard Worker 
445*598139dcSAndroid Build Coastguard Worker             if (forward_signals) {
446*598139dcSAndroid Build Coastguard Worker                 // Our signal handlers forward these signals to 'child_pid', but waitpid() may reap
447*598139dcSAndroid Build Coastguard Worker                 // the child, so we must block these signals until we either 1) conclude that the
448*598139dcSAndroid Build Coastguard Worker                 // child is still running or 2) determine the child has been reaped and we have
449*598139dcSAndroid Build Coastguard Worker                 // reset the signals to their original disposition.
450*598139dcSAndroid Build Coastguard Worker                 block_signals(&oldset);
451*598139dcSAndroid Build Coastguard Worker             }
452*598139dcSAndroid Build Coastguard Worker 
453*598139dcSAndroid Build Coastguard Worker             int flags = (poll_fds[0].revents & POLLHUP) ? 0 : WNOHANG;
454*598139dcSAndroid Build Coastguard Worker             ret = TEMP_FAILURE_RETRY(waitpid(pid, &status, flags));
455*598139dcSAndroid Build Coastguard Worker             if (ret < 0) {
456*598139dcSAndroid Build Coastguard Worker                 rc = errno;
457*598139dcSAndroid Build Coastguard Worker                 ALOG(LOG_ERROR, "logwrap", "waitpid failed with %s\n", strerror(errno));
458*598139dcSAndroid Build Coastguard Worker                 goto err_waitpid;
459*598139dcSAndroid Build Coastguard Worker             }
460*598139dcSAndroid Build Coastguard Worker             if (ret > 0) {
461*598139dcSAndroid Build Coastguard Worker                 found_child = true;
462*598139dcSAndroid Build Coastguard Worker             }
463*598139dcSAndroid Build Coastguard Worker 
464*598139dcSAndroid Build Coastguard Worker             if (forward_signals) {
465*598139dcSAndroid Build Coastguard Worker                 if (found_child) {
466*598139dcSAndroid Build Coastguard Worker                     restore_signal_handlers();
467*598139dcSAndroid Build Coastguard Worker                 }
468*598139dcSAndroid Build Coastguard Worker                 unblock_signals(&oldset);
469*598139dcSAndroid Build Coastguard Worker             }
470*598139dcSAndroid Build Coastguard Worker         }
471*598139dcSAndroid Build Coastguard Worker     }
472*598139dcSAndroid Build Coastguard Worker 
473*598139dcSAndroid Build Coastguard Worker     if (chld_sts != nullptr) {
474*598139dcSAndroid Build Coastguard Worker         *chld_sts = status;
475*598139dcSAndroid Build Coastguard Worker     } else {
476*598139dcSAndroid Build Coastguard Worker         if (WIFEXITED(status))
477*598139dcSAndroid Build Coastguard Worker             rc = WEXITSTATUS(status);
478*598139dcSAndroid Build Coastguard Worker         else
479*598139dcSAndroid Build Coastguard Worker             rc = -ECHILD;
480*598139dcSAndroid Build Coastguard Worker     }
481*598139dcSAndroid Build Coastguard Worker 
482*598139dcSAndroid Build Coastguard Worker     // Flush remaining data
483*598139dcSAndroid Build Coastguard Worker     if (a != b) {
484*598139dcSAndroid Build Coastguard Worker         buffer[b] = '\0';
485*598139dcSAndroid Build Coastguard Worker         log_line(&log_info, &buffer[a], b - a);
486*598139dcSAndroid Build Coastguard Worker     }
487*598139dcSAndroid Build Coastguard Worker 
488*598139dcSAndroid Build Coastguard Worker     /* All the output has been processed, time to dump the abbreviated output */
489*598139dcSAndroid Build Coastguard Worker     if (abbreviated) {
490*598139dcSAndroid Build Coastguard Worker         print_abbr_buf(&log_info);
491*598139dcSAndroid Build Coastguard Worker     }
492*598139dcSAndroid Build Coastguard Worker 
493*598139dcSAndroid Build Coastguard Worker     if (WIFEXITED(status)) {
494*598139dcSAndroid Build Coastguard Worker         if (WEXITSTATUS(status)) {
495*598139dcSAndroid Build Coastguard Worker             snprintf(tmpbuf, sizeof(tmpbuf), "%s terminated by exit(%d)\n", log_info.btag,
496*598139dcSAndroid Build Coastguard Worker                      WEXITSTATUS(status));
497*598139dcSAndroid Build Coastguard Worker             do_log_line(&log_info, tmpbuf);
498*598139dcSAndroid Build Coastguard Worker         }
499*598139dcSAndroid Build Coastguard Worker     } else {
500*598139dcSAndroid Build Coastguard Worker         if (WIFSIGNALED(status)) {
501*598139dcSAndroid Build Coastguard Worker             snprintf(tmpbuf, sizeof(tmpbuf), "%s terminated by signal %d\n", log_info.btag,
502*598139dcSAndroid Build Coastguard Worker                      WTERMSIG(status));
503*598139dcSAndroid Build Coastguard Worker             do_log_line(&log_info, tmpbuf);
504*598139dcSAndroid Build Coastguard Worker         } else if (WIFSTOPPED(status)) {
505*598139dcSAndroid Build Coastguard Worker             snprintf(tmpbuf, sizeof(tmpbuf), "%s stopped by signal %d\n", log_info.btag,
506*598139dcSAndroid Build Coastguard Worker                      WSTOPSIG(status));
507*598139dcSAndroid Build Coastguard Worker             do_log_line(&log_info, tmpbuf);
508*598139dcSAndroid Build Coastguard Worker         }
509*598139dcSAndroid Build Coastguard Worker     }
510*598139dcSAndroid Build Coastguard Worker 
511*598139dcSAndroid Build Coastguard Worker err_waitpid:
512*598139dcSAndroid Build Coastguard Worker err_poll:
513*598139dcSAndroid Build Coastguard Worker     if (log_info.fp) {
514*598139dcSAndroid Build Coastguard Worker         fclose(log_info.fp);
515*598139dcSAndroid Build Coastguard Worker     }
516*598139dcSAndroid Build Coastguard Worker     if (abbreviated) {
517*598139dcSAndroid Build Coastguard Worker         free_abbr_buf(&log_info.a_buf);
518*598139dcSAndroid Build Coastguard Worker     }
519*598139dcSAndroid Build Coastguard Worker     return rc;
520*598139dcSAndroid Build Coastguard Worker }
521*598139dcSAndroid Build Coastguard Worker 
child(int argc,const char * const * argv)522*598139dcSAndroid Build Coastguard Worker static void child(int argc, const char* const* argv) {
523*598139dcSAndroid Build Coastguard Worker     // create null terminated argv_child array
524*598139dcSAndroid Build Coastguard Worker     char* argv_child[argc + 1];
525*598139dcSAndroid Build Coastguard Worker     memcpy(argv_child, argv, argc * sizeof(char*));
526*598139dcSAndroid Build Coastguard Worker     argv_child[argc] = nullptr;
527*598139dcSAndroid Build Coastguard Worker 
528*598139dcSAndroid Build Coastguard Worker     if (execvp(argv_child[0], argv_child)) {
529*598139dcSAndroid Build Coastguard Worker         FATAL_CHILD("executing %s failed: %s\n", argv_child[0], strerror(errno));
530*598139dcSAndroid Build Coastguard Worker     }
531*598139dcSAndroid Build Coastguard Worker }
532*598139dcSAndroid Build Coastguard Worker 
logwrap_fork_execvp(int argc,const char * const * argv,int * status,bool forward_signals,int log_target,bool abbreviated,const char * file_path)533*598139dcSAndroid Build Coastguard Worker int logwrap_fork_execvp(int argc, const char* const* argv, int* status, bool forward_signals,
534*598139dcSAndroid Build Coastguard Worker                         int log_target, bool abbreviated, const char* file_path) {
535*598139dcSAndroid Build Coastguard Worker     pid_t pid;
536*598139dcSAndroid Build Coastguard Worker     int parent_ptty;
537*598139dcSAndroid Build Coastguard Worker     sigset_t oldset;
538*598139dcSAndroid Build Coastguard Worker     int rc = 0;
539*598139dcSAndroid Build Coastguard Worker 
540*598139dcSAndroid Build Coastguard Worker     rc = pthread_mutex_lock(&fd_mutex);
541*598139dcSAndroid Build Coastguard Worker     if (rc) {
542*598139dcSAndroid Build Coastguard Worker         ERROR("failed to lock signal_fd mutex\n");
543*598139dcSAndroid Build Coastguard Worker         goto err_lock;
544*598139dcSAndroid Build Coastguard Worker     }
545*598139dcSAndroid Build Coastguard Worker 
546*598139dcSAndroid Build Coastguard Worker     /* Use ptty instead of socketpair so that STDOUT is not buffered */
547*598139dcSAndroid Build Coastguard Worker     parent_ptty = TEMP_FAILURE_RETRY(posix_openpt(O_RDWR | O_CLOEXEC));
548*598139dcSAndroid Build Coastguard Worker     if (parent_ptty < 0) {
549*598139dcSAndroid Build Coastguard Worker         ERROR("Cannot create parent ptty\n");
550*598139dcSAndroid Build Coastguard Worker         rc = -1;
551*598139dcSAndroid Build Coastguard Worker         goto err_open;
552*598139dcSAndroid Build Coastguard Worker     }
553*598139dcSAndroid Build Coastguard Worker 
554*598139dcSAndroid Build Coastguard Worker     char child_devname[64];
555*598139dcSAndroid Build Coastguard Worker     if (grantpt(parent_ptty) || unlockpt(parent_ptty) ||
556*598139dcSAndroid Build Coastguard Worker         ptsname_r(parent_ptty, child_devname, sizeof(child_devname)) != 0) {
557*598139dcSAndroid Build Coastguard Worker         ERROR("Problem with /dev/ptmx\n");
558*598139dcSAndroid Build Coastguard Worker         rc = -1;
559*598139dcSAndroid Build Coastguard Worker         goto err_ptty;
560*598139dcSAndroid Build Coastguard Worker     }
561*598139dcSAndroid Build Coastguard Worker 
562*598139dcSAndroid Build Coastguard Worker     if (forward_signals) {
563*598139dcSAndroid Build Coastguard Worker         // Block these signals until we have the child pid and our signal handlers set up.
564*598139dcSAndroid Build Coastguard Worker         block_signals(&oldset);
565*598139dcSAndroid Build Coastguard Worker     }
566*598139dcSAndroid Build Coastguard Worker 
567*598139dcSAndroid Build Coastguard Worker     pid = fork();
568*598139dcSAndroid Build Coastguard Worker     if (pid < 0) {
569*598139dcSAndroid Build Coastguard Worker         ERROR("Failed to fork\n");
570*598139dcSAndroid Build Coastguard Worker         rc = -1;
571*598139dcSAndroid Build Coastguard Worker         goto err_fork;
572*598139dcSAndroid Build Coastguard Worker     } else if (pid == 0) {
573*598139dcSAndroid Build Coastguard Worker         pthread_mutex_unlock(&fd_mutex);
574*598139dcSAndroid Build Coastguard Worker         if (forward_signals) {
575*598139dcSAndroid Build Coastguard Worker             unblock_signals(&oldset);
576*598139dcSAndroid Build Coastguard Worker         }
577*598139dcSAndroid Build Coastguard Worker 
578*598139dcSAndroid Build Coastguard Worker         setsid();
579*598139dcSAndroid Build Coastguard Worker 
580*598139dcSAndroid Build Coastguard Worker         int child_ptty = TEMP_FAILURE_RETRY(open(child_devname, O_RDWR | O_CLOEXEC));
581*598139dcSAndroid Build Coastguard Worker         if (child_ptty < 0) {
582*598139dcSAndroid Build Coastguard Worker             FATAL_CHILD("Cannot open child_ptty: %s\n", strerror(errno));
583*598139dcSAndroid Build Coastguard Worker         }
584*598139dcSAndroid Build Coastguard Worker         close(parent_ptty);
585*598139dcSAndroid Build Coastguard Worker 
586*598139dcSAndroid Build Coastguard Worker         dup2(child_ptty, 1);
587*598139dcSAndroid Build Coastguard Worker         dup2(child_ptty, 2);
588*598139dcSAndroid Build Coastguard Worker         close(child_ptty);
589*598139dcSAndroid Build Coastguard Worker 
590*598139dcSAndroid Build Coastguard Worker         child(argc, argv);
591*598139dcSAndroid Build Coastguard Worker     } else {
592*598139dcSAndroid Build Coastguard Worker         if (forward_signals) {
593*598139dcSAndroid Build Coastguard Worker             setup_signal_handlers(pid);
594*598139dcSAndroid Build Coastguard Worker             unblock_signals(&oldset);
595*598139dcSAndroid Build Coastguard Worker         }
596*598139dcSAndroid Build Coastguard Worker 
597*598139dcSAndroid Build Coastguard Worker         rc = parent(argv[0], parent_ptty, pid, status, log_target, abbreviated, file_path,
598*598139dcSAndroid Build Coastguard Worker                     forward_signals);
599*598139dcSAndroid Build Coastguard Worker 
600*598139dcSAndroid Build Coastguard Worker         if (forward_signals) {
601*598139dcSAndroid Build Coastguard Worker             restore_signal_handlers();
602*598139dcSAndroid Build Coastguard Worker         }
603*598139dcSAndroid Build Coastguard Worker     }
604*598139dcSAndroid Build Coastguard Worker 
605*598139dcSAndroid Build Coastguard Worker err_fork:
606*598139dcSAndroid Build Coastguard Worker     if (forward_signals) {
607*598139dcSAndroid Build Coastguard Worker         unblock_signals(&oldset);
608*598139dcSAndroid Build Coastguard Worker     }
609*598139dcSAndroid Build Coastguard Worker err_ptty:
610*598139dcSAndroid Build Coastguard Worker     close(parent_ptty);
611*598139dcSAndroid Build Coastguard Worker err_open:
612*598139dcSAndroid Build Coastguard Worker     pthread_mutex_unlock(&fd_mutex);
613*598139dcSAndroid Build Coastguard Worker err_lock:
614*598139dcSAndroid Build Coastguard Worker     return rc;
615*598139dcSAndroid Build Coastguard Worker }
616