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