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