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