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