1168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat/* 2168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat * Copyright (C) 2008 The Android Open Source Project 3168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat * 4168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat * Licensed under the Apache License, Version 2.0 (the "License"); 5168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat * you may not use this file except in compliance with the License. 6168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat * You may obtain a copy of the License at 7168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat * 8168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat * http://www.apache.org/licenses/LICENSE-2.0 9168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat * 10168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat * Unless required by applicable law or agreed to in writing, software 11168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat * distributed under the License is distributed on an "AS IS" BASIS, 12168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat * See the License for the specific language governing permissions and 14168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat * limitations under the License. 15168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat */ 16168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat#include <errno.h> 173d40729054803fae1c4d4bb5ac7554665a132b26San Mehat#include <string.h> 18b93e5812faffd3b6c5fb349072413aace31918d8Olivier Bailly#include <stdlib.h> 19168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat 20168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat#define LOG_TAG "FrameworkListener" 21168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat 22168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat#include <cutils/log.h> 23168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat 24168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat#include <sysutils/FrameworkListener.h> 25168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat#include <sysutils/FrameworkCommand.h> 26fa644ffe944c01a9b00f8d7676d58394fabee285San Mehat#include <sysutils/SocketClient.h> 27168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat 28168415b822cae1f8b54ef09c41c11a9b97b87f40San MehatFrameworkListener::FrameworkListener(const char *socketName) : 29168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat SocketListener(socketName, true) { 30168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat mCommands = new FrameworkCommandCollection(); 31168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat} 32168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat 33fa644ffe944c01a9b00f8d7676d58394fabee285San Mehatbool FrameworkListener::onDataAvailable(SocketClient *c) { 34d768066ef54270a0d3ccfccd50ae8238db5a2cddSan Mehat char buffer[255]; 35168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat int len; 36168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat 37c6b0def5f039dc3bbe1d4b7dc1666c24316eb020David 'Digit' Turner len = TEMP_FAILURE_RETRY(read(c->getSocket(), buffer, sizeof(buffer))); 38c6b0def5f039dc3bbe1d4b7dc1666c24316eb020David 'Digit' Turner if (len < 0) { 397e8529a8b528fd30586aa037f15a31b29582c537San Mehat SLOGE("read() failed (%s)", strerror(errno)); 40f31d2ed1fd3a39a92bccc12eb66728594290ef3bKenny Root return false; 41c73a3a5771a2d29d1bae666bfde12f751d66fc96San Mehat } else if (!len) 42168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat return false; 43168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat 44d768066ef54270a0d3ccfccd50ae8238db5a2cddSan Mehat int offset = 0; 45168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat int i; 46168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat 47168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat for (i = 0; i < len; i++) { 48c73a3a5771a2d29d1bae666bfde12f751d66fc96San Mehat if (buffer[i] == '\0') { 49c6b0def5f039dc3bbe1d4b7dc1666c24316eb020David 'Digit' Turner /* IMPORTANT: dispatchCommand() expects a zero-terminated string */ 50d768066ef54270a0d3ccfccd50ae8238db5a2cddSan Mehat dispatchCommand(c, buffer + offset); 51d768066ef54270a0d3ccfccd50ae8238db5a2cddSan Mehat offset = i + 1; 52168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat } 53168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat } 54168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat return true; 55168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat} 56168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat 57168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehatvoid FrameworkListener::registerCmd(FrameworkCommand *cmd) { 58168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat mCommands->push_back(cmd); 59168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat} 60168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat 61c73a3a5771a2d29d1bae666bfde12f751d66fc96San Mehatvoid FrameworkListener::dispatchCommand(SocketClient *cli, char *data) { 62c4a895b7094461c98101924cf096680bfb7856f1San Mehat FrameworkCommandCollection::iterator i; 63c4a895b7094461c98101924cf096680bfb7856f1San Mehat int argc = 0; 64c73a3a5771a2d29d1bae666bfde12f751d66fc96San Mehat char *argv[FrameworkListener::CMD_ARGS_MAX]; 65c4a895b7094461c98101924cf096680bfb7856f1San Mehat char tmp[255]; 66c4a895b7094461c98101924cf096680bfb7856f1San Mehat char *p = data; 67c4a895b7094461c98101924cf096680bfb7856f1San Mehat char *q = tmp; 68c6b0def5f039dc3bbe1d4b7dc1666c24316eb020David 'Digit' Turner char *qlimit = tmp + sizeof(tmp) - 1; 69c4a895b7094461c98101924cf096680bfb7856f1San Mehat bool esc = false; 70c4a895b7094461c98101924cf096680bfb7856f1San Mehat bool quote = false; 71c4a895b7094461c98101924cf096680bfb7856f1San Mehat int k; 72c4a895b7094461c98101924cf096680bfb7856f1San Mehat 73c4a895b7094461c98101924cf096680bfb7856f1San Mehat memset(argv, 0, sizeof(argv)); 74c4a895b7094461c98101924cf096680bfb7856f1San Mehat memset(tmp, 0, sizeof(tmp)); 75c4a895b7094461c98101924cf096680bfb7856f1San Mehat while(*p) { 76c4a895b7094461c98101924cf096680bfb7856f1San Mehat if (*p == '\\') { 77c4a895b7094461c98101924cf096680bfb7856f1San Mehat if (esc) { 78c6b0def5f039dc3bbe1d4b7dc1666c24316eb020David 'Digit' Turner if (q >= qlimit) 79c6b0def5f039dc3bbe1d4b7dc1666c24316eb020David 'Digit' Turner goto overflow; 80c4a895b7094461c98101924cf096680bfb7856f1San Mehat *q++ = '\\'; 81c4a895b7094461c98101924cf096680bfb7856f1San Mehat esc = false; 82c4a895b7094461c98101924cf096680bfb7856f1San Mehat } else 83c4a895b7094461c98101924cf096680bfb7856f1San Mehat esc = true; 84c4a895b7094461c98101924cf096680bfb7856f1San Mehat p++; 85c4a895b7094461c98101924cf096680bfb7856f1San Mehat continue; 86c4a895b7094461c98101924cf096680bfb7856f1San Mehat } else if (esc) { 87c6b0def5f039dc3bbe1d4b7dc1666c24316eb020David 'Digit' Turner if (*p == '"') { 88c6b0def5f039dc3bbe1d4b7dc1666c24316eb020David 'Digit' Turner if (q >= qlimit) 89c6b0def5f039dc3bbe1d4b7dc1666c24316eb020David 'Digit' Turner goto overflow; 90c4a895b7094461c98101924cf096680bfb7856f1San Mehat *q++ = '"'; 91c6b0def5f039dc3bbe1d4b7dc1666c24316eb020David 'Digit' Turner } else if (*p == '\\') { 92c6b0def5f039dc3bbe1d4b7dc1666c24316eb020David 'Digit' Turner if (q >= qlimit) 93c6b0def5f039dc3bbe1d4b7dc1666c24316eb020David 'Digit' Turner goto overflow; 94c4a895b7094461c98101924cf096680bfb7856f1San Mehat *q++ = '\\'; 95c6b0def5f039dc3bbe1d4b7dc1666c24316eb020David 'Digit' Turner } else { 96c4a895b7094461c98101924cf096680bfb7856f1San Mehat cli->sendMsg(500, "Unsupported escape sequence", false); 97c4a895b7094461c98101924cf096680bfb7856f1San Mehat goto out; 98c4a895b7094461c98101924cf096680bfb7856f1San Mehat } 99c4a895b7094461c98101924cf096680bfb7856f1San Mehat p++; 100c4a895b7094461c98101924cf096680bfb7856f1San Mehat esc = false; 101c4a895b7094461c98101924cf096680bfb7856f1San Mehat continue; 102c4a895b7094461c98101924cf096680bfb7856f1San Mehat } 103c4a895b7094461c98101924cf096680bfb7856f1San Mehat 104c4a895b7094461c98101924cf096680bfb7856f1San Mehat if (*p == '"') { 105c4a895b7094461c98101924cf096680bfb7856f1San Mehat if (quote) 106c4a895b7094461c98101924cf096680bfb7856f1San Mehat quote = false; 107c4a895b7094461c98101924cf096680bfb7856f1San Mehat else 108c4a895b7094461c98101924cf096680bfb7856f1San Mehat quote = true; 109c4a895b7094461c98101924cf096680bfb7856f1San Mehat p++; 110c4a895b7094461c98101924cf096680bfb7856f1San Mehat continue; 111c4a895b7094461c98101924cf096680bfb7856f1San Mehat } 112c73a3a5771a2d29d1bae666bfde12f751d66fc96San Mehat 113c6b0def5f039dc3bbe1d4b7dc1666c24316eb020David 'Digit' Turner if (q >= qlimit) 114c6b0def5f039dc3bbe1d4b7dc1666c24316eb020David 'Digit' Turner goto overflow; 115c4a895b7094461c98101924cf096680bfb7856f1San Mehat *q = *p++; 116c4a895b7094461c98101924cf096680bfb7856f1San Mehat if (!quote && *q == ' ') { 117c4a895b7094461c98101924cf096680bfb7856f1San Mehat *q = '\0'; 118c6b0def5f039dc3bbe1d4b7dc1666c24316eb020David 'Digit' Turner if (argc >= CMD_ARGS_MAX) 119c6b0def5f039dc3bbe1d4b7dc1666c24316eb020David 'Digit' Turner goto overflow; 120c4a895b7094461c98101924cf096680bfb7856f1San Mehat argv[argc++] = strdup(tmp); 121c4a895b7094461c98101924cf096680bfb7856f1San Mehat memset(tmp, 0, sizeof(tmp)); 122c4a895b7094461c98101924cf096680bfb7856f1San Mehat q = tmp; 123c4a895b7094461c98101924cf096680bfb7856f1San Mehat continue; 124c4a895b7094461c98101924cf096680bfb7856f1San Mehat } 125c4a895b7094461c98101924cf096680bfb7856f1San Mehat q++; 126fa644ffe944c01a9b00f8d7676d58394fabee285San Mehat } 127fa644ffe944c01a9b00f8d7676d58394fabee285San Mehat 128c6b0def5f039dc3bbe1d4b7dc1666c24316eb020David 'Digit' Turner *q = '\0'; 129c6b0def5f039dc3bbe1d4b7dc1666c24316eb020David 'Digit' Turner if (argc >= CMD_ARGS_MAX) 130c6b0def5f039dc3bbe1d4b7dc1666c24316eb020David 'Digit' Turner goto overflow; 131c4a895b7094461c98101924cf096680bfb7856f1San Mehat argv[argc++] = strdup(tmp); 132c4a895b7094461c98101924cf096680bfb7856f1San Mehat#if 0 133c4a895b7094461c98101924cf096680bfb7856f1San Mehat for (k = 0; k < argc; k++) { 1347e8529a8b528fd30586aa037f15a31b29582c537San Mehat SLOGD("arg[%d] = '%s'", k, argv[k]); 135c4a895b7094461c98101924cf096680bfb7856f1San Mehat } 136c4a895b7094461c98101924cf096680bfb7856f1San Mehat#endif 137168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat 138c4a895b7094461c98101924cf096680bfb7856f1San Mehat if (quote) { 139c4a895b7094461c98101924cf096680bfb7856f1San Mehat cli->sendMsg(500, "Unclosed quotes error", false); 140c4a895b7094461c98101924cf096680bfb7856f1San Mehat goto out; 141c4a895b7094461c98101924cf096680bfb7856f1San Mehat } 142c6b0def5f039dc3bbe1d4b7dc1666c24316eb020David 'Digit' Turner 143168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat for (i = mCommands->begin(); i != mCommands->end(); ++i) { 144168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat FrameworkCommand *c = *i; 145168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat 146c73a3a5771a2d29d1bae666bfde12f751d66fc96San Mehat if (!strcmp(argv[0], c->getCommand())) { 147c73a3a5771a2d29d1bae666bfde12f751d66fc96San Mehat if (c->runCommand(cli, argc, argv)) { 1487e8529a8b528fd30586aa037f15a31b29582c537San Mehat SLOGW("Handler '%s' error (%s)", c->getCommand(), strerror(errno)); 149168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat } 150c4a895b7094461c98101924cf096680bfb7856f1San Mehat goto out; 151168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat } 152168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat } 153168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat 154d768066ef54270a0d3ccfccd50ae8238db5a2cddSan Mehat cli->sendMsg(500, "Command not recognized", false); 155c4a895b7094461c98101924cf096680bfb7856f1San Mehatout: 156c4a895b7094461c98101924cf096680bfb7856f1San Mehat int j; 157c4a895b7094461c98101924cf096680bfb7856f1San Mehat for (j = 0; j < argc; j++) 158c4a895b7094461c98101924cf096680bfb7856f1San Mehat free(argv[j]); 159fa644ffe944c01a9b00f8d7676d58394fabee285San Mehat return; 160c6b0def5f039dc3bbe1d4b7dc1666c24316eb020David 'Digit' Turner 161c6b0def5f039dc3bbe1d4b7dc1666c24316eb020David 'Digit' Turneroverflow: 162c6b0def5f039dc3bbe1d4b7dc1666c24316eb020David 'Digit' Turner cli->sendMsg(500, "Command too long", false); 163c6b0def5f039dc3bbe1d4b7dc1666c24316eb020David 'Digit' Turner goto out; 164168415b822cae1f8b54ef09c41c11a9b97b87f40San Mehat} 165