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