Added a specific reply function for the data channel.
[uftps.git] / next_command.c
blob1d7cfecec50082bc47b3699712a096ec1b3aa0c1
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 <errno.h>
22 #include <unistd.h>
23 #include <stdlib.h>
24 #include <string.h>
25 #include <ctype.h>
27 #include "command_parser.h"
31 * Read data from the control channel until a complete request (delimited by
32 * CRLF) is found.
34 * Control channel processing is implemented in a pipelined fashion. Trailing
35 * bytes belonging to the following request are left in the buffer; to be read
36 * in the next call to this function.
38 static void read_request (void)
40 int l, i, b;
42 i = 0;
43 l = SS.input_len;
44 /* Shift trailing data from previous call */
45 if (SS.input_offset > 0)
46 memmove(SS.input, SS.input + SS.input_offset, l);
48 do {
49 while (i < l && SS.input[i] != '\n')
50 i++;
51 if (SS.input[i] == '\n')
53 if (i > 0 && SS.input[i - 1] == '\r')
54 break;
55 else
56 continue;
59 /* Buffer data exhausted, get more from the network */
60 b = recv(SS.control_sk, SS.input + l, LINE_SIZE - l, 0);
61 if (b <= 0)
63 if (b == -1)
64 fatal("Control channel input");
65 else if (l == LINE_SIZE)
67 errno = 0;
68 fatal("Input buffer overflow");
70 else
72 notice("Peer closed control connection");
73 close(SS.control_sk);
74 exit(EXIT_SUCCESS);
78 l += b;
79 } while (1);
81 /* Mark residual (trailing) bytes for the next call */
82 SS.input[i - 1] = '\0';
83 SS.input[i] = '\0';
84 i++;
85 SS.input_len = l - i;
86 SS.input_offset = (l - i > 0 ? i : 0);
88 debug("Request : %s", SS.input);
93 * Parse the current request from the control channel and return the
94 * corresponding command number. The command argument (SS.arg) is filled
95 * accordingly.
97 enum command next_command (void)
99 const struct Cmd *cmd;
100 int i;
102 read_request();
104 i = 0;
105 while (SS.input[i] != ' ' && SS.input[i] != '\0')
107 SS.input[i] = toupper(SS.input[i] & 0x07F);
108 i++;
111 SS.arg = (SS.input[i] == ' ' ? &SS.input[i + 1] : NULL);
112 SS.input[i] = '\0';
114 cmd = parse_command(SS.input, i);
115 if (cmd == NULL)
116 return FTP_NONE;
117 return cmd->value;