Fix LIST directory argument manipulation.
[uftps.git] / command_loop.c
blob909133b803ccc8669914850cd35834df3551ce7d
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
20 #include "uftps.h"
21 #include <ctype.h>
22 #include <unistd.h>
23 #include <stdlib.h>
24 #include <stdio.h>
28 * Main FTP server loop. The switch should be converted to an indexed jump
29 * because the command values are consecutive integers. Thus avoiding the
30 * multiple string comparisons.
32 void command_loop (void)
34 int e, l;
36 do {
37 switch (next_command())
40 * Straightforward implementations.
42 case FTP_NOOP:
43 reply_c("200 I'm alive, don't worry\r\n");
44 break;
46 case FTP_FEAT:
47 reply_c("211-Feature list:\r\n"
48 "211- MDTM\r\n"
49 "211- REST STREAM\r\n"
50 "211- SIZE\r\n"
51 "211- TVFS\r\n"
52 "211 End.\r\n");
53 break;
55 case FTP_SYST:
56 reply_c("215 UNIX Type: L8\r\n");
57 break;
59 case FTP_PASS:
60 case FTP_USER:
61 reply_c("230 I don't care.\r\n");
62 break;
64 case FTP_OPTS:
65 reply_c("501 Option not understood.\r\n");
66 break;
68 case FTP_ACCT:
69 case FTP_SMNT:
70 reply_c("202 Unimplemented, ignored.\r\n");
71 break;
73 case FTP_REIN:
74 reply_c("220 Nothing to REIN.\r\n");
75 break;
78 * A bit more complex commands.
80 case FTP_MODE:
81 if (toupper(SS.arg[0]) == 'S')
82 reply_c("200 MODE set to stream.\r\n");
83 else
84 reply_c("504 Mode not supported.\r\n");
85 break;
87 case FTP_STRU:
88 if (toupper(SS.arg[0]) == 'F')
89 reply_c("200 STRUcture set to file.\r\n");
90 else
91 reply_c("504 Structure not supported.\r\n");
92 break;
94 case FTP_TYPE:
95 switch (toupper(SS.arg[0]))
97 case 'I':
98 case 'A':
99 case 'L': reply_c("200 Whatever.\r\n"); break;
100 default : reply_c("504 Type not supported.\r\n");
102 break;
104 case FTP_PWD:
105 l = snprintf(SS.aux, LINE_SIZE, "257 \"%s\"\r\n", &SS.cwd[1]);
106 reply(SS.aux, l);
107 break;
109 case FTP_REST:
110 /* We don't need str_to_ll() as sscanf() does de job */
111 sscanf(SS.arg, "%lld", (long long *) &SS.file_offset);
112 l = snprintf(SS.aux, LINE_SIZE, "350 Got it (%lld).\r\n",
113 (long long) SS.file_offset);
114 reply(SS.aux, l);
115 break;
117 case FTP_QUIT:
118 reply_c("221 Goodbye.\r\n");
119 e = close(SS.control_sk);
120 if (e == -1)
121 error("Closing control channel");
123 if (SS.passive_sk != -1)
125 e = close(SS.passive_sk);
126 if (e == -1)
127 error("Closing passive socket");
129 exit(EXIT_SUCCESS);
130 break;
133 * Complex commands implemented separately.
135 case FTP_PORT:
136 parse_port_argument();
137 break;
139 case FTP_PASV:
140 enable_passive();
141 break;
143 case FTP_NLST:
144 list_dir(0);
145 break;
147 case FTP_LIST:
148 list_dir(1);
149 break;
151 case FTP_MDTM:
152 file_stats(0);
153 break;
155 case FTP_SIZE:
156 file_stats(1);
157 break;
159 case FTP_CWD:
160 change_dir();
161 break;
163 case FTP_RETR:
164 send_file();
165 break;
167 case FTP_NONE:
168 reply_c("500 Command unrecognized.\r\n");
169 break;
171 default:
172 reply_c("502 Command not implemented.\r\n");
174 } while (1);