From d8a039ee18825d1f29e0c020ae6569453fb7bb4f Mon Sep 17 00:00:00 2001 From: patacongo Date: Sun, 5 Feb 2012 17:36:13 +0000 Subject: FTPD daemon and example now build without errors git-svn-id: svn://svn.code.sf.net/p/nuttx/code/trunk@4371 42af7a65-404d-4744-a932-0658087f49c3 --- apps/examples/README.txt | 41 ++- apps/examples/ftpd/Makefile | 9 +- apps/examples/ftpd/ftpd.h | 67 +++- apps/examples/ftpd/ftpd_main.c | 151 +++++++-- apps/include/netutils/ftpd.h | 32 +- apps/netutils/ftpd/ftpd.c | 479 ++++++++++------------------- apps/netutils/ftpd/ftpd.h | 111 ++++--- apps/nshlib/Makefile | 4 +- apps/nshlib/nsh_init.c | 102 ++++++ apps/nshlib/nsh_parse.c | 31 -- nuttx/ChangeLog | 2 +- nuttx/Documentation/NuttxPortingGuide.html | 32 +- nuttx/configs/README.txt | 19 ++ nuttx/configs/stm3240g-eval/README.txt | 20 +- nuttx/configs/stm3240g-eval/nsh/appconfig | 4 +- nuttx/include/netinet/in.h | 53 +++- nuttx/include/pthread.h | 4 +- nuttx/include/semaphore.h | 12 + nuttx/include/sys/socket.h | 83 +++-- 19 files changed, 744 insertions(+), 512 deletions(-) create mode 100644 apps/nshlib/nsh_init.c diff --git a/apps/examples/README.txt b/apps/examples/README.txt index bb401c99a..d598180e5 100644 --- a/apps/examples/README.txt +++ b/apps/examples/README.txt @@ -282,15 +282,42 @@ examples/ftpd configuration if the network is configuration prior to running the example. - If CONFIG_EXAMPELS_FTPD_NONETINIT is not defined, then the following may + NSH always initializes the network so if CONFIG_NSH_BUILTIN_APPS is + defined, so is CONFIG_EXAMPLES_FTPD_NONETINIT (se it does not explicitly + need to be defined in that case): + + CONFIG_NSH_BUILTIN_APPS - Build the FTPD daemon example test as an + NSH built-in function. By default the FTPD daemon will be built + as a standalone application. + + If CONFIG_EXAMPLES_FTPD_NONETINIT is not defined, then the following may be specified to customized the network configuration: - CONFIG_EXAMPLE_FTPD_NOMAC - If the hardware has no MAC address of its - own, define this =y to provide a bogus address for testing. - CONFIG_EXAMPLE_FTPD_IPADDR - The target IP address. Default 10.0.0.2 - CONFIG_EXAMPLE_FTPD_DRIPADDR - The default router address. Default - 10.0.0.1 - CONFIG_EXAMPLE_FTPD_NETMASK - The network mask. Default: 255.255.255.0 + CONFIG_EXAMPLE_FTPD_NOMAC - If the hardware has no MAC address of its + own, define this =y to provide a bogus address for testing. + CONFIG_EXAMPLE_FTPD_IPADDR - The target IP address. Default 10.0.0.2 + CONFIG_EXAMPLE_FTPD_DRIPADDR - The default router address. Default + 10.0.0.1 + CONFIG_EXAMPLE_FTPD_NETMASK - The network mask. Default: 255.255.255.0 + + Other required configuration settings: Of course TCP networking support + is required. But here are a couple that are less obvious: + + CONFIG_DISABLE_PTHREAD - pthread support is required + CONFIG_DISABLE_POLL - poll() support is required + + Other FTPD configuration options thay may be of interest: + + CONFIG_FTPD_VENDORID - The vendor name to use in FTP communications. + Default: "NuttX" + CONFIG_FTPD_SERVERID - The server name to use in FTP communications. + Default: "NuttX FTP Server" + CONFIG_FTPD_CMDBUFFERSIZE - The maximum size of one command. Default: + 512 bytes. + CONFIG_FTPD_DATABUFFERSIZE - The size of the I/O buffer for data + transfers. Default: 2048 bytes. + CONFIG_FTPD_WORKERSTACKSIZE - The stacksize to allocate for each + FTP daemon worker thread. Default: 2048 bytes. The appconfig file (apps/.config) should include: diff --git a/apps/examples/ftpd/Makefile b/apps/examples/ftpd/Makefile index d3ccda7cc..4eb25c9e9 100644 --- a/apps/examples/ftpd/Makefile +++ b/apps/examples/ftpd/Makefile @@ -56,12 +56,6 @@ endif ROOTDEPPATH = --dep-path . -# Buttons built-in application info - -APPNAME = ftpd -PRIORITY = SCHED_PRIORITY_DEFAULT -STACKSIZE = 2048 - # Common build VPATH = @@ -84,7 +78,8 @@ $(COBJS): %$(OBJEXT): %.c .context: ifeq ($(CONFIG_NSH_BUILTIN_APPS),y) - $(call REGISTER,$(APPNAME),$(PRIORITY),$(STACKSIZE),$(APPNAME)_main) + $(call REGISTER,ftpd_start,SCHED_PRIORITY_DEFAULT,2048,ftpd_start) + $(call REGISTER,ftpd_stop,SCHED_PRIORITY_DEFAULT,2048,ftpd_stop) @touch $@ endif diff --git a/apps/examples/ftpd/ftpd.h b/apps/examples/ftpd/ftpd.h index 619a9fa51..98ee3b3b6 100644 --- a/apps/examples/ftpd/ftpd.h +++ b/apps/examples/ftpd/ftpd.h @@ -35,6 +35,16 @@ #ifndef __APPS_EXAMPLES_FTPD_FTPD_H #define __APPS_EXAMPLES_FTPD_FTPD_H +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +#include + +#include +#include +#include + /**************************************************************************** * Pre-processor Definitions ****************************************************************************/ @@ -48,7 +58,7 @@ * configuration if the network is configuration prior to running the * example. * - * If CONFIG_EXAMPELS_FTPD_NONETINIT is not defined, then the following may + * If CONFIG_EXAMPLES_FTPD_NONETINIT is not defined, then the following may * be specified to customized the network configuration: * * CONFIG_EXAMPLE_FTPD_NOMAC - If the hardware has no MAC address of its @@ -75,21 +85,33 @@ # define CONFIG_EXAMPLES_FTPD_CLIENTSTACKSIZE 2048 #endif -#ifndef CONFIG_EXAMPLE_FTPD_IPADDR -# define CONFIG_EXAMPLE_FTPD_IPADDR 0x0a000002 -#endif -#ifndef CONFIG_EXAMPLE_FTPD_DRIPADDR -# define CONFIG_EXAMPLE_FTPD_DRIPADDR 0x0a000002 +/* NSH always initializes the network */ + +#if defined(CONFIG_NSH_BUILTIN_APPS) && !defined(CONFIG_EXAMPLES_FTPD_NONETINIT) +# define CONFIG_EXAMPLES_FTPD_NONETINIT 1 #endif -#ifndef CONFIG_EXAMPLE_FTPD_NETMASK -# define CONFIG_EXAMPLE_FTPD_NETMASK 0xffffff00 + +#ifdef CONFIG_EXAMPLES_FTPD_NONETINIT +# undef CONFIG_EXAMPLE_FTPD_IPADDR +# undef CONFIG_EXAMPLE_FTPD_DRIPADDR +# undef CONFIG_EXAMPLE_FTPD_NETMASK +#else +# ifndef CONFIG_EXAMPLE_FTPD_IPADDR +# define CONFIG_EXAMPLE_FTPD_IPADDR 0x0a000002 +# endif +# ifndef CONFIG_EXAMPLE_FTPD_DRIPADDR +# define CONFIG_EXAMPLE_FTPD_DRIPADDR 0x0a000001 +# endif +# ifndef CONFIG_EXAMPLE_FTPD_NETMASK +# define CONFIG_EXAMPLE_FTPD_NETMASK 0xffffff00 +# endif #endif /* Is this being built as an NSH built-in application? */ #ifdef CONFIG_NSH_BUILTIN_APPS -# define MAIN_NAME ftpd_main -# define MAIN_STRING "ftpd_main: " +# define MAIN_NAME ftpd_start +# define MAIN_STRING "ftpd_start: " #else # define MAIN_NAME user_start # define MAIN_STRING "user_start: " @@ -99,6 +121,8 @@ * Public Types ****************************************************************************/ +/* This structure describes one entry in a table of accounts */ + struct fptd_account_s { uint8_t flags; @@ -107,17 +131,34 @@ struct fptd_account_s FAR const char *home; }; +/* To minimize the probability of name collisitions, all FTPD example + * global data is maintained in single structure. + */ + struct ftpd_globals_s { - bool initialized; - volatile bool stop; + bool initialized; /* True: Networking is initialized. The + * network must be initialized only once. + */ +#ifdef CONFIG_NSH_BUILTIN_APPS + volatile bool stop; /* True: Request daemon to exit */ + volatile bool running; /* True: The daemon is running */ +#endif + pid_t pid; /* Task ID of the FTPD daemon. The value + * -1 is a redundant indication that the + * daemon is not running. + */ }; /**************************************************************************** * Public Function Prototypes ****************************************************************************/ -extern struct ftpd_globls_s g_ftpdglobls; +/* To minimize the probability of name collisitions, all FTPD example + * global data is maintained in a single instance of a structure. + */ + +extern struct ftpd_globals_s g_ftpdglob; /**************************************************************************** * Public Function Prototypes diff --git a/apps/examples/ftpd/ftpd_main.c b/apps/examples/ftpd/ftpd_main.c index ee3481d80..1f43e317c 100755 --- a/apps/examples/ftpd/ftpd_main.c +++ b/apps/examples/ftpd/ftpd_main.c @@ -34,6 +34,20 @@ * Included Files ****************************************************************************/ +#include + +#include +#include +#include +#include +#include +#include + +#include + +#include +#include + #include "ftpd.h" /**************************************************************************** @@ -48,14 +62,24 @@ static const struct fptd_account_s g_ftpdaccounts[] = }; #define NACCOUNTS (sizeof(g_ftpdaccounts) / sizeof(struct fptd_account_s)) +/**************************************************************************** + * Public Data + ****************************************************************************/ + +/* To minimize the probability of name collisitions, all FTPD example + * global data is maintained in a single instance of a structure. + */ + +struct ftpd_globals_s g_ftpdglob; + /**************************************************************************** * Private Functions ****************************************************************************/ /**************************************************************************** - * Name: shell_netinit + * Name: fptd_netinit ****************************************************************************/ -static void shell_netinit(void) +static void fptd_netinit(void) { #ifndef CONFIG_EXAMPLES_FTPD_NONETINIT struct in_addr addr; @@ -98,14 +122,22 @@ static void shell_netinit(void) static void ftpd_accounts(FTPD_SESSION handle) { - FAR onst struct fptd_account_s *account; + FAR const struct fptd_account_s *account; int i; + printf("Adding accounts:\n"); for (i = 0; i < NACCOUNTS; i++) { account = &g_ftpdaccounts[i]; - ftpd_add_user(handle, account->flags, account->user, - account->password, account->home); + + printf("%d. %s account: USER=%s PASSWORD=%s HOME=%s\n", + (account->flags & FTPD_ACCOUNTFLAG_SYSTEM) != 0 ? "Root" : "User", + (account->user) ? "(none)" : account->user, + (account->password) ? "(none)" : account->password, + (account->home) ? "(none)" : account->home); + + ftpd_adduser(handle, account->flags, account->user, + account->password, account->home); } } @@ -118,12 +150,24 @@ int ftpd_daemon(int s_argc, char **s_argv) FTPD_SESSION handle; int ret; + /* The FTPD daemon has been started */ + +#ifdef CONFIG_NSH_BUILTIN_APPS + g_ftpdglob.running = true; +#endif + printf("FTP daemon [%d] started\n", g_ftpdglob.pid); + /* Open FTPD */ handle = ftpd_open(); if (!handle) { - ndbg("Failed to open FTPD\n"); + printf("FTP daemon [%d] failed to open FTPD\n", g_ftpdglob.pid); +#ifdef CONFIG_NSH_BUILTIN_APPS + g_ftpdglob.running = false; + g_ftpdglob.stop = false; +#endif + g_ftpdglob.pid = -1; return EXIT_FAILURE; } @@ -131,16 +175,33 @@ int ftpd_daemon(int s_argc, char **s_argv) (void)ftpd_accounts(handle); - /* Then drive the FTPD server */ + /* Then drive the FTPD server. */ - while (g_ftpdglobls.stop == 0) +#ifdef CONFIG_NSH_BUILTIN_APPS + while (g_ftpdglob.stop == 0) +#else + for (;;) +#endif { - (void)ftpd_run(handle, 1000); + /* If ftpd_session returns success, it means that a new FTP session + * has been started. + */ + + ret = ftpd_session(handle, 1000); + printf("FTP daemon [%d] ftpd_session returned %d\n", g_ftpdglob.pid, ret); } - /* Close the FTPD server and exit */ + /* Close the FTPD server and exit (we can get here only if + * CONFIG_NSH_BUILTIN_APPS is defined). + */ +#ifdef CONFIG_NSH_BUILTIN_APPS + printf("FTP daemon [%d] stopping\n", g_ftpdglob.pid); + g_ftpdglob.running = false; + g_ftpdglob.stop = false; + g_ftpdglob.pid = -1; ftpd_close(handle); +#endif return EXIT_SUCCESS; } @@ -148,44 +209,76 @@ int ftpd_daemon(int s_argc, char **s_argv) * Public Functions ****************************************************************************/ /**************************************************************************** - * Name: user_start/ftpd_main + * Name: user_start/ftpd_start ****************************************************************************/ int MAIN_NAME(int s_argc, char **s_argv) { - FTPD_SESSION handle; - pid_t pid; - int ret; - /* Check if we have already initialized the network */ - if (!g_ftpdglobls.initialized) + if (!g_ftpdglob.initialized) { /* Bring up the network */ - ret = ftpd_netinit(); - if (ret < 0) + printf("Initializing the network\n"); + fptd_netinit(); + + /* Initialize daemon state */ + + g_ftpdglob.initialized = true; + g_ftpdglob.pid = -1; +#ifdef CONFIG_NSH_BUILTIN_APPS + g_ftpdglob.stop = false; + g_ftpdglob.running = false; +#endif + } + + /* Then start the new daemon (if it is not already running) */ + +#ifdef CONFIG_NSH_BUILTIN_APPS + if (g_ftpdglob.stop && g_ftpdglob.running) + { + printf("Waiting for FTP daemon [%d] to stop\n", g_ftpdglob.pid); + return EXIT_FAILURE; + } + else +#endif + if (!g_ftpdglob.running) + { + printf("Starting the FTP daemon\n"); + g_ftpdglob.pid = TASK_CREATE("FTP daemon", CONFIG_EXAMPLES_FTPD_PRIO, + CONFIG_EXAMPLES_FTPD_STACKSIZE, + ftpd_daemon, NULL); + if (g_ftpdglob.pid < 0) { - ndbg("Failed to initialize the network\n"); + printf("Failed to start the FTP daemon: %d\n", errno); return EXIT_FAILURE; } - - g_ftpdglobls.initialized = true; - g_ftpdglobls.stop = false; } + else + { + printf("FTP daemon [%d] is running\n", g_ftpdglob.pid); + } + + return EXIT_SUCCESS; +} - /* Then start the new daemon */ +/**************************************************************************** + * Name: ftpd_stop + ****************************************************************************/ - g_telnetdcommon.daemon = daemon; - pid = TASK_CREATE("Telnet daemon", CONFIG_EXAMPLES_FTPD_PRIO, - CONFIG_EXAMPLES_FTPD_STACKSIZE, ftpd_daemon, NULL); - if (pid < 0) +#ifdef CONFIG_NSH_BUILTIN_APPS +int ftpd_stop(int s_argc, char **s_argv) +{ + if (!g_ftpdglob.initialized || g_ftpdglob.running) { - ndbg("Failed to start the telnet daemon: %d\n", errno); + printf("The FTP daemon not running\n"); return EXIT_FAILURE; } - printf("The FTP daemon is running, pid=%d\n", pid); + printf("Stopping the FTP daemon, pid=%d\n", g_ftpdglob.pid); + g_ftpdglob.stop = true; return EXIT_SUCCESS; } +#endif diff --git a/apps/include/netutils/ftpd.h b/apps/include/netutils/ftpd.h index 870b5cf94..f7581c89e 100755 --- a/apps/include/netutils/ftpd.h +++ b/apps/include/netutils/ftpd.h @@ -48,11 +48,34 @@ * Pre-processor Definitions ****************************************************************************/ /* Configuration ************************************************************/ +/* Required configuration settings: Of course TCP networking support is + * required. But here are a couple that are less obvious: + * + * CONFIG_DISABLE_PTHREAD - pthread support is required + * CONFIG_DISABLE_POLL - poll() support is required + * + * Other FTPD configuration options thay may be of interest: + * + * CONFIG_FTPD_VENDORID - The vendor name to use in FTP communications. + * Default: "NuttX" + * CONFIG_FTPD_SERVERID - The server name to use in FTP communications. + * Default: "NuttX FTP Server" + * CONFIG_FTPD_CMDBUFFERSIZE - The maximum size of one command. Default: + * 512 bytes. + * CONFIG_FTPD_DATABUFFERSIZE - The size of the I/O buffer for data + * transfers. Default: 2048 bytes. + * CONFIG_FTPD_WORKERSTACKSIZE - The stacksize to allocate for each + * FTP daemon worker thread. Default: 2048 bytes. + */ #ifdef CONFIG_DISABLE_PTHREAD # error "pthread support is required (CONFIG_DISABLE_PTHREAD=n)" #endif +#ifdef CONFIG_DISABLE_POLL +# error "poll() support is required (CONFIG_DISABLE_POLL=n)" +#endif + #ifndef CONFIG_FTPD_VENDORID # define CONFIG_FTPD_VENDORID "NuttX" #endif @@ -73,6 +96,13 @@ # define CONFIG_FTPD_WORKERSTACKSIZE 2048 #endif +/* Interface definitions ****************************************************/ + +#define FTPD_ACCOUNTFLAG_NONE (0) +#define FTPD_ACCOUNTFLAG_ADMIN (1 << 0) +#define FTPD_ACCOUNTFLAG_SYSTEM (1 << 1) +#define FTPD_ACCOUNTFLAG_GUEST (1 << 2) + /**************************************************************************** * Public Types ****************************************************************************/ @@ -123,7 +153,7 @@ EXTERN FTPD_SESSION ftpd_open(void); * Input Parameters: * handle - A handle previously returned by ftpd_open * accountflags - The characteristics of this user (see FTPD_ACCOUNTFLAGS_* - * defintiions. + * definitions above). * user - The user login name. May be NULL indicating that no login is * required. * passwd - The user password. May be NULL indicating that no password diff --git a/apps/netutils/ftpd/ftpd.c b/apps/netutils/ftpd/ftpd.c index fa15afeec..3dead6cb1 100755 --- a/apps/netutils/ftpd/ftpd.c +++ b/apps/netutils/ftpd/ftpd.c @@ -7,8 +7,8 @@ * Includes original code as well as logic adapted from hwport_ftpd, written * by Jaehyuk Cho which is released under a BSD license. * - * Copyright (C) HWPORT.COM. All rights reserved. - * Author: JAEHYUK CHO + * Copyright (C) hwport.com. All rights reserved. + * Author: Jaehyuk Cho * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -46,19 +46,32 @@ #include #include +#include #include +#include +#include +#include #include +#include +#include +#include +#include #include +#include #include +#include + #include "ftpd.h" /**************************************************************************** * Pre-processor Definitions ****************************************************************************/ +#define __NUTTX__ 1 /* Flags some unusual NuttX dependencies */ + /**************************************************************************** * Private Function Prototypes ****************************************************************************/ @@ -86,11 +99,9 @@ static FAR char *ftpd_strtok(bool skipspace, FAR const char *delimiters, FAR char **str); static FAR char *ftpd_strtok_alloc(bool skipspace, FAR const char *delimiters, FAR const char **str); -static int ftpd_patternmatch(FAR const char *pattern, FAR const char *str); /* Socket helpers */ -static int ftpd_getprotocol(FAR const char *protocol) static int ftpd_rxpoll(int sd, int timeout); static int ftpd_txpoll(int sd, int timeout); static int ftpd_accept(int sd, FAR void *addr, FAR socklen_t *addrlen, @@ -115,13 +126,13 @@ static FAR struct ftpd_pathnode_s * ftpd_nodeappend(FAR struct ftpd_pathnode_s *head, FAR struct ftpd_pathnode_s *node, bool override); static int ftpd_getpath(FAR struct ftpd_session_s *session, - FAR const char *chdirectory, FAR char **abspath, + FAR const char *path, FAR char **abspath, FAR char **workpath); /* Commmand helpers */ static int ftpd_changedir(FAR struct ftpd_session_s *session, - FAR char *rempath); + FAR const char *rempath); static off_t ftpd_offsatoi(FAR const char *filename, off_t offset); static int ftpd_stream(FAR struct ftpd_session_s *session, int cmdtype); static uint8_t ftpd_listoption(FAR char **param); @@ -224,7 +235,7 @@ static const struct ftpd_cmd_s g_ftpdcmdtab[] = {"OPTS", ftpd_command_opts, FTPD_CMDFLAG_LOGIN}, /* OPTS