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