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