Removed system headers from uftps.h.
[uftps.git] / next_command.c
blobdd2cc9a992ef9ad436449efc63a80017731e6c04
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
21 * Return the next command (as an integer) available in the control channel.
23 * Most of this implementation has been inspired by str_netfd_alloc() from
24 * netstr.c of VsFTPd.
27 #include "uftps.h"
28 #include "command_list.h" /* Command recognizer */
29 #include <sys/types.h>
30 #include <sys/socket.h>
31 #include <unistd.h>
32 #include <stdlib.h>
33 #include <stdio.h>
34 #include <ctype.h>
37 command_t next_command (void)
39 const struct Cmd *cmd; /* parsed command value */
40 int keepon; /* loop exit flag */
41 int i; /* processed and saved information index */
42 int j; /* unprocessed and saved information index */
43 int b; /* read bytes from recv() (auxiliary) */
46 * First of all, try to read a whole line (consuming up to the CRLF
47 * sequence), doing a peek; that is, reading from the socket buffer
48 * without really consuming. There is a hard limit of LINE_SIZE up to
49 * the LF character.
51 * If a LF character is found before reaching the end of the read chunk,
52 * only that line will be retired from the socket buffer. Otherwise,
53 * consume everything to let more network data to come.
55 * The management scheme of the 'Line' buffer is as follows:
57 * ____________ b ___________
58 * / \
59 * +--------------------+----------------+----------+-------+
60 * Line: | Processed data | Last call to recv() | ... |
61 * +--------------------+----------------+----------+-------+
62 * ^ ^ ^
63 * i j (i+b)
65 i = 0;
66 keepon = 1;
67 while (keepon) {
68 b = recv(S_cmd_sk, LineBuf + i, LINE_SIZE - i, MSG_PEEK);
69 if (b == 0) {
70 if (i == LINE_SIZE)
71 printf("(%d) * Overflow attempt, exiting.\n",
72 getpid());
73 else
74 printf("(%d) * Close request without QUIT command, exiting.\n",
75 getpid());
76 close(S_cmd_sk);
77 exit(EXIT_FAILURE);
80 /* Locate LF character, j will point to it */
81 for (j = i; j < (b + i) && LineBuf[j] != '\n'; j++)
82 /* ... */;
84 /* Check limits */
85 if (j == (b + i)) {
86 /* LF not found yet, clean the socket buffer */
87 i += b;
88 j = b;
89 do {
90 b = recv(S_cmd_sk, AuxBuf, j, 0);
91 j -= b;
92 } while (j > 0);
93 } else {
94 /* LF found, consume only that line and get out */
95 LineBuf[j-1] = '\0';
96 i = j + 1;
97 do {
98 b = recv(S_cmd_sk, AuxBuf, i, 0);
99 i -= b;
100 } while (i > 0);
101 keepon = 0;
105 debug_msg(">>> %s\n", LineBuf);
107 /* Check if arguments are present and set 'S_arg' pointer as needed */
108 for (; LineBuf[i] != ' ' && LineBuf[i] != '\0'; i++)
109 LineBuf[i] = (char) (toupper(LineBuf[i]) & 0x07F);
111 if (LineBuf[i] != '\0')
112 S_arg = LineBuf + i + 1;
113 else
114 S_arg = NULL;
116 cmd = command_lookup(LineBuf, i);
117 if (cmd == NULL)
118 return FTP_NONE;
120 return cmd->value;