forked from Imagelibrary/rtems
Patch from Emmanuel Rauget (raguet@crf.canon.fr) to add a htons on the
sin_port.
This commit is contained in:
@@ -1,4 +1,8 @@
|
|||||||
/*
|
/* FIXME: 1. Parse command is a hack. We can do better.
|
||||||
|
* 2. chdir is a hack. We can do better.
|
||||||
|
* 3. PWD doesn't work.
|
||||||
|
* 4. Some sort of access control?
|
||||||
|
*
|
||||||
* FTP Server Daemon
|
* FTP Server Daemon
|
||||||
*
|
*
|
||||||
* Submitted by: Jake Janovetz <janovetz@tempest.ece.uiuc.edu>
|
* Submitted by: Jake Janovetz <janovetz@tempest.ece.uiuc.edu>
|
||||||
@@ -6,34 +10,17 @@
|
|||||||
* $Id$
|
* $Id$
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/*
|
|
||||||
* Current state:
|
|
||||||
* To untar, put as "untar"
|
|
||||||
* CWD uses chdir
|
|
||||||
* This is bad due to global setting of chdir.
|
|
||||||
*
|
|
||||||
* Stored files come into RAM and are saved later. This is an artifact
|
|
||||||
* of a previous implementation (no filesystem -- had to do stuff with
|
|
||||||
* the "files" later). This can be eliminated once all of Jake's stuff
|
|
||||||
* is moved to devices/filesystems.
|
|
||||||
*
|
|
||||||
* CLOSE(S) doesn't seem to work. This causes problems in
|
|
||||||
* several areas. It lets too many file descriptors pile up
|
|
||||||
* and it doesn't seem to flush the stream.
|
|
||||||
*
|
|
||||||
* Is 'recv' what I want to use to get commands from the control port?
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
/**************************************************************************
|
/**************************************************************************
|
||||||
* ftpd.c *
|
* ftpd.c *
|
||||||
**************************************************************************
|
**************************************************************************
|
||||||
* Description: *
|
* Description: *
|
||||||
* *
|
* *
|
||||||
* This file contains the daemon which services requests that appear *
|
* This file contains the daemon which services requests that appear *
|
||||||
* on the 'FTP' port. This server is compatible with FTP, but it *
|
* on the FTP port. This server is compatible with FTP, but it *
|
||||||
* also provides services specific to the Erithacus system. *
|
* also provides 'hooks' to make it usable in situations where files *
|
||||||
* This server is started at boot-time and runs forever. *
|
* are not used/necessary. Once the server is started, it runs *
|
||||||
|
* forever. *
|
||||||
|
* *
|
||||||
* *
|
* *
|
||||||
* Organization: *
|
* Organization: *
|
||||||
* *
|
* *
|
||||||
@@ -44,12 +31,6 @@
|
|||||||
* is complete, the session task deletes itself. The daemon still *
|
* is complete, the session task deletes itself. The daemon still *
|
||||||
* runs, however. *
|
* runs, however. *
|
||||||
* *
|
* *
|
||||||
* Implementation Notes: *
|
|
||||||
* *
|
|
||||||
* The 'current working directory' implementation utilizes the *
|
|
||||||
* RTEMS filesystem cwd. This is no good since other processes *
|
|
||||||
* inherit the same cwd. *
|
|
||||||
* *
|
|
||||||
* *
|
* *
|
||||||
* Supported commands are: *
|
* Supported commands are: *
|
||||||
* *
|
* *
|
||||||
@@ -70,51 +51,34 @@
|
|||||||
* and port (x*256 + y). *
|
* and port (x*256 + y). *
|
||||||
* *
|
* *
|
||||||
* *
|
* *
|
||||||
* *
|
|
||||||
* The public routines contained in this file are: *
|
* The public routines contained in this file are: *
|
||||||
* *
|
* *
|
||||||
* FTPD_Start - Starts the server daemon, then returns to its caller. *
|
* rtems_initialize_ftpd_start - Starts the server daemon, then *
|
||||||
|
* returns to its caller. *
|
||||||
* *
|
* *
|
||||||
* *
|
* *
|
||||||
* The private routines contained in this file are: *
|
* The private routines contained in this file are: *
|
||||||
* *
|
* *
|
||||||
* FTPD_SendReply - Sends a reply code and text through the control *
|
* rtems_ftpd_send_reply - Sends a reply code and text through the *
|
||||||
* port. *
|
* control port. *
|
||||||
* FTPD_CommandStore - Performs the "STOR" command. *
|
* rtems_ftpd_command_retrieve - Performs to "RETR" command. *
|
||||||
* FTPD_CommandList - Performs the "LIST" command. *
|
* rtems_ftpd_command_store - Performs the "STOR" command. *
|
||||||
* FTPD_CommandPort - Opens a data port (the "PORT" command). *
|
* rtems_ftpd_command_list - Performs the "LIST" command. *
|
||||||
* FTPD_ParseCommand - Parses an incoming command. *
|
* rtems_ftpd_command_port - Opens a data port (the "PORT" command). *
|
||||||
* FTPD_Session - Begins a service session. *
|
* rtems_ftpd_parse_command - Parses an incoming command. *
|
||||||
* FTPD_Daemon - Listens on the FTP port for service requests. *
|
* rtmes_ftpd_session - Begins a service session. *
|
||||||
* *
|
* rtems_ftpd_daemon - Listens on the FTP port for service *
|
||||||
* *
|
* requests. *
|
||||||
*------------------------------------------------------------------------*
|
*------------------------------------------------------------------------*
|
||||||
* *
|
|
||||||
* Jake Janovetz *
|
* Jake Janovetz *
|
||||||
* University of Illinois *
|
* University of Illinois *
|
||||||
* 1406 West Green Street *
|
* 1406 West Green Street *
|
||||||
* Urbana IL 61801 *
|
* Urbana IL 61801 *
|
||||||
* *
|
|
||||||
**************************************************************************
|
**************************************************************************
|
||||||
* Change History: *
|
* Change History: *
|
||||||
* 12/01/97 - Creation (JWJ) *
|
* 12/01/97 - Creation (JWJ) *
|
||||||
*************************************************************************/
|
*************************************************************************/
|
||||||
|
|
||||||
/* Revision Control Information:
|
|
||||||
*
|
|
||||||
* $Source$
|
|
||||||
* $Id$
|
|
||||||
* $Log$
|
|
||||||
* Revision 1.3 1998/05/19 21:28:17 erithacus
|
|
||||||
* Update control socket to file I/O.
|
|
||||||
*
|
|
||||||
* Revision 1.2 1998/05/19 20:13:50 erithacus
|
|
||||||
* Remodeled to be entirely reentrant.
|
|
||||||
*
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
@@ -133,9 +97,10 @@
|
|||||||
#include <netinet/in.h>
|
#include <netinet/in.h>
|
||||||
|
|
||||||
#include "ftpd.h"
|
#include "ftpd.h"
|
||||||
#include "untar.h"
|
|
||||||
|
|
||||||
|
|
||||||
|
extern struct rtems_ftpd_configuration rtems_ftpd_configuration;
|
||||||
|
|
||||||
/**************************************************************************
|
/**************************************************************************
|
||||||
* Meanings of first and second digits of reply codes:
|
* Meanings of first and second digits of reply codes:
|
||||||
*
|
*
|
||||||
@@ -163,14 +128,6 @@
|
|||||||
*************************************************************************/
|
*************************************************************************/
|
||||||
|
|
||||||
|
|
||||||
/**************************************************************************
|
|
||||||
* Maximum buffer size for use by the transfer protocol.
|
|
||||||
* This will be eliminated when the filesystem is complete enough that
|
|
||||||
* we don't have to store the received data until we have something to
|
|
||||||
* do with it.
|
|
||||||
*************************************************************************/
|
|
||||||
#define FTPD_MAX_RECEIVESIZE (512*1024)
|
|
||||||
|
|
||||||
/**************************************************************************
|
/**************************************************************************
|
||||||
* SessionInfo structure.
|
* SessionInfo structure.
|
||||||
*
|
*
|
||||||
@@ -180,13 +137,14 @@
|
|||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
struct sockaddr_in data_addr; /* Data address for PORT commands */
|
struct sockaddr_in data_addr; /* Data address for PORT commands */
|
||||||
int ctrl_sock; /* Control connection socker */
|
FILE *ctrl_fp; /* File pointer for control connection */
|
||||||
char cwd[255]; /* Current working directory */
|
char cwd[255]; /* Current working directory */
|
||||||
/* Login -- future use -- */
|
/* Login -- future use -- */
|
||||||
int xfer_mode; /* Transfer mode (ASCII/binary) */
|
int xfer_mode; /* Transfer mode (ASCII/binary) */
|
||||||
} FTPD_SessionInfo_t;
|
} FTPD_SessionInfo_t;
|
||||||
|
|
||||||
|
|
||||||
|
#define FTPD_SERVER_MESSAGE "RTEMS FTP server (Version 1.0-JWJ) ready."
|
||||||
#define FTPD_WELCOME_MESSAGE \
|
#define FTPD_WELCOME_MESSAGE \
|
||||||
"Welcome to the RTEMS FTP server.\n" \
|
"Welcome to the RTEMS FTP server.\n" \
|
||||||
"\n" \
|
"\n" \
|
||||||
@@ -194,7 +152,7 @@ typedef struct
|
|||||||
|
|
||||||
|
|
||||||
/**************************************************************************
|
/**************************************************************************
|
||||||
* Function: FTPD_SendReply *
|
* Function: rtems_ftpd_send_reply *
|
||||||
**************************************************************************
|
**************************************************************************
|
||||||
* Description: *
|
* Description: *
|
||||||
* *
|
* *
|
||||||
@@ -216,7 +174,7 @@ typedef struct
|
|||||||
* 12/01/97 - Creation (JWJ) *
|
* 12/01/97 - Creation (JWJ) *
|
||||||
*************************************************************************/
|
*************************************************************************/
|
||||||
static void
|
static void
|
||||||
FTPD_SendReply(int code, char *text)
|
rtems_ftpd_send_reply(int code, char *text)
|
||||||
{
|
{
|
||||||
rtems_status_code sc;
|
rtems_status_code sc;
|
||||||
FTPD_SessionInfo_t *info = NULL;
|
FTPD_SessionInfo_t *info = NULL;
|
||||||
@@ -241,17 +199,19 @@ FTPD_SendReply(int code, char *text)
|
|||||||
if (text != NULL)
|
if (text != NULL)
|
||||||
{
|
{
|
||||||
sprintf(str, "%d %.70s\r\n", code, text);
|
sprintf(str, "%d %.70s\r\n", code, text);
|
||||||
|
fprintf(info->ctrl_fp, "%d %.70s\r\n", code, text);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
sprintf(str, "%d\r\n", code);
|
sprintf(str, "%d\r\n", code);
|
||||||
|
fprintf(info->ctrl_fp, "%d\r\n", code);
|
||||||
}
|
}
|
||||||
send(info->ctrl_sock, str, strlen(str), 0);
|
fflush(info->ctrl_fp);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**************************************************************************
|
/**************************************************************************
|
||||||
* Function: FTPD_CommandRetrieve *
|
* Function: rtems_ftpd_command_retrieve *
|
||||||
**************************************************************************
|
**************************************************************************
|
||||||
* Description: *
|
* Description: *
|
||||||
* *
|
* *
|
||||||
@@ -274,12 +234,11 @@ FTPD_SendReply(int code, char *text)
|
|||||||
* 04/29/98 - Creation (JWJ) *
|
* 04/29/98 - Creation (JWJ) *
|
||||||
*************************************************************************/
|
*************************************************************************/
|
||||||
static int
|
static int
|
||||||
FTPD_CommandRetrieve(char *filename)
|
rtems_ftpd_command_retrieve(char *filename)
|
||||||
{
|
{
|
||||||
int s;
|
int s;
|
||||||
int n;
|
int n;
|
||||||
|
int fd;
|
||||||
FILE *fp;
|
|
||||||
unsigned char *bufr;
|
unsigned char *bufr;
|
||||||
rtems_status_code sc;
|
rtems_status_code sc;
|
||||||
FTPD_SessionInfo_t *info = NULL;
|
FTPD_SessionInfo_t *info = NULL;
|
||||||
@@ -288,32 +247,31 @@ FTPD_CommandRetrieve(char *filename)
|
|||||||
sc = rtems_task_get_note(RTEMS_SELF, RTEMS_NOTEPAD_0,
|
sc = rtems_task_get_note(RTEMS_SELF, RTEMS_NOTEPAD_0,
|
||||||
(rtems_unsigned32 *)&info);
|
(rtems_unsigned32 *)&info);
|
||||||
|
|
||||||
|
if ((fd = open(filename, O_RDONLY)) == -1)
|
||||||
if ((fp = fopen(filename, "r")) == NULL)
|
|
||||||
{
|
{
|
||||||
FTPD_SendReply(450, "Error opening file.");
|
rtems_ftpd_send_reply(450, "Error opening file.");
|
||||||
return(0);
|
return(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
bufr = (unsigned char *)malloc(BUFSIZ);
|
bufr = (unsigned char *)malloc(BUFSIZ);
|
||||||
if (bufr == NULL)
|
if (bufr == NULL)
|
||||||
{
|
{
|
||||||
FTPD_SendReply(440, "Server error - malloc fail.");
|
rtems_ftpd_send_reply(440, "Server error - malloc fail.");
|
||||||
fclose(fp);
|
close(fd);
|
||||||
return(0);
|
return(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
/***********************************************************************
|
/***********************************************************************
|
||||||
* Connect to the data connection (PORT made in an earlier PORT call).
|
* Connect to the data connection (PORT made in an earlier PORT call).
|
||||||
**********************************************************************/
|
**********************************************************************/
|
||||||
FTPD_SendReply(150, "BINARY data connection.");
|
rtems_ftpd_send_reply(150, "BINARY data connection.");
|
||||||
s = socket(AF_INET, SOCK_STREAM, 0);
|
s = socket(AF_INET, SOCK_STREAM, 0);
|
||||||
if (connect(s, (struct sockaddr *)&info->data_addr,
|
if (connect(s, (struct sockaddr *)&info->data_addr,
|
||||||
sizeof(struct sockaddr)) < 0)
|
sizeof(struct sockaddr)) < 0)
|
||||||
{
|
{
|
||||||
FTPD_SendReply(420, "Server error - could not connect socket.");
|
rtems_ftpd_send_reply(420, "Server error - could not connect socket.");
|
||||||
free(bufr);
|
free(bufr);
|
||||||
fclose(fp);
|
close(fd);
|
||||||
close(s);
|
close(s);
|
||||||
return(1);
|
return(1);
|
||||||
}
|
}
|
||||||
@@ -321,18 +279,19 @@ FTPD_CommandRetrieve(char *filename)
|
|||||||
/***********************************************************************
|
/***********************************************************************
|
||||||
* Send the data over the ether.
|
* Send the data over the ether.
|
||||||
**********************************************************************/
|
**********************************************************************/
|
||||||
while ((n = fread(bufr, 1, BUFSIZ, fp)) != 0)
|
while ((n = read(fd, bufr, BUFSIZ)) > 0)
|
||||||
{
|
{
|
||||||
send(s, bufr, n, 0);
|
send(s, bufr, n, 0);
|
||||||
|
bufr[n-1] = '\0';
|
||||||
}
|
}
|
||||||
|
|
||||||
if (feof(fp))
|
if (n == 0)
|
||||||
{
|
{
|
||||||
FTPD_SendReply(210, "File sent successfully.");
|
rtems_ftpd_send_reply(210, "File sent successfully.");
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
FTPD_SendReply(450, "Retrieve failed.");
|
rtems_ftpd_send_reply(450, "Retrieve failed.");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (close(s) != 0)
|
if (close(s) != 0)
|
||||||
@@ -341,13 +300,13 @@ FTPD_CommandRetrieve(char *filename)
|
|||||||
}
|
}
|
||||||
|
|
||||||
free(bufr);
|
free(bufr);
|
||||||
fclose(fp);
|
close(fd);
|
||||||
return(0);
|
return(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**************************************************************************
|
/**************************************************************************
|
||||||
* Function: FTPD_CommandStore *
|
* Function: rtems_ftpd_command_store *
|
||||||
**************************************************************************
|
**************************************************************************
|
||||||
* Description: *
|
* Description: *
|
||||||
* *
|
* *
|
||||||
@@ -370,15 +329,15 @@ FTPD_CommandRetrieve(char *filename)
|
|||||||
* 12/01/97 - Creation (JWJ) *
|
* 12/01/97 - Creation (JWJ) *
|
||||||
*************************************************************************/
|
*************************************************************************/
|
||||||
static int
|
static int
|
||||||
FTPD_CommandStore(char *filename)
|
rtems_ftpd_command_store(char *filename)
|
||||||
{
|
{
|
||||||
char *bufr;
|
char *bufr;
|
||||||
char *bigBufr;
|
int s;
|
||||||
int s;
|
int n;
|
||||||
int n;
|
unsigned long size = 0;
|
||||||
unsigned long size = 0;
|
rtems_status_code sc;
|
||||||
rtems_status_code sc;
|
FTPD_SessionInfo_t *info = NULL;
|
||||||
FTPD_SessionInfo_t *info = NULL;
|
struct rtems_ftpd_hook *usehook = NULL;
|
||||||
|
|
||||||
|
|
||||||
sc = rtems_task_get_note(RTEMS_SELF, RTEMS_NOTEPAD_0,
|
sc = rtems_task_get_note(RTEMS_SELF, RTEMS_NOTEPAD_0,
|
||||||
@@ -387,26 +346,17 @@ FTPD_CommandStore(char *filename)
|
|||||||
bufr = (char *)malloc(BUFSIZ * sizeof(char));
|
bufr = (char *)malloc(BUFSIZ * sizeof(char));
|
||||||
if (bufr == NULL)
|
if (bufr == NULL)
|
||||||
{
|
{
|
||||||
FTPD_SendReply(440, "Server error - malloc fail.");
|
rtems_ftpd_send_reply(440, "Server error - malloc fail.");
|
||||||
return(1);
|
return(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
bigBufr = (char *)malloc(FTPD_MAX_RECEIVESIZE * sizeof(char));
|
rtems_ftpd_send_reply(150, "BINARY data connection.");
|
||||||
if (bigBufr == NULL)
|
|
||||||
{
|
|
||||||
FTPD_SendReply(440, "Server error - malloc fail.");
|
|
||||||
free(bufr);
|
|
||||||
return(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
FTPD_SendReply(150, "BINARY data connection.");
|
|
||||||
|
|
||||||
s = socket(AF_INET, SOCK_STREAM, 0);
|
s = socket(AF_INET, SOCK_STREAM, 0);
|
||||||
if (connect(s, (struct sockaddr *)&info->data_addr,
|
if (connect(s, (struct sockaddr *)&info->data_addr,
|
||||||
sizeof(struct sockaddr)) < 0)
|
sizeof(struct sockaddr)) < 0)
|
||||||
{
|
{
|
||||||
free(bufr);
|
free(bufr);
|
||||||
free(bigBufr);
|
|
||||||
close(s);
|
close(s);
|
||||||
return(1);
|
return(1);
|
||||||
}
|
}
|
||||||
@@ -414,22 +364,57 @@ FTPD_CommandStore(char *filename)
|
|||||||
|
|
||||||
/***********************************************************************
|
/***********************************************************************
|
||||||
* File: "/dev/null" just throws the data away.
|
* File: "/dev/null" just throws the data away.
|
||||||
|
* Otherwise, search our list of hooks to see if we need to do something
|
||||||
|
* special.
|
||||||
**********************************************************************/
|
**********************************************************************/
|
||||||
if (!strncmp("/dev/null", filename, 9))
|
if (!strncmp("/dev/null", filename, 9))
|
||||||
{
|
{
|
||||||
while ((n = read(s, bufr, BUFSIZ)) > 0);
|
while ((n = read(s, bufr, BUFSIZ)) > 0);
|
||||||
}
|
}
|
||||||
else
|
else if (rtems_ftpd_configuration.hooks != NULL)
|
||||||
{
|
{
|
||||||
|
struct rtems_ftpd_hook *hook;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
i = 0;
|
||||||
|
hook = &rtems_ftpd_configuration.hooks[i++];
|
||||||
|
while (hook->filename != NULL)
|
||||||
|
{
|
||||||
|
if (!strcmp(hook->filename, filename))
|
||||||
|
{
|
||||||
|
usehook = hook;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
hook = &rtems_ftpd_configuration.hooks[i++];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (usehook != NULL)
|
||||||
|
{
|
||||||
|
char *bigBufr;
|
||||||
|
|
||||||
|
/***********************************************************************
|
||||||
|
* Allocate space for our "file".
|
||||||
|
**********************************************************************/
|
||||||
|
bigBufr = (char *)malloc(
|
||||||
|
rtems_ftpd_configuration.max_hook_filesize * sizeof(char));
|
||||||
|
if (bigBufr == NULL)
|
||||||
|
{
|
||||||
|
rtems_ftpd_send_reply(440, "Server error - malloc fail.");
|
||||||
|
free(bufr);
|
||||||
|
return(1);
|
||||||
|
}
|
||||||
|
|
||||||
/***********************************************************************
|
/***********************************************************************
|
||||||
* Retrieve the file into our buffer space.
|
* Retrieve the file into our buffer space.
|
||||||
**********************************************************************/
|
**********************************************************************/
|
||||||
size = 0;
|
size = 0;
|
||||||
while ((n = read(s, bufr, BUFSIZ)) > 0)
|
while ((n = read(s, bufr, BUFSIZ)) > 0)
|
||||||
{
|
{
|
||||||
if (size + n > FTPD_MAX_RECEIVESIZE)
|
if (size + n >
|
||||||
|
rtems_ftpd_configuration.max_hook_filesize * sizeof(char))
|
||||||
{
|
{
|
||||||
FTPD_SendReply(440, "Server error - Buffer size exceeded.");
|
rtems_ftpd_send_reply(440, "Server error - Buffer size exceeded.");
|
||||||
free(bufr);
|
free(bufr);
|
||||||
free(bigBufr);
|
free(bigBufr);
|
||||||
close(s);
|
close(s);
|
||||||
@@ -438,66 +423,60 @@ FTPD_CommandStore(char *filename)
|
|||||||
memcpy(&bigBufr[size], bufr, n);
|
memcpy(&bigBufr[size], bufr, n);
|
||||||
size += n;
|
size += n;
|
||||||
}
|
}
|
||||||
}
|
close(s);
|
||||||
free(bufr);
|
|
||||||
close(s);
|
|
||||||
|
|
||||||
|
/***********************************************************************
|
||||||
/***********************************************************************
|
* Call our hook.
|
||||||
* Figure out what to do with the data we just received.
|
**********************************************************************/
|
||||||
**********************************************************************/
|
if ((usehook->hook_function)(bigBufr, size) == 0)
|
||||||
if (!strncmp("untar", filename, 5))
|
|
||||||
{
|
|
||||||
Untar_FromMemory(bigBufr, size);
|
|
||||||
FTPD_SendReply(210, "Untar successful.");
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
FILE *fp;
|
|
||||||
size_t len;
|
|
||||||
size_t written;
|
|
||||||
|
|
||||||
fp = fopen(filename, "w");
|
|
||||||
if (fp == NULL)
|
|
||||||
{
|
{
|
||||||
FTPD_SendReply(440, "Could not open file.");
|
rtems_ftpd_send_reply(210, "File transferred successfully.");
|
||||||
free(bigBufr);
|
|
||||||
return(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
n = 0;
|
|
||||||
written = 0;
|
|
||||||
while (n<size)
|
|
||||||
{
|
|
||||||
len = ((size-n>BUFSIZ)?(BUFSIZ):(size-n));
|
|
||||||
written = fwrite(&bigBufr[n], 1, len, fp);
|
|
||||||
n += written;
|
|
||||||
if (written != len)
|
|
||||||
{
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
fclose(fp);
|
|
||||||
|
|
||||||
if (n == size)
|
|
||||||
{
|
|
||||||
FTPD_SendReply(226, "Transfer complete.");
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
FTPD_SendReply(440, "Error during write.");
|
rtems_ftpd_send_reply(440, "File transfer failed.");
|
||||||
free(bigBufr);
|
}
|
||||||
|
free(bigBufr);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
int fd;
|
||||||
|
size_t written;
|
||||||
|
|
||||||
|
fd = creat(filename, S_IRUSR | S_IWUSR |
|
||||||
|
S_IRGRP | S_IWGRP |
|
||||||
|
S_IROTH | S_IWOTH);
|
||||||
|
if (fd == -1)
|
||||||
|
{
|
||||||
|
rtems_ftpd_send_reply(450, "Could not open file.");
|
||||||
|
close(s);
|
||||||
|
free(bufr);
|
||||||
return(1);
|
return(1);
|
||||||
}
|
}
|
||||||
|
while ((n = read(s, bufr, BUFSIZ)) > 0)
|
||||||
|
{
|
||||||
|
written = write(fd, bufr, n);
|
||||||
|
if (written == -1)
|
||||||
|
{
|
||||||
|
rtems_ftpd_send_reply(450, "Error during write.");
|
||||||
|
close(fd);
|
||||||
|
close(s);
|
||||||
|
free(bufr);
|
||||||
|
return(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
close(fd);
|
||||||
|
close(s);
|
||||||
|
rtems_ftpd_send_reply(226, "Transfer complete.");
|
||||||
}
|
}
|
||||||
|
|
||||||
free(bigBufr);
|
free(bufr);
|
||||||
return(0);
|
return(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**************************************************************************
|
/**************************************************************************
|
||||||
* Function: FTPD_CommandList *
|
* Function: rtems_ftpd_command_list *
|
||||||
**************************************************************************
|
**************************************************************************
|
||||||
* Description: *
|
* Description: *
|
||||||
* *
|
* *
|
||||||
@@ -518,7 +497,7 @@ FTPD_CommandStore(char *filename)
|
|||||||
* 12/01/97 - Creation (JWJ) *
|
* 12/01/97 - Creation (JWJ) *
|
||||||
*************************************************************************/
|
*************************************************************************/
|
||||||
static void
|
static void
|
||||||
FTPD_CommandList(char *fname)
|
rtems_ftpd_command_list(char *fname)
|
||||||
{
|
{
|
||||||
int s;
|
int s;
|
||||||
rtems_status_code sc;
|
rtems_status_code sc;
|
||||||
@@ -532,7 +511,7 @@ FTPD_CommandList(char *fname)
|
|||||||
sc = rtems_task_get_note(RTEMS_SELF, RTEMS_NOTEPAD_0,
|
sc = rtems_task_get_note(RTEMS_SELF, RTEMS_NOTEPAD_0,
|
||||||
(rtems_unsigned32 *)&info);
|
(rtems_unsigned32 *)&info);
|
||||||
|
|
||||||
FTPD_SendReply(150, "ASCII data connection for LIST.");
|
rtems_ftpd_send_reply(150, "ASCII data connection for LIST.");
|
||||||
|
|
||||||
s = socket(AF_INET, SOCK_STREAM, 0);
|
s = socket(AF_INET, SOCK_STREAM, 0);
|
||||||
if (connect(s, (struct sockaddr *)&info->data_addr,
|
if (connect(s, (struct sockaddr *)&info->data_addr,
|
||||||
@@ -548,7 +527,7 @@ FTPD_CommandList(char *fname)
|
|||||||
fname, (info->xfer_mode==TYPE_A)?("\r"):(""));
|
fname, (info->xfer_mode==TYPE_A)?("\r"):(""));
|
||||||
send(s, dirline, strlen(dirline), 0);
|
send(s, dirline, strlen(dirline), 0);
|
||||||
close(s);
|
close(s);
|
||||||
FTPD_SendReply(226, "Transfer complete.");
|
rtems_ftpd_send_reply(226, "Transfer complete.");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
while ((dp = readdir(dirp)) != NULL)
|
while ((dp = readdir(dirp)) != NULL)
|
||||||
@@ -578,7 +557,7 @@ FTPD_CommandList(char *fname)
|
|||||||
closedir(dirp);
|
closedir(dirp);
|
||||||
|
|
||||||
close(s);
|
close(s);
|
||||||
FTPD_SendReply(226, "Transfer complete.");
|
rtems_ftpd_send_reply(226, "Transfer complete.");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -586,7 +565,7 @@ FTPD_CommandList(char *fname)
|
|||||||
* Cheesy way to change directories
|
* Cheesy way to change directories
|
||||||
*/
|
*/
|
||||||
static void
|
static void
|
||||||
FTPD_CWD(char *dir)
|
rtems_ftpd_CWD(char *dir)
|
||||||
{
|
{
|
||||||
rtems_status_code sc;
|
rtems_status_code sc;
|
||||||
FTPD_SessionInfo_t *info = NULL;
|
FTPD_SessionInfo_t *info = NULL;
|
||||||
@@ -597,17 +576,17 @@ FTPD_CWD(char *dir)
|
|||||||
|
|
||||||
if (chdir(dir) == 0)
|
if (chdir(dir) == 0)
|
||||||
{
|
{
|
||||||
FTPD_SendReply(250, "CWD command successful.");
|
rtems_ftpd_send_reply(250, "CWD command successful.");
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
FTPD_SendReply(550, "CWD command failed.");
|
rtems_ftpd_send_reply(550, "CWD command failed.");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**************************************************************************
|
/**************************************************************************
|
||||||
* Function: FTPD_CommandPort *
|
* Function: rtems_ftpd_command_port *
|
||||||
**************************************************************************
|
**************************************************************************
|
||||||
* Description: *
|
* Description: *
|
||||||
* *
|
* *
|
||||||
@@ -630,7 +609,7 @@ FTPD_CWD(char *dir)
|
|||||||
* 12/01/97 - Creation (JWJ) *
|
* 12/01/97 - Creation (JWJ) *
|
||||||
*************************************************************************/
|
*************************************************************************/
|
||||||
static void
|
static void
|
||||||
FTPD_CommandPort(char *bufr)
|
rtems_ftpd_command_port(char *bufr)
|
||||||
{
|
{
|
||||||
char *ip;
|
char *ip;
|
||||||
char *port;
|
char *port;
|
||||||
@@ -656,13 +635,15 @@ FTPD_CommandPort(char *bufr)
|
|||||||
|
|
||||||
|
|
||||||
/**************************************************************************
|
/**************************************************************************
|
||||||
* Function: FTPD_ParseCommand *
|
* Function: rtems_ftpd_parse_command *
|
||||||
**************************************************************************
|
**************************************************************************
|
||||||
* Description: *
|
* Description: *
|
||||||
* *
|
* *
|
||||||
* Here, we parse the commands that have come through the control *
|
* Here, we parse the commands that have come through the control *
|
||||||
* connection. *
|
* connection. *
|
||||||
* *
|
* *
|
||||||
|
* FIXME: This section is somewhat of a hack. We should have a better *
|
||||||
|
* way to parse commands. *
|
||||||
* *
|
* *
|
||||||
* Inputs: *
|
* Inputs: *
|
||||||
* *
|
* *
|
||||||
@@ -678,7 +659,7 @@ FTPD_CommandPort(char *bufr)
|
|||||||
* 12/01/97 - Creation (JWJ) *
|
* 12/01/97 - Creation (JWJ) *
|
||||||
*************************************************************************/
|
*************************************************************************/
|
||||||
static void
|
static void
|
||||||
FTPD_ParseCommand(char *bufr)
|
rtems_ftpd_parse_command(char *bufr)
|
||||||
{
|
{
|
||||||
char fname[255];
|
char fname[255];
|
||||||
rtems_status_code sc;
|
rtems_status_code sc;
|
||||||
@@ -690,71 +671,71 @@ FTPD_ParseCommand(char *bufr)
|
|||||||
|
|
||||||
if (!strncmp("PORT", bufr, 4))
|
if (!strncmp("PORT", bufr, 4))
|
||||||
{
|
{
|
||||||
FTPD_SendReply(200, "PORT command successful.");
|
rtems_ftpd_send_reply(200, "PORT command successful.");
|
||||||
FTPD_CommandPort(&bufr[5]);
|
rtems_ftpd_command_port(&bufr[5]);
|
||||||
}
|
}
|
||||||
else if (!strncmp("RETR", bufr, 4))
|
else if (!strncmp("RETR", bufr, 4))
|
||||||
{
|
{
|
||||||
sscanf(&bufr[5], "%254s", fname);
|
sscanf(&bufr[5], "%254s", fname);
|
||||||
FTPD_CommandRetrieve(fname);
|
rtems_ftpd_command_retrieve(fname);
|
||||||
}
|
}
|
||||||
else if (!strncmp("STOR", bufr, 4))
|
else if (!strncmp("STOR", bufr, 4))
|
||||||
{
|
{
|
||||||
sscanf(&bufr[5], "%254s", fname);
|
sscanf(&bufr[5], "%254s", fname);
|
||||||
FTPD_CommandStore(fname);
|
rtems_ftpd_command_store(fname);
|
||||||
}
|
}
|
||||||
else if (!strncmp("LIST", bufr, 4))
|
else if (!strncmp("LIST", bufr, 4))
|
||||||
{
|
{
|
||||||
if (bufr[5] == '\n')
|
if (bufr[5] == '\n')
|
||||||
{
|
{
|
||||||
FTPD_CommandList(".");
|
rtems_ftpd_command_list(".");
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
sscanf(&bufr[5], "%254s", fname);
|
sscanf(&bufr[5], "%254s", fname);
|
||||||
FTPD_CommandList(fname);
|
rtems_ftpd_command_list(fname);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (!strncmp("USER", bufr, 4))
|
else if (!strncmp("USER", bufr, 4))
|
||||||
{
|
{
|
||||||
FTPD_SendReply(230, "User logged in.");
|
rtems_ftpd_send_reply(230, "User logged in.");
|
||||||
}
|
}
|
||||||
else if (!strncmp("SYST", bufr, 4))
|
else if (!strncmp("SYST", bufr, 4))
|
||||||
{
|
{
|
||||||
FTPD_SendReply(240, "RTEMS");
|
rtems_ftpd_send_reply(240, "RTEMS");
|
||||||
}
|
}
|
||||||
else if (!strncmp("TYPE", bufr, 4))
|
else if (!strncmp("TYPE", bufr, 4))
|
||||||
{
|
{
|
||||||
if (bufr[5] == 'I')
|
if (bufr[5] == 'I')
|
||||||
{
|
{
|
||||||
info->xfer_mode = TYPE_I;
|
info->xfer_mode = TYPE_I;
|
||||||
FTPD_SendReply(200, "Type set to I.");
|
rtems_ftpd_send_reply(200, "Type set to I.");
|
||||||
}
|
}
|
||||||
else if (bufr[5] == 'A')
|
else if (bufr[5] == 'A')
|
||||||
{
|
{
|
||||||
info->xfer_mode = TYPE_A;
|
info->xfer_mode = TYPE_A;
|
||||||
FTPD_SendReply(200, "Type set to A.");
|
rtems_ftpd_send_reply(200, "Type set to A.");
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
info->xfer_mode = TYPE_I;
|
info->xfer_mode = TYPE_I;
|
||||||
FTPD_SendReply(504, "Type not implemented. Set to I.");
|
rtems_ftpd_send_reply(504, "Type not implemented. Set to I.");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (!strncmp("PASS", bufr, 4))
|
else if (!strncmp("PASS", bufr, 4))
|
||||||
{
|
{
|
||||||
FTPD_SendReply(230, "User logged in.");
|
rtems_ftpd_send_reply(230, "User logged in.");
|
||||||
}
|
}
|
||||||
else if (!strncmp("DELE", bufr, 4))
|
else if (!strncmp("DELE", bufr, 4))
|
||||||
{
|
{
|
||||||
sscanf(&bufr[4], "%254s", fname);
|
sscanf(&bufr[4], "%254s", fname);
|
||||||
if (unlink(fname) == 0)
|
if (unlink(fname) == 0)
|
||||||
{
|
{
|
||||||
FTPD_SendReply(257, "DELE successful.");
|
rtems_ftpd_send_reply(257, "DELE successful.");
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
FTPD_SendReply(550, "DELE failed.");
|
rtems_ftpd_send_reply(550, "DELE failed.");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (!strncmp("SITE CHMOD", bufr, 10))
|
else if (!strncmp("SITE CHMOD", bufr, 10))
|
||||||
@@ -764,11 +745,11 @@ FTPD_ParseCommand(char *bufr)
|
|||||||
sscanf(&bufr[11], "%o %254s", &mask, fname);
|
sscanf(&bufr[11], "%o %254s", &mask, fname);
|
||||||
if (chmod(fname, (mode_t)mask) == 0)
|
if (chmod(fname, (mode_t)mask) == 0)
|
||||||
{
|
{
|
||||||
FTPD_SendReply(257, "CHMOD successful.");
|
rtems_ftpd_send_reply(257, "CHMOD successful.");
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
FTPD_SendReply(550, "CHMOD failed.");
|
rtems_ftpd_send_reply(550, "CHMOD failed.");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (!strncmp("RMD", bufr, 3))
|
else if (!strncmp("RMD", bufr, 3))
|
||||||
@@ -776,11 +757,11 @@ FTPD_ParseCommand(char *bufr)
|
|||||||
sscanf(&bufr[4], "%254s", fname);
|
sscanf(&bufr[4], "%254s", fname);
|
||||||
if (rmdir(fname) == 0)
|
if (rmdir(fname) == 0)
|
||||||
{
|
{
|
||||||
FTPD_SendReply(257, "RMD successful.");
|
rtems_ftpd_send_reply(257, "RMD successful.");
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
FTPD_SendReply(550, "RMD failed.");
|
rtems_ftpd_send_reply(550, "RMD failed.");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (!strncmp("MKD", bufr, 3))
|
else if (!strncmp("MKD", bufr, 3))
|
||||||
@@ -788,33 +769,34 @@ FTPD_ParseCommand(char *bufr)
|
|||||||
sscanf(&bufr[4], "%254s", fname);
|
sscanf(&bufr[4], "%254s", fname);
|
||||||
if (mkdir(fname, S_IRWXU | S_IRWXG | S_IRWXO) == 0)
|
if (mkdir(fname, S_IRWXU | S_IRWXG | S_IRWXO) == 0)
|
||||||
{
|
{
|
||||||
FTPD_SendReply(257, "MKD successful.");
|
rtems_ftpd_send_reply(257, "MKD successful.");
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
FTPD_SendReply(550, "MKD failed.");
|
rtems_ftpd_send_reply(550, "MKD failed.");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (!strncmp("CWD", bufr, 3))
|
else if (!strncmp("CWD", bufr, 3))
|
||||||
{
|
{
|
||||||
sscanf(&bufr[4], "%254s", fname);
|
sscanf(&bufr[4], "%254s", fname);
|
||||||
FTPD_CWD(fname);
|
rtems_ftpd_CWD(fname);
|
||||||
}
|
}
|
||||||
else if (!strncmp("PWD", bufr, 3))
|
else if (!strncmp("PWD", bufr, 3))
|
||||||
{
|
{
|
||||||
char *cwd = getcwd(0, 0);
|
char *cwd = getcwd(0, 0);
|
||||||
sprintf(bufr, "\"%s\" is the current directory.", cwd);
|
sprintf(bufr, "\"%s\" is the current directory.", cwd);
|
||||||
FTPD_SendReply(250, bufr);
|
rtems_ftpd_send_reply(250, bufr);
|
||||||
free(cwd);
|
free(cwd);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
FTPD_SendReply(500, "Unrecognized/unsupported command.");
|
rtems_ftpd_send_reply(500, "Unrecognized/unsupported command.");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**************************************************************************
|
/**************************************************************************
|
||||||
* Function: FTPD_Session *
|
* Function: rtems_ftpd_session *
|
||||||
**************************************************************************
|
**************************************************************************
|
||||||
* Description: *
|
* Description: *
|
||||||
* *
|
* *
|
||||||
@@ -827,7 +809,7 @@ FTPD_ParseCommand(char *bufr)
|
|||||||
* *
|
* *
|
||||||
* Inputs: *
|
* Inputs: *
|
||||||
* *
|
* *
|
||||||
* rtems_task_argument arg - The FTPD_Daemon task passes the socket *
|
* rtems_task_argument arg - The daemon task passes the socket *
|
||||||
* which serves as the control connection. *
|
* which serves as the control connection. *
|
||||||
* *
|
* *
|
||||||
* Output: *
|
* Output: *
|
||||||
@@ -839,7 +821,7 @@ FTPD_ParseCommand(char *bufr)
|
|||||||
* 12/01/97 - Creation (JWJ) *
|
* 12/01/97 - Creation (JWJ) *
|
||||||
*************************************************************************/
|
*************************************************************************/
|
||||||
static void
|
static void
|
||||||
FTPD_Session(rtems_task_argument arg)
|
rtems_ftpd_session(rtems_task_argument arg)
|
||||||
{
|
{
|
||||||
char cmd[256];
|
char cmd[256];
|
||||||
rtems_status_code sc;
|
rtems_status_code sc;
|
||||||
@@ -849,7 +831,7 @@ FTPD_Session(rtems_task_argument arg)
|
|||||||
sc = rtems_task_get_note(RTEMS_SELF, RTEMS_NOTEPAD_0,
|
sc = rtems_task_get_note(RTEMS_SELF, RTEMS_NOTEPAD_0,
|
||||||
(rtems_unsigned32 *)&info);
|
(rtems_unsigned32 *)&info);
|
||||||
|
|
||||||
FTPD_SendReply(220, "Erithacus FTP server (Version 1.0) ready.");
|
rtems_ftpd_send_reply(220, FTPD_SERVER_MESSAGE);
|
||||||
|
|
||||||
/***********************************************************************
|
/***********************************************************************
|
||||||
* Set initial directory to "/".
|
* Set initial directory to "/".
|
||||||
@@ -858,7 +840,7 @@ FTPD_Session(rtems_task_argument arg)
|
|||||||
info->xfer_mode = TYPE_A;
|
info->xfer_mode = TYPE_A;
|
||||||
while (1)
|
while (1)
|
||||||
{
|
{
|
||||||
if (recv(info->ctrl_sock, cmd, 256, 0) == -1)
|
if (fgets(cmd, 256, info->ctrl_fp) == NULL)
|
||||||
{
|
{
|
||||||
syslog(LOG_INFO, "ftpd: Connection aborted.");
|
syslog(LOG_INFO, "ftpd: Connection aborted.");
|
||||||
break;
|
break;
|
||||||
@@ -866,16 +848,16 @@ FTPD_Session(rtems_task_argument arg)
|
|||||||
|
|
||||||
if (!strncmp("QUIT", cmd, 4))
|
if (!strncmp("QUIT", cmd, 4))
|
||||||
{
|
{
|
||||||
FTPD_SendReply(221, "Goodbye.");
|
rtems_ftpd_send_reply(221, "Goodbye.");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
FTPD_ParseCommand(cmd);
|
rtems_ftpd_parse_command(cmd);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (close(info->ctrl_sock) < 0)
|
if (fclose(info->ctrl_fp) != 0)
|
||||||
{
|
{
|
||||||
syslog(LOG_ERR, "ftpd: Could not close session.");
|
syslog(LOG_ERR, "ftpd: Could not close session.");
|
||||||
}
|
}
|
||||||
@@ -895,7 +877,7 @@ FTPD_Session(rtems_task_argument arg)
|
|||||||
|
|
||||||
|
|
||||||
/**************************************************************************
|
/**************************************************************************
|
||||||
* Function: FTPD_Daemon *
|
* Function: rtems_ftpd_daemon *
|
||||||
**************************************************************************
|
**************************************************************************
|
||||||
* Description: *
|
* Description: *
|
||||||
* *
|
* *
|
||||||
@@ -918,7 +900,7 @@ FTPD_Session(rtems_task_argument arg)
|
|||||||
* 12/01/97 - Creation (JWJ) *
|
* 12/01/97 - Creation (JWJ) *
|
||||||
*************************************************************************/
|
*************************************************************************/
|
||||||
static void
|
static void
|
||||||
FTPD_Daemon()
|
rtems_ftpd_daemon()
|
||||||
{
|
{
|
||||||
int s;
|
int s;
|
||||||
int s1;
|
int s1;
|
||||||
@@ -941,7 +923,7 @@ FTPD_Daemon()
|
|||||||
}
|
}
|
||||||
|
|
||||||
localAddr.sin_family = AF_INET;
|
localAddr.sin_family = AF_INET;
|
||||||
localAddr.sin_port = FTPD_CONTROL_PORT;
|
localAddr.sin_port = htons(rtems_ftpd_configuration.port);
|
||||||
localAddr.sin_addr.s_addr = INADDR_ANY;
|
localAddr.sin_addr.s_addr = INADDR_ANY;
|
||||||
memset(localAddr.sin_zero, '\0', sizeof(localAddr.sin_zero));
|
memset(localAddr.sin_zero, '\0', sizeof(localAddr.sin_zero));
|
||||||
if (bind(s, (struct sockaddr *)&localAddr,
|
if (bind(s, (struct sockaddr *)&localAddr,
|
||||||
@@ -1002,21 +984,28 @@ FTPD_Daemon()
|
|||||||
/********************************************************************
|
/********************************************************************
|
||||||
* Send the socket on to the new session.
|
* Send the socket on to the new session.
|
||||||
*******************************************************************/
|
*******************************************************************/
|
||||||
info->ctrl_sock = s1;
|
if ((info->ctrl_fp = fdopen(s1, "r+")) == NULL)
|
||||||
sc = rtems_task_set_note(tid, RTEMS_NOTEPAD_0,
|
|
||||||
(rtems_unsigned32)info);
|
|
||||||
sc = rtems_task_start(tid, FTPD_Session, 0);
|
|
||||||
if (sc != RTEMS_SUCCESSFUL)
|
|
||||||
{
|
{
|
||||||
syslog(LOG_ERR, "ftpd: Could not start FTPD session: %s",
|
syslog(LOG_ERR, "ftpd: fdopen() on socket failed.");
|
||||||
rtems_status_text(sc));
|
close(s1);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
sc = rtems_task_set_note(tid, RTEMS_NOTEPAD_0,
|
||||||
|
(rtems_unsigned32)info);
|
||||||
|
sc = rtems_task_start(tid, rtems_ftpd_session, 0);
|
||||||
|
if (sc != RTEMS_SUCCESSFUL)
|
||||||
|
{
|
||||||
|
syslog(LOG_ERR, "ftpd: Could not start FTPD session: %s",
|
||||||
|
rtems_status_text(sc));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**************************************************************************
|
/**************************************************************************
|
||||||
* Function: FTPD_Start *
|
* Function: rtems_ftpd_start *
|
||||||
**************************************************************************
|
**************************************************************************
|
||||||
* Description: *
|
* Description: *
|
||||||
* *
|
* *
|
||||||
@@ -1031,21 +1020,33 @@ FTPD_Daemon()
|
|||||||
* *
|
* *
|
||||||
* Output: *
|
* Output: *
|
||||||
* *
|
* *
|
||||||
* none *
|
* int - RTEMS_SUCCESSFUL on successful start of the daemon. *
|
||||||
* *
|
* *
|
||||||
**************************************************************************
|
**************************************************************************
|
||||||
* Change History: *
|
* Change History: *
|
||||||
* 12/01/97 - Creation (JWJ) *
|
* 12/01/97 - Creation (JWJ) *
|
||||||
*************************************************************************/
|
*************************************************************************/
|
||||||
void
|
int
|
||||||
FTPD_Start(rtems_task_priority priority)
|
rtems_initialize_ftpd()
|
||||||
{
|
{
|
||||||
rtems_status_code sc;
|
rtems_status_code sc;
|
||||||
rtems_id tid;
|
rtems_id tid;
|
||||||
|
|
||||||
|
|
||||||
|
if (rtems_ftpd_configuration.port == 0)
|
||||||
|
{
|
||||||
|
rtems_ftpd_configuration.port = FTPD_CONTROL_PORT;
|
||||||
|
}
|
||||||
|
|
||||||
|
/***********************************************************************
|
||||||
|
* Default FTPD priority.
|
||||||
|
**********************************************************************/
|
||||||
|
if (rtems_ftpd_configuration.priority == 0)
|
||||||
|
{
|
||||||
|
rtems_ftpd_configuration.priority = 40;
|
||||||
|
}
|
||||||
sc = rtems_task_create(rtems_build_name('F', 'T', 'P', 'D'),
|
sc = rtems_task_create(rtems_build_name('F', 'T', 'P', 'D'),
|
||||||
priority, 8*1024,
|
rtems_ftpd_configuration.priority, 8*1024,
|
||||||
RTEMS_PREEMPT | RTEMS_NO_TIMESLICE | RTEMS_NO_ASR |
|
RTEMS_PREEMPT | RTEMS_NO_TIMESLICE | RTEMS_NO_ASR |
|
||||||
RTEMS_INTERRUPT_LEVEL(0),
|
RTEMS_INTERRUPT_LEVEL(0),
|
||||||
RTEMS_NO_FLOATING_POINT | RTEMS_LOCAL,
|
RTEMS_NO_FLOATING_POINT | RTEMS_LOCAL,
|
||||||
@@ -1054,14 +1055,18 @@ FTPD_Start(rtems_task_priority priority)
|
|||||||
{
|
{
|
||||||
syslog(LOG_ERR, "ftpd: Could not create FTP daemon: %s",
|
syslog(LOG_ERR, "ftpd: Could not create FTP daemon: %s",
|
||||||
rtems_status_text(sc));
|
rtems_status_text(sc));
|
||||||
|
return(RTEMS_UNSATISFIED);
|
||||||
}
|
}
|
||||||
|
|
||||||
sc = rtems_task_start(tid, FTPD_Daemon, 0);
|
sc = rtems_task_start(tid, rtems_ftpd_daemon, 0);
|
||||||
if (sc != RTEMS_SUCCESSFUL)
|
if (sc != RTEMS_SUCCESSFUL)
|
||||||
{
|
{
|
||||||
syslog(LOG_ERR, "ftpd: Could not start FTP daemon: %s",
|
syslog(LOG_ERR, "ftpd: Could not start FTP daemon: %s",
|
||||||
rtems_status_text(sc));
|
rtems_status_text(sc));
|
||||||
|
return(RTEMS_UNSATISFIED);
|
||||||
}
|
}
|
||||||
|
|
||||||
syslog(LOG_INFO, "ftpd: FTP daemon started.");
|
syslog(LOG_INFO, "ftpd: FTP daemon started.");
|
||||||
|
return(RTEMS_SUCCESSFUL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -10,17 +10,33 @@
|
|||||||
|
|
||||||
#define FTPD_CONTROL_PORT 21
|
#define FTPD_CONTROL_PORT 21
|
||||||
|
|
||||||
|
typedef int (*rtems_ftpd_hookfunction)(unsigned char *, unsigned long);
|
||||||
|
|
||||||
|
struct rtems_ftpd_hook
|
||||||
|
{
|
||||||
|
char *filename;
|
||||||
|
rtems_ftpd_hookfunction hook_function;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct rtems_ftpd_configuration
|
||||||
|
{
|
||||||
|
rtems_task_priority priority; /* FTPD task priority */
|
||||||
|
unsigned long max_hook_filesize; /* Maximum buffersize */
|
||||||
|
/* for hooks */
|
||||||
|
int port; /* Well-known port */
|
||||||
|
struct rtems_ftpd_hook *hooks; /* List of hooks */
|
||||||
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Reply codes.
|
* Reply codes.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#define PRELIM 1 /* positive preliminary */
|
#define PRELIM 1 /* positive preliminary */
|
||||||
#define COMPLETE 2 /* positive completion */
|
#define COMPLETE 2 /* positive completion */
|
||||||
#define CONTINUE 3 /* positive intermediate */
|
#define CONTINUE 3 /* positive intermediate */
|
||||||
#define TRANSIENT 4 /* transient negative completion */
|
#define TRANSIENT 4 /* transient negative completion */
|
||||||
#define ERROR 5 /* permanent negative completion */
|
#define ERROR 5 /* permanent negative completion */
|
||||||
|
|
||||||
void rtems_ftpd_sTart(rtems_task_priority priority);
|
int rtems_initialize_ftpd();
|
||||||
|
|
||||||
#endif /* __FTPD_H__ */
|
#endif /* __FTPD_H__ */
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,8 @@
|
|||||||
/*
|
/* FIXME: 1. Parse command is a hack. We can do better.
|
||||||
|
* 2. chdir is a hack. We can do better.
|
||||||
|
* 3. PWD doesn't work.
|
||||||
|
* 4. Some sort of access control?
|
||||||
|
*
|
||||||
* FTP Server Daemon
|
* FTP Server Daemon
|
||||||
*
|
*
|
||||||
* Submitted by: Jake Janovetz <janovetz@tempest.ece.uiuc.edu>
|
* Submitted by: Jake Janovetz <janovetz@tempest.ece.uiuc.edu>
|
||||||
@@ -6,34 +10,17 @@
|
|||||||
* $Id$
|
* $Id$
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/*
|
|
||||||
* Current state:
|
|
||||||
* To untar, put as "untar"
|
|
||||||
* CWD uses chdir
|
|
||||||
* This is bad due to global setting of chdir.
|
|
||||||
*
|
|
||||||
* Stored files come into RAM and are saved later. This is an artifact
|
|
||||||
* of a previous implementation (no filesystem -- had to do stuff with
|
|
||||||
* the "files" later). This can be eliminated once all of Jake's stuff
|
|
||||||
* is moved to devices/filesystems.
|
|
||||||
*
|
|
||||||
* CLOSE(S) doesn't seem to work. This causes problems in
|
|
||||||
* several areas. It lets too many file descriptors pile up
|
|
||||||
* and it doesn't seem to flush the stream.
|
|
||||||
*
|
|
||||||
* Is 'recv' what I want to use to get commands from the control port?
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
/**************************************************************************
|
/**************************************************************************
|
||||||
* ftpd.c *
|
* ftpd.c *
|
||||||
**************************************************************************
|
**************************************************************************
|
||||||
* Description: *
|
* Description: *
|
||||||
* *
|
* *
|
||||||
* This file contains the daemon which services requests that appear *
|
* This file contains the daemon which services requests that appear *
|
||||||
* on the 'FTP' port. This server is compatible with FTP, but it *
|
* on the FTP port. This server is compatible with FTP, but it *
|
||||||
* also provides services specific to the Erithacus system. *
|
* also provides 'hooks' to make it usable in situations where files *
|
||||||
* This server is started at boot-time and runs forever. *
|
* are not used/necessary. Once the server is started, it runs *
|
||||||
|
* forever. *
|
||||||
|
* *
|
||||||
* *
|
* *
|
||||||
* Organization: *
|
* Organization: *
|
||||||
* *
|
* *
|
||||||
@@ -44,12 +31,6 @@
|
|||||||
* is complete, the session task deletes itself. The daemon still *
|
* is complete, the session task deletes itself. The daemon still *
|
||||||
* runs, however. *
|
* runs, however. *
|
||||||
* *
|
* *
|
||||||
* Implementation Notes: *
|
|
||||||
* *
|
|
||||||
* The 'current working directory' implementation utilizes the *
|
|
||||||
* RTEMS filesystem cwd. This is no good since other processes *
|
|
||||||
* inherit the same cwd. *
|
|
||||||
* *
|
|
||||||
* *
|
* *
|
||||||
* Supported commands are: *
|
* Supported commands are: *
|
||||||
* *
|
* *
|
||||||
@@ -70,51 +51,34 @@
|
|||||||
* and port (x*256 + y). *
|
* and port (x*256 + y). *
|
||||||
* *
|
* *
|
||||||
* *
|
* *
|
||||||
* *
|
|
||||||
* The public routines contained in this file are: *
|
* The public routines contained in this file are: *
|
||||||
* *
|
* *
|
||||||
* FTPD_Start - Starts the server daemon, then returns to its caller. *
|
* rtems_initialize_ftpd_start - Starts the server daemon, then *
|
||||||
|
* returns to its caller. *
|
||||||
* *
|
* *
|
||||||
* *
|
* *
|
||||||
* The private routines contained in this file are: *
|
* The private routines contained in this file are: *
|
||||||
* *
|
* *
|
||||||
* FTPD_SendReply - Sends a reply code and text through the control *
|
* rtems_ftpd_send_reply - Sends a reply code and text through the *
|
||||||
* port. *
|
* control port. *
|
||||||
* FTPD_CommandStore - Performs the "STOR" command. *
|
* rtems_ftpd_command_retrieve - Performs to "RETR" command. *
|
||||||
* FTPD_CommandList - Performs the "LIST" command. *
|
* rtems_ftpd_command_store - Performs the "STOR" command. *
|
||||||
* FTPD_CommandPort - Opens a data port (the "PORT" command). *
|
* rtems_ftpd_command_list - Performs the "LIST" command. *
|
||||||
* FTPD_ParseCommand - Parses an incoming command. *
|
* rtems_ftpd_command_port - Opens a data port (the "PORT" command). *
|
||||||
* FTPD_Session - Begins a service session. *
|
* rtems_ftpd_parse_command - Parses an incoming command. *
|
||||||
* FTPD_Daemon - Listens on the FTP port for service requests. *
|
* rtmes_ftpd_session - Begins a service session. *
|
||||||
* *
|
* rtems_ftpd_daemon - Listens on the FTP port for service *
|
||||||
* *
|
* requests. *
|
||||||
*------------------------------------------------------------------------*
|
*------------------------------------------------------------------------*
|
||||||
* *
|
|
||||||
* Jake Janovetz *
|
* Jake Janovetz *
|
||||||
* University of Illinois *
|
* University of Illinois *
|
||||||
* 1406 West Green Street *
|
* 1406 West Green Street *
|
||||||
* Urbana IL 61801 *
|
* Urbana IL 61801 *
|
||||||
* *
|
|
||||||
**************************************************************************
|
**************************************************************************
|
||||||
* Change History: *
|
* Change History: *
|
||||||
* 12/01/97 - Creation (JWJ) *
|
* 12/01/97 - Creation (JWJ) *
|
||||||
*************************************************************************/
|
*************************************************************************/
|
||||||
|
|
||||||
/* Revision Control Information:
|
|
||||||
*
|
|
||||||
* $Source$
|
|
||||||
* $Id$
|
|
||||||
* $Log$
|
|
||||||
* Revision 1.3 1998/05/19 21:28:17 erithacus
|
|
||||||
* Update control socket to file I/O.
|
|
||||||
*
|
|
||||||
* Revision 1.2 1998/05/19 20:13:50 erithacus
|
|
||||||
* Remodeled to be entirely reentrant.
|
|
||||||
*
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
@@ -133,9 +97,10 @@
|
|||||||
#include <netinet/in.h>
|
#include <netinet/in.h>
|
||||||
|
|
||||||
#include "ftpd.h"
|
#include "ftpd.h"
|
||||||
#include "untar.h"
|
|
||||||
|
|
||||||
|
|
||||||
|
extern struct rtems_ftpd_configuration rtems_ftpd_configuration;
|
||||||
|
|
||||||
/**************************************************************************
|
/**************************************************************************
|
||||||
* Meanings of first and second digits of reply codes:
|
* Meanings of first and second digits of reply codes:
|
||||||
*
|
*
|
||||||
@@ -163,14 +128,6 @@
|
|||||||
*************************************************************************/
|
*************************************************************************/
|
||||||
|
|
||||||
|
|
||||||
/**************************************************************************
|
|
||||||
* Maximum buffer size for use by the transfer protocol.
|
|
||||||
* This will be eliminated when the filesystem is complete enough that
|
|
||||||
* we don't have to store the received data until we have something to
|
|
||||||
* do with it.
|
|
||||||
*************************************************************************/
|
|
||||||
#define FTPD_MAX_RECEIVESIZE (512*1024)
|
|
||||||
|
|
||||||
/**************************************************************************
|
/**************************************************************************
|
||||||
* SessionInfo structure.
|
* SessionInfo structure.
|
||||||
*
|
*
|
||||||
@@ -180,13 +137,14 @@
|
|||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
struct sockaddr_in data_addr; /* Data address for PORT commands */
|
struct sockaddr_in data_addr; /* Data address for PORT commands */
|
||||||
int ctrl_sock; /* Control connection socker */
|
FILE *ctrl_fp; /* File pointer for control connection */
|
||||||
char cwd[255]; /* Current working directory */
|
char cwd[255]; /* Current working directory */
|
||||||
/* Login -- future use -- */
|
/* Login -- future use -- */
|
||||||
int xfer_mode; /* Transfer mode (ASCII/binary) */
|
int xfer_mode; /* Transfer mode (ASCII/binary) */
|
||||||
} FTPD_SessionInfo_t;
|
} FTPD_SessionInfo_t;
|
||||||
|
|
||||||
|
|
||||||
|
#define FTPD_SERVER_MESSAGE "RTEMS FTP server (Version 1.0-JWJ) ready."
|
||||||
#define FTPD_WELCOME_MESSAGE \
|
#define FTPD_WELCOME_MESSAGE \
|
||||||
"Welcome to the RTEMS FTP server.\n" \
|
"Welcome to the RTEMS FTP server.\n" \
|
||||||
"\n" \
|
"\n" \
|
||||||
@@ -194,7 +152,7 @@ typedef struct
|
|||||||
|
|
||||||
|
|
||||||
/**************************************************************************
|
/**************************************************************************
|
||||||
* Function: FTPD_SendReply *
|
* Function: rtems_ftpd_send_reply *
|
||||||
**************************************************************************
|
**************************************************************************
|
||||||
* Description: *
|
* Description: *
|
||||||
* *
|
* *
|
||||||
@@ -216,7 +174,7 @@ typedef struct
|
|||||||
* 12/01/97 - Creation (JWJ) *
|
* 12/01/97 - Creation (JWJ) *
|
||||||
*************************************************************************/
|
*************************************************************************/
|
||||||
static void
|
static void
|
||||||
FTPD_SendReply(int code, char *text)
|
rtems_ftpd_send_reply(int code, char *text)
|
||||||
{
|
{
|
||||||
rtems_status_code sc;
|
rtems_status_code sc;
|
||||||
FTPD_SessionInfo_t *info = NULL;
|
FTPD_SessionInfo_t *info = NULL;
|
||||||
@@ -241,17 +199,19 @@ FTPD_SendReply(int code, char *text)
|
|||||||
if (text != NULL)
|
if (text != NULL)
|
||||||
{
|
{
|
||||||
sprintf(str, "%d %.70s\r\n", code, text);
|
sprintf(str, "%d %.70s\r\n", code, text);
|
||||||
|
fprintf(info->ctrl_fp, "%d %.70s\r\n", code, text);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
sprintf(str, "%d\r\n", code);
|
sprintf(str, "%d\r\n", code);
|
||||||
|
fprintf(info->ctrl_fp, "%d\r\n", code);
|
||||||
}
|
}
|
||||||
send(info->ctrl_sock, str, strlen(str), 0);
|
fflush(info->ctrl_fp);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**************************************************************************
|
/**************************************************************************
|
||||||
* Function: FTPD_CommandRetrieve *
|
* Function: rtems_ftpd_command_retrieve *
|
||||||
**************************************************************************
|
**************************************************************************
|
||||||
* Description: *
|
* Description: *
|
||||||
* *
|
* *
|
||||||
@@ -274,12 +234,11 @@ FTPD_SendReply(int code, char *text)
|
|||||||
* 04/29/98 - Creation (JWJ) *
|
* 04/29/98 - Creation (JWJ) *
|
||||||
*************************************************************************/
|
*************************************************************************/
|
||||||
static int
|
static int
|
||||||
FTPD_CommandRetrieve(char *filename)
|
rtems_ftpd_command_retrieve(char *filename)
|
||||||
{
|
{
|
||||||
int s;
|
int s;
|
||||||
int n;
|
int n;
|
||||||
|
int fd;
|
||||||
FILE *fp;
|
|
||||||
unsigned char *bufr;
|
unsigned char *bufr;
|
||||||
rtems_status_code sc;
|
rtems_status_code sc;
|
||||||
FTPD_SessionInfo_t *info = NULL;
|
FTPD_SessionInfo_t *info = NULL;
|
||||||
@@ -288,32 +247,31 @@ FTPD_CommandRetrieve(char *filename)
|
|||||||
sc = rtems_task_get_note(RTEMS_SELF, RTEMS_NOTEPAD_0,
|
sc = rtems_task_get_note(RTEMS_SELF, RTEMS_NOTEPAD_0,
|
||||||
(rtems_unsigned32 *)&info);
|
(rtems_unsigned32 *)&info);
|
||||||
|
|
||||||
|
if ((fd = open(filename, O_RDONLY)) == -1)
|
||||||
if ((fp = fopen(filename, "r")) == NULL)
|
|
||||||
{
|
{
|
||||||
FTPD_SendReply(450, "Error opening file.");
|
rtems_ftpd_send_reply(450, "Error opening file.");
|
||||||
return(0);
|
return(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
bufr = (unsigned char *)malloc(BUFSIZ);
|
bufr = (unsigned char *)malloc(BUFSIZ);
|
||||||
if (bufr == NULL)
|
if (bufr == NULL)
|
||||||
{
|
{
|
||||||
FTPD_SendReply(440, "Server error - malloc fail.");
|
rtems_ftpd_send_reply(440, "Server error - malloc fail.");
|
||||||
fclose(fp);
|
close(fd);
|
||||||
return(0);
|
return(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
/***********************************************************************
|
/***********************************************************************
|
||||||
* Connect to the data connection (PORT made in an earlier PORT call).
|
* Connect to the data connection (PORT made in an earlier PORT call).
|
||||||
**********************************************************************/
|
**********************************************************************/
|
||||||
FTPD_SendReply(150, "BINARY data connection.");
|
rtems_ftpd_send_reply(150, "BINARY data connection.");
|
||||||
s = socket(AF_INET, SOCK_STREAM, 0);
|
s = socket(AF_INET, SOCK_STREAM, 0);
|
||||||
if (connect(s, (struct sockaddr *)&info->data_addr,
|
if (connect(s, (struct sockaddr *)&info->data_addr,
|
||||||
sizeof(struct sockaddr)) < 0)
|
sizeof(struct sockaddr)) < 0)
|
||||||
{
|
{
|
||||||
FTPD_SendReply(420, "Server error - could not connect socket.");
|
rtems_ftpd_send_reply(420, "Server error - could not connect socket.");
|
||||||
free(bufr);
|
free(bufr);
|
||||||
fclose(fp);
|
close(fd);
|
||||||
close(s);
|
close(s);
|
||||||
return(1);
|
return(1);
|
||||||
}
|
}
|
||||||
@@ -321,18 +279,19 @@ FTPD_CommandRetrieve(char *filename)
|
|||||||
/***********************************************************************
|
/***********************************************************************
|
||||||
* Send the data over the ether.
|
* Send the data over the ether.
|
||||||
**********************************************************************/
|
**********************************************************************/
|
||||||
while ((n = fread(bufr, 1, BUFSIZ, fp)) != 0)
|
while ((n = read(fd, bufr, BUFSIZ)) > 0)
|
||||||
{
|
{
|
||||||
send(s, bufr, n, 0);
|
send(s, bufr, n, 0);
|
||||||
|
bufr[n-1] = '\0';
|
||||||
}
|
}
|
||||||
|
|
||||||
if (feof(fp))
|
if (n == 0)
|
||||||
{
|
{
|
||||||
FTPD_SendReply(210, "File sent successfully.");
|
rtems_ftpd_send_reply(210, "File sent successfully.");
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
FTPD_SendReply(450, "Retrieve failed.");
|
rtems_ftpd_send_reply(450, "Retrieve failed.");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (close(s) != 0)
|
if (close(s) != 0)
|
||||||
@@ -341,13 +300,13 @@ FTPD_CommandRetrieve(char *filename)
|
|||||||
}
|
}
|
||||||
|
|
||||||
free(bufr);
|
free(bufr);
|
||||||
fclose(fp);
|
close(fd);
|
||||||
return(0);
|
return(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**************************************************************************
|
/**************************************************************************
|
||||||
* Function: FTPD_CommandStore *
|
* Function: rtems_ftpd_command_store *
|
||||||
**************************************************************************
|
**************************************************************************
|
||||||
* Description: *
|
* Description: *
|
||||||
* *
|
* *
|
||||||
@@ -370,15 +329,15 @@ FTPD_CommandRetrieve(char *filename)
|
|||||||
* 12/01/97 - Creation (JWJ) *
|
* 12/01/97 - Creation (JWJ) *
|
||||||
*************************************************************************/
|
*************************************************************************/
|
||||||
static int
|
static int
|
||||||
FTPD_CommandStore(char *filename)
|
rtems_ftpd_command_store(char *filename)
|
||||||
{
|
{
|
||||||
char *bufr;
|
char *bufr;
|
||||||
char *bigBufr;
|
int s;
|
||||||
int s;
|
int n;
|
||||||
int n;
|
unsigned long size = 0;
|
||||||
unsigned long size = 0;
|
rtems_status_code sc;
|
||||||
rtems_status_code sc;
|
FTPD_SessionInfo_t *info = NULL;
|
||||||
FTPD_SessionInfo_t *info = NULL;
|
struct rtems_ftpd_hook *usehook = NULL;
|
||||||
|
|
||||||
|
|
||||||
sc = rtems_task_get_note(RTEMS_SELF, RTEMS_NOTEPAD_0,
|
sc = rtems_task_get_note(RTEMS_SELF, RTEMS_NOTEPAD_0,
|
||||||
@@ -387,26 +346,17 @@ FTPD_CommandStore(char *filename)
|
|||||||
bufr = (char *)malloc(BUFSIZ * sizeof(char));
|
bufr = (char *)malloc(BUFSIZ * sizeof(char));
|
||||||
if (bufr == NULL)
|
if (bufr == NULL)
|
||||||
{
|
{
|
||||||
FTPD_SendReply(440, "Server error - malloc fail.");
|
rtems_ftpd_send_reply(440, "Server error - malloc fail.");
|
||||||
return(1);
|
return(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
bigBufr = (char *)malloc(FTPD_MAX_RECEIVESIZE * sizeof(char));
|
rtems_ftpd_send_reply(150, "BINARY data connection.");
|
||||||
if (bigBufr == NULL)
|
|
||||||
{
|
|
||||||
FTPD_SendReply(440, "Server error - malloc fail.");
|
|
||||||
free(bufr);
|
|
||||||
return(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
FTPD_SendReply(150, "BINARY data connection.");
|
|
||||||
|
|
||||||
s = socket(AF_INET, SOCK_STREAM, 0);
|
s = socket(AF_INET, SOCK_STREAM, 0);
|
||||||
if (connect(s, (struct sockaddr *)&info->data_addr,
|
if (connect(s, (struct sockaddr *)&info->data_addr,
|
||||||
sizeof(struct sockaddr)) < 0)
|
sizeof(struct sockaddr)) < 0)
|
||||||
{
|
{
|
||||||
free(bufr);
|
free(bufr);
|
||||||
free(bigBufr);
|
|
||||||
close(s);
|
close(s);
|
||||||
return(1);
|
return(1);
|
||||||
}
|
}
|
||||||
@@ -414,22 +364,57 @@ FTPD_CommandStore(char *filename)
|
|||||||
|
|
||||||
/***********************************************************************
|
/***********************************************************************
|
||||||
* File: "/dev/null" just throws the data away.
|
* File: "/dev/null" just throws the data away.
|
||||||
|
* Otherwise, search our list of hooks to see if we need to do something
|
||||||
|
* special.
|
||||||
**********************************************************************/
|
**********************************************************************/
|
||||||
if (!strncmp("/dev/null", filename, 9))
|
if (!strncmp("/dev/null", filename, 9))
|
||||||
{
|
{
|
||||||
while ((n = read(s, bufr, BUFSIZ)) > 0);
|
while ((n = read(s, bufr, BUFSIZ)) > 0);
|
||||||
}
|
}
|
||||||
else
|
else if (rtems_ftpd_configuration.hooks != NULL)
|
||||||
{
|
{
|
||||||
|
struct rtems_ftpd_hook *hook;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
i = 0;
|
||||||
|
hook = &rtems_ftpd_configuration.hooks[i++];
|
||||||
|
while (hook->filename != NULL)
|
||||||
|
{
|
||||||
|
if (!strcmp(hook->filename, filename))
|
||||||
|
{
|
||||||
|
usehook = hook;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
hook = &rtems_ftpd_configuration.hooks[i++];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (usehook != NULL)
|
||||||
|
{
|
||||||
|
char *bigBufr;
|
||||||
|
|
||||||
|
/***********************************************************************
|
||||||
|
* Allocate space for our "file".
|
||||||
|
**********************************************************************/
|
||||||
|
bigBufr = (char *)malloc(
|
||||||
|
rtems_ftpd_configuration.max_hook_filesize * sizeof(char));
|
||||||
|
if (bigBufr == NULL)
|
||||||
|
{
|
||||||
|
rtems_ftpd_send_reply(440, "Server error - malloc fail.");
|
||||||
|
free(bufr);
|
||||||
|
return(1);
|
||||||
|
}
|
||||||
|
|
||||||
/***********************************************************************
|
/***********************************************************************
|
||||||
* Retrieve the file into our buffer space.
|
* Retrieve the file into our buffer space.
|
||||||
**********************************************************************/
|
**********************************************************************/
|
||||||
size = 0;
|
size = 0;
|
||||||
while ((n = read(s, bufr, BUFSIZ)) > 0)
|
while ((n = read(s, bufr, BUFSIZ)) > 0)
|
||||||
{
|
{
|
||||||
if (size + n > FTPD_MAX_RECEIVESIZE)
|
if (size + n >
|
||||||
|
rtems_ftpd_configuration.max_hook_filesize * sizeof(char))
|
||||||
{
|
{
|
||||||
FTPD_SendReply(440, "Server error - Buffer size exceeded.");
|
rtems_ftpd_send_reply(440, "Server error - Buffer size exceeded.");
|
||||||
free(bufr);
|
free(bufr);
|
||||||
free(bigBufr);
|
free(bigBufr);
|
||||||
close(s);
|
close(s);
|
||||||
@@ -438,66 +423,60 @@ FTPD_CommandStore(char *filename)
|
|||||||
memcpy(&bigBufr[size], bufr, n);
|
memcpy(&bigBufr[size], bufr, n);
|
||||||
size += n;
|
size += n;
|
||||||
}
|
}
|
||||||
}
|
close(s);
|
||||||
free(bufr);
|
|
||||||
close(s);
|
|
||||||
|
|
||||||
|
/***********************************************************************
|
||||||
/***********************************************************************
|
* Call our hook.
|
||||||
* Figure out what to do with the data we just received.
|
**********************************************************************/
|
||||||
**********************************************************************/
|
if ((usehook->hook_function)(bigBufr, size) == 0)
|
||||||
if (!strncmp("untar", filename, 5))
|
|
||||||
{
|
|
||||||
Untar_FromMemory(bigBufr, size);
|
|
||||||
FTPD_SendReply(210, "Untar successful.");
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
FILE *fp;
|
|
||||||
size_t len;
|
|
||||||
size_t written;
|
|
||||||
|
|
||||||
fp = fopen(filename, "w");
|
|
||||||
if (fp == NULL)
|
|
||||||
{
|
{
|
||||||
FTPD_SendReply(440, "Could not open file.");
|
rtems_ftpd_send_reply(210, "File transferred successfully.");
|
||||||
free(bigBufr);
|
|
||||||
return(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
n = 0;
|
|
||||||
written = 0;
|
|
||||||
while (n<size)
|
|
||||||
{
|
|
||||||
len = ((size-n>BUFSIZ)?(BUFSIZ):(size-n));
|
|
||||||
written = fwrite(&bigBufr[n], 1, len, fp);
|
|
||||||
n += written;
|
|
||||||
if (written != len)
|
|
||||||
{
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
fclose(fp);
|
|
||||||
|
|
||||||
if (n == size)
|
|
||||||
{
|
|
||||||
FTPD_SendReply(226, "Transfer complete.");
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
FTPD_SendReply(440, "Error during write.");
|
rtems_ftpd_send_reply(440, "File transfer failed.");
|
||||||
free(bigBufr);
|
}
|
||||||
|
free(bigBufr);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
int fd;
|
||||||
|
size_t written;
|
||||||
|
|
||||||
|
fd = creat(filename, S_IRUSR | S_IWUSR |
|
||||||
|
S_IRGRP | S_IWGRP |
|
||||||
|
S_IROTH | S_IWOTH);
|
||||||
|
if (fd == -1)
|
||||||
|
{
|
||||||
|
rtems_ftpd_send_reply(450, "Could not open file.");
|
||||||
|
close(s);
|
||||||
|
free(bufr);
|
||||||
return(1);
|
return(1);
|
||||||
}
|
}
|
||||||
|
while ((n = read(s, bufr, BUFSIZ)) > 0)
|
||||||
|
{
|
||||||
|
written = write(fd, bufr, n);
|
||||||
|
if (written == -1)
|
||||||
|
{
|
||||||
|
rtems_ftpd_send_reply(450, "Error during write.");
|
||||||
|
close(fd);
|
||||||
|
close(s);
|
||||||
|
free(bufr);
|
||||||
|
return(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
close(fd);
|
||||||
|
close(s);
|
||||||
|
rtems_ftpd_send_reply(226, "Transfer complete.");
|
||||||
}
|
}
|
||||||
|
|
||||||
free(bigBufr);
|
free(bufr);
|
||||||
return(0);
|
return(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**************************************************************************
|
/**************************************************************************
|
||||||
* Function: FTPD_CommandList *
|
* Function: rtems_ftpd_command_list *
|
||||||
**************************************************************************
|
**************************************************************************
|
||||||
* Description: *
|
* Description: *
|
||||||
* *
|
* *
|
||||||
@@ -518,7 +497,7 @@ FTPD_CommandStore(char *filename)
|
|||||||
* 12/01/97 - Creation (JWJ) *
|
* 12/01/97 - Creation (JWJ) *
|
||||||
*************************************************************************/
|
*************************************************************************/
|
||||||
static void
|
static void
|
||||||
FTPD_CommandList(char *fname)
|
rtems_ftpd_command_list(char *fname)
|
||||||
{
|
{
|
||||||
int s;
|
int s;
|
||||||
rtems_status_code sc;
|
rtems_status_code sc;
|
||||||
@@ -532,7 +511,7 @@ FTPD_CommandList(char *fname)
|
|||||||
sc = rtems_task_get_note(RTEMS_SELF, RTEMS_NOTEPAD_0,
|
sc = rtems_task_get_note(RTEMS_SELF, RTEMS_NOTEPAD_0,
|
||||||
(rtems_unsigned32 *)&info);
|
(rtems_unsigned32 *)&info);
|
||||||
|
|
||||||
FTPD_SendReply(150, "ASCII data connection for LIST.");
|
rtems_ftpd_send_reply(150, "ASCII data connection for LIST.");
|
||||||
|
|
||||||
s = socket(AF_INET, SOCK_STREAM, 0);
|
s = socket(AF_INET, SOCK_STREAM, 0);
|
||||||
if (connect(s, (struct sockaddr *)&info->data_addr,
|
if (connect(s, (struct sockaddr *)&info->data_addr,
|
||||||
@@ -548,7 +527,7 @@ FTPD_CommandList(char *fname)
|
|||||||
fname, (info->xfer_mode==TYPE_A)?("\r"):(""));
|
fname, (info->xfer_mode==TYPE_A)?("\r"):(""));
|
||||||
send(s, dirline, strlen(dirline), 0);
|
send(s, dirline, strlen(dirline), 0);
|
||||||
close(s);
|
close(s);
|
||||||
FTPD_SendReply(226, "Transfer complete.");
|
rtems_ftpd_send_reply(226, "Transfer complete.");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
while ((dp = readdir(dirp)) != NULL)
|
while ((dp = readdir(dirp)) != NULL)
|
||||||
@@ -578,7 +557,7 @@ FTPD_CommandList(char *fname)
|
|||||||
closedir(dirp);
|
closedir(dirp);
|
||||||
|
|
||||||
close(s);
|
close(s);
|
||||||
FTPD_SendReply(226, "Transfer complete.");
|
rtems_ftpd_send_reply(226, "Transfer complete.");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -586,7 +565,7 @@ FTPD_CommandList(char *fname)
|
|||||||
* Cheesy way to change directories
|
* Cheesy way to change directories
|
||||||
*/
|
*/
|
||||||
static void
|
static void
|
||||||
FTPD_CWD(char *dir)
|
rtems_ftpd_CWD(char *dir)
|
||||||
{
|
{
|
||||||
rtems_status_code sc;
|
rtems_status_code sc;
|
||||||
FTPD_SessionInfo_t *info = NULL;
|
FTPD_SessionInfo_t *info = NULL;
|
||||||
@@ -597,17 +576,17 @@ FTPD_CWD(char *dir)
|
|||||||
|
|
||||||
if (chdir(dir) == 0)
|
if (chdir(dir) == 0)
|
||||||
{
|
{
|
||||||
FTPD_SendReply(250, "CWD command successful.");
|
rtems_ftpd_send_reply(250, "CWD command successful.");
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
FTPD_SendReply(550, "CWD command failed.");
|
rtems_ftpd_send_reply(550, "CWD command failed.");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**************************************************************************
|
/**************************************************************************
|
||||||
* Function: FTPD_CommandPort *
|
* Function: rtems_ftpd_command_port *
|
||||||
**************************************************************************
|
**************************************************************************
|
||||||
* Description: *
|
* Description: *
|
||||||
* *
|
* *
|
||||||
@@ -630,7 +609,7 @@ FTPD_CWD(char *dir)
|
|||||||
* 12/01/97 - Creation (JWJ) *
|
* 12/01/97 - Creation (JWJ) *
|
||||||
*************************************************************************/
|
*************************************************************************/
|
||||||
static void
|
static void
|
||||||
FTPD_CommandPort(char *bufr)
|
rtems_ftpd_command_port(char *bufr)
|
||||||
{
|
{
|
||||||
char *ip;
|
char *ip;
|
||||||
char *port;
|
char *port;
|
||||||
@@ -656,13 +635,15 @@ FTPD_CommandPort(char *bufr)
|
|||||||
|
|
||||||
|
|
||||||
/**************************************************************************
|
/**************************************************************************
|
||||||
* Function: FTPD_ParseCommand *
|
* Function: rtems_ftpd_parse_command *
|
||||||
**************************************************************************
|
**************************************************************************
|
||||||
* Description: *
|
* Description: *
|
||||||
* *
|
* *
|
||||||
* Here, we parse the commands that have come through the control *
|
* Here, we parse the commands that have come through the control *
|
||||||
* connection. *
|
* connection. *
|
||||||
* *
|
* *
|
||||||
|
* FIXME: This section is somewhat of a hack. We should have a better *
|
||||||
|
* way to parse commands. *
|
||||||
* *
|
* *
|
||||||
* Inputs: *
|
* Inputs: *
|
||||||
* *
|
* *
|
||||||
@@ -678,7 +659,7 @@ FTPD_CommandPort(char *bufr)
|
|||||||
* 12/01/97 - Creation (JWJ) *
|
* 12/01/97 - Creation (JWJ) *
|
||||||
*************************************************************************/
|
*************************************************************************/
|
||||||
static void
|
static void
|
||||||
FTPD_ParseCommand(char *bufr)
|
rtems_ftpd_parse_command(char *bufr)
|
||||||
{
|
{
|
||||||
char fname[255];
|
char fname[255];
|
||||||
rtems_status_code sc;
|
rtems_status_code sc;
|
||||||
@@ -690,71 +671,71 @@ FTPD_ParseCommand(char *bufr)
|
|||||||
|
|
||||||
if (!strncmp("PORT", bufr, 4))
|
if (!strncmp("PORT", bufr, 4))
|
||||||
{
|
{
|
||||||
FTPD_SendReply(200, "PORT command successful.");
|
rtems_ftpd_send_reply(200, "PORT command successful.");
|
||||||
FTPD_CommandPort(&bufr[5]);
|
rtems_ftpd_command_port(&bufr[5]);
|
||||||
}
|
}
|
||||||
else if (!strncmp("RETR", bufr, 4))
|
else if (!strncmp("RETR", bufr, 4))
|
||||||
{
|
{
|
||||||
sscanf(&bufr[5], "%254s", fname);
|
sscanf(&bufr[5], "%254s", fname);
|
||||||
FTPD_CommandRetrieve(fname);
|
rtems_ftpd_command_retrieve(fname);
|
||||||
}
|
}
|
||||||
else if (!strncmp("STOR", bufr, 4))
|
else if (!strncmp("STOR", bufr, 4))
|
||||||
{
|
{
|
||||||
sscanf(&bufr[5], "%254s", fname);
|
sscanf(&bufr[5], "%254s", fname);
|
||||||
FTPD_CommandStore(fname);
|
rtems_ftpd_command_store(fname);
|
||||||
}
|
}
|
||||||
else if (!strncmp("LIST", bufr, 4))
|
else if (!strncmp("LIST", bufr, 4))
|
||||||
{
|
{
|
||||||
if (bufr[5] == '\n')
|
if (bufr[5] == '\n')
|
||||||
{
|
{
|
||||||
FTPD_CommandList(".");
|
rtems_ftpd_command_list(".");
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
sscanf(&bufr[5], "%254s", fname);
|
sscanf(&bufr[5], "%254s", fname);
|
||||||
FTPD_CommandList(fname);
|
rtems_ftpd_command_list(fname);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (!strncmp("USER", bufr, 4))
|
else if (!strncmp("USER", bufr, 4))
|
||||||
{
|
{
|
||||||
FTPD_SendReply(230, "User logged in.");
|
rtems_ftpd_send_reply(230, "User logged in.");
|
||||||
}
|
}
|
||||||
else if (!strncmp("SYST", bufr, 4))
|
else if (!strncmp("SYST", bufr, 4))
|
||||||
{
|
{
|
||||||
FTPD_SendReply(240, "RTEMS");
|
rtems_ftpd_send_reply(240, "RTEMS");
|
||||||
}
|
}
|
||||||
else if (!strncmp("TYPE", bufr, 4))
|
else if (!strncmp("TYPE", bufr, 4))
|
||||||
{
|
{
|
||||||
if (bufr[5] == 'I')
|
if (bufr[5] == 'I')
|
||||||
{
|
{
|
||||||
info->xfer_mode = TYPE_I;
|
info->xfer_mode = TYPE_I;
|
||||||
FTPD_SendReply(200, "Type set to I.");
|
rtems_ftpd_send_reply(200, "Type set to I.");
|
||||||
}
|
}
|
||||||
else if (bufr[5] == 'A')
|
else if (bufr[5] == 'A')
|
||||||
{
|
{
|
||||||
info->xfer_mode = TYPE_A;
|
info->xfer_mode = TYPE_A;
|
||||||
FTPD_SendReply(200, "Type set to A.");
|
rtems_ftpd_send_reply(200, "Type set to A.");
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
info->xfer_mode = TYPE_I;
|
info->xfer_mode = TYPE_I;
|
||||||
FTPD_SendReply(504, "Type not implemented. Set to I.");
|
rtems_ftpd_send_reply(504, "Type not implemented. Set to I.");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (!strncmp("PASS", bufr, 4))
|
else if (!strncmp("PASS", bufr, 4))
|
||||||
{
|
{
|
||||||
FTPD_SendReply(230, "User logged in.");
|
rtems_ftpd_send_reply(230, "User logged in.");
|
||||||
}
|
}
|
||||||
else if (!strncmp("DELE", bufr, 4))
|
else if (!strncmp("DELE", bufr, 4))
|
||||||
{
|
{
|
||||||
sscanf(&bufr[4], "%254s", fname);
|
sscanf(&bufr[4], "%254s", fname);
|
||||||
if (unlink(fname) == 0)
|
if (unlink(fname) == 0)
|
||||||
{
|
{
|
||||||
FTPD_SendReply(257, "DELE successful.");
|
rtems_ftpd_send_reply(257, "DELE successful.");
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
FTPD_SendReply(550, "DELE failed.");
|
rtems_ftpd_send_reply(550, "DELE failed.");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (!strncmp("SITE CHMOD", bufr, 10))
|
else if (!strncmp("SITE CHMOD", bufr, 10))
|
||||||
@@ -764,11 +745,11 @@ FTPD_ParseCommand(char *bufr)
|
|||||||
sscanf(&bufr[11], "%o %254s", &mask, fname);
|
sscanf(&bufr[11], "%o %254s", &mask, fname);
|
||||||
if (chmod(fname, (mode_t)mask) == 0)
|
if (chmod(fname, (mode_t)mask) == 0)
|
||||||
{
|
{
|
||||||
FTPD_SendReply(257, "CHMOD successful.");
|
rtems_ftpd_send_reply(257, "CHMOD successful.");
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
FTPD_SendReply(550, "CHMOD failed.");
|
rtems_ftpd_send_reply(550, "CHMOD failed.");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (!strncmp("RMD", bufr, 3))
|
else if (!strncmp("RMD", bufr, 3))
|
||||||
@@ -776,11 +757,11 @@ FTPD_ParseCommand(char *bufr)
|
|||||||
sscanf(&bufr[4], "%254s", fname);
|
sscanf(&bufr[4], "%254s", fname);
|
||||||
if (rmdir(fname) == 0)
|
if (rmdir(fname) == 0)
|
||||||
{
|
{
|
||||||
FTPD_SendReply(257, "RMD successful.");
|
rtems_ftpd_send_reply(257, "RMD successful.");
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
FTPD_SendReply(550, "RMD failed.");
|
rtems_ftpd_send_reply(550, "RMD failed.");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (!strncmp("MKD", bufr, 3))
|
else if (!strncmp("MKD", bufr, 3))
|
||||||
@@ -788,33 +769,34 @@ FTPD_ParseCommand(char *bufr)
|
|||||||
sscanf(&bufr[4], "%254s", fname);
|
sscanf(&bufr[4], "%254s", fname);
|
||||||
if (mkdir(fname, S_IRWXU | S_IRWXG | S_IRWXO) == 0)
|
if (mkdir(fname, S_IRWXU | S_IRWXG | S_IRWXO) == 0)
|
||||||
{
|
{
|
||||||
FTPD_SendReply(257, "MKD successful.");
|
rtems_ftpd_send_reply(257, "MKD successful.");
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
FTPD_SendReply(550, "MKD failed.");
|
rtems_ftpd_send_reply(550, "MKD failed.");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (!strncmp("CWD", bufr, 3))
|
else if (!strncmp("CWD", bufr, 3))
|
||||||
{
|
{
|
||||||
sscanf(&bufr[4], "%254s", fname);
|
sscanf(&bufr[4], "%254s", fname);
|
||||||
FTPD_CWD(fname);
|
rtems_ftpd_CWD(fname);
|
||||||
}
|
}
|
||||||
else if (!strncmp("PWD", bufr, 3))
|
else if (!strncmp("PWD", bufr, 3))
|
||||||
{
|
{
|
||||||
char *cwd = getcwd(0, 0);
|
char *cwd = getcwd(0, 0);
|
||||||
sprintf(bufr, "\"%s\" is the current directory.", cwd);
|
sprintf(bufr, "\"%s\" is the current directory.", cwd);
|
||||||
FTPD_SendReply(250, bufr);
|
rtems_ftpd_send_reply(250, bufr);
|
||||||
free(cwd);
|
free(cwd);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
FTPD_SendReply(500, "Unrecognized/unsupported command.");
|
rtems_ftpd_send_reply(500, "Unrecognized/unsupported command.");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**************************************************************************
|
/**************************************************************************
|
||||||
* Function: FTPD_Session *
|
* Function: rtems_ftpd_session *
|
||||||
**************************************************************************
|
**************************************************************************
|
||||||
* Description: *
|
* Description: *
|
||||||
* *
|
* *
|
||||||
@@ -827,7 +809,7 @@ FTPD_ParseCommand(char *bufr)
|
|||||||
* *
|
* *
|
||||||
* Inputs: *
|
* Inputs: *
|
||||||
* *
|
* *
|
||||||
* rtems_task_argument arg - The FTPD_Daemon task passes the socket *
|
* rtems_task_argument arg - The daemon task passes the socket *
|
||||||
* which serves as the control connection. *
|
* which serves as the control connection. *
|
||||||
* *
|
* *
|
||||||
* Output: *
|
* Output: *
|
||||||
@@ -839,7 +821,7 @@ FTPD_ParseCommand(char *bufr)
|
|||||||
* 12/01/97 - Creation (JWJ) *
|
* 12/01/97 - Creation (JWJ) *
|
||||||
*************************************************************************/
|
*************************************************************************/
|
||||||
static void
|
static void
|
||||||
FTPD_Session(rtems_task_argument arg)
|
rtems_ftpd_session(rtems_task_argument arg)
|
||||||
{
|
{
|
||||||
char cmd[256];
|
char cmd[256];
|
||||||
rtems_status_code sc;
|
rtems_status_code sc;
|
||||||
@@ -849,7 +831,7 @@ FTPD_Session(rtems_task_argument arg)
|
|||||||
sc = rtems_task_get_note(RTEMS_SELF, RTEMS_NOTEPAD_0,
|
sc = rtems_task_get_note(RTEMS_SELF, RTEMS_NOTEPAD_0,
|
||||||
(rtems_unsigned32 *)&info);
|
(rtems_unsigned32 *)&info);
|
||||||
|
|
||||||
FTPD_SendReply(220, "Erithacus FTP server (Version 1.0) ready.");
|
rtems_ftpd_send_reply(220, FTPD_SERVER_MESSAGE);
|
||||||
|
|
||||||
/***********************************************************************
|
/***********************************************************************
|
||||||
* Set initial directory to "/".
|
* Set initial directory to "/".
|
||||||
@@ -858,7 +840,7 @@ FTPD_Session(rtems_task_argument arg)
|
|||||||
info->xfer_mode = TYPE_A;
|
info->xfer_mode = TYPE_A;
|
||||||
while (1)
|
while (1)
|
||||||
{
|
{
|
||||||
if (recv(info->ctrl_sock, cmd, 256, 0) == -1)
|
if (fgets(cmd, 256, info->ctrl_fp) == NULL)
|
||||||
{
|
{
|
||||||
syslog(LOG_INFO, "ftpd: Connection aborted.");
|
syslog(LOG_INFO, "ftpd: Connection aborted.");
|
||||||
break;
|
break;
|
||||||
@@ -866,16 +848,16 @@ FTPD_Session(rtems_task_argument arg)
|
|||||||
|
|
||||||
if (!strncmp("QUIT", cmd, 4))
|
if (!strncmp("QUIT", cmd, 4))
|
||||||
{
|
{
|
||||||
FTPD_SendReply(221, "Goodbye.");
|
rtems_ftpd_send_reply(221, "Goodbye.");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
FTPD_ParseCommand(cmd);
|
rtems_ftpd_parse_command(cmd);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (close(info->ctrl_sock) < 0)
|
if (fclose(info->ctrl_fp) != 0)
|
||||||
{
|
{
|
||||||
syslog(LOG_ERR, "ftpd: Could not close session.");
|
syslog(LOG_ERR, "ftpd: Could not close session.");
|
||||||
}
|
}
|
||||||
@@ -895,7 +877,7 @@ FTPD_Session(rtems_task_argument arg)
|
|||||||
|
|
||||||
|
|
||||||
/**************************************************************************
|
/**************************************************************************
|
||||||
* Function: FTPD_Daemon *
|
* Function: rtems_ftpd_daemon *
|
||||||
**************************************************************************
|
**************************************************************************
|
||||||
* Description: *
|
* Description: *
|
||||||
* *
|
* *
|
||||||
@@ -918,7 +900,7 @@ FTPD_Session(rtems_task_argument arg)
|
|||||||
* 12/01/97 - Creation (JWJ) *
|
* 12/01/97 - Creation (JWJ) *
|
||||||
*************************************************************************/
|
*************************************************************************/
|
||||||
static void
|
static void
|
||||||
FTPD_Daemon()
|
rtems_ftpd_daemon()
|
||||||
{
|
{
|
||||||
int s;
|
int s;
|
||||||
int s1;
|
int s1;
|
||||||
@@ -941,7 +923,7 @@ FTPD_Daemon()
|
|||||||
}
|
}
|
||||||
|
|
||||||
localAddr.sin_family = AF_INET;
|
localAddr.sin_family = AF_INET;
|
||||||
localAddr.sin_port = FTPD_CONTROL_PORT;
|
localAddr.sin_port = htons(rtems_ftpd_configuration.port);
|
||||||
localAddr.sin_addr.s_addr = INADDR_ANY;
|
localAddr.sin_addr.s_addr = INADDR_ANY;
|
||||||
memset(localAddr.sin_zero, '\0', sizeof(localAddr.sin_zero));
|
memset(localAddr.sin_zero, '\0', sizeof(localAddr.sin_zero));
|
||||||
if (bind(s, (struct sockaddr *)&localAddr,
|
if (bind(s, (struct sockaddr *)&localAddr,
|
||||||
@@ -1002,21 +984,28 @@ FTPD_Daemon()
|
|||||||
/********************************************************************
|
/********************************************************************
|
||||||
* Send the socket on to the new session.
|
* Send the socket on to the new session.
|
||||||
*******************************************************************/
|
*******************************************************************/
|
||||||
info->ctrl_sock = s1;
|
if ((info->ctrl_fp = fdopen(s1, "r+")) == NULL)
|
||||||
sc = rtems_task_set_note(tid, RTEMS_NOTEPAD_0,
|
|
||||||
(rtems_unsigned32)info);
|
|
||||||
sc = rtems_task_start(tid, FTPD_Session, 0);
|
|
||||||
if (sc != RTEMS_SUCCESSFUL)
|
|
||||||
{
|
{
|
||||||
syslog(LOG_ERR, "ftpd: Could not start FTPD session: %s",
|
syslog(LOG_ERR, "ftpd: fdopen() on socket failed.");
|
||||||
rtems_status_text(sc));
|
close(s1);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
sc = rtems_task_set_note(tid, RTEMS_NOTEPAD_0,
|
||||||
|
(rtems_unsigned32)info);
|
||||||
|
sc = rtems_task_start(tid, rtems_ftpd_session, 0);
|
||||||
|
if (sc != RTEMS_SUCCESSFUL)
|
||||||
|
{
|
||||||
|
syslog(LOG_ERR, "ftpd: Could not start FTPD session: %s",
|
||||||
|
rtems_status_text(sc));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**************************************************************************
|
/**************************************************************************
|
||||||
* Function: FTPD_Start *
|
* Function: rtems_ftpd_start *
|
||||||
**************************************************************************
|
**************************************************************************
|
||||||
* Description: *
|
* Description: *
|
||||||
* *
|
* *
|
||||||
@@ -1031,21 +1020,33 @@ FTPD_Daemon()
|
|||||||
* *
|
* *
|
||||||
* Output: *
|
* Output: *
|
||||||
* *
|
* *
|
||||||
* none *
|
* int - RTEMS_SUCCESSFUL on successful start of the daemon. *
|
||||||
* *
|
* *
|
||||||
**************************************************************************
|
**************************************************************************
|
||||||
* Change History: *
|
* Change History: *
|
||||||
* 12/01/97 - Creation (JWJ) *
|
* 12/01/97 - Creation (JWJ) *
|
||||||
*************************************************************************/
|
*************************************************************************/
|
||||||
void
|
int
|
||||||
FTPD_Start(rtems_task_priority priority)
|
rtems_initialize_ftpd()
|
||||||
{
|
{
|
||||||
rtems_status_code sc;
|
rtems_status_code sc;
|
||||||
rtems_id tid;
|
rtems_id tid;
|
||||||
|
|
||||||
|
|
||||||
|
if (rtems_ftpd_configuration.port == 0)
|
||||||
|
{
|
||||||
|
rtems_ftpd_configuration.port = FTPD_CONTROL_PORT;
|
||||||
|
}
|
||||||
|
|
||||||
|
/***********************************************************************
|
||||||
|
* Default FTPD priority.
|
||||||
|
**********************************************************************/
|
||||||
|
if (rtems_ftpd_configuration.priority == 0)
|
||||||
|
{
|
||||||
|
rtems_ftpd_configuration.priority = 40;
|
||||||
|
}
|
||||||
sc = rtems_task_create(rtems_build_name('F', 'T', 'P', 'D'),
|
sc = rtems_task_create(rtems_build_name('F', 'T', 'P', 'D'),
|
||||||
priority, 8*1024,
|
rtems_ftpd_configuration.priority, 8*1024,
|
||||||
RTEMS_PREEMPT | RTEMS_NO_TIMESLICE | RTEMS_NO_ASR |
|
RTEMS_PREEMPT | RTEMS_NO_TIMESLICE | RTEMS_NO_ASR |
|
||||||
RTEMS_INTERRUPT_LEVEL(0),
|
RTEMS_INTERRUPT_LEVEL(0),
|
||||||
RTEMS_NO_FLOATING_POINT | RTEMS_LOCAL,
|
RTEMS_NO_FLOATING_POINT | RTEMS_LOCAL,
|
||||||
@@ -1054,14 +1055,18 @@ FTPD_Start(rtems_task_priority priority)
|
|||||||
{
|
{
|
||||||
syslog(LOG_ERR, "ftpd: Could not create FTP daemon: %s",
|
syslog(LOG_ERR, "ftpd: Could not create FTP daemon: %s",
|
||||||
rtems_status_text(sc));
|
rtems_status_text(sc));
|
||||||
|
return(RTEMS_UNSATISFIED);
|
||||||
}
|
}
|
||||||
|
|
||||||
sc = rtems_task_start(tid, FTPD_Daemon, 0);
|
sc = rtems_task_start(tid, rtems_ftpd_daemon, 0);
|
||||||
if (sc != RTEMS_SUCCESSFUL)
|
if (sc != RTEMS_SUCCESSFUL)
|
||||||
{
|
{
|
||||||
syslog(LOG_ERR, "ftpd: Could not start FTP daemon: %s",
|
syslog(LOG_ERR, "ftpd: Could not start FTP daemon: %s",
|
||||||
rtems_status_text(sc));
|
rtems_status_text(sc));
|
||||||
|
return(RTEMS_UNSATISFIED);
|
||||||
}
|
}
|
||||||
|
|
||||||
syslog(LOG_INFO, "ftpd: FTP daemon started.");
|
syslog(LOG_INFO, "ftpd: FTP daemon started.");
|
||||||
|
return(RTEMS_SUCCESSFUL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -10,17 +10,33 @@
|
|||||||
|
|
||||||
#define FTPD_CONTROL_PORT 21
|
#define FTPD_CONTROL_PORT 21
|
||||||
|
|
||||||
|
typedef int (*rtems_ftpd_hookfunction)(unsigned char *, unsigned long);
|
||||||
|
|
||||||
|
struct rtems_ftpd_hook
|
||||||
|
{
|
||||||
|
char *filename;
|
||||||
|
rtems_ftpd_hookfunction hook_function;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct rtems_ftpd_configuration
|
||||||
|
{
|
||||||
|
rtems_task_priority priority; /* FTPD task priority */
|
||||||
|
unsigned long max_hook_filesize; /* Maximum buffersize */
|
||||||
|
/* for hooks */
|
||||||
|
int port; /* Well-known port */
|
||||||
|
struct rtems_ftpd_hook *hooks; /* List of hooks */
|
||||||
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Reply codes.
|
* Reply codes.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#define PRELIM 1 /* positive preliminary */
|
#define PRELIM 1 /* positive preliminary */
|
||||||
#define COMPLETE 2 /* positive completion */
|
#define COMPLETE 2 /* positive completion */
|
||||||
#define CONTINUE 3 /* positive intermediate */
|
#define CONTINUE 3 /* positive intermediate */
|
||||||
#define TRANSIENT 4 /* transient negative completion */
|
#define TRANSIENT 4 /* transient negative completion */
|
||||||
#define ERROR 5 /* permanent negative completion */
|
#define ERROR 5 /* permanent negative completion */
|
||||||
|
|
||||||
void rtems_ftpd_sTart(rtems_task_priority priority);
|
int rtems_initialize_ftpd();
|
||||||
|
|
||||||
#endif /* __FTPD_H__ */
|
#endif /* __FTPD_H__ */
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,8 @@
|
|||||||
/*
|
/* FIXME: 1. Parse command is a hack. We can do better.
|
||||||
|
* 2. chdir is a hack. We can do better.
|
||||||
|
* 3. PWD doesn't work.
|
||||||
|
* 4. Some sort of access control?
|
||||||
|
*
|
||||||
* FTP Server Daemon
|
* FTP Server Daemon
|
||||||
*
|
*
|
||||||
* Submitted by: Jake Janovetz <janovetz@tempest.ece.uiuc.edu>
|
* Submitted by: Jake Janovetz <janovetz@tempest.ece.uiuc.edu>
|
||||||
@@ -6,34 +10,17 @@
|
|||||||
* $Id$
|
* $Id$
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/*
|
|
||||||
* Current state:
|
|
||||||
* To untar, put as "untar"
|
|
||||||
* CWD uses chdir
|
|
||||||
* This is bad due to global setting of chdir.
|
|
||||||
*
|
|
||||||
* Stored files come into RAM and are saved later. This is an artifact
|
|
||||||
* of a previous implementation (no filesystem -- had to do stuff with
|
|
||||||
* the "files" later). This can be eliminated once all of Jake's stuff
|
|
||||||
* is moved to devices/filesystems.
|
|
||||||
*
|
|
||||||
* CLOSE(S) doesn't seem to work. This causes problems in
|
|
||||||
* several areas. It lets too many file descriptors pile up
|
|
||||||
* and it doesn't seem to flush the stream.
|
|
||||||
*
|
|
||||||
* Is 'recv' what I want to use to get commands from the control port?
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
/**************************************************************************
|
/**************************************************************************
|
||||||
* ftpd.c *
|
* ftpd.c *
|
||||||
**************************************************************************
|
**************************************************************************
|
||||||
* Description: *
|
* Description: *
|
||||||
* *
|
* *
|
||||||
* This file contains the daemon which services requests that appear *
|
* This file contains the daemon which services requests that appear *
|
||||||
* on the 'FTP' port. This server is compatible with FTP, but it *
|
* on the FTP port. This server is compatible with FTP, but it *
|
||||||
* also provides services specific to the Erithacus system. *
|
* also provides 'hooks' to make it usable in situations where files *
|
||||||
* This server is started at boot-time and runs forever. *
|
* are not used/necessary. Once the server is started, it runs *
|
||||||
|
* forever. *
|
||||||
|
* *
|
||||||
* *
|
* *
|
||||||
* Organization: *
|
* Organization: *
|
||||||
* *
|
* *
|
||||||
@@ -44,12 +31,6 @@
|
|||||||
* is complete, the session task deletes itself. The daemon still *
|
* is complete, the session task deletes itself. The daemon still *
|
||||||
* runs, however. *
|
* runs, however. *
|
||||||
* *
|
* *
|
||||||
* Implementation Notes: *
|
|
||||||
* *
|
|
||||||
* The 'current working directory' implementation utilizes the *
|
|
||||||
* RTEMS filesystem cwd. This is no good since other processes *
|
|
||||||
* inherit the same cwd. *
|
|
||||||
* *
|
|
||||||
* *
|
* *
|
||||||
* Supported commands are: *
|
* Supported commands are: *
|
||||||
* *
|
* *
|
||||||
@@ -70,51 +51,34 @@
|
|||||||
* and port (x*256 + y). *
|
* and port (x*256 + y). *
|
||||||
* *
|
* *
|
||||||
* *
|
* *
|
||||||
* *
|
|
||||||
* The public routines contained in this file are: *
|
* The public routines contained in this file are: *
|
||||||
* *
|
* *
|
||||||
* FTPD_Start - Starts the server daemon, then returns to its caller. *
|
* rtems_initialize_ftpd_start - Starts the server daemon, then *
|
||||||
|
* returns to its caller. *
|
||||||
* *
|
* *
|
||||||
* *
|
* *
|
||||||
* The private routines contained in this file are: *
|
* The private routines contained in this file are: *
|
||||||
* *
|
* *
|
||||||
* FTPD_SendReply - Sends a reply code and text through the control *
|
* rtems_ftpd_send_reply - Sends a reply code and text through the *
|
||||||
* port. *
|
* control port. *
|
||||||
* FTPD_CommandStore - Performs the "STOR" command. *
|
* rtems_ftpd_command_retrieve - Performs to "RETR" command. *
|
||||||
* FTPD_CommandList - Performs the "LIST" command. *
|
* rtems_ftpd_command_store - Performs the "STOR" command. *
|
||||||
* FTPD_CommandPort - Opens a data port (the "PORT" command). *
|
* rtems_ftpd_command_list - Performs the "LIST" command. *
|
||||||
* FTPD_ParseCommand - Parses an incoming command. *
|
* rtems_ftpd_command_port - Opens a data port (the "PORT" command). *
|
||||||
* FTPD_Session - Begins a service session. *
|
* rtems_ftpd_parse_command - Parses an incoming command. *
|
||||||
* FTPD_Daemon - Listens on the FTP port for service requests. *
|
* rtmes_ftpd_session - Begins a service session. *
|
||||||
* *
|
* rtems_ftpd_daemon - Listens on the FTP port for service *
|
||||||
* *
|
* requests. *
|
||||||
*------------------------------------------------------------------------*
|
*------------------------------------------------------------------------*
|
||||||
* *
|
|
||||||
* Jake Janovetz *
|
* Jake Janovetz *
|
||||||
* University of Illinois *
|
* University of Illinois *
|
||||||
* 1406 West Green Street *
|
* 1406 West Green Street *
|
||||||
* Urbana IL 61801 *
|
* Urbana IL 61801 *
|
||||||
* *
|
|
||||||
**************************************************************************
|
**************************************************************************
|
||||||
* Change History: *
|
* Change History: *
|
||||||
* 12/01/97 - Creation (JWJ) *
|
* 12/01/97 - Creation (JWJ) *
|
||||||
*************************************************************************/
|
*************************************************************************/
|
||||||
|
|
||||||
/* Revision Control Information:
|
|
||||||
*
|
|
||||||
* $Source$
|
|
||||||
* $Id$
|
|
||||||
* $Log$
|
|
||||||
* Revision 1.3 1998/05/19 21:28:17 erithacus
|
|
||||||
* Update control socket to file I/O.
|
|
||||||
*
|
|
||||||
* Revision 1.2 1998/05/19 20:13:50 erithacus
|
|
||||||
* Remodeled to be entirely reentrant.
|
|
||||||
*
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
@@ -133,9 +97,10 @@
|
|||||||
#include <netinet/in.h>
|
#include <netinet/in.h>
|
||||||
|
|
||||||
#include "ftpd.h"
|
#include "ftpd.h"
|
||||||
#include "untar.h"
|
|
||||||
|
|
||||||
|
|
||||||
|
extern struct rtems_ftpd_configuration rtems_ftpd_configuration;
|
||||||
|
|
||||||
/**************************************************************************
|
/**************************************************************************
|
||||||
* Meanings of first and second digits of reply codes:
|
* Meanings of first and second digits of reply codes:
|
||||||
*
|
*
|
||||||
@@ -163,14 +128,6 @@
|
|||||||
*************************************************************************/
|
*************************************************************************/
|
||||||
|
|
||||||
|
|
||||||
/**************************************************************************
|
|
||||||
* Maximum buffer size for use by the transfer protocol.
|
|
||||||
* This will be eliminated when the filesystem is complete enough that
|
|
||||||
* we don't have to store the received data until we have something to
|
|
||||||
* do with it.
|
|
||||||
*************************************************************************/
|
|
||||||
#define FTPD_MAX_RECEIVESIZE (512*1024)
|
|
||||||
|
|
||||||
/**************************************************************************
|
/**************************************************************************
|
||||||
* SessionInfo structure.
|
* SessionInfo structure.
|
||||||
*
|
*
|
||||||
@@ -180,13 +137,14 @@
|
|||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
struct sockaddr_in data_addr; /* Data address for PORT commands */
|
struct sockaddr_in data_addr; /* Data address for PORT commands */
|
||||||
int ctrl_sock; /* Control connection socker */
|
FILE *ctrl_fp; /* File pointer for control connection */
|
||||||
char cwd[255]; /* Current working directory */
|
char cwd[255]; /* Current working directory */
|
||||||
/* Login -- future use -- */
|
/* Login -- future use -- */
|
||||||
int xfer_mode; /* Transfer mode (ASCII/binary) */
|
int xfer_mode; /* Transfer mode (ASCII/binary) */
|
||||||
} FTPD_SessionInfo_t;
|
} FTPD_SessionInfo_t;
|
||||||
|
|
||||||
|
|
||||||
|
#define FTPD_SERVER_MESSAGE "RTEMS FTP server (Version 1.0-JWJ) ready."
|
||||||
#define FTPD_WELCOME_MESSAGE \
|
#define FTPD_WELCOME_MESSAGE \
|
||||||
"Welcome to the RTEMS FTP server.\n" \
|
"Welcome to the RTEMS FTP server.\n" \
|
||||||
"\n" \
|
"\n" \
|
||||||
@@ -194,7 +152,7 @@ typedef struct
|
|||||||
|
|
||||||
|
|
||||||
/**************************************************************************
|
/**************************************************************************
|
||||||
* Function: FTPD_SendReply *
|
* Function: rtems_ftpd_send_reply *
|
||||||
**************************************************************************
|
**************************************************************************
|
||||||
* Description: *
|
* Description: *
|
||||||
* *
|
* *
|
||||||
@@ -216,7 +174,7 @@ typedef struct
|
|||||||
* 12/01/97 - Creation (JWJ) *
|
* 12/01/97 - Creation (JWJ) *
|
||||||
*************************************************************************/
|
*************************************************************************/
|
||||||
static void
|
static void
|
||||||
FTPD_SendReply(int code, char *text)
|
rtems_ftpd_send_reply(int code, char *text)
|
||||||
{
|
{
|
||||||
rtems_status_code sc;
|
rtems_status_code sc;
|
||||||
FTPD_SessionInfo_t *info = NULL;
|
FTPD_SessionInfo_t *info = NULL;
|
||||||
@@ -241,17 +199,19 @@ FTPD_SendReply(int code, char *text)
|
|||||||
if (text != NULL)
|
if (text != NULL)
|
||||||
{
|
{
|
||||||
sprintf(str, "%d %.70s\r\n", code, text);
|
sprintf(str, "%d %.70s\r\n", code, text);
|
||||||
|
fprintf(info->ctrl_fp, "%d %.70s\r\n", code, text);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
sprintf(str, "%d\r\n", code);
|
sprintf(str, "%d\r\n", code);
|
||||||
|
fprintf(info->ctrl_fp, "%d\r\n", code);
|
||||||
}
|
}
|
||||||
send(info->ctrl_sock, str, strlen(str), 0);
|
fflush(info->ctrl_fp);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**************************************************************************
|
/**************************************************************************
|
||||||
* Function: FTPD_CommandRetrieve *
|
* Function: rtems_ftpd_command_retrieve *
|
||||||
**************************************************************************
|
**************************************************************************
|
||||||
* Description: *
|
* Description: *
|
||||||
* *
|
* *
|
||||||
@@ -274,12 +234,11 @@ FTPD_SendReply(int code, char *text)
|
|||||||
* 04/29/98 - Creation (JWJ) *
|
* 04/29/98 - Creation (JWJ) *
|
||||||
*************************************************************************/
|
*************************************************************************/
|
||||||
static int
|
static int
|
||||||
FTPD_CommandRetrieve(char *filename)
|
rtems_ftpd_command_retrieve(char *filename)
|
||||||
{
|
{
|
||||||
int s;
|
int s;
|
||||||
int n;
|
int n;
|
||||||
|
int fd;
|
||||||
FILE *fp;
|
|
||||||
unsigned char *bufr;
|
unsigned char *bufr;
|
||||||
rtems_status_code sc;
|
rtems_status_code sc;
|
||||||
FTPD_SessionInfo_t *info = NULL;
|
FTPD_SessionInfo_t *info = NULL;
|
||||||
@@ -288,32 +247,31 @@ FTPD_CommandRetrieve(char *filename)
|
|||||||
sc = rtems_task_get_note(RTEMS_SELF, RTEMS_NOTEPAD_0,
|
sc = rtems_task_get_note(RTEMS_SELF, RTEMS_NOTEPAD_0,
|
||||||
(rtems_unsigned32 *)&info);
|
(rtems_unsigned32 *)&info);
|
||||||
|
|
||||||
|
if ((fd = open(filename, O_RDONLY)) == -1)
|
||||||
if ((fp = fopen(filename, "r")) == NULL)
|
|
||||||
{
|
{
|
||||||
FTPD_SendReply(450, "Error opening file.");
|
rtems_ftpd_send_reply(450, "Error opening file.");
|
||||||
return(0);
|
return(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
bufr = (unsigned char *)malloc(BUFSIZ);
|
bufr = (unsigned char *)malloc(BUFSIZ);
|
||||||
if (bufr == NULL)
|
if (bufr == NULL)
|
||||||
{
|
{
|
||||||
FTPD_SendReply(440, "Server error - malloc fail.");
|
rtems_ftpd_send_reply(440, "Server error - malloc fail.");
|
||||||
fclose(fp);
|
close(fd);
|
||||||
return(0);
|
return(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
/***********************************************************************
|
/***********************************************************************
|
||||||
* Connect to the data connection (PORT made in an earlier PORT call).
|
* Connect to the data connection (PORT made in an earlier PORT call).
|
||||||
**********************************************************************/
|
**********************************************************************/
|
||||||
FTPD_SendReply(150, "BINARY data connection.");
|
rtems_ftpd_send_reply(150, "BINARY data connection.");
|
||||||
s = socket(AF_INET, SOCK_STREAM, 0);
|
s = socket(AF_INET, SOCK_STREAM, 0);
|
||||||
if (connect(s, (struct sockaddr *)&info->data_addr,
|
if (connect(s, (struct sockaddr *)&info->data_addr,
|
||||||
sizeof(struct sockaddr)) < 0)
|
sizeof(struct sockaddr)) < 0)
|
||||||
{
|
{
|
||||||
FTPD_SendReply(420, "Server error - could not connect socket.");
|
rtems_ftpd_send_reply(420, "Server error - could not connect socket.");
|
||||||
free(bufr);
|
free(bufr);
|
||||||
fclose(fp);
|
close(fd);
|
||||||
close(s);
|
close(s);
|
||||||
return(1);
|
return(1);
|
||||||
}
|
}
|
||||||
@@ -321,18 +279,19 @@ FTPD_CommandRetrieve(char *filename)
|
|||||||
/***********************************************************************
|
/***********************************************************************
|
||||||
* Send the data over the ether.
|
* Send the data over the ether.
|
||||||
**********************************************************************/
|
**********************************************************************/
|
||||||
while ((n = fread(bufr, 1, BUFSIZ, fp)) != 0)
|
while ((n = read(fd, bufr, BUFSIZ)) > 0)
|
||||||
{
|
{
|
||||||
send(s, bufr, n, 0);
|
send(s, bufr, n, 0);
|
||||||
|
bufr[n-1] = '\0';
|
||||||
}
|
}
|
||||||
|
|
||||||
if (feof(fp))
|
if (n == 0)
|
||||||
{
|
{
|
||||||
FTPD_SendReply(210, "File sent successfully.");
|
rtems_ftpd_send_reply(210, "File sent successfully.");
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
FTPD_SendReply(450, "Retrieve failed.");
|
rtems_ftpd_send_reply(450, "Retrieve failed.");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (close(s) != 0)
|
if (close(s) != 0)
|
||||||
@@ -341,13 +300,13 @@ FTPD_CommandRetrieve(char *filename)
|
|||||||
}
|
}
|
||||||
|
|
||||||
free(bufr);
|
free(bufr);
|
||||||
fclose(fp);
|
close(fd);
|
||||||
return(0);
|
return(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**************************************************************************
|
/**************************************************************************
|
||||||
* Function: FTPD_CommandStore *
|
* Function: rtems_ftpd_command_store *
|
||||||
**************************************************************************
|
**************************************************************************
|
||||||
* Description: *
|
* Description: *
|
||||||
* *
|
* *
|
||||||
@@ -370,15 +329,15 @@ FTPD_CommandRetrieve(char *filename)
|
|||||||
* 12/01/97 - Creation (JWJ) *
|
* 12/01/97 - Creation (JWJ) *
|
||||||
*************************************************************************/
|
*************************************************************************/
|
||||||
static int
|
static int
|
||||||
FTPD_CommandStore(char *filename)
|
rtems_ftpd_command_store(char *filename)
|
||||||
{
|
{
|
||||||
char *bufr;
|
char *bufr;
|
||||||
char *bigBufr;
|
int s;
|
||||||
int s;
|
int n;
|
||||||
int n;
|
unsigned long size = 0;
|
||||||
unsigned long size = 0;
|
rtems_status_code sc;
|
||||||
rtems_status_code sc;
|
FTPD_SessionInfo_t *info = NULL;
|
||||||
FTPD_SessionInfo_t *info = NULL;
|
struct rtems_ftpd_hook *usehook = NULL;
|
||||||
|
|
||||||
|
|
||||||
sc = rtems_task_get_note(RTEMS_SELF, RTEMS_NOTEPAD_0,
|
sc = rtems_task_get_note(RTEMS_SELF, RTEMS_NOTEPAD_0,
|
||||||
@@ -387,26 +346,17 @@ FTPD_CommandStore(char *filename)
|
|||||||
bufr = (char *)malloc(BUFSIZ * sizeof(char));
|
bufr = (char *)malloc(BUFSIZ * sizeof(char));
|
||||||
if (bufr == NULL)
|
if (bufr == NULL)
|
||||||
{
|
{
|
||||||
FTPD_SendReply(440, "Server error - malloc fail.");
|
rtems_ftpd_send_reply(440, "Server error - malloc fail.");
|
||||||
return(1);
|
return(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
bigBufr = (char *)malloc(FTPD_MAX_RECEIVESIZE * sizeof(char));
|
rtems_ftpd_send_reply(150, "BINARY data connection.");
|
||||||
if (bigBufr == NULL)
|
|
||||||
{
|
|
||||||
FTPD_SendReply(440, "Server error - malloc fail.");
|
|
||||||
free(bufr);
|
|
||||||
return(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
FTPD_SendReply(150, "BINARY data connection.");
|
|
||||||
|
|
||||||
s = socket(AF_INET, SOCK_STREAM, 0);
|
s = socket(AF_INET, SOCK_STREAM, 0);
|
||||||
if (connect(s, (struct sockaddr *)&info->data_addr,
|
if (connect(s, (struct sockaddr *)&info->data_addr,
|
||||||
sizeof(struct sockaddr)) < 0)
|
sizeof(struct sockaddr)) < 0)
|
||||||
{
|
{
|
||||||
free(bufr);
|
free(bufr);
|
||||||
free(bigBufr);
|
|
||||||
close(s);
|
close(s);
|
||||||
return(1);
|
return(1);
|
||||||
}
|
}
|
||||||
@@ -414,22 +364,57 @@ FTPD_CommandStore(char *filename)
|
|||||||
|
|
||||||
/***********************************************************************
|
/***********************************************************************
|
||||||
* File: "/dev/null" just throws the data away.
|
* File: "/dev/null" just throws the data away.
|
||||||
|
* Otherwise, search our list of hooks to see if we need to do something
|
||||||
|
* special.
|
||||||
**********************************************************************/
|
**********************************************************************/
|
||||||
if (!strncmp("/dev/null", filename, 9))
|
if (!strncmp("/dev/null", filename, 9))
|
||||||
{
|
{
|
||||||
while ((n = read(s, bufr, BUFSIZ)) > 0);
|
while ((n = read(s, bufr, BUFSIZ)) > 0);
|
||||||
}
|
}
|
||||||
else
|
else if (rtems_ftpd_configuration.hooks != NULL)
|
||||||
{
|
{
|
||||||
|
struct rtems_ftpd_hook *hook;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
i = 0;
|
||||||
|
hook = &rtems_ftpd_configuration.hooks[i++];
|
||||||
|
while (hook->filename != NULL)
|
||||||
|
{
|
||||||
|
if (!strcmp(hook->filename, filename))
|
||||||
|
{
|
||||||
|
usehook = hook;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
hook = &rtems_ftpd_configuration.hooks[i++];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (usehook != NULL)
|
||||||
|
{
|
||||||
|
char *bigBufr;
|
||||||
|
|
||||||
|
/***********************************************************************
|
||||||
|
* Allocate space for our "file".
|
||||||
|
**********************************************************************/
|
||||||
|
bigBufr = (char *)malloc(
|
||||||
|
rtems_ftpd_configuration.max_hook_filesize * sizeof(char));
|
||||||
|
if (bigBufr == NULL)
|
||||||
|
{
|
||||||
|
rtems_ftpd_send_reply(440, "Server error - malloc fail.");
|
||||||
|
free(bufr);
|
||||||
|
return(1);
|
||||||
|
}
|
||||||
|
|
||||||
/***********************************************************************
|
/***********************************************************************
|
||||||
* Retrieve the file into our buffer space.
|
* Retrieve the file into our buffer space.
|
||||||
**********************************************************************/
|
**********************************************************************/
|
||||||
size = 0;
|
size = 0;
|
||||||
while ((n = read(s, bufr, BUFSIZ)) > 0)
|
while ((n = read(s, bufr, BUFSIZ)) > 0)
|
||||||
{
|
{
|
||||||
if (size + n > FTPD_MAX_RECEIVESIZE)
|
if (size + n >
|
||||||
|
rtems_ftpd_configuration.max_hook_filesize * sizeof(char))
|
||||||
{
|
{
|
||||||
FTPD_SendReply(440, "Server error - Buffer size exceeded.");
|
rtems_ftpd_send_reply(440, "Server error - Buffer size exceeded.");
|
||||||
free(bufr);
|
free(bufr);
|
||||||
free(bigBufr);
|
free(bigBufr);
|
||||||
close(s);
|
close(s);
|
||||||
@@ -438,66 +423,60 @@ FTPD_CommandStore(char *filename)
|
|||||||
memcpy(&bigBufr[size], bufr, n);
|
memcpy(&bigBufr[size], bufr, n);
|
||||||
size += n;
|
size += n;
|
||||||
}
|
}
|
||||||
}
|
close(s);
|
||||||
free(bufr);
|
|
||||||
close(s);
|
|
||||||
|
|
||||||
|
/***********************************************************************
|
||||||
/***********************************************************************
|
* Call our hook.
|
||||||
* Figure out what to do with the data we just received.
|
**********************************************************************/
|
||||||
**********************************************************************/
|
if ((usehook->hook_function)(bigBufr, size) == 0)
|
||||||
if (!strncmp("untar", filename, 5))
|
|
||||||
{
|
|
||||||
Untar_FromMemory(bigBufr, size);
|
|
||||||
FTPD_SendReply(210, "Untar successful.");
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
FILE *fp;
|
|
||||||
size_t len;
|
|
||||||
size_t written;
|
|
||||||
|
|
||||||
fp = fopen(filename, "w");
|
|
||||||
if (fp == NULL)
|
|
||||||
{
|
{
|
||||||
FTPD_SendReply(440, "Could not open file.");
|
rtems_ftpd_send_reply(210, "File transferred successfully.");
|
||||||
free(bigBufr);
|
|
||||||
return(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
n = 0;
|
|
||||||
written = 0;
|
|
||||||
while (n<size)
|
|
||||||
{
|
|
||||||
len = ((size-n>BUFSIZ)?(BUFSIZ):(size-n));
|
|
||||||
written = fwrite(&bigBufr[n], 1, len, fp);
|
|
||||||
n += written;
|
|
||||||
if (written != len)
|
|
||||||
{
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
fclose(fp);
|
|
||||||
|
|
||||||
if (n == size)
|
|
||||||
{
|
|
||||||
FTPD_SendReply(226, "Transfer complete.");
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
FTPD_SendReply(440, "Error during write.");
|
rtems_ftpd_send_reply(440, "File transfer failed.");
|
||||||
free(bigBufr);
|
}
|
||||||
|
free(bigBufr);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
int fd;
|
||||||
|
size_t written;
|
||||||
|
|
||||||
|
fd = creat(filename, S_IRUSR | S_IWUSR |
|
||||||
|
S_IRGRP | S_IWGRP |
|
||||||
|
S_IROTH | S_IWOTH);
|
||||||
|
if (fd == -1)
|
||||||
|
{
|
||||||
|
rtems_ftpd_send_reply(450, "Could not open file.");
|
||||||
|
close(s);
|
||||||
|
free(bufr);
|
||||||
return(1);
|
return(1);
|
||||||
}
|
}
|
||||||
|
while ((n = read(s, bufr, BUFSIZ)) > 0)
|
||||||
|
{
|
||||||
|
written = write(fd, bufr, n);
|
||||||
|
if (written == -1)
|
||||||
|
{
|
||||||
|
rtems_ftpd_send_reply(450, "Error during write.");
|
||||||
|
close(fd);
|
||||||
|
close(s);
|
||||||
|
free(bufr);
|
||||||
|
return(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
close(fd);
|
||||||
|
close(s);
|
||||||
|
rtems_ftpd_send_reply(226, "Transfer complete.");
|
||||||
}
|
}
|
||||||
|
|
||||||
free(bigBufr);
|
free(bufr);
|
||||||
return(0);
|
return(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**************************************************************************
|
/**************************************************************************
|
||||||
* Function: FTPD_CommandList *
|
* Function: rtems_ftpd_command_list *
|
||||||
**************************************************************************
|
**************************************************************************
|
||||||
* Description: *
|
* Description: *
|
||||||
* *
|
* *
|
||||||
@@ -518,7 +497,7 @@ FTPD_CommandStore(char *filename)
|
|||||||
* 12/01/97 - Creation (JWJ) *
|
* 12/01/97 - Creation (JWJ) *
|
||||||
*************************************************************************/
|
*************************************************************************/
|
||||||
static void
|
static void
|
||||||
FTPD_CommandList(char *fname)
|
rtems_ftpd_command_list(char *fname)
|
||||||
{
|
{
|
||||||
int s;
|
int s;
|
||||||
rtems_status_code sc;
|
rtems_status_code sc;
|
||||||
@@ -532,7 +511,7 @@ FTPD_CommandList(char *fname)
|
|||||||
sc = rtems_task_get_note(RTEMS_SELF, RTEMS_NOTEPAD_0,
|
sc = rtems_task_get_note(RTEMS_SELF, RTEMS_NOTEPAD_0,
|
||||||
(rtems_unsigned32 *)&info);
|
(rtems_unsigned32 *)&info);
|
||||||
|
|
||||||
FTPD_SendReply(150, "ASCII data connection for LIST.");
|
rtems_ftpd_send_reply(150, "ASCII data connection for LIST.");
|
||||||
|
|
||||||
s = socket(AF_INET, SOCK_STREAM, 0);
|
s = socket(AF_INET, SOCK_STREAM, 0);
|
||||||
if (connect(s, (struct sockaddr *)&info->data_addr,
|
if (connect(s, (struct sockaddr *)&info->data_addr,
|
||||||
@@ -548,7 +527,7 @@ FTPD_CommandList(char *fname)
|
|||||||
fname, (info->xfer_mode==TYPE_A)?("\r"):(""));
|
fname, (info->xfer_mode==TYPE_A)?("\r"):(""));
|
||||||
send(s, dirline, strlen(dirline), 0);
|
send(s, dirline, strlen(dirline), 0);
|
||||||
close(s);
|
close(s);
|
||||||
FTPD_SendReply(226, "Transfer complete.");
|
rtems_ftpd_send_reply(226, "Transfer complete.");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
while ((dp = readdir(dirp)) != NULL)
|
while ((dp = readdir(dirp)) != NULL)
|
||||||
@@ -578,7 +557,7 @@ FTPD_CommandList(char *fname)
|
|||||||
closedir(dirp);
|
closedir(dirp);
|
||||||
|
|
||||||
close(s);
|
close(s);
|
||||||
FTPD_SendReply(226, "Transfer complete.");
|
rtems_ftpd_send_reply(226, "Transfer complete.");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -586,7 +565,7 @@ FTPD_CommandList(char *fname)
|
|||||||
* Cheesy way to change directories
|
* Cheesy way to change directories
|
||||||
*/
|
*/
|
||||||
static void
|
static void
|
||||||
FTPD_CWD(char *dir)
|
rtems_ftpd_CWD(char *dir)
|
||||||
{
|
{
|
||||||
rtems_status_code sc;
|
rtems_status_code sc;
|
||||||
FTPD_SessionInfo_t *info = NULL;
|
FTPD_SessionInfo_t *info = NULL;
|
||||||
@@ -597,17 +576,17 @@ FTPD_CWD(char *dir)
|
|||||||
|
|
||||||
if (chdir(dir) == 0)
|
if (chdir(dir) == 0)
|
||||||
{
|
{
|
||||||
FTPD_SendReply(250, "CWD command successful.");
|
rtems_ftpd_send_reply(250, "CWD command successful.");
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
FTPD_SendReply(550, "CWD command failed.");
|
rtems_ftpd_send_reply(550, "CWD command failed.");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**************************************************************************
|
/**************************************************************************
|
||||||
* Function: FTPD_CommandPort *
|
* Function: rtems_ftpd_command_port *
|
||||||
**************************************************************************
|
**************************************************************************
|
||||||
* Description: *
|
* Description: *
|
||||||
* *
|
* *
|
||||||
@@ -630,7 +609,7 @@ FTPD_CWD(char *dir)
|
|||||||
* 12/01/97 - Creation (JWJ) *
|
* 12/01/97 - Creation (JWJ) *
|
||||||
*************************************************************************/
|
*************************************************************************/
|
||||||
static void
|
static void
|
||||||
FTPD_CommandPort(char *bufr)
|
rtems_ftpd_command_port(char *bufr)
|
||||||
{
|
{
|
||||||
char *ip;
|
char *ip;
|
||||||
char *port;
|
char *port;
|
||||||
@@ -656,13 +635,15 @@ FTPD_CommandPort(char *bufr)
|
|||||||
|
|
||||||
|
|
||||||
/**************************************************************************
|
/**************************************************************************
|
||||||
* Function: FTPD_ParseCommand *
|
* Function: rtems_ftpd_parse_command *
|
||||||
**************************************************************************
|
**************************************************************************
|
||||||
* Description: *
|
* Description: *
|
||||||
* *
|
* *
|
||||||
* Here, we parse the commands that have come through the control *
|
* Here, we parse the commands that have come through the control *
|
||||||
* connection. *
|
* connection. *
|
||||||
* *
|
* *
|
||||||
|
* FIXME: This section is somewhat of a hack. We should have a better *
|
||||||
|
* way to parse commands. *
|
||||||
* *
|
* *
|
||||||
* Inputs: *
|
* Inputs: *
|
||||||
* *
|
* *
|
||||||
@@ -678,7 +659,7 @@ FTPD_CommandPort(char *bufr)
|
|||||||
* 12/01/97 - Creation (JWJ) *
|
* 12/01/97 - Creation (JWJ) *
|
||||||
*************************************************************************/
|
*************************************************************************/
|
||||||
static void
|
static void
|
||||||
FTPD_ParseCommand(char *bufr)
|
rtems_ftpd_parse_command(char *bufr)
|
||||||
{
|
{
|
||||||
char fname[255];
|
char fname[255];
|
||||||
rtems_status_code sc;
|
rtems_status_code sc;
|
||||||
@@ -690,71 +671,71 @@ FTPD_ParseCommand(char *bufr)
|
|||||||
|
|
||||||
if (!strncmp("PORT", bufr, 4))
|
if (!strncmp("PORT", bufr, 4))
|
||||||
{
|
{
|
||||||
FTPD_SendReply(200, "PORT command successful.");
|
rtems_ftpd_send_reply(200, "PORT command successful.");
|
||||||
FTPD_CommandPort(&bufr[5]);
|
rtems_ftpd_command_port(&bufr[5]);
|
||||||
}
|
}
|
||||||
else if (!strncmp("RETR", bufr, 4))
|
else if (!strncmp("RETR", bufr, 4))
|
||||||
{
|
{
|
||||||
sscanf(&bufr[5], "%254s", fname);
|
sscanf(&bufr[5], "%254s", fname);
|
||||||
FTPD_CommandRetrieve(fname);
|
rtems_ftpd_command_retrieve(fname);
|
||||||
}
|
}
|
||||||
else if (!strncmp("STOR", bufr, 4))
|
else if (!strncmp("STOR", bufr, 4))
|
||||||
{
|
{
|
||||||
sscanf(&bufr[5], "%254s", fname);
|
sscanf(&bufr[5], "%254s", fname);
|
||||||
FTPD_CommandStore(fname);
|
rtems_ftpd_command_store(fname);
|
||||||
}
|
}
|
||||||
else if (!strncmp("LIST", bufr, 4))
|
else if (!strncmp("LIST", bufr, 4))
|
||||||
{
|
{
|
||||||
if (bufr[5] == '\n')
|
if (bufr[5] == '\n')
|
||||||
{
|
{
|
||||||
FTPD_CommandList(".");
|
rtems_ftpd_command_list(".");
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
sscanf(&bufr[5], "%254s", fname);
|
sscanf(&bufr[5], "%254s", fname);
|
||||||
FTPD_CommandList(fname);
|
rtems_ftpd_command_list(fname);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (!strncmp("USER", bufr, 4))
|
else if (!strncmp("USER", bufr, 4))
|
||||||
{
|
{
|
||||||
FTPD_SendReply(230, "User logged in.");
|
rtems_ftpd_send_reply(230, "User logged in.");
|
||||||
}
|
}
|
||||||
else if (!strncmp("SYST", bufr, 4))
|
else if (!strncmp("SYST", bufr, 4))
|
||||||
{
|
{
|
||||||
FTPD_SendReply(240, "RTEMS");
|
rtems_ftpd_send_reply(240, "RTEMS");
|
||||||
}
|
}
|
||||||
else if (!strncmp("TYPE", bufr, 4))
|
else if (!strncmp("TYPE", bufr, 4))
|
||||||
{
|
{
|
||||||
if (bufr[5] == 'I')
|
if (bufr[5] == 'I')
|
||||||
{
|
{
|
||||||
info->xfer_mode = TYPE_I;
|
info->xfer_mode = TYPE_I;
|
||||||
FTPD_SendReply(200, "Type set to I.");
|
rtems_ftpd_send_reply(200, "Type set to I.");
|
||||||
}
|
}
|
||||||
else if (bufr[5] == 'A')
|
else if (bufr[5] == 'A')
|
||||||
{
|
{
|
||||||
info->xfer_mode = TYPE_A;
|
info->xfer_mode = TYPE_A;
|
||||||
FTPD_SendReply(200, "Type set to A.");
|
rtems_ftpd_send_reply(200, "Type set to A.");
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
info->xfer_mode = TYPE_I;
|
info->xfer_mode = TYPE_I;
|
||||||
FTPD_SendReply(504, "Type not implemented. Set to I.");
|
rtems_ftpd_send_reply(504, "Type not implemented. Set to I.");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (!strncmp("PASS", bufr, 4))
|
else if (!strncmp("PASS", bufr, 4))
|
||||||
{
|
{
|
||||||
FTPD_SendReply(230, "User logged in.");
|
rtems_ftpd_send_reply(230, "User logged in.");
|
||||||
}
|
}
|
||||||
else if (!strncmp("DELE", bufr, 4))
|
else if (!strncmp("DELE", bufr, 4))
|
||||||
{
|
{
|
||||||
sscanf(&bufr[4], "%254s", fname);
|
sscanf(&bufr[4], "%254s", fname);
|
||||||
if (unlink(fname) == 0)
|
if (unlink(fname) == 0)
|
||||||
{
|
{
|
||||||
FTPD_SendReply(257, "DELE successful.");
|
rtems_ftpd_send_reply(257, "DELE successful.");
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
FTPD_SendReply(550, "DELE failed.");
|
rtems_ftpd_send_reply(550, "DELE failed.");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (!strncmp("SITE CHMOD", bufr, 10))
|
else if (!strncmp("SITE CHMOD", bufr, 10))
|
||||||
@@ -764,11 +745,11 @@ FTPD_ParseCommand(char *bufr)
|
|||||||
sscanf(&bufr[11], "%o %254s", &mask, fname);
|
sscanf(&bufr[11], "%o %254s", &mask, fname);
|
||||||
if (chmod(fname, (mode_t)mask) == 0)
|
if (chmod(fname, (mode_t)mask) == 0)
|
||||||
{
|
{
|
||||||
FTPD_SendReply(257, "CHMOD successful.");
|
rtems_ftpd_send_reply(257, "CHMOD successful.");
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
FTPD_SendReply(550, "CHMOD failed.");
|
rtems_ftpd_send_reply(550, "CHMOD failed.");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (!strncmp("RMD", bufr, 3))
|
else if (!strncmp("RMD", bufr, 3))
|
||||||
@@ -776,11 +757,11 @@ FTPD_ParseCommand(char *bufr)
|
|||||||
sscanf(&bufr[4], "%254s", fname);
|
sscanf(&bufr[4], "%254s", fname);
|
||||||
if (rmdir(fname) == 0)
|
if (rmdir(fname) == 0)
|
||||||
{
|
{
|
||||||
FTPD_SendReply(257, "RMD successful.");
|
rtems_ftpd_send_reply(257, "RMD successful.");
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
FTPD_SendReply(550, "RMD failed.");
|
rtems_ftpd_send_reply(550, "RMD failed.");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (!strncmp("MKD", bufr, 3))
|
else if (!strncmp("MKD", bufr, 3))
|
||||||
@@ -788,33 +769,34 @@ FTPD_ParseCommand(char *bufr)
|
|||||||
sscanf(&bufr[4], "%254s", fname);
|
sscanf(&bufr[4], "%254s", fname);
|
||||||
if (mkdir(fname, S_IRWXU | S_IRWXG | S_IRWXO) == 0)
|
if (mkdir(fname, S_IRWXU | S_IRWXG | S_IRWXO) == 0)
|
||||||
{
|
{
|
||||||
FTPD_SendReply(257, "MKD successful.");
|
rtems_ftpd_send_reply(257, "MKD successful.");
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
FTPD_SendReply(550, "MKD failed.");
|
rtems_ftpd_send_reply(550, "MKD failed.");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (!strncmp("CWD", bufr, 3))
|
else if (!strncmp("CWD", bufr, 3))
|
||||||
{
|
{
|
||||||
sscanf(&bufr[4], "%254s", fname);
|
sscanf(&bufr[4], "%254s", fname);
|
||||||
FTPD_CWD(fname);
|
rtems_ftpd_CWD(fname);
|
||||||
}
|
}
|
||||||
else if (!strncmp("PWD", bufr, 3))
|
else if (!strncmp("PWD", bufr, 3))
|
||||||
{
|
{
|
||||||
char *cwd = getcwd(0, 0);
|
char *cwd = getcwd(0, 0);
|
||||||
sprintf(bufr, "\"%s\" is the current directory.", cwd);
|
sprintf(bufr, "\"%s\" is the current directory.", cwd);
|
||||||
FTPD_SendReply(250, bufr);
|
rtems_ftpd_send_reply(250, bufr);
|
||||||
free(cwd);
|
free(cwd);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
FTPD_SendReply(500, "Unrecognized/unsupported command.");
|
rtems_ftpd_send_reply(500, "Unrecognized/unsupported command.");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**************************************************************************
|
/**************************************************************************
|
||||||
* Function: FTPD_Session *
|
* Function: rtems_ftpd_session *
|
||||||
**************************************************************************
|
**************************************************************************
|
||||||
* Description: *
|
* Description: *
|
||||||
* *
|
* *
|
||||||
@@ -827,7 +809,7 @@ FTPD_ParseCommand(char *bufr)
|
|||||||
* *
|
* *
|
||||||
* Inputs: *
|
* Inputs: *
|
||||||
* *
|
* *
|
||||||
* rtems_task_argument arg - The FTPD_Daemon task passes the socket *
|
* rtems_task_argument arg - The daemon task passes the socket *
|
||||||
* which serves as the control connection. *
|
* which serves as the control connection. *
|
||||||
* *
|
* *
|
||||||
* Output: *
|
* Output: *
|
||||||
@@ -839,7 +821,7 @@ FTPD_ParseCommand(char *bufr)
|
|||||||
* 12/01/97 - Creation (JWJ) *
|
* 12/01/97 - Creation (JWJ) *
|
||||||
*************************************************************************/
|
*************************************************************************/
|
||||||
static void
|
static void
|
||||||
FTPD_Session(rtems_task_argument arg)
|
rtems_ftpd_session(rtems_task_argument arg)
|
||||||
{
|
{
|
||||||
char cmd[256];
|
char cmd[256];
|
||||||
rtems_status_code sc;
|
rtems_status_code sc;
|
||||||
@@ -849,7 +831,7 @@ FTPD_Session(rtems_task_argument arg)
|
|||||||
sc = rtems_task_get_note(RTEMS_SELF, RTEMS_NOTEPAD_0,
|
sc = rtems_task_get_note(RTEMS_SELF, RTEMS_NOTEPAD_0,
|
||||||
(rtems_unsigned32 *)&info);
|
(rtems_unsigned32 *)&info);
|
||||||
|
|
||||||
FTPD_SendReply(220, "Erithacus FTP server (Version 1.0) ready.");
|
rtems_ftpd_send_reply(220, FTPD_SERVER_MESSAGE);
|
||||||
|
|
||||||
/***********************************************************************
|
/***********************************************************************
|
||||||
* Set initial directory to "/".
|
* Set initial directory to "/".
|
||||||
@@ -858,7 +840,7 @@ FTPD_Session(rtems_task_argument arg)
|
|||||||
info->xfer_mode = TYPE_A;
|
info->xfer_mode = TYPE_A;
|
||||||
while (1)
|
while (1)
|
||||||
{
|
{
|
||||||
if (recv(info->ctrl_sock, cmd, 256, 0) == -1)
|
if (fgets(cmd, 256, info->ctrl_fp) == NULL)
|
||||||
{
|
{
|
||||||
syslog(LOG_INFO, "ftpd: Connection aborted.");
|
syslog(LOG_INFO, "ftpd: Connection aborted.");
|
||||||
break;
|
break;
|
||||||
@@ -866,16 +848,16 @@ FTPD_Session(rtems_task_argument arg)
|
|||||||
|
|
||||||
if (!strncmp("QUIT", cmd, 4))
|
if (!strncmp("QUIT", cmd, 4))
|
||||||
{
|
{
|
||||||
FTPD_SendReply(221, "Goodbye.");
|
rtems_ftpd_send_reply(221, "Goodbye.");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
FTPD_ParseCommand(cmd);
|
rtems_ftpd_parse_command(cmd);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (close(info->ctrl_sock) < 0)
|
if (fclose(info->ctrl_fp) != 0)
|
||||||
{
|
{
|
||||||
syslog(LOG_ERR, "ftpd: Could not close session.");
|
syslog(LOG_ERR, "ftpd: Could not close session.");
|
||||||
}
|
}
|
||||||
@@ -895,7 +877,7 @@ FTPD_Session(rtems_task_argument arg)
|
|||||||
|
|
||||||
|
|
||||||
/**************************************************************************
|
/**************************************************************************
|
||||||
* Function: FTPD_Daemon *
|
* Function: rtems_ftpd_daemon *
|
||||||
**************************************************************************
|
**************************************************************************
|
||||||
* Description: *
|
* Description: *
|
||||||
* *
|
* *
|
||||||
@@ -918,7 +900,7 @@ FTPD_Session(rtems_task_argument arg)
|
|||||||
* 12/01/97 - Creation (JWJ) *
|
* 12/01/97 - Creation (JWJ) *
|
||||||
*************************************************************************/
|
*************************************************************************/
|
||||||
static void
|
static void
|
||||||
FTPD_Daemon()
|
rtems_ftpd_daemon()
|
||||||
{
|
{
|
||||||
int s;
|
int s;
|
||||||
int s1;
|
int s1;
|
||||||
@@ -941,7 +923,7 @@ FTPD_Daemon()
|
|||||||
}
|
}
|
||||||
|
|
||||||
localAddr.sin_family = AF_INET;
|
localAddr.sin_family = AF_INET;
|
||||||
localAddr.sin_port = FTPD_CONTROL_PORT;
|
localAddr.sin_port = htons(rtems_ftpd_configuration.port);
|
||||||
localAddr.sin_addr.s_addr = INADDR_ANY;
|
localAddr.sin_addr.s_addr = INADDR_ANY;
|
||||||
memset(localAddr.sin_zero, '\0', sizeof(localAddr.sin_zero));
|
memset(localAddr.sin_zero, '\0', sizeof(localAddr.sin_zero));
|
||||||
if (bind(s, (struct sockaddr *)&localAddr,
|
if (bind(s, (struct sockaddr *)&localAddr,
|
||||||
@@ -1002,21 +984,28 @@ FTPD_Daemon()
|
|||||||
/********************************************************************
|
/********************************************************************
|
||||||
* Send the socket on to the new session.
|
* Send the socket on to the new session.
|
||||||
*******************************************************************/
|
*******************************************************************/
|
||||||
info->ctrl_sock = s1;
|
if ((info->ctrl_fp = fdopen(s1, "r+")) == NULL)
|
||||||
sc = rtems_task_set_note(tid, RTEMS_NOTEPAD_0,
|
|
||||||
(rtems_unsigned32)info);
|
|
||||||
sc = rtems_task_start(tid, FTPD_Session, 0);
|
|
||||||
if (sc != RTEMS_SUCCESSFUL)
|
|
||||||
{
|
{
|
||||||
syslog(LOG_ERR, "ftpd: Could not start FTPD session: %s",
|
syslog(LOG_ERR, "ftpd: fdopen() on socket failed.");
|
||||||
rtems_status_text(sc));
|
close(s1);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
sc = rtems_task_set_note(tid, RTEMS_NOTEPAD_0,
|
||||||
|
(rtems_unsigned32)info);
|
||||||
|
sc = rtems_task_start(tid, rtems_ftpd_session, 0);
|
||||||
|
if (sc != RTEMS_SUCCESSFUL)
|
||||||
|
{
|
||||||
|
syslog(LOG_ERR, "ftpd: Could not start FTPD session: %s",
|
||||||
|
rtems_status_text(sc));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**************************************************************************
|
/**************************************************************************
|
||||||
* Function: FTPD_Start *
|
* Function: rtems_ftpd_start *
|
||||||
**************************************************************************
|
**************************************************************************
|
||||||
* Description: *
|
* Description: *
|
||||||
* *
|
* *
|
||||||
@@ -1031,21 +1020,33 @@ FTPD_Daemon()
|
|||||||
* *
|
* *
|
||||||
* Output: *
|
* Output: *
|
||||||
* *
|
* *
|
||||||
* none *
|
* int - RTEMS_SUCCESSFUL on successful start of the daemon. *
|
||||||
* *
|
* *
|
||||||
**************************************************************************
|
**************************************************************************
|
||||||
* Change History: *
|
* Change History: *
|
||||||
* 12/01/97 - Creation (JWJ) *
|
* 12/01/97 - Creation (JWJ) *
|
||||||
*************************************************************************/
|
*************************************************************************/
|
||||||
void
|
int
|
||||||
FTPD_Start(rtems_task_priority priority)
|
rtems_initialize_ftpd()
|
||||||
{
|
{
|
||||||
rtems_status_code sc;
|
rtems_status_code sc;
|
||||||
rtems_id tid;
|
rtems_id tid;
|
||||||
|
|
||||||
|
|
||||||
|
if (rtems_ftpd_configuration.port == 0)
|
||||||
|
{
|
||||||
|
rtems_ftpd_configuration.port = FTPD_CONTROL_PORT;
|
||||||
|
}
|
||||||
|
|
||||||
|
/***********************************************************************
|
||||||
|
* Default FTPD priority.
|
||||||
|
**********************************************************************/
|
||||||
|
if (rtems_ftpd_configuration.priority == 0)
|
||||||
|
{
|
||||||
|
rtems_ftpd_configuration.priority = 40;
|
||||||
|
}
|
||||||
sc = rtems_task_create(rtems_build_name('F', 'T', 'P', 'D'),
|
sc = rtems_task_create(rtems_build_name('F', 'T', 'P', 'D'),
|
||||||
priority, 8*1024,
|
rtems_ftpd_configuration.priority, 8*1024,
|
||||||
RTEMS_PREEMPT | RTEMS_NO_TIMESLICE | RTEMS_NO_ASR |
|
RTEMS_PREEMPT | RTEMS_NO_TIMESLICE | RTEMS_NO_ASR |
|
||||||
RTEMS_INTERRUPT_LEVEL(0),
|
RTEMS_INTERRUPT_LEVEL(0),
|
||||||
RTEMS_NO_FLOATING_POINT | RTEMS_LOCAL,
|
RTEMS_NO_FLOATING_POINT | RTEMS_LOCAL,
|
||||||
@@ -1054,14 +1055,18 @@ FTPD_Start(rtems_task_priority priority)
|
|||||||
{
|
{
|
||||||
syslog(LOG_ERR, "ftpd: Could not create FTP daemon: %s",
|
syslog(LOG_ERR, "ftpd: Could not create FTP daemon: %s",
|
||||||
rtems_status_text(sc));
|
rtems_status_text(sc));
|
||||||
|
return(RTEMS_UNSATISFIED);
|
||||||
}
|
}
|
||||||
|
|
||||||
sc = rtems_task_start(tid, FTPD_Daemon, 0);
|
sc = rtems_task_start(tid, rtems_ftpd_daemon, 0);
|
||||||
if (sc != RTEMS_SUCCESSFUL)
|
if (sc != RTEMS_SUCCESSFUL)
|
||||||
{
|
{
|
||||||
syslog(LOG_ERR, "ftpd: Could not start FTP daemon: %s",
|
syslog(LOG_ERR, "ftpd: Could not start FTP daemon: %s",
|
||||||
rtems_status_text(sc));
|
rtems_status_text(sc));
|
||||||
|
return(RTEMS_UNSATISFIED);
|
||||||
}
|
}
|
||||||
|
|
||||||
syslog(LOG_INFO, "ftpd: FTP daemon started.");
|
syslog(LOG_INFO, "ftpd: FTP daemon started.");
|
||||||
|
return(RTEMS_SUCCESSFUL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -10,17 +10,33 @@
|
|||||||
|
|
||||||
#define FTPD_CONTROL_PORT 21
|
#define FTPD_CONTROL_PORT 21
|
||||||
|
|
||||||
|
typedef int (*rtems_ftpd_hookfunction)(unsigned char *, unsigned long);
|
||||||
|
|
||||||
|
struct rtems_ftpd_hook
|
||||||
|
{
|
||||||
|
char *filename;
|
||||||
|
rtems_ftpd_hookfunction hook_function;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct rtems_ftpd_configuration
|
||||||
|
{
|
||||||
|
rtems_task_priority priority; /* FTPD task priority */
|
||||||
|
unsigned long max_hook_filesize; /* Maximum buffersize */
|
||||||
|
/* for hooks */
|
||||||
|
int port; /* Well-known port */
|
||||||
|
struct rtems_ftpd_hook *hooks; /* List of hooks */
|
||||||
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Reply codes.
|
* Reply codes.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#define PRELIM 1 /* positive preliminary */
|
#define PRELIM 1 /* positive preliminary */
|
||||||
#define COMPLETE 2 /* positive completion */
|
#define COMPLETE 2 /* positive completion */
|
||||||
#define CONTINUE 3 /* positive intermediate */
|
#define CONTINUE 3 /* positive intermediate */
|
||||||
#define TRANSIENT 4 /* transient negative completion */
|
#define TRANSIENT 4 /* transient negative completion */
|
||||||
#define ERROR 5 /* permanent negative completion */
|
#define ERROR 5 /* permanent negative completion */
|
||||||
|
|
||||||
void rtems_ftpd_sTart(rtems_task_priority priority);
|
int rtems_initialize_ftpd();
|
||||||
|
|
||||||
#endif /* __FTPD_H__ */
|
#endif /* __FTPD_H__ */
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user