Develop and Download Open Source Software

Browse Subversion Repository

Contents of /trunk/sub.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 26 - (show 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 /*
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 #include <sys/select.h>
20
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 /*! 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 /*! 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 /*! ������������������������������������������
222 *
223 *@param ftp LIBOFTP���������������������
224 *@param cmd FTP������������ (ex: RETR, STOR, APPE)
225 *@param fname ������������������������������
226 *@retval int ������������, ������������������������������
227 *@note
228 ������������������������������������������������������������������������������������������������
229 ���) ���������
230 (port open) --> PORT --> RETR
231 */
232 int ftp_getready_active( LIBOFTP *ftp, const char *cmd, const char *fname )
233 {
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 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 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
357
358
359 /****************************************************************************/
360 /*! ���������������������������������������
361 *
362 *@param ftp LIBOFTP���������������������
363 *@param cmd FTP������������ (ex: RETR, STOR, APPE)
364 *@param fname ������������������������������
365 *@retval int ������������, ������������������������������
366 *@note
367 ���������������������������������������������������������������������������������������������
368 ���) ���������
369 PASV --> RETR --> (port open)
370 */
371 int ftp_getready_pasv( LIBOFTP *ftp, const char *cmd, const char *fname )
372 {
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 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 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