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