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