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