FrameworkListener.cpp revision 6bbaaa630195a1bcfa90c168a354f76b90125ed6
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) : 29 SocketListener(socketName, true) { 30 mCommands = new FrameworkCommandCollection(); 31} 32 33bool FrameworkListener::onDataAvailable(SocketClient *c) { 34 char buffer[255]; 35 int len; 36 37 len = TEMP_FAILURE_RETRY(read(c->getSocket(), buffer, sizeof(buffer))); 38 if (len < 0) { 39 SLOGE("read() failed (%s)", strerror(errno)); 40 return false; 41 } else if (!len) 42 return false; 43 44 int offset = 0; 45 int i; 46 47 for (i = 0; i < len; i++) { 48 if (buffer[i] == '\0') { 49 /* IMPORTANT: dispatchCommand() expects a zero-terminated string */ 50 dispatchCommand(c, buffer + offset); 51 offset = i + 1; 52 } 53 } 54 return true; 55} 56 57void FrameworkListener::registerCmd(FrameworkCommand *cmd) { 58 mCommands->push_back(cmd); 59} 60 61void FrameworkListener::dispatchCommand(SocketClient *cli, char *data) { 62 FrameworkCommandCollection::iterator i; 63 int argc = 0; 64 char *argv[FrameworkListener::CMD_ARGS_MAX]; 65 char tmp[255]; 66 char *p = data; 67 char *q = tmp; 68 char *qlimit = tmp + sizeof(tmp) - 1; 69 bool esc = false; 70 bool quote = false; 71 int k; 72 73 memset(argv, 0, sizeof(argv)); 74 memset(tmp, 0, sizeof(tmp)); 75 while(*p) { 76 if (*p == '\\') { 77 if (esc) { 78 if (q >= qlimit) 79 goto overflow; 80 *q++ = '\\'; 81 esc = false; 82 } else 83 esc = true; 84 p++; 85 continue; 86 } else if (esc) { 87 if (*p == '"') { 88 if (q >= qlimit) 89 goto overflow; 90 *q++ = '"'; 91 } else if (*p == '\\') { 92 if (q >= qlimit) 93 goto overflow; 94 *q++ = '\\'; 95 } else { 96 cli->sendMsg(500, "Unsupported escape sequence", false); 97 goto out; 98 } 99 p++; 100 esc = false; 101 continue; 102 } 103 104 if (*p == '"') { 105 if (quote) 106 quote = false; 107 else 108 quote = true; 109 p++; 110 continue; 111 } 112 113 if (q >= qlimit) 114 goto overflow; 115 *q = *p++; 116 if (!quote && *q == ' ') { 117 *q = '\0'; 118 if (argc >= CMD_ARGS_MAX) 119 goto overflow; 120 argv[argc++] = strdup(tmp); 121 memset(tmp, 0, sizeof(tmp)); 122 q = tmp; 123 continue; 124 } 125 q++; 126 } 127 128 *q = '\0'; 129 if (argc >= CMD_ARGS_MAX) 130 goto overflow; 131 argv[argc++] = strdup(tmp); 132#if 0 133 for (k = 0; k < argc; k++) { 134 SLOGD("arg[%d] = '%s'", k, argv[k]); 135 } 136#endif 137 138 if (quote) { 139 cli->sendMsg(500, "Unclosed quotes error", false); 140 goto out; 141 } 142 143 for (i = mCommands->begin(); i != mCommands->end(); ++i) { 144 FrameworkCommand *c = *i; 145 146 if (!strcmp(argv[0], c->getCommand())) { 147 if (c->runCommand(cli, argc, argv)) { 148 SLOGW("Handler '%s' error (%s)", c->getCommand(), strerror(errno)); 149 } 150 goto out; 151 } 152 } 153 154 cli->sendMsg(500, "Command not recognized", false); 155out: 156 int j; 157 for (j = 0; j < argc; j++) 158 free(argv[j]); 159 return; 160 161overflow: 162 LOG_EVENT_INT(78001, cli->getUid()); 163 cli->sendMsg(500, "Command too long", false); 164 goto out; 165} 166