1 /*
2 * Copyright (C) 2015-2017 Alibaba Group Holding Limited
3 */
4
5 #include <stdlib.h>
6 #include <stdio.h>
7 #include <stdarg.h>
8 #include <string.h>
9 #include <errno.h>
10 #include "aos/kernel.h"
11
12 #include <lwip/def.h>
13 #include <lwip/netdb.h>
14 #include <lwip/sockets.h>
15 #include "lwip/apps/telnetserver.h"
16
17 #define MAX_COMMANDLINE_LENGTH 512U
18 #define AOS_TELNETD_PRI (AOS_DEFAULT_APP_PRI+1)
19
20 typedef struct
21 {
22 char command_buffer[MAX_COMMANDLINE_LENGTH]; /* A buffer which stores the currently being built command. */
23 int buffer_position; /* The current write position in the command buffer. */
24 } CommandInterpreter_t;
25
26 static CommandInterpreter_t interpreter;
27
28 static bool telnetserver_is_running = false;
29
30 static aos_task_t aos_telnetd_task;
31
32 extern int proc_onecmd(int argc, char *argv[]);
33
34 /**
35 * Clear all characters from the command buffer.
36 *
37 * @param none
38 * @retval none
39 */
ClearCommandBuffer(void)40 void ClearCommandBuffer(void) {
41 for (int i = 0; i < MAX_COMMANDLINE_LENGTH; ++i) {
42 interpreter.command_buffer[i] = '\0';
43 }
44 interpreter.buffer_position = 0U;
45 }
46
47 /* Parse input line and locate arguments (if any), keeping count of the number
48 * of arguments and their locations. Look up and call the corresponding cli
49 * function if one is found and pass it the argv array.
50 *
51 * Returns: 0 on success: the input line contained at least a function name and
52 * that function exists and was called.
53 * 1 on lookup failure: there is no corresponding function for the
54 * input line.
55 * 2 on invalid syntax: the arguments list couldn't be parsed
56 */
CommandParseLine(char * inbuf)57 static int CommandParseLine(char *inbuf)
58 {
59 struct {
60 unsigned inArg: 1;
61 unsigned inQuote: 1;
62 unsigned done: 1;
63 } stat;
64 static char *argvall[CLI_MAX_ONCECMD_NUM][CLI_MAX_ARG_NUM];
65 int argcall[CLI_MAX_ONCECMD_NUM] = {0};
66 /*
67 static char *argv[CLI_MAX_ONCECMD_NUM][CLI_MAX_ARG_NUM];
68 int argc = 0;*/
69 int cmdnum = 0;
70 int *pargc = &argcall[0];
71 int i = 0;
72 int ret = 0;
73
74 memset((void *)&argvall, 0, sizeof(argvall));
75 memset((void *)&argcall, 0, sizeof(argcall));
76 memset(&stat, 0, sizeof(stat));
77
78 do {
79 switch (inbuf[i]) {
80 case '\0':
81 if (stat.inQuote) {
82 return 2;
83 }
84 stat.done = 1;
85 break;
86
87 case '"':
88 if (i > 0 && inbuf[i - 1] == '\\' && stat.inArg) {
89 memcpy(&inbuf[i - 1], &inbuf[i], strlen(&inbuf[i]) + 1);
90 --i;
91 break;
92 }
93 if (!stat.inQuote && stat.inArg) {
94 break;
95 }
96 if (stat.inQuote && !stat.inArg) {
97 return 2;
98 }
99
100 if (!stat.inQuote && !stat.inArg) {
101 stat.inArg = 1;
102 stat.inQuote = 1;
103 (*pargc)++;
104 argvall[cmdnum][(*pargc) - 1] = &inbuf[i + 1];
105 } else if (stat.inQuote && stat.inArg) {
106 stat.inArg = 0;
107 stat.inQuote = 0;
108 inbuf[i] = '\0';
109 }
110 break;
111
112 case ' ':
113 if (i > 0 && inbuf[i - 1] == '\\' && stat.inArg) {
114 memcpy(&inbuf[i - 1], &inbuf[i],
115 strlen(&inbuf[i]) + 1);
116 --i;
117 break;
118 }
119 if (!stat.inQuote && stat.inArg) {
120 stat.inArg = 0;
121 inbuf[i] = '\0';
122 }
123 break;
124
125 case ';':
126 if (i > 0 && inbuf[i - 1] == '\\' && stat.inArg) {
127 memcpy(&inbuf[i - 1], &inbuf[i],
128 strlen(&inbuf[i]) + 1);
129 --i;
130 break;
131 }
132 if (stat.inQuote) {
133 return 2;
134 }
135 if (!stat.inQuote && stat.inArg) {
136 stat.inArg = 0;
137 inbuf[i] = '\0';
138
139 if (*pargc) {
140 if (++cmdnum < CLI_MAX_ONCECMD_NUM) {
141 pargc = &argcall[cmdnum];
142 }
143 }
144 }
145
146 break;
147
148 default:
149 if (!stat.inArg) {
150 stat.inArg = 1;
151 (*pargc)++;
152 argvall[cmdnum][(*pargc) - 1] = &inbuf[i];
153 }
154 break;
155 }
156 } while (!stat.done && ++i < BUFSIZ && cmdnum < CLI_MAX_ONCECMD_NUM && (*pargc) < CLI_MAX_ARG_NUM);
157
158 if (stat.inQuote) {
159 return 2;
160 }
161
162 for ( i = 0; i <= cmdnum && i < CLI_MAX_ONCECMD_NUM ; i++ ) {
163 TelnetWriteString("\n");
164 ret |= proc_onecmd(argcall[i], argvall[i]);
165 }
166
167 return ret;
168 }
169
CommandAddChar(const char character)170 void CommandAddChar(const char character)
171 {
172 if (character != 0x00 && interpreter.buffer_position < MAX_COMMANDLINE_LENGTH)
173 {
174 if (character == 0x0A || character == 0x0D)
175 {
176 /* We have reached the end of a command, parse it */
177 CommandParseLine(interpreter.command_buffer);
178 /* Clear the command buffer */
179 ClearCommandBuffer();
180 }
181 else if (character == 0x08 || character == 0x7F)
182 {
183 /* Remove the last character from the buffer */
184 if (interpreter.buffer_position > 0)
185 {
186 --interpreter.buffer_position; /* Move the list back one */
187 interpreter.command_buffer[interpreter.buffer_position] = '\0'; /* Set the current position to a null character */
188 }
189 }
190 else if (character == 0x20)
191 {
192 if (interpreter.buffer_position > 0
193 && interpreter.command_buffer[interpreter.buffer_position - 1] != 0x20)
194 {
195 /* Add another character to the buffer */
196 interpreter.command_buffer[interpreter.buffer_position] = character; /* Add the character at the current position */
197 ++interpreter.buffer_position; /* Move the buffer pointer to the next position */
198 }
199 /* If the previous character is a space, ignore further spaces */
200 }
201 else
202 {
203 /* Add another character to the buffer */
204 interpreter.command_buffer[interpreter.buffer_position] = character; /* Add the character at the current position */
205 ++interpreter.buffer_position; /* Move the buffer pointer to the next position */
206 }
207 }
208 return ;
209 }
210
TelnetServerProcess(void * arg)211 static void TelnetServerProcess(void* arg)
212 {
213 char character;
214 char telcmd[10] = "echo tel";
215
216 if (InitializeTelnetServer() != TELNET_OK)
217 {
218 return ;
219 }
220
221 telnetserver_is_running = true;
222
223 /* set cli aos telnet server mode */
224 CommandParseLine(telcmd);
225
226 while(1)
227 {
228 if(telnetserver_is_running != true)
229 {
230 aos_task_exit(0);
231 }
232
233 if (TelnetIsConnected() == true)
234 { /* We have an active Telnet connection to service */
235 /* Do server stuff */
236 character = TelnetRead();
237 if(character != '\0')
238 {
239 CommandAddChar(character);
240 }
241 else
242 {
243 aos_msleep(500);
244 }
245 }
246 else
247 {
248 //printf("Telnet is not connected, try again later.\n");
249 aos_msleep(1000);
250 }
251 aos_msleep(50);
252 }
253 return ;
254 }
255
telnetserver_start()256 void telnetserver_start()
257 {
258 aos_task_new_ext(&aos_telnetd_task, "telnetserver", TelnetServerProcess, NULL, 81920, AOS_TELNETD_PRI);
259 }
260
telnetserver_stop()261 void telnetserver_stop()
262 {
263 telnetserver_is_running = false;
264 if(TelnetIsConnected() == true)
265 {
266 TelnetClose();
267 }
268 }
269
270