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