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