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 <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 
     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 
     56 CommandListener::ShutdownCmd::ShutdownCmd(LogReader* reader, LogListener* swl)
     57     : LogCommand("shutdown"), mReader(*reader), mSwl(*swl) {
     58 }
     59 
     60 int CommandListener::ShutdownCmd::runCommand(SocketClient* /*cli*/,
     61                                              int /*argc*/, char** /*argv*/) {
     62     mSwl.stopListener();
     63     mReader.stopListener();
     64     exit(0);
     65 }
     66 
     67 CommandListener::ClearCmd::ClearCmd(LogBuffer* buf)
     68     : LogCommand("clear"), 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, 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 
    102 CommandListener::GetBufSizeCmd::GetBufSizeCmd(LogBuffer* buf)
    103     : LogCommand("getLogSize"), mBuf(*buf) {
    104 }
    105 
    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 
    127 CommandListener::SetBufSizeCmd::SetBufSizeCmd(LogBuffer* buf)
    128     : LogCommand("setLogSize"), mBuf(*buf) {
    129 }
    130 
    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 
    160 CommandListener::GetBufSizeUsedCmd::GetBufSizeUsedCmd(LogBuffer* buf)
    161     : LogCommand("getLogSizeUsed"), mBuf(*buf) {
    162 }
    163 
    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 
    185 CommandListener::GetStatisticsCmd::GetStatisticsCmd(LogBuffer* buf)
    186     : LogCommand("getStatistics"), mBuf(*buf) {
    187 }
    188 
    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 
    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 
    236 CommandListener::GetPruneListCmd::GetPruneListCmd(LogBuffer* buf)
    237     : LogCommand("getPruneList"), mBuf(*buf) {
    238 }
    239 
    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 
    247 CommandListener::SetPruneListCmd::SetPruneListCmd(LogBuffer* buf)
    248     : LogCommand("setPruneList"), mBuf(*buf) {
    249 }
    250 
    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 
    279 CommandListener::GetEventTagCmd::GetEventTagCmd(LogBuffer* buf)
    280     : LogCommand("getEventTag"), mBuf(*buf) {
    281 }
    282 
    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 = NULL;
    292     const char* format = NULL;
    293     const char* id = NULL;
    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 
    329 CommandListener::ReinitCmd::ReinitCmd() : LogCommand("reinit") {
    330 }
    331 
    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 
    343 CommandListener::ExitCmd::ExitCmd(CommandListener* parent)
    344     : LogCommand("EXIT"), mParent(*parent) {
    345 }
    346 
    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 
    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