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