1/* 2 * Copyright (C) 2008 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#include <errno.h> 17#include <string.h> 18#include <stdlib.h> 19 20#define LOG_TAG "FrameworkListener" 21 22#include <cutils/log.h> 23 24#include <sysutils/FrameworkListener.h> 25#include <sysutils/FrameworkCommand.h> 26#include <sysutils/SocketClient.h> 27 28FrameworkListener::FrameworkListener(const char *socketName, bool withSeq) : 29 SocketListener(socketName, true, withSeq) { 30 init(socketName, withSeq); 31} 32 33FrameworkListener::FrameworkListener(const char *socketName) : 34 SocketListener(socketName, true, false) { 35 init(socketName, false); 36} 37 38void FrameworkListener::init(const char *socketName, bool withSeq) { 39 mCommands = new FrameworkCommandCollection(); 40 errorRate = 0; 41 mCommandCount = 0; 42 mWithSeq = withSeq; 43} 44 45bool FrameworkListener::onDataAvailable(SocketClient *c) { 46 char buffer[255]; 47 int len; 48 49 len = TEMP_FAILURE_RETRY(read(c->getSocket(), buffer, sizeof(buffer))); 50 if (len < 0) { 51 SLOGE("read() failed (%s)", strerror(errno)); 52 return false; 53 } else if (!len) 54 return false; 55 56 int offset = 0; 57 int i; 58 59 for (i = 0; i < len; i++) { 60 if (buffer[i] == '\0') { 61 /* IMPORTANT: dispatchCommand() expects a zero-terminated string */ 62 dispatchCommand(c, buffer + offset); 63 offset = i + 1; 64 } 65 } 66 return true; 67} 68 69void FrameworkListener::registerCmd(FrameworkCommand *cmd) { 70 mCommands->push_back(cmd); 71} 72 73void FrameworkListener::dispatchCommand(SocketClient *cli, char *data) { 74 FrameworkCommandCollection::iterator i; 75 int argc = 0; 76 char *argv[FrameworkListener::CMD_ARGS_MAX]; 77 char tmp[255]; 78 char *p = data; 79 char *q = tmp; 80 char *qlimit = tmp + sizeof(tmp) - 1; 81 bool esc = false; 82 bool quote = false; 83 int k; 84 bool haveCmdNum = !mWithSeq; 85 86 memset(argv, 0, sizeof(argv)); 87 memset(tmp, 0, sizeof(tmp)); 88 while(*p) { 89 if (*p == '\\') { 90 if (esc) { 91 if (q >= qlimit) 92 goto overflow; 93 *q++ = '\\'; 94 esc = false; 95 } else 96 esc = true; 97 p++; 98 continue; 99 } else if (esc) { 100 if (*p == '"') { 101 if (q >= qlimit) 102 goto overflow; 103 *q++ = '"'; 104 } else if (*p == '\\') { 105 if (q >= qlimit) 106 goto overflow; 107 *q++ = '\\'; 108 } else { 109 cli->sendMsg(500, "Unsupported escape sequence", false); 110 goto out; 111 } 112 p++; 113 esc = false; 114 continue; 115 } 116 117 if (*p == '"') { 118 if (quote) 119 quote = false; 120 else 121 quote = true; 122 p++; 123 continue; 124 } 125 126 if (q >= qlimit) 127 goto overflow; 128 *q = *p++; 129 if (!quote && *q == ' ') { 130 *q = '\0'; 131 if (!haveCmdNum) { 132 char *endptr; 133 int cmdNum = (int)strtol(tmp, &endptr, 0); 134 if (endptr == NULL || *endptr != '\0') { 135 cli->sendMsg(500, "Invalid sequence number", false); 136 goto out; 137 } 138 cli->setCmdNum(cmdNum); 139 haveCmdNum = true; 140 } else { 141 if (argc >= CMD_ARGS_MAX) 142 goto overflow; 143 argv[argc++] = strdup(tmp); 144 } 145 memset(tmp, 0, sizeof(tmp)); 146 q = tmp; 147 continue; 148 } 149 q++; 150 } 151 152 *q = '\0'; 153 if (argc >= CMD_ARGS_MAX) 154 goto overflow; 155 argv[argc++] = strdup(tmp); 156#if 0 157 for (k = 0; k < argc; k++) { 158 SLOGD("arg[%d] = '%s'", k, argv[k]); 159 } 160#endif 161 162 if (quote) { 163 cli->sendMsg(500, "Unclosed quotes error", false); 164 goto out; 165 } 166 167 if (errorRate && (++mCommandCount % errorRate == 0)) { 168 /* ignore this command - let the timeout handler handle it */ 169 SLOGE("Faking a timeout"); 170 goto out; 171 } 172 173 for (i = mCommands->begin(); i != mCommands->end(); ++i) { 174 FrameworkCommand *c = *i; 175 176 if (!strcmp(argv[0], c->getCommand())) { 177 if (c->runCommand(cli, argc, argv)) { 178 SLOGW("Handler '%s' error (%s)", c->getCommand(), strerror(errno)); 179 } 180 goto out; 181 } 182 } 183 184 cli->sendMsg(500, "Command not recognized", false); 185out: 186 int j; 187 for (j = 0; j < argc; j++) 188 free(argv[j]); 189 return; 190 191overflow: 192 LOG_EVENT_INT(78001, cli->getUid()); 193 cli->sendMsg(500, "Command too long", false); 194 goto out; 195} 196