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.38 (Berkeley) 04/22/91"; 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)(SIGINT); 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)(SIGINT); 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 (errno != EPIPE) 574 perror("netout"); 575 bytes = -1; 576 } 577 break; 578 579 case TYPE_A: 580 while ((c = getc(fin)) != EOF) { 581 if (c == '\n') { 582 while (hash && (bytes >= hashbytes)) { 583 (void) putchar('#'); 584 (void) fflush(stdout); 585 hashbytes += HASHBYTES; 586 } 587 if (ferror(dout)) 588 break; 589 (void) putc('\r', dout); 590 bytes++; 591 } 592 (void) putc(c, dout); 593 bytes++; 594 /* if (c == '\r') { */ 595 /* (void) putc('\0', dout); /* this violates rfc */ 596 /* bytes++; */ 597 /* } */ 598 } 599 if (hash) { 600 if (bytes < hashbytes) 601 (void) putchar('#'); 602 (void) putchar('\n'); 603 (void) fflush(stdout); 604 } 605 if (ferror(fin)) 606 fprintf(stderr, "local: %s: %s\n", local, 607 strerror(errno)); 608 if (ferror(dout)) { 609 if (errno != EPIPE) 610 perror("netout"); 611 bytes = -1; 612 } 613 break; 614 } 615 (void) gettimeofday(&stop, (struct timezone *)0); 616 if (closefunc != NULL) 617 (*closefunc)(fin); 618 (void) fclose(dout); 619 (void) getreply(0); 620 (void) signal(SIGINT, oldintr); 621 if (oldintp) 622 (void) signal(SIGPIPE, oldintp); 623 if (bytes > 0) 624 ptransfer("sent", bytes, &start, &stop); 625 return; 626 abort: 627 (void) gettimeofday(&stop, (struct timezone *)0); 628 (void) signal(SIGINT, oldintr); 629 if (oldintp) 630 (void) signal(SIGPIPE, oldintp); 631 if (!cpend) { 632 code = -1; 633 return; 634 } 635 if (data >= 0) { 636 (void) close(data); 637 data = -1; 638 } 639 if (dout) 640 (void) fclose(dout); 641 (void) getreply(0); 642 code = -1; 643 if (closefunc != NULL && fin != NULL) 644 (*closefunc)(fin); 645 if (bytes > 0) 646 ptransfer("sent", bytes, &start, &stop); 647 } 648 649 jmp_buf recvabort; 650 651 void 652 abortrecv() 653 { 654 655 mflag = 0; 656 abrtflag = 0; 657 printf("\nreceive aborted\nwaiting for remote to finish abort\n"); 658 (void) fflush(stdout); 659 longjmp(recvabort, 1); 660 } 661 662 recvrequest(cmd, local, remote, lmode, printnames) 663 char *cmd, *local, *remote, *lmode; 664 { 665 FILE *fout, *din = 0, *popen(); 666 int (*closefunc)(), pclose(), fclose(); 667 sig_t oldintr, oldintp; 668 int is_retr, tcrflag, bare_lfs = 0; 669 char *gunique(); 670 static int bufsize; 671 static char *buf; 672 long bytes = 0, hashbytes = HASHBYTES; 673 register int c, d; 674 struct timeval start, stop; 675 struct stat st; 676 off_t lseek(); 677 void abortrecv(); 678 char *malloc(); 679 680 is_retr = strcmp(cmd, "RETR") == 0; 681 if (is_retr && verbose && printnames) { 682 if (local && *local != '-') 683 printf("local: %s ", local); 684 if (remote) 685 printf("remote: %s\n", remote); 686 } 687 if (proxy && is_retr) { 688 proxtrans(cmd, local, remote); 689 return; 690 } 691 closefunc = NULL; 692 oldintr = NULL; 693 oldintp = NULL; 694 tcrflag = !crflag && is_retr; 695 if (setjmp(recvabort)) { 696 while (cpend) { 697 (void) getreply(0); 698 } 699 if (data >= 0) { 700 (void) close(data); 701 data = -1; 702 } 703 if (oldintr) 704 (void) signal(SIGINT, oldintr); 705 code = -1; 706 return; 707 } 708 oldintr = signal(SIGINT, abortrecv); 709 if (strcmp(local, "-") && *local != '|') { 710 if (access(local, 2) < 0) { 711 char *dir = rindex(local, '/'); 712 713 if (errno != ENOENT && errno != EACCES) { 714 fprintf(stderr, "local: %s: %s\n", local, 715 strerror(errno)); 716 (void) signal(SIGINT, oldintr); 717 code = -1; 718 return; 719 } 720 if (dir != NULL) 721 *dir = 0; 722 d = access(dir ? local : ".", 2); 723 if (dir != NULL) 724 *dir = '/'; 725 if (d < 0) { 726 fprintf(stderr, "local: %s: %s\n", local, 727 strerror(errno)); 728 (void) signal(SIGINT, oldintr); 729 code = -1; 730 return; 731 } 732 if (!runique && errno == EACCES && 733 chmod(local, 0600) < 0) { 734 fprintf(stderr, "local: %s: %s\n", local, 735 strerror(errno)); 736 (void) signal(SIGINT, oldintr); 737 (void) signal(SIGINT, oldintr); 738 code = -1; 739 return; 740 } 741 if (runique && errno == EACCES && 742 (local = gunique(local)) == NULL) { 743 (void) signal(SIGINT, oldintr); 744 code = -1; 745 return; 746 } 747 } 748 else if (runique && (local = gunique(local)) == NULL) { 749 (void) signal(SIGINT, oldintr); 750 code = -1; 751 return; 752 } 753 } 754 if (!is_retr) { 755 if (curtype != TYPE_A) 756 changetype(TYPE_A, 0); 757 } else if (curtype != type) 758 changetype(type, 0); 759 if (initconn()) { 760 (void) signal(SIGINT, oldintr); 761 code = -1; 762 return; 763 } 764 if (setjmp(recvabort)) 765 goto abort; 766 if (is_retr && restart_point && 767 command("REST %ld", (long) restart_point) != CONTINUE) 768 return; 769 if (remote) { 770 if (command("%s %s", cmd, remote) != PRELIM) { 771 (void) signal(SIGINT, oldintr); 772 return; 773 } 774 } else { 775 if (command("%s", cmd) != PRELIM) { 776 (void) signal(SIGINT, oldintr); 777 return; 778 } 779 } 780 din = dataconn("r"); 781 if (din == NULL) 782 goto abort; 783 if (strcmp(local, "-") == 0) 784 fout = stdout; 785 else if (*local == '|') { 786 oldintp = signal(SIGPIPE, SIG_IGN); 787 fout = popen(local + 1, "w"); 788 if (fout == NULL) { 789 perror(local+1); 790 goto abort; 791 } 792 closefunc = pclose; 793 } else { 794 fout = fopen(local, lmode); 795 if (fout == NULL) { 796 fprintf(stderr, "local: %s: %s\n", local, 797 strerror(errno)); 798 goto abort; 799 } 800 closefunc = fclose; 801 } 802 if (fstat(fileno(fout), &st) < 0 || st.st_blksize == 0) 803 st.st_blksize = BUFSIZ; 804 if (st.st_blksize > bufsize) { 805 if (buf) 806 (void) free(buf); 807 buf = malloc((unsigned)st.st_blksize); 808 if (buf == NULL) { 809 perror("malloc"); 810 bufsize = 0; 811 goto abort; 812 } 813 bufsize = st.st_blksize; 814 } 815 (void) gettimeofday(&start, (struct timezone *)0); 816 switch (curtype) { 817 818 case TYPE_I: 819 case TYPE_L: 820 if (restart_point && 821 lseek(fileno(fout), (long) restart_point, L_SET) < 0) { 822 fprintf(stderr, "local: %s: %s\n", local, 823 strerror(errno)); 824 if (closefunc != NULL) 825 (*closefunc)(fout); 826 return; 827 } 828 errno = d = 0; 829 while ((c = read(fileno(din), buf, bufsize)) > 0) { 830 if ((d = write(fileno(fout), buf, c)) != c) 831 break; 832 bytes += c; 833 if (hash) { 834 while (bytes >= hashbytes) { 835 (void) putchar('#'); 836 hashbytes += HASHBYTES; 837 } 838 (void) fflush(stdout); 839 } 840 } 841 if (hash && bytes > 0) { 842 if (bytes < HASHBYTES) 843 (void) putchar('#'); 844 (void) putchar('\n'); 845 (void) fflush(stdout); 846 } 847 if (c < 0) { 848 if (errno != EPIPE) 849 perror("netin"); 850 bytes = -1; 851 } 852 if (d < c) { 853 if (d < 0) 854 fprintf(stderr, "local: %s: %s\n", local, 855 strerror(errno)); 856 else 857 fprintf(stderr, "%s: short write\n", local); 858 } 859 break; 860 861 case TYPE_A: 862 if (restart_point) { 863 register int i, n, ch; 864 865 if (fseek(fout, 0L, L_SET) < 0) 866 goto done; 867 n = restart_point; 868 for (i = 0; i++ < n;) { 869 if ((ch = getc(fout)) == EOF) 870 goto done; 871 if (ch == '\n') 872 i++; 873 } 874 if (fseek(fout, 0L, L_INCR) < 0) { 875 done: 876 fprintf(stderr, "local: %s: %s\n", local, 877 strerror(errno)); 878 if (closefunc != NULL) 879 (*closefunc)(fout); 880 return; 881 } 882 } 883 while ((c = getc(din)) != EOF) { 884 if (c == '\n') 885 bare_lfs++; 886 while (c == '\r') { 887 while (hash && (bytes >= hashbytes)) { 888 (void) putchar('#'); 889 (void) fflush(stdout); 890 hashbytes += HASHBYTES; 891 } 892 bytes++; 893 if ((c = getc(din)) != '\n' || tcrflag) { 894 if (ferror(fout)) 895 goto break2; 896 (void) putc('\r', fout); 897 if (c == '\0') { 898 bytes++; 899 goto contin2; 900 } 901 if (c == EOF) 902 goto contin2; 903 } 904 } 905 (void) putc(c, fout); 906 bytes++; 907 contin2: ; 908 } 909 break2: 910 if (bare_lfs) { 911 printf("WARNING! %d bare linefeeds received in ASCII mode\n", bare_lfs); 912 printf("File may not have transferred correctly.\n"); 913 } 914 if (hash) { 915 if (bytes < hashbytes) 916 (void) putchar('#'); 917 (void) putchar('\n'); 918 (void) fflush(stdout); 919 } 920 if (ferror(din)) { 921 if (errno != EPIPE) 922 perror("netin"); 923 bytes = -1; 924 } 925 if (ferror(fout)) 926 fprintf(stderr, "local: %s: %s\n", local, 927 strerror(errno)); 928 break; 929 } 930 if (closefunc != NULL) 931 (*closefunc)(fout); 932 (void) signal(SIGINT, oldintr); 933 if (oldintp) 934 (void) signal(SIGPIPE, oldintp); 935 (void) gettimeofday(&stop, (struct timezone *)0); 936 (void) fclose(din); 937 (void) getreply(0); 938 if (bytes > 0 && is_retr) 939 ptransfer("received", bytes, &start, &stop); 940 return; 941 abort: 942 943 /* abort using RFC959 recommended IP,SYNC sequence */ 944 945 (void) gettimeofday(&stop, (struct timezone *)0); 946 if (oldintp) 947 (void) signal(SIGPIPE, oldintr); 948 (void) signal(SIGINT, SIG_IGN); 949 if (!cpend) { 950 code = -1; 951 (void) signal(SIGINT, oldintr); 952 return; 953 } 954 955 abort_remote(din); 956 code = -1; 957 if (data >= 0) { 958 (void) close(data); 959 data = -1; 960 } 961 if (closefunc != NULL && fout != NULL) 962 (*closefunc)(fout); 963 if (din) 964 (void) fclose(din); 965 if (bytes > 0) 966 ptransfer("received", bytes, &start, &stop); 967 (void) signal(SIGINT, oldintr); 968 } 969 970 /* 971 * Need to start a listen on the data channel before we send the command, 972 * otherwise the server's connect may fail. 973 */ 974 initconn() 975 { 976 register char *p, *a; 977 int result, len, tmpno = 0; 978 int on = 1; 979 980 noport: 981 data_addr = myctladdr; 982 if (sendport) 983 data_addr.sin_port = 0; /* let system pick one */ 984 if (data != -1) 985 (void) close(data); 986 data = socket(AF_INET, SOCK_STREAM, 0); 987 if (data < 0) { 988 perror("ftp: socket"); 989 if (tmpno) 990 sendport = 1; 991 return (1); 992 } 993 if (!sendport) 994 if (setsockopt(data, SOL_SOCKET, SO_REUSEADDR, (char *)&on, sizeof (on)) < 0) { 995 perror("ftp: setsockopt (reuse address)"); 996 goto bad; 997 } 998 if (bind(data, (struct sockaddr *)&data_addr, sizeof (data_addr)) < 0) { 999 perror("ftp: bind"); 1000 goto bad; 1001 } 1002 if (options & SO_DEBUG && 1003 setsockopt(data, SOL_SOCKET, SO_DEBUG, (char *)&on, sizeof (on)) < 0) 1004 perror("ftp: setsockopt (ignored)"); 1005 len = sizeof (data_addr); 1006 if (getsockname(data, (struct sockaddr *)&data_addr, &len) < 0) { 1007 perror("ftp: getsockname"); 1008 goto bad; 1009 } 1010 if (listen(data, 1) < 0) 1011 perror("ftp: listen"); 1012 if (sendport) { 1013 a = (char *)&data_addr.sin_addr; 1014 p = (char *)&data_addr.sin_port; 1015 #define UC(b) (((int)b)&0xff) 1016 result = 1017 command("PORT %d,%d,%d,%d,%d,%d", 1018 UC(a[0]), UC(a[1]), UC(a[2]), UC(a[3]), 1019 UC(p[0]), UC(p[1])); 1020 if (result == ERROR && sendport == -1) { 1021 sendport = 0; 1022 tmpno = 1; 1023 goto noport; 1024 } 1025 return (result != COMPLETE); 1026 } 1027 if (tmpno) 1028 sendport = 1; 1029 #ifdef IP_TOS 1030 on = IPTOS_THROUGHPUT; 1031 if (setsockopt(data, IPPROTO_IP, IP_TOS, (char *)&on, sizeof(int)) < 0) 1032 perror("ftp: setsockopt TOS (ignored)"); 1033 #endif 1034 return (0); 1035 bad: 1036 (void) close(data), data = -1; 1037 if (tmpno) 1038 sendport = 1; 1039 return (1); 1040 } 1041 1042 FILE * 1043 dataconn(lmode) 1044 char *lmode; 1045 { 1046 struct sockaddr_in from; 1047 int s, fromlen = sizeof (from), tos; 1048 1049 s = accept(data, (struct sockaddr *) &from, &fromlen); 1050 if (s < 0) { 1051 perror("ftp: accept"); 1052 (void) close(data), data = -1; 1053 return (NULL); 1054 } 1055 (void) close(data); 1056 data = s; 1057 #ifdef IP_TOS 1058 tos = IPTOS_THROUGHPUT; 1059 if (setsockopt(s, IPPROTO_IP, IP_TOS, (char *)&tos, sizeof(int)) < 0) 1060 perror("ftp: setsockopt TOS (ignored)"); 1061 #endif 1062 return (fdopen(data, lmode)); 1063 } 1064 1065 ptransfer(direction, bytes, t0, t1) 1066 char *direction; 1067 long bytes; 1068 struct timeval *t0, *t1; 1069 { 1070 struct timeval td; 1071 float s, bs; 1072 1073 if (verbose) { 1074 tvsub(&td, t1, t0); 1075 s = td.tv_sec + (td.tv_usec / 1000000.); 1076 #define nz(x) ((x) == 0 ? 1 : (x)) 1077 bs = bytes / nz(s); 1078 printf("%ld bytes %s in %.2g seconds (%.2g Kbytes/s)\n", 1079 bytes, direction, s, bs / 1024.); 1080 } 1081 } 1082 1083 /*tvadd(tsum, t0) 1084 struct timeval *tsum, *t0; 1085 { 1086 1087 tsum->tv_sec += t0->tv_sec; 1088 tsum->tv_usec += t0->tv_usec; 1089 if (tsum->tv_usec > 1000000) 1090 tsum->tv_sec++, tsum->tv_usec -= 1000000; 1091 } */ 1092 1093 tvsub(tdiff, t1, t0) 1094 struct timeval *tdiff, *t1, *t0; 1095 { 1096 1097 tdiff->tv_sec = t1->tv_sec - t0->tv_sec; 1098 tdiff->tv_usec = t1->tv_usec - t0->tv_usec; 1099 if (tdiff->tv_usec < 0) 1100 tdiff->tv_sec--, tdiff->tv_usec += 1000000; 1101 } 1102 1103 void 1104 psabort() 1105 { 1106 extern int abrtflag; 1107 1108 abrtflag++; 1109 } 1110 1111 pswitch(flag) 1112 int flag; 1113 { 1114 extern int proxy, abrtflag; 1115 sig_t oldintr; 1116 static struct comvars { 1117 int connect; 1118 char name[MAXHOSTNAMELEN]; 1119 struct sockaddr_in mctl; 1120 struct sockaddr_in hctl; 1121 FILE *in; 1122 FILE *out; 1123 int tpe; 1124 int curtpe; 1125 int cpnd; 1126 int sunqe; 1127 int runqe; 1128 int mcse; 1129 int ntflg; 1130 char nti[17]; 1131 char nto[17]; 1132 int mapflg; 1133 char mi[MAXPATHLEN]; 1134 char mo[MAXPATHLEN]; 1135 } proxstruct, tmpstruct; 1136 struct comvars *ip, *op; 1137 1138 abrtflag = 0; 1139 oldintr = signal(SIGINT, psabort); 1140 if (flag) { 1141 if (proxy) 1142 return; 1143 ip = &tmpstruct; 1144 op = &proxstruct; 1145 proxy++; 1146 } else { 1147 if (!proxy) 1148 return; 1149 ip = &proxstruct; 1150 op = &tmpstruct; 1151 proxy = 0; 1152 } 1153 ip->connect = connected; 1154 connected = op->connect; 1155 if (hostname) { 1156 (void) strncpy(ip->name, hostname, sizeof(ip->name) - 1); 1157 ip->name[strlen(ip->name)] = '\0'; 1158 } else 1159 ip->name[0] = 0; 1160 hostname = op->name; 1161 ip->hctl = hisctladdr; 1162 hisctladdr = op->hctl; 1163 ip->mctl = myctladdr; 1164 myctladdr = op->mctl; 1165 ip->in = cin; 1166 cin = op->in; 1167 ip->out = cout; 1168 cout = op->out; 1169 ip->tpe = type; 1170 type = op->tpe; 1171 ip->curtpe = curtype; 1172 curtype = op->curtpe; 1173 ip->cpnd = cpend; 1174 cpend = op->cpnd; 1175 ip->sunqe = sunique; 1176 sunique = op->sunqe; 1177 ip->runqe = runique; 1178 runique = op->runqe; 1179 ip->mcse = mcase; 1180 mcase = op->mcse; 1181 ip->ntflg = ntflag; 1182 ntflag = op->ntflg; 1183 (void) strncpy(ip->nti, ntin, 16); 1184 (ip->nti)[strlen(ip->nti)] = '\0'; 1185 (void) strcpy(ntin, op->nti); 1186 (void) strncpy(ip->nto, ntout, 16); 1187 (ip->nto)[strlen(ip->nto)] = '\0'; 1188 (void) strcpy(ntout, op->nto); 1189 ip->mapflg = mapflag; 1190 mapflag = op->mapflg; 1191 (void) strncpy(ip->mi, mapin, MAXPATHLEN - 1); 1192 (ip->mi)[strlen(ip->mi)] = '\0'; 1193 (void) strcpy(mapin, op->mi); 1194 (void) strncpy(ip->mo, mapout, MAXPATHLEN - 1); 1195 (ip->mo)[strlen(ip->mo)] = '\0'; 1196 (void) strcpy(mapout, op->mo); 1197 (void) signal(SIGINT, oldintr); 1198 if (abrtflag) { 1199 abrtflag = 0; 1200 (*oldintr)(SIGINT); 1201 } 1202 } 1203 1204 jmp_buf ptabort; 1205 int ptabflg; 1206 1207 void 1208 abortpt() 1209 { 1210 printf("\n"); 1211 (void) fflush(stdout); 1212 ptabflg++; 1213 mflag = 0; 1214 abrtflag = 0; 1215 longjmp(ptabort, 1); 1216 } 1217 1218 proxtrans(cmd, local, remote) 1219 char *cmd, *local, *remote; 1220 { 1221 sig_t oldintr; 1222 int secndflag = 0, prox_type, nfnd; 1223 extern jmp_buf ptabort; 1224 char *cmd2; 1225 struct fd_set mask; 1226 void abortpt(); 1227 1228 if (strcmp(cmd, "RETR")) 1229 cmd2 = "RETR"; 1230 else 1231 cmd2 = runique ? "STOU" : "STOR"; 1232 if ((prox_type = type) == 0) { 1233 if (unix_server && unix_proxy) 1234 prox_type = TYPE_I; 1235 else 1236 prox_type = TYPE_A; 1237 } 1238 if (curtype != prox_type) 1239 changetype(prox_type, 1); 1240 if (command("PASV") != COMPLETE) { 1241 printf("proxy server does not support third party transfers.\n"); 1242 return; 1243 } 1244 pswitch(0); 1245 if (!connected) { 1246 printf("No primary connection\n"); 1247 pswitch(1); 1248 code = -1; 1249 return; 1250 } 1251 if (curtype != prox_type) 1252 changetype(prox_type, 1); 1253 if (command("PORT %s", pasv) != COMPLETE) { 1254 pswitch(1); 1255 return; 1256 } 1257 if (setjmp(ptabort)) 1258 goto abort; 1259 oldintr = signal(SIGINT, abortpt); 1260 if (command("%s %s", cmd, remote) != PRELIM) { 1261 (void) signal(SIGINT, oldintr); 1262 pswitch(1); 1263 return; 1264 } 1265 sleep(2); 1266 pswitch(1); 1267 secndflag++; 1268 if (command("%s %s", cmd2, local) != PRELIM) 1269 goto abort; 1270 ptflag++; 1271 (void) getreply(0); 1272 pswitch(0); 1273 (void) getreply(0); 1274 (void) signal(SIGINT, oldintr); 1275 pswitch(1); 1276 ptflag = 0; 1277 printf("local: %s remote: %s\n", local, remote); 1278 return; 1279 abort: 1280 (void) signal(SIGINT, SIG_IGN); 1281 ptflag = 0; 1282 if (strcmp(cmd, "RETR") && !proxy) 1283 pswitch(1); 1284 else if (!strcmp(cmd, "RETR") && proxy) 1285 pswitch(0); 1286 if (!cpend && !secndflag) { /* only here if cmd = "STOR" (proxy=1) */ 1287 if (command("%s %s", cmd2, local) != PRELIM) { 1288 pswitch(0); 1289 if (cpend) 1290 abort_remote((FILE *) NULL); 1291 } 1292 pswitch(1); 1293 if (ptabflg) 1294 code = -1; 1295 (void) signal(SIGINT, oldintr); 1296 return; 1297 } 1298 if (cpend) 1299 abort_remote((FILE *) NULL); 1300 pswitch(!proxy); 1301 if (!cpend && !secndflag) { /* only if cmd = "RETR" (proxy=1) */ 1302 if (command("%s %s", cmd2, local) != PRELIM) { 1303 pswitch(0); 1304 if (cpend) 1305 abort_remote((FILE *) NULL); 1306 pswitch(1); 1307 if (ptabflg) 1308 code = -1; 1309 (void) signal(SIGINT, oldintr); 1310 return; 1311 } 1312 } 1313 if (cpend) 1314 abort_remote((FILE *) NULL); 1315 pswitch(!proxy); 1316 if (cpend) { 1317 FD_ZERO(&mask); 1318 FD_SET(fileno(cin), &mask); 1319 if ((nfnd = empty(&mask, 10)) <= 0) { 1320 if (nfnd < 0) { 1321 perror("abort"); 1322 } 1323 if (ptabflg) 1324 code = -1; 1325 lostpeer(); 1326 } 1327 (void) getreply(0); 1328 (void) getreply(0); 1329 } 1330 if (proxy) 1331 pswitch(0); 1332 pswitch(1); 1333 if (ptabflg) 1334 code = -1; 1335 (void) signal(SIGINT, oldintr); 1336 } 1337 1338 reset() 1339 { 1340 struct fd_set mask; 1341 int nfnd = 1; 1342 1343 FD_ZERO(&mask); 1344 while (nfnd > 0) { 1345 FD_SET(fileno(cin), &mask); 1346 if ((nfnd = empty(&mask,0)) < 0) { 1347 perror("reset"); 1348 code = -1; 1349 lostpeer(); 1350 } 1351 else if (nfnd) { 1352 (void) getreply(0); 1353 } 1354 } 1355 } 1356 1357 char * 1358 gunique(local) 1359 char *local; 1360 { 1361 static char new[MAXPATHLEN]; 1362 char *cp = rindex(local, '/'); 1363 int d, count=0; 1364 char ext = '1'; 1365 1366 if (cp) 1367 *cp = '\0'; 1368 d = access(cp ? local : ".", 2); 1369 if (cp) 1370 *cp = '/'; 1371 if (d < 0) { 1372 fprintf(stderr, "local: %s: %s\n", local, strerror(errno)); 1373 return((char *) 0); 1374 } 1375 (void) strcpy(new, local); 1376 cp = new + strlen(new); 1377 *cp++ = '.'; 1378 while (!d) { 1379 if (++count == 100) { 1380 printf("runique: can't find unique file name.\n"); 1381 return((char *) 0); 1382 } 1383 *cp++ = ext; 1384 *cp = '\0'; 1385 if (ext == '9') 1386 ext = '0'; 1387 else 1388 ext++; 1389 if ((d = access(new, 0)) < 0) 1390 break; 1391 if (ext != '0') 1392 cp--; 1393 else if (*(cp - 2) == '.') 1394 *(cp - 1) = '1'; 1395 else { 1396 *(cp - 2) = *(cp - 2) + 1; 1397 cp--; 1398 } 1399 } 1400 return(new); 1401 } 1402 1403 abort_remote(din) 1404 FILE *din; 1405 { 1406 char buf[BUFSIZ]; 1407 int nfnd; 1408 struct fd_set mask; 1409 1410 /* 1411 * send IAC in urgent mode instead of DM because 4.3BSD places oob mark 1412 * after urgent byte rather than before as is protocol now 1413 */ 1414 sprintf(buf, "%c%c%c", IAC, IP, IAC); 1415 if (send(fileno(cout), buf, 3, MSG_OOB) != 3) 1416 perror("abort"); 1417 fprintf(cout,"%cABOR\r\n", DM); 1418 (void) fflush(cout); 1419 FD_ZERO(&mask); 1420 FD_SET(fileno(cin), &mask); 1421 if (din) { 1422 FD_SET(fileno(din), &mask); 1423 } 1424 if ((nfnd = empty(&mask, 10)) <= 0) { 1425 if (nfnd < 0) { 1426 perror("abort"); 1427 } 1428 if (ptabflg) 1429 code = -1; 1430 lostpeer(); 1431 } 1432 if (din && FD_ISSET(fileno(din), &mask)) { 1433 while (read(fileno(din), buf, BUFSIZ) > 0) 1434 /* LOOP */; 1435 } 1436 if (getreply(0) == ERROR && code == 552) { 1437 /* 552 needed for nic style abort */ 1438 (void) getreply(0); 1439 } 1440 (void) getreply(0); 1441 } 1442