MIDAS
Loading...
Searching...
No Matches
ftplib.cxx
Go to the documentation of this file.
1/********************************************************************\
2
3 Name: ftplib.c
4 Created by: Originally written by Oleg Orel (orel@lpuds.oea.ihep.su),
5 translated from UNIX to NT by Urs Rohrer (rohrer@psi.ch),
6 simplified and adapted for MIDAS by Stefan Ritt.
7
8 Contents: File Transfer Protocol library
9
10 $Id$
11
12\********************************************************************/
13
14#include "midas.h"
15#include "msystem.h"
16#include "ftplib.h"
17
18#ifndef FTP_SUCCESS
19#define FTP_SUCCESS 1
20#define FTP_NET_ERROR 802
21#define FTP_FILE_ERROR 803
22#define FTP_RESPONSE_ERROR 804
23#define FTP_INVALID_ARG 805
24#endif
25
26static char bars[] = "/-\\|";
27int (*ftp_debug_func) (const char *message);
28int (*ftp_error_func) (const char *message);
29
30/*------------------------------------------------------------------*/
31
32void ftp_debug(int (*debug_func) (const char *message), int (*error_func) (const char *message))
33/* set message display functions for debug and error messages */
34{
37}
38
39/*------------------------------------------------------------------*/
40
41int ftp_connect(FTP_CON ** con, const char *host_name, unsigned short port)
42/* Connect to a FTP server on a host at a given port (usually 21).
43 Return a FTP_CON structure if successful */
44{
45 struct sockaddr_in bind_addr;
46 int sock;
47 char str[4000];
48 int status;
49 struct hostent *phe;
50
51 *con = NULL;
52
53#ifdef OS_WINNT
54 {
56
57 /* Start windows sockets */
58 if (WSAStartup(MAKEWORD(1, 1), &WSAData) != 0)
59 return FTP_NET_ERROR;
60 }
61#endif
62
63 if ((sock = socket(AF_INET, SOCK_STREAM, 0)) == -1) {
65 ftp_error_func("cannot create socket");
66 return FTP_NET_ERROR;
67 }
68
69 /* connect to remote node */
70 memset(&bind_addr, 0, sizeof(bind_addr));
71 bind_addr.sin_family = AF_INET;
72 bind_addr.sin_addr.s_addr = 0;
73 bind_addr.sin_port = htons(port);
74
75#ifdef OS_VXWORKS
76 {
78
80 memcpy((char *) &(bind_addr.sin_addr), &host_addr, 4);
81 }
82#else
84 if (phe == NULL) {
86 ftp_error_func("cannot get host name");
87 return RPC_NET_ERROR;
88 }
89 memcpy((char *) &(bind_addr.sin_addr), phe->h_addr, phe->h_length);
90#endif
91
92#ifdef OS_UNIX
93 do {
94 status = connect(sock, (struct sockaddr *) &bind_addr, sizeof(bind_addr));
95
96 /* don't return if an alarm signal was cought */
97 } while (status == -1 && errno == EINTR);
98#else
99 status = connect(sock, (struct sockaddr *) &bind_addr, sizeof(bind_addr));
100#endif
101
102 if (status != 0) {
103 sprintf(str, "cannot connect to host %s, port %d", host_name, port);
104 if (ftp_error_func)
106 return FTP_NET_ERROR;
107 }
108
109
110 *con = (FTP_CON *) malloc(sizeof(FTP_CON));
111 (*con)->sock = sock;
112 (*con)->data = 0;
113
114 memset(str, 0, sizeof(str));
116
117 /* check for status */
118 if (status == FTP_QUIT || !ftp_good(status, 120, 220, EOF)) {
119 closesocket(sock);
120 free(*con);
121 return FTP_NET_ERROR;
122 }
123
124 return FTP_SUCCESS;
125}
126
127/*------------------------------------------------------------------*/
128
130/* send a message to a FTP server */
131{
132 if (send(con->sock, message, strlen(message), 0) == -1)
133 return FTP_NET_ERROR;
134
135 if (send(con->sock, "\r\n", 2, 0) == -1)
136 return FTP_NET_ERROR;
137
138 if (ftp_debug_func != NULL)
140
141 return FTP_SUCCESS;
142}
143
144/*------------------------------------------------------------------*/
145
146int ftp_command(FTP_CON * con, const char *command, const char *param, ...)
147/* execute FTP command, check for return codes */
148{
150 char str[256];
151 int status, code;
153
154 /* compose command string */
155 sprintf(str, command, param);
156
157 /* send command */
159 return FTP_NET_ERROR;
160
161 /* read reply */
163 if (status == FTP_QUIT)
164 return FTP_NET_ERROR;
165
166 /* check reply code */
167 va_start(args, param);
168
170 do {
171 code = va_arg(args, int);
172 if (code == EOF)
173 break;
174
175 if (code == status)
176 result_ok = TRUE;
177
178 } while (!result_ok);
179
180 va_end(args);
181
182 if (!result_ok) {
183 if (ftp_error_func != NULL)
185
186 return FTP_RESPONSE_ERROR;
187 }
188
189 return -status;
190}
191
192/*------------------------------------------------------------------*/
193
195/* read message from FTP server */
196{
197 int i;
198
199 for (i = 0;; i++) {
200 if (recv(con->sock, &message[i], 1, 0) != 1)
201 return FTP_QUIT;
202
203 if (i > 1 && message[i] == 10 && message[i - 1] == 13)
204 break;
205 }
206
207 message[i - 1] = 0;
208
209 con->err_no = atoi(message);
210
211 if (ftp_debug_func != NULL)
213
214 /* check for continuation message */
215 if (message[3] == '-')
217
218 return con->err_no;
219}
220
221/*------------------------------------------------------------------*/
222
223BOOL ftp_good(int number, ...)
224/* check if number matches any code from argument list */
225{
227 BOOL result;
228 int code;
229
230 va_start(args, number);
231 result = FALSE;
232
233 do {
234 code = va_arg(args, int);
235 if (code == EOF)
236 break;
237
238 if (code == number)
239 result = TRUE;
240
241 } while (!result);
242
243 va_end(args);
244
245 return result;
246}
247
248/*------------------------------------------------------------------*/
249
250int ftp_data(FTP_CON * con, const char *command, const char *file)
251/* open data socket */
252{
253 struct sockaddr_in data, from;
254 struct hostent *host;
255 char host_name[256];
257 unsigned int len = sizeof(data), fromlen = sizeof(from);
258 int one = 1, status;
259 char *a, *b;
260
261 memset(&data, 0, sizeof(data));
262 memset(&from, 0, sizeof(from));
263
264 if (gethostname(host_name, sizeof(host_name)) == -1)
265 return FTP_NET_ERROR;
266
267 if ((host = (struct hostent *) gethostbyname(host_name)) == 0)
268 return FTP_NET_ERROR;
269
270 if ((listen_socket = socket(AF_INET, SOCK_STREAM, 0)) == -1)
271 return FTP_NET_ERROR;
272
274 (char *) &one, sizeof(one)) < 0) {
276 return FTP_NET_ERROR;
277 }
278
279 data.sin_family = AF_INET;
280 data.sin_port = htons(0);
281 data.sin_addr.s_addr = *(unsigned long *) *(host->h_addr_list);
282
283 if (bind(listen_socket, (struct sockaddr *) &data, sizeof(data)) == -1) {
285 return FTP_NET_ERROR;
286 }
287
288#ifdef OS_WINNT
289 if (getsockname(listen_socket, (struct sockaddr *) &data, (int *)&len) < 0) {
290#else
291 if (getsockname(listen_socket, (struct sockaddr *) &data, &len) < 0) {
292#endif
294 return FTP_NET_ERROR;
295 }
296
297 if (listen(listen_socket, 1) != 0) {
299 return FTP_NET_ERROR;
300 }
301
302 a = (char *) &data.sin_addr;
303 b = (char *) &data.sin_port;
304
305 status = ftp_port(con, FTP_CUT(a[0]), FTP_CUT(a[1]), FTP_CUT(a[2]),
306 FTP_CUT(a[3]), FTP_CUT(b[0]), FTP_CUT(b[1]));
307 if (status != FTP_SUCCESS)
308 return FTP_NET_ERROR;
309
310 status = ftp_command(con, command, file, 200, 120, 150, 125, 250, EOF);
311 if (status >= 0)
312 return status;
313
314#ifdef OS_WINNT
315 data_socket = accept(listen_socket, (struct sockaddr *) &from, (int *)&fromlen);
316#else
318#endif
319
320 if (data_socket == -1) {
322 return FTP_NET_ERROR;
323 }
324
326
327 con->data = data_socket;
328
329 return status;
330}
331
332/*------------------------------------------------------------------*/
333
335/* close data connection */
336{
337 char str[256];
338
339 closesocket(con->data);
340
341 return ftp_get_message(con, str);
342}
343
344/*------------------------------------------------------------------*/
345
346int ftp_send(int sock, const char *buffer, int n_bytes_to_write)
347/* send number of bytes over socket */
348{
350
352
353 while (n_bytes_left > 0) {
354 n_written = send(sock, buffer, n_bytes_left > 8192 ? 8192 : n_bytes_left, 0);
355 if (n_written <= 0)
357
359 buffer += n_written;
360 }
361
362 return n_bytes_to_write;
363}
364
365/*------------------------------------------------------------------*/
366
367int ftp_receive(int sock, char *buffer, int bsize)
368/* receive buffer from socket, return number of received bytes */
369{
370 int count, i;
371
372 i = 0;
373 while (TRUE) {
374 count = recv(sock, buffer + i, bsize - 1 - i, 0);
375 if (count <= 0)
376 return i;
377
378 i += count;
379 buffer[i] = 0;
380
381 if (i >= bsize - 1)
382 return i;
383 }
384}
385
386/*------------------------------------------------------------------*/
387
388int ftp_login(FTP_CON ** con, const char *host, unsigned short port,
389 const char *user, const char *password, const char *account)
390/* FTP login with username and password */
391{
392 int status;
393
394 status = ftp_connect(con, host, port);
395 if (status != FTP_SUCCESS)
396 return status;
397
398 status = ftp_user(*con, user);
399 if (status >= 0)
400 return status;
401
402 if (status == -230)
403 return status;
404
405 if (status == -332) {
406 if (account == NULL)
407 return FTP_NET_ERROR;
408
410 if (status < 1)
411 return status;
412
413 if (status == -230)
414 return status;
415 }
416
417 return ftp_password(*con, password);
418}
419
420/*------------------------------------------------------------------*/
421
423/* disconnect from FTP server */
424{
425 char str[256];
426
427 ftp_send_message(con, "QUIT");
429
430 closesocket(con->sock);
431 free(con);
432
433 return FTP_SUCCESS;
434}
435
436/*------------------------------------------------------------------*/
437
438int ftp_port(FTP_CON * con, int a, int b, int c, int d, int e, int f)
439/* set port for data connection */
440{
441 char cmd[256];
442 int status;
443
444 sprintf(cmd, "PORT %d,%d,%d,%d,%d,%d", a, b, c, d, e, f);
445 if (ftp_send_message(con, cmd) != FTP_SUCCESS)
446 return FTP_NET_ERROR;
447
448 status = ftp_get_message(con, cmd);
449 if (status == FTP_QUIT)
450 return FTP_QUIT;
451
452 if (!ftp_good(status, 200, EOF))
453 return FTP_NET_ERROR;
454
455 return FTP_SUCCESS;
456}
457
458/*------------------------------------------------------------------*/
459
460int ftp_move(FTP_CON * con, const char *oldname, const char *newname)
461/* move/rename file */
462{
463 int status;
464
465 status = ftp_command(con, "RNFR %s", oldname, 200, 350, EOF);
466
467 if (status < 0)
468 return ftp_command(con, "RNTO %s", newname, 200, 250, EOF);
469 else
470 return status;
471}
472
473/*------------------------------------------------------------------*/
474
475int ftp_get(FTP_CON * con, const char *local_name, const char *remote_name)
476/* get file */
477{
478 int fh;
479 int status;
480 char buff[8192];
481 char str[256];
482 int count, i;
483 long total = 0;
484 DWORD start, stop;
485
486 if (ftp_open_read(con, remote_name) >= 0)
487 return con->err_no;
488
489 if ((fh = open(local_name, O_RDWR | O_CREAT | O_TRUNC | O_BINARY, 0644)) == -1)
490 return FTP_FILE_ERROR;
491
492 start = ss_millitime();
493
494 while ((count = ftp_receive(con->data, buff, sizeof(buff))) > 0) {
495 total += write(fh, buff, count);
496 i = 0;
497 if (ftp_debug_func != NULL) {
498 printf("%c\r", bars[(i++) % 4]);
499 fflush(stdout);
500 }
501 }
502
503 close(fh);
504 stop = ss_millitime();
505
507 if (ftp_debug_func != NULL) {
508 sprintf(str, "%ld bytes received in %1.2f seconds (%1.2lf kB/sec).",
509 total, (stop - start) / 1000.0, total / 1024.0 / ((stop - start) / 1000.0));
511 }
512
513 return status;
514}
515
516/*------------------------------------------------------------------*/
517
518int ftp_put(FTP_CON * con, const char *local_name, const char *remote_name)
519/* put file */
520{
521 int fh;
522 int status;
523 char buff[8193];
524 char str[256];
525 int count, i = 0;
526 long total = 0;
527 DWORD start, stop;
528
529 if (ftp_open_write(con, remote_name) >= 0)
530 return con->err_no;
531
532 if ((fh = open(local_name, O_BINARY)) == -1)
533 return FTP_FILE_ERROR;
534
535 start = ss_millitime();
536
537 while ((count = read(fh, buff, 8192)) > 0) {
538 total += ftp_send(con->data, buff, count);
539 if (ftp_debug_func != NULL) {
540 printf("%c\r", bars[(i++) % 4]);
541 fflush(stdout);
542 }
543 }
544
545 close(fh);
546 stop = ss_millitime();
547
549 if (ftp_debug_func != NULL) {
550 sprintf(str, "%ld bytes sent in %1.2f seconds (%1.2lf kB/sec).",
551 total, (stop - start) / 1000.0, total / 1024.0 / ((stop - start) / 1000.0));
553 }
554
555 return status;
556}
557
558/*------------------------------------------------------------------*/
559
561/* show present working directory */
562{
563 static char str[256];
564 char tmp[256];
565 int status;
566
567 str[0] = 0;
568 if (ftp_send_message(con, "PWD") != FTP_SUCCESS)
569 return str;
570
572
573 if (status != 257) {
574 if (ftp_error_func != NULL)
576
577 return str;
578 }
579
580 sscanf(tmp, "%*[^\"]%*c%[^\"]%*s", str);
581
582 return str;
583}
584
585/*------------------------------------------------------------------*/
586
587int ftp_dir(FTP_CON * con, const char *file)
588/* display directory */
589{
590 char command[256], buffer[8192];
591
592 if (file == NULL || *file == '\0')
593 strcpy(command, "LIST");
594 else
595 sprintf(command, "LIST %s", file);
596
597 if (ftp_data(con, command, "") >= 0)
598 return con->err_no;
599
600 while (ftp_receive(con->data, buffer, sizeof(buffer)))
601 printf("%s", buffer);
602
603 return ftp_close(con);
604}
605
606/*------------------------------------------------------------------*/
#define FALSE
Definition cfortran.h:309
int(* ftp_debug_func)(const char *message)
Definition ftplib.cxx:27
int ftp_login(FTP_CON **con, const char *host, unsigned short port, const char *user, const char *password, const char *account)
Definition ftplib.cxx:388
int ftp_close(FTP_CON *con)
Definition ftplib.cxx:334
static char bars[]
Definition ftplib.cxx:26
int(* ftp_error_func)(const char *message)
Definition ftplib.cxx:28
#define FTP_SUCCESS
Definition ftplib.cxx:19
int ftp_command(FTP_CON *con, const char *command, const char *param,...)
Definition ftplib.cxx:146
int ftp_send_message(FTP_CON *con, const char *message)
Definition ftplib.cxx:129
int ftp_dir(FTP_CON *con, const char *file)
Definition ftplib.cxx:587
#define FTP_RESPONSE_ERROR
Definition ftplib.cxx:22
char * ftp_pwd(FTP_CON *con)
Definition ftplib.cxx:560
void ftp_debug(int(*debug_func)(const char *message), int(*error_func)(const char *message))
Definition ftplib.cxx:32
#define FTP_FILE_ERROR
Definition ftplib.cxx:21
int ftp_send(int sock, const char *buffer, int n_bytes_to_write)
Definition ftplib.cxx:346
int ftp_get_message(FTP_CON *con, char *message)
Definition ftplib.cxx:194
int ftp_connect(FTP_CON **con, const char *host_name, unsigned short port)
Definition ftplib.cxx:41
#define FTP_NET_ERROR
Definition ftplib.cxx:20
int ftp_data(FTP_CON *con, const char *command, const char *file)
Definition ftplib.cxx:250
int ftp_receive(int sock, char *buffer, int bsize)
Definition ftplib.cxx:367
int ftp_put(FTP_CON *con, const char *local_name, const char *remote_name)
Definition ftplib.cxx:518
int ftp_port(FTP_CON *con, int a, int b, int c, int d, int e, int f)
Definition ftplib.cxx:438
int ftp_bye(FTP_CON *con)
Definition ftplib.cxx:422
int ftp_get(FTP_CON *con, const char *local_name, const char *remote_name)
Definition ftplib.cxx:475
BOOL ftp_good(int number,...)
Definition ftplib.cxx:223
int ftp_move(FTP_CON *con, const char *oldname, const char *newname)
Definition ftplib.cxx:460
#define ftp_open_read(ftp, file)
Definition ftplib.h:40
#define ftp_account(ftp, acc)
Definition ftplib.h:31
#define ftp_password(ftp, pas)
Definition ftplib.h:33
#define FTP_CUT(x)
Definition ftplib.h:23
#define ftp_open_write(ftp, file)
Definition ftplib.h:41
#define FTP_QUIT
Definition ftplib.h:20
#define ftp_user(ftp, user)
Definition ftplib.h:32
#define RPC_NET_ERROR
Definition midas.h:701
unsigned int DWORD
Definition mcstd.h:51
#define O_BINARY
Definition msystem.h:219
DWORD ss_millitime()
Definition system.cxx:3393
char param[10][256]
Definition mana.cxx:250
void * data
Definition mana.cxx:268
char host_name[HOST_NAME_LENGTH]
Definition mana.cxx:242
double count
Definition mdump.cxx:33
INT i
Definition mdump.cxx:32
#define closesocket(s)
Definition melog.cxx:29
DWORD BOOL
Definition midas.h:105
int INT
Definition midas.h:129
#define TRUE
Definition midas.h:182
#define message(type, str)
#define read(n, a, f)
#define write(n, a, f, d)
double total[100]
Definition odbhist.cxx:42
char str[256]
Definition odbhist.cxx:33
DWORD status
Definition odbhist.cxx:39
TH1X EXPRT * h1_book(const char *name, const char *title, int bins, double min, double max)
Definition rmidas.h:24
double d
Definition system.cxx:1311
char c
Definition system.cxx:1310
static double e(void)
Definition tinyexpr.c:136