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