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 @@

NuttShell (NSH)

-

Last Updated: September 3, 2008

+

Last Updated: September 5, 2008

@@ -113,127 +113,139 @@
- 2.7 Exit NSH (exit) + 2.7 Get File Via TFTP (get)
- 2.8 Show Usage Command Usage (help) + 2.8 Exit NSH (exit)
- 2.9 Show Network Configuration (ifconfig) + 2.9 Show Usage Command Usage (help)
- 2.10 List Directory Contents (ls) + 2.10 Show Network Configuration (ifconfig)
- 2.11 Access Memory (mb, mh, and mw) + 2.11 List Directory Contents (ls)
- 2.12 Show Memory Manager Status (mem) + 2.12 Access Memory (mb, mh, and mw)
- 2.13 Show Current Tasks and Threads (ps) + 2.13 Show Memory Manager Status (mem)
- 2.14 Create a Directory (mkdir) + 2.14 Show Current Tasks and Threads (ps)
- 2.15 Create a FAT Filesystem (mkfatfs) + 2.15 Create a Directory (mkdir)
- 2.16 Create a FIFO (mkfifo) + 2.16 Create a FAT Filesystem (mkfatfs)
- 2.17 Mount a File System (mount) + 2.17 Create a FIFO (mkfifo)
- 2.18 Check Network Peer (ping) + 2.18 Mount a File System (mount)
- 2.19 Show Current Working Directory (pwd) + 2.19 Check Network Peer (ping)
- 2.20 Remove a File (rm) + 2.20 Send File Via TFTP (put)
- 2.21 Remove a Directory (rmdir) + 2.21 Show Current Working Directory (pwd)
- 2.22 Set an Environment Variable (set) + 2.22 Remove a File (rm)
- 2.23 Execute an NSH Script (sh) + 2.23 Remove a Directory (rmdir)
- 2.24 Wait for Seconds (sleep) + 2.24 Set an Environment Variable (set)
- 2.25 Unmount a File System (umount) + 2.25 Execute an NSH Script (sh)
- 2.26 Unset an Environment Variable (unset) + 2.26 Wait for Seconds (sleep)
- 2.27 Wait for Microseconds (usleep) + 2.27 Unmount a File System (umount) + + + +
+ + 2.28 Unset an Environment Variable (unset) + + + +
+ + 2.29 Wait for Microseconds (usleep) @@ -621,7 +633,42 @@ exec <hex-address> + +
-

2.7 Exit NSH (exit)

+

2.7 Get File Via TFTP (get)

+
+ +Command Syntax:

+ +

+ Synopsis. + Copy the file at <remote-address> from the host whose IP address is + identified by <ip-address>. +

+

Other options:

+ + + + +
+

2.8 Exit NSH (exit)

@@ -640,7 +687,7 @@ exit
-

2.8 Show Usage Command Usage (help)

+

2.9 Show Usage Command Usage (help)

@@ -657,7 +704,7 @@ help
-

2.9 Show Network Configuration (ifconfig)

+

2.10 Show Network Configuration (ifconfig)

@@ -683,7 +730,7 @@ eth0 HWaddr 00:18:11:80:10:06
-

2.10 List Directory Contents (ls)

+

2.11 List Directory Contents (ls)

@@ -720,7 +767,7 @@ ls [-lRs] <dir-path>
-

2.11 Access Memory (mb, mh, and mw)

+

2.12 Access Memory (mb, mh, and mw)

@@ -774,7 +821,7 @@ nsh>
-

2.12 Show Memory Manager Status (mem)

+

2.13 Show Memory Manager Status (mem)

@@ -823,7 +870,7 @@ nsh>
-

2.13 Show Current Tasks and Threads (ps)

+

2.14 Show Current Tasks and Threads (ps)

@@ -849,7 +896,7 @@ nsh>
-

2.14 Create a Directory (mkdir)

+

2.15 Create a Directory (mkdir)

@@ -884,7 +931,7 @@ nsh>
-

2.15 Create a FAT Filesystem (mkfatfs)

+

2.16 Create a FAT Filesystem (mkfatfs)

@@ -904,7 +951,7 @@ mkfatfs <path>
-

2.16 Create a FIFO (mkfifo)

+

2.17 Create a FIFO (mkfifo)

@@ -942,7 +989,7 @@ nsh>
-

2.17 Mount a File System (mount)

+

2.18 Mount a File System (mount)

@@ -1009,7 +1056,7 @@ nsh>
-

2.18 Check Network Peer (ping)

+

2.19 Check Network Peer (ping)

@@ -1042,7 +1089,42 @@ nsh> + +
-

2.19 Show Current Working Directory (pwd)

+

2.20 Send File Via TFTP (put)

+
+ +
Command Syntax:

+ +

+ Synopsis. + Copy the file at <local-address> to the host whose IP address is + identified by <ip-address>. +

+

Other options:

+ + + + +
+

2.21 Show Current Working Directory (pwd)

@@ -1072,7 +1154,7 @@ nsh>
-

2.20 Remove a File (rm)

+

2.22 Remove a File (rm)

@@ -1106,7 +1188,7 @@ nsh>
-

2.21 Remove a Directory (rmdir)

+

2.23 Remove a Directory (rmdir)

@@ -1141,7 +1223,7 @@ nsh>
-

2.22 Set an Environment Variable (set)

+

2.24 Set an Environment Variable (set)

@@ -1167,7 +1249,7 @@ nsh>
-

2.23 Execute an NSH Script (sh)

+

2.25 Execute an NSH Script (sh)

@@ -1185,7 +1267,7 @@ sh <script-path>
-

2.24 Wait for Seconds (sleep)

+

2.26 Wait for Seconds (sleep)

@@ -1202,7 +1284,7 @@ sleep <sec>
-

2.25 Unmount a File System (umount)

+

2.27 Unmount a File System (umount)

@@ -1232,7 +1314,7 @@ nsh>
-

2.26 Unset an Environment Variable (unset)

+

2.28 Unset an Environment Variable (unset)

@@ -1258,7 +1340,7 @@ nsh>
-

2.27 Wait for Microseconds (usleep)

+

2.29 Wait for Microseconds (usleep)

@@ -1331,6 +1413,10 @@ usleep <usec> exit
+ + get + CONFIG_NET && CONFIG_NET_UDP && CONFIG_NFILE_DESCRIPTORS > 0 + help
@@ -1375,6 +1461,10 @@ usleep <usec> ps
+ + put + CONFIG_NET && CONFIG_NET_UDP && CONFIG_NFILE_DESCRIPTORS > 0 + 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 */