diff --git a/ChangeLog b/ChangeLog
index f35cef7ead..a3ebf96e79 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -450,4 +450,5 @@
* Correct IP checksum calculation in ICMP and UDP message send logic.
* NSH: Created an HTML document and a more detailed README file describing NSH.
* Added basic TFTP client logic (netutils/tftpc). Untested as of initial check-in.
+ * NSH: Add get and put commands to support TFTP get and put operations.
diff --git a/Documentation/NuttShell.html b/Documentation/NuttShell.html
index c689cbb468..e9d363dc97 100644
--- a/Documentation/NuttShell.html
+++ b/Documentation/NuttShell.html
@@ -8,7 +8,7 @@
pwd |
!CONFIG_DISABLE_ENVIRON && CONFIG_NFILE_DESCRIPTORS > 0 |
@@ -1602,6 +1692,7 @@ usleep <usec>
Environment Variables
exec
exit
+ get
Greeting
@@ -1623,6 +1714,7 @@ usleep <usec>
ping
Prompt
ps
+ put
pwd
PWD
Re-directed commands
diff --git a/Documentation/NuttX.html b/Documentation/NuttX.html
index d8edf1eb2c..2e936dee9e 100644
--- a/Documentation/NuttX.html
+++ b/Documentation/NuttX.html
@@ -1077,6 +1077,7 @@ nuttx-0.3.14 2008-xx-xx Gregory Nutt <spudmonkey@racsa.co.cr>
* Correct IP checksum calculation in ICMP and UDP message send logic.
* NSH: Created an HTML document and a more detailed README file describing NSH.
* Added basic TFTP client logic (netutils/tftpc). Untested as of initial check-in.
+ * NSH: Add get and put commands to support TFTP get and put operations.
pascal-0.1.3 2008-xx-xx Gregory Nutt <spudmonkey@racsa.co.cr>
diff --git a/examples/nsh/README.txt b/examples/nsh/README.txt
index 366be8a3ce..fd0c4884b2 100644
--- a/examples/nsh/README.txt
+++ b/examples/nsh/README.txt
@@ -173,6 +173,18 @@ o exit
using the 'exec' command') and you would like to have NSH out of the
way.
+o get [-b|-n] [-f ] -h
+
+ Copy the file at from the host whose IP address is
+ identified by . Other options:
+
+ -f
+ The file will be saved relative to the current working directory
+ unless is provided.
+ -b|-n
+ Selects either binary ("octect") or test ("netascii") transfer
+ mode. Default: text.
+
o help
Presents summary information about each command to console.
@@ -393,6 +405,18 @@ o ping [-c ] [-i ]
10 packets transmitted, 10 received, 0% packet loss, time 10190 ms
nsh>
+o put [-b|-n] [-f ] -h
+
+ Copy the file at to the host whose IP address is
+ identified by . Other options:
+
+ -f
+ The file will be saved with the same name on the host unless
+ unless is provided.
+ -b|-n
+ Selects either binary ("octect") or test ("netascii") transfer
+ mode. Default: text.
+
o pwd
Show the current working directory.
@@ -511,6 +535,7 @@ Command Dependencies on Configuration Settings
echo --
exec --
exit --
+ get CONFIG_NET && CONFIG_NET_UDP && CONFIG_NFILE_DESCRIPTORS > 0
help --
ifconfig CONFIG_NET
ls CONFIG_NFILE_DESCRIPTORS > 0
@@ -522,6 +547,7 @@ Command Dependencies on Configuration Settings
mount !CONFIG_DISABLE_MOUNTPOINT && CONFIG_NFILE_DESCRIPTORS > 0 && CONFIG_FS_FAT
ping CONFIG_NET && CONFIG_NET_ICMP && CONFIG_NET_ICMP_PING && !CONFIG_DISABLE_CLOCK && !CONFIG_DISABLE_SIGNALS
ps --
+ put CONFIG_NET && CONFIG_NET_UDP && CONFIG_NFILE_DESCRIPTORS > 0
pwd !CONFIG_DISABLE_ENVIRON && CONFIG_NFILE_DESCRIPTORS > 0
rm !CONFIG_DISABLE_MOUNTPOINT && CONFIG_NFILE_DESCRIPTORS > 0
rmdir !CONFIG_DISABLE_MOUNTPOINT && CONFIG_NFILE_DESCRIPTORS > 0
diff --git a/examples/nsh/nsh.h b/examples/nsh/nsh.h
index 861be30c2d..f468a264a4 100644
--- a/examples/nsh/nsh.h
+++ b/examples/nsh/nsh.h
@@ -73,9 +73,11 @@
*/
#ifdef CONFIG_EXAMPLES_NSH_STRERROR
-# define NSH_ERRNO strerror(errno)
+# define NSH_ERRNO strerror(errno)
+# define NSH_ERRNO_OF(err) strerror(err)
#else
-# define NSH_ERRNO errno
+# define NSH_ERRNO (errno)
+# define NSH_ERRNO_OF(err) (err)
#endif
/* Maximum size of one command line (telnet or serial) */
@@ -298,6 +300,10 @@ extern int cmd_lbracket(FAR struct nsh_vtbl_s *vtbl, int argc, char **argv);
#if defined(CONFIG_NET)
extern int cmd_ifconfig(FAR struct nsh_vtbl_s *vtbl, int argc, char **argv);
+#if defined(CONFIG_NET_UDP) && CONFIG_NFILE_DESCRIPTORS > 0
+ extern int cmd_get(FAR struct nsh_vtbl_s *vtbl, int argc, char **argv);
+ extern int cmd_put(FAR struct nsh_vtbl_s *vtbl, int argc, char **argv);
+#endif
#if defined(CONFIG_NET_ICMP) && defined(CONFIG_NET_ICMP_PING) && \
!defined(CONFIG_DISABLE_CLOCK) && !defined(CONFIG_DISABLE_SIGNALS)
extern int cmd_ping(FAR struct nsh_vtbl_s *vtbl, int argc, char **argv);
diff --git a/examples/nsh/nsh_main.c b/examples/nsh/nsh_main.c
index ba7ad389fc..f2890159c6 100644
--- a/examples/nsh/nsh_main.c
+++ b/examples/nsh/nsh_main.c
@@ -145,6 +145,9 @@ static const struct cmdmap_s g_cmdmap[] =
#endif
{ "exec", cmd_exec, 2, 3, "" },
{ "exit", cmd_exit, 1, 1, NULL },
+#if defined(CONFIG_NET_UDP) && CONFIG_NFILE_DESCRIPTORS > 0
+ { "get", cmd_get, 4, 7, "[-b|-n] [-f ] -h " },
+#endif
{ "help", cmd_help, 1, 1, NULL },
#ifdef CONFIG_NET
{ "ifconfig", cmd_ifconfig, 1, 1, NULL },
@@ -173,6 +176,9 @@ static const struct cmdmap_s g_cmdmap[] =
!defined(CONFIG_DISABLE_CLOCK) && !defined(CONFIG_DISABLE_SIGNALS)
{ "ping", cmd_ping, 2, 6, "[-c ] [-i ] " },
#endif
+#if defined(CONFIG_NET_UDP) && CONFIG_NFILE_DESCRIPTORS > 0
+ { "put", cmd_put, 4, 7, "[-b|-n] [-f ] -h " },
+#endif
#if CONFIG_NFILE_DESCRIPTORS > 0 && !defined(CONFIG_DISABLE_ENVIRON)
{ "pwd", cmd_pwd, 1, 1, NULL },
#endif
@@ -1122,7 +1128,7 @@ int nsh_parse(FAR struct nsh_vtbl_s *vtbl, char *cmdline)
ret = pthread_create(&thread, &attr, nsh_child, (pthread_addr_t)args);
if (ret != 0)
{
- nsh_output(vtbl, g_fmtcmdfailed, cmd, "pthread_create", ret);
+ nsh_output(vtbl, g_fmtcmdfailed, cmd, "pthread_create", NSH_ERRNO_OF(ret));
nsh_releaseargs(args);
nsh_release(bkgvtbl);
goto errout;
diff --git a/examples/nsh/nsh_netcmds.c b/examples/nsh/nsh_netcmds.c
index 01f472a319..33eeb9966b 100644
--- a/examples/nsh/nsh_netcmds.c
+++ b/examples/nsh/nsh_netcmds.c
@@ -44,7 +44,10 @@
#include
#include
#include
+#include
#include
+#include
+#include
#include
#include
@@ -54,12 +57,17 @@
#include
#ifdef CONFIG_NET_STATISTICS
-#include
+# include
#endif
#if defined(CONFIG_NET_ICMP) && defined(CONFIG_NET_ICMP_PING) && \
!defined(CONFIG_DISABLE_CLOCK) && !defined(CONFIG_DISABLE_SIGNALS)
-#include
+# include
+#endif
+
+#if defined(CONFIG_NET_UDP) && CONFIG_NFILE_DESCRIPTORS > 0
+# include
+# include
#endif
#include "nsh.h"
@@ -74,6 +82,17 @@
* Private Types
****************************************************************************/
+#if defined(CONFIG_NET_UDP) && CONFIG_NFILE_DESCRIPTORS > 0
+struct tftpc_args_s
+{
+ boolean binary; /* TRUE:binary ("octect") FALSE:text ("netascii") */
+ boolean allocated; /* TRUE: destpath is allocated */
+ char *destpath; /* Path at destination */
+ const char *srcpath; /* Path at src */
+ in_addr_t ipaddr; /* Host IP address */
+};
+#endif
+
/****************************************************************************
* Private Function Prototypes
****************************************************************************/
@@ -242,10 +261,159 @@ int ifconfig_callback(FAR struct uip_driver_s *dev, void *arg)
return OK;
}
+/****************************************************************************
+ * Name: tftpc_parseargs
+ ****************************************************************************/
+
+#if defined(CONFIG_NET_UDP) && CONFIG_NFILE_DESCRIPTORS > 0
+int tftpc_parseargs(FAR struct nsh_vtbl_s *vtbl, int argc, char **argv,
+ struct tftpc_args_s *args)
+{
+ FAR const char *fmt = g_fmtarginvalid;
+ int option;
+
+ /* Get the ping options */
+
+ memset(args, 0, sizeof(struct tftpc_args_s));
+ while ((option = getopt(argc, argv, ":bnf:h:")) != ERROR)
+ {
+ switch (option)
+ {
+ case 'b':
+ args->binary = TRUE;
+ break;
+
+ case 'n':
+ args->binary = FALSE;
+ break;
+
+ case 'f':
+ args->destpath = optarg;
+ break;
+
+ case 'h':
+ if (!uiplib_ipaddrconv(optarg, (FAR unsigned char*)&args->ipaddr))
+ {
+ nsh_output(vtbl, g_fmtarginvalid, argv[0]);
+ goto errout;
+ }
+ break;
+
+ case ':':
+ fmt = g_fmtargrequired;
+
+ case '?':
+ default:
+ goto errout;
+ }
+ }
+
+ /* There should be exactly on parameter left on the command-line */
+
+ if (optind == argc-1)
+ {
+ args->srcpath = argv[optind];
+ }
+ else if (optind >= argc)
+ {
+ fmt = g_fmttoomanyargs;
+ goto errout;
+ }
+ else
+ {
+ fmt = g_fmtargrequired;
+ goto errout;
+ }
+
+ /* The HOST IP address is also required */
+
+ if (!args->ipaddr)
+ {
+ fmt = g_fmtargrequired;
+ goto errout;
+ }
+
+ /* If the destpath was not provided, then we have do a little work. */
+
+ if (!args->destpath)
+ {
+ char *tmp1;
+ char *tmp2;
+
+ /* Copy the srcpath... baseanme might modify it */
+
+ fmt = g_fmtcmdoutofmemory;
+ tmp1 = strdup(args->srcpath);
+ if (!tmp1)
+ {
+ goto errout;
+ }
+
+ /* Get the basename of the srcpath */
+
+ tmp2 = basename(tmp1);
+ if (!tmp2)
+ {
+ free(tmp1);
+ goto errout;
+ }
+
+ /* Use that basename as the destpath */
+
+ args->destpath = strdup(tmp2);
+ free(tmp1);
+ if (!args->destpath)
+ {
+ goto errout;
+ }
+ args->allocated = TRUE;
+ }
+
+ return OK;
+
+errout:
+ nsh_output(vtbl, fmt, argv[0]);
+ return ERROR;
+}
+#endif
+
/****************************************************************************
* Public Functions
****************************************************************************/
+/****************************************************************************
+ * Name: cmd_get
+ ****************************************************************************/
+
+#if defined(CONFIG_NET_UDP) && CONFIG_NFILE_DESCRIPTORS > 0
+int cmd_get(FAR struct nsh_vtbl_s *vtbl, int argc, char **argv)
+{
+ struct tftpc_args_s args;
+
+ /* Parse the input parameter list */
+
+ if (tftpc_parseargs(vtbl, argc, argv, &args) != OK)
+ {
+ return ERROR;
+ }
+
+ /* Then perform the TFTP get operation */
+
+ if (tftpget(args.srcpath, args.destpath, args.ipaddr, args.binary) != OK)
+ {
+ nsh_output(vtbl, g_fmtcmdfailed, argv[0], "tftpget", NSH_ERRNO);
+ }
+
+ /* Release any allocated memory */
+
+ if (args.allocated)
+ {
+ free(args.destpath);
+ }
+ return OK;
+}
+#endif
+
/****************************************************************************
* Name: cmd_ifconfig
****************************************************************************/
@@ -403,4 +571,44 @@ errout:
return ERROR;
}
#endif /* CONFIG_NET_ICMP && CONFIG_NET_ICMP_PING */
+
+/****************************************************************************
+ * Name: cmd_put
+ ****************************************************************************/
+
+#if defined(CONFIG_NET_UDP) && CONFIG_NFILE_DESCRIPTORS > 0
+int cmd_put(FAR struct nsh_vtbl_s *vtbl, int argc, char **argv)
+{
+ struct tftpc_args_s args;
+ char *fullpath;
+
+ /* Parse the input parameter list */
+
+ if (tftpc_parseargs(vtbl, argc, argv, &args) != OK)
+ {
+ return ERROR;
+ }
+
+ /* Get the full path to the local file */
+
+ fullpath = nsh_getfullpath(vtbl, args.srcpath);
+
+ /* Then perform the TFTP put operation */
+
+ if (tftpput(fullpath, args.destpath, args.ipaddr, args.binary) != OK)
+ {
+ nsh_output(vtbl, g_fmtcmdfailed, argv[0], "tftpput", NSH_ERRNO);
+ }
+
+ /* Release any allocated memory */
+
+ if (args.allocated)
+ {
+ free(args.destpath);
+ }
+ free(fullpath);
+ return OK;
+}
+#endif
+
#endif /* CONFIG_NET */
diff --git a/netutils/tftpc/tftpc_get.c b/netutils/tftpc/tftpc_get.c
index 49c39a2cbb..bb2f96267b 100644
--- a/netutils/tftpc/tftpc_get.c
+++ b/netutils/tftpc/tftpc_get.c
@@ -323,7 +323,7 @@ int tftpget(const char *remote, const char *local, in_addr_t addr, boolean binar
*/
#if CONFIG_NETUTILS_TFTP_ACKPACKETS > 1
- if (ndatabytes < blockno != lastacked)
+ if (ndatabytes < TFTP_DATASIZE && blockno != lastacked)
{
len = tftp_mkackpacket(packet, blockno);
ret = tftp_sendto(sd, packet, len, &server);
diff --git a/netutils/tftpc/tftpc_put.c b/netutils/tftpc/tftpc_put.c
index 73004bdbc2..1d19a2d749 100644
--- a/netutils/tftpc/tftpc_put.c
+++ b/netutils/tftpc/tftpc_put.c
@@ -402,7 +402,7 @@ int tftpput(const char *local, const char *remote, in_addr_t addr, boolean binar
#if CONFIG_NETUTILS_TFTP_ACKPACKETS > 1
/* Construct the next data packet */
- packetlen = tftp_mkdatapacket(fd, offset[tail], packet, blockno);
+ packetlen = tftp_mkdatapacket(fd, offsets[tail], packet, blockno);
if (packetlen < 0)
{
goto errout_with_sd;
@@ -474,7 +474,6 @@ int tftpput(const char *local, const char *remote, in_addr_t addr, boolean binar
#if CONFIG_NETUTILS_TFTP_ACKPACKETS > 1
if (blockno - hblockno >= CONFIG_NETUTILS_TFTP_ACKPACKETS || eof)
{
- uint16 rblockno;
int ndx;
/* Get the next ACK from the wire */
|