Added a specific reply function for the data channel.
[uftps.git] / command_loop.c
blob829673cb9c0a99469f0bbed4b10e05863246f77b
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 * This function never returns.
34 void command_loop (void)
36 int l;
38 do {
39 switch (next_command())
42 * Straightforward implementations.
44 case FTP_NOOP:
45 reply_c("200 I'm alive, don't worry\r\n");
46 break;
48 case FTP_FEAT:
49 reply_c("211-Feature list:\r\n"
50 "211- MDTM\r\n"
51 "211- REST STREAM\r\n"
52 "211- SIZE\r\n"
53 "211- TVFS\r\n"
54 "211 End.\r\n");
55 break;
57 case FTP_SYST:
58 reply_c("215 UNIX Type: L8\r\n");
59 break;
61 case FTP_PASS:
62 case FTP_USER:
63 reply_c("230 I don't care.\r\n");
64 break;
66 case FTP_OPTS:
67 reply_c("501 Option not understood.\r\n");
68 break;
70 case FTP_ACCT:
71 case FTP_SMNT:
72 reply_c("202 Unimplemented, ignored.\r\n");
73 break;
75 case FTP_REIN:
76 reply_c("220 Nothing to REIN.\r\n");
77 break;
80 * A bit more complex commands.
82 case FTP_MODE:
83 if (toupper(SS.arg[0]) == 'S')
84 reply_c("200 MODE set to stream.\r\n");
85 else
86 reply_c("504 Mode not supported.\r\n");
87 break;
89 case FTP_STRU:
90 if (toupper(SS.arg[0]) == 'F')
91 reply_c("200 STRUcture set to file.\r\n");
92 else
93 reply_c("504 Structure not supported.\r\n");
94 break;
96 case FTP_TYPE:
97 switch (toupper(SS.arg[0]))
99 case 'I':
100 case 'A':
101 case 'L': reply_c("200 Whatever.\r\n"); break;
102 default : reply_c("504 Type not supported.\r\n");
104 break;
106 case FTP_PWD:
107 l = snprintf(SS.aux, LINE_SIZE, "257 \"%s\"\r\n", &SS.cwd[1]);
108 reply(SS.aux, l);
109 break;
111 case FTP_REST:
112 /* We don't need str_to_ll() as sscanf() does de job */
113 sscanf(SS.arg, "%lld", (long long *) &SS.file_offset);
114 l = snprintf(SS.aux, LINE_SIZE, "350 Got it (%lld).\r\n",
115 (long long) SS.file_offset);
116 reply(SS.aux, l);
117 break;
119 case FTP_QUIT:
120 reply_c("221 Goodbye.\r\n");
121 close(SS.control_sk);
122 if (SS.passive_sk != -1)
123 close(SS.passive_sk);
124 exit(EXIT_SUCCESS);
125 break;
128 * Complex commands implemented separately.
130 case FTP_PORT:
131 parse_port_argument();
132 break;
134 case FTP_PASV:
135 enable_passive();
136 break;
138 case FTP_CWD:
139 change_dir();
140 break;
142 case FTP_NLST:
143 list_dir(0);
144 break;
146 case FTP_LIST:
147 list_dir(1);
148 break;
150 case FTP_MDTM:
151 file_stats(0);
152 break;
154 case FTP_SIZE:
155 file_stats(1);
156 break;
158 case FTP_RETR:
159 send_file();
160 break;
163 * Unrecognized or unimplemented commands.
165 case FTP_NONE:
166 reply_c("500 Command unrecognized.\r\n");
167 break;
169 default:
170 reply_c("502 Command not implemented.\r\n");
172 } while (1);