/commands/ftpd200/ftpd.c
C | 410 lines | 306 code | 66 blank | 38 comment | 49 complexity | 5b9837b0a31b0e374c14b1dc8e312535 MD5 | raw file
Possible License(s): AGPL-1.0, BSD-3-Clause
- /* ftpd.c Copyright 1992-2000 by Michael Temari All Rights Reserved
- *
- * ftpd An FTP server program for use with Minix.
- *
- * Usage: Minix usage: tcpd ftp ftpd
- *
- * 06/14/92 Tnet Release Michael Temari
- * 01/15/96 0.30 Michael Temari
- * 01/25/96 0.90 Michael Temari
- * 03/17/96 0.91 Michael Temari
- * 06/27/96 0.92 Michael Temari
- * 07/02/96 0.93 Michael Temari
- * 07/15/96 0.94 Michael Temari
- * 08/27/96 0.95 Michael Temari
- * 02/09/97 0.96 Michael Temari
- * 02/10/97 0.97 Michael Temari
- * 09/25/97 0.98 Michael Temari
- * 03/10/00 0.99 Michael Temari, <Michael@TemWare.Com>
- * 12/12/03 1.00 Michael Temari, <Michael@TemWare.Com>
- * 02/06/05 1.01 Michael Temari, <Michael@TemWare.Com>
- * 02/12/05 2.00 Michael Temari, <Michael@TemWare.Com>
- */
- char *FtpdVersion = "2.00";
- #include <sys/types.h>
- #include <signal.h>
- #include <stdio.h>
- #include <stdlib.h>
- #include <ctype.h>
- #include <string.h>
- #include <time.h>
- #include <unistd.h>
- #include <net/gen/in.h>
- #include <net/gen/tcp.h>
- #include "ftpd.h"
- #include "access.h"
- #include "file.h"
- #include "net.h"
- #ifdef __NBSD_LIBC
- /* Already declared in stdio.h */
- #define getline ftpd_getline
- #endif
- _PROTOTYPE(static void init, (void));
- _PROTOTYPE(static int doHELP, (char *buff));
- _PROTOTYPE(static int doNOOP, (char *buff));
- _PROTOTYPE(static int doUNIMP, (char *buff));
- _PROTOTYPE(static int getline, (char *line, int len));
- FILE *msgfile = (FILE *)NULL;
- /* The following defines the inactivity timeout in seconds */
- #define INACTIVITY_TIMEOUT 60*5
- char *days[] = {"Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"};
- char *months[] = {"Jan", "Feb", "Mar", "Apr", "May", "Jun",
- "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"};
- char line[512];
- int type, format, mode, structure;
- int ftpdata_fd = -1;
- int loggedin, gotuser, anonymous;
- char username[80];
- char anonpass[128];
- char newroot[128];
- ipaddr_t myipaddr, rmtipaddr, dataaddr;
- tcpport_t myport, rmtport, dataport;
- char myhostname[256], rmthostname[256];
- #define FTPD_LOG "/usr/adm/ftpd.log"
- #define FTPD_MSG "/etc/ftpd_msg"
- FILE *logfile;
- int timeout = 0;
- _PROTOTYPE(static int doHELP, (char *buff));
- _PROTOTYPE(int readline, (char **args));
- _PROTOTYPE(void Timeout, (int sig));
- _PROTOTYPE(int main, (int argc, char *argv[]));
- struct commands {
- char *name;
- _PROTOTYPE(int (*func), (char *buff));
- };
- struct commands commands[] = {
- "ABOR", doUNIMP,
- "ACCT", doUNIMP,
- "ALLO", doALLO,
- "APPE", doAPPE,
- "CDUP", doCDUP,
- "CWD", doCWD,
- "DELE", doDELE,
- "HELP", doHELP,
- "LIST", doLIST,
- "MDTM", doMDTM,
- "MKD", doMKD,
- "MODE", doMODE,
- "NLST", doNLST,
- "NOOP", doNOOP,
- "PASS", doPASS,
- "PASV", doPASV,
- "PORT", doPORT,
- "PWD", doPWD,
- "QUIT", doQUIT,
- "REIN", doUNIMP,
- "REST", doREST,
- "RETR", doRETR,
- "RMD", doRMD,
- "RNFR", doRNFR,
- "RNTO", doRNTO,
- "SITE", doSITE,
- "SIZE", doSIZE,
- "SMNT", doUNIMP,
- "STAT", doSTAT,
- "STOR", doSTOR,
- "STOU", doSTOU,
- "STRU", doSTRU,
- "SYST", doSYST,
- "TYPE", doTYPE,
- "USER", doUSER,
- "XCUP", doCDUP,
- "XCWD", doCWD,
- "XMKD", doMKD,
- "XPWD", doPWD,
- "XRMD", doRMD,
- "", (int (*)())0
- };
- static void init()
- {
- loggedin = 0;
- gotuser = 0;
- anonymous = 0;
- newroot[0] = '\0';
- type = TYPE_A;
- format = 0;
- mode = MODE_S;
- structure = 0;
- ftpdata_fd = -1;
- username[0] = '\0';
- anonpass[0] = '\0';
- }
- /* nothing, nada, zilch... */
- static int doNOOP(buff)
- char *buff;
- {
- printf("200 NOOP to you too!\r\n");
- return(GOOD);
- }
- /* giv'em help, what a USER! */
- static int doHELP(buff)
- char *buff;
- {
- struct commands *cmd;
- char star;
- int i;
- char *space = " ";
- printf("214-Here is a list of available ftp commands\r\n");
- printf(" Those with '*' are not yet implemented.\r\n");
- i = 0;
- for(cmd = commands; *cmd->name != '\0'; cmd++) {
- if(cmd->func == doUNIMP)
- star = '*';
- else
- star = ' ';
- printf(" %s%c%s", cmd->name, star, space + strlen(cmd->name));
- if(++i == 6) {
- printf("\r\n");
- i = 0;
- }
- }
- if(i)
- printf("\r\n");
- printf("214 That's all the help you get.\r\n");
- return(GOOD);
- }
- /* not implemented */
- static int doUNIMP(buff)
- char *buff;
- {
- printf("502 Command \"%s\" not implemented!\r\n", line);
- return(GOOD);
- }
- /* convert line for use */
- void cvtline(args)
- char **args;
- {
- char *p;
- p = line + strlen(line);
- while(--p >= line)
- if(*p == '\r' || *p == '\n' || isspace(*p))
- *p = '\0';
- else
- break;
- p = line;
- #ifdef DEBUG
- logit("COMMAND", line);
- #endif
- while(*p && !isspace(*p)) {
- *p = toupper(*p);
- p++;
- }
- if(*p) {
- *p = '\0';
- p++;
- while(*p && isspace(*p))
- p++;
- }
- *args = p;
- return;
- }
- static int getline(line, len)
- char *line;
- int len;
- {
- int s;
- int gotcr;
- /* leave room for at end for null */
- len--;
- /* got to be able to put in at least 1 character */
- if(len < 1)
- return(-1);
- gotcr = 0;
- while(len-- > 0) {
- s = read(0, line, 1);
- if(s != 1)
- return(-1);
- if(*line == '\n')
- break;
- gotcr = (*line == '\r');
- line++;
- }
- if(gotcr)
- --line;
- *line = '\0';
- return(0);
- }
- int readline(args)
- char **args;
- {
- if(getline(line, sizeof(line)))
- return(BAD);
- cvtline(args);
- return(GOOD);
- }
- /* signal handler for inactivity timeout */
- void Timeout(sig)
- int sig;
- {
- timeout = 1;
- printf("421 Inactivity timer expired.\r\n");
- }
- /* logit */
- void logit(type, parm)
- char *type;
- char *parm;
- {
- time_t now;
- struct tm *tm;
- if(logfile == (FILE *)NULL)
- return;
- time(&now);
- tm = localtime(&now);
- fprintf(logfile, "%4d%02d%02d%02d%02d%02d ",
- 1900+tm->tm_year,
- tm->tm_mon + 1,
- tm->tm_mday,
- tm->tm_hour, tm->tm_min, tm->tm_sec);
- fprintf(logfile, "%s %s %s %s %s\n",
- rmthostname, username, anonymous ? anonpass : username, type, parm);
- fflush(logfile);
- }
- void showmsg(reply, filename)
- char *reply;
- char *filename;
- {
- FILE *mfp;
- char *pe;
- static char mline[256];
- if(filename == (char *)NULL)
- mfp = msgfile;
- else
- mfp = fopen(filename, "r");
- if(mfp == (FILE *)NULL)
- return;
- while(fgets(mline, sizeof(mline), mfp) != (char *)NULL) {
- pe = mline + strlen(mline);
- while(--pe >= mline)
- if(*pe == '\r' || *pe == '\n')
- *pe = '\0';
- else
- break;
- printf("%s- %s\r\n", reply, mline);
- }
- if(filename != (char *)NULL)
- fclose(mfp);
- }
- int main(argc, argv)
- int argc;
- char *argv[];
- {
- struct commands *cmd;
- char *args;
- int status;
- time_t now;
- struct tm *tm;
- int s;
- GetNetInfo();
- /* open transfer log file if it exists */
- if((logfile = fopen(FTPD_LOG, "r")) != (FILE *)NULL) {
- fclose(logfile);
- logfile = fopen(FTPD_LOG, "a");
- }
- /* open login msg file */
- msgfile = fopen(FTPD_MSG, "r");
- /* Let's initialize some stuff */
- init();
- /* Log the connection */
- logit("CONNECT", "");
- /* Tell 'em we are ready */
- time(&now);
- tm = localtime(&now);
- printf("220 FTP service (Ftpd %s) ready on %s at ",
- FtpdVersion, myhostname);
- printf("%s, %02d %s %d %02d:%02d:%02d %s\r\n", days[tm->tm_wday],
- tm->tm_mday, months[tm->tm_mon], 1900+tm->tm_year,
- tm->tm_hour, tm->tm_min, tm->tm_sec,
- tzname[tm->tm_isdst]);
- fflush(stdout);
- /* Loop here getting commands */
- while(1) {
- signal(SIGALRM, Timeout);
- alarm(INACTIVITY_TIMEOUT);
- if(readline(&args) != GOOD) {
- if(!timeout)
- printf("221 Control connection closing (EOF).\r\n");
- break;
- }
- alarm(0);
- for(cmd = commands; *cmd->name != '\0'; cmd++)
- if(!strcmp(line, cmd->name))
- break;
- if(*cmd->name != '\0')
- status = (*cmd->func)(args);
- else {
- printf("500 Command \"%s\" not recognized.\r\n", line);
- status = GOOD;
- }
- fflush(stdout);
- if(status != GOOD)
- break;
- }
- CleanUpPasv();
- return(-1);
- }