Develop and Download Open Source Software

Browse Subversion Repository

Annotation of /trunk/sub.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 26 - (hide annotations) (download) (as text)
Sat Feb 28 02:04:32 2009 UTC (15 years, 1 month ago) by hirohitohigashi
File MIME type: text/x-csrc
File size: 11191 byte(s)
added list and nlist functions.

1 hirohitohigashi 17 /*
2     Some global functions for libOftp.
3    
4     Copyright (c) 2009-2009 hirohito higashi. All rights reserved.
5     This file is distributed under BSD license.
6     */
7    
8    
9     /***** Feature test switches ************************************************/
10     /***** System headers *******************************************************/
11     #include <stdlib.h>
12     #include <unistd.h>
13     #include <sys/types.h>
14     #include <sys/socket.h>
15     #include <errno.h>
16     #include <string.h>
17     #include <arpa/inet.h>
18     #include <sys/time.h>
19 hirohitohigashi 20 #include <sys/select.h>
20 hirohitohigashi 17
21    
22     /***** Local headers ********************************************************/
23     #include "liboftp.h"
24     #include "sub.h"
25    
26    
27     /***** Constat values *******************************************************/
28     /***** Macros ***************************************************************/
29     /***** Typedefs *************************************************************/
30     /***** Function prototypes **************************************************/
31     /***** Local variables ******************************************************/
32     /***** Global variables *****************************************************/
33     /***** Signal catching functions ********************************************/
34     /***** Local functions ******************************************************/
35     /***** Global functions *****************************************************/
36    
37     /****************************************************************************/
38     /*! send n bytes.
39     *
40     *@param sd socket descriptor
41     *@param buf pointer of send buffer
42     *@param len message length
43     *@param flags flags of send()
44     *@retval int number of bytes sent, or -1 if an error.
45     *@note
46     *
47     */
48     int sendn( int sd, const char *buf, int len, int flags )
49     {
50     int left = len;
51     int n;
52    
53     while( left > 0 ) {
54     n = send( sd, buf, left, flags );
55     if( n < 0 ) {
56     if( errno == EINTR ) continue;
57     DEBUGPRINT1( "sendn: get minus. %s\n", strerror(errno) );
58     return n;
59     }
60     buf += n;
61     left -= n;
62     }
63    
64     return len;
65     }
66    
67    
68    
69     /****************************************************************************/
70     /*! read a line
71     *
72     *@param sd socket descriptor
73     *@param buf pointer of receive buffer
74     *@param bufsiz buffer size
75     *@param flags flags of recv()
76     *@retval int number of bytes received, or -1 if an error.
77     *@note
78     *
79     */
80     int recv_line( int sd, char *buf, int bufsiz, int flags )
81     {
82     int n;
83     char c;
84     char *p = buf;
85     int total_len = 0;
86    
87     bufsiz--;
88    
89     while( 1 ) {
90     n = recv( sd, &c, 1, flags );
91     if( n < 0 ) {
92     if( errno == EINTR ) continue;
93     *p = 0;
94     DEBUGPRINT1( "recv_line: get minus. %s\n", strerror(errno) );
95     return n;
96     }
97    
98     *p++ = c;
99     total_len++;
100    
101     if( c == '\n' ) break;
102     if( bufsiz < total_len ) break;
103     }
104     *p = 0;
105    
106     return total_len;
107     }
108    
109    
110    
111     /****************************************************************************/
112 hirohitohigashi 20 /*! send ftp command
113     *
114     *@param ftp pointer of LIBOFTP.
115     *@param cmd ftp command.
116     *@retval int 0 is no error, or -1 if an error.
117     *@note
118     *
119     */
120     int ftp_send_command( LIBOFTP *ftp, const char *cmd )
121     {
122     int ret;
123     DEBUGPRINT1( "SENDC: %s", cmd );
124     ret = sendn( ftp->socket, cmd, strlen( cmd ), 0 );
125     if( ret < 0 ) {
126     return ret;
127     }
128    
129     return 0;
130     }
131    
132    
133    
134     /****************************************************************************/
135 hirohitohigashi 17 /*! receive response
136     *
137     *@param ftp pointer of LIBOFTP.
138     *@param res_buf response buffer ( null ok )
139     *@param bufsiz response buffer size.
140     *@retval int response code, or error code (minus value)
141     *@note
142     *
143     */
144     int ftp_receive_response( LIBOFTP *ftp, char *res_buf, int bufsiz )
145     {
146     char str1[256];
147     int res_code = 0;
148     int n;
149    
150     if( res_buf ) {
151     *res_buf = 0;
152     }
153    
154     /*
155     * receive 1st line.
156     */
157     if( (n = recv_line( ftp->socket, str1, sizeof(str1), 0 )) < 0 ) {
158     return -1;
159     }
160     DEBUGPRINT1( "RESP1: %s", str1 );
161     if( n < 3 ) {
162     return -2;
163     }
164     res_code = atoi( str1 );
165    
166     /*
167     * if exist next line, receive all response.
168     */
169     if( str1[3] == '-' ) {
170     while( 1 ) {
171     if( (n = recv_line( ftp->socket, str1, sizeof(str1), 0 )) < 0 ) {
172     return -1;
173     }
174     DEBUGPRINT1( "RESP2: %s", str1 );
175     if( n < 3 ) {
176     return -2;
177     }
178    
179     if( atoi(str1) == res_code && str1[3] == ' ' ) {
180     break;
181     }
182     }
183     }
184    
185     /*
186     * copy a response strings to user buffer, if need
187     */
188     if( res_buf ) {
189     strncpy( res_buf, str1, bufsiz );
190     res_buf[bufsiz-1] = 0;
191     }
192    
193     return res_code;
194     }
195    
196    
197    
198     /****************************************************************************/
199     /*! set receive timeout.
200     *
201     *@param sock socket descriptor
202     *@param sec second.
203     *@param usec micro second.
204     *@retval int 0 if no error, -1 if error occurred.
205     *@note
206     *
207     */
208     int ftp_set_so_rcvtimeo( int sock, int sec, int usec )
209     {
210     struct timeval tval;
211    
212     tval.tv_sec = sec;
213     tval.tv_usec = usec;
214    
215     return setsockopt( sock, SOL_SOCKET, SO_RCVTIMEO, &tval, sizeof(struct timeval) );
216     }
217    
218    
219    
220     /****************************************************************************/
221 hirohitohigashi 21 /*! ������������������������������������������
222 hirohitohigashi 17 *
223     *@param ftp LIBOFTP���������������������
224 hirohitohigashi 26 *@param cmd FTP������������ (ex: RETR, STOR, APPE)
225 hirohitohigashi 17 *@param fname ������������������������������
226     *@retval int ������������, ������������������������������
227     *@note
228 hirohitohigashi 21 ������������������������������������������������������������������������������������������������
229 hirohitohigashi 17 ���) ���������
230 hirohitohigashi 21 (port open) --> PORT --> RETR
231 hirohitohigashi 17 */
232 hirohitohigashi 26 int ftp_getready_active( LIBOFTP *ftp, const char *cmd, const char *fname )
233 hirohitohigashi 20 {
234     int sock;
235     struct sockaddr_in saddr;
236     int saddr_len;
237     unsigned char *ip, *pt;
238     char str1[256];
239     int res;
240     struct timeval timeout;
241     fd_set rfds, wfds;
242    
243     /*
244     * open data port.
245     * (note)
246     * same command port ip and automatic random port.
247     */
248     sock = socket( PF_INET, SOCK_STREAM, IPPROTO_TCP );
249     if( sock < 0 ) {
250     DEBUGPRINT1( "getready_active: can't open socket. %s\n", strerror(errno) );
251     return -1;
252     }
253    
254     memset( &saddr, 0, sizeof( saddr ) );
255     saddr_len = sizeof( saddr );
256     if( getsockname( ftp->socket, (struct sockaddr *)&saddr, &saddr_len ) < 0 ) {
257     DEBUGPRINT1( "getready_active: can't get control socket name. %s\n", strerror(errno) );
258     close( sock );
259     return -2;
260     }
261     saddr.sin_port = htons( 0 );
262    
263     if( bind( sock, (struct sockaddr *)&saddr, sizeof( saddr ) ) < 0 ) {
264     DEBUGPRINT1( "getready_active: can't bind socket. %s\n", strerror(errno) );
265     close( sock );
266     return -2;
267     }
268    
269     if( listen( sock, 1 ) < 0 ) {
270     DEBUGPRINT1( "getready_active: can't listen socket. %s\n", strerror(errno) );
271     close( sock );
272     return -2;
273     }
274    
275    
276     /*
277     * make PORT command.
278     */
279     memset( &saddr, 0, sizeof( saddr ) );
280     saddr_len = sizeof( saddr );
281     if( getsockname( sock, (struct sockaddr *)&saddr, &saddr_len ) < 0 ) {
282     DEBUGPRINT1( "getready_active: can't get data socket name. %s\n", strerror(errno) );
283     close( sock );
284     return -2;
285     }
286     ip = (unsigned char*)&saddr.sin_addr.s_addr;
287     pt = (unsigned char*)&saddr.sin_port;
288     snprintf( str1, sizeof(str1), "PORT %d,%d,%d,%d,%d,%d\r\n", ip[0], ip[1], ip[2], ip[3], pt[0], pt[1] );
289    
290     /*
291     * send PORT command and get status.
292     */
293     if( ftp_send_command( ftp, str1 ) < 0 ) {
294     close( sock );
295     return -1;
296     }
297     res = ftp_receive_response( ftp, str1, sizeof(str1) );
298     if( res != 200 ) { /* 200: Command okay. */
299     DEBUGPRINT1( "getready_active: get PORT response code %d\n", res );
300     close( sock );
301     return -2;
302     }
303    
304     /*
305     * send ftp command.
306     */
307 hirohitohigashi 26 if( fname ) {
308     snprintf( str1, sizeof(str1), "%s %s\r\n", cmd, fname );
309     } else {
310     snprintf( str1, sizeof(str1), "%s\r\n", cmd );
311     }
312 hirohitohigashi 20 if( ftp_send_command( ftp, str1 ) < 0 ) {
313     close( sock );
314     return -2;
315     }
316    
317     /*
318     * accept data connection with timeout.
319     */
320     timeout.tv_sec = ftp->timeout_sec;
321     timeout.tv_usec = 0;
322     FD_ZERO( &rfds );
323     FD_ZERO( &wfds );
324     FD_SET( sock, &rfds );
325     FD_SET( sock, &wfds );
326    
327     res = select( sock+1, &rfds, &wfds, 0, &timeout );
328     if( res == 0 ) { /* timeout */
329     DEBUGPRINT1( "getready_active: waiting connection timeout.%s\n", "" );
330     close( sock );
331     return -3;
332     }
333    
334     res = accept( sock, (struct sockaddr *)&saddr, &saddr_len );
335     close( sock );
336     if( res < 0 ) {
337     DEBUGPRINT1( "getready_active: socket accept error. %s\n", strerror(errno) );
338     close( sock );
339     return -1;
340     }
341     sock = res;
342    
343     /*
344     * get status.
345     */
346     res = ftp_receive_response( ftp, str1, sizeof(str1) );
347     if( res != 150 ) { /* 150: File status okay; about to open data connection. */
348     DEBUGPRINT1( "getready_active: get STOR/RETR response code %d\n", res );
349     close( sock );
350     return -2;
351     }
352    
353    
354     return sock;
355     }
356 hirohitohigashi 21
357    
358    
359     /****************************************************************************/
360     /*! ���������������������������������������
361     *
362     *@param ftp LIBOFTP���������������������
363 hirohitohigashi 26 *@param cmd FTP������������ (ex: RETR, STOR, APPE)
364 hirohitohigashi 21 *@param fname ������������������������������
365     *@retval int ������������, ������������������������������
366     *@note
367     ���������������������������������������������������������������������������������������������
368     ���) ���������
369     PASV --> RETR --> (port open)
370     */
371 hirohitohigashi 26 int ftp_getready_pasv( LIBOFTP *ftp, const char *cmd, const char *fname )
372 hirohitohigashi 21 {
373     char str1[256];
374     int res;
375     char *p;
376     int h1, h2, h3, h4, p1, p2;
377     struct sockaddr_in saddr;
378     int sock;
379    
380     /*
381     * send "PASV" command and get status.
382     */
383     str1[255] = 0;
384     snprintf( str1, sizeof(str1)-1, "PASV\r\n" );
385     if( ftp_send_command( ftp, str1 ) < 0 ) {
386     return -1;
387     }
388     res = ftp_receive_response( ftp, str1, sizeof(str1) );
389     if( res != 227 ) { /* 227: Entering Passive Mode */
390     DEBUGPRINT1( "getready_pasv: get ftp response code %d\n", res );
391     return -2;
392     }
393    
394     /*
395     * parse (h1,h2,h3,h4,p1,p2)
396     */
397     p = strchr( str1, '(' );
398     if( p == NULL ) {
399     DEBUGPRINT1( "getready_pasv: response parse error. %d", 1 );
400     return -2;
401     }
402     if( sscanf( p+1, "%d,%d,%d,%d,%d,%d", &h1, &h2, &h3, &h4, &p1, &p2 ) != 6 ) {
403     DEBUGPRINT1( "getready_pasv: response parse error. %d", 2 );
404     return -2;
405     }
406    
407    
408     /*
409     * send ftp command.
410     */
411 hirohitohigashi 26 if( fname ) {
412     snprintf( str1, sizeof(str1), "%s %s\r\n", cmd, fname );
413     } else {
414     snprintf( str1, sizeof(str1), "%s\r\n", cmd );
415     }
416 hirohitohigashi 21 if( ftp_send_command( ftp, str1 ) < 0 ) {
417     return -2;
418     }
419    
420     /*
421     * open data port.
422     */
423     sock = socket( PF_INET, SOCK_STREAM, IPPROTO_TCP );
424     if( sock < 0 ) {
425     DEBUGPRINT1( "getready_pasv: can't open socket. %s\n", strerror(errno) );
426     return -1;
427     }
428    
429     memset( &saddr, 0, sizeof( saddr ) );
430     saddr.sin_family = AF_INET;
431     saddr.sin_addr.s_addr = htonl( (((unsigned long)h1) << 24) | (h2 << 16) | (h3 << 8) | h4 );
432     saddr.sin_port = htons( (p1 << 8) | p2 );
433    
434     if( connect( sock, (struct sockaddr *)&saddr, sizeof( saddr ) ) < 0 ) {
435     DEBUGPRINT1( "getready_pasv: can't connect socket. %s\n", strerror(errno) );
436     close( sock );
437     return -2;
438     }
439     ftp_set_so_rcvtimeo( sock, ftp->timeout_sec, 0 );
440    
441     /*
442     * check response.
443     */
444     res = ftp_receive_response( ftp, 0, 0 );
445     if( res == 150 || res == 125 ) {
446     return sock;
447     } else {
448     close( sock );
449     return -2;
450     }
451     }

Back to OSDN">Back to OSDN
ViewVC Help
Powered by ViewVC 1.1.26