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