Added more logging messages.
[uftps.git] / command_loop.c
blob60a3d8bcd99f8c631a4dd710b2d444f83c420317
1 /*
2 * User FTP Server, Share folders over FTP without being root.
3 * Copyright (C) 2008 Isaac Jurado
5 * This program is free software; you can redistribute it and/or modify it under
6 * the terms of the GNU General Public License as published by the Free Software
7 * Foundation; either version 2 of the License, or (at your option) any later
8 * version.
10 * This program is distributed in the hope that it will be useful, but WITHOUT
11 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
12 * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
13 * details.
15 * You should have received a copy of the GNU General Public License along with
16 * this program; if not, write to the Free Software Foundation, Inc.,
17 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
19 #include "uftps.h"
22 * Main FTP server loop which attends one client.
24 * It seems unbelievable but it's possible to implement a FTP server without
25 * the need of select() or poll(). In fact, this kind of complexity is present
26 * in the client.
28 * Commands not implemented are interpreted as unknown. There used to be
29 * dedicated dummy messages for some of them but code simplicity is preferred.
32 #include <ctype.h>
33 #include <unistd.h>
34 #include <stdlib.h>
35 #include <stdio.h>
38 void command_loop (void)
40 while (1) {
41 switch (next_command()) {
44 * Straightforward implementations.
46 case FTP_NOOP:
47 send_reply(S_cmd_sk, "200 I'm alive, don't worry\r\n");
48 break;
50 case FTP_FEAT:
51 send_reply(S_cmd_sk,
52 "211-Feature list:\r\n"
53 "211- MDTM\r\n"
54 "211- REST STREAM\r\n"
55 "211- SIZE\r\n"
56 "211- TVFS\r\n"
57 "211 End.\r\n");
58 break;
60 case FTP_PASS:
61 case FTP_USER:
62 send_reply(S_cmd_sk, "230 I don't care.\r\n");
63 break;
65 case FTP_SYST:
66 send_reply(S_cmd_sk, "215 UNIX Type: L8\r\n");
67 break;
69 case FTP_OPTS:
70 send_reply(S_cmd_sk, "501 Option not understood.\r\n");
71 break;
73 case FTP_ACCT:
74 case FTP_SMNT:
75 send_reply(S_cmd_sk, "202 Unimplemented, ignored.\r\n");
76 break;
78 case FTP_REIN:
79 send_reply(S_cmd_sk, "220 Nothing to REIN.\r\n");
80 break;
83 * A bit more complex commands.
85 case FTP_MODE:
86 if (toupper(S_arg[0]) == 'S')
87 send_reply(S_cmd_sk,
88 "200 MODE set to stream.\r\n");
89 else
90 send_reply(S_cmd_sk,
91 "504 Mode not supported.\r\n");
92 break;
94 case FTP_STRU:
95 if (toupper(S_arg[0]) == 'F')
96 send_reply(S_cmd_sk,
97 "200 STRUcture set to file.\r\n");
98 else
99 send_reply(S_cmd_sk,
100 "504 Structure not supported.\r\n");
101 break;
103 case FTP_TYPE:
104 switch (toupper(S_arg[0])) {
105 case 'I':
106 case 'A':
107 case 'L':
108 send_reply(S_cmd_sk, "200 Whatever.\r\n");
109 break;
110 default:
111 send_reply(S_cmd_sk,
112 "501 Invalid type.\r\n");
114 break;
116 case FTP_QUIT:
117 send_reply(S_cmd_sk, "221 Goodbye.\r\n");
118 close(S_cmd_sk);
119 close(S_passive_bind_sk);
120 exit(EXIT_SUCCESS);
121 break;
123 case FTP_PASV:
124 S_passive_mode = 1;
125 send_reply(S_cmd_sk, S_passive_str);
126 break;
128 case FTP_PWD:
129 getcwd(AuxBuf, LINE_SIZE);
130 /* Root directory santy check */
131 if (AuxBuf[Basedir_len] == '\0') {
132 AuxBuf[Basedir_len] = '/';
133 AuxBuf[Basedir_len + 1] = '\0';
135 /* We can overwrite the line buffer as no useful
136 * argument will be present */
137 snprintf(LineBuf, LINE_SIZE, "257 \"%s\"\r\n",
138 AuxBuf + Basedir_len);
139 send_reply(S_cmd_sk, LineBuf);
140 break;
142 case FTP_REST:
143 /* We don't need str_to_ll() as sscanf() does de job */
144 sscanf(S_arg, "%lld", &S_offset);
145 snprintf(AuxBuf, LINE_SIZE, "350 Got it (%lld).\r\n",
146 S_offset);
147 send_reply(S_cmd_sk, AuxBuf);
148 break;
151 * Complex commands implemented separately.
153 case FTP_PORT:
154 client_port();
155 break;
157 case FTP_NLST:
158 list_dir(0);
159 break;
161 case FTP_LIST:
162 list_dir(1);
163 break;
165 case FTP_MDTM:
166 file_stats(0);
167 break;
169 case FTP_SIZE:
170 file_stats(1);
171 break;
173 case FTP_CWD:
174 change_dir();
175 break;
177 case FTP_RETR:
178 send_file();
179 break;
181 case FTP_NONE:
182 default:
183 send_reply(S_cmd_sk, "500 Command unrecognized.\r\n");