• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
FrameworkListener(const char * socketName)28 FrameworkListener::FrameworkListener(const char *socketName) :
29                             SocketListener(socketName, true) {
30     mCommands = new FrameworkCommandCollection();
31 }
32 
onDataAvailable(SocketClient * c)33 bool 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 
registerCmd(FrameworkCommand * cmd)57 void FrameworkListener::registerCmd(FrameworkCommand *cmd) {
58     mCommands->push_back(cmd);
59 }
60 
dispatchCommand(SocketClient * cli,char * data)61 void 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);
155 out:
156     int j;
157     for (j = 0; j < argc; j++)
158         free(argv[j]);
159     return;
160 
161 overflow:
162     cli->sendMsg(500, "Command too long", false);
163     goto out;
164 }
165