Home | History | Annotate | Download | only in logd
      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/prctl.h>
     25 #include <sys/socket.h>
     26 #include <sys/types.h>
     27 
     28 #include <cutils/sockets.h>
     29 #include <private/android_filesystem_config.h>
     30 #include <sysutils/SocketClient.h>
     31 
     32 #include "CommandListener.h"
     33 #include "LogCommand.h"
     34 
     35 CommandListener::CommandListener(LogBuffer *buf, LogReader * /*reader*/,
     36                                  LogListener * /*swl*/) :
     37         FrameworkListener(getLogSocket()),
     38         mBuf(*buf) {
     39     // registerCmd(new ShutdownCmd(buf, writer, swl));
     40     registerCmd(new ClearCmd(buf));
     41     registerCmd(new GetBufSizeCmd(buf));
     42     registerCmd(new SetBufSizeCmd(buf));
     43     registerCmd(new GetBufSizeUsedCmd(buf));
     44     registerCmd(new GetStatisticsCmd(buf));
     45     registerCmd(new SetPruneListCmd(buf));
     46     registerCmd(new GetPruneListCmd(buf));
     47     registerCmd(new ReinitCmd());
     48 }
     49 
     50 CommandListener::ShutdownCmd::ShutdownCmd(LogBuffer *buf, LogReader *reader,
     51                                           LogListener *swl) :
     52         LogCommand("shutdown"),
     53         mBuf(*buf),
     54         mReader(*reader),
     55         mSwl(*swl) {
     56 }
     57 
     58 int CommandListener::ShutdownCmd::runCommand(SocketClient * /*cli*/,
     59                                              int /*argc*/,
     60                                              char ** /*argv*/) {
     61     mSwl.stopListener();
     62     mReader.stopListener();
     63     exit(0);
     64 }
     65 
     66 CommandListener::ClearCmd::ClearCmd(LogBuffer *buf) :
     67         LogCommand("clear"),
     68         mBuf(*buf) {
     69 }
     70 
     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 
     79 int CommandListener::ClearCmd::runCommand(SocketClient *cli,
     80                                          int argc, 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     mBuf.clear((log_id_t) id, uid);
     99     cli->sendMsg("success");
    100     return 0;
    101 }
    102 
    103 CommandListener::GetBufSizeCmd::GetBufSizeCmd(LogBuffer *buf) :
    104         LogCommand("getLogSize"),
    105         mBuf(*buf) {
    106 }
    107 
    108 int CommandListener::GetBufSizeCmd::runCommand(SocketClient *cli,
    109                                          int argc, char **argv) {
    110     setname();
    111     if (argc < 2) {
    112         cli->sendMsg("Missing Argument");
    113         return 0;
    114     }
    115 
    116     int id = atoi(argv[1]);
    117     if ((id < LOG_ID_MIN) || (LOG_ID_MAX <= id)) {
    118         cli->sendMsg("Range Error");
    119         return 0;
    120     }
    121 
    122     unsigned long size = mBuf.getSize((log_id_t) id);
    123     char buf[512];
    124     snprintf(buf, sizeof(buf), "%lu", size);
    125     cli->sendMsg(buf);
    126     return 0;
    127 }
    128 
    129 CommandListener::SetBufSizeCmd::SetBufSizeCmd(LogBuffer *buf) :
    130         LogCommand("setLogSize"),
    131         mBuf(*buf) {
    132 }
    133 
    134 int CommandListener::SetBufSizeCmd::runCommand(SocketClient *cli,
    135                                          int argc, char **argv) {
    136     setname();
    137     if (!clientHasLogCredentials(cli)) {
    138         cli->sendMsg("Permission Denied");
    139         return 0;
    140     }
    141 
    142     if (argc < 3) {
    143         cli->sendMsg("Missing Argument");
    144         return 0;
    145     }
    146 
    147     int id = atoi(argv[1]);
    148     if ((id < LOG_ID_MIN) || (LOG_ID_MAX <= id)) {
    149         cli->sendMsg("Range Error");
    150         return 0;
    151     }
    152 
    153     unsigned long size = atol(argv[2]);
    154     if (mBuf.setSize((log_id_t) id, size)) {
    155         cli->sendMsg("Range Error");
    156         return 0;
    157     }
    158 
    159     cli->sendMsg("success");
    160     return 0;
    161 }
    162 
    163 CommandListener::GetBufSizeUsedCmd::GetBufSizeUsedCmd(LogBuffer *buf) :
    164         LogCommand("getLogSizeUsed"),
    165         mBuf(*buf) {
    166 }
    167 
    168 int CommandListener::GetBufSizeUsedCmd::runCommand(SocketClient *cli,
    169                                          int argc, char **argv) {
    170     setname();
    171     if (argc < 2) {
    172         cli->sendMsg("Missing Argument");
    173         return 0;
    174     }
    175 
    176     int id = atoi(argv[1]);
    177     if ((id < LOG_ID_MIN) || (LOG_ID_MAX <= id)) {
    178         cli->sendMsg("Range Error");
    179         return 0;
    180     }
    181 
    182     unsigned long size = mBuf.getSizeUsed((log_id_t) id);
    183     char buf[512];
    184     snprintf(buf, sizeof(buf), "%lu", size);
    185     cli->sendMsg(buf);
    186     return 0;
    187 }
    188 
    189 CommandListener::GetStatisticsCmd::GetStatisticsCmd(LogBuffer *buf) :
    190         LogCommand("getStatistics"),
    191         mBuf(*buf) {
    192 }
    193 
    194 static void package_string(char **strp) {
    195     const char *a = *strp;
    196     if (!a) {
    197         a = "";
    198     }
    199 
    200     // Calculate total buffer size prefix, count is the string length w/o nul
    201     char fmt[32];
    202     for(size_t l = strlen(a), y = 0, x = 6; y != x; y = x, x = strlen(fmt) - 2) {
    203         snprintf(fmt, sizeof(fmt), "%zu\n%%s\n\f", l + x);
    204     }
    205 
    206     char *b = *strp;
    207     *strp = NULL;
    208     asprintf(strp, fmt, a);
    209     free(b);
    210 }
    211 
    212 int CommandListener::GetStatisticsCmd::runCommand(SocketClient *cli,
    213                                          int argc, char **argv) {
    214     setname();
    215     uid_t uid = cli->getUid();
    216     if (clientHasLogCredentials(cli)) {
    217         uid = AID_ROOT;
    218     }
    219 
    220     unsigned int logMask = -1;
    221     if (argc > 1) {
    222         logMask = 0;
    223         for (int i = 1; i < argc; ++i) {
    224             int id = atoi(argv[i]);
    225             if ((id < LOG_ID_MIN) || (LOG_ID_MAX <= id)) {
    226                 cli->sendMsg("Range Error");
    227                 return 0;
    228             }
    229             logMask |= 1 << id;
    230         }
    231     }
    232 
    233     char *buf = NULL;
    234 
    235     mBuf.formatStatistics(&buf, uid, logMask);
    236     if (!buf) {
    237         cli->sendMsg("Failed");
    238     } else {
    239         package_string(&buf);
    240         cli->sendMsg(buf);
    241         free(buf);
    242     }
    243     return 0;
    244 }
    245 
    246 CommandListener::GetPruneListCmd::GetPruneListCmd(LogBuffer *buf) :
    247         LogCommand("getPruneList"),
    248         mBuf(*buf) {
    249 }
    250 
    251 int CommandListener::GetPruneListCmd::runCommand(SocketClient *cli,
    252                                          int /*argc*/, char ** /*argv*/) {
    253     setname();
    254     char *buf = NULL;
    255     mBuf.formatPrune(&buf);
    256     if (!buf) {
    257         cli->sendMsg("Failed");
    258     } else {
    259         package_string(&buf);
    260         cli->sendMsg(buf);
    261         free(buf);
    262     }
    263     return 0;
    264 }
    265 
    266 CommandListener::SetPruneListCmd::SetPruneListCmd(LogBuffer *buf) :
    267         LogCommand("setPruneList"),
    268         mBuf(*buf) {
    269 }
    270 
    271 int CommandListener::SetPruneListCmd::runCommand(SocketClient *cli,
    272                                          int argc, char **argv) {
    273     setname();
    274     if (!clientHasLogCredentials(cli)) {
    275         cli->sendMsg("Permission Denied");
    276         return 0;
    277     }
    278 
    279     char *cp = NULL;
    280     for (int i = 1; i < argc; ++i) {
    281         char *p = cp;
    282         if (p) {
    283             cp = NULL;
    284             asprintf(&cp, "%s %s", p, argv[i]);
    285             free(p);
    286         } else {
    287             asprintf(&cp, "%s", argv[i]);
    288         }
    289     }
    290 
    291     int ret = mBuf.initPrune(cp);
    292     free(cp);
    293 
    294     if (ret) {
    295         cli->sendMsg("Invalid");
    296         return 0;
    297     }
    298 
    299     cli->sendMsg("success");
    300 
    301     return 0;
    302 }
    303 
    304 CommandListener::ReinitCmd::ReinitCmd() : LogCommand("reinit") {
    305 }
    306 
    307 int CommandListener::ReinitCmd::runCommand(SocketClient *cli,
    308                                          int /*argc*/, char ** /*argv*/) {
    309     setname();
    310 
    311     reinit_signal_handler(SIGHUP);
    312 
    313     cli->sendMsg("success");
    314 
    315     return 0;
    316 }
    317 
    318 int CommandListener::getLogSocket() {
    319     static const char socketName[] = "logd";
    320     int sock = android_get_control_socket(socketName);
    321 
    322     if (sock < 0) {
    323         sock = socket_local_server(socketName,
    324                                    ANDROID_SOCKET_NAMESPACE_RESERVED,
    325                                    SOCK_STREAM);
    326     }
    327 
    328     return sock;
    329 }
    330