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.5 1994/03/28 07:11:18 cgd 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), 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; 1099 long bs; 1100 1101 if (verbose) { 1102 tvsub(&td, t1, t0); 1103 s = td.tv_sec + (td.tv_usec / 1000000.); 1104 #define nz(x) ((x) == 0 ? 1 : (x)) 1105 bs = bytes / nz(s); 1106 printf("%ld bytes %s in %.3g secs (%ld bytes/sec)\n", 1107 bytes, direction, s, bs); 1108 } 1109 } 1110 1111 /*tvadd(tsum, t0) 1112 struct timeval *tsum, *t0; 1113 { 1114 1115 tsum->tv_sec += t0->tv_sec; 1116 tsum->tv_usec += t0->tv_usec; 1117 if (tsum->tv_usec > 1000000) 1118 tsum->tv_sec++, tsum->tv_usec -= 1000000; 1119 } */ 1120 1121 tvsub(tdiff, t1, t0) 1122 struct timeval *tdiff, *t1, *t0; 1123 { 1124 1125 tdiff->tv_sec = t1->tv_sec - t0->tv_sec; 1126 tdiff->tv_usec = t1->tv_usec - t0->tv_usec; 1127 if (tdiff->tv_usec < 0) 1128 tdiff->tv_sec--, tdiff->tv_usec += 1000000; 1129 } 1130 1131 void 1132 psabort() 1133 { 1134 extern int abrtflag; 1135 1136 abrtflag++; 1137 } 1138 1139 pswitch(flag) 1140 int flag; 1141 { 1142 extern int proxy, abrtflag; 1143 sig_t oldintr; 1144 static struct comvars { 1145 int connect; 1146 char name[MAXHOSTNAMELEN]; 1147 struct sockaddr_in mctl; 1148 struct sockaddr_in hctl; 1149 FILE *in; 1150 FILE *out; 1151 int tpe; 1152 int curtpe; 1153 int cpnd; 1154 int sunqe; 1155 int runqe; 1156 int mcse; 1157 int ntflg; 1158 char nti[17]; 1159 char nto[17]; 1160 int mapflg; 1161 char mi[MAXPATHLEN]; 1162 char mo[MAXPATHLEN]; 1163 } proxstruct, tmpstruct; 1164 struct comvars *ip, *op; 1165 1166 abrtflag = 0; 1167 oldintr = signal(SIGINT, psabort); 1168 if (flag) { 1169 if (proxy) 1170 return; 1171 ip = &tmpstruct; 1172 op = &proxstruct; 1173 proxy++; 1174 } else { 1175 if (!proxy) 1176 return; 1177 ip = &proxstruct; 1178 op = &tmpstruct; 1179 proxy = 0; 1180 } 1181 ip->connect = connected; 1182 connected = op->connect; 1183 if (hostname) { 1184 (void) strncpy(ip->name, hostname, sizeof(ip->name) - 1); 1185 ip->name[strlen(ip->name)] = '\0'; 1186 } else 1187 ip->name[0] = 0; 1188 hostname = op->name; 1189 ip->hctl = hisctladdr; 1190 hisctladdr = op->hctl; 1191 ip->mctl = myctladdr; 1192 myctladdr = op->mctl; 1193 ip->in = cin; 1194 cin = op->in; 1195 ip->out = cout; 1196 cout = op->out; 1197 ip->tpe = type; 1198 type = op->tpe; 1199 ip->curtpe = curtype; 1200 curtype = op->curtpe; 1201 ip->cpnd = cpend; 1202 cpend = op->cpnd; 1203 ip->sunqe = sunique; 1204 sunique = op->sunqe; 1205 ip->runqe = runique; 1206 runique = op->runqe; 1207 ip->mcse = mcase; 1208 mcase = op->mcse; 1209 ip->ntflg = ntflag; 1210 ntflag = op->ntflg; 1211 (void) strncpy(ip->nti, ntin, 16); 1212 (ip->nti)[strlen(ip->nti)] = '\0'; 1213 (void) strcpy(ntin, op->nti); 1214 (void) strncpy(ip->nto, ntout, 16); 1215 (ip->nto)[strlen(ip->nto)] = '\0'; 1216 (void) strcpy(ntout, op->nto); 1217 ip->mapflg = mapflag; 1218 mapflag = op->mapflg; 1219 (void) strncpy(ip->mi, mapin, MAXPATHLEN - 1); 1220 (ip->mi)[strlen(ip->mi)] = '\0'; 1221 (void) strcpy(mapin, op->mi); 1222 (void) strncpy(ip->mo, mapout, MAXPATHLEN - 1); 1223 (ip->mo)[strlen(ip->mo)] = '\0'; 1224 (void) strcpy(mapout, op->mo); 1225 (void) signal(SIGINT, oldintr); 1226 if (abrtflag) { 1227 abrtflag = 0; 1228 (*oldintr)(SIGINT); 1229 } 1230 } 1231 1232 jmp_buf ptabort; 1233 int ptabflg; 1234 1235 void 1236 abortpt() 1237 { 1238 printf("\n"); 1239 (void) fflush(stdout); 1240 ptabflg++; 1241 mflag = 0; 1242 abrtflag = 0; 1243 longjmp(ptabort, 1); 1244 } 1245 1246 proxtrans(cmd, local, remote) 1247 char *cmd, *local, *remote; 1248 { 1249 sig_t oldintr; 1250 int secndflag = 0, prox_type, nfnd; 1251 extern jmp_buf ptabort; 1252 char *cmd2; 1253 struct fd_set mask; 1254 void abortpt(); 1255 1256 if (strcmp(cmd, "RETR")) 1257 cmd2 = "RETR"; 1258 else 1259 cmd2 = runique ? "STOU" : "STOR"; 1260 if ((prox_type = type) == 0) { 1261 if (unix_server && unix_proxy) 1262 prox_type = TYPE_I; 1263 else 1264 prox_type = TYPE_A; 1265 } 1266 if (curtype != prox_type) 1267 changetype(prox_type, 1); 1268 if (command("PASV") != COMPLETE) { 1269 printf("proxy server does not support third party transfers.\n"); 1270 return; 1271 } 1272 pswitch(0); 1273 if (!connected) { 1274 printf("No primary connection\n"); 1275 pswitch(1); 1276 code = -1; 1277 return; 1278 } 1279 if (curtype != prox_type) 1280 changetype(prox_type, 1); 1281 if (command("PORT %s", pasv) != COMPLETE) { 1282 pswitch(1); 1283 return; 1284 } 1285 if (setjmp(ptabort)) 1286 goto abort; 1287 oldintr = signal(SIGINT, abortpt); 1288 if (command("%s %s", cmd, remote) != PRELIM) { 1289 (void) signal(SIGINT, oldintr); 1290 pswitch(1); 1291 return; 1292 } 1293 sleep(2); 1294 pswitch(1); 1295 secndflag++; 1296 if (command("%s %s", cmd2, local) != PRELIM) 1297 goto abort; 1298 ptflag++; 1299 (void) getreply(0); 1300 pswitch(0); 1301 (void) getreply(0); 1302 (void) signal(SIGINT, oldintr); 1303 pswitch(1); 1304 ptflag = 0; 1305 printf("local: %s remote: %s\n", local, remote); 1306 return; 1307 abort: 1308 (void) signal(SIGINT, SIG_IGN); 1309 ptflag = 0; 1310 if (strcmp(cmd, "RETR") && !proxy) 1311 pswitch(1); 1312 else if (!strcmp(cmd, "RETR") && proxy) 1313 pswitch(0); 1314 if (!cpend && !secndflag) { /* only here if cmd = "STOR" (proxy=1) */ 1315 if (command("%s %s", cmd2, local) != PRELIM) { 1316 pswitch(0); 1317 if (cpend) 1318 abort_remote((FILE *) NULL); 1319 } 1320 pswitch(1); 1321 if (ptabflg) 1322 code = -1; 1323 (void) signal(SIGINT, oldintr); 1324 return; 1325 } 1326 if (cpend) 1327 abort_remote((FILE *) NULL); 1328 pswitch(!proxy); 1329 if (!cpend && !secndflag) { /* only if cmd = "RETR" (proxy=1) */ 1330 if (command("%s %s", cmd2, local) != PRELIM) { 1331 pswitch(0); 1332 if (cpend) 1333 abort_remote((FILE *) NULL); 1334 pswitch(1); 1335 if (ptabflg) 1336 code = -1; 1337 (void) signal(SIGINT, oldintr); 1338 return; 1339 } 1340 } 1341 if (cpend) 1342 abort_remote((FILE *) NULL); 1343 pswitch(!proxy); 1344 if (cpend) { 1345 FD_ZERO(&mask); 1346 FD_SET(fileno(cin), &mask); 1347 if ((nfnd = empty(&mask, 10)) <= 0) { 1348 if (nfnd < 0) { 1349 perror("abort"); 1350 } 1351 if (ptabflg) 1352 code = -1; 1353 lostpeer(); 1354 } 1355 (void) getreply(0); 1356 (void) getreply(0); 1357 } 1358 if (proxy) 1359 pswitch(0); 1360 pswitch(1); 1361 if (ptabflg) 1362 code = -1; 1363 (void) signal(SIGINT, oldintr); 1364 } 1365 1366 reset() 1367 { 1368 struct fd_set mask; 1369 int nfnd = 1; 1370 1371 FD_ZERO(&mask); 1372 while (nfnd > 0) { 1373 FD_SET(fileno(cin), &mask); 1374 if ((nfnd = empty(&mask,0)) < 0) { 1375 perror("reset"); 1376 code = -1; 1377 lostpeer(); 1378 } 1379 else if (nfnd) { 1380 (void) getreply(0); 1381 } 1382 } 1383 } 1384 1385 char * 1386 gunique(local) 1387 char *local; 1388 { 1389 static char new[MAXPATHLEN]; 1390 char *cp = rindex(local, '/'); 1391 int d, count=0; 1392 char ext = '1'; 1393 1394 if (cp) 1395 *cp = '\0'; 1396 d = access(cp ? local : ".", 2); 1397 if (cp) 1398 *cp = '/'; 1399 if (d < 0) { 1400 fprintf(stderr, "local: %s: %s\n", local, strerror(errno)); 1401 return((char *) 0); 1402 } 1403 (void) strcpy(new, local); 1404 cp = new + strlen(new); 1405 *cp++ = '.'; 1406 while (!d) { 1407 if (++count == 100) { 1408 printf("runique: can't find unique file name.\n"); 1409 return((char *) 0); 1410 } 1411 *cp++ = ext; 1412 *cp = '\0'; 1413 if (ext == '9') 1414 ext = '0'; 1415 else 1416 ext++; 1417 if ((d = access(new, 0)) < 0) 1418 break; 1419 if (ext != '0') 1420 cp--; 1421 else if (*(cp - 2) == '.') 1422 *(cp - 1) = '1'; 1423 else { 1424 *(cp - 2) = *(cp - 2) + 1; 1425 cp--; 1426 } 1427 } 1428 return(new); 1429 } 1430 1431 abort_remote(din) 1432 FILE *din; 1433 { 1434 char buf[BUFSIZ]; 1435 int nfnd; 1436 struct fd_set mask; 1437 1438 /* 1439 * send IAC in urgent mode instead of DM because 4.3BSD places oob mark 1440 * after urgent byte rather than before as is protocol now 1441 */ 1442 sprintf(buf, "%c%c%c", IAC, IP, IAC); 1443 if (send(fileno(cout), buf, 3, MSG_OOB) != 3) 1444 perror("abort"); 1445 fprintf(cout,"%cABOR\r\n", DM); 1446 (void) fflush(cout); 1447 FD_ZERO(&mask); 1448 FD_SET(fileno(cin), &mask); 1449 if (din) { 1450 FD_SET(fileno(din), &mask); 1451 } 1452 if ((nfnd = empty(&mask, 10)) <= 0) { 1453 if (nfnd < 0) { 1454 perror("abort"); 1455 } 1456 if (ptabflg) 1457 code = -1; 1458 lostpeer(); 1459 } 1460 if (din && FD_ISSET(fileno(din), &mask)) { 1461 while (read(fileno(din), buf, BUFSIZ) > 0) 1462 /* LOOP */; 1463 } 1464 if (getreply(0) == ERROR && code == 552) { 1465 /* 552 needed for nic style abort */ 1466 (void) getreply(0); 1467 } 1468 (void) getreply(0); 1469 } 1470