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