www.pudn.com > tcpipstack.rar > TINYFT2.C
/* TINYFT2.C - Part 2 of tiny FTP. * Copyright (C) 1986, IMAGEN Corporation * "This code may be duplicated in whole or in part provided that [1] there * is no commercial gain involved in the duplication, and [2] that this * copyright notice is preserved on all copies. Any other duplication * requires written notice of the author." |===================================================================| | The author of this code hereby licenses all duplication and/or | | modification of this code, in whole or in part, consistent with | | the terms of the GNU Library General Public License. | | - Geoffrey H. Cooper 10/29/97 | |===================================================================| |===================================================================| | My changes can be considered public domain. Geof's statement | | will cover everything. | | - Rick Rodman 09/02/97 | |===================================================================| 941012 rr split into 3 parts */ /* #define DEBUG_FTP */ #define RECEIVE_DATA_PORT 0x8080 /* This is working now. */ /* #define IMMEDIATE_OPEN */ #include "tinytcp.h" #include "fileio.h" #include/* for printf, etc */ #include /* for kbhit, etc. Amazingly, Hitech C has these entry points too! */ #include /* for strcpy, etc. */ /* the following are what these seem to be */ #define isina kbhit #define busyina getch #define busyouta putch /* Sockets */ extern struct tcp_Socket s_og_ctl, /* outgoing connection socket */ s_og_data, /* data socket */ s_ic_ctl, /* server control socket */ s_ic_data; /* server data socket */ /* Receive buffer for client side. */ extern char b_response[ 120 ]; /* response buffer */ extern int i_response; /* index into response buf */ /* Client output command buffer */ extern char b_c_command[ 82 ]; /* send buffer */ /* Server output buffer */ extern char b_s_response[ 128 ]; /* server output buffer */ /* Server file transfer buffer, index, and length */ extern Byte b_s_data[ 1024 ]; /* server output buffer */ extern int n_s_sent, /* bytes sent of buffer */ n_s_left; /* bytes left in serv2 buffer */ /* file handle for retrieve */ extern char recv_filename[ 82 ]; extern FH p_recv_file; /* file handle for server */ extern char send_filename[ 82 ]; extern FH p_send_file; static char * get_a_number P(( char *ps, unsigned short *pn )); /* ----- ftp server data handler ------------------------------------ */ Void ftp_server_handler( s, dp, len ) struct tcp_Socket * s; Byte * dp; int len; { S8 unsigned short l, h; S8 char * p; static int first_time = 1; static int his_data_port = RECEIVE_DATA_PORT; /* THINK I NEED TO COLLECT DATA UNTIL I RECEIVE AN ENTIRE STRING TERMINATED WITH CR/LF. */ /* #ifdef DEBUG_FTP */ printf( "in ftp_server_handler. dp %08lx len %d, his port %04x\n", dp, len, s -> hisport ); /* #endif */ if( len < 0 ) { /* 0 = EOF, -1 = close */ /* Close of port. What is there to say? I suppose I need to redo the listen. */ return; } /* Here's the usual exchange: (open) 220 tritium FTP server ready. user rickr 331 password required for rickr. pass grelber 230 user rickr logged on. retr \temp\2 150 opening blah blah Data port is opened. Data gets sent. Data port is closed. quit 221 goodbye. */ /* When I enter 'get' in FTP on OS/2, he sends me a PORT message... */ /* His port number is at s -> hisport */ /* Set up the reply */ if( len == 0 ) { if( first_time ) { strcat( b_s_response, "220 Tiny-TCP FTP server ready.\r\n" ); first_time = 0; } else return; } else if( strncmp( ( char * ) dp, "USER", 4 ) == 0 ) { strcat( b_s_response, "230 No logon required.\r\n" ); } else if( strncmp( ( char * ) dp, "PASS", 4 ) == 0 ) { strcat( b_s_response, "230 No logon required.\r\n" ); } else if( strncmp( ( char * ) dp, "PORT", 4 ) == 0 ) { /* I get 192,9,201,2,4,7 */ p = ( char * ) dp + 4; p = get_a_number( p, &h ); /* 192 */ if( *p != ',' ) goto syntax_error; ++p; p = get_a_number( p, &h ); /* 9 */ if( *p != ',' ) goto syntax_error; ++p; p = get_a_number( p, &h ); /* 201 */ if( *p != ',' ) goto syntax_error; ++p; p = get_a_number( p, &h ); /* 2 */ if( *p != ',' ) goto syntax_error; ++p; p = get_a_number( p, &h ); /* 4 */ if( *p != ',' ) goto syntax_error; ++p; p = get_a_number( p, &l ); /* 7 */ his_data_port = ( int )(( h << 8 ) + l ); printf( "His data port set to %04x\n", his_data_port ); strcat( b_s_response, "200 Okay.\r\n" ); } else if( strncmp( ( char * ) dp, "RETR", 4 ) == 0 ) { if( *( dp + 4 ) != ' ' ) { syntax_error: strcat( b_s_response, "501 Syntax error.\r\n" ); return; } strncpy( send_filename, ( char * ) dp + 4, len - 5 ); send_filename[ len - 5 ] = '\0'; printf( "retrieving file: %s\n", send_filename ); /* Open the output file */ p_send_file = my_open( send_filename, MY_OPEN_READ ); if( p_send_file == ( FH ) 0 ) { strcat( b_s_response, "550 File doesn't exist.\r\n" ); return; } /* Open a socket for the send data. */ tcp_Open( &s_ic_data, /* socket */ RECEIVE_DATA_PORT, /* my port */ s -> hisaddr, /* host to call */ his_data_port, /* his port */ ( Procref ) ftp_dataHandler ); /* handler for data receive */ strcat( b_s_response, "150 File open.\r\n" ); /* When transfer is complete, need to send 226. */ /* } else if( strncmp( ( char * ) dp, "STOR", 4 ) == 0 ) { */ /* STOR is like RETR, but needs to use the recv_filename instead. I think I can use the same data handler... */ } else if( strncmp( ( char * ) dp, "QUIT", 4 ) == 0 ) { strcat( b_s_response, "221 Goodbye.\r\n" ); } else if( strncmp( ( char * ) dp, "HELP", 4 ) == 0 ) { strcat( b_s_response, "211 When we say Tiny, we mean it.\r\n" ); } else if( len > 0 ) { /* dump it to the screen (Hm, to stdout?) */ printf( "** Unrecognized command: " ); while( len > 0 ) { if(( *dp < 32 ) || ( *dp > 126 )) printf( " %02x ", *dp ); else putchar( ( char ) *dp ); ++dp; --len; } putchar( '\n' ); strcat( b_s_response, "502 Command not implemented.\r\n" ); } } /* ----- get a number (unsigned short) ------------------------------ */ static char * get_a_number( ps, pn ) char *ps; unsigned short *pn; { S8 unsigned short us; us = 0; /* ignore leading blanks */ while( *ps == ' ' ) ++ps; /* convert any digits present */ while(( *ps >= '0' ) && ( *ps <= '9' )) us = ( unsigned short )(( 10 * us ) + *ps++ - '0' ); /* store the converted number */ *pn = us; /* return pointer to next char */ return ps; } /* end of tinyft2.c */