00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014 #include "midas.h"
00015 #include "msystem.h"
00016 #include "ftplib.h"
00017
00018 #ifndef FTP_SUCCESS
00019 #define FTP_SUCCESS 1
00020 #define FTP_NET_ERROR 802
00021 #define FTP_FILE_ERROR 803
00022 #define FTP_RESPONSE_ERROR 804
00023 #define FTP_INVALID_ARG 805
00024 #endif
00025
00026 static char bars[] = "/-\\|";
00027 int (*ftp_debug_func) (char *message);
00028 int (*ftp_error_func) (char *message);
00029
00030
00031
00032 void ftp_debug(int (*debug_func) (char *message), int (*error_func) (char *message))
00033
00034 {
00035 ftp_debug_func = debug_func;
00036 ftp_error_func = error_func;
00037 }
00038
00039
00040
00041 int ftp_connect(FTP_CON ** con, const char *host_name, unsigned short port)
00042
00043
00044 {
00045 struct sockaddr_in bind_addr;
00046 int sock;
00047 char str[4000];
00048 int status;
00049 struct hostent *phe;
00050
00051 *con = NULL;
00052
00053 #ifdef OS_WINNT
00054 {
00055 WSADATA WSAData;
00056
00057
00058 if (WSAStartup(MAKEWORD(1, 1), &WSAData) != 0)
00059 return FTP_NET_ERROR;
00060 }
00061 #endif
00062
00063 if ((sock = socket(AF_INET, SOCK_STREAM, 0)) == -1) {
00064 if (ftp_error_func)
00065 ftp_error_func("cannot create socket");
00066 return FTP_NET_ERROR;
00067 }
00068
00069
00070 memset(&bind_addr, 0, sizeof(bind_addr));
00071 bind_addr.sin_family = AF_INET;
00072 bind_addr.sin_addr.s_addr = 0;
00073 bind_addr.sin_port = htons(port);
00074
00075 #ifdef OS_VXWORKS
00076 {
00077 INT host_addr;
00078
00079 host_addr = hostGetByName(host_name);
00080 memcpy((char *) &(bind_addr.sin_addr), &host_addr, 4);
00081 }
00082 #else
00083 phe = gethostbyname(host_name);
00084 if (phe == NULL) {
00085 if (ftp_error_func)
00086 ftp_error_func("cannot get host name");
00087 return RPC_NET_ERROR;
00088 }
00089 memcpy((char *) &(bind_addr.sin_addr), phe->h_addr, phe->h_length);
00090 #endif
00091
00092 #ifdef OS_UNIX
00093 do {
00094 status = connect(sock, (struct sockaddr *) &bind_addr, sizeof(bind_addr));
00095
00096
00097 } while (status == -1 && errno == EINTR);
00098 #else
00099 status = connect(sock, (struct sockaddr *) &bind_addr, sizeof(bind_addr));
00100 #endif
00101
00102 if (status != 0) {
00103 sprintf(str, "cannot connect to host %s, port %d", host_name, port);
00104 if (ftp_error_func)
00105 ftp_error_func(str);
00106 return FTP_NET_ERROR;
00107 }
00108
00109
00110 *con = (FTP_CON *) malloc(sizeof(FTP_CON));
00111 (*con)->sock = sock;
00112 (*con)->data = 0;
00113
00114 memset(str, 0, sizeof(str));
00115 status = ftp_get_message(*con, str);
00116
00117
00118 if (status == FTP_QUIT || !ftp_good(status, 120, 220, EOF)) {
00119 closesocket(sock);
00120 free(*con);
00121 return FTP_NET_ERROR;
00122 }
00123
00124 return FTP_SUCCESS;
00125 }
00126
00127
00128
00129 int ftp_send_message(FTP_CON * con, char *message)
00130
00131 {
00132 if (send(con->sock, message, strlen(message), 0) == -1)
00133 return FTP_NET_ERROR;
00134
00135 if (send(con->sock, "\r\n", 2, 0) == -1)
00136 return FTP_NET_ERROR;
00137
00138 if (ftp_debug_func != NULL)
00139 ftp_debug_func(message);
00140
00141 return FTP_SUCCESS;
00142 }
00143
00144
00145
00146 int ftp_command(FTP_CON * con, const char *command, const char *param, ...)
00147
00148 {
00149 va_list args;
00150 char str[256];
00151 int status, code;
00152 BOOL result_ok;
00153
00154
00155 sprintf(str, command, param);
00156
00157
00158 if (ftp_send_message(con, str) != FTP_SUCCESS)
00159 return FTP_NET_ERROR;
00160
00161
00162 status = ftp_get_message(con, str);
00163 if (status == FTP_QUIT)
00164 return FTP_NET_ERROR;
00165
00166
00167 va_start(args, param);
00168
00169 result_ok = FALSE;
00170 do {
00171 code = va_arg(args, int);
00172 if (code == EOF)
00173 break;
00174
00175 if (code == status)
00176 result_ok = TRUE;
00177
00178 } while (!result_ok);
00179
00180 va_end(args);
00181
00182 if (!result_ok) {
00183 if (ftp_error_func != NULL)
00184 ftp_error_func(str);
00185
00186 return FTP_RESPONSE_ERROR;
00187 }
00188
00189 return -status;
00190 }
00191
00192
00193
00194 int ftp_get_message(FTP_CON * con, char *message)
00195
00196 {
00197 int i;
00198
00199 for (i = 0;; i++) {
00200 if (recv(con->sock, &message[i], 1, 0) != 1)
00201 return FTP_QUIT;
00202
00203 if (i > 1 && message[i] == 10 && message[i - 1] == 13)
00204 break;
00205 }
00206
00207 message[i - 1] = 0;
00208
00209 con->err_no = atoi(message);
00210
00211 if (ftp_debug_func != NULL)
00212 ftp_debug_func(message);
00213
00214
00215 if (message[3] == '-')
00216 ftp_get_message(con, message + strlen(message));
00217
00218 return con->err_no;
00219 }
00220
00221
00222
00223 BOOL ftp_good(int number, ...)
00224
00225 {
00226 va_list args;
00227 BOOL result;
00228 int code;
00229
00230 va_start(args, number);
00231 result = FALSE;
00232
00233 do {
00234 code = va_arg(args, int);
00235 if (code == EOF)
00236 break;
00237
00238 if (code == number)
00239 result = TRUE;
00240
00241 } while (!result);
00242
00243 va_end(args);
00244
00245 return result;
00246 }
00247
00248
00249
00250 int ftp_data(FTP_CON * con, const char *command, const char *file)
00251
00252 {
00253 struct sockaddr_in data, from;
00254 struct hostent *host;
00255 char host_name[256];
00256 int listen_socket, data_socket;
00257 unsigned int len = sizeof(data), fromlen = sizeof(from);
00258 int one = 1, status;
00259 char *a, *b;
00260
00261 memset(&data, 0, sizeof(data));
00262 memset(&from, 0, sizeof(from));
00263
00264 if (gethostname(host_name, sizeof(host_name)) == -1)
00265 return FTP_NET_ERROR;
00266
00267 if ((host = (struct hostent *) gethostbyname(host_name)) == 0)
00268 return FTP_NET_ERROR;
00269
00270 if ((listen_socket = socket(AF_INET, SOCK_STREAM, 0)) == -1)
00271 return FTP_NET_ERROR;
00272
00273 if (setsockopt(listen_socket, SOL_SOCKET, SO_REUSEADDR,
00274 (char *) &one, sizeof(one)) < 0) {
00275 closesocket(listen_socket);
00276 return FTP_NET_ERROR;
00277 }
00278
00279 data.sin_family = AF_INET;
00280 data.sin_port = htons(0);
00281 data.sin_addr.s_addr = *(unsigned long *) *(host->h_addr_list);
00282
00283 if (bind(listen_socket, (struct sockaddr *) &data, sizeof(data)) == -1) {
00284 closesocket(listen_socket);
00285 return FTP_NET_ERROR;
00286 }
00287
00288 #ifdef OS_WINNT
00289 if (getsockname(listen_socket, (struct sockaddr *) &data, (int *)&len) < 0) {
00290 #else
00291 if (getsockname(listen_socket, (struct sockaddr *) &data, &len) < 0) {
00292 #endif
00293 closesocket(listen_socket);
00294 return FTP_NET_ERROR;
00295 }
00296
00297 if (listen(listen_socket, 1) != 0) {
00298 closesocket(listen_socket);
00299 return FTP_NET_ERROR;
00300 }
00301
00302 a = (char *) &data.sin_addr;
00303 b = (char *) &data.sin_port;
00304
00305 status = ftp_port(con, FTP_CUT(a[0]), FTP_CUT(a[1]), FTP_CUT(a[2]),
00306 FTP_CUT(a[3]), FTP_CUT(b[0]), FTP_CUT(b[1]));
00307 if (status != FTP_SUCCESS)
00308 return FTP_NET_ERROR;
00309
00310 status = ftp_command(con, command, file, 200, 120, 150, 125, 250, EOF);
00311 if (status >= 0)
00312 return status;
00313
00314 #ifdef OS_WINNT
00315 data_socket = accept(listen_socket, (struct sockaddr *) &from, (int *)&fromlen);
00316 #else
00317 data_socket = accept(listen_socket, (struct sockaddr *) &from, &fromlen);
00318 #endif
00319
00320 if (data_socket == -1) {
00321 closesocket(listen_socket);
00322 return FTP_NET_ERROR;
00323 }
00324
00325 closesocket(listen_socket);
00326
00327 con->data = data_socket;
00328
00329 return status;
00330 }
00331
00332
00333
00334 int ftp_close(FTP_CON * con)
00335
00336 {
00337 char str[256];
00338
00339 closesocket(con->data);
00340
00341 return ftp_get_message(con, str);
00342 }
00343
00344
00345
00346 int ftp_send(int sock, char *buffer, int n_bytes_to_write)
00347
00348 {
00349 int n_bytes_left, n_written;
00350
00351 n_bytes_left = n_bytes_to_write;
00352
00353 while (n_bytes_left > 0) {
00354 n_written = send(sock, buffer, n_bytes_left > 8192 ? 8192 : n_bytes_left, 0);
00355 if (n_written <= 0)
00356 return n_bytes_to_write - n_bytes_left;
00357
00358 n_bytes_left -= n_written;
00359 buffer += n_written;
00360 }
00361
00362 return n_bytes_to_write;
00363 }
00364
00365
00366
00367 int ftp_receive(int sock, char *buffer, int bsize)
00368
00369 {
00370 int count, i;
00371
00372 i = 0;
00373 while (TRUE) {
00374 count = recv(sock, buffer + i, bsize - 1 - i, 0);
00375 if (count <= 0)
00376 return i;
00377
00378 i += count;
00379 buffer[i] = 0;
00380
00381 if (i >= bsize - 1)
00382 return i;
00383 }
00384 }
00385
00386
00387
00388 int ftp_login(FTP_CON ** con, const char *host, unsigned short port,
00389 const char *user, const char *password, const char *account)
00390
00391 {
00392 int status;
00393
00394 status = ftp_connect(con, host, port);
00395 if (status != FTP_SUCCESS)
00396 return status;
00397
00398 status = ftp_user(*con, user);
00399 if (status >= 0)
00400 return status;
00401
00402 if (status == -230)
00403 return status;
00404
00405 if (status == -332) {
00406 if (account == NULL)
00407 return FTP_NET_ERROR;
00408
00409 status = ftp_account(*con, account);
00410 if (status < 1)
00411 return status;
00412
00413 if (status == -230)
00414 return status;
00415 }
00416
00417 return ftp_password(*con, password);
00418 }
00419
00420
00421
00422 int ftp_bye(FTP_CON * con)
00423
00424 {
00425 char str[256];
00426
00427 ftp_send_message(con, "QUIT");
00428 ftp_get_message(con, str);
00429
00430 closesocket(con->sock);
00431 free(con);
00432
00433 return FTP_SUCCESS;
00434 }
00435
00436
00437
00438 int ftp_port(FTP_CON * con, int a, int b, int c, int d, int e, int f)
00439
00440 {
00441 char cmd[256];
00442 int status;
00443
00444 sprintf(cmd, "PORT %d,%d,%d,%d,%d,%d", a, b, c, d, e, f);
00445 if (ftp_send_message(con, cmd) != FTP_SUCCESS)
00446 return FTP_NET_ERROR;
00447
00448 status = ftp_get_message(con, cmd);
00449 if (status == FTP_QUIT)
00450 return FTP_QUIT;
00451
00452 if (!ftp_good(status, 200, EOF))
00453 return FTP_NET_ERROR;
00454
00455 return FTP_SUCCESS;
00456 }
00457
00458
00459
00460 int ftp_move(FTP_CON * con, const char *oldname, const char *newname)
00461
00462 {
00463 int status;
00464
00465 status = ftp_command(con, "RNFR %s", oldname, 200, 350, EOF);
00466
00467 if (status < 0)
00468 return ftp_command(con, "RNTO %s", newname, 200, 250, EOF);
00469 else
00470 return status;
00471 }
00472
00473
00474
00475 int ftp_get(FTP_CON * con, const char *local_name, const char *remote_name)
00476
00477 {
00478 int fh;
00479 int status;
00480 char buff[8192];
00481 char str[256];
00482 int count, i;
00483 long total = 0;
00484 DWORD start, stop;
00485
00486 if (ftp_open_read(con, remote_name) >= 0)
00487 return con->err_no;
00488
00489 if ((fh = open(local_name, O_RDWR | O_CREAT | O_TRUNC | O_BINARY, 0644)) == -1)
00490 return FTP_FILE_ERROR;
00491
00492 start = ss_millitime();
00493
00494 while ((count = ftp_receive(con->data, buff, sizeof(buff))) > 0) {
00495 total += write(fh, buff, count);
00496 i = 0;
00497 if (ftp_debug_func != NULL) {
00498 printf("%c\r", bars[(i++) % 4]);
00499 fflush(stdout);
00500 }
00501 }
00502
00503 close(fh);
00504 stop = ss_millitime();
00505
00506 status = ftp_close(con);
00507 if (ftp_debug_func != NULL) {
00508 sprintf(str, "%ld bytes received in %1.2f seconds (%1.2lf kB/sec).",
00509 total, (stop - start) / 1000.0, total / 1024.0 / ((stop - start) / 1000.0));
00510 ftp_debug_func(str);
00511 }
00512
00513 return status;
00514 }
00515
00516
00517
00518 int ftp_put(FTP_CON * con, const char *local_name, const char *remote_name)
00519
00520 {
00521 int fh;
00522 int status;
00523 char buff[8193];
00524 char str[256];
00525 int count, i = 0;
00526 long total = 0;
00527 DWORD start, stop;
00528
00529 if (ftp_open_write(con, remote_name) >= 0)
00530 return con->err_no;
00531
00532 if ((fh = open(local_name, O_BINARY)) == -1)
00533 return FTP_FILE_ERROR;
00534
00535 start = ss_millitime();
00536
00537 while ((count = read(fh, buff, 8192)) > 0) {
00538 total += ftp_send(con->data, buff, count);
00539 if (ftp_debug_func != NULL) {
00540 printf("%c\r", bars[(i++) % 4]);
00541 fflush(stdout);
00542 }
00543 }
00544
00545 close(fh);
00546 stop = ss_millitime();
00547
00548 status = ftp_close(con);
00549 if (ftp_debug_func != NULL) {
00550 sprintf(str, "%ld bytes sent in %1.2f seconds (%1.2lf kB/sec).",
00551 total, (stop - start) / 1000.0, total / 1024.0 / ((stop - start) / 1000.0));
00552 ftp_debug_func(str);
00553 }
00554
00555 return status;
00556 }
00557
00558
00559
00560 char *ftp_pwd(FTP_CON * con)
00561
00562 {
00563 static char str[256];
00564 char tmp[256];
00565 int status;
00566
00567 str[0] = 0;
00568 if (ftp_send_message(con, "PWD") != FTP_SUCCESS)
00569 return str;
00570
00571 status = ftp_get_message(con, tmp);
00572
00573 if (status != 257) {
00574 if (ftp_error_func != NULL)
00575 ftp_error_func(tmp);
00576
00577 return str;
00578 }
00579
00580 sscanf(tmp, "%*[^\"]%*c%[^\"]%*s", str);
00581
00582 return str;
00583 }
00584
00585
00586
00587 int ftp_dir(FTP_CON * con, const char *file)
00588
00589 {
00590 char command[256], buffer[8192];
00591
00592 if (file == NULL || *file == '\0')
00593 strcpy(command, "LIST");
00594 else
00595 sprintf(command, "LIST %s", file);
00596
00597 if (ftp_data(con, command, "") >= 0)
00598 return con->err_no;
00599
00600 while (ftp_receive(con->data, buffer, sizeof(buffer)))
00601 printf(buffer);
00602
00603 return ftp_close(con);
00604 }
00605
00606