Add NLST by Liu Yang.
[xylftp.git] / server / src / parse_cmd.c
blobce4b8e5d5d541b5419c333b5b3f2bb9f10bcd2df
1 /*
2 * Copyright (c) 2007,西安邮电学院Linux兴趣小组
3 * All rights reserved.
5 * 文件名称:parse_cmd.c
6 * 摘 要:从一行数据中解析出命令和参数 并调用相应的命令处理模块
7 * 对读取的字符串做了初步分析 提高了容错能力 对参数的接收做了限制,一次只接收一个参数。
8 * 重写了接收参数模块,去掉了无用参数buf_size,_line_cmd()的返回值改成了结构体指针。
9 * 当前版本:4.0
10 * 作 者:贾孟树
11 * 完成日期:2007年6月13日
12 * 取代版本:3.0
13 * 完成日期:2007年6月8日
14 * 修改者:王聪
15 * 修改日期:2007年6月15日
19 #include "xylftp.h"
20 #include "do_cmd.h"
21 #include "debug.h"
23 #define MAX_CMD 5
24 #define MAX_ARG 4096
26 extern struct user_env user_env;
27 extern struct run_env run_env;
28 struct parse_cmd{
29 char cmd[MAX_CMD];
30 char arg[MAX_ARG];
34 const char *commands[] = {"USER","PASS","SYST","QUIT","RETR","STOR","RNFR","RNTO","ABOR","DELE",
35 "RMD","MKD","PWD","CWD","CDUP","PORT","NOOP","PASV","TYPE","MODE",
36 "STAT","STRU","LIST", "REST", "SIZE", "SITE", "HELP", "NLST"}; /*服务器支持的所有命令*/
38 static int _line_cmd(char *line_buf, struct parse_cmd *user_cmd)
40 int i = 0;
41 int j = 0;
42 int k = 0;
44 while (!isalpha(line_buf[i])) {
45 i++;
46 } /*<--略过不是字母的字符*/
47 while (line_buf[i] != ' '
48 && line_buf[i] != '\r'
49 && line_buf[i] != '\n') {
50 if (k < MAX_CMD-1) {
51 user_cmd->cmd[k++] = line_buf[i];
52 i++;
54 else {
55 return -1;
57 } /*<--接收以字母开头的字符串(命令)*/
58 while (line_buf[i] == ' ') {
59 i++;
60 } /*<--清除命令与参数之间的空格*/
61 while (line_buf[i] != '\0'
62 && line_buf[i] != '\r'
63 && line_buf[i] != '\n') {
64 user_cmd->arg[j++] = line_buf[i];
65 i++;
66 } /*<--只提取第一个参数*/
68 for (;k >= 0;k--) { /*检查命令中字母的大小写,若是小写字母,则转化为大写字母*/
69 user_cmd->cmd[k] = toupper(user_cmd->cmd[k]);
71 #ifdef DEBUG
72 printf("\n");
73 printf("CMD:");
74 printf("%s",user_cmd->cmd);
75 printf("\n");
76 printf("ARG:");
77 printf("%s",user_cmd->arg);
78 printf("\n");
79 #endif
80 return 0;
83 static int _cmd_num(struct parse_cmd cmd)
85 int i;
86 for (i = 0; i < (int)(sizeof(commands)/sizeof(commands[0])); i++) {
87 if (strcmp(cmd.cmd, commands[i]) == 0) {
88 return i+1;
91 return 0;
95 int parse_cmd(char *p_buf)
97 char rnfr_arg[MAX_ARG];
98 struct parse_cmd user_cmd;
99 const char login_error[] = "530 Please login with USER and PASS.\r\n";
100 int i = 0;
102 memset(&user_cmd, 0, sizeof(struct parse_cmd));
103 if (_line_cmd(p_buf, &user_cmd) == -1) {
104 failed(user_cmd.cmd);
105 return 2;
107 if (( i = _cmd_num(user_cmd)) <= 4 || user_env.login_in == TRUE) {
108 switch (i) {
109 case 1:
110 debug_printf("****call do_user()\n");
111 do_user(user_cmd.arg);
112 break;
113 case 2:
114 debug_printf("call do_pass()\n");
115 debug_printf("username=%s\n", user_env.user_name);
117 if (strlen(user_env.user_name) != 0) {
118 if (do_pass(user_cmd.arg) == 0) {
119 if (chroot(run_env.ftp_dir) < 0) {
120 write_log("chroot error", 0);
121 do_quit();
122 break;
124 if (chdir("/") < 0) {
125 write_log("chdir error", 0);
126 do_quit();
127 break;
129 } else {
130 break;
132 } else {
133 const char mess[] = "220 No username input.\r\n";
134 write(user_env.connect_fd, mess, strlen(mess));
137 break;
138 case 3:
139 debug_printf("call do_syst()\n");
140 do_syst();
141 break;
142 case 4:
143 debug_printf("call do_quit()\n");
144 do_quit();
145 break;
146 case 5:
147 debug_printf("call do_retr()\n");
148 do_retr(user_cmd.arg);
149 break;
150 case 6:
151 debug_printf("call do_stor()\n");
152 do_stor(user_cmd.arg);
153 break;
154 case 7:
155 debug_printf("call do_rnfr()\n");
156 do_rnfr();
157 strcpy(rnfr_arg, user_cmd.arg);
158 break;
159 case 8:
160 debug_printf("call do_rnto()\n");
161 do_rnto(rnfr_arg, user_cmd.arg);
162 memset(rnfr_arg, 0, MAX_ARG);
163 break;
164 case 9:
165 debug_printf("call do_abor()\n");
166 fflush(stdout);
167 do_abor(user_cmd.arg);
168 break;
169 case 10:
170 debug_printf("call do_dele()\n");
171 do_dele(user_cmd.arg);
172 break;
173 case 11:
174 debug_printf("call do_rmd()\n");
175 do_rmd(user_cmd.arg);
176 break;
177 case 12:
178 debug_printf("call mkd()\n");
179 do_mkd(user_cmd.arg);
180 break;
181 case 13:
182 debug_printf("call do_pwd()\n");
183 do_pwd();
184 break;
185 case 14:
186 debug_printf("call do_cwd()\n");
187 do_cwd(user_cmd.arg);
188 break;
189 case 15:
190 debug_printf("call do_cdup()\n");
191 do_cdup();
192 break;
193 case 16:
194 debug_printf("call do_port()\n");
195 do_port(user_cmd.arg);
196 break;
197 case 17:
198 debug_printf("call do_noop()\n");
199 do_noop();
200 break;
201 case 18:
202 debug_printf("call do_pasv()\n\n");
203 do_pasv();
204 break;
205 case 19:
206 debug_printf("call do_type()\n");
207 do_type(user_cmd.arg);
208 break;
209 case 20:
210 debug_printf("call do_mode()\n");
211 do_mode(user_cmd.arg);
212 break;
213 case 21:
214 debug_printf("call do_stat()\n");
215 do_stat(user_cmd.arg);
216 break;
217 case 22:
218 debug_printf("call do_stru()\n");
219 do_stru(user_cmd.arg);
220 break;
221 case 23:
222 debug_printf("call do_list()\n");
223 do_list(user_cmd.arg);
224 break;
225 case 24:
226 debug_printf("call do_rest()\n");
227 do_rest(user_cmd.arg);
228 break;
229 case 25:
230 debug_printf("call do_size()\n");
231 do_size(user_cmd.arg);
232 break;
233 case 26:
234 debug_printf("call do_site()\n");
235 do_site(user_cmd.arg);
236 break;
237 case 27:
238 debug_printf("call do_help()\n");
239 do_help(user_cmd.arg);
240 break;
241 case 28:
242 debug_printf("call do_nlst()\n");
243 do_nlst(user_cmd.arg);
244 break;
245 default:
246 debug_printf("call failed()\n");
247 failed(user_cmd.cmd);
248 break;
250 } else if (i <= 23 && i >= 1) {
251 write(user_env.connect_fd, login_error, strlen(login_error));
252 } else {
253 failed(user_cmd.cmd);
255 return 1;