• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2012-2014 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #include <arpa/inet.h>
18 #include <ctype.h>
19 #include <dirent.h>
20 #include <errno.h>
21 #include <fcntl.h>
22 #include <netinet/in.h>
23 #include <stdlib.h>
24 #include <string.h>
25 #include <sys/prctl.h>
26 #include <sys/socket.h>
27 #include <sys/types.h>
28 
29 #include <string>
30 
31 #include <android-base/stringprintf.h>
32 #include <cutils/sockets.h>
33 #include <private/android_filesystem_config.h>
34 #include <sysutils/SocketClient.h>
35 
36 #include "CommandListener.h"
37 #include "LogCommand.h"
38 #include "LogUtils.h"
39 
CommandListener(LogBuffer * buf,LogReader *,LogListener *)40 CommandListener::CommandListener(LogBuffer* buf, LogReader* /*reader*/,
41                                  LogListener* /*swl*/)
42     : FrameworkListener(getLogSocket()) {
43     // registerCmd(new ShutdownCmd(buf, writer, swl));
44     registerCmd(new ClearCmd(buf));
45     registerCmd(new GetBufSizeCmd(buf));
46     registerCmd(new SetBufSizeCmd(buf));
47     registerCmd(new GetBufSizeUsedCmd(buf));
48     registerCmd(new GetStatisticsCmd(buf));
49     registerCmd(new SetPruneListCmd(buf));
50     registerCmd(new GetPruneListCmd(buf));
51     registerCmd(new GetEventTagCmd(buf));
52     registerCmd(new ReinitCmd());
53     registerCmd(new ExitCmd(this));
54 }
55 
ShutdownCmd(LogReader * reader,LogListener * swl)56 CommandListener::ShutdownCmd::ShutdownCmd(LogReader* reader, LogListener* swl)
57     : LogCommand("shutdown"), mReader(*reader), mSwl(*swl) {
58 }
59 
runCommand(SocketClient *,int,char **)60 int CommandListener::ShutdownCmd::runCommand(SocketClient* /*cli*/,
61                                              int /*argc*/, char** /*argv*/) {
62     mSwl.stopListener();
63     mReader.stopListener();
64     exit(0);
65 }
66 
ClearCmd(LogBuffer * buf)67 CommandListener::ClearCmd::ClearCmd(LogBuffer* buf)
68     : LogCommand("clear"), mBuf(*buf) {
69 }
70 
setname()71 static void setname() {
72     static bool name_set;
73     if (!name_set) {
74         prctl(PR_SET_NAME, "logd.control");
75         name_set = true;
76     }
77 }
78 
runCommand(SocketClient * cli,int argc,char ** argv)79 int CommandListener::ClearCmd::runCommand(SocketClient* cli, int argc,
80                                           char** argv) {
81     setname();
82     uid_t uid = cli->getUid();
83     if (clientHasLogCredentials(cli)) {
84         uid = AID_ROOT;
85     }
86 
87     if (argc < 2) {
88         cli->sendMsg("Missing Argument");
89         return 0;
90     }
91 
92     int id = atoi(argv[1]);
93     if ((id < LOG_ID_MIN) || (LOG_ID_MAX <= id)) {
94         cli->sendMsg("Range Error");
95         return 0;
96     }
97 
98     cli->sendMsg(mBuf.clear((log_id_t)id, uid) ? "busy" : "success");
99     return 0;
100 }
101 
GetBufSizeCmd(LogBuffer * buf)102 CommandListener::GetBufSizeCmd::GetBufSizeCmd(LogBuffer* buf)
103     : LogCommand("getLogSize"), mBuf(*buf) {
104 }
105 
runCommand(SocketClient * cli,int argc,char ** argv)106 int CommandListener::GetBufSizeCmd::runCommand(SocketClient* cli, int argc,
107                                                char** argv) {
108     setname();
109     if (argc < 2) {
110         cli->sendMsg("Missing Argument");
111         return 0;
112     }
113 
114     int id = atoi(argv[1]);
115     if ((id < LOG_ID_MIN) || (LOG_ID_MAX <= id)) {
116         cli->sendMsg("Range Error");
117         return 0;
118     }
119 
120     unsigned long size = mBuf.getSize((log_id_t)id);
121     char buf[512];
122     snprintf(buf, sizeof(buf), "%lu", size);
123     cli->sendMsg(buf);
124     return 0;
125 }
126 
SetBufSizeCmd(LogBuffer * buf)127 CommandListener::SetBufSizeCmd::SetBufSizeCmd(LogBuffer* buf)
128     : LogCommand("setLogSize"), mBuf(*buf) {
129 }
130 
runCommand(SocketClient * cli,int argc,char ** argv)131 int CommandListener::SetBufSizeCmd::runCommand(SocketClient* cli, int argc,
132                                                char** argv) {
133     setname();
134     if (!clientHasLogCredentials(cli)) {
135         cli->sendMsg("Permission Denied");
136         return 0;
137     }
138 
139     if (argc < 3) {
140         cli->sendMsg("Missing Argument");
141         return 0;
142     }
143 
144     int id = atoi(argv[1]);
145     if ((id < LOG_ID_MIN) || (LOG_ID_MAX <= id)) {
146         cli->sendMsg("Range Error");
147         return 0;
148     }
149 
150     unsigned long size = atol(argv[2]);
151     if (mBuf.setSize((log_id_t)id, size)) {
152         cli->sendMsg("Range Error");
153         return 0;
154     }
155 
156     cli->sendMsg("success");
157     return 0;
158 }
159 
GetBufSizeUsedCmd(LogBuffer * buf)160 CommandListener::GetBufSizeUsedCmd::GetBufSizeUsedCmd(LogBuffer* buf)
161     : LogCommand("getLogSizeUsed"), mBuf(*buf) {
162 }
163 
runCommand(SocketClient * cli,int argc,char ** argv)164 int CommandListener::GetBufSizeUsedCmd::runCommand(SocketClient* cli, int argc,
165                                                    char** argv) {
166     setname();
167     if (argc < 2) {
168         cli->sendMsg("Missing Argument");
169         return 0;
170     }
171 
172     int id = atoi(argv[1]);
173     if ((id < LOG_ID_MIN) || (LOG_ID_MAX <= id)) {
174         cli->sendMsg("Range Error");
175         return 0;
176     }
177 
178     unsigned long size = mBuf.getSizeUsed((log_id_t)id);
179     char buf[512];
180     snprintf(buf, sizeof(buf), "%lu", size);
181     cli->sendMsg(buf);
182     return 0;
183 }
184 
GetStatisticsCmd(LogBuffer * buf)185 CommandListener::GetStatisticsCmd::GetStatisticsCmd(LogBuffer* buf)
186     : LogCommand("getStatistics"), mBuf(*buf) {
187 }
188 
package_string(const std::string & str)189 static std::string package_string(const std::string& str) {
190     // Calculate total buffer size prefix, count is the string length w/o nul
191     char fmt[32];
192     for (size_t l = str.length(), y = 0, x = 6; y != x;
193          y = x, x = strlen(fmt) - 2) {
194         snprintf(fmt, sizeof(fmt), "%zu\n%%s\n\f", l + x);
195     }
196     return android::base::StringPrintf(fmt, str.c_str());
197 }
198 
runCommand(SocketClient * cli,int argc,char ** argv)199 int CommandListener::GetStatisticsCmd::runCommand(SocketClient* cli, int argc,
200                                                   char** argv) {
201     setname();
202     uid_t uid = cli->getUid();
203     if (clientHasLogCredentials(cli)) {
204         uid = AID_ROOT;
205     }
206 
207     unsigned int logMask = -1;
208     pid_t pid = 0;
209     if (argc > 1) {
210         logMask = 0;
211         for (int i = 1; i < argc; ++i) {
212             static const char _pid[] = "pid=";
213             if (!strncmp(argv[i], _pid, sizeof(_pid) - 1)) {
214                 pid = atol(argv[i] + sizeof(_pid) - 1);
215                 if (pid == 0) {
216                     cli->sendMsg("PID Error");
217                     return 0;
218                 }
219                 continue;
220             }
221 
222             int id = atoi(argv[i]);
223             if ((id < LOG_ID_MIN) || (LOG_ID_MAX <= id)) {
224                 cli->sendMsg("Range Error");
225                 return 0;
226             }
227             logMask |= 1 << id;
228         }
229     }
230 
231     cli->sendMsg(
232         package_string(mBuf.formatStatistics(uid, pid, logMask)).c_str());
233     return 0;
234 }
235 
GetPruneListCmd(LogBuffer * buf)236 CommandListener::GetPruneListCmd::GetPruneListCmd(LogBuffer* buf)
237     : LogCommand("getPruneList"), mBuf(*buf) {
238 }
239 
runCommand(SocketClient * cli,int,char **)240 int CommandListener::GetPruneListCmd::runCommand(SocketClient* cli,
241                                                  int /*argc*/, char** /*argv*/) {
242     setname();
243     cli->sendMsg(package_string(mBuf.formatPrune()).c_str());
244     return 0;
245 }
246 
SetPruneListCmd(LogBuffer * buf)247 CommandListener::SetPruneListCmd::SetPruneListCmd(LogBuffer* buf)
248     : LogCommand("setPruneList"), mBuf(*buf) {
249 }
250 
runCommand(SocketClient * cli,int argc,char ** argv)251 int CommandListener::SetPruneListCmd::runCommand(SocketClient* cli, int argc,
252                                                  char** argv) {
253     setname();
254     if (!clientHasLogCredentials(cli)) {
255         cli->sendMsg("Permission Denied");
256         return 0;
257     }
258 
259     std::string str;
260     for (int i = 1; i < argc; ++i) {
261         if (str.length()) {
262             str += " ";
263         }
264         str += argv[i];
265     }
266 
267     int ret = mBuf.initPrune(str.c_str());
268 
269     if (ret) {
270         cli->sendMsg("Invalid");
271         return 0;
272     }
273 
274     cli->sendMsg("success");
275 
276     return 0;
277 }
278 
GetEventTagCmd(LogBuffer * buf)279 CommandListener::GetEventTagCmd::GetEventTagCmd(LogBuffer* buf)
280     : LogCommand("getEventTag"), mBuf(*buf) {
281 }
282 
runCommand(SocketClient * cli,int argc,char ** argv)283 int CommandListener::GetEventTagCmd::runCommand(SocketClient* cli, int argc,
284                                                 char** argv) {
285     setname();
286     uid_t uid = cli->getUid();
287     if (clientHasLogCredentials(cli)) {
288         uid = AID_ROOT;
289     }
290 
291     const char* name = nullptr;
292     const char* format = nullptr;
293     const char* id = nullptr;
294     for (int i = 1; i < argc; ++i) {
295         static const char _name[] = "name=";
296         if (!strncmp(argv[i], _name, strlen(_name))) {
297             name = argv[i] + strlen(_name);
298             continue;
299         }
300 
301         static const char _format[] = "format=";
302         if (!strncmp(argv[i], _format, strlen(_format))) {
303             format = argv[i] + strlen(_format);
304             continue;
305         }
306 
307         static const char _id[] = "id=";
308         if (!strncmp(argv[i], _id, strlen(_id))) {
309             id = argv[i] + strlen(_id);
310             continue;
311         }
312     }
313 
314     if (id) {
315         if (format || name) {
316             cli->sendMsg("can not mix id= with either format= or name=");
317             return 0;
318         }
319         cli->sendMsg(package_string(mBuf.formatEntry(atoi(id), uid)).c_str());
320         return 0;
321     }
322 
323     cli->sendMsg(
324         package_string(mBuf.formatGetEventTag(uid, name, format)).c_str());
325 
326     return 0;
327 }
328 
ReinitCmd()329 CommandListener::ReinitCmd::ReinitCmd() : LogCommand("reinit") {
330 }
331 
runCommand(SocketClient * cli,int,char **)332 int CommandListener::ReinitCmd::runCommand(SocketClient* cli, int /*argc*/,
333                                            char** /*argv*/) {
334     setname();
335 
336     reinit_signal_handler(SIGHUP);
337 
338     cli->sendMsg("success");
339 
340     return 0;
341 }
342 
ExitCmd(CommandListener * parent)343 CommandListener::ExitCmd::ExitCmd(CommandListener* parent)
344     : LogCommand("EXIT"), mParent(*parent) {
345 }
346 
runCommand(SocketClient * cli,int,char **)347 int CommandListener::ExitCmd::runCommand(SocketClient* cli, int /*argc*/,
348                                          char** /*argv*/) {
349     setname();
350 
351     cli->sendMsg("success");
352     release(cli);
353 
354     return 0;
355 }
356 
getLogSocket()357 int CommandListener::getLogSocket() {
358     static const char socketName[] = "logd";
359     int sock = android_get_control_socket(socketName);
360 
361     if (sock < 0) {
362         sock = socket_local_server(
363             socketName, ANDROID_SOCKET_NAMESPACE_RESERVED, SOCK_STREAM);
364     }
365 
366     return sock;
367 }
368