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