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