xref: /aosp_15_r20/system/logging/logwrapper/logwrapper.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 <stdio.h>
19*598139dcSAndroid Build Coastguard Worker #include <stdlib.h>
20*598139dcSAndroid Build Coastguard Worker #include <sys/wait.h>
21*598139dcSAndroid Build Coastguard Worker #include <unistd.h>
22*598139dcSAndroid Build Coastguard Worker 
23*598139dcSAndroid Build Coastguard Worker #include <cutils/klog.h>
24*598139dcSAndroid Build Coastguard Worker #include <log/log.h>
25*598139dcSAndroid Build Coastguard Worker #include <logwrap/logwrap.h>
26*598139dcSAndroid Build Coastguard Worker 
fatal(const char * msg)27*598139dcSAndroid Build Coastguard Worker void fatal(const char* msg) {
28*598139dcSAndroid Build Coastguard Worker     fprintf(stderr, "%s", msg);
29*598139dcSAndroid Build Coastguard Worker     ALOG(LOG_ERROR, "logwrapper", "%s", msg);
30*598139dcSAndroid Build Coastguard Worker     exit(-1);
31*598139dcSAndroid Build Coastguard Worker }
32*598139dcSAndroid Build Coastguard Worker 
usage()33*598139dcSAndroid Build Coastguard Worker void usage() {
34*598139dcSAndroid Build Coastguard Worker     fatal("Usage: logwrapper [-a] [-d] [-k] BINARY [ARGS ...]\n"
35*598139dcSAndroid Build Coastguard Worker           "\n"
36*598139dcSAndroid Build Coastguard Worker           "Forks and executes BINARY ARGS, redirecting stdout and stderr to\n"
37*598139dcSAndroid Build Coastguard Worker           "the Android logging system. Tag is set to BINARY, priority is\n"
38*598139dcSAndroid Build Coastguard Worker           "always LOG_INFO.\n"
39*598139dcSAndroid Build Coastguard Worker           "\n"
40*598139dcSAndroid Build Coastguard Worker           "-a: Causes logwrapper to do abbreviated logging.\n"
41*598139dcSAndroid Build Coastguard Worker           "    This logs up to the first 4K and last 4K of the command\n"
42*598139dcSAndroid Build Coastguard Worker           "    being run, and logs the output when the command exits\n"
43*598139dcSAndroid Build Coastguard Worker           "-d: Causes logwrapper to SIGSEGV when BINARY terminates\n"
44*598139dcSAndroid Build Coastguard Worker           "    fault address is set to the status of wait()\n"
45*598139dcSAndroid Build Coastguard Worker           "-k: Causes logwrapper to log to the kernel log instead of\n"
46*598139dcSAndroid Build Coastguard Worker           "    the Android system log\n");
47*598139dcSAndroid Build Coastguard Worker }
48*598139dcSAndroid Build Coastguard Worker 
main(int argc,char * argv[])49*598139dcSAndroid Build Coastguard Worker int main(int argc, char* argv[]) {
50*598139dcSAndroid Build Coastguard Worker     int seg_fault_on_exit = 0;
51*598139dcSAndroid Build Coastguard Worker     int log_target = LOG_ALOG;
52*598139dcSAndroid Build Coastguard Worker     bool abbreviated = false;
53*598139dcSAndroid Build Coastguard Worker     int ch;
54*598139dcSAndroid Build Coastguard Worker     int status = 0xAAAA;
55*598139dcSAndroid Build Coastguard Worker     int rc;
56*598139dcSAndroid Build Coastguard Worker 
57*598139dcSAndroid Build Coastguard Worker     while ((ch = getopt(argc, argv, "adk")) != -1) {
58*598139dcSAndroid Build Coastguard Worker         switch (ch) {
59*598139dcSAndroid Build Coastguard Worker             case 'a':
60*598139dcSAndroid Build Coastguard Worker                 abbreviated = true;
61*598139dcSAndroid Build Coastguard Worker                 break;
62*598139dcSAndroid Build Coastguard Worker             case 'd':
63*598139dcSAndroid Build Coastguard Worker                 seg_fault_on_exit = 1;
64*598139dcSAndroid Build Coastguard Worker                 break;
65*598139dcSAndroid Build Coastguard Worker             case 'k':
66*598139dcSAndroid Build Coastguard Worker                 log_target = LOG_KLOG;
67*598139dcSAndroid Build Coastguard Worker                 klog_set_level(6);
68*598139dcSAndroid Build Coastguard Worker                 break;
69*598139dcSAndroid Build Coastguard Worker             case '?':
70*598139dcSAndroid Build Coastguard Worker             default:
71*598139dcSAndroid Build Coastguard Worker                 usage();
72*598139dcSAndroid Build Coastguard Worker         }
73*598139dcSAndroid Build Coastguard Worker     }
74*598139dcSAndroid Build Coastguard Worker     argc -= optind;
75*598139dcSAndroid Build Coastguard Worker     argv += optind;
76*598139dcSAndroid Build Coastguard Worker 
77*598139dcSAndroid Build Coastguard Worker     if (argc < 1) {
78*598139dcSAndroid Build Coastguard Worker         usage();
79*598139dcSAndroid Build Coastguard Worker     }
80*598139dcSAndroid Build Coastguard Worker 
81*598139dcSAndroid Build Coastguard Worker     rc = logwrap_fork_execvp(argc, &argv[0], &status, true, log_target, abbreviated, nullptr);
82*598139dcSAndroid Build Coastguard Worker     if (!rc) {
83*598139dcSAndroid Build Coastguard Worker         if (WIFEXITED(status))
84*598139dcSAndroid Build Coastguard Worker             rc = WEXITSTATUS(status);
85*598139dcSAndroid Build Coastguard Worker         else
86*598139dcSAndroid Build Coastguard Worker             rc = -ECHILD;
87*598139dcSAndroid Build Coastguard Worker     }
88*598139dcSAndroid Build Coastguard Worker 
89*598139dcSAndroid Build Coastguard Worker     if (seg_fault_on_exit) {
90*598139dcSAndroid Build Coastguard Worker         uintptr_t fault_address = (uintptr_t)status;
91*598139dcSAndroid Build Coastguard Worker         *(int*)fault_address = 0;  // causes SIGSEGV with fault_address = status
92*598139dcSAndroid Build Coastguard Worker     }
93*598139dcSAndroid Build Coastguard Worker 
94*598139dcSAndroid Build Coastguard Worker     return rc;
95*598139dcSAndroid Build Coastguard Worker }
96