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