diff options
author | The Android Open Source Project | 2008-12-17 20:08:08 -0600 |
---|---|---|
committer | The Android Open Source Project | 2008-12-17 20:08:08 -0600 |
commit | 35237d135807af84bf9b0e5b8d7f8633e58db6f5 (patch) | |
tree | d8bcf3ada2182d248604728285dd80abb466f22a /logwrapper/logwrapper.c | |
parent | 4f6e8d7a00cbeda1e70cc15be9c4af1018bdad53 (diff) | |
download | platform-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.c | 99 |
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 | ||
27 | void fatal(const char *msg) { | 29 | void fatal(const char *msg) { |
@@ -32,48 +34,74 @@ void fatal(const char *msg) { | |||
32 | 34 | ||
33 | void usage() { | 35 | void 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 | ||
42 | void parent(const char *tag, int parent_read) { | 47 | void 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 | ||
79 | void child(int argc, char* argv[]) { | 107 | void child(int argc, char* argv[]) { |
@@ -91,35 +119,62 @@ void child(int argc, char* argv[]) { | |||
91 | 119 | ||
92 | int main(int argc, char* argv[]) { | 120 | int 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; |