source: trunk/minix/commands/ftpd200/ftpd.c@ 15

Last change on this file since 15 was 9, checked in by Mattia Monga, 14 years ago

Minix 3.1.2a

File size: 7.3 KB
Line 
1/* ftpd.c Copyright 1992-2000 by Michael Temari All Rights Reserved
2 *
3 * ftpd An FTP server program for use with Minix.
4 *
5 * Usage: Minix usage: tcpd ftp ftpd
6 *
7 * 06/14/92 Tnet Release Michael Temari
8 * 01/15/96 0.30 Michael Temari
9 * 01/25/96 0.90 Michael Temari
10 * 03/17/96 0.91 Michael Temari
11 * 06/27/96 0.92 Michael Temari
12 * 07/02/96 0.93 Michael Temari
13 * 07/15/96 0.94 Michael Temari
14 * 08/27/96 0.95 Michael Temari
15 * 02/09/97 0.96 Michael Temari
16 * 02/10/97 0.97 Michael Temari
17 * 09/25/97 0.98 Michael Temari
18 * 03/10/00 0.99 Michael Temari, <Michael@TemWare.Com>
19 * 12/12/03 1.00 Michael Temari, <Michael@TemWare.Com>
20 * 02/06/05 1.01 Michael Temari, <Michael@TemWare.Com>
21 * 02/12/05 2.00 Michael Temari, <Michael@TemWare.Com>
22 */
23
24char *FtpdVersion = "2.00";
25
26#include <sys/types.h>
27#include <signal.h>
28#include <stdio.h>
29#include <stdlib.h>
30#include <ctype.h>
31#include <string.h>
32#include <time.h>
33#include <unistd.h>
34#include <net/gen/in.h>
35#include <net/gen/tcp.h>
36
37#include "ftpd.h"
38#include "access.h"
39#include "file.h"
40#include "net.h"
41
42_PROTOTYPE(static void init, (void));
43_PROTOTYPE(static int doHELP, (char *buff));
44_PROTOTYPE(static int doNOOP, (char *buff));
45_PROTOTYPE(static int doUNIMP, (char *buff));
46_PROTOTYPE(static int getline, (char *line, int len));
47
48FILE *msgfile = (FILE *)NULL;
49
50/* The following defines the inactivity timeout in seconds */
51#define INACTIVITY_TIMEOUT 60*5
52
53char *days[] = {"Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"};
54char *months[] = {"Jan", "Feb", "Mar", "Apr", "May", "Jun",
55 "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"};
56
57char line[512];
58
59int type, format, mode, structure;
60int ftpdata_fd = -1;
61int loggedin, gotuser, anonymous;
62char username[80];
63char anonpass[128];
64char newroot[128];
65
66ipaddr_t myipaddr, rmtipaddr, dataaddr;
67tcpport_t myport, rmtport, dataport;
68
69char myhostname[256], rmthostname[256];
70
71#define FTPD_LOG "/usr/adm/ftpd.log"
72#define FTPD_MSG "/etc/ftpd_msg"
73
74FILE *logfile;
75
76int timeout = 0;
77
78_PROTOTYPE(static int doHELP, (char *buff));
79_PROTOTYPE(int readline, (char **args));
80_PROTOTYPE(void Timeout, (int sig));
81_PROTOTYPE(int main, (int argc, char *argv[]));
82
83struct commands {
84 char *name;
85 _PROTOTYPE(int (*func), (char *buff));
86};
87
88struct commands commands[] = {
89 "ABOR", doUNIMP,
90 "ACCT", doUNIMP,
91 "ALLO", doALLO,
92 "APPE", doAPPE,
93 "CDUP", doCDUP,
94 "CWD", doCWD,
95 "DELE", doDELE,
96 "HELP", doHELP,
97 "LIST", doLIST,
98 "MDTM", doMDTM,
99 "MKD", doMKD,
100 "MODE", doMODE,
101 "NLST", doNLST,
102 "NOOP", doNOOP,
103 "PASS", doPASS,
104 "PASV", doPASV,
105 "PORT", doPORT,
106 "PWD", doPWD,
107 "QUIT", doQUIT,
108 "REIN", doUNIMP,
109 "REST", doREST,
110 "RETR", doRETR,
111 "RMD", doRMD,
112 "RNFR", doRNFR,
113 "RNTO", doRNTO,
114 "SITE", doSITE,
115 "SIZE", doSIZE,
116 "SMNT", doUNIMP,
117 "STAT", doSTAT,
118 "STOR", doSTOR,
119 "STOU", doSTOU,
120 "STRU", doSTRU,
121 "SYST", doSYST,
122 "TYPE", doTYPE,
123 "USER", doUSER,
124 "XCUP", doCDUP,
125 "XCWD", doCWD,
126 "XMKD", doMKD,
127 "XPWD", doPWD,
128 "XRMD", doRMD,
129 "", (int (*)())0
130};
131
132static void init()
133{
134 loggedin = 0;
135 gotuser = 0;
136 anonymous = 0;
137 newroot[0] = '\0';
138 type = TYPE_A;
139 format = 0;
140 mode = MODE_S;
141 structure = 0;
142 ftpdata_fd = -1;
143 username[0] = '\0';
144 anonpass[0] = '\0';
145}
146
147/* nothing, nada, zilch... */
148static int doNOOP(buff)
149char *buff;
150{
151 printf("200 NOOP to you too!\r\n");
152
153 return(GOOD);
154}
155
156/* giv'em help, what a USER! */
157static int doHELP(buff)
158char *buff;
159{
160struct commands *cmd;
161char star;
162int i;
163char *space = " ";
164
165 printf("214-Here is a list of available ftp commands\r\n");
166 printf(" Those with '*' are not yet implemented.\r\n");
167
168 i = 0;
169 for(cmd = commands; *cmd->name != '\0'; cmd++) {
170 if(cmd->func == doUNIMP)
171 star = '*';
172 else
173 star = ' ';
174 printf(" %s%c%s", cmd->name, star, space + strlen(cmd->name));
175 if(++i == 6) {
176 printf("\r\n");
177 i = 0;
178 }
179 }
180
181 if(i)
182 printf("\r\n");
183
184 printf("214 That's all the help you get.\r\n");
185
186 return(GOOD);
187}
188
189/* not implemented */
190static int doUNIMP(buff)
191char *buff;
192{
193 printf("502 Command \"%s\" not implemented!\r\n", line);
194
195 return(GOOD);
196}
197
198/* convert line for use */
199void cvtline(args)
200char **args;
201{
202char *p;
203
204 p = line + strlen(line);
205 while(--p >= line)
206 if(*p == '\r' || *p == '\n' || isspace(*p))
207 *p = '\0';
208 else
209 break;
210
211 p = line;
212
213#ifdef DEBUG
214 logit("COMMAND", line);
215#endif
216
217 while(*p && !isspace(*p)) {
218 *p = toupper(*p);
219 p++;
220 }
221
222 if(*p) {
223 *p = '\0';
224 p++;
225 while(*p && isspace(*p))
226 p++;
227 }
228
229 *args = p;
230
231 return;
232}
233
234static int getline(line, len)
235char *line;
236int len;
237{
238int s;
239int gotcr;
240
241 /* leave room for at end for null */
242 len--;
243
244 /* got to be able to put in at least 1 character */
245 if(len < 1)
246 return(-1);
247
248 gotcr = 0;
249 while(len-- > 0) {
250 s = read(0, line, 1);
251 if(s != 1)
252 return(-1);
253 if(*line == '\n')
254 break;
255 gotcr = (*line == '\r');
256 line++;
257 }
258 if(gotcr)
259 --line;
260
261 *line = '\0';
262
263 return(0);
264}
265
266int readline(args)
267char **args;
268{
269 if(getline(line, sizeof(line)))
270 return(BAD);
271
272 cvtline(args);
273
274 return(GOOD);
275}
276
277/* signal handler for inactivity timeout */
278void Timeout(sig)
279int sig;
280{
281 timeout = 1;
282
283 printf("421 Inactivity timer expired.\r\n");
284}
285
286/* logit */
287void logit(type, parm)
288char *type;
289char *parm;
290{
291time_t now;
292struct tm *tm;
293
294 if(logfile == (FILE *)NULL)
295 return;
296
297 time(&now);
298 tm = localtime(&now);
299 fprintf(logfile, "%4d%02d%02d%02d%02d%02d ",
300 1900+tm->tm_year,
301 tm->tm_mon + 1,
302 tm->tm_mday,
303 tm->tm_hour, tm->tm_min, tm->tm_sec);
304 fprintf(logfile, "%s %s %s %s %s\n",
305 rmthostname, username, anonymous ? anonpass : username, type, parm);
306 fflush(logfile);
307}
308
309void showmsg(reply, filename)
310char *reply;
311char *filename;
312{
313FILE *mfp;
314char *pe;
315static char mline[256];
316
317 if(filename == (char *)NULL)
318 mfp = msgfile;
319 else
320 mfp = fopen(filename, "r");
321
322 if(mfp == (FILE *)NULL)
323 return;
324
325 while(fgets(mline, sizeof(mline), mfp) != (char *)NULL) {
326 pe = mline + strlen(mline);
327 while(--pe >= mline)
328 if(*pe == '\r' || *pe == '\n')
329 *pe = '\0';
330 else
331 break;
332 printf("%s- %s\r\n", reply, mline);
333 }
334
335 if(filename != (char *)NULL)
336 fclose(mfp);
337}
338
339int main(argc, argv)
340int argc;
341char *argv[];
342{
343struct commands *cmd;
344char *args;
345int status;
346time_t now;
347struct tm *tm;
348int s;
349
350 GetNetInfo();
351
352 /* open transfer log file if it exists */
353 if((logfile = fopen(FTPD_LOG, "r")) != (FILE *)NULL) {
354 fclose(logfile);
355 logfile = fopen(FTPD_LOG, "a");
356 }
357
358 /* open login msg file */
359 msgfile = fopen(FTPD_MSG, "r");
360
361 /* Let's initialize some stuff */
362 init();
363
364 /* Log the connection */
365 logit("CONNECT", "");
366
367 /* Tell 'em we are ready */
368 time(&now);
369 tm = localtime(&now);
370 printf("220 FTP service (Ftpd %s) ready on %s at ",
371 FtpdVersion, myhostname);
372 printf("%s, %02d %s %d %02d:%02d:%02d %s\r\n", days[tm->tm_wday],
373 tm->tm_mday, months[tm->tm_mon], 1900+tm->tm_year,
374 tm->tm_hour, tm->tm_min, tm->tm_sec,
375 tzname[tm->tm_isdst]);
376 fflush(stdout);
377
378 /* Loop here getting commands */
379 while(1) {
380 signal(SIGALRM, Timeout);
381 alarm(INACTIVITY_TIMEOUT);
382 if(readline(&args) != GOOD) {
383 if(!timeout)
384 printf("221 Control connection closing (EOF).\r\n");
385 break;
386 }
387 alarm(0);
388 for(cmd = commands; *cmd->name != '\0'; cmd++)
389 if(!strcmp(line, cmd->name))
390 break;
391 if(*cmd->name != '\0')
392 status = (*cmd->func)(args);
393 else {
394 printf("500 Command \"%s\" not recognized.\r\n", line);
395 status = GOOD;
396 }
397 fflush(stdout);
398 if(status != GOOD)
399 break;
400 }
401
402 CleanUpPasv();
403
404 return(-1);
405}
Note: See TracBrowser for help on using the repository browser.