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