1 /* 2 * Copyright (c) 1985 Regents of the University of California. 3 * All rights reserved. The Berkeley software License Agreement 4 * specifies the terms and conditions for redistribution. 5 */ 6 7 #ifndef lint 8 static char sccsid[] = "@(#)ftp.c 5.11 (Berkeley) 04/02/86"; 9 #endif not lint 10 11 #include "ftp_var.h" 12 13 #include <sys/stat.h> 14 #include <sys/ioctl.h> 15 #include <sys/socket.h> 16 #include <sys/time.h> 17 #include <sys/types.h> 18 19 #include <netinet/in.h> 20 #include <arpa/ftp.h> 21 #include <arpa/telnet.h> 22 23 #include <stdio.h> 24 #include <signal.h> 25 #include <errno.h> 26 #include <netdb.h> 27 #include <fcntl.h> 28 #include <pwd.h> 29 30 struct sockaddr_in hisctladdr; 31 struct sockaddr_in data_addr; 32 int data = -1; 33 int telflag = 0; 34 int abrtflag = 0; 35 int ptflag = 0; 36 int connected; 37 struct sockaddr_in myctladdr; 38 uid_t getuid(); 39 40 FILE *cin, *cout; 41 FILE *dataconn(); 42 43 char * 44 hookup(host, port) 45 char *host; 46 int port; 47 { 48 register struct hostent *hp = 0; 49 int s,len,oldverbose; 50 static char hostnamebuf[80]; 51 char msg[2]; 52 53 bzero((char *)&hisctladdr, sizeof (hisctladdr)); 54 hisctladdr.sin_addr.s_addr = inet_addr(host); 55 if (hisctladdr.sin_addr.s_addr != -1) { 56 hisctladdr.sin_family = AF_INET; 57 (void) strcpy(hostnamebuf, host); 58 } 59 else { 60 hp = gethostbyname(host); 61 if (hp == NULL) { 62 printf("%s: unknown host\n", host); 63 code = -1; 64 return((char *) 0); 65 } 66 hisctladdr.sin_family = hp->h_addrtype; 67 bcopy(hp->h_addr_list[0], 68 (caddr_t)&hisctladdr.sin_addr, hp->h_length); 69 (void) strcpy(hostnamebuf, hp->h_name); 70 } 71 hostname = hostnamebuf; 72 s = socket(hisctladdr.sin_family, SOCK_STREAM, 0); 73 if (s < 0) { 74 perror("ftp: socket"); 75 code = -1; 76 return (0); 77 } 78 hisctladdr.sin_port = port; 79 while (connect(s, &hisctladdr, sizeof (hisctladdr)) < 0) { 80 if (hp && hp->h_addr_list[1]) { 81 int oerrno = errno; 82 83 fprintf(stderr, "ftp: connect to address %s: ", 84 inet_ntoa(hisctladdr.sin_addr)); 85 errno = oerrno; 86 perror((char *) 0); 87 hp->h_addr_list++; 88 bcopy(hp->h_addr_list[0], 89 (caddr_t)&hisctladdr.sin_addr, hp->h_length); 90 fprintf(stdout, "Trying %s...\n", 91 inet_ntoa(hisctladdr.sin_addr)); 92 (void) close(s); 93 s = socket(hisctladdr.sin_family, SOCK_STREAM, 0); 94 if (s < 0) { 95 perror("ftp: socket"); 96 code = -1; 97 return (0); 98 } 99 continue; 100 } 101 perror("ftp: connect"); 102 code = -1; 103 goto bad; 104 } 105 len = sizeof (myctladdr); 106 if (getsockname(s, (char *)&myctladdr, &len) < 0) { 107 perror("ftp: getsockname"); 108 code = -1; 109 goto bad; 110 } 111 cin = fdopen(s, "r"); 112 cout = fdopen(s, "w"); 113 if (cin == NULL || cout == NULL) { 114 fprintf(stderr, "ftp: fdopen failed.\n"); 115 if (cin) 116 (void) fclose(cin); 117 if (cout) 118 (void) fclose(cout); 119 code = -1; 120 goto bad; 121 } 122 if (verbose) 123 printf("Connected to %s.\n", hostname); 124 if (getreply(0) != 2) { /* read startup message from server */ 125 if (cin) 126 (void) fclose(cin); 127 if (cout) 128 (void) fclose(cout); 129 code = -1; 130 goto bad; 131 } 132 133 /* test to see if server command parser understands TELNET SYNC command */ 134 135 fprintf(cout,"%c%c",IAC,NOP); 136 (void) fflush(cout); 137 *msg = IAC; 138 *(msg+1) = DM; 139 if (send(s,msg,2,MSG_OOB) != 2) 140 perror("sync"); 141 oldverbose = verbose; 142 if (!debug) 143 verbose = -1; 144 if (command("NOOP") == COMPLETE) 145 telflag = 1; 146 else 147 telflag = 0; 148 verbose = oldverbose; 149 return (hostname); 150 bad: 151 (void) close(s); 152 return ((char *)0); 153 } 154 155 login(host) 156 char *host; 157 { 158 char tmp[80]; 159 char *user, *pass, *acct, *getlogin(), *mygetpass(); 160 int n, aflag = 0; 161 162 user = pass = acct = 0; 163 if (ruserpass(host, &user, &pass, &acct) < 0) { 164 disconnect(); 165 code = -1; 166 return(0); 167 } 168 if (user == NULL) { 169 char *myname = getlogin(); 170 171 if (myname == NULL) { 172 struct passwd *pp = getpwuid(getuid()); 173 174 if (pp != NULL) 175 myname = pp->pw_name; 176 } 177 printf("Name (%s:%s): ", host, myname); 178 (void) fgets(tmp, sizeof(tmp) - 1, stdin); 179 tmp[strlen(tmp) - 1] = '\0'; 180 if (*tmp == '\0') 181 user = myname; 182 else 183 user = tmp; 184 } 185 n = command("USER %s", user); 186 if (n == CONTINUE) { 187 if (pass == NULL) 188 pass = mygetpass("Password:"); 189 n = command("PASS %s", pass); 190 } 191 if (n == CONTINUE) { 192 aflag++; 193 acct = mygetpass("Account:"); 194 n = command("ACCT %s", acct); 195 } 196 if (n != COMPLETE) { 197 fprintf(stderr, "Login failed.\n"); 198 return (0); 199 } 200 if (!aflag && acct != NULL) 201 (void) command("ACCT %s", acct); 202 if (proxy) 203 return(1); 204 for (n = 0; n < macnum; ++n) { 205 if (!strcmp("init", macros[n].mac_name)) { 206 (void) strcpy(line, "$init"); 207 makeargv(); 208 domacro(margc, margv); 209 break; 210 } 211 } 212 return (1); 213 } 214 215 cmdabort() 216 { 217 extern jmp_buf ptabort; 218 219 printf("\n"); 220 (void) fflush(stdout); 221 abrtflag++; 222 if (ptflag) 223 longjmp(ptabort,1); 224 } 225 226 /*VARARGS1*/ 227 command(fmt, args) 228 char *fmt; 229 { 230 int r, (*oldintr)(), cmdabort(); 231 232 abrtflag = 0; 233 if (debug) { 234 printf("---> "); 235 _doprnt(fmt, &args, stdout); 236 printf("\n"); 237 (void) fflush(stdout); 238 } 239 if (cout == NULL) { 240 perror ("No control connection for command"); 241 code = -1; 242 return (0); 243 } 244 oldintr = signal(SIGINT,cmdabort); 245 _doprnt(fmt, &args, cout); 246 fprintf(cout, "\r\n"); 247 (void) fflush(cout); 248 cpend = 1; 249 r = getreply(!strcmp(fmt, "QUIT")); 250 if (abrtflag && oldintr != SIG_IGN) 251 (*oldintr)(); 252 (void) signal(SIGINT, oldintr); 253 return(r); 254 } 255 256 #include <ctype.h> 257 258 getreply(expecteof) 259 int expecteof; 260 { 261 register int c, n; 262 register int dig; 263 int originalcode = 0, continuation = 0, (*oldintr)(), cmdabort(); 264 int pflag = 0; 265 char *pt = pasv; 266 267 oldintr = signal(SIGINT,cmdabort); 268 for (;;) { 269 dig = n = code = 0; 270 while ((c = getc(cin)) != '\n') { 271 dig++; 272 if (c == EOF) { 273 if (expecteof) { 274 (void) signal(SIGINT,oldintr); 275 code = 221; 276 return (0); 277 } 278 lostpeer(); 279 if (verbose) { 280 printf("421 Service not available, remote server has closed connection\n"); 281 (void) fflush(stdout); 282 code = 421; 283 return(4); 284 } 285 } 286 if (c != '\r' && (verbose > 0 || 287 (verbose > -1 && n == '5' && dig > 4))) { 288 if (proxflag && 289 (dig == 1 || dig == 5 && verbose == 0)) 290 printf("%s:",hostname); 291 (void) putchar(c); 292 } 293 if (dig < 4 && isdigit(c)) 294 code = code * 10 + (c - '0'); 295 if (!pflag && code == 227) 296 pflag = 1; 297 if (dig > 4 && pflag == 1 && isdigit(c)) 298 pflag = 2; 299 if (pflag == 2) { 300 if (c != '\r' && c != ')') 301 *pt++ = c; 302 else { 303 *pt = '\0'; 304 pflag = 3; 305 } 306 } 307 if (dig == 4 && c == '-') { 308 if (continuation) 309 code = 0; 310 continuation++; 311 } 312 if (n == 0) 313 n = c; 314 } 315 if (verbose > 0 || verbose > -1 && n == '5') { 316 (void) putchar(c); 317 (void) fflush (stdout); 318 } 319 if (continuation && code != originalcode) { 320 if (originalcode == 0) 321 originalcode = code; 322 continue; 323 } 324 if (n != '1') 325 cpend = 0; 326 (void) signal(SIGINT,oldintr); 327 if (code == 421 || originalcode == 421) 328 lostpeer(); 329 if (abrtflag && oldintr != cmdabort && oldintr != SIG_IGN) 330 (*oldintr)(); 331 return (n - '0'); 332 } 333 } 334 335 empty(mask, sec) 336 struct fd_set mask; 337 int sec; 338 { 339 struct timeval t; 340 341 t.tv_sec = (long) sec; 342 t.tv_usec = 0; 343 if (select(20, &mask, (struct fd_set *) 0, (struct fd_set *) 0, &t) < 0) 344 return(-1); 345 return (1); 346 } 347 348 jmp_buf sendabort; 349 350 abortsend() 351 { 352 353 mflag = 0; 354 abrtflag = 0; 355 printf("\nsend aborted\n"); 356 (void) fflush(stdout); 357 longjmp(sendabort, 1); 358 } 359 360 sendrequest(cmd, local, remote) 361 char *cmd, *local, *remote; 362 { 363 FILE *fin, *dout = 0, *mypopen(); 364 int (*closefunc)(), mypclose(), fclose(), (*oldintr)(), (*oldintp)(); 365 int abortsend(); 366 char buf[BUFSIZ]; 367 long bytes = 0, hashbytes = sizeof (buf); 368 register int c, d; 369 struct stat st; 370 struct timeval start, stop; 371 372 if (proxy) { 373 proxtrans(cmd, local, remote); 374 return; 375 } 376 closefunc = NULL; 377 oldintr = NULL; 378 oldintp = NULL; 379 if (setjmp(sendabort)) { 380 while (cpend) { 381 (void) getreply(0); 382 } 383 if (data >= 0) { 384 (void) close(data); 385 data = -1; 386 } 387 if (oldintr) 388 (void) signal(SIGINT,oldintr); 389 if (oldintp) 390 (void) signal(SIGPIPE,oldintp); 391 code = -1; 392 return; 393 } 394 oldintr = signal(SIGINT, abortsend); 395 if (strcmp(local, "-") == 0) 396 fin = stdin; 397 else if (*local == '|') { 398 oldintp = signal(SIGPIPE,SIG_IGN); 399 fin = mypopen(local + 1, "r"); 400 if (fin == NULL) { 401 perror(local + 1); 402 (void) signal(SIGINT, oldintr); 403 (void) signal(SIGPIPE, oldintp); 404 code = -1; 405 return; 406 } 407 closefunc = mypclose; 408 } else { 409 fin = fopen(local, "r"); 410 if (fin == NULL) { 411 perror(local); 412 (void) signal(SIGINT, oldintr); 413 code = -1; 414 return; 415 } 416 closefunc = fclose; 417 if (fstat(fileno(fin), &st) < 0 || 418 (st.st_mode&S_IFMT) != S_IFREG) { 419 fprintf(stdout, "%s: not a plain file.\n", local); 420 (void) signal(SIGINT, oldintr); 421 code = -1; 422 return; 423 } 424 } 425 if (initconn()) { 426 (void) signal(SIGINT, oldintr); 427 if (oldintp) 428 (void) signal(SIGPIPE, oldintp); 429 code = -1; 430 return; 431 } 432 if (setjmp(sendabort)) 433 goto abort; 434 if (remote) { 435 if (command("%s %s", cmd, remote) != PRELIM) { 436 (void) signal(SIGINT, oldintr); 437 if (oldintp) 438 (void) signal(SIGPIPE, oldintp); 439 return; 440 } 441 } else 442 if (command("%s", cmd) != PRELIM) { 443 (void) signal(SIGINT, oldintr); 444 if (oldintp) 445 (void) signal(SIGPIPE, oldintp); 446 return; 447 } 448 dout = dataconn("w"); 449 if (dout == NULL) 450 goto abort; 451 (void) gettimeofday(&start, (struct timezone *)0); 452 switch (type) { 453 454 case TYPE_I: 455 case TYPE_L: 456 errno = d = 0; 457 while ((c = read(fileno (fin), buf, sizeof (buf))) > 0) { 458 if ((d = write(fileno (dout), buf, c)) < 0) 459 break; 460 bytes += c; 461 if (hash) { 462 (void) putchar('#'); 463 (void) fflush(stdout); 464 } 465 } 466 if (hash && bytes > 0) { 467 (void) putchar('\n'); 468 (void) fflush(stdout); 469 } 470 if (c < 0) 471 perror(local); 472 if (d < 0) 473 perror("netout"); 474 break; 475 476 case TYPE_A: 477 while ((c = getc(fin)) != EOF) { 478 if (c == '\n') { 479 while (hash && (bytes >= hashbytes)) { 480 (void) putchar('#'); 481 (void) fflush(stdout); 482 hashbytes += sizeof (buf); 483 } 484 if (ferror(dout)) 485 break; 486 (void) putc('\r', dout); 487 bytes++; 488 } 489 (void) putc(c, dout); 490 bytes++; 491 /* if (c == '\r') { */ 492 /* (void) putc('\0', dout); /* this violates rfc */ 493 /* bytes++; */ 494 /* } */ 495 } 496 if (hash) { 497 if (bytes < hashbytes) 498 (void) putchar('#'); 499 (void) putchar('\n'); 500 (void) fflush(stdout); 501 } 502 if (ferror(fin)) 503 perror(local); 504 if (ferror(dout)) 505 perror("netout"); 506 break; 507 } 508 (void) gettimeofday(&stop, (struct timezone *)0); 509 if (closefunc != NULL) 510 (*closefunc)(fin); 511 (void) fclose(dout); 512 (void) getreply(0); 513 (void) signal(SIGINT, oldintr); 514 if (bytes > 0 && verbose) 515 ptransfer("sent", bytes, &start, &stop, local, remote); 516 return; 517 abort: 518 (void) gettimeofday(&stop, (struct timezone *)0); 519 (void) signal(SIGINT, oldintr); 520 if (oldintp) 521 (void) signal(SIGPIPE, oldintp); 522 if (!cpend) { 523 code = -1; 524 return; 525 } 526 if (data >= 0) { 527 (void) close(data); 528 data = -1; 529 } 530 if (dout) 531 (void) fclose(dout); 532 (void) getreply(0); 533 code = -1; 534 if (closefunc != NULL && fin != NULL) 535 (*closefunc)(fin); 536 if (bytes > 0 && verbose) 537 ptransfer("sent", bytes, &start, &stop, local, remote); 538 } 539 540 jmp_buf recvabort; 541 542 abortrecv() 543 { 544 545 mflag = 0; 546 abrtflag = 0; 547 printf("\n"); 548 (void) fflush(stdout); 549 longjmp(recvabort, 1); 550 } 551 552 recvrequest(cmd, local, remote, mode) 553 char *cmd, *local, *remote, *mode; 554 { 555 FILE *fout, *din = 0, *mypopen(); 556 int (*closefunc)(), mypclose(), fclose(), (*oldintr)(), (*oldintp)(); 557 int abortrecv(), oldverbose, oldtype = 0, tcrflag; 558 char buf[BUFSIZ], *gunique(); 559 long bytes = 0, hashbytes = sizeof (buf); 560 struct fd_set mask; 561 register int c, d; 562 struct timeval start, stop; 563 564 if (proxy && strcmp(cmd,"RETR") == 0) { 565 proxtrans(cmd, local, remote); 566 return; 567 } 568 closefunc = NULL; 569 oldintr = NULL; 570 oldintp = NULL; 571 tcrflag = !crflag && !strcmp(cmd, "RETR"); 572 if (setjmp(recvabort)) { 573 while (cpend) { 574 (void) getreply(0); 575 } 576 if (data >= 0) { 577 (void) close(data); 578 data = -1; 579 } 580 if (oldintr) 581 (void) signal(SIGINT, oldintr); 582 code = -1; 583 return; 584 } 585 oldintr = signal(SIGINT, abortrecv); 586 if (strcmp(local, "-") && *local != '|') { 587 if (access(local, 2) < 0) { 588 char *dir = rindex(local, '/'); 589 590 if (errno != ENOENT && errno != EACCES) { 591 perror(local); 592 (void) signal(SIGINT, oldintr); 593 code = -1; 594 return; 595 } 596 if (dir != NULL) 597 *dir = 0; 598 d = access(dir ? local : ".", 2); 599 if (dir != NULL) 600 *dir = '/'; 601 if (d < 0) { 602 perror(local); 603 (void) signal(SIGINT, oldintr); 604 code = -1; 605 return; 606 } 607 if (!runique && errno == EACCES && 608 chmod(local,0600) < 0) { 609 perror(local); 610 (void) signal(SIGINT, oldintr); 611 code = -1; 612 return; 613 } 614 if (runique && errno == EACCES && 615 (local = gunique(local)) == NULL) { 616 (void) signal(SIGINT, oldintr); 617 code = -1; 618 return; 619 } 620 } 621 else if (runique && (local = gunique(local)) == NULL) { 622 (void) signal(SIGINT, oldintr); 623 code = -1; 624 return; 625 } 626 } 627 if (initconn()) { 628 (void) signal(SIGINT, oldintr); 629 code = -1; 630 return; 631 } 632 if (setjmp(recvabort)) 633 goto abort; 634 if (strcmp(cmd, "RETR") && type != TYPE_A) { 635 oldtype = type; 636 oldverbose = verbose; 637 if (!debug) 638 verbose = 0; 639 setascii(); 640 verbose = oldverbose; 641 } 642 if (remote) { 643 if (command("%s %s", cmd, remote) != PRELIM) { 644 (void) signal(SIGINT, oldintr); 645 if (oldtype) { 646 if (!debug) 647 verbose = 0; 648 switch (oldtype) { 649 case TYPE_I: 650 setbinary(); 651 break; 652 case TYPE_E: 653 setebcdic(); 654 break; 655 case TYPE_L: 656 settenex(); 657 break; 658 } 659 verbose = oldverbose; 660 } 661 return; 662 } 663 } else { 664 if (command("%s", cmd) != PRELIM) { 665 (void) signal(SIGINT, oldintr); 666 if (oldtype) { 667 if (!debug) 668 verbose = 0; 669 switch (oldtype) { 670 case TYPE_I: 671 setbinary(); 672 break; 673 case TYPE_E: 674 setebcdic(); 675 break; 676 case TYPE_L: 677 settenex(); 678 break; 679 } 680 verbose = oldverbose; 681 } 682 return; 683 } 684 } 685 din = dataconn("r"); 686 if (din == NULL) 687 goto abort; 688 if (strcmp(local, "-") == 0) 689 fout = stdout; 690 else if (*local == '|') { 691 oldintp = signal(SIGPIPE, SIG_IGN); 692 fout = mypopen(local + 1, "w"); 693 if (fout == NULL) { 694 perror(local+1); 695 goto abort; 696 } 697 closefunc = mypclose; 698 } 699 else { 700 fout = fopen(local, mode); 701 if (fout == NULL) { 702 perror(local); 703 goto abort; 704 } 705 closefunc = fclose; 706 } 707 (void) gettimeofday(&start, (struct timezone *)0); 708 switch (type) { 709 710 case TYPE_I: 711 case TYPE_L: 712 errno = d = 0; 713 while ((c = read(fileno(din), buf, sizeof (buf))) > 0) { 714 if ((d = write(fileno(fout), buf, c)) < 0) 715 break; 716 bytes += c; 717 if (hash) { 718 (void) putchar('#'); 719 (void) fflush(stdout); 720 } 721 } 722 if (hash && bytes > 0) { 723 (void) putchar('\n'); 724 (void) fflush(stdout); 725 } 726 if (c < 0) 727 perror("netin"); 728 if (d < 0) 729 perror(local); 730 break; 731 732 case TYPE_A: 733 while ((c = getc(din)) != EOF) { 734 if (c == '\r') { 735 while (hash && (bytes >= hashbytes)) { 736 (void) putchar('#'); 737 (void) fflush(stdout); 738 hashbytes += sizeof (buf); 739 } 740 bytes++; 741 if ((c = getc(din)) != '\n' || tcrflag) { 742 if (ferror (fout)) 743 break; 744 (void) putc ('\r', fout); 745 } 746 /*if (c == '\0') { 747 bytes++; 748 continue; 749 }*/ 750 } 751 (void) putc (c, fout); 752 bytes++; 753 } 754 if (hash) { 755 if (bytes < hashbytes) 756 (void) putchar('#'); 757 (void) putchar('\n'); 758 (void) fflush(stdout); 759 } 760 if (ferror (din)) 761 perror ("netin"); 762 if (ferror (fout)) 763 perror (local); 764 break; 765 } 766 if (closefunc != NULL) 767 (*closefunc)(fout); 768 (void) signal(SIGINT, oldintr); 769 if (oldintp) 770 (void) signal(SIGPIPE, oldintp); 771 (void) gettimeofday(&stop, (struct timezone *)0); 772 (void) fclose(din); 773 (void) getreply(0); 774 if (bytes > 0 && verbose) 775 ptransfer("received", bytes, &start, &stop, local, remote); 776 if (oldtype) { 777 if (!debug) 778 verbose = 0; 779 switch (oldtype) { 780 case TYPE_I: 781 setbinary(); 782 break; 783 case TYPE_E: 784 setebcdic(); 785 break; 786 case TYPE_L: 787 settenex(); 788 break; 789 } 790 verbose = oldverbose; 791 } 792 return; 793 abort: 794 795 /* if server command parser understands TELNET commands, abort using */ 796 /* recommended IP,SYNC sequence */ 797 798 (void) gettimeofday(&stop, (struct timezone *)0); 799 if (oldintp) 800 (void) signal(SIGPIPE, oldintr); 801 (void) signal(SIGINT,SIG_IGN); 802 if (oldtype) { 803 if (!debug) 804 verbose = 0; 805 switch (oldtype) { 806 case TYPE_I: 807 setbinary(); 808 break; 809 case TYPE_E: 810 setebcdic(); 811 break; 812 case TYPE_L: 813 settenex(); 814 break; 815 } 816 verbose = oldverbose; 817 } 818 if (!cpend) { 819 code = -1; 820 (void) signal(SIGINT,oldintr); 821 return; 822 } 823 if (telflag) { 824 char msg[2]; 825 826 fprintf(cout,"%c%c",IAC,IP); 827 (void) fflush(cout); 828 *msg = IAC; 829 *(msg+1) = DM; 830 if (send(fileno(cout),msg,2,MSG_OOB) != 2) 831 perror("abort"); 832 } 833 fprintf(cout,"ABOR\r\n"); 834 (void) fflush(cout); 835 FD_ZERO((char *) &mask); 836 FD_SET(fileno(cin), &mask); 837 if (din) { 838 FD_SET(fileno(din), &mask); 839 } 840 if (empty(mask,10) < 0) { 841 perror("abort"); 842 code = -1; 843 lostpeer(); 844 } 845 if (din && FD_ISSET(fileno(din), &mask)) { 846 while ((c = read(fileno(din), buf, sizeof (buf))) > 0) 847 ; 848 } 849 if ((c = getreply(0)) == ERROR) { /* needed for nic style abort */ 850 if (data >= 0) { 851 (void) close(data); 852 data = -1; 853 } 854 (void) getreply(0); 855 } 856 (void) getreply(0); 857 code = -1; 858 if (data >= 0) { 859 (void) close(data); 860 data = -1; 861 } 862 if (closefunc != NULL && fout != NULL) 863 (*closefunc)(fout); 864 if (din) 865 (void) fclose(din); 866 if (bytes > 0 && verbose) 867 ptransfer("received", bytes, &start, &stop, local, remote); 868 (void) signal(SIGINT,oldintr); 869 } 870 871 /* 872 * Need to start a listen on the data channel 873 * before we send the command, otherwise the 874 * server's connect may fail. 875 */ 876 static int sendport = -1; 877 878 initconn() 879 { 880 register char *p, *a; 881 int result, len, tmpno = 0; 882 int on = 1; 883 884 noport: 885 data_addr = myctladdr; 886 if (sendport) 887 data_addr.sin_port = 0; /* let system pick one */ 888 if (data != -1) 889 (void) close (data); 890 data = socket(AF_INET, SOCK_STREAM, 0); 891 if (data < 0) { 892 perror("ftp: socket"); 893 if (tmpno) 894 sendport = 1; 895 return (1); 896 } 897 if (!sendport) 898 if (setsockopt(data, SOL_SOCKET, SO_REUSEADDR, &on, sizeof (on)) < 0) { 899 perror("ftp: setsockopt (resuse address)"); 900 goto bad; 901 } 902 if (bind(data, (struct sockaddr *)&data_addr, sizeof (data_addr)) < 0) { 903 perror("ftp: bind"); 904 goto bad; 905 } 906 if (options & SO_DEBUG && 907 setsockopt(data, SOL_SOCKET, SO_DEBUG, &on, sizeof (on)) < 0) 908 perror("ftp: setsockopt (ignored)"); 909 len = sizeof (data_addr); 910 if (getsockname(data, (char *)&data_addr, &len) < 0) { 911 perror("ftp: getsockname"); 912 goto bad; 913 } 914 if (listen(data, 1) < 0) 915 perror("ftp: listen"); 916 if (sendport) { 917 a = (char *)&data_addr.sin_addr; 918 p = (char *)&data_addr.sin_port; 919 #define UC(b) (((int)b)&0xff) 920 result = 921 command("PORT %d,%d,%d,%d,%d,%d", 922 UC(a[0]), UC(a[1]), UC(a[2]), UC(a[3]), 923 UC(p[0]), UC(p[1])); 924 if (result == ERROR && sendport == -1) { 925 sendport = 0; 926 tmpno = 1; 927 goto noport; 928 } 929 return (result != COMPLETE); 930 } 931 if (tmpno) 932 sendport = 1; 933 return (0); 934 bad: 935 (void) close(data), data = -1; 936 if (tmpno) 937 sendport = 1; 938 return (1); 939 } 940 941 FILE * 942 dataconn(mode) 943 char *mode; 944 { 945 struct sockaddr_in from; 946 int s, fromlen = sizeof (from); 947 948 s = accept(data, (struct sockaddr *) &from, &fromlen); 949 if (s < 0) { 950 perror("ftp: accept"); 951 (void) close(data), data = -1; 952 return (NULL); 953 } 954 (void) close(data); 955 data = s; 956 return (fdopen(data, mode)); 957 } 958 959 ptransfer(direction, bytes, t0, t1, local, remote) 960 char *direction, *local, *remote; 961 long bytes; 962 struct timeval *t0, *t1; 963 { 964 struct timeval td; 965 float s, bs; 966 967 tvsub(&td, t1, t0); 968 s = td.tv_sec + (td.tv_usec / 1000000.); 969 #define nz(x) ((x) == 0 ? 1 : (x)) 970 bs = bytes / nz(s); 971 if (local && *local != '-') 972 printf("local: %s ", local); 973 if (remote) 974 printf("remote: %s\n", remote); 975 printf("%ld bytes %s in %.2g seconds (%.2g Kbytes/s)\n", 976 bytes, direction, s, bs / 1024.); 977 } 978 979 /*tvadd(tsum, t0) 980 struct timeval *tsum, *t0; 981 { 982 983 tsum->tv_sec += t0->tv_sec; 984 tsum->tv_usec += t0->tv_usec; 985 if (tsum->tv_usec > 1000000) 986 tsum->tv_sec++, tsum->tv_usec -= 1000000; 987 } */ 988 989 tvsub(tdiff, t1, t0) 990 struct timeval *tdiff, *t1, *t0; 991 { 992 993 tdiff->tv_sec = t1->tv_sec - t0->tv_sec; 994 tdiff->tv_usec = t1->tv_usec - t0->tv_usec; 995 if (tdiff->tv_usec < 0) 996 tdiff->tv_sec--, tdiff->tv_usec += 1000000; 997 } 998 999 psabort() 1000 { 1001 extern int abrtflag; 1002 1003 abrtflag++; 1004 } 1005 1006 pswitch(flag) 1007 int flag; 1008 { 1009 extern int proxy, abrtflag; 1010 int (*oldintr)(); 1011 static struct comvars { 1012 int connect; 1013 char name[32]; 1014 struct sockaddr_in mctl; 1015 struct sockaddr_in hctl; 1016 FILE *in; 1017 FILE *out; 1018 int tflag; 1019 int tpe; 1020 int cpnd; 1021 int sunqe; 1022 int runqe; 1023 int mcse; 1024 int ntflg; 1025 char nti[17]; 1026 char nto[17]; 1027 int mapflg; 1028 char mi[MAXPATHLEN]; 1029 char mo[MAXPATHLEN]; 1030 } proxstruct, tmpstruct; 1031 struct comvars *ip, *op; 1032 1033 abrtflag = 0; 1034 oldintr = signal(SIGINT, psabort); 1035 if (flag) { 1036 if (proxy) 1037 return; 1038 ip = &tmpstruct; 1039 op = &proxstruct; 1040 proxy++; 1041 } 1042 else { 1043 if (!proxy) 1044 return; 1045 ip = &proxstruct; 1046 op = &tmpstruct; 1047 proxy = 0; 1048 } 1049 ip->connect = connected; 1050 connected = op->connect; 1051 (void) strncpy(ip->name, hostname, 31); 1052 (ip->name)[strlen(ip->name)] = '\0'; 1053 hostname = op->name; 1054 ip->hctl = hisctladdr; 1055 hisctladdr = op->hctl; 1056 ip->mctl = myctladdr; 1057 myctladdr = op->mctl; 1058 ip->in = cin; 1059 cin = op->in; 1060 ip->out = cout; 1061 cout = op->out; 1062 ip->tflag = telflag; 1063 telflag = op->tflag; 1064 ip->tpe = type; 1065 type = op->tpe; 1066 if (!type) 1067 type = 1; 1068 ip->cpnd = cpend; 1069 cpend = op->cpnd; 1070 ip->sunqe = sunique; 1071 sunique = op->sunqe; 1072 ip->runqe = runique; 1073 runique = op->runqe; 1074 ip->mcse = mcase; 1075 mcase = op->mcse; 1076 ip->ntflg = ntflag; 1077 ntflag = op->ntflg; 1078 (void) strncpy(ip->nti, ntin, 16); 1079 (ip->nti)[strlen(ip->nti)] = '\0'; 1080 (void) strcpy(ntin, op->nti); 1081 (void) strncpy(ip->nto, ntout, 16); 1082 (ip->nto)[strlen(ip->nto)] = '\0'; 1083 (void) strcpy(ntout, op->nto); 1084 ip->mapflg = mapflag; 1085 mapflag = op->mapflg; 1086 (void) strncpy(ip->mi, mapin, MAXPATHLEN - 1); 1087 (ip->mi)[strlen(ip->mi)] = '\0'; 1088 (void) strcpy(mapin, op->mi); 1089 (void) strncpy(ip->mo, mapout, MAXPATHLEN - 1); 1090 (ip->mo)[strlen(ip->mo)] = '\0'; 1091 (void) strcpy(mapout, op->mo); 1092 (void) signal(SIGINT, oldintr); 1093 if (abrtflag) { 1094 abrtflag = 0; 1095 (*oldintr)(); 1096 } 1097 } 1098 1099 jmp_buf ptabort; 1100 int ptabflg; 1101 1102 abortpt() 1103 { 1104 printf("\n"); 1105 (void) fflush(stdout); 1106 ptabflg++; 1107 mflag = 0; 1108 abrtflag = 0; 1109 longjmp(ptabort, 1); 1110 } 1111 1112 proxtrans(cmd, local, remote) 1113 char *cmd, *local, *remote; 1114 { 1115 int (*oldintr)(), abortpt(), tmptype, oldtype = 0, secndflag = 0; 1116 extern jmp_buf ptabort; 1117 char *cmd2; 1118 struct fd_set mask; 1119 1120 if (strcmp(cmd, "RETR")) 1121 cmd2 = "RETR"; 1122 else 1123 cmd2 = runique ? "STOU" : "STOR"; 1124 if (command("PASV") != COMPLETE) { 1125 printf("proxy server does not support third part transfers.\n"); 1126 return; 1127 } 1128 tmptype = type; 1129 pswitch(0); 1130 if (!connected) { 1131 printf("No primary connection\n"); 1132 pswitch(1); 1133 code = -1; 1134 return; 1135 } 1136 if (type != tmptype) { 1137 oldtype = type; 1138 switch (tmptype) { 1139 case TYPE_A: 1140 setascii(); 1141 break; 1142 case TYPE_I: 1143 setbinary(); 1144 break; 1145 case TYPE_E: 1146 setebcdic(); 1147 break; 1148 case TYPE_L: 1149 settenex(); 1150 break; 1151 } 1152 } 1153 if (command("PORT %s", pasv) != COMPLETE) { 1154 switch (oldtype) { 1155 case 0: 1156 break; 1157 case TYPE_A: 1158 setascii(); 1159 break; 1160 case TYPE_I: 1161 setbinary(); 1162 break; 1163 case TYPE_E: 1164 setebcdic(); 1165 break; 1166 case TYPE_L: 1167 settenex(); 1168 break; 1169 } 1170 pswitch(1); 1171 return; 1172 } 1173 if (setjmp(ptabort)) 1174 goto abort; 1175 oldintr = signal(SIGINT, abortpt); 1176 if (command("%s %s", cmd, remote) != PRELIM) { 1177 (void) signal(SIGINT, oldintr); 1178 switch (oldtype) { 1179 case 0: 1180 break; 1181 case TYPE_A: 1182 setascii(); 1183 break; 1184 case TYPE_I: 1185 setbinary(); 1186 break; 1187 case TYPE_E: 1188 setebcdic(); 1189 break; 1190 case TYPE_L: 1191 settenex(); 1192 break; 1193 } 1194 pswitch(1); 1195 return; 1196 } 1197 sleep(2); 1198 pswitch(1); 1199 secndflag++; 1200 if (command("%s %s", cmd2, local) != PRELIM) 1201 goto abort; 1202 ptflag++; 1203 (void) getreply(0); 1204 pswitch(0); 1205 (void) getreply(0); 1206 (void) signal(SIGINT, oldintr); 1207 switch (oldtype) { 1208 case 0: 1209 break; 1210 case TYPE_A: 1211 setascii(); 1212 break; 1213 case TYPE_I: 1214 setbinary(); 1215 break; 1216 case TYPE_E: 1217 setebcdic(); 1218 break; 1219 case TYPE_L: 1220 settenex(); 1221 break; 1222 } 1223 pswitch(1); 1224 ptflag = 0; 1225 printf("local: %s remote: %s\n", local, remote); 1226 return; 1227 abort: 1228 (void) signal(SIGINT, SIG_IGN); 1229 ptflag = 0; 1230 if (strcmp(cmd, "RETR") && !proxy) 1231 pswitch(1); 1232 else if (!strcmp(cmd, "RETR") && proxy) 1233 pswitch(0); 1234 if (!cpend && !secndflag) { /* only here if cmd = "STOR" (proxy=1) */ 1235 if (command("%s %s", cmd2, local) != PRELIM) { 1236 pswitch(0); 1237 switch (oldtype) { 1238 case 0: 1239 break; 1240 case TYPE_A: 1241 setascii(); 1242 break; 1243 case TYPE_I: 1244 setbinary(); 1245 break; 1246 case TYPE_E: 1247 setebcdic(); 1248 break; 1249 case TYPE_L: 1250 settenex(); 1251 break; 1252 } 1253 if (cpend && telflag) { 1254 char msg[2]; 1255 1256 fprintf(cout,"%c%c",IAC,IP); 1257 (void) fflush(cout); 1258 *msg = IAC; 1259 *(msg+1) = DM; 1260 if (send(fileno(cout),msg,2,MSG_OOB) != 2) 1261 perror("abort"); 1262 } 1263 if (cpend) { 1264 fprintf(cout,"ABOR\r\n"); 1265 (void) fflush(cout); 1266 FD_ZERO((char *) &mask); 1267 FD_SET(fileno(cin), &mask); 1268 if (empty(mask,10) < 0) { 1269 perror("abort"); 1270 if (ptabflg) 1271 code = -1; 1272 lostpeer(); 1273 } 1274 (void) getreply(0); 1275 (void) getreply(0); 1276 } 1277 } 1278 pswitch(1); 1279 if (ptabflg) 1280 code = -1; 1281 (void) signal(SIGINT, oldintr); 1282 return; 1283 } 1284 if (cpend && telflag) { 1285 char msg[2]; 1286 1287 fprintf(cout,"%c%c",IAC,IP); 1288 (void) fflush(cout); 1289 *msg = IAC; 1290 *(msg+1) = DM; 1291 if (send(fileno(cout),msg,2,MSG_OOB) != 2) 1292 perror("abort"); 1293 } 1294 if (cpend) { 1295 fprintf(cout,"ABOR\r\n"); 1296 (void) fflush(cout); 1297 FD_ZERO((char *) &mask); 1298 FD_SET(fileno(cin), &mask); 1299 if ((empty(mask,10)) < 0) { 1300 perror("abort"); 1301 if (ptabflg) 1302 code = -1; 1303 lostpeer(); 1304 } 1305 (void) getreply(0); 1306 (void) getreply(0); 1307 } 1308 pswitch(!proxy); 1309 if (!cpend && !secndflag) { /* only if cmd = "RETR" (proxy=1) */ 1310 if (command("%s %s", cmd2, local) != PRELIM) { 1311 pswitch(0); 1312 switch (oldtype) { 1313 case 0: 1314 break; 1315 case TYPE_A: 1316 setascii(); 1317 break; 1318 case TYPE_I: 1319 setbinary(); 1320 break; 1321 case TYPE_E: 1322 setebcdic(); 1323 break; 1324 case TYPE_L: 1325 settenex(); 1326 break; 1327 } 1328 if (cpend && telflag) { 1329 char msg[2]; 1330 1331 fprintf(cout,"%c%c",IAC,IP); 1332 (void) fflush(cout); 1333 *msg = IAC; 1334 *(msg+1) = DM; 1335 if (send(fileno(cout),msg,2,MSG_OOB) != 2) 1336 perror("abort"); 1337 } 1338 if (cpend) { 1339 fprintf(cout,"ABOR\r\n"); 1340 (void) fflush(cout); 1341 FD_ZERO((char *) &mask); 1342 FD_SET(fileno(cin), &mask); 1343 if (empty(mask,10) < 0) { 1344 perror("abort"); 1345 if (ptabflg) 1346 code = -1; 1347 lostpeer(); 1348 } 1349 (void) getreply(0); 1350 (void) getreply(0); 1351 } 1352 pswitch(1); 1353 if (ptabflg) 1354 code = -1; 1355 (void) signal(SIGINT, oldintr); 1356 return; 1357 } 1358 } 1359 if (cpend && telflag) { 1360 char msg[2]; 1361 1362 fprintf(cout,"%c%c",IAC,IP); 1363 (void) fflush(cout); 1364 *msg = IAC; 1365 *(msg+1) = DM; 1366 if (send(fileno(cout),msg,2,MSG_OOB) != 2) 1367 perror("abort"); 1368 } 1369 if (cpend) { 1370 fprintf(cout,"ABOR\r\n"); 1371 (void) fflush(cout); 1372 FD_ZERO((char *) &mask); 1373 FD_SET(fileno(cin), &mask); 1374 if (empty(mask,10) < 0) { 1375 perror("abort"); 1376 if (ptabflg) 1377 code = -1; 1378 lostpeer(); 1379 } 1380 (void) getreply(0); 1381 (void) getreply(0); 1382 } 1383 pswitch(!proxy); 1384 if (cpend) { 1385 FD_ZERO((char *) &mask); 1386 FD_SET(fileno(cin), &mask); 1387 if (empty(mask,10) < 0) { 1388 perror("abort"); 1389 if (ptabflg) 1390 code = -1; 1391 lostpeer(); 1392 } 1393 (void) getreply(0); 1394 (void) getreply(0); 1395 } 1396 if (proxy) 1397 pswitch(0); 1398 switch (oldtype) { 1399 case 0: 1400 break; 1401 case TYPE_A: 1402 setascii(); 1403 break; 1404 case TYPE_I: 1405 setbinary(); 1406 break; 1407 case TYPE_E: 1408 setebcdic(); 1409 break; 1410 case TYPE_L: 1411 settenex(); 1412 break; 1413 } 1414 pswitch(1); 1415 if (ptabflg) 1416 code = -1; 1417 (void) signal(SIGINT, oldintr); 1418 } 1419 1420 reset() 1421 { 1422 struct fd_set mask; 1423 int nfnd = 1; 1424 1425 FD_ZERO((char *) &mask); 1426 while (nfnd) { 1427 FD_SET(fileno(cin), &mask); 1428 if ((nfnd = empty(mask,0)) < 0) { 1429 perror("reset"); 1430 code = -1; 1431 lostpeer(); 1432 } 1433 else { 1434 (void) getreply(0); 1435 } 1436 } 1437 } 1438 1439 char * 1440 gunique(local) 1441 char *local; 1442 { 1443 static char new[MAXPATHLEN]; 1444 char *cp = rindex(local, '/'); 1445 int d, count=0; 1446 char ext = '1'; 1447 1448 if (cp) 1449 *cp = '\0'; 1450 d = access(cp ? local : ".", 2); 1451 if (cp) 1452 *cp = '/'; 1453 if (d < 0) { 1454 perror(local); 1455 return((char *) 0); 1456 } 1457 (void) strcpy(new, local); 1458 cp = new + strlen(new); 1459 *cp++ = '.'; 1460 while (!d) { 1461 if (++count == 100) { 1462 printf("runique: can't find unique file name.\n"); 1463 return((char *) 0); 1464 } 1465 *cp++ = ext; 1466 *cp = '\0'; 1467 if (ext == '9') 1468 ext = '0'; 1469 else 1470 ext++; 1471 if ((d = access(new, 0)) < 0) 1472 break; 1473 if (ext != '0') 1474 cp--; 1475 else if (*(cp - 2) == '.') 1476 *(cp - 1) = '1'; 1477 else { 1478 *(cp - 2) = *(cp - 2) + 1; 1479 cp--; 1480 } 1481 } 1482 return(new); 1483 } 1484