summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorThe Android Open Source Project2008-12-17 20:08:08 -0600
committerThe Android Open Source Project2008-12-17 20:08:08 -0600
commit35237d135807af84bf9b0e5b8d7f8633e58db6f5 (patch)
treed8bcf3ada2182d248604728285dd80abb466f22a /logwrapper/logwrapper.c
parent4f6e8d7a00cbeda1e70cc15be9c4af1018bdad53 (diff)
downloadplatform-system-core-35237d135807af84bf9b0e5b8d7f8633e58db6f5.tar.gz
platform-system-core-35237d135807af84bf9b0e5b8d7f8633e58db6f5.tar.xz
platform-system-core-35237d135807af84bf9b0e5b8d7f8633e58db6f5.zip
Code drop from //branches/cupcake/...@124589
Diffstat (limited to 'logwrapper/logwrapper.c')
-rw-r--r--logwrapper/logwrapper.c99
1 files changed, 77 insertions, 22 deletions
diff --git a/logwrapper/logwrapper.c b/logwrapper/logwrapper.c
index c7a253460..f00bfbf3d 100644
--- a/logwrapper/logwrapper.c
+++ b/logwrapper/logwrapper.c
@@ -21,7 +21,9 @@
21#include <stdlib.h> 21#include <stdlib.h>
22#include <unistd.h> 22#include <unistd.h>
23#include <errno.h> 23#include <errno.h>
24#include <fcntl.h>
24 25
26#include "private/android_filesystem_config.h"
25#include "cutils/log.h" 27#include "cutils/log.h"
26 28
27void fatal(const char *msg) { 29void fatal(const char *msg) {
@@ -32,48 +34,74 @@ void fatal(const char *msg) {
32 34
33void usage() { 35void usage() {
34 fatal( 36 fatal(
35 "Usage: logwrapper BINARY [ARGS ...]\n" 37 "Usage: logwrapper [-x] BINARY [ARGS ...]\n"
36 "\n" 38 "\n"
37 "Forks and executes BINARY ARGS, redirecting stdout and stderr to\n" 39 "Forks and executes BINARY ARGS, redirecting stdout and stderr to\n"
38 "the Android logging system. Tag is set to BINARY, priority is\n" 40 "the Android logging system. Tag is set to BINARY, priority is\n"
39 "always LOG_INFO.\n"); 41 "always LOG_INFO.\n"
42 "\n"
43 "-x: Causes logwrapper to SIGSEGV when BINARY terminates\n"
44 " fault address is set to the status of wait()\n");
40} 45}
41 46
42void parent(const char *tag, int parent_read) { 47void parent(const char *tag, int seg_fault_on_exit, int parent_read) {
43 int status; 48 int status;
44 char buffer[1024]; 49 char buffer[4096];
45 50
46 int a = 0; // start index of unprocessed data 51 int a = 0; // start index of unprocessed data
47 int b = 0; // end index of unprocessed data 52 int b = 0; // end index of unprocessed data
48 int sz; 53 int sz;
49 while ((sz = read(parent_read, &buffer[b], 1023 - b)) > 0) { 54 while ((sz = read(parent_read, &buffer[b], sizeof(buffer) - 1 - b)) > 0) {
55
56 sz += b;
50 // Log one line at a time 57 // Log one line at a time
51 for (b = a; b < sz; b++) { 58 for (b = 0; b < sz; b++) {
52 if (buffer[b] == '\n') { 59 if (buffer[b] == '\r') {
60 buffer[b] = '\0';
61 } else if (buffer[b] == '\n') {
53 buffer[b] = '\0'; 62 buffer[b] = '\0';
54 LOG(LOG_INFO, tag, &buffer[a]); 63 LOG(LOG_INFO, tag, &buffer[a]);
55 a = b + 1; 64 a = b + 1;
56 } 65 }
57 } 66 }
58 67
59 if (a == 0 && b == 1023) { 68 if (a == 0 && b == sizeof(buffer) - 1) {
60 // buffer is full, flush 69 // buffer is full, flush
61 buffer[b] = '\0'; 70 buffer[b] = '\0';
62 LOG(LOG_INFO, tag, &buffer[a]); 71 LOG(LOG_INFO, tag, &buffer[a]);
63 b = 0; 72 b = 0;
64 } else { 73 } else if (a != b) {
65 // Keep left-overs 74 // Keep left-overs
66 b = sz - a; 75 b -= a;
67 memmove(buffer, &buffer[a], b); 76 memmove(buffer, &buffer[a], b);
68 a = 0; 77 a = 0;
78 } else {
79 a = 0;
80 b = 0;
69 } 81 }
82
70 } 83 }
71 // Flush remaining data 84 // Flush remaining data
72 if (a != b) { 85 if (a != b) {
73 buffer[b] = '\0'; 86 buffer[b] = '\0';
74 LOG(LOG_INFO, tag, &buffer[a]); 87 LOG(LOG_INFO, tag, &buffer[a]);
75 } 88 }
76 wait(&status); // Wait for child 89 status = 0xAAAA;
90 if (wait(&status) != -1) { // Wait for child
91 if (WIFEXITED(status))
92 LOG(LOG_INFO, "logwrapper", "%s terminated by exit(%d)", tag,
93 WEXITSTATUS(status));
94 else if (WIFSIGNALED(status))
95 LOG(LOG_INFO, "logwrapper", "%s terminated by signal %d", tag,
96 WTERMSIG(status));
97 else if (WIFSTOPPED(status))
98 LOG(LOG_INFO, "logwrapper", "%s stopped by signal %d", tag,
99 WSTOPSIG(status));
100 } else
101 LOG(LOG_INFO, "logwrapper", "%s wait() failed: %s (%d)", tag,
102 strerror(errno), errno);
103 if (seg_fault_on_exit)
104 *(int *)status = 0; // causes SIGSEGV with fault_address = status
77} 105}
78 106
79void child(int argc, char* argv[]) { 107void child(int argc, char* argv[]) {
@@ -91,35 +119,62 @@ void child(int argc, char* argv[]) {
91 119
92int main(int argc, char* argv[]) { 120int main(int argc, char* argv[]) {
93 pid_t pid; 121 pid_t pid;
122 int seg_fault_on_exit = 0;
123
124 int parent_ptty;
125 int child_ptty;
126 char *child_devname = NULL;
94 127
95 int pipe_fds[2]; 128 if (argc < 2) {
96 int *parent_read = &pipe_fds[0]; 129 usage();
97 int *child_write = &pipe_fds[1]; 130 }
131
132 if (strncmp(argv[1], "-d", 2) == 0) {
133 seg_fault_on_exit = 1;
134 argc--;
135 argv++;
136 }
98 137
99 if (argc < 2) { 138 if (argc < 2) {
100 usage(); 139 usage();
101 } 140 }
102 141
103 if (pipe(pipe_fds) < 0) { 142 /* Use ptty instead of socketpair so that STDOUT is not buffered */
104 fatal("Cannot create pipe\n"); 143 parent_ptty = open("/dev/ptmx", O_RDWR);
144 if (parent_ptty < 0) {
145 fatal("Cannot create parent ptty\n");
146 }
147
148 if (grantpt(parent_ptty) || unlockpt(parent_ptty) ||
149 ((child_devname = (char*)ptsname(parent_ptty)) == 0)) {
150 fatal("Problem with /dev/ptmx\n");
105 } 151 }
106 152
107 pid = fork(); 153 pid = fork();
108 if (pid < 0) { 154 if (pid < 0) {
109 fatal("Failed to fork\n"); 155 fatal("Failed to fork\n");
110 } else if (pid == 0) { 156 } else if (pid == 0) {
157 child_ptty = open(child_devname, O_RDWR);
158 if (child_ptty < 0) {
159 fatal("Problem with child ptty\n");
160 }
161
111 // redirect stdout and stderr 162 // redirect stdout and stderr
112 close(*parent_read); 163 close(parent_ptty);
113 dup2(*child_write, 1); 164 dup2(child_ptty, 1);
114 dup2(*child_write, 2); 165 dup2(child_ptty, 2);
115 close(*child_write); 166 close(child_ptty);
116 167
117 child(argc - 1, &argv[1]); 168 child(argc - 1, &argv[1]);
118 169
119 } else { 170 } else {
120 close(*child_write); 171 // switch user and group to "log"
172 // this may fail if we are not root,
173 // but in that case switching user/group is unnecessary
174 setgid(AID_LOG);
175 setuid(AID_LOG);
121 176
122 parent(argv[1], *parent_read); 177 parent(argv[1], seg_fault_on_exit, parent_ptty);
123 } 178 }
124 179
125 return 0; 180 return 0;