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.15 (Berkeley) 04/23/87"; 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/param.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 while (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[MAXHOSTNAMELEN]; 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 if (hostname) { 1060 (void) strncpy(ip->name, hostname, sizeof(ip->name) - 1); 1061 ip->name[strlen(ip->name)] = '\0'; 1062 } else 1063 ip->name[0] = 0; 1064 hostname = op->name; 1065 ip->hctl = hisctladdr; 1066 hisctladdr = op->hctl; 1067 ip->mctl = myctladdr; 1068 myctladdr = op->mctl; 1069 ip->in = cin; 1070 cin = op->in; 1071 ip->out = cout; 1072 cout = op->out; 1073 ip->tpe = type; 1074 type = op->tpe; 1075 if (!type) 1076 type = 1; 1077 ip->cpnd = cpend; 1078 cpend = op->cpnd; 1079 ip->sunqe = sunique; 1080 sunique = op->sunqe; 1081 ip->runqe = runique; 1082 runique = op->runqe; 1083 ip->mcse = mcase; 1084 mcase = op->mcse; 1085 ip->ntflg = ntflag; 1086 ntflag = op->ntflg; 1087 (void) strncpy(ip->nti, ntin, 16); 1088 (ip->nti)[strlen(ip->nti)] = '\0'; 1089 (void) strcpy(ntin, op->nti); 1090 (void) strncpy(ip->nto, ntout, 16); 1091 (ip->nto)[strlen(ip->nto)] = '\0'; 1092 (void) strcpy(ntout, op->nto); 1093 ip->mapflg = mapflag; 1094 mapflag = op->mapflg; 1095 (void) strncpy(ip->mi, mapin, MAXPATHLEN - 1); 1096 (ip->mi)[strlen(ip->mi)] = '\0'; 1097 (void) strcpy(mapin, op->mi); 1098 (void) strncpy(ip->mo, mapout, MAXPATHLEN - 1); 1099 (ip->mo)[strlen(ip->mo)] = '\0'; 1100 (void) strcpy(mapout, op->mo); 1101 (void) signal(SIGINT, oldintr); 1102 if (abrtflag) { 1103 abrtflag = 0; 1104 (*oldintr)(); 1105 } 1106 } 1107 1108 jmp_buf ptabort; 1109 int ptabflg; 1110 1111 abortpt() 1112 { 1113 printf("\n"); 1114 (void) fflush(stdout); 1115 ptabflg++; 1116 mflag = 0; 1117 abrtflag = 0; 1118 longjmp(ptabort, 1); 1119 } 1120 1121 proxtrans(cmd, local, remote) 1122 char *cmd, *local, *remote; 1123 { 1124 int (*oldintr)(), abortpt(), tmptype, oldtype = 0, secndflag = 0, nfnd; 1125 extern jmp_buf ptabort; 1126 char *cmd2; 1127 struct fd_set mask; 1128 1129 if (strcmp(cmd, "RETR")) 1130 cmd2 = "RETR"; 1131 else 1132 cmd2 = runique ? "STOU" : "STOR"; 1133 if (command("PASV") != COMPLETE) { 1134 printf("proxy server does not support third part transfers.\n"); 1135 return; 1136 } 1137 tmptype = type; 1138 pswitch(0); 1139 if (!connected) { 1140 printf("No primary connection\n"); 1141 pswitch(1); 1142 code = -1; 1143 return; 1144 } 1145 if (type != tmptype) { 1146 oldtype = type; 1147 switch (tmptype) { 1148 case TYPE_A: 1149 setascii(); 1150 break; 1151 case TYPE_I: 1152 setbinary(); 1153 break; 1154 case TYPE_E: 1155 setebcdic(); 1156 break; 1157 case TYPE_L: 1158 settenex(); 1159 break; 1160 } 1161 } 1162 if (command("PORT %s", pasv) != COMPLETE) { 1163 switch (oldtype) { 1164 case 0: 1165 break; 1166 case TYPE_A: 1167 setascii(); 1168 break; 1169 case TYPE_I: 1170 setbinary(); 1171 break; 1172 case TYPE_E: 1173 setebcdic(); 1174 break; 1175 case TYPE_L: 1176 settenex(); 1177 break; 1178 } 1179 pswitch(1); 1180 return; 1181 } 1182 if (setjmp(ptabort)) 1183 goto abort; 1184 oldintr = signal(SIGINT, abortpt); 1185 if (command("%s %s", cmd, remote) != PRELIM) { 1186 (void) signal(SIGINT, oldintr); 1187 switch (oldtype) { 1188 case 0: 1189 break; 1190 case TYPE_A: 1191 setascii(); 1192 break; 1193 case TYPE_I: 1194 setbinary(); 1195 break; 1196 case TYPE_E: 1197 setebcdic(); 1198 break; 1199 case TYPE_L: 1200 settenex(); 1201 break; 1202 } 1203 pswitch(1); 1204 return; 1205 } 1206 sleep(2); 1207 pswitch(1); 1208 secndflag++; 1209 if (command("%s %s", cmd2, local) != PRELIM) 1210 goto abort; 1211 ptflag++; 1212 (void) getreply(0); 1213 pswitch(0); 1214 (void) getreply(0); 1215 (void) signal(SIGINT, oldintr); 1216 switch (oldtype) { 1217 case 0: 1218 break; 1219 case TYPE_A: 1220 setascii(); 1221 break; 1222 case TYPE_I: 1223 setbinary(); 1224 break; 1225 case TYPE_E: 1226 setebcdic(); 1227 break; 1228 case TYPE_L: 1229 settenex(); 1230 break; 1231 } 1232 pswitch(1); 1233 ptflag = 0; 1234 printf("local: %s remote: %s\n", local, remote); 1235 return; 1236 abort: 1237 (void) signal(SIGINT, SIG_IGN); 1238 ptflag = 0; 1239 if (strcmp(cmd, "RETR") && !proxy) 1240 pswitch(1); 1241 else if (!strcmp(cmd, "RETR") && proxy) 1242 pswitch(0); 1243 if (!cpend && !secndflag) { /* only here if cmd = "STOR" (proxy=1) */ 1244 if (command("%s %s", cmd2, local) != PRELIM) { 1245 pswitch(0); 1246 switch (oldtype) { 1247 case 0: 1248 break; 1249 case TYPE_A: 1250 setascii(); 1251 break; 1252 case TYPE_I: 1253 setbinary(); 1254 break; 1255 case TYPE_E: 1256 setebcdic(); 1257 break; 1258 case TYPE_L: 1259 settenex(); 1260 break; 1261 } 1262 if (cpend) { 1263 char msg[2]; 1264 1265 fprintf(cout,"%c%c",IAC,IP); 1266 (void) fflush(cout); 1267 *msg = IAC; 1268 *(msg+1) = DM; 1269 if (send(fileno(cout),msg,2,MSG_OOB) != 2) 1270 perror("abort"); 1271 fprintf(cout,"ABOR\r\n"); 1272 (void) fflush(cout); 1273 FD_ZERO(&mask); 1274 FD_SET(fileno(cin), &mask); 1275 if ((nfnd = empty(&mask,10)) <= 0) { 1276 if (nfnd < 0) { 1277 perror("abort"); 1278 } 1279 if (ptabflg) 1280 code = -1; 1281 lostpeer(); 1282 } 1283 (void) getreply(0); 1284 (void) getreply(0); 1285 } 1286 } 1287 pswitch(1); 1288 if (ptabflg) 1289 code = -1; 1290 (void) signal(SIGINT, oldintr); 1291 return; 1292 } 1293 if (cpend) { 1294 char msg[2]; 1295 1296 fprintf(cout,"%c%c",IAC,IP); 1297 (void) fflush(cout); 1298 *msg = IAC; 1299 *(msg+1) = DM; 1300 if (send(fileno(cout),msg,2,MSG_OOB) != 2) 1301 perror("abort"); 1302 fprintf(cout,"ABOR\r\n"); 1303 (void) fflush(cout); 1304 FD_ZERO(&mask); 1305 FD_SET(fileno(cin), &mask); 1306 if ((nfnd = empty(&mask,10)) <= 0) { 1307 if (nfnd < 0) { 1308 perror("abort"); 1309 } 1310 if (ptabflg) 1311 code = -1; 1312 lostpeer(); 1313 } 1314 (void) getreply(0); 1315 (void) getreply(0); 1316 } 1317 pswitch(!proxy); 1318 if (!cpend && !secndflag) { /* only if cmd = "RETR" (proxy=1) */ 1319 if (command("%s %s", cmd2, local) != PRELIM) { 1320 pswitch(0); 1321 switch (oldtype) { 1322 case 0: 1323 break; 1324 case TYPE_A: 1325 setascii(); 1326 break; 1327 case TYPE_I: 1328 setbinary(); 1329 break; 1330 case TYPE_E: 1331 setebcdic(); 1332 break; 1333 case TYPE_L: 1334 settenex(); 1335 break; 1336 } 1337 if (cpend) { 1338 char msg[2]; 1339 1340 fprintf(cout,"%c%c",IAC,IP); 1341 (void) fflush(cout); 1342 *msg = IAC; 1343 *(msg+1) = DM; 1344 if (send(fileno(cout),msg,2,MSG_OOB) != 2) 1345 perror("abort"); 1346 fprintf(cout,"ABOR\r\n"); 1347 (void) fflush(cout); 1348 FD_ZERO(&mask); 1349 FD_SET(fileno(cin), &mask); 1350 if ((nfnd = empty(&mask,10)) <= 0) { 1351 if (nfnd < 0) { 1352 perror("abort"); 1353 } 1354 if (ptabflg) 1355 code = -1; 1356 lostpeer(); 1357 } 1358 (void) getreply(0); 1359 (void) getreply(0); 1360 } 1361 pswitch(1); 1362 if (ptabflg) 1363 code = -1; 1364 (void) signal(SIGINT, oldintr); 1365 return; 1366 } 1367 } 1368 if (cpend) { 1369 char msg[2]; 1370 1371 fprintf(cout,"%c%c",IAC,IP); 1372 (void) fflush(cout); 1373 *msg = IAC; 1374 *(msg+1) = DM; 1375 if (send(fileno(cout),msg,2,MSG_OOB) != 2) 1376 perror("abort"); 1377 fprintf(cout,"ABOR\r\n"); 1378 (void) fflush(cout); 1379 FD_ZERO(&mask); 1380 FD_SET(fileno(cin), &mask); 1381 if ((nfnd = empty(&mask,10)) <= 0) { 1382 if (nfnd < 0) { 1383 perror("abort"); 1384 } 1385 if (ptabflg) 1386 code = -1; 1387 lostpeer(); 1388 } 1389 (void) getreply(0); 1390 (void) getreply(0); 1391 } 1392 pswitch(!proxy); 1393 if (cpend) { 1394 FD_ZERO(&mask); 1395 FD_SET(fileno(cin), &mask); 1396 if ((nfnd = empty(&mask,10)) <= 0) { 1397 if (nfnd < 0) { 1398 perror("abort"); 1399 } 1400 if (ptabflg) 1401 code = -1; 1402 lostpeer(); 1403 } 1404 (void) getreply(0); 1405 (void) getreply(0); 1406 } 1407 if (proxy) 1408 pswitch(0); 1409 switch (oldtype) { 1410 case 0: 1411 break; 1412 case TYPE_A: 1413 setascii(); 1414 break; 1415 case TYPE_I: 1416 setbinary(); 1417 break; 1418 case TYPE_E: 1419 setebcdic(); 1420 break; 1421 case TYPE_L: 1422 settenex(); 1423 break; 1424 } 1425 pswitch(1); 1426 if (ptabflg) 1427 code = -1; 1428 (void) signal(SIGINT, oldintr); 1429 } 1430 1431 reset() 1432 { 1433 struct fd_set mask; 1434 int nfnd = 1; 1435 1436 FD_ZERO(&mask); 1437 while (nfnd > 0) { 1438 FD_SET(fileno(cin), &mask); 1439 if ((nfnd = empty(&mask,0)) < 0) { 1440 perror("reset"); 1441 code = -1; 1442 lostpeer(); 1443 } 1444 else if (nfnd) { 1445 (void) getreply(0); 1446 } 1447 } 1448 } 1449 1450 char * 1451 gunique(local) 1452 char *local; 1453 { 1454 static char new[MAXPATHLEN]; 1455 char *cp = rindex(local, '/'); 1456 int d, count=0; 1457 char ext = '1'; 1458 1459 if (cp) 1460 *cp = '\0'; 1461 d = access(cp ? local : ".", 2); 1462 if (cp) 1463 *cp = '/'; 1464 if (d < 0) { 1465 perror(local); 1466 return((char *) 0); 1467 } 1468 (void) strcpy(new, local); 1469 cp = new + strlen(new); 1470 *cp++ = '.'; 1471 while (!d) { 1472 if (++count == 100) { 1473 printf("runique: can't find unique file name.\n"); 1474 return((char *) 0); 1475 } 1476 *cp++ = ext; 1477 *cp = '\0'; 1478 if (ext == '9') 1479 ext = '0'; 1480 else 1481 ext++; 1482 if ((d = access(new, 0)) < 0) 1483 break; 1484 if (ext != '0') 1485 cp--; 1486 else if (*(cp - 2) == '.') 1487 *(cp - 1) = '1'; 1488 else { 1489 *(cp - 2) = *(cp - 2) + 1; 1490 cp--; 1491 } 1492 } 1493 return(new); 1494 } 1495