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