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