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