CommandListener.cpp revision 1c950479393d42d18829d4009dbdb3a7f03acbb7
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 <dirent.h>
19#include <errno.h>
20#include <fcntl.h>
21#include <netinet/in.h>
22#include <string.h>
23#include <stdlib.h>
24#include <sys/socket.h>
25#include <sys/types.h>
26
27#include <private/android_filesystem_config.h>
28#include <sysutils/SocketClient.h>
29
30#include "CommandListener.h"
31#include "LogCommand.h"
32
33CommandListener::CommandListener(LogBuffer *buf, LogReader * /*reader*/,
34                                 LogListener * /*swl*/)
35        : FrameworkListener("logd")
36        , mBuf(*buf) {
37    // registerCmd(new ShutdownCmd(buf, writer, swl));
38    registerCmd(new ClearCmd(buf));
39    registerCmd(new GetBufSizeCmd(buf));
40    registerCmd(new SetBufSizeCmd(buf));
41    registerCmd(new GetBufSizeUsedCmd(buf));
42    registerCmd(new GetStatisticsCmd(buf));
43    registerCmd(new SetPruneListCmd(buf));
44    registerCmd(new GetPruneListCmd(buf));
45}
46
47CommandListener::ShutdownCmd::ShutdownCmd(LogBuffer *buf, LogReader *reader,
48                                          LogListener *swl)
49        : LogCommand("shutdown")
50        , mBuf(*buf)
51        , mReader(*reader)
52        , mSwl(*swl)
53{ }
54
55int CommandListener::ShutdownCmd::runCommand(SocketClient * /*cli*/,
56                                             int /*argc*/,
57                                             char ** /*argv*/) {
58    mSwl.stopListener();
59    mReader.stopListener();
60    exit(0);
61}
62
63CommandListener::ClearCmd::ClearCmd(LogBuffer *buf)
64        : LogCommand("clear")
65        , mBuf(*buf)
66{ }
67
68int CommandListener::ClearCmd::runCommand(SocketClient *cli,
69                                         int argc, char **argv) {
70    if (!clientHasLogCredentials(cli)) {
71        cli->sendMsg("Permission Denied");
72        return 0;
73    }
74
75    if (argc < 2) {
76        cli->sendMsg("Missing Argument");
77        return 0;
78    }
79
80    int id = atoi(argv[1]);
81    if ((id < LOG_ID_MIN) || (LOG_ID_MAX <= id)) {
82        cli->sendMsg("Range Error");
83        return 0;
84    }
85
86    mBuf.clear((log_id_t) id);
87    cli->sendMsg("success");
88    return 0;
89}
90
91CommandListener::GetBufSizeCmd::GetBufSizeCmd(LogBuffer *buf)
92        : LogCommand("getLogSize")
93        , mBuf(*buf)
94{ }
95
96int CommandListener::GetBufSizeCmd::runCommand(SocketClient *cli,
97                                         int argc, char **argv) {
98    if (argc < 2) {
99        cli->sendMsg("Missing Argument");
100        return 0;
101    }
102
103    int id = atoi(argv[1]);
104    if ((id < LOG_ID_MIN) || (LOG_ID_MAX <= id)) {
105        cli->sendMsg("Range Error");
106        return 0;
107    }
108
109    unsigned long size = mBuf.getSize((log_id_t) id);
110    char buf[512];
111    snprintf(buf, sizeof(buf), "%lu", size);
112    cli->sendMsg(buf);
113    return 0;
114}
115
116CommandListener::SetBufSizeCmd::SetBufSizeCmd(LogBuffer *buf)
117        : LogCommand("setLogSize")
118        , mBuf(*buf)
119{ }
120
121int CommandListener::SetBufSizeCmd::runCommand(SocketClient *cli,
122                                         int argc, char **argv) {
123    if (!clientHasLogCredentials(cli)) {
124        cli->sendMsg("Permission Denied");
125        return 0;
126    }
127
128    if (argc < 3) {
129        cli->sendMsg("Missing Argument");
130        return 0;
131    }
132
133    int id = atoi(argv[1]);
134    if ((id < LOG_ID_MIN) || (LOG_ID_MAX <= id)) {
135        cli->sendMsg("Range Error");
136        return 0;
137    }
138
139    unsigned long size = atol(argv[2]);
140    if (mBuf.setSize((log_id_t) id, size)) {
141        cli->sendMsg("Range Error");
142        return 0;
143    }
144
145    cli->sendMsg("success");
146    return 0;
147}
148
149CommandListener::GetBufSizeUsedCmd::GetBufSizeUsedCmd(LogBuffer *buf)
150        : LogCommand("getLogSizeUsed")
151        , mBuf(*buf)
152{ }
153
154int CommandListener::GetBufSizeUsedCmd::runCommand(SocketClient *cli,
155                                         int argc, char **argv) {
156    if (argc < 2) {
157        cli->sendMsg("Missing Argument");
158        return 0;
159    }
160
161    int id = atoi(argv[1]);
162    if ((id < LOG_ID_MIN) || (LOG_ID_MAX <= id)) {
163        cli->sendMsg("Range Error");
164        return 0;
165    }
166
167    unsigned long size = mBuf.getSizeUsed((log_id_t) id);
168    char buf[512];
169    snprintf(buf, sizeof(buf), "%lu", size);
170    cli->sendMsg(buf);
171    return 0;
172}
173
174CommandListener::GetStatisticsCmd::GetStatisticsCmd(LogBuffer *buf)
175        : LogCommand("getStatistics")
176        , mBuf(*buf)
177{ }
178
179static void package_string(char **strp) {
180    const char *a = *strp;
181    if (!a) {
182        a = "";
183    }
184
185    // Calculate total buffer size prefix, count is the string length w/o nul
186    char fmt[32];
187    for(size_t l = strlen(a), y = 0, x = 6; y != x; y = x, x = strlen(fmt) - 2) {
188        snprintf(fmt, sizeof(fmt), "%zu\n%%s\n\f", l + x);
189    }
190
191    char *b = *strp;
192    *strp = NULL;
193    asprintf(strp, fmt, a);
194    free(b);
195}
196
197int CommandListener::GetStatisticsCmd::runCommand(SocketClient *cli,
198                                         int argc, char **argv) {
199    uid_t uid = cli->getUid();
200    gid_t gid = cli->getGid();
201    if (clientHasLogCredentials(cli)) {
202        uid = AID_ROOT;
203    }
204
205    unsigned int logMask = -1;
206    if (argc > 1) {
207        logMask = 0;
208        for (int i = 1; i < argc; ++i) {
209            int id = atoi(argv[i]);
210            if ((id < LOG_ID_MIN) || (LOG_ID_MAX <= id)) {
211                cli->sendMsg("Range Error");
212                return 0;
213            }
214            logMask |= 1 << id;
215        }
216    }
217
218    char *buf = NULL;
219
220    mBuf.formatStatistics(&buf, uid, logMask);
221    if (!buf) {
222        cli->sendMsg("Failed");
223    } else {
224        package_string(&buf);
225        cli->sendMsg(buf);
226        free(buf);
227    }
228    return 0;
229}
230
231CommandListener::GetPruneListCmd::GetPruneListCmd(LogBuffer *buf)
232        : LogCommand("getPruneList")
233        , mBuf(*buf)
234{ }
235
236int CommandListener::GetPruneListCmd::runCommand(SocketClient *cli,
237                                         int /*argc*/, char ** /*argv*/) {
238    char *buf = NULL;
239    mBuf.formatPrune(&buf);
240    if (!buf) {
241        cli->sendMsg("Failed");
242    } else {
243        package_string(&buf);
244        cli->sendMsg(buf);
245        free(buf);
246    }
247    return 0;
248}
249
250CommandListener::SetPruneListCmd::SetPruneListCmd(LogBuffer *buf)
251        : LogCommand("setPruneList")
252        , mBuf(*buf)
253{ }
254
255int CommandListener::SetPruneListCmd::runCommand(SocketClient *cli,
256                                         int argc, char **argv) {
257    if (!clientHasLogCredentials(cli)) {
258        cli->sendMsg("Permission Denied");
259        return 0;
260    }
261
262    char *cp = NULL;
263    for (int i = 1; i < argc; ++i) {
264        char *p = cp;
265        if (p) {
266            cp = NULL;
267            asprintf(&cp, "%s %s", p, argv[i]);
268            free(p);
269        } else {
270            asprintf(&cp, "%s", argv[i]);
271        }
272    }
273
274    int ret = mBuf.initPrune(cp);
275    free(cp);
276
277    if (ret) {
278        cli->sendMsg("Invalid");
279        return 0;
280    }
281
282    cli->sendMsg("success");
283
284    return 0;
285}
286