1 /* 2 * Copyright (c) 1985 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.24 (Berkeley) 03/01/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) 390 char *cmd, *local, *remote; 391 { 392 FILE *fin, *dout = 0, *popen(); 393 int (*closefunc)(), pclose(), fclose(), (*oldintr)(), (*oldintp)(); 394 int abortsend(); 395 char buf[BUFSIZ]; 396 long bytes = 0, hashbytes = HASHBYTES; 397 register int c, d; 398 struct stat st; 399 struct timeval start, stop; 400 char *mode; 401 402 if (proxy) { 403 proxtrans(cmd, local, remote); 404 return; 405 } 406 closefunc = NULL; 407 oldintr = NULL; 408 oldintp = NULL; 409 mode = "w"; 410 if (setjmp(sendabort)) { 411 while (cpend) { 412 (void) getreply(0); 413 } 414 if (data >= 0) { 415 (void) close(data); 416 data = -1; 417 } 418 if (oldintr) 419 (void) signal(SIGINT,oldintr); 420 if (oldintp) 421 (void) signal(SIGPIPE,oldintp); 422 code = -1; 423 return; 424 } 425 oldintr = signal(SIGINT, abortsend); 426 if (strcmp(local, "-") == 0) 427 fin = stdin; 428 else if (*local == '|') { 429 oldintp = signal(SIGPIPE,SIG_IGN); 430 fin = popen(local + 1, "r"); 431 if (fin == NULL) { 432 perror(local + 1); 433 (void) signal(SIGINT, oldintr); 434 (void) signal(SIGPIPE, oldintp); 435 code = -1; 436 return; 437 } 438 closefunc = pclose; 439 } else { 440 fin = fopen(local, "r"); 441 if (fin == NULL) { 442 perror(local); 443 (void) signal(SIGINT, oldintr); 444 code = -1; 445 return; 446 } 447 closefunc = fclose; 448 if (fstat(fileno(fin), &st) < 0 || 449 (st.st_mode&S_IFMT) != S_IFREG) { 450 fprintf(stdout, "%s: not a plain file.\n", local); 451 (void) signal(SIGINT, oldintr); 452 fclose(fin); 453 code = -1; 454 return; 455 } 456 } 457 if (initconn()) { 458 (void) signal(SIGINT, oldintr); 459 if (oldintp) 460 (void) signal(SIGPIPE, oldintp); 461 code = -1; 462 if (closefunc != NULL) 463 (*closefunc)(fin); 464 return; 465 } 466 if (setjmp(sendabort)) 467 goto abort; 468 469 if (strcmp(cmd, "STOR") == 0 || strcmp(cmd, "APPE") == 0) { 470 if (restart_point) { 471 if (fseek(fin, (long) restart_point, 0) < 0) { 472 perror(local); 473 restart_point = 0; 474 if (closefunc != NULL) 475 (*closefunc)(fin); 476 return; 477 } 478 if (command("REST %ld", (long) restart_point) 479 != CONTINUE) { 480 restart_point = 0; 481 if (closefunc != NULL) 482 (*closefunc)(fin); 483 return; 484 } 485 restart_point = 0; 486 mode = "r+w"; 487 } 488 } 489 if (remote) { 490 if (command("%s %s", cmd, remote) != PRELIM) { 491 (void) signal(SIGINT, oldintr); 492 if (oldintp) 493 (void) signal(SIGPIPE, oldintp); 494 if (closefunc != NULL) 495 (*closefunc)(fin); 496 return; 497 } 498 } else 499 if (command("%s", cmd) != PRELIM) { 500 (void) signal(SIGINT, oldintr); 501 if (oldintp) 502 (void) signal(SIGPIPE, oldintp); 503 if (closefunc != NULL) 504 (*closefunc)(fin); 505 return; 506 } 507 dout = dataconn(mode); 508 if (dout == NULL) 509 goto abort; 510 (void) gettimeofday(&start, (struct timezone *)0); 511 oldintp = signal(SIGPIPE, SIG_IGN); 512 switch (type) { 513 514 case TYPE_I: 515 case TYPE_L: 516 errno = d = 0; 517 while ((c = read(fileno (fin), buf, sizeof (buf))) > 0) { 518 if ((d = write(fileno (dout), buf, c)) != c) 519 break; 520 bytes += c; 521 if (hash) { 522 while (bytes >= hashbytes) { 523 (void) putchar('#'); 524 hashbytes += HASHBYTES; 525 } 526 (void) fflush(stdout); 527 } 528 } 529 if (hash && bytes > 0) { 530 if (bytes < HASHBYTES) 531 (void) putchar('#'); 532 (void) putchar('\n'); 533 (void) fflush(stdout); 534 } 535 if (c < 0) 536 perror(local); 537 if (d < 0) { 538 if (errno != EPIPE) 539 perror("netout"); 540 bytes = -1; 541 } 542 break; 543 544 case TYPE_A: 545 while ((c = getc(fin)) != EOF) { 546 if (c == '\n') { 547 while (hash && (bytes >= hashbytes)) { 548 (void) putchar('#'); 549 (void) fflush(stdout); 550 hashbytes += HASHBYTES; 551 } 552 if (ferror(dout)) 553 break; 554 (void) putc('\r', dout); 555 bytes++; 556 } 557 (void) putc(c, dout); 558 bytes++; 559 /* if (c == '\r') { */ 560 /* (void) putc('\0', dout); /* this violates rfc */ 561 /* bytes++; */ 562 /* } */ 563 } 564 if (hash) { 565 if (bytes < hashbytes) 566 (void) putchar('#'); 567 (void) putchar('\n'); 568 (void) fflush(stdout); 569 } 570 if (ferror(fin)) 571 perror(local); 572 if (ferror(dout)) { 573 if (errno != EPIPE) 574 perror("netout"); 575 bytes = -1; 576 } 577 break; 578 } 579 (void) gettimeofday(&stop, (struct timezone *)0); 580 if (closefunc != NULL) 581 (*closefunc)(fin); 582 (void) fclose(dout); 583 (void) getreply(0); 584 (void) signal(SIGINT, oldintr); 585 if (oldintp) 586 (void) signal(SIGPIPE, oldintp); 587 if (bytes > 0) 588 ptransfer("sent", bytes, &start, &stop, local, remote); 589 return; 590 abort: 591 (void) gettimeofday(&stop, (struct timezone *)0); 592 (void) signal(SIGINT, oldintr); 593 if (oldintp) 594 (void) signal(SIGPIPE, oldintp); 595 if (!cpend) { 596 code = -1; 597 return; 598 } 599 if (data >= 0) { 600 (void) close(data); 601 data = -1; 602 } 603 if (dout) 604 (void) fclose(dout); 605 (void) getreply(0); 606 code = -1; 607 if (closefunc != NULL && fin != NULL) 608 (*closefunc)(fin); 609 if (bytes > 0) 610 ptransfer("sent", bytes, &start, &stop, local, remote); 611 } 612 613 jmp_buf recvabort; 614 615 abortrecv() 616 { 617 618 mflag = 0; 619 abrtflag = 0; 620 printf("\n"); 621 (void) fflush(stdout); 622 longjmp(recvabort, 1); 623 } 624 625 recvrequest(cmd, local, remote, mode) 626 char *cmd, *local, *remote, *mode; 627 { 628 FILE *fout, *din = 0, *popen(); 629 int (*closefunc)(), pclose(), fclose(), (*oldintr)(), (*oldintp)(); 630 int abortrecv(), oldverbose, oldtype = 0, is_retr, tcrflag, nfnd; 631 char *buf, *gunique(), msg; 632 static int bufsize; 633 long bytes = 0, hashbytes = HASHBYTES; 634 struct fd_set mask; 635 register int c, d; 636 struct timeval start, stop; 637 struct stat st; 638 extern char *malloc(); 639 640 is_retr = strcmp(cmd, "RETR") == 0; 641 if (proxy && is_retr) { 642 proxtrans(cmd, local, remote); 643 return; 644 } 645 closefunc = NULL; 646 oldintr = NULL; 647 oldintp = NULL; 648 tcrflag = !crflag && is_retr; 649 if (setjmp(recvabort)) { 650 while (cpend) { 651 (void) getreply(0); 652 } 653 if (data >= 0) { 654 (void) close(data); 655 data = -1; 656 } 657 if (oldintr) 658 (void) signal(SIGINT, oldintr); 659 code = -1; 660 return; 661 } 662 oldintr = signal(SIGINT, abortrecv); 663 if (strcmp(local, "-") && *local != '|') { 664 if (access(local, 2) < 0) { 665 char *dir = rindex(local, '/'); 666 667 if (errno != ENOENT && errno != EACCES) { 668 perror(local); 669 (void) signal(SIGINT, oldintr); 670 code = -1; 671 return; 672 } 673 if (dir != NULL) 674 *dir = 0; 675 d = access(dir ? local : ".", 2); 676 if (dir != NULL) 677 *dir = '/'; 678 if (d < 0) { 679 perror(local); 680 (void) signal(SIGINT, oldintr); 681 code = -1; 682 return; 683 } 684 if (!runique && errno == EACCES && 685 chmod(local, 0600) < 0) { 686 perror(local); 687 (void) signal(SIGINT, oldintr); 688 code = -1; 689 return; 690 } 691 if (runique && errno == EACCES && 692 (local = gunique(local)) == NULL) { 693 (void) signal(SIGINT, oldintr); 694 code = -1; 695 return; 696 } 697 } 698 else if (runique && (local = gunique(local)) == NULL) { 699 (void) signal(SIGINT, oldintr); 700 code = -1; 701 return; 702 } 703 } 704 if (initconn()) { 705 (void) signal(SIGINT, oldintr); 706 code = -1; 707 return; 708 } 709 if (setjmp(recvabort)) 710 goto abort; 711 if (!is_retr) { 712 if (type != TYPE_A) { 713 oldtype = type; 714 oldverbose = verbose; 715 if (!debug) 716 verbose = 0; 717 setascii(); 718 verbose = oldverbose; 719 } 720 } else if (restart_point) { 721 if (command("REST %ld", (long) restart_point) != CONTINUE) 722 return; 723 } 724 if (remote) { 725 if (command("%s %s", cmd, remote) != PRELIM) { 726 (void) signal(SIGINT, oldintr); 727 if (oldtype) { 728 if (!debug) 729 verbose = 0; 730 switch (oldtype) { 731 case TYPE_I: 732 setbinary(); 733 break; 734 case TYPE_E: 735 setebcdic(); 736 break; 737 case TYPE_L: 738 settenex(); 739 break; 740 } 741 verbose = oldverbose; 742 } 743 return; 744 } 745 } else { 746 if (command("%s", cmd) != PRELIM) { 747 (void) signal(SIGINT, oldintr); 748 if (oldtype) { 749 if (!debug) 750 verbose = 0; 751 switch (oldtype) { 752 case TYPE_I: 753 setbinary(); 754 break; 755 case TYPE_E: 756 setebcdic(); 757 break; 758 case TYPE_L: 759 settenex(); 760 break; 761 } 762 verbose = oldverbose; 763 } 764 return; 765 } 766 } 767 din = dataconn("r"); 768 if (din == NULL) 769 goto abort; 770 if (strcmp(local, "-") == 0) 771 fout = stdout; 772 else if (*local == '|') { 773 oldintp = signal(SIGPIPE, SIG_IGN); 774 fout = popen(local + 1, "w"); 775 if (fout == NULL) { 776 perror(local+1); 777 goto abort; 778 } 779 closefunc = pclose; 780 } else { 781 fout = fopen(local, mode); 782 if (fout == NULL) { 783 perror(local); 784 goto abort; 785 } 786 closefunc = fclose; 787 } 788 if (fstat(fileno(fout), &st) < 0 || st.st_blksize == 0) 789 st.st_blksize = BUFSIZ; 790 if (st.st_blksize > bufsize) { 791 if (buf) 792 (void) free(buf); 793 buf = malloc(st.st_blksize); 794 if (buf == NULL) { 795 perror("malloc"); 796 goto abort; 797 } 798 bufsize = st.st_blksize; 799 } 800 (void) gettimeofday(&start, (struct timezone *)0); 801 switch (type) { 802 803 case TYPE_I: 804 case TYPE_L: 805 if (restart_point && 806 lseek(fileno(fout), (long) restart_point, L_SET) < 0) { 807 perror(local); 808 if (closefunc != NULL) 809 (*closefunc)(fout); 810 return; 811 } 812 errno = d = 0; 813 while ((c = read(fileno(din), buf, bufsize)) > 0) { 814 if ((d = write(fileno(fout), buf, c)) != c) 815 break; 816 bytes += c; 817 if (hash) { 818 while (bytes >= hashbytes) { 819 (void) putchar('#'); 820 hashbytes += HASHBYTES; 821 } 822 (void) fflush(stdout); 823 } 824 } 825 if (hash && bytes > 0) { 826 if (bytes < HASHBYTES) 827 (void) putchar('#'); 828 (void) putchar('\n'); 829 (void) fflush(stdout); 830 } 831 if (c < 0) { 832 if (errno != EPIPE) 833 perror("netin"); 834 bytes = -1; 835 } 836 if (d < 0) 837 perror(local); 838 break; 839 840 case TYPE_A: 841 if (restart_point) { 842 register int i, n, c; 843 844 if (fseek(fout, 0L, L_SET) < 0) 845 goto done; 846 n = restart_point; 847 i = 0; 848 while (i++ < n) { 849 if ((c=getc(fout)) == EOF) 850 goto done; 851 if (c == '\n') 852 i++; 853 } 854 if (fseek(fout, 0L, L_INCR) < 0) { 855 done: 856 perror(local); 857 if (closefunc != NULL) 858 (*closefunc)(fout); 859 return; 860 } 861 } 862 while ((c = getc(din)) != EOF) { 863 while (c == '\r') { 864 while (hash && (bytes >= hashbytes)) { 865 (void) putchar('#'); 866 (void) fflush(stdout); 867 hashbytes += HASHBYTES; 868 } 869 bytes++; 870 if ((c = getc(din)) != '\n' || tcrflag) { 871 if (ferror(fout)) 872 goto break2; 873 (void) putc('\r', fout); 874 if (c == '\0' || c == EOF) 875 goto contin2; 876 } 877 } 878 (void) putc(c, fout); 879 bytes++; 880 contin2: ; 881 } 882 break2: 883 if (hash) { 884 if (bytes < hashbytes) 885 (void) putchar('#'); 886 (void) putchar('\n'); 887 (void) fflush(stdout); 888 } 889 if (ferror(din)){ 890 if (errno != EPIPE) 891 perror ("netin"); 892 bytes = -1; 893 } 894 if (ferror(fout)) 895 perror (local); 896 break; 897 } 898 if (closefunc != NULL) 899 (*closefunc)(fout); 900 (void) signal(SIGINT, oldintr); 901 if (oldintp) 902 (void) signal(SIGPIPE, oldintp); 903 (void) gettimeofday(&stop, (struct timezone *)0); 904 (void) fclose(din); 905 (void) getreply(0); 906 if (bytes > 0 && is_retr) 907 ptransfer("received", bytes, &start, &stop, local, remote); 908 if (oldtype) { 909 if (!debug) 910 verbose = 0; 911 switch (oldtype) { 912 case TYPE_I: 913 setbinary(); 914 break; 915 case TYPE_E: 916 setebcdic(); 917 break; 918 case TYPE_L: 919 settenex(); 920 break; 921 } 922 verbose = oldverbose; 923 } 924 return; 925 abort: 926 927 /* abort using RFC959 recommended IP,SYNC sequence */ 928 929 (void) gettimeofday(&stop, (struct timezone *)0); 930 if (oldintp) 931 (void) signal(SIGPIPE, oldintr); 932 (void) signal(SIGINT,SIG_IGN); 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 if (!cpend) { 950 code = -1; 951 (void) signal(SIGINT,oldintr); 952 return; 953 } 954 955 fprintf(cout,"%c%c",IAC,IP); 956 (void) fflush(cout); 957 msg = IAC; 958 /* send IAC in urgent mode instead of DM because UNIX places oob mark */ 959 /* after urgent byte rather than before as now is protocol */ 960 if (send(fileno(cout),&msg,1,MSG_OOB) != 1) { 961 perror("abort"); 962 } 963 fprintf(cout,"%cABOR\r\n",DM); 964 (void) fflush(cout); 965 FD_ZERO(&mask); 966 FD_SET(fileno(cin), &mask); 967 if (din) { 968 FD_SET(fileno(din), &mask); 969 } 970 if ((nfnd = empty(&mask,10)) <= 0) { 971 if (nfnd < 0) { 972 perror("abort"); 973 } 974 code = -1; 975 lostpeer(); 976 } 977 if (din && FD_ISSET(fileno(din), &mask)) { 978 while ((c = read(fileno(din), buf, bufsize)) > 0) 979 ; 980 } 981 if ((c = getreply(0)) == ERROR && code == 552) { /* needed for nic style abort */ 982 if (data >= 0) { 983 (void) close(data); 984 data = -1; 985 } 986 (void) getreply(0); 987 } 988 (void) getreply(0); 989 code = -1; 990 if (data >= 0) { 991 (void) close(data); 992 data = -1; 993 } 994 if (closefunc != NULL && fout != NULL) 995 (*closefunc)(fout); 996 if (din) 997 (void) fclose(din); 998 if (bytes > 0) 999 ptransfer("received", bytes, &start, &stop, local, remote); 1000 (void) signal(SIGINT,oldintr); 1001 } 1002 1003 /* 1004 * Need to start a listen on the data channel 1005 * before we send the command, otherwise the 1006 * server's connect may fail. 1007 */ 1008 int sendport = -1; 1009 1010 initconn() 1011 { 1012 register char *p, *a; 1013 int result, len, tmpno = 0; 1014 int on = 1; 1015 1016 noport: 1017 data_addr = myctladdr; 1018 if (sendport) 1019 data_addr.sin_port = 0; /* let system pick one */ 1020 if (data != -1) 1021 (void) close (data); 1022 data = socket(AF_INET, SOCK_STREAM, 0); 1023 if (data < 0) { 1024 perror("ftp: socket"); 1025 if (tmpno) 1026 sendport = 1; 1027 return (1); 1028 } 1029 if (!sendport) 1030 if (setsockopt(data, SOL_SOCKET, SO_REUSEADDR, (char *)&on, sizeof (on)) < 0) { 1031 perror("ftp: setsockopt (reuse address)"); 1032 goto bad; 1033 } 1034 if (bind(data, (struct sockaddr *)&data_addr, sizeof (data_addr)) < 0) { 1035 perror("ftp: bind"); 1036 goto bad; 1037 } 1038 if (options & SO_DEBUG && 1039 setsockopt(data, SOL_SOCKET, SO_DEBUG, (char *)&on, sizeof (on)) < 0) 1040 perror("ftp: setsockopt (ignored)"); 1041 len = sizeof (data_addr); 1042 if (getsockname(data, (char *)&data_addr, &len) < 0) { 1043 perror("ftp: getsockname"); 1044 goto bad; 1045 } 1046 if (listen(data, 1) < 0) 1047 perror("ftp: listen"); 1048 if (sendport) { 1049 a = (char *)&data_addr.sin_addr; 1050 p = (char *)&data_addr.sin_port; 1051 #define UC(b) (((int)b)&0xff) 1052 result = 1053 command("PORT %d,%d,%d,%d,%d,%d", 1054 UC(a[0]), UC(a[1]), UC(a[2]), UC(a[3]), 1055 UC(p[0]), UC(p[1])); 1056 if (result == ERROR && sendport == -1) { 1057 sendport = 0; 1058 tmpno = 1; 1059 goto noport; 1060 } 1061 return (result != COMPLETE); 1062 } 1063 if (tmpno) 1064 sendport = 1; 1065 return (0); 1066 bad: 1067 (void) close(data), data = -1; 1068 if (tmpno) 1069 sendport = 1; 1070 return (1); 1071 } 1072 1073 FILE * 1074 dataconn(mode) 1075 char *mode; 1076 { 1077 struct sockaddr_in from; 1078 int s, fromlen = sizeof (from); 1079 1080 s = accept(data, (struct sockaddr *) &from, &fromlen); 1081 if (s < 0) { 1082 perror("ftp: accept"); 1083 (void) close(data), data = -1; 1084 return (NULL); 1085 } 1086 (void) close(data); 1087 data = s; 1088 return (fdopen(data, mode)); 1089 } 1090 1091 ptransfer(direction, bytes, t0, t1, local, remote) 1092 char *direction, *local, *remote; 1093 long bytes; 1094 struct timeval *t0, *t1; 1095 { 1096 struct timeval td; 1097 float s, bs; 1098 1099 if (verbose) { 1100 tvsub(&td, t1, t0); 1101 s = td.tv_sec + (td.tv_usec / 1000000.); 1102 #define nz(x) ((x) == 0 ? 1 : (x)) 1103 bs = bytes / nz(s); 1104 printf("%ld bytes %s in %.2g seconds (%.2g Kbytes/s)\n", 1105 bytes, direction, s, bs / 1024.); 1106 } else { 1107 if (local && *local != '-') 1108 printf("local: %s ", local); 1109 if (remote) 1110 printf("remote: %s\n", remote); 1111 } 1112 } 1113 1114 /*tvadd(tsum, t0) 1115 struct timeval *tsum, *t0; 1116 { 1117 1118 tsum->tv_sec += t0->tv_sec; 1119 tsum->tv_usec += t0->tv_usec; 1120 if (tsum->tv_usec > 1000000) 1121 tsum->tv_sec++, tsum->tv_usec -= 1000000; 1122 } */ 1123 1124 tvsub(tdiff, t1, t0) 1125 struct timeval *tdiff, *t1, *t0; 1126 { 1127 1128 tdiff->tv_sec = t1->tv_sec - t0->tv_sec; 1129 tdiff->tv_usec = t1->tv_usec - t0->tv_usec; 1130 if (tdiff->tv_usec < 0) 1131 tdiff->tv_sec--, tdiff->tv_usec += 1000000; 1132 } 1133 1134 psabort() 1135 { 1136 extern int abrtflag; 1137 1138 abrtflag++; 1139 } 1140 1141 pswitch(flag) 1142 int flag; 1143 { 1144 extern int proxy, abrtflag; 1145 int (*oldintr)(); 1146 static struct comvars { 1147 int connect; 1148 char name[MAXHOSTNAMELEN]; 1149 struct sockaddr_in mctl; 1150 struct sockaddr_in hctl; 1151 FILE *in; 1152 FILE *out; 1153 int tpe; 1154 int cpnd; 1155 int sunqe; 1156 int runqe; 1157 int mcse; 1158 int ntflg; 1159 char nti[17]; 1160 char nto[17]; 1161 int mapflg; 1162 char mi[MAXPATHLEN]; 1163 char mo[MAXPATHLEN]; 1164 } proxstruct, tmpstruct; 1165 struct comvars *ip, *op; 1166 1167 abrtflag = 0; 1168 oldintr = signal(SIGINT, psabort); 1169 if (flag) { 1170 if (proxy) 1171 return; 1172 ip = &tmpstruct; 1173 op = &proxstruct; 1174 proxy++; 1175 } 1176 else { 1177 if (!proxy) 1178 return; 1179 ip = &proxstruct; 1180 op = &tmpstruct; 1181 proxy = 0; 1182 } 1183 ip->connect = connected; 1184 connected = op->connect; 1185 if (hostname) { 1186 (void) strncpy(ip->name, hostname, sizeof(ip->name) - 1); 1187 ip->name[strlen(ip->name)] = '\0'; 1188 } else 1189 ip->name[0] = 0; 1190 hostname = op->name; 1191 ip->hctl = hisctladdr; 1192 hisctladdr = op->hctl; 1193 ip->mctl = myctladdr; 1194 myctladdr = op->mctl; 1195 ip->in = cin; 1196 cin = op->in; 1197 ip->out = cout; 1198 cout = op->out; 1199 ip->tpe = type; 1200 type = op->tpe; 1201 if (!type) 1202 type = 1; 1203 ip->cpnd = cpend; 1204 cpend = op->cpnd; 1205 ip->sunqe = sunique; 1206 sunique = op->sunqe; 1207 ip->runqe = runique; 1208 runique = op->runqe; 1209 ip->mcse = mcase; 1210 mcase = op->mcse; 1211 ip->ntflg = ntflag; 1212 ntflag = op->ntflg; 1213 (void) strncpy(ip->nti, ntin, 16); 1214 (ip->nti)[strlen(ip->nti)] = '\0'; 1215 (void) strcpy(ntin, op->nti); 1216 (void) strncpy(ip->nto, ntout, 16); 1217 (ip->nto)[strlen(ip->nto)] = '\0'; 1218 (void) strcpy(ntout, op->nto); 1219 ip->mapflg = mapflag; 1220 mapflag = op->mapflg; 1221 (void) strncpy(ip->mi, mapin, MAXPATHLEN - 1); 1222 (ip->mi)[strlen(ip->mi)] = '\0'; 1223 (void) strcpy(mapin, op->mi); 1224 (void) strncpy(ip->mo, mapout, MAXPATHLEN - 1); 1225 (ip->mo)[strlen(ip->mo)] = '\0'; 1226 (void) strcpy(mapout, op->mo); 1227 (void) signal(SIGINT, oldintr); 1228 if (abrtflag) { 1229 abrtflag = 0; 1230 (*oldintr)(); 1231 } 1232 } 1233 1234 jmp_buf ptabort; 1235 int ptabflg; 1236 1237 abortpt() 1238 { 1239 printf("\n"); 1240 (void) fflush(stdout); 1241 ptabflg++; 1242 mflag = 0; 1243 abrtflag = 0; 1244 longjmp(ptabort, 1); 1245 } 1246 1247 proxtrans(cmd, local, remote) 1248 char *cmd, *local, *remote; 1249 { 1250 int (*oldintr)(), abortpt(), tmptype, oldtype = 0, secndflag = 0, nfnd; 1251 extern jmp_buf ptabort; 1252 char *cmd2; 1253 struct fd_set mask; 1254 1255 if (strcmp(cmd, "RETR")) 1256 cmd2 = "RETR"; 1257 else 1258 cmd2 = runique ? "STOU" : "STOR"; 1259 if (command("PASV") != COMPLETE) { 1260 printf("proxy server does not support third part transfers.\n"); 1261 return; 1262 } 1263 tmptype = type; 1264 pswitch(0); 1265 if (!connected) { 1266 printf("No primary connection\n"); 1267 pswitch(1); 1268 code = -1; 1269 return; 1270 } 1271 if (type != tmptype) { 1272 oldtype = type; 1273 switch (tmptype) { 1274 case TYPE_A: 1275 setascii(); 1276 break; 1277 case TYPE_I: 1278 setbinary(); 1279 break; 1280 case TYPE_E: 1281 setebcdic(); 1282 break; 1283 case TYPE_L: 1284 settenex(); 1285 break; 1286 } 1287 } 1288 if (command("PORT %s", pasv) != COMPLETE) { 1289 switch (oldtype) { 1290 case 0: 1291 break; 1292 case TYPE_A: 1293 setascii(); 1294 break; 1295 case TYPE_I: 1296 setbinary(); 1297 break; 1298 case TYPE_E: 1299 setebcdic(); 1300 break; 1301 case TYPE_L: 1302 settenex(); 1303 break; 1304 } 1305 pswitch(1); 1306 return; 1307 } 1308 if (setjmp(ptabort)) 1309 goto abort; 1310 oldintr = signal(SIGINT, abortpt); 1311 if (command("%s %s", cmd, remote) != PRELIM) { 1312 (void) signal(SIGINT, oldintr); 1313 switch (oldtype) { 1314 case 0: 1315 break; 1316 case TYPE_A: 1317 setascii(); 1318 break; 1319 case TYPE_I: 1320 setbinary(); 1321 break; 1322 case TYPE_E: 1323 setebcdic(); 1324 break; 1325 case TYPE_L: 1326 settenex(); 1327 break; 1328 } 1329 pswitch(1); 1330 return; 1331 } 1332 sleep(2); 1333 pswitch(1); 1334 secndflag++; 1335 if (command("%s %s", cmd2, local) != PRELIM) 1336 goto abort; 1337 ptflag++; 1338 (void) getreply(0); 1339 pswitch(0); 1340 (void) getreply(0); 1341 (void) signal(SIGINT, oldintr); 1342 switch (oldtype) { 1343 case 0: 1344 break; 1345 case TYPE_A: 1346 setascii(); 1347 break; 1348 case TYPE_I: 1349 setbinary(); 1350 break; 1351 case TYPE_E: 1352 setebcdic(); 1353 break; 1354 case TYPE_L: 1355 settenex(); 1356 break; 1357 } 1358 pswitch(1); 1359 ptflag = 0; 1360 printf("local: %s remote: %s\n", local, remote); 1361 return; 1362 abort: 1363 (void) signal(SIGINT, SIG_IGN); 1364 ptflag = 0; 1365 if (strcmp(cmd, "RETR") && !proxy) 1366 pswitch(1); 1367 else if (!strcmp(cmd, "RETR") && proxy) 1368 pswitch(0); 1369 if (!cpend && !secndflag) { /* only here if cmd = "STOR" (proxy=1) */ 1370 if (command("%s %s", cmd2, local) != PRELIM) { 1371 pswitch(0); 1372 switch (oldtype) { 1373 case 0: 1374 break; 1375 case TYPE_A: 1376 setascii(); 1377 break; 1378 case TYPE_I: 1379 setbinary(); 1380 break; 1381 case TYPE_E: 1382 setebcdic(); 1383 break; 1384 case TYPE_L: 1385 settenex(); 1386 break; 1387 } 1388 if (cpend) { 1389 char msg[2]; 1390 1391 fprintf(cout,"%c%c",IAC,IP); 1392 (void) fflush(cout); 1393 *msg = IAC; 1394 *(msg+1) = DM; 1395 if (send(fileno(cout),msg,2,MSG_OOB) != 2) 1396 perror("abort"); 1397 fprintf(cout,"ABOR\r\n"); 1398 (void) fflush(cout); 1399 FD_ZERO(&mask); 1400 FD_SET(fileno(cin), &mask); 1401 if ((nfnd = empty(&mask,10)) <= 0) { 1402 if (nfnd < 0) { 1403 perror("abort"); 1404 } 1405 if (ptabflg) 1406 code = -1; 1407 lostpeer(); 1408 } 1409 (void) getreply(0); 1410 (void) getreply(0); 1411 } 1412 } 1413 pswitch(1); 1414 if (ptabflg) 1415 code = -1; 1416 (void) signal(SIGINT, oldintr); 1417 return; 1418 } 1419 if (cpend) { 1420 char msg[2]; 1421 1422 fprintf(cout,"%c%c",IAC,IP); 1423 (void) fflush(cout); 1424 *msg = IAC; 1425 *(msg+1) = DM; 1426 if (send(fileno(cout),msg,2,MSG_OOB) != 2) 1427 perror("abort"); 1428 fprintf(cout,"ABOR\r\n"); 1429 (void) fflush(cout); 1430 FD_ZERO(&mask); 1431 FD_SET(fileno(cin), &mask); 1432 if ((nfnd = empty(&mask,10)) <= 0) { 1433 if (nfnd < 0) { 1434 perror("abort"); 1435 } 1436 if (ptabflg) 1437 code = -1; 1438 lostpeer(); 1439 } 1440 (void) getreply(0); 1441 (void) getreply(0); 1442 } 1443 pswitch(!proxy); 1444 if (!cpend && !secndflag) { /* only if cmd = "RETR" (proxy=1) */ 1445 if (command("%s %s", cmd2, local) != PRELIM) { 1446 pswitch(0); 1447 switch (oldtype) { 1448 case 0: 1449 break; 1450 case TYPE_A: 1451 setascii(); 1452 break; 1453 case TYPE_I: 1454 setbinary(); 1455 break; 1456 case TYPE_E: 1457 setebcdic(); 1458 break; 1459 case TYPE_L: 1460 settenex(); 1461 break; 1462 } 1463 if (cpend) { 1464 char msg[2]; 1465 1466 fprintf(cout,"%c%c",IAC,IP); 1467 (void) fflush(cout); 1468 *msg = IAC; 1469 *(msg+1) = DM; 1470 if (send(fileno(cout),msg,2,MSG_OOB) != 2) 1471 perror("abort"); 1472 fprintf(cout,"ABOR\r\n"); 1473 (void) fflush(cout); 1474 FD_ZERO(&mask); 1475 FD_SET(fileno(cin), &mask); 1476 if ((nfnd = empty(&mask,10)) <= 0) { 1477 if (nfnd < 0) { 1478 perror("abort"); 1479 } 1480 if (ptabflg) 1481 code = -1; 1482 lostpeer(); 1483 } 1484 (void) getreply(0); 1485 (void) getreply(0); 1486 } 1487 pswitch(1); 1488 if (ptabflg) 1489 code = -1; 1490 (void) signal(SIGINT, oldintr); 1491 return; 1492 } 1493 } 1494 if (cpend) { 1495 char msg[2]; 1496 1497 fprintf(cout,"%c%c",IAC,IP); 1498 (void) fflush(cout); 1499 *msg = IAC; 1500 *(msg+1) = DM; 1501 if (send(fileno(cout),msg,2,MSG_OOB) != 2) 1502 perror("abort"); 1503 fprintf(cout,"ABOR\r\n"); 1504 (void) fflush(cout); 1505 FD_ZERO(&mask); 1506 FD_SET(fileno(cin), &mask); 1507 if ((nfnd = empty(&mask,10)) <= 0) { 1508 if (nfnd < 0) { 1509 perror("abort"); 1510 } 1511 if (ptabflg) 1512 code = -1; 1513 lostpeer(); 1514 } 1515 (void) getreply(0); 1516 (void) getreply(0); 1517 } 1518 pswitch(!proxy); 1519 if (cpend) { 1520 FD_ZERO(&mask); 1521 FD_SET(fileno(cin), &mask); 1522 if ((nfnd = empty(&mask,10)) <= 0) { 1523 if (nfnd < 0) { 1524 perror("abort"); 1525 } 1526 if (ptabflg) 1527 code = -1; 1528 lostpeer(); 1529 } 1530 (void) getreply(0); 1531 (void) getreply(0); 1532 } 1533 if (proxy) 1534 pswitch(0); 1535 switch (oldtype) { 1536 case 0: 1537 break; 1538 case TYPE_A: 1539 setascii(); 1540 break; 1541 case TYPE_I: 1542 setbinary(); 1543 break; 1544 case TYPE_E: 1545 setebcdic(); 1546 break; 1547 case TYPE_L: 1548 settenex(); 1549 break; 1550 } 1551 pswitch(1); 1552 if (ptabflg) 1553 code = -1; 1554 (void) signal(SIGINT, oldintr); 1555 } 1556 1557 reset() 1558 { 1559 struct fd_set mask; 1560 int nfnd = 1; 1561 1562 FD_ZERO(&mask); 1563 while (nfnd > 0) { 1564 FD_SET(fileno(cin), &mask); 1565 if ((nfnd = empty(&mask,0)) < 0) { 1566 perror("reset"); 1567 code = -1; 1568 lostpeer(); 1569 } 1570 else if (nfnd) { 1571 (void) getreply(0); 1572 } 1573 } 1574 } 1575 1576 char * 1577 gunique(local) 1578 char *local; 1579 { 1580 static char new[MAXPATHLEN]; 1581 char *cp = rindex(local, '/'); 1582 int d, count=0; 1583 char ext = '1'; 1584 1585 if (cp) 1586 *cp = '\0'; 1587 d = access(cp ? local : ".", 2); 1588 if (cp) 1589 *cp = '/'; 1590 if (d < 0) { 1591 perror(local); 1592 return((char *) 0); 1593 } 1594 (void) strcpy(new, local); 1595 cp = new + strlen(new); 1596 *cp++ = '.'; 1597 while (!d) { 1598 if (++count == 100) { 1599 printf("runique: can't find unique file name.\n"); 1600 return((char *) 0); 1601 } 1602 *cp++ = ext; 1603 *cp = '\0'; 1604 if (ext == '9') 1605 ext = '0'; 1606 else 1607 ext++; 1608 if ((d = access(new, 0)) < 0) 1609 break; 1610 if (ext != '0') 1611 cp--; 1612 else if (*(cp - 2) == '.') 1613 *(cp - 1) = '1'; 1614 else { 1615 *(cp - 2) = *(cp - 2) + 1; 1616 cp--; 1617 } 1618 } 1619 return(new); 1620 } 1621