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.19 (Berkeley) 06/29/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(), *mygetpass(); 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 = mygetpass("Password:"); 192 n = command("PASS %s", pass); 193 } 194 if (n == CONTINUE) { 195 aflag++; 196 acct = mygetpass("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, *mypopen(); 384 int (*closefunc)(), mypclose(), 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 = mypopen(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 = mypclose; 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 && verbose) 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 && verbose) 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, *mypopen(); 576 int (*closefunc)(), mypclose(), 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 = mypopen(local + 1, "w"); 713 if (fout == NULL) { 714 perror(local+1); 715 goto abort; 716 } 717 closefunc = mypclose; 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 && verbose) 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 && verbose) 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 tvsub(&td, t1, t0); 988 s = td.tv_sec + (td.tv_usec / 1000000.); 989 #define nz(x) ((x) == 0 ? 1 : (x)) 990 bs = bytes / nz(s); 991 if (local && *local != '-') 992 printf("local: %s ", local); 993 if (remote) 994 printf("remote: %s\n", remote); 995 printf("%ld bytes %s in %.2g seconds (%.2g Kbytes/s)\n", 996 bytes, direction, s, bs / 1024.); 997 } 998 999 /*tvadd(tsum, t0) 1000 struct timeval *tsum, *t0; 1001 { 1002 1003 tsum->tv_sec += t0->tv_sec; 1004 tsum->tv_usec += t0->tv_usec; 1005 if (tsum->tv_usec > 1000000) 1006 tsum->tv_sec++, tsum->tv_usec -= 1000000; 1007 } */ 1008 1009 tvsub(tdiff, t1, t0) 1010 struct timeval *tdiff, *t1, *t0; 1011 { 1012 1013 tdiff->tv_sec = t1->tv_sec - t0->tv_sec; 1014 tdiff->tv_usec = t1->tv_usec - t0->tv_usec; 1015 if (tdiff->tv_usec < 0) 1016 tdiff->tv_sec--, tdiff->tv_usec += 1000000; 1017 } 1018 1019 psabort() 1020 { 1021 extern int abrtflag; 1022 1023 abrtflag++; 1024 } 1025 1026 pswitch(flag) 1027 int flag; 1028 { 1029 extern int proxy, abrtflag; 1030 int (*oldintr)(); 1031 static struct comvars { 1032 int connect; 1033 char name[MAXHOSTNAMELEN]; 1034 struct sockaddr_in mctl; 1035 struct sockaddr_in hctl; 1036 FILE *in; 1037 FILE *out; 1038 int tpe; 1039 int cpnd; 1040 int sunqe; 1041 int runqe; 1042 int mcse; 1043 int ntflg; 1044 char nti[17]; 1045 char nto[17]; 1046 int mapflg; 1047 char mi[MAXPATHLEN]; 1048 char mo[MAXPATHLEN]; 1049 } proxstruct, tmpstruct; 1050 struct comvars *ip, *op; 1051 1052 abrtflag = 0; 1053 oldintr = signal(SIGINT, psabort); 1054 if (flag) { 1055 if (proxy) 1056 return; 1057 ip = &tmpstruct; 1058 op = &proxstruct; 1059 proxy++; 1060 } 1061 else { 1062 if (!proxy) 1063 return; 1064 ip = &proxstruct; 1065 op = &tmpstruct; 1066 proxy = 0; 1067 } 1068 ip->connect = connected; 1069 connected = op->connect; 1070 if (hostname) { 1071 (void) strncpy(ip->name, hostname, sizeof(ip->name) - 1); 1072 ip->name[strlen(ip->name)] = '\0'; 1073 } else 1074 ip->name[0] = 0; 1075 hostname = op->name; 1076 ip->hctl = hisctladdr; 1077 hisctladdr = op->hctl; 1078 ip->mctl = myctladdr; 1079 myctladdr = op->mctl; 1080 ip->in = cin; 1081 cin = op->in; 1082 ip->out = cout; 1083 cout = op->out; 1084 ip->tpe = type; 1085 type = op->tpe; 1086 if (!type) 1087 type = 1; 1088 ip->cpnd = cpend; 1089 cpend = op->cpnd; 1090 ip->sunqe = sunique; 1091 sunique = op->sunqe; 1092 ip->runqe = runique; 1093 runique = op->runqe; 1094 ip->mcse = mcase; 1095 mcase = op->mcse; 1096 ip->ntflg = ntflag; 1097 ntflag = op->ntflg; 1098 (void) strncpy(ip->nti, ntin, 16); 1099 (ip->nti)[strlen(ip->nti)] = '\0'; 1100 (void) strcpy(ntin, op->nti); 1101 (void) strncpy(ip->nto, ntout, 16); 1102 (ip->nto)[strlen(ip->nto)] = '\0'; 1103 (void) strcpy(ntout, op->nto); 1104 ip->mapflg = mapflag; 1105 mapflag = op->mapflg; 1106 (void) strncpy(ip->mi, mapin, MAXPATHLEN - 1); 1107 (ip->mi)[strlen(ip->mi)] = '\0'; 1108 (void) strcpy(mapin, op->mi); 1109 (void) strncpy(ip->mo, mapout, MAXPATHLEN - 1); 1110 (ip->mo)[strlen(ip->mo)] = '\0'; 1111 (void) strcpy(mapout, op->mo); 1112 (void) signal(SIGINT, oldintr); 1113 if (abrtflag) { 1114 abrtflag = 0; 1115 (*oldintr)(); 1116 } 1117 } 1118 1119 jmp_buf ptabort; 1120 int ptabflg; 1121 1122 abortpt() 1123 { 1124 printf("\n"); 1125 (void) fflush(stdout); 1126 ptabflg++; 1127 mflag = 0; 1128 abrtflag = 0; 1129 longjmp(ptabort, 1); 1130 } 1131 1132 proxtrans(cmd, local, remote) 1133 char *cmd, *local, *remote; 1134 { 1135 int (*oldintr)(), abortpt(), tmptype, oldtype = 0, secndflag = 0, nfnd; 1136 extern jmp_buf ptabort; 1137 char *cmd2; 1138 struct fd_set mask; 1139 1140 if (strcmp(cmd, "RETR")) 1141 cmd2 = "RETR"; 1142 else 1143 cmd2 = runique ? "STOU" : "STOR"; 1144 if (command("PASV") != COMPLETE) { 1145 printf("proxy server does not support third part transfers.\n"); 1146 return; 1147 } 1148 tmptype = type; 1149 pswitch(0); 1150 if (!connected) { 1151 printf("No primary connection\n"); 1152 pswitch(1); 1153 code = -1; 1154 return; 1155 } 1156 if (type != tmptype) { 1157 oldtype = type; 1158 switch (tmptype) { 1159 case TYPE_A: 1160 setascii(); 1161 break; 1162 case TYPE_I: 1163 setbinary(); 1164 break; 1165 case TYPE_E: 1166 setebcdic(); 1167 break; 1168 case TYPE_L: 1169 settenex(); 1170 break; 1171 } 1172 } 1173 if (command("PORT %s", pasv) != COMPLETE) { 1174 switch (oldtype) { 1175 case 0: 1176 break; 1177 case TYPE_A: 1178 setascii(); 1179 break; 1180 case TYPE_I: 1181 setbinary(); 1182 break; 1183 case TYPE_E: 1184 setebcdic(); 1185 break; 1186 case TYPE_L: 1187 settenex(); 1188 break; 1189 } 1190 pswitch(1); 1191 return; 1192 } 1193 if (setjmp(ptabort)) 1194 goto abort; 1195 oldintr = signal(SIGINT, abortpt); 1196 if (command("%s %s", cmd, remote) != PRELIM) { 1197 (void) signal(SIGINT, oldintr); 1198 switch (oldtype) { 1199 case 0: 1200 break; 1201 case TYPE_A: 1202 setascii(); 1203 break; 1204 case TYPE_I: 1205 setbinary(); 1206 break; 1207 case TYPE_E: 1208 setebcdic(); 1209 break; 1210 case TYPE_L: 1211 settenex(); 1212 break; 1213 } 1214 pswitch(1); 1215 return; 1216 } 1217 sleep(2); 1218 pswitch(1); 1219 secndflag++; 1220 if (command("%s %s", cmd2, local) != PRELIM) 1221 goto abort; 1222 ptflag++; 1223 (void) getreply(0); 1224 pswitch(0); 1225 (void) getreply(0); 1226 (void) signal(SIGINT, oldintr); 1227 switch (oldtype) { 1228 case 0: 1229 break; 1230 case TYPE_A: 1231 setascii(); 1232 break; 1233 case TYPE_I: 1234 setbinary(); 1235 break; 1236 case TYPE_E: 1237 setebcdic(); 1238 break; 1239 case TYPE_L: 1240 settenex(); 1241 break; 1242 } 1243 pswitch(1); 1244 ptflag = 0; 1245 printf("local: %s remote: %s\n", local, remote); 1246 return; 1247 abort: 1248 (void) signal(SIGINT, SIG_IGN); 1249 ptflag = 0; 1250 if (strcmp(cmd, "RETR") && !proxy) 1251 pswitch(1); 1252 else if (!strcmp(cmd, "RETR") && proxy) 1253 pswitch(0); 1254 if (!cpend && !secndflag) { /* only here if cmd = "STOR" (proxy=1) */ 1255 if (command("%s %s", cmd2, local) != PRELIM) { 1256 pswitch(0); 1257 switch (oldtype) { 1258 case 0: 1259 break; 1260 case TYPE_A: 1261 setascii(); 1262 break; 1263 case TYPE_I: 1264 setbinary(); 1265 break; 1266 case TYPE_E: 1267 setebcdic(); 1268 break; 1269 case TYPE_L: 1270 settenex(); 1271 break; 1272 } 1273 if (cpend) { 1274 char msg[2]; 1275 1276 fprintf(cout,"%c%c",IAC,IP); 1277 (void) fflush(cout); 1278 *msg = IAC; 1279 *(msg+1) = DM; 1280 if (send(fileno(cout),msg,2,MSG_OOB) != 2) 1281 perror("abort"); 1282 fprintf(cout,"ABOR\r\n"); 1283 (void) fflush(cout); 1284 FD_ZERO(&mask); 1285 FD_SET(fileno(cin), &mask); 1286 if ((nfnd = empty(&mask,10)) <= 0) { 1287 if (nfnd < 0) { 1288 perror("abort"); 1289 } 1290 if (ptabflg) 1291 code = -1; 1292 lostpeer(); 1293 } 1294 (void) getreply(0); 1295 (void) getreply(0); 1296 } 1297 } 1298 pswitch(1); 1299 if (ptabflg) 1300 code = -1; 1301 (void) signal(SIGINT, oldintr); 1302 return; 1303 } 1304 if (cpend) { 1305 char msg[2]; 1306 1307 fprintf(cout,"%c%c",IAC,IP); 1308 (void) fflush(cout); 1309 *msg = IAC; 1310 *(msg+1) = DM; 1311 if (send(fileno(cout),msg,2,MSG_OOB) != 2) 1312 perror("abort"); 1313 fprintf(cout,"ABOR\r\n"); 1314 (void) fflush(cout); 1315 FD_ZERO(&mask); 1316 FD_SET(fileno(cin), &mask); 1317 if ((nfnd = empty(&mask,10)) <= 0) { 1318 if (nfnd < 0) { 1319 perror("abort"); 1320 } 1321 if (ptabflg) 1322 code = -1; 1323 lostpeer(); 1324 } 1325 (void) getreply(0); 1326 (void) getreply(0); 1327 } 1328 pswitch(!proxy); 1329 if (!cpend && !secndflag) { /* only if cmd = "RETR" (proxy=1) */ 1330 if (command("%s %s", cmd2, local) != PRELIM) { 1331 pswitch(0); 1332 switch (oldtype) { 1333 case 0: 1334 break; 1335 case TYPE_A: 1336 setascii(); 1337 break; 1338 case TYPE_I: 1339 setbinary(); 1340 break; 1341 case TYPE_E: 1342 setebcdic(); 1343 break; 1344 case TYPE_L: 1345 settenex(); 1346 break; 1347 } 1348 if (cpend) { 1349 char msg[2]; 1350 1351 fprintf(cout,"%c%c",IAC,IP); 1352 (void) fflush(cout); 1353 *msg = IAC; 1354 *(msg+1) = DM; 1355 if (send(fileno(cout),msg,2,MSG_OOB) != 2) 1356 perror("abort"); 1357 fprintf(cout,"ABOR\r\n"); 1358 (void) fflush(cout); 1359 FD_ZERO(&mask); 1360 FD_SET(fileno(cin), &mask); 1361 if ((nfnd = empty(&mask,10)) <= 0) { 1362 if (nfnd < 0) { 1363 perror("abort"); 1364 } 1365 if (ptabflg) 1366 code = -1; 1367 lostpeer(); 1368 } 1369 (void) getreply(0); 1370 (void) getreply(0); 1371 } 1372 pswitch(1); 1373 if (ptabflg) 1374 code = -1; 1375 (void) signal(SIGINT, oldintr); 1376 return; 1377 } 1378 } 1379 if (cpend) { 1380 char msg[2]; 1381 1382 fprintf(cout,"%c%c",IAC,IP); 1383 (void) fflush(cout); 1384 *msg = IAC; 1385 *(msg+1) = DM; 1386 if (send(fileno(cout),msg,2,MSG_OOB) != 2) 1387 perror("abort"); 1388 fprintf(cout,"ABOR\r\n"); 1389 (void) fflush(cout); 1390 FD_ZERO(&mask); 1391 FD_SET(fileno(cin), &mask); 1392 if ((nfnd = empty(&mask,10)) <= 0) { 1393 if (nfnd < 0) { 1394 perror("abort"); 1395 } 1396 if (ptabflg) 1397 code = -1; 1398 lostpeer(); 1399 } 1400 (void) getreply(0); 1401 (void) getreply(0); 1402 } 1403 pswitch(!proxy); 1404 if (cpend) { 1405 FD_ZERO(&mask); 1406 FD_SET(fileno(cin), &mask); 1407 if ((nfnd = empty(&mask,10)) <= 0) { 1408 if (nfnd < 0) { 1409 perror("abort"); 1410 } 1411 if (ptabflg) 1412 code = -1; 1413 lostpeer(); 1414 } 1415 (void) getreply(0); 1416 (void) getreply(0); 1417 } 1418 if (proxy) 1419 pswitch(0); 1420 switch (oldtype) { 1421 case 0: 1422 break; 1423 case TYPE_A: 1424 setascii(); 1425 break; 1426 case TYPE_I: 1427 setbinary(); 1428 break; 1429 case TYPE_E: 1430 setebcdic(); 1431 break; 1432 case TYPE_L: 1433 settenex(); 1434 break; 1435 } 1436 pswitch(1); 1437 if (ptabflg) 1438 code = -1; 1439 (void) signal(SIGINT, oldintr); 1440 } 1441 1442 reset() 1443 { 1444 struct fd_set mask; 1445 int nfnd = 1; 1446 1447 FD_ZERO(&mask); 1448 while (nfnd > 0) { 1449 FD_SET(fileno(cin), &mask); 1450 if ((nfnd = empty(&mask,0)) < 0) { 1451 perror("reset"); 1452 code = -1; 1453 lostpeer(); 1454 } 1455 else if (nfnd) { 1456 (void) getreply(0); 1457 } 1458 } 1459 } 1460 1461 char * 1462 gunique(local) 1463 char *local; 1464 { 1465 static char new[MAXPATHLEN]; 1466 char *cp = rindex(local, '/'); 1467 int d, count=0; 1468 char ext = '1'; 1469 1470 if (cp) 1471 *cp = '\0'; 1472 d = access(cp ? local : ".", 2); 1473 if (cp) 1474 *cp = '/'; 1475 if (d < 0) { 1476 perror(local); 1477 return((char *) 0); 1478 } 1479 (void) strcpy(new, local); 1480 cp = new + strlen(new); 1481 *cp++ = '.'; 1482 while (!d) { 1483 if (++count == 100) { 1484 printf("runique: can't find unique file name.\n"); 1485 return((char *) 0); 1486 } 1487 *cp++ = ext; 1488 *cp = '\0'; 1489 if (ext == '9') 1490 ext = '0'; 1491 else 1492 ext++; 1493 if ((d = access(new, 0)) < 0) 1494 break; 1495 if (ext != '0') 1496 cp--; 1497 else if (*(cp - 2) == '.') 1498 *(cp - 1) = '1'; 1499 else { 1500 *(cp - 2) = *(cp - 2) + 1; 1501 cp--; 1502 } 1503 } 1504 return(new); 1505 } 1506