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