URL
https://opencores.org/ocsvn/or1k/or1k/trunk
Subversion Repositories or1k
Compare Revisions
- This comparison shows the changes necessary to convert path
/or1k/trunk/ecos-2.0/packages/net/ftpclient
- from Rev 1254 to Rev 1765
- ↔ Reverse comparison
Rev 1254 → Rev 1765
/v2_0/cdl/ftpclient.cdl
0,0 → 1,109
#==================================================================== |
# |
# ftpclient.cdl |
# |
# SNMP library configuration data |
# |
# ==================================================================== |
#####ECOSGPLCOPYRIGHTBEGIN#### |
## ------------------------------------------- |
## This file is part of eCos, the Embedded Configurable Operating System. |
## Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc. |
## |
## eCos is free software; you can redistribute it and/or modify it under |
## the terms of the GNU General Public License as published by the Free |
## Software Foundation; either version 2 or (at your option) any later version. |
## |
## eCos is distributed in the hope that it will be useful, but WITHOUT ANY |
## WARRANTY; without even the implied warranty of MERCHANTABILITY or |
## FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License |
## for more details. |
## |
## You should have received a copy of the GNU General Public License along |
## with eCos; if not, write to the Free Software Foundation, Inc., |
## 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. |
## |
## As a special exception, if other files instantiate templates or use macros |
## or inline functions from this file, or you compile this file and link it |
## with other works to produce a work based on this file, this file does not |
## by itself cause the resulting work to be covered by the GNU General Public |
## License. However the source code for this file must still be made available |
## in accordance with section (3) of the GNU General Public License. |
## |
## This exception does not invalidate any other reasons why a work based on |
## this file might be covered by the GNU General Public License. |
## |
## Alternative licenses for eCos may be arranged by contacting Red Hat, Inc. |
## at http://sources.redhat.com/ecos/ecos-license/ |
## ------------------------------------------- |
#####ECOSGPLCOPYRIGHTEND#### |
# ==================================================================== |
######DESCRIPTIONBEGIN#### |
# |
# Author(s): andrew.lunn@ascom.ch |
# Original data: andrew.lunn@ascom.ch |
# Contributors: |
# Date: 2001-11-04 |
# |
#####DESCRIPTIONEND#### |
# |
# ==================================================================== |
|
cdl_package CYGPKG_NET_FTPCLIENT { |
display "FTP client" |
parent CYGPKG_NET |
requires CYGPKG_IO |
requires { 0 != CYGINT_ISO_STRING_STRFUNCS } |
requires { 0 != CYGINT_ISO_STRING_MEMFUNCS } |
requires { 0 != CYGINT_ISO_STDLIB_STRCONV } |
requires { 0 != CYGINT_ISO_STDIO_FORMATTED_IO } |
requires { 0 != CYGINT_ISO_STRING_STRFUNCS } |
requires { 0 != CYGINT_ISO_ERRNO } |
requires { 0 != CYGINT_ISO_ERRNO_CODES } |
requires { 0 != CYGINT_ISO_CTYPE } |
requires CYGPKG_NET |
description " |
FTP client support. Provides ftp_put and ftp_get to put a file |
onto a remote FTP server and get a file from a remote server. |
Only binary more is supported." |
doc ref/net-ftpclient.html |
|
compile ftpclient.c |
|
cdl_component CYGPKG_NET_FTPCLIENT_OPTIONS { |
display "FTP client build options" |
flavor none |
no_define |
|
cdl_option CYGPKG_NET_FTPCLIENT_CFLAGS_ADD { |
display "Additional compiler flags" |
flavor data |
no_define |
default_value { "-D_KERNEL -D__ECOS" } |
description " |
This option modifies the set of compiler flags for |
building the FTP client package. These flags are used |
in addition to the set of global flags." |
} |
|
cdl_option CYGPKG_NET_FTPCLIENT_CFLAGS_REMOVE { |
display "Suppressed compiler flags" |
flavor data |
no_define |
default_value { "" } |
description " |
This option modifies the set of compiler flags for |
building the FTP client package. These flags are removed from |
the set of global flags if present." |
} |
} |
cdl_option CYGPKG_NET_FTPCLIENT_TESTS { |
display "FTP Client tests" |
flavor data |
no_define |
calculated { "tests/ftpclient1.c"} |
description " |
This option specifies the set of tests for the ftpclient package." |
} |
} |
|
/v2_0/tests/ftpclient1.c
0,0 → 1,164
//========================================================================== |
// |
// tests/dns1.c |
// |
// Simple test of DNS client support |
// |
//========================================================================== |
//####ECOSGPLCOPYRIGHTBEGIN#### |
// ------------------------------------------- |
// This file is part of eCos, the Embedded Configurable Operating System. |
// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc. |
// |
// eCos is free software; you can redistribute it and/or modify it under |
// the terms of the GNU General Public License as published by the Free |
// Software Foundation; either version 2 or (at your option) any later version. |
// |
// eCos is distributed in the hope that it will be useful, but WITHOUT ANY |
// WARRANTY; without even the implied warranty of MERCHANTABILITY or |
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License |
// for more details. |
// |
// You should have received a copy of the GNU General Public License along |
// with eCos; if not, write to the Free Software Foundation, Inc., |
// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. |
// |
// As a special exception, if other files instantiate templates or use macros |
// or inline functions from this file, or you compile this file and link it |
// with other works to produce a work based on this file, this file does not |
// by itself cause the resulting work to be covered by the GNU General Public |
// License. However the source code for this file must still be made available |
// in accordance with section (3) of the GNU General Public License. |
// |
// This exception does not invalidate any other reasons why a work based on |
// this file might be covered by the GNU General Public License. |
// |
// Alternative licenses for eCos may be arranged by contacting Red Hat, Inc. |
// at http://sources.redhat.com/ecos/ecos-license/ |
// ------------------------------------------- |
//####ECOSGPLCOPYRIGHTEND#### |
//========================================================================== |
//#####DESCRIPTIONBEGIN#### |
// |
// Author(s): andrew.lunn |
// Contributors: andrew.lunn, jskov |
// Date: 2001-09-18 |
// Purpose: |
// Description: Test FTPClient functions. Note that the _XXX defines below |
// control what addresses the test uses. These must be |
// changed to match the particular testing network in which |
// the test is to be run. |
// |
//####DESCRIPTIONEND#### |
// |
//========================================================================== |
|
#include <network.h> |
#include <ftpclient.h> |
#include <cyg/infra/testcase.h> |
|
#define STACK_SIZE (CYGNUM_HAL_STACK_SIZE_TYPICAL + 0x1000) |
static char stack[STACK_SIZE]; |
static cyg_thread thread_data; |
static cyg_handle_t thread_handle; |
|
#define __string(_x) #_x |
#define __xstring(_x) __string(_x) |
|
#define _FTP_SRV __xstring(172.16.19.254) // farmnet dns0 address |
|
#define FTPBUFSIZE (1024 * 64) |
char ftpbuf[FTPBUFSIZE]; |
char ftpbuf1[FTPBUFSIZE]; |
|
void |
ftp_test(cyg_addrword_t p) |
{ |
int ret; |
|
CYG_TEST_INIT(); |
|
init_all_network_interfaces(); |
|
CYG_TEST_INFO("Getting /etc/passwd from %s\n" _FTP_SRV); |
ret = ftp_get(_FTP_SRV,"anonymous","ftpclient1", |
"/etc/passwd",ftpbuf,FTPBUFSIZE, |
ftpclient_printf); |
|
if (ret > 0) { |
diag_printf("PASS:< %s bytes received>\n",ret); |
} else { |
diag_printf("FAIL:< ftp_get returned %d>\n",ret); |
} |
|
CYG_TEST_INFO("Putting passwd file back in /incoming/passwd\n"); |
ret = ftp_put(_FTP_SRV,"anonymous","ftpclient1", |
"/incoming/passwd",ftpbuf,ret, |
ftpclient_printf); |
|
if (ret > 0) { |
diag_printf("PASS:\n"); |
} else { |
diag_printf("FAIL:< ftp_get returned %d>\n",ret); |
} |
|
CYG_TEST_INFO("Reading back /incoming/passwd\n"); |
ret = ftp_get(_FTP_SRV,"anonymous","ftpclient1", |
"/incoming/passwd",ftpbuf1,FTPBUFSIZE, |
ftpclient_printf); |
|
if (ret > 0) { |
diag_printf("PASS:< %s bytes received>\n",ret); |
} else { |
diag_printf("FAIL:< ftp_get returned %d>\n",ret); |
} |
|
CYG_TEST_PASS_FAIL(!memcmp(ftpbuf,ftpbuf1,ret),"Transfer integrity"); |
|
CYG_TEST_INFO("ftp_Get'ing with a bad username\n"); |
ret = ftp_get(_FTP_SRV,"nosuchuser","ftpclient1", |
"/incoming/passwd",ftpbuf1,FTPBUFSIZE, |
ftpclient_printf); |
CYG_TEST_PASS_FAIL(ret==FTP_BADUSER,"Bad Username"); |
|
CYG_TEST_INFO("ftp_get'ting with a bad passwd\n"); |
ret = ftp_get(_FTP_SRV,"nobody","ftpclient1", |
"/incoming/passwd",ftpbuf1,FTPBUFSIZE, |
ftpclient_printf); |
CYG_TEST_PASS_FAIL(ret==FTP_BADUSER,"Bad passwd"); |
|
CYG_TEST_INFO("ftp_get'ing from a with a bad passwd\n"); |
ret = ftp_get(_FTP_SRV,"nobody","ftpclient1", |
"/incoming/passwd",ftpbuf1,FTPBUFSIZE, |
ftpclient_printf); |
CYG_TEST_PASS_FAIL(ret==FTP_BADUSER,"Bad passwd"); |
|
CYG_TEST_INFO("ftp_get'ing from a bad server\n"); |
ret = ftp_get("127.0.0.1","nobody","ftpclient1", |
"/incoming/passwd",ftpbuf1,FTPBUFSIZE, |
ftpclient_printf); |
CYG_TEST_PASS_FAIL(ret==FTP_NOSUCHHOST,"Bad server"); |
|
CYG_TEST_INFO("ftp_get'ing a file which is too big"); |
ret = ftp_get(_FTP_SRV,"nobody","ftpclient1", |
"/incoming/passwd",ftpbuf,2, |
ftpclient_printf); |
CYG_TEST_PASS_FAIL(ret==FTP_TOOBIG,"File too big"); |
} |
|
void |
cyg_start(void) |
{ |
/* Create a main thread, so we can run the scheduler and have time 'pass' */ |
cyg_thread_create(10, // Priority - just a number |
ftp_test, // entry |
0, // entry parameter |
"FTP test", // Name |
&stack[0], // Stack |
STACK_SIZE, // Size |
&thread_handle, // Handle |
&thread_data // Thread data structure |
); |
cyg_thread_resume(thread_handle); /* Start it */ |
cyg_scheduler_start(); |
} |
/v2_0/include/ftpclient.h
0,0 → 1,106
#ifndef CYGONCE_NET_FTPCLIENT_FTPCLIENT_H |
#define CYGONCE_NET_FTPCLIENT_FTPCLIENT_H |
|
//========================================================================== |
// |
// ftpclient.h |
// |
// A simple FTP client |
// |
//========================================================================== |
//####ECOSGPLCOPYRIGHTBEGIN#### |
// ------------------------------------------- |
// This file is part of eCos, the Embedded Configurable Operating System. |
// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc. |
// |
// eCos is free software; you can redistribute it and/or modify it under |
// the terms of the GNU General Public License as published by the Free |
// Software Foundation; either version 2 or (at your option) any later version. |
// |
// eCos is distributed in the hope that it will be useful, but WITHOUT ANY |
// WARRANTY; without even the implied warranty of MERCHANTABILITY or |
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License |
// for more details. |
// |
// You should have received a copy of the GNU General Public License along |
// with eCos; if not, write to the Free Software Foundation, Inc., |
// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. |
// |
// As a special exception, if other files instantiate templates or use macros |
// or inline functions from this file, or you compile this file and link it |
// with other works to produce a work based on this file, this file does not |
// by itself cause the resulting work to be covered by the GNU General Public |
// License. However the source code for this file must still be made available |
// in accordance with section (3) of the GNU General Public License. |
// |
// This exception does not invalidate any other reasons why a work based on |
// this file might be covered by the GNU General Public License. |
// |
// Alternative licenses for eCos may be arranged by contacting Red Hat, Inc. |
// at http://sources.redhat.com/ecos/ecos-license/ |
// ------------------------------------------- |
//####ECOSGPLCOPYRIGHTEND#### |
//========================================================================== |
//#####DESCRIPTIONBEGIN#### |
// |
// Author(s): andrew.lunn@ascom.ch |
// Contributors: andrew.lunn@ascom.ch |
// Date: 2001-11-4 |
// Purpose: |
// Description: |
// |
//####DESCRIPTIONEND#### |
// |
//========================================================================== |
|
typedef void (*ftp_printf_t)(unsigned error, const char *, ...); |
|
/* Use the FTP protocol to retrieve a file from a server. Only binary |
mode is supported. The filename can include a directory name. Only |
use unix style / not M$'s \. The file is placed into buf. buf has |
maximum size buf_size. If the file is bigger than this, the |
transfer fails and FTP_TOOBIG is returned. Other error codes as |
listed below can also be returned. If the transfer is succseful the |
number of bytes received is returned. */ |
|
int ftp_get(char * hostname, |
char * username, |
char * passwd, |
char * filename, |
char * buf, |
unsigned buf_size, |
ftp_printf_t ftp_printf); |
|
/*Use the FTP protocol to send a file from a server. Only binary mode |
is supported. The filename can include a directory name. Only use |
unix style / not M$'s \. The contents of buf is placed into the file |
on the server. If an error occurs one of the codes as listed below |
will be returned. If the transfer is succseful zero is returned.*/ |
|
int ftp_put(char * hostname, |
char * username, |
char * passwd, |
char * filename, |
char * buf, |
unsigned buf_size, |
ftp_printf_t ftp_printf); |
|
/*ftp_get() and ftp_put take the name of a function to call to print |
out diagnostic and error messages. This is a sample implementation |
which can be used if you don't want to implement the function |
yourself. error will be true when the message to print is an error |
message. Otherwise the message is diagnostic, eg the commands sent |
and received from the server.*/ |
|
void ftpclient_printf(unsigned error, const char *fmt, ...); |
|
/* Error codes */ |
|
#define FTP_BAD -2 /* Catch all, socket errors etc. */ |
#define FTP_NOSUCHHOST -3 /* The server does not exist. */ |
#define FTP_BADUSER -4 /* Username/Password failed */ |
#define FTP_TOOBIG -5 /* Out of buffer space or disk space */ |
#define FTP_BADFILENAME -6 /* The file does not exist */ |
|
#endif CYGONCE_NET_FTPCLIENT_FTPCLIENT |
|
/v2_0/doc/ftpclient.sgml
0,0 → 1,117
<!-- {{{ Banner --> |
|
<!-- =============================================================== --> |
<!-- --> |
<!-- ftpclient.sgml --> |
<!-- --> |
<!-- eCos TCP/IP Stacks --> |
<!-- --> |
<!-- =============================================================== --> |
<!-- ####COPYRIGHTBEGIN#### --> |
<!-- --> |
<!-- =============================================================== --> |
<!-- Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002 Red Hat, Inc. --> |
<!-- This material may be distributed only subject to the terms --> |
<!-- and conditions set forth in the Open Publication License, v1.0 --> |
<!-- or later (the latest version is presently available at --> |
<!-- http://www.opencontent.org/openpub/) --> |
<!-- Distribution of the work or derivative of the work in any --> |
<!-- standard (paper) book form is prohibited unless prior --> |
<!-- permission obtained from the copyright holder --> |
<!-- =============================================================== --> |
<!-- --> |
<!-- ####COPYRIGHTEND#### --> |
<!-- =============================================================== --> |
<!-- #####DESCRIPTIONBEGIN#### --> |
<!-- --> |
<!-- ####DESCRIPTIONEND#### --> |
<!-- =============================================================== --> |
|
<!-- }}} --> |
|
<PART ID="net-ftpclient"> |
<TITLE>FTP Client for eCos TCP/IP Stack</TITLE> |
<PARTINTRO> |
<PARA> |
The ftpclient package provides an FTP (File Transfer Protocol) client |
for use with the TCP/IP stack in eCos. |
</PARA> |
</PARTINTRO> |
<CHAPTER id="net-ftpclient-features"> |
<TITLE>FTP Client Features</TITLE> |
<SECT1 id="net-ftpclient-features-api"> |
<TITLE>FTP Client API</TITLE> |
<para> |
This package implements an FTP client. The API is in include file |
<filename>install/include/ftpclient.h</filename> and it can be used thus: |
<programlisting> |
#include <network.h> |
#include <ftpclient.h> |
</programlisting> |
It looks like this: |
</para> |
<sect2 id="net-ftpclient-features-api-get"> |
<title>ftp_get</title> |
<programlisting> |
int ftp_get(char * hostname, |
char * username, |
char * passwd, |
char * filename, |
char * buf, |
unsigned buf_size, |
ftp_printf_t ftp_printf); |
</programlisting> |
<para> |
Use the FTP protocol to retrieve a file from a server. Only binary |
mode is supported. The filename can include a directory name. Only |
use unix style ‘/’ file separators, |
not ‘\’. |
The file is placed into <parameter>buf</parameter>. |
<parameter>buf</parameter> has maximum size <parameter>buf_size</parameter>. |
If the file is bigger than this, the |
transfer fails and <errorcode>FTP_TOOBIG</errorcode> is returned. |
Other error codes listed in the header can also be returned. |
If the transfer is successful the number of bytes received is returned. |
</para> |
</sect2> |
<sect2 id="net-ftpclient-features-api-put"> |
<title>ftp_put</title> |
<programlisting> |
int ftp_put(char * hostname, |
char * username, |
char * passwd, |
char * filename, |
char * buf, |
unsigned buf_size, |
ftp_printf_t ftp_printf); |
</programlisting> |
<para> |
Use the FTP protocol to send a file to a server. |
Only binary |
mode is supported. The filename can include a directory name. Only |
use unix style ‘/’ file separators, |
not ‘\’. |
The contents of <parameter>buf</parameter> are placed into the file on the |
server. If an error occurs one of the codes listed will be returned. If the |
transfer is successful zero is returned. |
</para> |
</sect2> |
<sect2 id="net-ftpclient-features-api-printf"> |
<title>ftpclient_printf</title> |
<programlisting> |
void ftpclient_printf(unsigned error, const char *fmt, ...); |
</programlisting> |
<para> |
<function>ftp_get()</function> and <function>ftp_put</function> |
take a pointer to a function to use for printing |
out diagnostic and error messages. This is a sample implementation |
which can be used if you don't want to implement the function |
yourself. |
<parameter>error</parameter> will be true when the message to print is an |
error message. Otherwise the message is diagnostic, eg. the commands sent |
and received from the server. |
</para> |
</sect2> |
</SECT1> |
</CHAPTER> |
</PART> |
v2_0/doc/ftpclient.sgml
Property changes :
Added: svn:executable
## -0,0 +1 ##
+*
\ No newline at end of property
Index: v2_0/ChangeLog
===================================================================
--- v2_0/ChangeLog (nonexistent)
+++ v2_0/ChangeLog (revision 1765)
@@ -0,0 +1,57 @@
+2003-02-24 Jonathan Larmour
+
+ * cdl/ftpclient.cdl: Add doc link.
+
+2002-08-06 Andrew Lunn
+
+ * src/ftpclient.c: Send "quit" not "quit " to keep some servers
+ happy. Also deal with multi line replies correctly.
+
+2002-02-22 Hugo Tyson
+
+ * doc/ftpclient.sgml: New file. Document it.
+
+2001-12-04 Andrew Lunn
+
+ * src/ftpclient.c: Allow it to compile!
+
+2001-11-04 Andrew Lunn
+
+ * First version. Implements an FTP client which can get and put
+ files on a server.
+
+//===========================================================================
+//####ECOSGPLCOPYRIGHTBEGIN####
+// -------------------------------------------
+// This file is part of eCos, the Embedded Configurable Operating System.
+// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc.
+//
+// eCos is free software; you can redistribute it and/or modify it under
+// the terms of the GNU General Public License as published by the Free
+// Software Foundation; either version 2 or (at your option) any later version.
+//
+// eCos is distributed in the hope that it will be useful, but WITHOUT ANY
+// WARRANTY; without even the implied warranty of MERCHANTABILITY or
+// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+// for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with eCos; if not, write to the Free Software Foundation, Inc.,
+// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+//
+// As a special exception, if other files instantiate templates or use macros
+// or inline functions from this file, or you compile this file and link it
+// with other works to produce a work based on this file, this file does not
+// by itself cause the resulting work to be covered by the GNU General Public
+// License. However the source code for this file must still be made available
+// in accordance with section (3) of the GNU General Public License.
+//
+// This exception does not invalidate any other reasons why a work based on
+// this file might be covered by the GNU General Public License.
+//
+// Alternative licenses for eCos may be arranged by contacting Red Hat, Inc.
+// at http://sources.redhat.com/ecos/ecos-license/
+// -------------------------------------------
+//####ECOSGPLCOPYRIGHTEND####
+//===========================================================================
+
Index: v2_0/src/ftpclient.c
===================================================================
--- v2_0/src/ftpclient.c (nonexistent)
+++ v2_0/src/ftpclient.c (revision 1765)
@@ -0,0 +1,694 @@
+//==========================================================================
+//
+// ftpclient.c
+//
+// A simple FTP client
+//
+//==========================================================================
+//####ECOSGPLCOPYRIGHTBEGIN####
+// -------------------------------------------
+// This file is part of eCos, the Embedded Configurable Operating System.
+// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc.
+// Copyright (C) 2002 Andrew Lunn.
+//
+// eCos is free software; you can redistribute it and/or modify it under
+// the terms of the GNU General Public License as published by the Free
+// Software Foundation; either version 2 or (at your option) any later version.
+//
+// eCos is distributed in the hope that it will be useful, but WITHOUT ANY
+// WARRANTY; without even the implied warranty of MERCHANTABILITY or
+// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+// for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with eCos; if not, write to the Free Software Foundation, Inc.,
+// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+//
+// As a special exception, if other files instantiate templates or use macros
+// or inline functions from this file, or you compile this file and link it
+// with other works to produce a work based on this file, this file does not
+// by itself cause the resulting work to be covered by the GNU General Public
+// License. However the source code for this file must still be made available
+// in accordance with section (3) of the GNU General Public License.
+//
+// This exception does not invalidate any other reasons why a work based on
+// this file might be covered by the GNU General Public License.
+//
+// Alternative licenses for eCos may be arranged by contacting Red Hat, Inc.
+// at http://sources.redhat.com/ecos/ecos-license/
+// -------------------------------------------
+//####ECOSGPLCOPYRIGHTEND####
+//==========================================================================
+//#####DESCRIPTIONBEGIN####
+//
+// Author(s): andrew.lunn@ascom.ch
+// Contributors: andrew.lunn@ascom.ch
+// Date: 2001-11-4
+// Purpose:
+// Description:
+//
+//####DESCRIPTIONEND####
+//
+//==========================================================================
+
+#include
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include "ftpclient.h"
+
+/* Build one command to send to the FTP server */
+static int
+build_cmd(char *buf,
+ unsigned bufsize,
+ char *cmd,
+ char *arg1)
+{
+ int cnt;
+
+ if (arg1) {
+ cnt = snprintf(buf,bufsize,"%s %s\r\n",cmd,arg1);
+ } else {
+ cnt = snprintf(buf,bufsize,"%s\r\n",cmd);
+ }
+
+ if (cnt < bufsize)
+ return 1;
+
+ return 0;
+}
+
+
+/* Read one line from the server, being careful not to overrun the
+ buffer. If we do reach the end of the buffer, discard the rest of
+ the line. */
+static int
+get_line(int s, char *buf, unsigned buf_size,ftp_printf_t ftp_printf) {
+
+ int eol = 0;
+ int cnt = 0;
+ int ret;
+ char c;
+
+ while(!eol) {
+ ret = read(s,&c,1);
+
+ if (ret != 1) {
+ ftp_printf(1,"read %s\n",strerror(errno));
+ return FTP_BAD;
+ }
+
+ if (c == '\n') {
+ eol = 1;
+ continue;
+ }
+
+ if (cnt < buf_size) {
+ buf[cnt++] = c;
+ }
+ }
+ if (cnt < buf_size) {
+ buf[cnt++] = '\0';
+ } else {
+ buf[buf_size -1] = '\0';
+ }
+ return 0;
+}
+
+/* Read the reply from the server and return the MSB from the return
+ code. This gives us a basic idea if the command failed/worked. The
+ reply can be spread over multiple lines. When this happens the line
+ will start with a - to indicate there is more*/
+static int
+get_reply(int s,ftp_printf_t ftp_printf) {
+
+ char buf[BUFSIZ];
+ int more = 0;
+ int ret;
+ int first_line=1;
+ int code=0;
+
+ do {
+
+ if ((ret=get_line(s,buf,sizeof(buf),ftp_printf)) < 0) {
+ return(ret);
+ }
+
+ ftp_printf(0,"FTP: %s\n",buf);
+
+ if (first_line) {
+ code = strtoul(buf,NULL,0);
+ first_line=0;
+ more = (buf[3] == '-');
+ } else {
+ if (isdigit(buf[0]) && isdigit(buf[1]) && isdigit(buf[2]) &&
+ (code == strtoul(buf,NULL,0)) &&
+ buf[3]==' ') {
+ more=0;
+ } else {
+ more =1;
+ }
+ }
+ } while (more);
+
+ return (buf[0] - '0');
+}
+
+/* Send a command to the server */
+static int
+send_cmd(int s,char * msgbuf,ftp_printf_t ftp_printf) {
+
+ int len;
+ int slen = strlen(msgbuf);
+
+ if ((len = write(s,msgbuf,slen)) != slen) {
+ if (slen < 0) {
+ ftp_printf(1,"write %s\n",strerror(errno));
+ return FTP_BAD;
+ } else {
+ ftp_printf(1,"write truncasted!\n");
+ return FTP_BAD;
+ }
+ }
+ return 1;
+}
+
+/* Send a complete command to the server and receive the reply. Return the
+ MSB of the reply code. */
+static int
+command(char * cmd,
+ char * arg,
+ int s,
+ char *msgbuf,
+ int msgbuflen,
+ ftp_printf_t ftp_printf) {
+
+ int err;
+
+ if (!build_cmd(msgbuf,msgbuflen,cmd,arg)) {
+ ftp_printf(1,"FTP: %s command to long\n",cmd);
+ return FTP_BAD;
+ }
+
+ ftp_printf(0,"FTP: Sending %s command\n",cmd);
+
+ if ((err=send_cmd(s,msgbuf,ftp_printf)) < 0) {
+ return(err);
+ }
+
+ return (get_reply(s,ftp_printf));
+}
+
+/* Open a socket and connect it to the server. Also print out the
+ address of the server for debug purposes.*/
+
+static int
+connect_to_server(char *hostname,
+ struct sockaddr_in * local,
+ ftp_printf_t ftp_printf)
+{
+ struct sockaddr_in host;
+ struct servent *sent;
+#ifdef CYGPKG_NS_DNS
+ struct hostent *hp=NULL;
+#endif
+ int s, len;
+
+ s = socket(AF_INET, SOCK_STREAM, 0);
+ if (s < 0) {
+ ftp_printf(1,"socket: %s\n",strerror(errno));
+ return FTP_BAD;
+ }
+
+ sent = getservbyname("ftp", "tcp");
+ if (sent == (struct servent *)0) {
+ ftp_printf(1,"FTP: unknown serivice\n");
+ close(s);
+ return FTP_BAD;
+ }
+
+#ifdef CYGPKG_NS_DNS
+ hp = gethostbyname(hostname);
+
+
+ if (hp) { /* try name first */
+ host.sin_family = hp->h_addrtype;
+ bcopy(hp->h_addr, &host.sin_addr, hp->h_length);
+ } else
+#endif
+ { /* maybe it's a numeric address ?*/
+ host.sin_family = AF_INET;
+
+ if (inet_aton(hostname,&host.sin_addr) == 0) {
+ ftp_printf(1,"host not found: %s\n", hostname);
+ close (s);
+ return FTP_NOSUCHHOST;
+ }
+ }
+
+ host.sin_port = sent->s_port;
+
+ if (connect(s, (struct sockaddr *)&host, sizeof(host)) < 0) {
+ ftp_printf(1,"FTP Connect failed: %s\n",strerror(errno));
+ close (s);
+ return FTP_NOSUCHHOST;
+ }
+
+ len = sizeof(struct sockaddr_in);
+ if (getsockname(s, (struct sockaddr *)local, &len) < 0) {
+ ftp_printf(1,"getsockname failed %s\n",strerror(errno));
+ close(s);
+ return FTP_BAD;
+ }
+ ftp_printf(0,"FTP: Connected to %s.%d\n",
+ inet_ntoa(host.sin_addr), ntohs(host.sin_port));
+
+ return (s);
+}
+
+/* Perform a login to the server. Pass the username and password and
+ put the connection into binary mode. This assumes a passwd is
+ always needed. Is this true? */
+
+static int
+login(char * username,
+ char *passwd,
+ int s,
+ char *msgbuf,
+ unsigned msgbuflen,
+ ftp_printf_t ftp_printf) {
+
+ int ret;
+
+ ret = command("USER",username,s,msgbuf,msgbuflen,ftp_printf);
+ if (ret != 3) {
+ ftp_printf(1,"FTP: User %s not accepted\n",username);
+ return (FTP_BADUSER);
+ }
+
+ ret = command("PASS",passwd,s,msgbuf,msgbuflen,ftp_printf);
+ if (ret < 0) {
+ return (ret);
+ }
+ if (ret != 2) {
+ ftp_printf(1,"FTP: Login failed for User %s\n",username);
+ return (FTP_BADUSER);
+ }
+
+ ftp_printf(0,"FTP: Login sucessfull\n");
+
+ ret = command("TYPE","I",s,msgbuf,msgbuflen,ftp_printf);
+ if (ret < 0) {
+ return (ret);
+ }
+ if (ret != 2) {
+ ftp_printf(1,"FTP: TYPE failed!\n");
+ return (FTP_BAD);
+ }
+ return (ret);
+}
+
+
+/* Open a data socket. This is a client socket, i.e. its listening
+waiting for the FTP server to connect to it. Once the socket has been
+opened send the port command to the server so the server knows which
+port we are listening on.*/
+static int
+opendatasock(int ctrl_s,
+ struct sockaddr_in ctrl,
+ char *msgbuf,
+ unsigned msgbuflen,
+ ftp_printf_t ftp_printf) {
+
+ struct sockaddr_in local;
+ socklen_t len;
+ int on = 1;
+ char buf[4*6+1];
+ char *a, *p;
+ int ret;
+ int s;
+
+ s = socket(AF_INET, SOCK_STREAM, 0);
+ if (s < 0) {
+ ftp_printf(1,"socket: %s\n",strerror(errno));
+ return FTP_BAD;
+ }
+
+ if (setsockopt(s, SOL_SOCKET, SO_REUSEADDR, (char *)&on, sizeof (on)) < 0) {
+ ftp_printf(1,"setsockopt: %s\n",strerror(errno));
+ close(s);
+ return FTP_BAD;
+ }
+
+ local = ctrl;
+ local.sin_family = AF_INET;
+ local.sin_port = 0;
+ if (bind(s,(struct sockaddr *)&local,sizeof(local)) < 0) {
+ ftp_printf(1,"bind: %s\n",strerror(errno));
+ close(s);
+ return FTP_BAD;
+ }
+
+ len = sizeof(local);
+ if (getsockname(s,(struct sockaddr *)&local,&len) < 0) {
+ ftp_printf(1,"getsockname: %s\n",strerror(errno));
+ close(s);
+ return FTP_BAD;
+ }
+
+ if (listen(s, 1) < 0) {
+ ftp_printf(1,"listen: %s\n",strerror(errno));
+ close(s);
+ return FTP_BAD;
+ }
+
+#define BtoI(b) (((int)b)&0xff)
+ a = (char *)&local.sin_addr;
+ p = (char *)&local.sin_port;
+ sprintf(buf,"%d,%d,%d,%d,%d,%d",
+ BtoI(a[0]),BtoI(a[1]),BtoI(a[2]),BtoI(a[3]),
+ BtoI(p[0]),BtoI(p[1]));
+
+ ret = command("PORT",buf,ctrl_s,msgbuf,msgbuflen,ftp_printf);
+ if (ret < 0) {
+ close(s);
+ return (ret);
+ }
+
+ if (ret != 2) {
+ ftp_printf(1,"FTP: PORT failed!\n");
+ close(s);
+ return (FTP_BAD);
+ }
+ return (s);
+}
+
+/* Receive the file into the buffer and close the data socket
+ afterwards */
+static int
+receive_file(int data_s, char *buf, int buf_size,ftp_printf_t ftp_printf)
+{
+ int remaining = buf_size;
+ int finished = 0;
+ int total_size=0;
+ char *bufp = buf;
+ int len;
+ int s;
+
+ s = accept(data_s,NULL,0);
+ if (s<0) {
+ ftp_printf(1,"listen: %s\n",strerror(errno));
+ return FTP_BAD;
+ }
+
+ do {
+ len = read(s,bufp,remaining);
+ if (len < 0) {
+ ftp_printf(1,"read: %s\n",strerror(errno));
+ close(s);
+ return FTP_BAD;
+ }
+
+ if (len == 0) {
+ finished = 1;
+ } else {
+ total_size += len;
+ remaining -= len;
+ bufp += len;
+
+ if (total_size == buf_size) {
+ ftp_printf(1,"FTP: File too big!\n");
+ close(s);
+ return FTP_TOOBIG;
+ }
+ }
+ } while (!finished);
+
+ close(s);
+ return total_size;
+}
+
+/* Receive the file into the buffer and close the socket afterwards*/
+static int
+send_file(int data_s, char *buf, int buf_size,ftp_printf_t ftp_printf)
+{
+ int remaining=buf_size;
+ int finished = 0;
+ char * bufp = buf;
+ int len;
+ int s;
+
+ s = accept(data_s,NULL,0);
+ if (s<0) {
+ ftp_printf(1,"listen: %s\n",strerror(errno));
+ return FTP_BAD;
+ }
+
+ do {
+ len = write(s,bufp,remaining);
+ if (len < 0) {
+ ftp_printf(1,"write: %s\n",strerror(errno));
+ close(s);
+ return FTP_BAD;
+ }
+
+ if (len == remaining) {
+ finished = 1;
+ } else {
+ remaining -= len;
+ bufp += len;
+ }
+ } while (!finished);
+
+ close(s);
+ return 0;
+}
+
+/* All done, say bye, bye */
+static int quit(int s,
+ char *msgbuf,
+ unsigned msgbuflen,
+ ftp_printf_t ftp_printf) {
+
+ int ret;
+
+ ret = command("QUIT",NULL,s,msgbuf,msgbuflen,ftp_printf);
+ if (ret < 0) {
+ return (ret);
+ }
+ if (ret != 2) {
+ ftp_printf(1,"FTP: Quit failed!\n");
+ return (FTP_BAD);
+ }
+
+ ftp_printf(0,"FTP: Connection closed\n");
+ return (0);
+}
+
+/* Get a file from an FTP server. Hostname is the name/IP address of
+ the server. username is the username used to connect to the server
+ with. Passwd is the password used to authentificate the
+ username. filename is the name of the file to receive. It should be
+ the full pathname of the file. buf is a pointer to a buffer the
+ contents of the file should be placed in and buf_size is the size
+ of the buffer. If the file is bigger than the buffer, buf_size
+ bytes will be retrieved and an error code returned. ftp_printf is a
+ function to be called to perform printing. On success the number of
+ bytes received is returned. On error a negative value is returned
+ indicating the type of error. */
+
+int ftp_get(char * hostname,
+ char * username,
+ char * passwd,
+ char * filename,
+ char * buf,
+ unsigned buf_size,
+ ftp_printf_t ftp_printf)
+{
+
+ struct sockaddr_in local;
+ char msgbuf[256];
+ int s,data_s;
+ int bytes;
+ int ret;
+
+ s = connect_to_server(hostname,&local,ftp_printf);
+ if (s < 0) {
+ return (s);
+ }
+
+ /* Read the welcome message from the server */
+ if (get_reply(s,ftp_printf) != 2) {
+ ftp_printf(0,"FTP: Server refused connection\n");
+ close(s);
+ return FTP_BAD;
+ }
+
+ ret = login(username,passwd,s,msgbuf,sizeof(msgbuf),ftp_printf);
+ if (ret < 0) {
+ close(s);
+ return (ret);
+ }
+
+ /* We are now logged in and ready to transfer the file. Open the
+ data socket ready to receive the file. It also build the PORT
+ command ready to send */
+ data_s = opendatasock(s,local,msgbuf,sizeof(msgbuf),ftp_printf);
+ if (data_s < 0) {
+ close (s);
+ return (data_s);
+ }
+
+ /* Ask for the file */
+ ret = command("RETR",filename,s,msgbuf,sizeof(msgbuf),ftp_printf);
+ if (ret < 0) {
+ close(s);
+ close(data_s);
+ return (ret);
+ }
+
+ if (ret != 1) {
+ ftp_printf(0,"FTP: RETR failed!\n");
+ close (data_s);
+ close(s);
+ return (FTP_BADFILENAME);
+ }
+
+ if ((bytes=receive_file(data_s,buf,buf_size,ftp_printf)) < 0) {
+ ftp_printf(0,"FTP: Receiving file failed\n");
+ close (data_s);
+ close(s);
+ return (bytes);
+ }
+
+ if (get_reply(s,ftp_printf) != 2) {
+ ftp_printf(0,"FTP: Transfer failed!\n");
+ close (data_s);
+ close(s);
+ return (FTP_BAD);
+ }
+
+ ret = quit(s,msgbuf,sizeof(msgbuf),ftp_printf);
+ if (ret < 0) {
+ close(s);
+ close(data_s);
+ return (ret);
+ }
+
+ close (data_s);
+ close(s);
+ return bytes;
+}
+
+/* Put a file on an FTP server. Hostname is the name/IP address of the
+ server. username is the username used to connect to the server
+ with. Passwd is the password used to authentificate the
+ username. filename is the name of the file to receive. It should be
+ the full pathname of the file. buf is a pointer to a buffer the
+ contents of the file should be placed in and buf_size is the size
+ of the buffer. ftp_printf is a function to be called to perform
+ printing. On success 0 is returned. On error a negative value is
+ returned indicating the type of error. */
+
+int ftp_put(char * hostname,
+ char * username,
+ char * passwd,
+ char * filename,
+ char * buf,
+ unsigned buf_size,
+ ftp_printf_t ftp_printf)
+{
+
+ struct sockaddr_in local;
+ char msgbuf[256];
+ int s,data_s;
+ int ret;
+
+ s = connect_to_server(hostname,&local,ftp_printf);
+ if (s < 0) {
+ return (s);
+ }
+
+ /* Read the welcome message from the server */
+ if (get_reply(s,ftp_printf) != 2) {
+ ftp_printf(1,"FTP: Server refused connection\n");
+ close(s);
+ return FTP_BAD;
+ }
+
+ ret = login(username,passwd,s,msgbuf,sizeof(msgbuf),ftp_printf);
+ if (ret < 0) {
+ close(s);
+ return (ret);
+ }
+
+ /* We are now logged in and ready to transfer the file. Open the
+ data socket ready to receive the file. It also build the PORT
+ command ready to send */
+ data_s = opendatasock(s,local,msgbuf,sizeof(msgbuf),ftp_printf);
+ if (data_s < 0) {
+ close (s);
+ return (data_s);
+ }
+
+ /* Ask for the file */
+ ret = command("STOR",filename,s,msgbuf,sizeof(msgbuf),ftp_printf);
+ if (ret < 0) {
+ close(s);
+ close(data_s);
+ return (ret);
+ }
+
+ if (ret != 1) {
+ ftp_printf(1,"FTP: STOR failed!\n");
+ close (data_s);
+ close(s);
+ return (FTP_BADFILENAME);
+ }
+
+ if ((ret = send_file(data_s,buf,buf_size,ftp_printf)) < 0) {
+ ftp_printf(1,"FTP: Sending file failed\n");
+ close (data_s);
+ close(s);
+ return (ret);
+ }
+
+ if (get_reply(s,ftp_printf) != 2) {
+ ftp_printf(1,"FTP: Transfer failed!\n");
+ close (data_s);
+ close(s);
+ return (FTP_BAD);
+ }
+
+ ret = quit(s,msgbuf,sizeof(msgbuf),ftp_printf);
+ if (ret < 0) {
+ close(s);
+ close(data_s);
+ return (ret);
+ }
+
+ close (data_s);
+ close(s);
+ return 0;
+}
+
+/* An example ftp_printf function. This uses the standard eCos diag
+output device for outputting error and diagnostic messages. The
+function take one addition parameter to the normal printf function. The
+first parameter indicates when the message is an error message when
+true. This can be used to filter errors from diagnostic output. In
+this example the error parameter is ignored and everything printed. */
+
+void ftpclient_printf(unsigned error, const char *fmt, ...)
+{
+ va_list ap;
+
+ va_start(ap, fmt);
+ diag_vprintf( fmt, ap);
+ va_end(ap);
+}