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