1 /* $NetBSD: ftp.c,v 1.28 1997/09/13 09:05:56 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.28 1997/09/13 09:05:56 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 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 || 502 (st.st_mode & S_IFMT) != S_IFREG) { 503 printf("%s: not a plain file.\n", local); 504 (void)signal(SIGINT, oldintr); 505 (void)signal(SIGINFO, oldinti); 506 fclose(fin); 507 code = -1; 508 return; 509 } 510 filesize = st.st_size; 511 } 512 if (initconn()) { 513 (void)signal(SIGINT, oldintr); 514 (void)signal(SIGINFO, oldinti); 515 if (oldintp) 516 (void)signal(SIGPIPE, oldintp); 517 code = -1; 518 progress = oprogress; 519 if (closefunc != NULL) 520 (*closefunc)(fin); 521 return; 522 } 523 if (setjmp(sendabort)) 524 goto abort; 525 526 if (restart_point && 527 (strcmp(cmd, "STOR") == 0 || strcmp(cmd, "APPE") == 0)) { 528 int rc; 529 530 rc = -1; 531 switch (curtype) { 532 case TYPE_A: 533 rc = fseek(fin, (long) restart_point, SEEK_SET); 534 break; 535 case TYPE_I: 536 case TYPE_L: 537 rc = lseek(fileno(fin), restart_point, SEEK_SET); 538 break; 539 } 540 if (rc < 0) { 541 warn("local: %s", local); 542 restart_point = 0; 543 progress = oprogress; 544 if (closefunc != NULL) 545 (*closefunc)(fin); 546 return; 547 } 548 if (command("REST %ld", (long) restart_point) 549 != CONTINUE) { 550 restart_point = 0; 551 progress = oprogress; 552 if (closefunc != NULL) 553 (*closefunc)(fin); 554 return; 555 } 556 restart_point = 0; 557 lmode = "r+w"; 558 } 559 if (remote) { 560 if (command("%s %s", cmd, remote) != PRELIM) { 561 (void)signal(SIGINT, oldintr); 562 (void)signal(SIGINFO, oldinti); 563 progress = oprogress; 564 if (oldintp) 565 (void)signal(SIGPIPE, oldintp); 566 if (closefunc != NULL) 567 (*closefunc)(fin); 568 return; 569 } 570 } else 571 if (command("%s", cmd) != PRELIM) { 572 (void)signal(SIGINT, oldintr); 573 (void)signal(SIGINFO, oldinti); 574 progress = oprogress; 575 if (oldintp) 576 (void)signal(SIGPIPE, oldintp); 577 if (closefunc != NULL) 578 (*closefunc)(fin); 579 return; 580 } 581 dout = dataconn(lmode); 582 if (dout == NULL) 583 goto abort; 584 progressmeter(-1); 585 oldintp = signal(SIGPIPE, SIG_IGN); 586 switch (curtype) { 587 588 case TYPE_I: 589 case TYPE_L: 590 errno = d = 0; 591 while ((c = read(fileno(fin), buf, sizeof(buf))) > 0) { 592 bytes += c; 593 for (bufp = buf; c > 0; c -= d, bufp += d) 594 if ((d = write(fileno(dout), bufp, c)) <= 0) 595 break; 596 if (hash && (!progress || filesize < 0) ) { 597 while (bytes >= hashbytes) { 598 (void)putchar('#'); 599 hashbytes += mark; 600 } 601 (void)fflush(stdout); 602 } 603 } 604 if (hash && (!progress || filesize < 0) && bytes > 0) { 605 if (bytes < mark) 606 (void)putchar('#'); 607 (void)putchar('\n'); 608 (void)fflush(stdout); 609 } 610 if (c < 0) 611 warn("local: %s", local); 612 if (d < 0) { 613 if (errno != EPIPE) 614 warn("netout"); 615 bytes = -1; 616 } 617 break; 618 619 case TYPE_A: 620 while ((c = getc(fin)) != EOF) { 621 if (c == '\n') { 622 while (hash && (!progress || filesize < 0) && 623 (bytes >= hashbytes)) { 624 (void)putchar('#'); 625 (void)fflush(stdout); 626 hashbytes += mark; 627 } 628 if (ferror(dout)) 629 break; 630 (void)putc('\r', dout); 631 bytes++; 632 } 633 (void)putc(c, dout); 634 bytes++; 635 #if 0 /* this violates RFC */ 636 if (c == '\r') { 637 (void)putc('\0', dout); 638 bytes++; 639 } 640 #endif 641 } 642 if (hash && (!progress || filesize < 0)) { 643 if (bytes < hashbytes) 644 (void)putchar('#'); 645 (void)putchar('\n'); 646 (void)fflush(stdout); 647 } 648 if (ferror(fin)) 649 warn("local: %s", local); 650 if (ferror(dout)) { 651 if (errno != EPIPE) 652 warn("netout"); 653 bytes = -1; 654 } 655 break; 656 } 657 progressmeter(1); 658 progress = oprogress; 659 if (closefunc != NULL) 660 (*closefunc)(fin); 661 (void)fclose(dout); 662 (void)getreply(0); 663 (void)signal(SIGINT, oldintr); 664 (void)signal(SIGINFO, oldinti); 665 if (oldintp) 666 (void)signal(SIGPIPE, oldintp); 667 if (bytes > 0) 668 ptransfer(0); 669 return; 670 abort: 671 (void)signal(SIGINT, oldintr); 672 (void)signal(SIGINFO, oldinti); 673 progress = oprogress; 674 if (oldintp) 675 (void)signal(SIGPIPE, oldintp); 676 if (!cpend) { 677 code = -1; 678 return; 679 } 680 if (data >= 0) { 681 (void)close(data); 682 data = -1; 683 } 684 if (dout) 685 (void)fclose(dout); 686 (void)getreply(0); 687 code = -1; 688 if (closefunc != NULL && fin != NULL) 689 (*closefunc)(fin); 690 if (bytes > 0) 691 ptransfer(0); 692 } 693 694 jmp_buf recvabort; 695 696 void 697 abortrecv(notused) 698 int notused; 699 { 700 701 alarmtimer(0); 702 mflag = 0; 703 abrtflag = 0; 704 puts("\nreceive aborted\nwaiting for remote to finish abort."); 705 (void)fflush(stdout); 706 longjmp(recvabort, 1); 707 } 708 709 void 710 recvrequest(cmd, local, remote, lmode, printnames, ignorespecial) 711 const char *cmd, *local, *remote, *lmode; 712 int printnames, ignorespecial; 713 { 714 FILE *fout, *din; 715 int (*closefunc) __P((FILE *)); 716 sig_t oldinti, oldintr, oldintp; 717 int c, d; 718 volatile int is_retr, tcrflag, bare_lfs; 719 static size_t bufsize; 720 static char *buf; 721 volatile off_t hashbytes; 722 struct stat st; 723 time_t mtime; 724 struct timeval tval[2]; 725 int oprogress; 726 int opreserve; 727 728 #ifdef __GNUC__ /* XXX: to shut up gcc warnings */ 729 (void)&local; 730 (void)&fout; 731 (void)&din; 732 (void)&closefunc; 733 (void)&oldinti; 734 (void)&oldintr; 735 (void)&oldintp; 736 #endif 737 738 fout = NULL; 739 din = NULL; 740 oldinti = NULL; 741 hashbytes = mark; 742 direction = "received"; 743 bytes = 0; 744 bare_lfs = 0; 745 filesize = -1; 746 oprogress = progress; 747 opreserve = preserve; 748 is_retr = strcmp(cmd, "RETR") == 0; 749 if (is_retr && verbose && printnames) { 750 if (local && (ignorespecial || *local != '-')) 751 printf("local: %s ", local); 752 if (remote) 753 printf("remote: %s\n", remote); 754 } 755 if (proxy && is_retr) { 756 proxtrans(cmd, local, remote); 757 return; 758 } 759 closefunc = NULL; 760 oldintr = NULL; 761 oldintp = NULL; 762 tcrflag = !crflag && is_retr; 763 if (setjmp(recvabort)) { 764 while (cpend) { 765 (void)getreply(0); 766 } 767 if (data >= 0) { 768 (void)close(data); 769 data = -1; 770 } 771 if (oldintr) 772 (void)signal(SIGINT, oldintr); 773 if (oldinti) 774 (void)signal(SIGINFO, oldinti); 775 progress = oprogress; 776 preserve = opreserve; 777 code = -1; 778 return; 779 } 780 oldintr = signal(SIGINT, abortrecv); 781 oldinti = signal(SIGINFO, psummary); 782 if (ignorespecial || (strcmp(local, "-") && *local != '|')) { 783 if (access(local, W_OK) < 0) { 784 char *dir = strrchr(local, '/'); 785 786 if (errno != ENOENT && errno != EACCES) { 787 warn("local: %s", local); 788 (void)signal(SIGINT, oldintr); 789 (void)signal(SIGINFO, oldinti); 790 code = -1; 791 return; 792 } 793 if (dir != NULL) 794 *dir = 0; 795 d = access(dir == local ? "/" : dir ? local : ".", W_OK); 796 if (dir != NULL) 797 *dir = '/'; 798 if (d < 0) { 799 warn("local: %s", local); 800 (void)signal(SIGINT, oldintr); 801 (void)signal(SIGINFO, oldinti); 802 code = -1; 803 return; 804 } 805 if (!runique && errno == EACCES && 806 chmod(local, 0600) < 0) { 807 warn("local: %s", local); 808 (void)signal(SIGINT, oldintr); 809 (void)signal(SIGINFO, oldinti); 810 code = -1; 811 return; 812 } 813 if (runique && errno == EACCES && 814 (local = gunique(local)) == NULL) { 815 (void)signal(SIGINT, oldintr); 816 (void)signal(SIGINFO, oldinti); 817 code = -1; 818 return; 819 } 820 } 821 else if (runique && (local = gunique(local)) == NULL) { 822 (void)signal(SIGINT, oldintr); 823 (void)signal(SIGINFO, oldinti); 824 code = -1; 825 return; 826 } 827 } 828 if (!is_retr) { 829 if (curtype != TYPE_A) 830 changetype(TYPE_A, 0); 831 } else { 832 if (curtype != type) 833 changetype(type, 0); 834 filesize = remotesize(remote, 0); 835 } 836 if (initconn()) { 837 (void)signal(SIGINT, oldintr); 838 (void)signal(SIGINFO, oldinti); 839 code = -1; 840 return; 841 } 842 if (setjmp(recvabort)) 843 goto abort; 844 if (is_retr && restart_point && 845 command("REST %ld", (long) restart_point) != CONTINUE) 846 return; 847 if (remote) { 848 if (command("%s %s", cmd, remote) != PRELIM) { 849 (void)signal(SIGINT, oldintr); 850 (void)signal(SIGINFO, oldinti); 851 return; 852 } 853 } else { 854 if (command("%s", cmd) != PRELIM) { 855 (void)signal(SIGINT, oldintr); 856 (void)signal(SIGINFO, oldinti); 857 return; 858 } 859 } 860 din = dataconn("r"); 861 if (din == NULL) 862 goto abort; 863 if (!ignorespecial && strcmp(local, "-") == 0) { 864 fout = stdout; 865 progress = 0; 866 preserve = 0; 867 } else if (!ignorespecial && *local == '|') { 868 oldintp = signal(SIGPIPE, SIG_IGN); 869 fout = popen(local + 1, "w"); 870 if (fout == NULL) { 871 warn("%s", local+1); 872 goto abort; 873 } 874 progress = 0; 875 preserve = 0; 876 closefunc = pclose; 877 } else { 878 fout = fopen(local, lmode); 879 if (fout == NULL) { 880 warn("local: %s", local); 881 goto abort; 882 } 883 closefunc = fclose; 884 } 885 if (fstat(fileno(fout), &st) < 0 || st.st_blksize == 0) 886 st.st_blksize = BUFSIZ; 887 if (st.st_blksize > bufsize) { 888 if (buf) 889 (void)free(buf); 890 buf = malloc((unsigned)st.st_blksize); 891 if (buf == NULL) { 892 warn("malloc"); 893 bufsize = 0; 894 goto abort; 895 } 896 bufsize = st.st_blksize; 897 } 898 if ((st.st_mode & S_IFMT) != S_IFREG) { 899 progress = 0; 900 preserve = 0; 901 } 902 progressmeter(-1); 903 switch (curtype) { 904 905 case TYPE_I: 906 case TYPE_L: 907 if (restart_point && 908 lseek(fileno(fout), restart_point, SEEK_SET) < 0) { 909 warn("local: %s", local); 910 progress = oprogress; 911 preserve = opreserve; 912 if (closefunc != NULL) 913 (*closefunc)(fout); 914 return; 915 } 916 errno = d = 0; 917 while ((c = read(fileno(din), buf, bufsize)) > 0) { 918 if ((d = write(fileno(fout), buf, c)) != c) 919 break; 920 bytes += c; 921 if (hash && (!progress || filesize < 0)) { 922 while (bytes >= hashbytes) { 923 (void)putchar('#'); 924 hashbytes += mark; 925 } 926 (void)fflush(stdout); 927 } 928 } 929 if (hash && (!progress || filesize < 0) && bytes > 0) { 930 if (bytes < mark) 931 (void)putchar('#'); 932 (void)putchar('\n'); 933 (void)fflush(stdout); 934 } 935 if (c < 0) { 936 if (errno != EPIPE) 937 warn("netin"); 938 bytes = -1; 939 } 940 if (d < c) { 941 if (d < 0) 942 warn("local: %s", local); 943 else 944 warnx("%s: short write", local); 945 } 946 break; 947 948 case TYPE_A: 949 if (restart_point) { 950 int i, n, ch; 951 952 if (fseek(fout, 0L, SEEK_SET) < 0) 953 goto done; 954 n = restart_point; 955 for (i = 0; i++ < n;) { 956 if ((ch = getc(fout)) == EOF) 957 goto done; 958 if (ch == '\n') 959 i++; 960 } 961 if (fseek(fout, 0L, SEEK_CUR) < 0) { 962 done: 963 warn("local: %s", local); 964 progress = oprogress; 965 preserve = opreserve; 966 if (closefunc != NULL) 967 (*closefunc)(fout); 968 return; 969 } 970 } 971 while ((c = getc(din)) != EOF) { 972 if (c == '\n') 973 bare_lfs++; 974 while (c == '\r') { 975 while (hash && (!progress || filesize < 0) && 976 (bytes >= hashbytes)) { 977 (void)putchar('#'); 978 (void)fflush(stdout); 979 hashbytes += mark; 980 } 981 bytes++; 982 if ((c = getc(din)) != '\n' || tcrflag) { 983 if (ferror(fout)) 984 goto break2; 985 (void)putc('\r', fout); 986 if (c == '\0') { 987 bytes++; 988 goto contin2; 989 } 990 if (c == EOF) 991 goto contin2; 992 } 993 } 994 (void)putc(c, fout); 995 bytes++; 996 contin2: ; 997 } 998 break2: 999 if (bare_lfs) { 1000 printf( 1001 "WARNING! %d bare linefeeds received in ASCII mode.\n", bare_lfs); 1002 puts("File may not have transferred correctly."); 1003 } 1004 if (hash && (!progress || filesize < 0)) { 1005 if (bytes < hashbytes) 1006 (void)putchar('#'); 1007 (void)putchar('\n'); 1008 (void)fflush(stdout); 1009 } 1010 if (ferror(din)) { 1011 if (errno != EPIPE) 1012 warn("netin"); 1013 bytes = -1; 1014 } 1015 if (ferror(fout)) 1016 warn("local: %s", local); 1017 break; 1018 } 1019 progressmeter(1); 1020 progress = oprogress; 1021 preserve = opreserve; 1022 if (closefunc != NULL) 1023 (*closefunc)(fout); 1024 (void)signal(SIGINT, oldintr); 1025 (void)signal(SIGINFO, oldinti); 1026 if (oldintp) 1027 (void)signal(SIGPIPE, oldintp); 1028 (void)fclose(din); 1029 (void)getreply(0); 1030 if (bytes >= 0 && is_retr) { 1031 if (bytes > 0) 1032 ptransfer(0); 1033 if (preserve && (closefunc == fclose)) { 1034 mtime = remotemodtime(remote, 0); 1035 if (mtime != -1) { 1036 (void)gettimeofday(&tval[0], 1037 (struct timezone *)0); 1038 tval[1].tv_sec = mtime; 1039 tval[1].tv_usec = 0; 1040 if (utimes(local, tval) == -1) { 1041 printf( 1042 "Can't change modification time on %s to %s", 1043 local, asctime(localtime(&mtime))); 1044 } 1045 } 1046 } 1047 } 1048 return; 1049 1050 abort: 1051 1052 /* abort using RFC959 recommended IP,SYNC sequence */ 1053 1054 progress = oprogress; 1055 preserve = opreserve; 1056 if (oldintp) 1057 (void)signal(SIGPIPE, oldintp); 1058 (void)signal(SIGINT, SIG_IGN); 1059 if (!cpend) { 1060 code = -1; 1061 (void)signal(SIGINT, oldintr); 1062 (void)signal(SIGINFO, oldinti); 1063 return; 1064 } 1065 1066 abort_remote(din); 1067 code = -1; 1068 if (data >= 0) { 1069 (void)close(data); 1070 data = -1; 1071 } 1072 if (closefunc != NULL && fout != NULL) 1073 (*closefunc)(fout); 1074 if (din) 1075 (void)fclose(din); 1076 if (bytes > 0) 1077 ptransfer(0); 1078 (void)signal(SIGINT, oldintr); 1079 (void)signal(SIGINFO, oldinti); 1080 } 1081 1082 /* 1083 * Need to start a listen on the data channel before we send the command, 1084 * otherwise the server's connect may fail. 1085 */ 1086 int 1087 initconn() 1088 { 1089 char *p, *a; 1090 int result, len, tmpno = 0; 1091 int on = 1; 1092 int a0, a1, a2, a3, p0, p1; 1093 1094 if (passivemode) { 1095 data = socket(AF_INET, SOCK_STREAM, 0); 1096 if (data < 0) { 1097 warn("socket"); 1098 return (1); 1099 } 1100 if ((options & SO_DEBUG) && 1101 setsockopt(data, SOL_SOCKET, SO_DEBUG, (char *)&on, 1102 sizeof(on)) < 0) 1103 warn("setsockopt (ignored)"); 1104 if (command("PASV") != COMPLETE) { 1105 puts("Passive mode refused."); 1106 goto bad; 1107 } 1108 1109 /* 1110 * What we've got at this point is a string of comma 1111 * separated one-byte unsigned integer values. 1112 * The first four are the an IP address. The fifth is 1113 * the MSB of the port number, the sixth is the LSB. 1114 * From that we'll prepare a sockaddr_in. 1115 */ 1116 1117 if (sscanf(pasv, "%d,%d,%d,%d,%d,%d", 1118 &a0, &a1, &a2, &a3, &p0, &p1) != 6) { 1119 puts( 1120 "Passive mode address scan failure. Shouldn't happen!"); 1121 goto bad; 1122 } 1123 1124 memset(&data_addr, 0, sizeof(data_addr)); 1125 data_addr.sin_family = AF_INET; 1126 a = (char *)&data_addr.sin_addr.s_addr; 1127 a[0] = a0 & 0xff; 1128 a[1] = a1 & 0xff; 1129 a[2] = a2 & 0xff; 1130 a[3] = a3 & 0xff; 1131 p = (char *)&data_addr.sin_port; 1132 p[0] = p0 & 0xff; 1133 p[1] = p1 & 0xff; 1134 1135 if (connect(data, (struct sockaddr *)&data_addr, 1136 sizeof(data_addr)) < 0) { 1137 warn("connect"); 1138 goto bad; 1139 } 1140 #ifdef IP_TOS 1141 on = IPTOS_THROUGHPUT; 1142 if (setsockopt(data, IPPROTO_IP, IP_TOS, (char *)&on, 1143 sizeof(int)) < 0) 1144 warn("setsockopt TOS (ignored)"); 1145 #endif 1146 return (0); 1147 } 1148 1149 noport: 1150 data_addr = myctladdr; 1151 if (sendport) 1152 data_addr.sin_port = 0; /* let system pick one */ 1153 if (data != -1) 1154 (void)close(data); 1155 data = socket(AF_INET, SOCK_STREAM, 0); 1156 if (data < 0) { 1157 warn("socket"); 1158 if (tmpno) 1159 sendport = 1; 1160 return (1); 1161 } 1162 if (!sendport) 1163 if (setsockopt(data, SOL_SOCKET, SO_REUSEADDR, (char *)&on, 1164 sizeof(on)) < 0) { 1165 warn("setsockopt (reuse address)"); 1166 goto bad; 1167 } 1168 if (bind(data, (struct sockaddr *)&data_addr, sizeof(data_addr)) < 0) { 1169 warn("bind"); 1170 goto bad; 1171 } 1172 if (options & SO_DEBUG && 1173 setsockopt(data, SOL_SOCKET, SO_DEBUG, (char *)&on, 1174 sizeof(on)) < 0) 1175 warn("setsockopt (ignored)"); 1176 len = sizeof(data_addr); 1177 if (getsockname(data, (struct sockaddr *)&data_addr, &len) < 0) { 1178 warn("getsockname"); 1179 goto bad; 1180 } 1181 if (listen(data, 1) < 0) 1182 warn("listen"); 1183 if (sendport) { 1184 a = (char *)&data_addr.sin_addr; 1185 p = (char *)&data_addr.sin_port; 1186 #define UC(b) (((int)b)&0xff) 1187 result = 1188 command("PORT %d,%d,%d,%d,%d,%d", 1189 UC(a[0]), UC(a[1]), UC(a[2]), UC(a[3]), 1190 UC(p[0]), UC(p[1])); 1191 if (result == ERROR && sendport == -1) { 1192 sendport = 0; 1193 tmpno = 1; 1194 goto noport; 1195 } 1196 return (result != COMPLETE); 1197 } 1198 if (tmpno) 1199 sendport = 1; 1200 #ifdef IP_TOS 1201 on = IPTOS_THROUGHPUT; 1202 if (setsockopt(data, IPPROTO_IP, IP_TOS, (char *)&on, sizeof(int)) < 0) 1203 warn("setsockopt TOS (ignored)"); 1204 #endif 1205 return (0); 1206 bad: 1207 (void)close(data), data = -1; 1208 if (tmpno) 1209 sendport = 1; 1210 return (1); 1211 } 1212 1213 FILE * 1214 dataconn(lmode) 1215 const char *lmode; 1216 { 1217 struct sockaddr_in from; 1218 int s, fromlen, tos; 1219 1220 fromlen = sizeof(from); 1221 1222 if (passivemode) 1223 return (fdopen(data, lmode)); 1224 1225 s = accept(data, (struct sockaddr *) &from, &fromlen); 1226 if (s < 0) { 1227 warn("accept"); 1228 (void)close(data), data = -1; 1229 return (NULL); 1230 } 1231 (void)close(data); 1232 data = s; 1233 #ifdef IP_TOS 1234 tos = IPTOS_THROUGHPUT; 1235 if (setsockopt(s, IPPROTO_IP, IP_TOS, (char *)&tos, sizeof(int)) < 0) 1236 warn("setsockopt TOS (ignored)"); 1237 #endif 1238 return (fdopen(data, lmode)); 1239 } 1240 1241 void 1242 psummary(notused) 1243 int notused; 1244 { 1245 1246 if (bytes > 0) 1247 ptransfer(1); 1248 } 1249 1250 void 1251 psabort(notused) 1252 int notused; 1253 { 1254 1255 alarmtimer(0); 1256 abrtflag++; 1257 } 1258 1259 void 1260 pswitch(flag) 1261 int flag; 1262 { 1263 sig_t oldintr; 1264 static struct comvars { 1265 int connect; 1266 char name[MAXHOSTNAMELEN]; 1267 struct sockaddr_in mctl; 1268 struct sockaddr_in hctl; 1269 FILE *in; 1270 FILE *out; 1271 int tpe; 1272 int curtpe; 1273 int cpnd; 1274 int sunqe; 1275 int runqe; 1276 int mcse; 1277 int ntflg; 1278 char nti[17]; 1279 char nto[17]; 1280 int mapflg; 1281 char mi[MAXPATHLEN]; 1282 char mo[MAXPATHLEN]; 1283 } proxstruct, tmpstruct; 1284 struct comvars *ip, *op; 1285 1286 abrtflag = 0; 1287 oldintr = signal(SIGINT, psabort); 1288 if (flag) { 1289 if (proxy) 1290 return; 1291 ip = &tmpstruct; 1292 op = &proxstruct; 1293 proxy++; 1294 } else { 1295 if (!proxy) 1296 return; 1297 ip = &proxstruct; 1298 op = &tmpstruct; 1299 proxy = 0; 1300 } 1301 ip->connect = connected; 1302 connected = op->connect; 1303 if (hostname) { 1304 (void)strncpy(ip->name, hostname, sizeof(ip->name) - 1); 1305 ip->name[sizeof(ip->name) - 1] = '\0'; 1306 } else 1307 ip->name[0] = '\0'; 1308 hostname = op->name; 1309 ip->hctl = hisctladdr; 1310 hisctladdr = op->hctl; 1311 ip->mctl = myctladdr; 1312 myctladdr = op->mctl; 1313 ip->in = cin; 1314 cin = op->in; 1315 ip->out = cout; 1316 cout = op->out; 1317 ip->tpe = type; 1318 type = op->tpe; 1319 ip->curtpe = curtype; 1320 curtype = op->curtpe; 1321 ip->cpnd = cpend; 1322 cpend = op->cpnd; 1323 ip->sunqe = sunique; 1324 sunique = op->sunqe; 1325 ip->runqe = runique; 1326 runique = op->runqe; 1327 ip->mcse = mcase; 1328 mcase = op->mcse; 1329 ip->ntflg = ntflag; 1330 ntflag = op->ntflg; 1331 (void)strncpy(ip->nti, ntin, sizeof(ip->nti) - 1); 1332 (ip->nti)[sizeof(ip->nti) - 1] = '\0'; 1333 (void)strcpy(ntin, op->nti); 1334 (void)strncpy(ip->nto, ntout, sizeof(ip->nto) - 1); 1335 (ip->nto)[sizeof(ip->nto) - 1] = '\0'; 1336 (void)strcpy(ntout, op->nto); 1337 ip->mapflg = mapflag; 1338 mapflag = op->mapflg; 1339 (void)strncpy(ip->mi, mapin, sizeof(ip->mi) - 1); 1340 (ip->mi)[sizeof(ip->mi) - 1] = '\0'; 1341 (void)strcpy(mapin, op->mi); 1342 (void)strncpy(ip->mo, mapout, sizeof(ip->mo) - 1); 1343 (ip->mo)[sizeof(ip->mo) - 1] = '\0'; 1344 (void)strcpy(mapout, op->mo); 1345 (void)signal(SIGINT, oldintr); 1346 if (abrtflag) { 1347 abrtflag = 0; 1348 (*oldintr)(SIGINT); 1349 } 1350 } 1351 1352 void 1353 abortpt(notused) 1354 int notused; 1355 { 1356 1357 alarmtimer(0); 1358 putchar('\n'); 1359 (void)fflush(stdout); 1360 ptabflg++; 1361 mflag = 0; 1362 abrtflag = 0; 1363 longjmp(ptabort, 1); 1364 } 1365 1366 void 1367 proxtrans(cmd, local, remote) 1368 const char *cmd, *local, *remote; 1369 { 1370 sig_t oldintr; 1371 int prox_type, nfnd; 1372 volatile int secndflag; 1373 char *cmd2; 1374 struct fd_set mask; 1375 1376 #ifdef __GNUC__ /* XXX: to shut up gcc warnings */ 1377 (void)&oldintr; 1378 (void)&cmd2; 1379 #endif 1380 1381 oldintr = NULL; 1382 secndflag = 0; 1383 if (strcmp(cmd, "RETR")) 1384 cmd2 = "RETR"; 1385 else 1386 cmd2 = runique ? "STOU" : "STOR"; 1387 if ((prox_type = type) == 0) { 1388 if (unix_server && unix_proxy) 1389 prox_type = TYPE_I; 1390 else 1391 prox_type = TYPE_A; 1392 } 1393 if (curtype != prox_type) 1394 changetype(prox_type, 1); 1395 if (command("PASV") != COMPLETE) { 1396 puts("proxy server does not support third party transfers."); 1397 return; 1398 } 1399 pswitch(0); 1400 if (!connected) { 1401 puts("No primary connection."); 1402 pswitch(1); 1403 code = -1; 1404 return; 1405 } 1406 if (curtype != prox_type) 1407 changetype(prox_type, 1); 1408 if (command("PORT %s", pasv) != COMPLETE) { 1409 pswitch(1); 1410 return; 1411 } 1412 if (setjmp(ptabort)) 1413 goto abort; 1414 oldintr = signal(SIGINT, abortpt); 1415 if (command("%s %s", cmd, remote) != PRELIM) { 1416 (void)signal(SIGINT, oldintr); 1417 pswitch(1); 1418 return; 1419 } 1420 sleep(2); 1421 pswitch(1); 1422 secndflag++; 1423 if (command("%s %s", cmd2, local) != PRELIM) 1424 goto abort; 1425 ptflag++; 1426 (void)getreply(0); 1427 pswitch(0); 1428 (void)getreply(0); 1429 (void)signal(SIGINT, oldintr); 1430 pswitch(1); 1431 ptflag = 0; 1432 printf("local: %s remote: %s\n", local, remote); 1433 return; 1434 abort: 1435 (void)signal(SIGINT, SIG_IGN); 1436 ptflag = 0; 1437 if (strcmp(cmd, "RETR") && !proxy) 1438 pswitch(1); 1439 else if (!strcmp(cmd, "RETR") && proxy) 1440 pswitch(0); 1441 if (!cpend && !secndflag) { /* only here if cmd = "STOR" (proxy=1) */ 1442 if (command("%s %s", cmd2, local) != PRELIM) { 1443 pswitch(0); 1444 if (cpend) 1445 abort_remote((FILE *) NULL); 1446 } 1447 pswitch(1); 1448 if (ptabflg) 1449 code = -1; 1450 (void)signal(SIGINT, oldintr); 1451 return; 1452 } 1453 if (cpend) 1454 abort_remote((FILE *) NULL); 1455 pswitch(!proxy); 1456 if (!cpend && !secndflag) { /* only if cmd = "RETR" (proxy=1) */ 1457 if (command("%s %s", cmd2, local) != PRELIM) { 1458 pswitch(0); 1459 if (cpend) 1460 abort_remote((FILE *) NULL); 1461 pswitch(1); 1462 if (ptabflg) 1463 code = -1; 1464 (void)signal(SIGINT, oldintr); 1465 return; 1466 } 1467 } 1468 if (cpend) 1469 abort_remote((FILE *) NULL); 1470 pswitch(!proxy); 1471 if (cpend) { 1472 FD_ZERO(&mask); 1473 FD_SET(fileno(cin), &mask); 1474 if ((nfnd = empty(&mask, 10)) <= 0) { 1475 if (nfnd < 0) { 1476 warn("abort"); 1477 } 1478 if (ptabflg) 1479 code = -1; 1480 lostpeer(); 1481 } 1482 (void)getreply(0); 1483 (void)getreply(0); 1484 } 1485 if (proxy) 1486 pswitch(0); 1487 pswitch(1); 1488 if (ptabflg) 1489 code = -1; 1490 (void)signal(SIGINT, oldintr); 1491 } 1492 1493 void 1494 reset(argc, argv) 1495 int argc; 1496 char *argv[]; 1497 { 1498 struct fd_set mask; 1499 int nfnd = 1; 1500 1501 FD_ZERO(&mask); 1502 while (nfnd > 0) { 1503 FD_SET(fileno(cin), &mask); 1504 if ((nfnd = empty(&mask, 0)) < 0) { 1505 warn("reset"); 1506 code = -1; 1507 lostpeer(); 1508 } 1509 else if (nfnd) { 1510 (void)getreply(0); 1511 } 1512 } 1513 } 1514 1515 char * 1516 gunique(local) 1517 const char *local; 1518 { 1519 static char new[MAXPATHLEN]; 1520 char *cp = strrchr(local, '/'); 1521 int d, count=0; 1522 char ext = '1'; 1523 1524 if (cp) 1525 *cp = '\0'; 1526 d = access(cp == local ? "/" : cp ? local : ".", W_OK); 1527 if (cp) 1528 *cp = '/'; 1529 if (d < 0) { 1530 warn("local: %s", local); 1531 return ((char *) 0); 1532 } 1533 (void)strcpy(new, local); 1534 cp = new + strlen(new); 1535 *cp++ = '.'; 1536 while (!d) { 1537 if (++count == 100) { 1538 puts("runique: can't find unique file name."); 1539 return ((char *) 0); 1540 } 1541 *cp++ = ext; 1542 *cp = '\0'; 1543 if (ext == '9') 1544 ext = '0'; 1545 else 1546 ext++; 1547 if ((d = access(new, F_OK)) < 0) 1548 break; 1549 if (ext != '0') 1550 cp--; 1551 else if (*(cp - 2) == '.') 1552 *(cp - 1) = '1'; 1553 else { 1554 *(cp - 2) = *(cp - 2) + 1; 1555 cp--; 1556 } 1557 } 1558 return (new); 1559 } 1560 1561 void 1562 abort_remote(din) 1563 FILE *din; 1564 { 1565 char buf[BUFSIZ]; 1566 int nfnd; 1567 struct fd_set mask; 1568 1569 if (cout == NULL) { 1570 warnx("Lost control connection for abort."); 1571 if (ptabflg) 1572 code = -1; 1573 lostpeer(); 1574 return; 1575 } 1576 /* 1577 * send IAC in urgent mode instead of DM because 4.3BSD places oob mark 1578 * after urgent byte rather than before as is protocol now 1579 */ 1580 sprintf(buf, "%c%c%c", IAC, IP, IAC); 1581 if (send(fileno(cout), buf, 3, MSG_OOB) != 3) 1582 warn("abort"); 1583 fprintf(cout, "%cABOR\r\n", DM); 1584 (void)fflush(cout); 1585 FD_ZERO(&mask); 1586 FD_SET(fileno(cin), &mask); 1587 if (din) { 1588 FD_SET(fileno(din), &mask); 1589 } 1590 if ((nfnd = empty(&mask, 10)) <= 0) { 1591 if (nfnd < 0) { 1592 warn("abort"); 1593 } 1594 if (ptabflg) 1595 code = -1; 1596 lostpeer(); 1597 } 1598 if (din && FD_ISSET(fileno(din), &mask)) { 1599 while (read(fileno(din), buf, BUFSIZ) > 0) 1600 /* LOOP */; 1601 } 1602 if (getreply(0) == ERROR && code == 552) { 1603 /* 552 needed for nic style abort */ 1604 (void)getreply(0); 1605 } 1606 (void)getreply(0); 1607 } 1608