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