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