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