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