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