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