cc17b27a2b
3 sets of libraries are built now: . ack: all libraries that ack can compile (/usr/lib/i386/) . clang+elf: all libraries with minix headers (/usr/lib/) . clang+elf: all libraries with netbsd headers (/usr/netbsd/) Once everything can be compiled with netbsd libraries and headers, the /usr/netbsd hierarchy will be obsolete and its libraries compiled with netbsd headers will be installed in /usr/lib, and its headers in /usr/include. (i.e. minix libc and current minix headers set will be gone.) To use the NetBSD libc system (libraries + headers) before it is the default libc, see: http://wiki.minix3.org/en/DevelopersGuide/UsingNetBSDCode This wiki page also documents the maintenance of the patch files of minix-specific changes to imported NetBSD code. Changes in this commit: . libsys: Add NBSD compilation and create a safe NBSD-based libc. . Port rest of libraries (except libddekit) to new header system. . Enable compilation of libddekit with new headers. . Enable kernel compilation with new headers. . Enable drivers compilation with new headers. . Port legacy commands to new headers and libc. . Port servers to new headers. . Add <sys/sigcontext.h> in compat library. . Remove dependency file in tree. . Enable compilation of common/lib/libc/atomic in libsys . Do not generate RCSID strings in libc. . Temporarily disable zoneinfo as they are incompatible with NetBSD format . obj-nbsd for .gitignore . Procfs: use only integer arithmetic. (Antoine Leca) . Increase ramdisk size to create NBSD-based images. . Remove INCSYMLINKS handling hack. . Add nbsd_include/sys/exec_elf.h . Enable ELF compilation with NBSD libc. . Add 'make nbsdsrc' in tools to download reference NetBSD sources. . Automate minix-port.patch creation. . Avoid using fstavfs() as it is *extremely* slow and unneeded. . Set err() as PRIVATE to avoid name clash with libc. . [NBSD] servers/vm: remove compilation warnings. . u32 is not a long in NBSD headers. . UPDATING info on netbsd hierarchy . commands fixes for netbsd libc
410 lines
7.4 KiB
C
410 lines
7.4 KiB
C
/* 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);
|
|
}
|