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