1 /* $NetBSD: ftp.c,v 1.92 2000/02/28 10:12:27 lukem Exp $ */ 2 3 /*- 4 * Copyright (c) 1996-1999 The NetBSD Foundation, Inc. 5 * All rights reserved. 6 * 7 * This code is derived from software contributed to The NetBSD Foundation 8 * by Luke Mewburn. 9 * 10 * Redistribution and use in source and binary forms, with or without 11 * modification, are permitted provided that the following conditions 12 * are met: 13 * 1. Redistributions of source code must retain the above copyright 14 * notice, this list of conditions and the following disclaimer. 15 * 2. Redistributions in binary form must reproduce the above copyright 16 * notice, this list of conditions and the following disclaimer in the 17 * documentation and/or other materials provided with the distribution. 18 * 3. All advertising materials mentioning features or use of this software 19 * must display the following acknowledgement: 20 * This product includes software developed by the NetBSD 21 * Foundation, Inc. and its contributors. 22 * 4. Neither the name of The NetBSD Foundation nor the names of its 23 * contributors may be used to endorse or promote products derived 24 * from this software without specific prior written permission. 25 * 26 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 27 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 28 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 29 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 30 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 31 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 32 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 33 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 34 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 35 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 36 * POSSIBILITY OF SUCH DAMAGE. 37 */ 38 39 /* 40 * Copyright (c) 1985, 1989, 1993, 1994 41 * The Regents of the University of California. All rights reserved. 42 * 43 * Redistribution and use in source and binary forms, with or without 44 * modification, are permitted provided that the following conditions 45 * are met: 46 * 1. Redistributions of source code must retain the above copyright 47 * notice, this list of conditions and the following disclaimer. 48 * 2. Redistributions in binary form must reproduce the above copyright 49 * notice, this list of conditions and the following disclaimer in the 50 * documentation and/or other materials provided with the distribution. 51 * 3. All advertising materials mentioning features or use of this software 52 * must display the following acknowledgement: 53 * This product includes software developed by the University of 54 * California, Berkeley and its contributors. 55 * 4. Neither the name of the University nor the names of its contributors 56 * may be used to endorse or promote products derived from this software 57 * without specific prior written permission. 58 * 59 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 60 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 61 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 62 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 63 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 64 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 65 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 66 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 67 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 68 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 69 * SUCH DAMAGE. 70 */ 71 72 /* 73 * Copyright (C) 1997 and 1998 WIDE Project. 74 * All rights reserved. 75 * 76 * Redistribution and use in source and binary forms, with or without 77 * modification, are permitted provided that the following conditions 78 * are met: 79 * 1. Redistributions of source code must retain the above copyright 80 * notice, this list of conditions and the following disclaimer. 81 * 2. Redistributions in binary form must reproduce the above copyright 82 * notice, this list of conditions and the following disclaimer in the 83 * documentation and/or other materials provided with the distribution. 84 * 3. Neither the name of the project nor the names of its contributors 85 * may be used to endorse or promote products derived from this software 86 * without specific prior written permission. 87 * 88 * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND 89 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 90 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 91 * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE 92 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 93 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 94 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 95 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 96 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 97 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 98 * SUCH DAMAGE. 99 */ 100 101 #include <sys/cdefs.h> 102 #ifndef lint 103 #if 0 104 static char sccsid[] = "@(#)ftp.c 8.6 (Berkeley) 10/27/94"; 105 #else 106 __RCSID("$NetBSD: ftp.c,v 1.92 2000/02/28 10:12:27 lukem Exp $"); 107 #endif 108 #endif /* not lint */ 109 110 #include <sys/types.h> 111 #include <sys/stat.h> 112 #include <sys/socket.h> 113 #include <sys/time.h> 114 115 #include <netinet/in.h> 116 #include <netinet/in_systm.h> 117 #include <netinet/ip.h> 118 #include <arpa/inet.h> 119 #include <arpa/ftp.h> 120 #include <arpa/telnet.h> 121 122 #include <ctype.h> 123 #include <err.h> 124 #include <errno.h> 125 #include <netdb.h> 126 #include <stdio.h> 127 #include <stdlib.h> 128 #include <string.h> 129 #include <time.h> 130 #include <unistd.h> 131 #ifdef __STDC__ 132 #include <stdarg.h> 133 #else 134 #include <varargs.h> 135 #endif 136 #ifndef __USE_SELECT 137 #include <poll.h> 138 #endif 139 140 #include "ftp_var.h" 141 142 volatile int abrtflag = 0; 143 volatile int timeoutflag = 0; 144 sigjmp_buf ptabort; 145 int ptabflg; 146 int ptflag = 0; 147 char pasv[BUFSIZ]; /* passive port for proxy data connection */ 148 149 static int empty __P((FILE *, FILE *, int)); 150 151 union sockunion { 152 struct sockinet { 153 #ifdef BSD4_4 154 u_char si_len; 155 u_char si_family; 156 #else 157 u_short si_family; 158 #endif 159 u_short si_port; 160 #ifndef BSD4_4 161 u_char si_pad[ 162 #ifdef INET6 163 sizeof(struct sockaddr_in6) 164 #else 165 sizeof(struct sockaddr_in) 166 #endif 167 - sizeof(u_int)]; 168 u_char si_len; 169 #endif 170 } su_si; 171 struct sockaddr_in su_sin; 172 #ifdef INET6 173 struct sockaddr_in6 su_sin6; 174 #endif 175 }; 176 177 #define su_len su_si.si_len 178 #define su_family su_si.si_family 179 #define su_port su_si.si_port 180 181 union sockunion myctladdr, hisctladdr, data_addr; 182 183 char * 184 hookup(host, port) 185 char *host; 186 char *port; 187 { 188 int s = -1, len, error; 189 #if defined(NI_NUMERICHOST) && defined(INET6) 190 struct addrinfo hints, *res, *res0; 191 char hbuf[MAXHOSTNAMELEN]; 192 #else 193 struct hostent *hp = NULL; 194 char **ptr, *ep; 195 struct sockaddr_in sin; 196 long nport; 197 #endif 198 static char hostnamebuf[MAXHOSTNAMELEN]; 199 char *cause = "unknown"; 200 int family; 201 202 #if defined(NI_NUMERICHOST) && defined(INET6) 203 memset((char *)&hisctladdr, 0, sizeof (hisctladdr)); 204 memset(&hints, 0, sizeof(hints)); 205 hints.ai_flags = AI_CANONNAME; 206 hints.ai_family = AF_UNSPEC; 207 hints.ai_socktype = SOCK_STREAM; 208 hints.ai_protocol = 0; 209 error = getaddrinfo(host, port, &hints, &res0); 210 if (error) { 211 warnx(gai_strerror(error)); 212 code = -1; 213 return (0); 214 } 215 216 if (res0->ai_canonname) 217 (void)strlcpy(hostnamebuf, res0->ai_canonname, 218 sizeof(hostnamebuf)); 219 else 220 (void)strlcpy(hostnamebuf, host, sizeof(hostnamebuf)); 221 hostname = hostnamebuf; 222 223 for (res = res0; res; res = res->ai_next) { 224 #if 0 /*old behavior*/ 225 if (res != res0) /* not on the first address */ 226 #else 227 if (res0->ai_next) /* if we have multiple possibilities */ 228 #endif 229 { 230 getnameinfo(res->ai_addr, res->ai_addrlen, 231 hbuf, sizeof(hbuf), NULL, 0, NI_NUMERICHOST); 232 fprintf(ttyout, "Trying %s...\n", hbuf); 233 } 234 s = socket(res->ai_family, res->ai_socktype, res->ai_protocol); 235 if (s < 0) { 236 cause = "socket"; 237 continue; 238 } 239 while ((error = xconnect(s, res->ai_addr, res->ai_addrlen)) < 0 240 && errno == EINTR) { 241 ; 242 } 243 if (error) { 244 /* this "if" clause is to prevent print warning twice */ 245 if (res->ai_next) { 246 getnameinfo(res->ai_addr, res->ai_addrlen, 247 hbuf, sizeof(hbuf), NULL, 0, 248 NI_NUMERICHOST); 249 warn("connect to address %s", hbuf); 250 } 251 cause = "connect"; 252 close(s); 253 s = -1; 254 continue; 255 } 256 257 /* finally we got one */ 258 break; 259 } 260 if (s < 0) { 261 warn(cause); 262 code = -1; 263 freeaddrinfo(res0); 264 return 0; 265 } 266 memcpy(&hisctladdr, res->ai_addr, res->ai_addrlen); 267 len = res->ai_addrlen; 268 freeaddrinfo(res0); 269 res0 = res = NULL; 270 family = hisctladdr.su_family; 271 #else 272 memset(&sin, 0, sizeof(sin)); 273 sin.sin_family = AF_INET; 274 if ((hp = gethostbyname(host)) == NULL) { 275 warnx("%s: %s", host, hstrerror(h_errno)); 276 code = -1; 277 return 0; 278 } 279 280 nport = strtol(port, &ep, 10); 281 if (*ep != '\0' && ep == port) { 282 struct servent *svp; 283 284 svp = getservbyname(port, "tcp"); 285 if (svp == NULL) { 286 warnx("hookup: unknown port `%s'", port); 287 sin.sin_port = htons(FTP_PORT); 288 } else 289 sin.sin_port = svp->s_port; 290 } else if (nport < 1 || nport > MAX_IN_PORT_T || *ep != '\0') { 291 warnx("hookup: invalid port `%s'", port); 292 sin.sin_port = htons(FTP_PORT); 293 } else 294 sin.sin_port = htons(nport); 295 296 (void)strlcpy(hostnamebuf, hp->h_name, sizeof(hostnamebuf)); 297 hostname = hostnamebuf; 298 299 if (hp->h_length > sizeof(sin.sin_addr)) 300 hp->h_length = sizeof(sin.sin_addr); 301 302 for (ptr = hp->h_addr_list; *ptr; ptr++) { 303 memcpy(&sin.sin_addr, *ptr, (size_t)hp->h_length); 304 if (hp->h_addr_list[1]) 305 fprintf(ttyout, "Trying %s...\n", 306 inet_ntoa(sin.sin_addr)); 307 s = socket(AF_INET, SOCK_STREAM, 0); 308 if (s < 0) { 309 cause = "socket"; 310 continue; 311 } 312 while ((error = xconnect(s, (struct sockaddr *)&sin, 313 sizeof(sin))) < 0 && errno == EINTR) { 314 ; 315 } 316 if (error) { 317 /* this "if" clause is to prevent print warning twice */ 318 if (hp->h_addr_list[1]) { 319 warn("connect to address %s", 320 inet_ntoa(sin.sin_addr)); 321 } 322 cause = "connect"; 323 close(s); 324 s = -1; 325 continue; 326 } 327 328 /* finally we got one */ 329 break; 330 } 331 if (s < 0) { 332 warn(cause); 333 code = -1; 334 return 0; 335 } 336 memcpy(&hisctladdr, &sin, sizeof(sin)); 337 len = sizeof(sin); 338 if (hisctladdr.su_len == 0) 339 hisctladdr.su_len = len; 340 family = AF_INET; 341 #endif 342 343 if (getsockname(s, (struct sockaddr *)&myctladdr, &len) < 0) { 344 warn("getsockname"); 345 code = -1; 346 goto bad; 347 } 348 if (myctladdr.su_len == 0) 349 myctladdr.su_len = len; 350 351 #ifdef IPTOS_LOWDELAY 352 if (family == AF_INET) { 353 int tos = IPTOS_LOWDELAY; 354 if (setsockopt(s, IPPROTO_IP, IP_TOS, (char *)&tos, 355 sizeof(int)) < 0) 356 warn("setsockopt TOS (ignored)"); 357 } 358 #endif 359 cin = fdopen(s, "r"); 360 cout = fdopen(s, "w"); 361 if (cin == NULL || cout == NULL) { 362 warnx("fdopen failed."); 363 if (cin) 364 (void)fclose(cin); 365 if (cout) 366 (void)fclose(cout); 367 code = -1; 368 goto bad; 369 } 370 if (verbose) 371 fprintf(ttyout, "Connected to %s.\n", hostname); 372 if (getreply(0) > 2) { /* read startup message from server */ 373 if (cin) 374 (void)fclose(cin); 375 if (cout) 376 (void)fclose(cout); 377 code = -1; 378 goto bad; 379 } 380 { 381 int on = 1; 382 383 if (setsockopt(s, SOL_SOCKET, SO_OOBINLINE, (char *)&on, sizeof(on)) 384 < 0 && debug) { 385 warn("setsockopt"); 386 } 387 } 388 389 return (hostname); 390 bad: 391 (void)close(s); 392 return (NULL); 393 } 394 395 void 396 cmdabort(notused) 397 int notused; 398 { 399 int oerrno = errno; 400 401 alarmtimer(0); 402 if (fromatty) 403 write(fileno(ttyout), "\n", 1); 404 abrtflag++; 405 if (ptflag) 406 siglongjmp(ptabort, 1); 407 errno = oerrno; 408 } 409 410 void 411 cmdtimeout(notused) 412 int notused; 413 { 414 int oerrno = errno; 415 416 alarmtimer(0); 417 if (fromatty) 418 write(fileno(ttyout), "\n", 1); 419 timeoutflag++; 420 if (ptflag) 421 siglongjmp(ptabort, 1); 422 errno = oerrno; 423 } 424 425 426 /*VARARGS*/ 427 int 428 #ifdef __STDC__ 429 command(const char *fmt, ...) 430 #else 431 command(va_alist) 432 va_dcl 433 #endif 434 { 435 va_list ap; 436 int r; 437 sigfunc oldsigint; 438 #ifndef __STDC__ 439 const char *fmt; 440 #endif 441 442 if (debug) { 443 fputs("---> ", ttyout); 444 #ifdef __STDC__ 445 va_start(ap, fmt); 446 #else 447 va_start(ap); 448 fmt = va_arg(ap, const char *); 449 #endif 450 if (strncmp("PASS ", fmt, 5) == 0) 451 fputs("PASS XXXX", ttyout); 452 else if (strncmp("ACCT ", fmt, 5) == 0) 453 fputs("ACCT XXXX", ttyout); 454 else 455 vfprintf(ttyout, fmt, ap); 456 va_end(ap); 457 putc('\n', ttyout); 458 } 459 if (cout == NULL) { 460 warnx("No control connection for command."); 461 code = -1; 462 return (0); 463 } 464 465 abrtflag = 0; 466 467 oldsigint = xsignal(SIGINT, cmdabort); 468 469 #ifdef __STDC__ 470 va_start(ap, fmt); 471 #else 472 va_start(ap); 473 fmt = va_arg(ap, char *); 474 #endif 475 vfprintf(cout, fmt, ap); 476 va_end(ap); 477 fputs("\r\n", cout); 478 (void)fflush(cout); 479 cpend = 1; 480 r = getreply(!strcmp(fmt, "QUIT")); 481 if (abrtflag && oldsigint != SIG_IGN) 482 (*oldsigint)(SIGINT); 483 (void)xsignal(SIGINT, oldsigint); 484 return (r); 485 } 486 487 int 488 getreply(expecteof) 489 int expecteof; 490 { 491 char current_line[BUFSIZ]; /* last line of previous reply */ 492 int c, n, line; 493 int dig; 494 int originalcode = 0, continuation = 0; 495 sigfunc oldsigint, oldsigalrm; 496 int pflag = 0; 497 char *cp, *pt = pasv; 498 499 abrtflag = 0; 500 timeoutflag = 0; 501 502 oldsigint = xsignal(SIGINT, cmdabort); 503 oldsigalrm = xsignal(SIGALRM, cmdtimeout); 504 505 for (line = 0 ;; line++) { 506 dig = n = code = 0; 507 cp = current_line; 508 while (alarmtimer(60),((c = getc(cin)) != '\n')) { 509 if (c == IAC) { /* handle telnet commands */ 510 switch (c = getc(cin)) { 511 case WILL: 512 case WONT: 513 c = getc(cin); 514 fprintf(cout, "%c%c%c", IAC, DONT, c); 515 (void)fflush(cout); 516 break; 517 case DO: 518 case DONT: 519 c = getc(cin); 520 fprintf(cout, "%c%c%c", IAC, WONT, c); 521 (void)fflush(cout); 522 break; 523 default: 524 break; 525 } 526 continue; 527 } 528 dig++; 529 if (c == EOF) { 530 /* 531 * these will get trashed by pswitch() 532 * in lostpeer() 533 */ 534 int reply_timeoutflag = timeoutflag; 535 int reply_abrtflag = abrtflag; 536 537 alarmtimer(0); 538 if (expecteof && feof(cin)) { 539 (void)xsignal(SIGINT, oldsigint); 540 (void)xsignal(SIGALRM, oldsigalrm); 541 code = 221; 542 return (0); 543 } 544 cpend = 0; 545 lostpeer(0); 546 if (verbose) { 547 if (reply_timeoutflag) 548 fputs( 549 "421 Service not available, remote server timed out. Connection closed\n", 550 ttyout); 551 else if (reply_abrtflag) 552 fputs( 553 "421 Service not available, user interrupt. Connection closed.\n", 554 ttyout); 555 else 556 fputs( 557 "421 Service not available, remote server has closed connection.\n", 558 ttyout); 559 (void)fflush(ttyout); 560 } 561 code = 421; 562 (void)xsignal(SIGINT, oldsigint); 563 (void)xsignal(SIGALRM, oldsigalrm); 564 return (4); 565 } 566 if (c != '\r' && (verbose > 0 || 567 ((verbose > -1 && n == '5' && dig > 4) && 568 (((!n && c < '5') || (n && n < '5')) 569 || !retry_connect)))) { 570 if (proxflag && 571 (dig == 1 || (dig == 5 && verbose == 0))) 572 fprintf(ttyout, "%s:", hostname); 573 (void)putc(c, ttyout); 574 } 575 if (dig < 4 && isdigit(c)) 576 code = code * 10 + (c - '0'); 577 if (!pflag && (code == 227 || code == 228)) 578 pflag = 1; 579 else if (!pflag && code == 229) 580 pflag = 100; 581 if (dig > 4 && pflag == 1 && isdigit(c)) 582 pflag = 2; 583 if (pflag == 2) { 584 if (c != '\r' && c != ')') 585 *pt++ = c; 586 else { 587 *pt = '\0'; 588 pflag = 3; 589 } 590 } 591 if (pflag == 100 && c == '(') 592 pflag = 2; 593 if (dig == 4 && c == '-') { 594 if (continuation) 595 code = 0; 596 continuation++; 597 } 598 if (n == 0) 599 n = c; 600 if (cp < ¤t_line[sizeof(current_line) - 1]) 601 *cp++ = c; 602 } 603 if (verbose > 0 || ((verbose > -1 && n == '5') && 604 (n < '5' || !retry_connect))) { 605 (void)putc(c, ttyout); 606 (void)fflush (ttyout); 607 } 608 if (line == 0) { 609 size_t len = cp - current_line; 610 611 if (len > sizeof(reply_string)) 612 len = sizeof(reply_string); 613 614 (void)strlcpy(reply_string, current_line, len); 615 } 616 if (continuation && code != originalcode) { 617 if (originalcode == 0) 618 originalcode = code; 619 continue; 620 } 621 *cp = '\0'; 622 if (n != '1') 623 cpend = 0; 624 alarmtimer(0); 625 (void)xsignal(SIGINT, oldsigint); 626 (void)xsignal(SIGALRM, oldsigalrm); 627 if (code == 421 || originalcode == 421) 628 lostpeer(0); 629 if (abrtflag && oldsigint != cmdabort && oldsigint != SIG_IGN) 630 (*oldsigint)(SIGINT); 631 if (timeoutflag && oldsigalrm != cmdtimeout && 632 oldsigalrm != SIG_IGN) 633 (*oldsigalrm)(SIGINT); 634 return (n - '0'); 635 } 636 } 637 638 static int 639 empty(cin, din, sec) 640 FILE *cin; 641 FILE *din; 642 int sec; 643 { 644 int nr; 645 int nfd = 0; 646 647 #ifdef __USE_SELECT 648 struct timeval t; 649 fd_set rmask; 650 651 FD_ZERO(&rmask); 652 if (cin) { 653 if (nfd < fileno(cin)) 654 nfd = fileno(cin); 655 FD_SET(fileno(cin), &rmask); 656 } 657 if (din) { 658 if (nfd < fileno(din)) 659 nfd = fileno(din); 660 FD_SET(fileno(din), &rmask); 661 } 662 663 t.tv_sec = (long) sec; 664 t.tv_usec = 0; 665 if ((nr = select(nfd, &rmask, NULL, NULL, &t)) <= 0) 666 return nr; 667 668 nr = 0; 669 if (cin) 670 nr |= FD_ISSET(fileno(cin), &rmask) ? 1 : 0; 671 if (din) 672 nr |= FD_ISSET(fileno(din), &rmask) ? 2 : 0; 673 674 #else 675 struct pollfd pfd[2]; 676 677 if (cin) { 678 pfd[nfd].fd = fileno(cin); 679 pfd[nfd++].events = POLLIN; 680 } 681 682 if (din) { 683 pfd[nfd].fd = fileno(din); 684 pfd[nfd++].events = POLLIN; 685 } 686 687 if ((nr = poll(pfd, nfd, sec * 1000)) <= 0) 688 return nr; 689 690 nr = 0; 691 nfd = 0; 692 if (cin) 693 nr |= (pfd[nfd++].revents & POLLIN) ? 1 : 0; 694 if (din) 695 nr |= (pfd[nfd++].revents & POLLIN) ? 2 : 0; 696 #endif 697 return nr; 698 } 699 700 sigjmp_buf xferabort; 701 702 void 703 abortxfer(notused) 704 int notused; 705 { 706 char msgbuf[100]; 707 int len; 708 709 alarmtimer(0); 710 mflag = 0; 711 abrtflag = 0; 712 switch (direction[0]) { 713 case 'r': 714 strlcpy(msgbuf, "\nreceive", sizeof(msgbuf)); 715 break; 716 case 's': 717 strlcpy(msgbuf, "\nsend", sizeof(msgbuf)); 718 break; 719 default: 720 errx(1, "abortxfer called with unknown direction `%s'", 721 direction); 722 } 723 len = strlcat(msgbuf, " aborted. Waiting for remote to finish abort.\n", 724 sizeof(msgbuf)); 725 write(fileno(ttyout), msgbuf, len); 726 siglongjmp(xferabort, 1); 727 } 728 729 void 730 sendrequest(cmd, local, remote, printnames) 731 const char *cmd, *local, *remote; 732 int printnames; 733 { 734 struct stat st; 735 int c, d; 736 FILE *fin, *dout; 737 int (*closefunc) __P((FILE *)); 738 sigfunc oldintr, oldintp; 739 volatile off_t hashbytes; 740 char *lmode, *bufp; 741 static size_t bufsize; 742 static char *buf; 743 int oprogress; 744 745 #ifdef __GNUC__ /* to shut up gcc warnings */ 746 (void)&fin; 747 (void)&dout; 748 (void)&closefunc; 749 (void)&oldintr; 750 (void)&oldintp; 751 (void)&lmode; 752 #endif 753 754 hashbytes = mark; 755 direction = "sent"; 756 dout = NULL; 757 bytes = 0; 758 filesize = -1; 759 oprogress = progress; 760 if (verbose && printnames) { 761 if (local && *local != '-') 762 fprintf(ttyout, "local: %s ", local); 763 if (remote) 764 fprintf(ttyout, "remote: %s\n", remote); 765 } 766 if (proxy) { 767 proxtrans(cmd, local, remote); 768 return; 769 } 770 if (curtype != type) 771 changetype(type, 0); 772 closefunc = NULL; 773 oldintr = NULL; 774 oldintp = NULL; 775 lmode = "w"; 776 if (sigsetjmp(xferabort, 1)) { 777 while (cpend) 778 (void)getreply(0); 779 code = -1; 780 goto cleanupsend; 781 } 782 (void)xsignal(SIGQUIT, psummary); 783 oldintr = xsignal(SIGINT, abortxfer); 784 if (strcmp(local, "-") == 0) { 785 fin = stdin; 786 progress = 0; 787 } else if (*local == '|') { 788 oldintp = xsignal(SIGPIPE, SIG_IGN); 789 fin = popen(local + 1, "r"); 790 if (fin == NULL) { 791 warn("%s", local + 1); 792 code = -1; 793 goto cleanupsend; 794 } 795 progress = 0; 796 closefunc = pclose; 797 } else { 798 fin = fopen(local, "r"); 799 if (fin == NULL) { 800 warn("local: %s", local); 801 code = -1; 802 goto cleanupsend; 803 } 804 closefunc = fclose; 805 if (fstat(fileno(fin), &st) < 0 || !S_ISREG(st.st_mode)) { 806 fprintf(ttyout, "%s: not a plain file.\n", local); 807 code = -1; 808 goto cleanupsend; 809 } 810 filesize = st.st_size; 811 } 812 if (initconn()) { 813 code = -1; 814 goto cleanupsend; 815 } 816 if (sigsetjmp(xferabort, 1)) 817 goto abort; 818 819 if (restart_point && 820 (strcmp(cmd, "STOR") == 0 || strcmp(cmd, "APPE") == 0)) { 821 int rc; 822 823 rc = -1; 824 switch (curtype) { 825 case TYPE_A: 826 rc = fseek(fin, (long) restart_point, SEEK_SET); 827 break; 828 case TYPE_I: 829 case TYPE_L: 830 rc = lseek(fileno(fin), restart_point, SEEK_SET); 831 break; 832 } 833 if (rc < 0) { 834 warn("local: %s", local); 835 goto cleanupsend; 836 } 837 #ifndef NO_QUAD 838 if (command("REST %lld", (long long) restart_point) != 839 #else 840 if (command("REST %ld", (long) restart_point) != 841 #endif 842 CONTINUE) 843 goto cleanupsend; 844 lmode = "r+w"; 845 } 846 if (remote) { 847 if (command("%s %s", cmd, remote) != PRELIM) 848 goto cleanupsend; 849 } else { 850 if (command("%s", cmd) != PRELIM) 851 goto cleanupsend; 852 } 853 dout = dataconn(lmode); 854 if (dout == NULL) 855 goto abort; 856 857 if (sndbuf_size > bufsize) { 858 if (buf) 859 (void)free(buf); 860 bufsize = sndbuf_size; 861 buf = xmalloc(bufsize); 862 } 863 864 progressmeter(-1); 865 oldintp = xsignal(SIGPIPE, SIG_IGN); 866 867 switch (curtype) { 868 869 case TYPE_I: 870 case TYPE_L: 871 if (rate_put) { /* rate limited */ 872 while (1) { 873 struct timeval then, now, td; 874 off_t bufrem; 875 876 (void)gettimeofday(&then, NULL); 877 errno = c = d = 0; 878 bufrem = rate_put; 879 while (bufrem > 0) { 880 if ((c = read(fileno(fin), buf, 881 MIN(bufsize, bufrem))) <= 0) 882 goto senddone; 883 bytes += c; 884 bufrem -= c; 885 for (bufp = buf; c > 0; 886 c -= d, bufp += d) 887 if ((d = write(fileno(dout), 888 bufp, c)) <= 0) 889 break; 890 if (d < 0) 891 goto senddone; 892 if (hash && 893 (!progress || filesize < 0) ) { 894 while (bytes >= hashbytes) { 895 (void)putc('#', ttyout); 896 hashbytes += mark; 897 } 898 (void)fflush(ttyout); 899 } 900 } 901 while (1) { 902 (void)gettimeofday(&now, NULL); 903 timersub(&now, &then, &td); 904 if (td.tv_sec > 0) 905 break; 906 usleep(1000000 - td.tv_usec); 907 } 908 } 909 } else { /* simpler/faster no rate limit */ 910 while (1) { 911 errno = c = d = 0; 912 if ((c = read(fileno(fin), buf, bufsize)) <= 0) 913 goto senddone; 914 bytes += c; 915 for (bufp = buf; c > 0; c -= d, bufp += d) 916 if ((d = write(fileno(dout), bufp, c)) 917 <= 0) 918 break; 919 if (d < 0) 920 goto senddone; 921 if (hash && (!progress || filesize < 0) ) { 922 while (bytes >= hashbytes) { 923 (void)putc('#', ttyout); 924 hashbytes += mark; 925 } 926 (void)fflush(ttyout); 927 } 928 } 929 } 930 senddone: 931 if (hash && (!progress || filesize < 0) && bytes > 0) { 932 if (bytes < mark) 933 (void)putc('#', ttyout); 934 (void)putc('\n', ttyout); 935 } 936 if (c < 0) 937 warn("local: %s", local); 938 if (d < 0) { 939 if (errno != EPIPE) 940 warn("netout"); 941 bytes = -1; 942 } 943 break; 944 945 case TYPE_A: 946 while ((c = getc(fin)) != EOF) { 947 if (c == '\n') { 948 while (hash && (!progress || filesize < 0) && 949 (bytes >= hashbytes)) { 950 (void)putc('#', ttyout); 951 (void)fflush(ttyout); 952 hashbytes += mark; 953 } 954 if (ferror(dout)) 955 break; 956 (void)putc('\r', dout); 957 bytes++; 958 } 959 (void)putc(c, dout); 960 bytes++; 961 #if 0 /* this violates RFC */ 962 if (c == '\r') { 963 (void)putc('\0', dout); 964 bytes++; 965 } 966 #endif 967 } 968 if (hash && (!progress || filesize < 0)) { 969 if (bytes < hashbytes) 970 (void)putc('#', ttyout); 971 (void)putc('\n', ttyout); 972 } 973 if (ferror(fin)) 974 warn("local: %s", local); 975 if (ferror(dout)) { 976 if (errno != EPIPE) 977 warn("netout"); 978 bytes = -1; 979 } 980 break; 981 } 982 983 progressmeter(1); 984 if (closefunc != NULL) { 985 (*closefunc)(fin); 986 fin = NULL; 987 } 988 (void)fclose(dout); 989 dout = NULL; 990 (void)getreply(0); 991 if (bytes > 0) 992 ptransfer(0); 993 goto cleanupsend; 994 995 abort: 996 (void)xsignal(SIGINT, oldintr); 997 oldintr = NULL; 998 if (!cpend) { 999 code = -1; 1000 goto cleanupsend; 1001 } 1002 if (data >= 0) { 1003 (void)close(data); 1004 data = -1; 1005 } 1006 if (dout) { 1007 (void)fclose(dout); 1008 dout = NULL; 1009 } 1010 (void)getreply(0); 1011 code = -1; 1012 if (bytes > 0) 1013 ptransfer(0); 1014 1015 cleanupsend: 1016 if (oldintr) 1017 (void)xsignal(SIGINT, oldintr); 1018 if (oldintp) 1019 (void)xsignal(SIGPIPE, oldintp); 1020 if (data >= 0) { 1021 (void)close(data); 1022 data = -1; 1023 } 1024 if (closefunc != NULL && fin != NULL) 1025 (*closefunc)(fin); 1026 if (dout) 1027 (void)fclose(dout); 1028 progress = oprogress; 1029 restart_point = 0; 1030 bytes = 0; 1031 } 1032 1033 void 1034 recvrequest(cmd, local, remote, lmode, printnames, ignorespecial) 1035 const char *cmd, *local, *remote, *lmode; 1036 int printnames, ignorespecial; 1037 { 1038 FILE *fout, *din; 1039 int (*closefunc) __P((FILE *)); 1040 sigfunc oldintr, oldintp; 1041 int c, d; 1042 volatile int is_retr, tcrflag, bare_lfs; 1043 static size_t bufsize; 1044 static char *buf; 1045 volatile off_t hashbytes; 1046 struct stat st; 1047 time_t mtime; 1048 struct timeval tval[2]; 1049 int oprogress; 1050 int opreserve; 1051 1052 #ifdef __GNUC__ /* to shut up gcc warnings */ 1053 (void)&local; 1054 (void)&fout; 1055 (void)&din; 1056 (void)&closefunc; 1057 (void)&oldintr; 1058 (void)&oldintp; 1059 #endif 1060 1061 fout = NULL; 1062 din = NULL; 1063 hashbytes = mark; 1064 direction = "received"; 1065 bytes = 0; 1066 bare_lfs = 0; 1067 filesize = -1; 1068 oprogress = progress; 1069 opreserve = preserve; 1070 is_retr = (strcmp(cmd, "RETR") == 0); 1071 if (is_retr && verbose && printnames) { 1072 if (local && (ignorespecial || *local != '-')) 1073 fprintf(ttyout, "local: %s ", local); 1074 if (remote) 1075 fprintf(ttyout, "remote: %s\n", remote); 1076 } 1077 if (proxy && is_retr) { 1078 proxtrans(cmd, local, remote); 1079 return; 1080 } 1081 closefunc = NULL; 1082 oldintr = NULL; 1083 oldintp = NULL; 1084 tcrflag = !crflag && is_retr; 1085 if (sigsetjmp(xferabort, 1)) { 1086 while (cpend) 1087 (void)getreply(0); 1088 code = -1; 1089 goto cleanuprecv; 1090 } 1091 (void)xsignal(SIGQUIT, psummary); 1092 oldintr = xsignal(SIGINT, abortxfer); 1093 if (ignorespecial || (strcmp(local, "-") && *local != '|')) { 1094 if (access(local, W_OK) < 0) { 1095 char *dir = strrchr(local, '/'); 1096 1097 if (errno != ENOENT && errno != EACCES) { 1098 warn("local: %s", local); 1099 code = -1; 1100 goto cleanuprecv; 1101 } 1102 if (dir != NULL) 1103 *dir = 0; 1104 d = access(dir == local ? "/" : 1105 dir ? local : ".", W_OK); 1106 if (dir != NULL) 1107 *dir = '/'; 1108 if (d < 0) { 1109 warn("local: %s", local); 1110 code = -1; 1111 goto cleanuprecv; 1112 } 1113 if (!runique && errno == EACCES && 1114 chmod(local, (S_IRUSR|S_IWUSR)) < 0) { 1115 warn("local: %s", local); 1116 code = -1; 1117 goto cleanuprecv; 1118 } 1119 if (runique && errno == EACCES && 1120 (local = gunique(local)) == NULL) { 1121 code = -1; 1122 goto cleanuprecv; 1123 } 1124 } 1125 else if (runique && (local = gunique(local)) == NULL) { 1126 code = -1; 1127 goto cleanuprecv; 1128 } 1129 } 1130 if (!is_retr) { 1131 if (curtype != TYPE_A) 1132 changetype(TYPE_A, 0); 1133 } else { 1134 if (curtype != type) 1135 changetype(type, 0); 1136 filesize = remotesize(remote, 0); 1137 if (code == 421 || code == -1) 1138 goto cleanuprecv; 1139 } 1140 if (initconn()) { 1141 code = -1; 1142 goto cleanuprecv; 1143 } 1144 if (sigsetjmp(xferabort, 1)) 1145 goto abort; 1146 if (is_retr && restart_point && 1147 #ifndef NO_QUAD 1148 command("REST %lld", (long long) restart_point) != CONTINUE) 1149 #else 1150 command("REST %ld", (long) restart_point) != CONTINUE) 1151 #endif 1152 goto cleanuprecv; 1153 if (! EMPTYSTRING(remote)) { 1154 if (command("%s %s", cmd, remote) != PRELIM) 1155 goto cleanuprecv; 1156 } else { 1157 if (command("%s", cmd) != PRELIM) 1158 goto cleanuprecv; 1159 } 1160 din = dataconn("r"); 1161 if (din == NULL) 1162 goto abort; 1163 if (!ignorespecial && strcmp(local, "-") == 0) { 1164 fout = stdout; 1165 progress = 0; 1166 preserve = 0; 1167 } else if (!ignorespecial && *local == '|') { 1168 oldintp = xsignal(SIGPIPE, SIG_IGN); 1169 fout = popen(local + 1, "w"); 1170 if (fout == NULL) { 1171 warn("%s", local+1); 1172 goto abort; 1173 } 1174 progress = 0; 1175 preserve = 0; 1176 closefunc = pclose; 1177 } else { 1178 fout = fopen(local, lmode); 1179 if (fout == NULL) { 1180 warn("local: %s", local); 1181 goto abort; 1182 } 1183 closefunc = fclose; 1184 } 1185 1186 if (fstat(fileno(fout), &st) != -1 && !S_ISREG(st.st_mode)) { 1187 progress = 0; 1188 preserve = 0; 1189 } 1190 if (rcvbuf_size > bufsize) { 1191 if (buf) 1192 (void)free(buf); 1193 bufsize = rcvbuf_size; 1194 buf = xmalloc(bufsize); 1195 } 1196 1197 progressmeter(-1); 1198 1199 switch (curtype) { 1200 1201 case TYPE_I: 1202 case TYPE_L: 1203 if (is_retr && restart_point && 1204 lseek(fileno(fout), restart_point, SEEK_SET) < 0) { 1205 warn("local: %s", local); 1206 goto cleanuprecv; 1207 } 1208 if (rate_get) { /* rate limiting */ 1209 while (1) { 1210 struct timeval then, now, td; 1211 off_t bufrem; 1212 1213 (void)gettimeofday(&then, NULL); 1214 errno = c = d = 0; 1215 for (bufrem = rate_get; bufrem > 0; ) { 1216 if ((c = read(fileno(din), buf, 1217 MIN(bufsize, bufrem))) <= 0) 1218 goto recvdone; 1219 bytes += c; 1220 bufrem -=c; 1221 if ((d = write(fileno(fout), buf, c)) 1222 != c) 1223 goto recvdone; 1224 if (hash && 1225 (!progress || filesize < 0)) { 1226 while (bytes >= hashbytes) { 1227 (void)putc('#', ttyout); 1228 hashbytes += mark; 1229 } 1230 (void)fflush(ttyout); 1231 } 1232 } 1233 /* sleep until time is up */ 1234 while (1) { 1235 (void)gettimeofday(&now, NULL); 1236 timersub(&now, &then, &td); 1237 if (td.tv_sec > 0) 1238 break; 1239 usleep(1000000 - td.tv_usec); 1240 } 1241 } 1242 } else { /* faster code (no limiting) */ 1243 while (1) { 1244 errno = c = d = 0; 1245 if ((c = read(fileno(din), buf, bufsize)) <= 0) 1246 goto recvdone; 1247 bytes += c; 1248 if ((d = write(fileno(fout), buf, c)) != c) 1249 goto recvdone; 1250 if (hash && (!progress || filesize < 0)) { 1251 while (bytes >= hashbytes) { 1252 (void)putc('#', ttyout); 1253 hashbytes += mark; 1254 } 1255 (void)fflush(ttyout); 1256 } 1257 } 1258 } 1259 recvdone: 1260 if (hash && (!progress || filesize < 0) && bytes > 0) { 1261 if (bytes < mark) 1262 (void)putc('#', ttyout); 1263 (void)putc('\n', ttyout); 1264 } 1265 if (c < 0) { 1266 if (errno != EPIPE) 1267 warn("netin"); 1268 bytes = -1; 1269 } 1270 if (d < c) { 1271 if (d < 0) 1272 warn("local: %s", local); 1273 else 1274 warnx("%s: short write", local); 1275 } 1276 break; 1277 1278 case TYPE_A: 1279 if (is_retr && restart_point) { 1280 int ch; 1281 long i, n; 1282 1283 if (fseek(fout, 0L, SEEK_SET) < 0) 1284 goto done; 1285 n = (long)restart_point; 1286 for (i = 0; i++ < n;) { 1287 if ((ch = getc(fout)) == EOF) 1288 goto done; 1289 if (ch == '\n') 1290 i++; 1291 } 1292 if (fseek(fout, 0L, SEEK_CUR) < 0) { 1293 done: 1294 warn("local: %s", local); 1295 goto cleanuprecv; 1296 } 1297 } 1298 while ((c = getc(din)) != EOF) { 1299 if (c == '\n') 1300 bare_lfs++; 1301 while (c == '\r') { 1302 while (hash && (!progress || filesize < 0) && 1303 (bytes >= hashbytes)) { 1304 (void)putc('#', ttyout); 1305 (void)fflush(ttyout); 1306 hashbytes += mark; 1307 } 1308 bytes++; 1309 if ((c = getc(din)) != '\n' || tcrflag) { 1310 if (ferror(fout)) 1311 goto break2; 1312 (void)putc('\r', fout); 1313 if (c == '\0') { 1314 bytes++; 1315 goto contin2; 1316 } 1317 if (c == EOF) 1318 goto contin2; 1319 } 1320 } 1321 (void)putc(c, fout); 1322 bytes++; 1323 contin2: ; 1324 } 1325 break2: 1326 if (hash && (!progress || filesize < 0)) { 1327 if (bytes < hashbytes) 1328 (void)putc('#', ttyout); 1329 (void)putc('\n', ttyout); 1330 } 1331 if (ferror(din)) { 1332 if (errno != EPIPE) 1333 warn("netin"); 1334 bytes = -1; 1335 } 1336 if (ferror(fout)) 1337 warn("local: %s", local); 1338 break; 1339 } 1340 1341 progressmeter(1); 1342 if (closefunc != NULL) { 1343 (*closefunc)(fout); 1344 fout = NULL; 1345 } 1346 (void)fclose(din); 1347 din = NULL; 1348 (void)getreply(0); 1349 if (bare_lfs) { 1350 fprintf(ttyout, 1351 "WARNING! %d bare linefeeds received in ASCII mode.\n", 1352 bare_lfs); 1353 fputs("File may not have transferred correctly.\n", ttyout); 1354 } 1355 if (bytes >= 0 && is_retr) { 1356 if (bytes > 0) 1357 ptransfer(0); 1358 if (preserve && (closefunc == fclose)) { 1359 mtime = remotemodtime(remote, 0); 1360 if (mtime != -1) { 1361 (void)gettimeofday(&tval[0], NULL); 1362 tval[1].tv_sec = mtime; 1363 tval[1].tv_usec = 0; 1364 if (utimes(local, tval) == -1) { 1365 fprintf(ttyout, 1366 "Can't change modification time on %s to %s", 1367 local, asctime(localtime(&mtime))); 1368 } 1369 } 1370 } 1371 } 1372 goto cleanuprecv; 1373 1374 abort: 1375 /* 1376 * abort using RFC 959 recommended IP,SYNC sequence 1377 */ 1378 if (! sigsetjmp(xferabort, 1)) { 1379 /* this is the first call */ 1380 (void)xsignal(SIGINT, abort_squared); 1381 if (!cpend) { 1382 code = -1; 1383 goto cleanuprecv; 1384 } 1385 abort_remote(din); 1386 } 1387 code = -1; 1388 if (bytes > 0) 1389 ptransfer(0); 1390 1391 cleanuprecv: 1392 if (oldintr) 1393 (void)xsignal(SIGINT, oldintr); 1394 if (oldintp) 1395 (void)xsignal(SIGPIPE, oldintp); 1396 if (data >= 0) { 1397 (void)close(data); 1398 data = -1; 1399 } 1400 if (closefunc != NULL && fout != NULL) 1401 (*closefunc)(fout); 1402 if (din) 1403 (void)fclose(din); 1404 progress = oprogress; 1405 preserve = opreserve; 1406 bytes = 0; 1407 } 1408 1409 /* 1410 * Need to start a listen on the data channel before we send the command, 1411 * otherwise the server's connect may fail. 1412 */ 1413 int 1414 initconn() 1415 { 1416 char *p, *a; 1417 int result, len, tmpno = 0; 1418 int on = 1; 1419 int error; 1420 u_int addr[16], port[2]; 1421 u_int af, hal, pal; 1422 char *pasvcmd = NULL; 1423 1424 #ifdef INET6 1425 if (myctladdr.su_family == AF_INET6 1426 && (IN6_IS_ADDR_LINKLOCAL(&myctladdr.su_sin6.sin6_addr) 1427 || IN6_IS_ADDR_SITELOCAL(&myctladdr.su_sin6.sin6_addr))) { 1428 warnx("use of scoped address can be troublesome"); 1429 } 1430 #endif 1431 reinit: 1432 if (passivemode) { 1433 data_addr = myctladdr; 1434 data = socket(data_addr.su_family, SOCK_STREAM, 0); 1435 if (data < 0) { 1436 warn("socket"); 1437 return (1); 1438 } 1439 if ((options & SO_DEBUG) && 1440 setsockopt(data, SOL_SOCKET, SO_DEBUG, (char *)&on, 1441 sizeof(on)) < 0) 1442 warn("setsockopt (ignored)"); 1443 result = COMPLETE + 1; 1444 switch (data_addr.su_family) { 1445 case AF_INET: 1446 if (epsv4 && !epsv4bad) { 1447 result = command(pasvcmd = "EPSV"); 1448 if (!connected) 1449 return (1); 1450 /* 1451 * this code is to be friendly with broken 1452 * BSDI ftpd 1453 */ 1454 if (code / 10 == 22 && code != 229) { 1455 fputs( 1456 "wrong server: return code must be 229\n", 1457 ttyout); 1458 result = COMPLETE + 1; 1459 } 1460 if (result != COMPLETE) { 1461 epsv4bad = 1; 1462 if (debug) 1463 fputs( 1464 "disabling epsv4 for this connection\n", 1465 ttyout); 1466 } 1467 } 1468 if (result != COMPLETE) { 1469 result = command(pasvcmd = "PASV"); 1470 if (!connected) 1471 return (1); 1472 } 1473 break; 1474 #ifdef INET6 1475 case AF_INET6: 1476 result = command(pasvcmd = "EPSV"); 1477 if (!connected) 1478 return (1); 1479 /* this code is to be friendly with broken BSDI ftpd */ 1480 if (code / 10 == 22 && code != 229) { 1481 fputs( 1482 "wrong server: return code must be 229\n", 1483 ttyout); 1484 result = COMPLETE + 1; 1485 } 1486 if (result != COMPLETE) 1487 result = command(pasvcmd = "LPSV"); 1488 if (!connected) 1489 return (1); 1490 break; 1491 #endif 1492 default: 1493 result = COMPLETE + 1; 1494 break; 1495 } 1496 if (result != COMPLETE) { 1497 if (activefallback) { 1498 (void)close(data); 1499 data = -1; 1500 passivemode = 0; 1501 #if 0 1502 activefallback = 0; 1503 #endif 1504 goto reinit; 1505 } 1506 fputs("Passive mode refused.\n", ttyout); 1507 goto bad; 1508 } 1509 1510 #define pack2(var, off) \ 1511 (((var[(off) + 0] & 0xff) << 8) | ((var[(off) + 1] & 0xff) << 0)) 1512 #define pack4(var, off) \ 1513 (((var[(off) + 0] & 0xff) << 24) | ((var[(off) + 1] & 0xff) << 16) | \ 1514 ((var[(off) + 2] & 0xff) << 8) | ((var[(off) + 3] & 0xff) << 0)) 1515 1516 /* 1517 * What we've got at this point is a string of comma separated 1518 * one-byte unsigned integer values, separated by commas. 1519 */ 1520 if (strcmp(pasvcmd, "PASV") == 0) { 1521 if (data_addr.su_family != AF_INET) { 1522 fputs( 1523 "Passive mode AF mismatch. Shouldn't happen!\n", ttyout); 1524 error = 1; 1525 goto bad; 1526 } 1527 if (code / 10 == 22 && code != 227) { 1528 fputs("wrong server: return code must be 227\n", 1529 ttyout); 1530 error = 1; 1531 goto bad; 1532 } 1533 error = sscanf(pasv, "%u,%u,%u,%u,%u,%u", 1534 &addr[0], &addr[1], &addr[2], &addr[3], 1535 &port[0], &port[1]); 1536 if (error != 6) { 1537 fputs( 1538 "Passive mode address scan failure. Shouldn't happen!\n", ttyout); 1539 error = 1; 1540 goto bad; 1541 } 1542 error = 0; 1543 memset(&data_addr, 0, sizeof(data_addr)); 1544 data_addr.su_family = AF_INET; 1545 data_addr.su_len = sizeof(struct sockaddr_in); 1546 data_addr.su_sin.sin_addr.s_addr = 1547 htonl(pack4(addr, 0)); 1548 data_addr.su_port = htons(pack2(port, 0)); 1549 } else if (strcmp(pasvcmd, "LPSV") == 0) { 1550 if (code / 10 == 22 && code != 228) { 1551 fputs("wrong server: return code must be 228\n", 1552 ttyout); 1553 error = 1; 1554 goto bad; 1555 } 1556 switch (data_addr.su_family) { 1557 case AF_INET: 1558 error = sscanf(pasv, 1559 "%u,%u,%u,%u,%u,%u,%u,%u,%u", 1560 &af, &hal, 1561 &addr[0], &addr[1], &addr[2], &addr[3], 1562 &pal, &port[0], &port[1]); 1563 if (error != 9) { 1564 fputs( 1565 "Passive mode address scan failure. Shouldn't happen!\n", ttyout); 1566 error = 1; 1567 goto bad; 1568 } 1569 if (af != 4 || hal != 4 || pal != 2) { 1570 fputs( 1571 "Passive mode AF mismatch. Shouldn't happen!\n", ttyout); 1572 error = 1; 1573 goto bad; 1574 } 1575 1576 error = 0; 1577 memset(&data_addr, 0, sizeof(data_addr)); 1578 data_addr.su_family = AF_INET; 1579 data_addr.su_len = sizeof(struct sockaddr_in); 1580 data_addr.su_sin.sin_addr.s_addr = 1581 htonl(pack4(addr, 0)); 1582 data_addr.su_port = htons(pack2(port, 0)); 1583 break; 1584 #ifdef INET6 1585 case AF_INET6: 1586 error = sscanf(pasv, 1587 "%u,%u,%u,%u,%u,%u,%u,%u,%u,%u,%u,%u,%u,%u,%u,%u,%u,%u,%u,%u,%u", 1588 &af, &hal, 1589 &addr[0], &addr[1], &addr[2], &addr[3], 1590 &addr[4], &addr[5], &addr[6], &addr[7], 1591 &addr[8], &addr[9], &addr[10], 1592 &addr[11], &addr[12], &addr[13], 1593 &addr[14], &addr[15], 1594 &pal, &port[0], &port[1]); 1595 if (error != 21) { 1596 fputs( 1597 "Passive mode address scan failure. Shouldn't happen!\n", ttyout); 1598 error = 1; 1599 goto bad; 1600 } 1601 if (af != 6 || hal != 16 || pal != 2) { 1602 fputs( 1603 "Passive mode AF mismatch. Shouldn't happen!\n", ttyout); 1604 error = 1; 1605 goto bad; 1606 } 1607 1608 error = 0; 1609 memset(&data_addr, 0, sizeof(data_addr)); 1610 data_addr.su_family = AF_INET6; 1611 data_addr.su_len = sizeof(struct sockaddr_in6); 1612 { 1613 u_int32_t *p32; 1614 p32 = (u_int32_t *)&data_addr.su_sin6.sin6_addr; 1615 p32[0] = htonl(pack4(addr, 0)); 1616 p32[1] = htonl(pack4(addr, 4)); 1617 p32[2] = htonl(pack4(addr, 8)); 1618 p32[3] = htonl(pack4(addr, 12)); 1619 } 1620 data_addr.su_port = htons(pack2(port, 0)); 1621 break; 1622 #endif 1623 default: 1624 error = 1; 1625 } 1626 } else if (strcmp(pasvcmd, "EPSV") == 0) { 1627 char delim[4]; 1628 1629 port[0] = 0; 1630 if (code / 10 == 22 && code != 229) { 1631 fputs("wrong server: return code must be 229\n", 1632 ttyout); 1633 error = 1; 1634 goto bad; 1635 } 1636 if (sscanf(pasv, "%c%c%c%d%c", &delim[0], 1637 &delim[1], &delim[2], &port[1], 1638 &delim[3]) != 5) { 1639 fputs("parse error!\n", ttyout); 1640 error = 1; 1641 goto bad; 1642 } 1643 if (delim[0] != delim[1] || delim[0] != delim[2] 1644 || delim[0] != delim[3]) { 1645 fputs("parse error!\n", ttyout); 1646 error = 1; 1647 goto bad; 1648 } 1649 data_addr = hisctladdr; 1650 data_addr.su_port = htons(port[1]); 1651 } else 1652 goto bad; 1653 1654 while (xconnect(data, (struct sockaddr *)&data_addr, 1655 data_addr.su_len) < 0) { 1656 if (errno == EINTR) 1657 continue; 1658 if (activefallback) { 1659 (void)close(data); 1660 data = -1; 1661 passivemode = 0; 1662 #if 0 1663 activefallback = 0; 1664 #endif 1665 goto reinit; 1666 } 1667 warn("connect"); 1668 goto bad; 1669 } 1670 #ifdef IPTOS_THROUGHPUT 1671 if (data_addr.su_family == AF_INET) { 1672 on = IPTOS_THROUGHPUT; 1673 if (setsockopt(data, IPPROTO_IP, IP_TOS, (char *)&on, 1674 sizeof(int)) < 0) 1675 warn("setsockopt TOS (ignored)"); 1676 } 1677 #endif 1678 return (0); 1679 } 1680 1681 noport: 1682 data_addr = myctladdr; 1683 if (sendport) 1684 data_addr.su_port = 0; /* let system pick one */ 1685 if (data != -1) 1686 (void)close(data); 1687 data = socket(data_addr.su_family, SOCK_STREAM, 0); 1688 if (data < 0) { 1689 warn("socket"); 1690 if (tmpno) 1691 sendport = 1; 1692 return (1); 1693 } 1694 if (!sendport) 1695 if (setsockopt(data, SOL_SOCKET, SO_REUSEADDR, (char *)&on, 1696 sizeof(on)) < 0) { 1697 warn("setsockopt (reuse address)"); 1698 goto bad; 1699 } 1700 if (bind(data, (struct sockaddr *)&data_addr, data_addr.su_len) < 0) { 1701 warn("bind"); 1702 goto bad; 1703 } 1704 if (options & SO_DEBUG && 1705 setsockopt(data, SOL_SOCKET, SO_DEBUG, (char *)&on, 1706 sizeof(on)) < 0) 1707 warn("setsockopt (ignored)"); 1708 len = sizeof(data_addr); 1709 if (getsockname(data, (struct sockaddr *)&data_addr, &len) < 0) { 1710 warn("getsockname"); 1711 goto bad; 1712 } 1713 if (xlisten(data, 1) < 0) 1714 warn("listen"); 1715 1716 #define UC(b) (((int)b)&0xff) 1717 1718 if (sendport) { 1719 #ifdef INET6 1720 char hname[INET6_ADDRSTRLEN]; 1721 int af; 1722 #endif 1723 1724 switch (data_addr.su_family) { 1725 case AF_INET: 1726 if (!epsv4 || epsv4bad) { 1727 result = COMPLETE + 1; 1728 break; 1729 } 1730 /* FALLTHROUGH */ 1731 #ifdef INET6 1732 case AF_INET6: 1733 af = (data_addr.su_family == AF_INET) ? 1 : 2; 1734 if (getnameinfo((struct sockaddr *)&data_addr, 1735 data_addr.su_len, hname, sizeof(hname), 1736 NULL, 0, NI_NUMERICHOST)) { 1737 result = ERROR; 1738 } else { 1739 result = command("EPRT |%d|%s|%d|", af, hname, 1740 ntohs(data_addr.su_port)); 1741 if (!connected) 1742 return (1); 1743 if (result != COMPLETE) { 1744 epsv4bad = 1; 1745 if (debug) 1746 fputs( 1747 "disabling epsv4 for this connection\n", 1748 ttyout); 1749 } 1750 } 1751 break; 1752 #endif 1753 default: 1754 result = COMPLETE + 1; 1755 break; 1756 } 1757 if (result == COMPLETE) 1758 goto skip_port; 1759 1760 switch (data_addr.su_family) { 1761 case AF_INET: 1762 a = (char *)&data_addr.su_sin.sin_addr; 1763 p = (char *)&data_addr.su_port; 1764 result = command("PORT %d,%d,%d,%d,%d,%d", 1765 UC(a[0]), UC(a[1]), UC(a[2]), UC(a[3]), 1766 UC(p[0]), UC(p[1])); 1767 break; 1768 #ifdef INET6 1769 case AF_INET6: 1770 a = (char *)&data_addr.su_sin6.sin6_addr; 1771 p = (char *)&data_addr.su_port; 1772 result = command( 1773 "LPRT %d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d", 1774 6, 16, 1775 UC(a[0]),UC(a[1]),UC(a[2]),UC(a[3]), 1776 UC(a[4]),UC(a[5]),UC(a[6]),UC(a[7]), 1777 UC(a[8]),UC(a[9]),UC(a[10]),UC(a[11]), 1778 UC(a[12]),UC(a[13]),UC(a[14]),UC(a[15]), 1779 2, UC(p[0]), UC(p[1])); 1780 break; 1781 #endif 1782 default: 1783 result = COMPLETE + 1; /* xxx */ 1784 } 1785 if (!connected) 1786 return (1); 1787 skip_port: 1788 1789 if (result == ERROR && sendport == -1) { 1790 sendport = 0; 1791 tmpno = 1; 1792 goto noport; 1793 } 1794 return (result != COMPLETE); 1795 } 1796 if (tmpno) 1797 sendport = 1; 1798 #ifdef IPTOS_THROUGHPUT 1799 if (data_addr.su_family == AF_INET) { 1800 on = IPTOS_THROUGHPUT; 1801 if (setsockopt(data, IPPROTO_IP, IP_TOS, (char *)&on, 1802 sizeof(int)) < 0) 1803 warn("setsockopt TOS (ignored)"); 1804 } 1805 #endif 1806 return (0); 1807 bad: 1808 (void)close(data), data = -1; 1809 if (tmpno) 1810 sendport = 1; 1811 return (1); 1812 } 1813 1814 FILE * 1815 dataconn(lmode) 1816 const char *lmode; 1817 { 1818 union sockunion from; 1819 int s, fromlen = myctladdr.su_len; 1820 1821 if (passivemode) 1822 return (fdopen(data, lmode)); 1823 1824 s = accept(data, (struct sockaddr *) &from, &fromlen); 1825 if (s < 0) { 1826 warn("accept"); 1827 (void)close(data), data = -1; 1828 return (NULL); 1829 } 1830 (void)close(data); 1831 data = s; 1832 #ifdef IPTOS_THROUGHPUT 1833 if (from.su_family == AF_INET) { 1834 int tos = IPTOS_THROUGHPUT; 1835 if (setsockopt(s, IPPROTO_IP, IP_TOS, (char *)&tos, 1836 sizeof(int)) < 0) { 1837 warn("setsockopt TOS (ignored)"); 1838 } 1839 } 1840 #endif 1841 return (fdopen(data, lmode)); 1842 } 1843 1844 void 1845 psabort(notused) 1846 int notused; 1847 { 1848 int oerrno = errno; 1849 1850 alarmtimer(0); 1851 abrtflag++; 1852 errno = oerrno; 1853 } 1854 1855 void 1856 pswitch(flag) 1857 int flag; 1858 { 1859 sigfunc oldintr; 1860 static struct comvars { 1861 int connect; 1862 char name[MAXHOSTNAMELEN]; 1863 union sockunion mctl; 1864 union sockunion hctl; 1865 FILE *in; 1866 FILE *out; 1867 int tpe; 1868 int curtpe; 1869 int cpnd; 1870 int sunqe; 1871 int runqe; 1872 int mcse; 1873 int ntflg; 1874 char nti[17]; 1875 char nto[17]; 1876 int mapflg; 1877 char mi[MAXPATHLEN]; 1878 char mo[MAXPATHLEN]; 1879 } proxstruct, tmpstruct; 1880 struct comvars *ip, *op; 1881 1882 abrtflag = 0; 1883 oldintr = xsignal(SIGINT, psabort); 1884 if (flag) { 1885 if (proxy) 1886 return; 1887 ip = &tmpstruct; 1888 op = &proxstruct; 1889 proxy++; 1890 } else { 1891 if (!proxy) 1892 return; 1893 ip = &proxstruct; 1894 op = &tmpstruct; 1895 proxy = 0; 1896 } 1897 ip->connect = connected; 1898 connected = op->connect; 1899 if (hostname) 1900 (void)strlcpy(ip->name, hostname, sizeof(ip->name)); 1901 else 1902 ip->name[0] = '\0'; 1903 hostname = op->name; 1904 ip->hctl = hisctladdr; 1905 hisctladdr = op->hctl; 1906 ip->mctl = myctladdr; 1907 myctladdr = op->mctl; 1908 ip->in = cin; 1909 cin = op->in; 1910 ip->out = cout; 1911 cout = op->out; 1912 ip->tpe = type; 1913 type = op->tpe; 1914 ip->curtpe = curtype; 1915 curtype = op->curtpe; 1916 ip->cpnd = cpend; 1917 cpend = op->cpnd; 1918 ip->sunqe = sunique; 1919 sunique = op->sunqe; 1920 ip->runqe = runique; 1921 runique = op->runqe; 1922 ip->mcse = mcase; 1923 mcase = op->mcse; 1924 ip->ntflg = ntflag; 1925 ntflag = op->ntflg; 1926 (void)strlcpy(ip->nti, ntin, sizeof(ip->nti)); 1927 (void)strlcpy(ntin, op->nti, sizeof(ntin)); 1928 (void)strlcpy(ip->nto, ntout, sizeof(ip->nto)); 1929 (void)strlcpy(ntout, op->nto, sizeof(ntout)); 1930 ip->mapflg = mapflag; 1931 mapflag = op->mapflg; 1932 (void)strlcpy(ip->mi, mapin, sizeof(ip->mi)); 1933 (void)strlcpy(mapin, op->mi, sizeof(mapin)); 1934 (void)strlcpy(ip->mo, mapout, sizeof(ip->mo)); 1935 (void)strlcpy(mapout, op->mo, sizeof(mapout)); 1936 (void)xsignal(SIGINT, oldintr); 1937 if (abrtflag) { 1938 abrtflag = 0; 1939 (*oldintr)(SIGINT); 1940 } 1941 } 1942 1943 void 1944 abortpt(notused) 1945 int notused; 1946 { 1947 1948 alarmtimer(0); 1949 if (fromatty) 1950 write(fileno(ttyout), "\n", 1); 1951 ptabflg++; 1952 mflag = 0; 1953 abrtflag = 0; 1954 siglongjmp(ptabort, 1); 1955 } 1956 1957 void 1958 proxtrans(cmd, local, remote) 1959 const char *cmd, *local, *remote; 1960 { 1961 sigfunc oldintr; 1962 int prox_type, nfnd; 1963 volatile int secndflag; 1964 char *cmd2; 1965 1966 #ifdef __GNUC__ /* to shut up gcc warnings */ 1967 (void)&oldintr; 1968 (void)&cmd2; 1969 #endif 1970 1971 oldintr = NULL; 1972 secndflag = 0; 1973 if (strcmp(cmd, "RETR")) 1974 cmd2 = "RETR"; 1975 else 1976 cmd2 = runique ? "STOU" : "STOR"; 1977 if ((prox_type = type) == 0) { 1978 if (unix_server && unix_proxy) 1979 prox_type = TYPE_I; 1980 else 1981 prox_type = TYPE_A; 1982 } 1983 if (curtype != prox_type) 1984 changetype(prox_type, 1); 1985 if (command("PASV") != COMPLETE) { 1986 fputs("proxy server does not support third party transfers.\n", 1987 ttyout); 1988 return; 1989 } 1990 pswitch(0); 1991 if (!connected) { 1992 fputs("No primary connection.\n", ttyout); 1993 pswitch(1); 1994 code = -1; 1995 return; 1996 } 1997 if (curtype != prox_type) 1998 changetype(prox_type, 1); 1999 if (command("PORT %s", pasv) != COMPLETE) { 2000 pswitch(1); 2001 return; 2002 } 2003 if (sigsetjmp(ptabort, 1)) 2004 goto abort; 2005 oldintr = xsignal(SIGINT, abortpt); 2006 if ((restart_point && 2007 #ifndef NO_QUAD 2008 (command("REST %lld", (long long) restart_point) != CONTINUE) 2009 #else 2010 (command("REST %ld", (long) restart_point) != CONTINUE) 2011 #endif 2012 ) || (command("%s %s", cmd, remote) != PRELIM)) { 2013 (void)xsignal(SIGINT, oldintr); 2014 pswitch(1); 2015 return; 2016 } 2017 sleep(2); 2018 pswitch(1); 2019 secndflag++; 2020 if ((restart_point && 2021 #ifndef NO_QUAD 2022 (command("REST %lld", (long long) restart_point) != CONTINUE) 2023 #else 2024 (command("REST %ld", (long) restart_point) != CONTINUE) 2025 #endif 2026 ) || (command("%s %s", cmd2, local) != PRELIM)) 2027 goto abort; 2028 ptflag++; 2029 (void)getreply(0); 2030 pswitch(0); 2031 (void)getreply(0); 2032 (void)xsignal(SIGINT, oldintr); 2033 pswitch(1); 2034 ptflag = 0; 2035 fprintf(ttyout, "local: %s remote: %s\n", local, remote); 2036 return; 2037 abort: 2038 if (sigsetjmp(xferabort, 1)) { 2039 (void)xsignal(SIGINT, oldintr); 2040 return; 2041 } 2042 (void)xsignal(SIGINT, abort_squared); 2043 ptflag = 0; 2044 if (strcmp(cmd, "RETR") && !proxy) 2045 pswitch(1); 2046 else if (!strcmp(cmd, "RETR") && proxy) 2047 pswitch(0); 2048 if (!cpend && !secndflag) { /* only here if cmd = "STOR" (proxy=1) */ 2049 if (command("%s %s", cmd2, local) != PRELIM) { 2050 pswitch(0); 2051 if (cpend) 2052 abort_remote(NULL); 2053 } 2054 pswitch(1); 2055 if (ptabflg) 2056 code = -1; 2057 (void)xsignal(SIGINT, oldintr); 2058 return; 2059 } 2060 if (cpend) 2061 abort_remote(NULL); 2062 pswitch(!proxy); 2063 if (!cpend && !secndflag) { /* only if cmd = "RETR" (proxy=1) */ 2064 if (command("%s %s", cmd2, local) != PRELIM) { 2065 pswitch(0); 2066 if (cpend) 2067 abort_remote(NULL); 2068 pswitch(1); 2069 if (ptabflg) 2070 code = -1; 2071 (void)xsignal(SIGINT, oldintr); 2072 return; 2073 } 2074 } 2075 if (cpend) 2076 abort_remote(NULL); 2077 pswitch(!proxy); 2078 if (cpend) { 2079 if ((nfnd = empty(cin, NULL, 10)) <= 0) { 2080 if (nfnd < 0) 2081 warn("abort"); 2082 if (ptabflg) 2083 code = -1; 2084 lostpeer(0); 2085 } 2086 (void)getreply(0); 2087 (void)getreply(0); 2088 } 2089 if (proxy) 2090 pswitch(0); 2091 pswitch(1); 2092 if (ptabflg) 2093 code = -1; 2094 (void)xsignal(SIGINT, oldintr); 2095 } 2096 2097 void 2098 reset(argc, argv) 2099 int argc; 2100 char *argv[]; 2101 { 2102 int nfnd = 1; 2103 2104 if (argc == 0 && argv != NULL) { 2105 fprintf(ttyout, "usage: %s\n", argv[0]); 2106 code = -1; 2107 return; 2108 } 2109 while (nfnd > 0) { 2110 if ((nfnd = empty(cin, NULL, 0)) < 0) { 2111 warn("reset"); 2112 code = -1; 2113 lostpeer(0); 2114 } else if (nfnd) 2115 (void)getreply(0); 2116 } 2117 } 2118 2119 char * 2120 gunique(local) 2121 const char *local; 2122 { 2123 static char new[MAXPATHLEN]; 2124 char *cp = strrchr(local, '/'); 2125 int d, count=0, len; 2126 char ext = '1'; 2127 2128 if (cp) 2129 *cp = '\0'; 2130 d = access(cp == local ? "/" : cp ? local : ".", W_OK); 2131 if (cp) 2132 *cp = '/'; 2133 if (d < 0) { 2134 warn("local: %s", local); 2135 return (NULL); 2136 } 2137 len = strlcpy(new, local, sizeof(new)); 2138 cp = &new[len]; 2139 *cp++ = '.'; 2140 while (!d) { 2141 if (++count == 100) { 2142 fputs("runique: can't find unique file name.\n", 2143 ttyout); 2144 return (NULL); 2145 } 2146 *cp++ = ext; 2147 *cp = '\0'; 2148 if (ext == '9') 2149 ext = '0'; 2150 else 2151 ext++; 2152 if ((d = access(new, F_OK)) < 0) 2153 break; 2154 if (ext != '0') 2155 cp--; 2156 else if (*(cp - 2) == '.') 2157 *(cp - 1) = '1'; 2158 else { 2159 *(cp - 2) = *(cp - 2) + 1; 2160 cp--; 2161 } 2162 } 2163 return (new); 2164 } 2165 2166 /* 2167 * abort_squared -- 2168 * aborts abort_remote(). lostpeer() is called because if the user is 2169 * too impatient to wait or there's another problem then ftp really 2170 * needs to get back to a known state. 2171 */ 2172 void 2173 abort_squared(dummy) 2174 int dummy; 2175 { 2176 char msgbuf[100]; 2177 int len; 2178 2179 alarmtimer(0); 2180 len = strlcpy(msgbuf, "\nremote abort aborted; closing connection.\n", 2181 sizeof(msgbuf)); 2182 write(fileno(ttyout), msgbuf, len); 2183 lostpeer(0); 2184 siglongjmp(xferabort, 1); 2185 } 2186 2187 void 2188 abort_remote(din) 2189 FILE *din; 2190 { 2191 char buf[BUFSIZ]; 2192 int nfnd; 2193 2194 if (cout == NULL) { 2195 warnx("Lost control connection for abort."); 2196 if (ptabflg) 2197 code = -1; 2198 lostpeer(0); 2199 return; 2200 } 2201 /* 2202 * send IAC in urgent mode instead of DM because 4.3BSD places oob mark 2203 * after urgent byte rather than before as is protocol now 2204 */ 2205 buf[0] = IAC; 2206 buf[1] = IP; 2207 buf[2] = IAC; 2208 if (send(fileno(cout), buf, 3, MSG_OOB) != 3) 2209 warn("abort"); 2210 fprintf(cout, "%cABOR\r\n", DM); 2211 (void)fflush(cout); 2212 if ((nfnd = empty(cin, din, 10)) <= 0) { 2213 if (nfnd < 0) 2214 warn("abort"); 2215 if (ptabflg) 2216 code = -1; 2217 lostpeer(0); 2218 } 2219 if (din && (nfnd & 2)) { 2220 while (read(fileno(din), buf, BUFSIZ) > 0) 2221 continue; 2222 } 2223 if (getreply(0) == ERROR && code == 552) { 2224 /* 552 needed for nic style abort */ 2225 (void)getreply(0); 2226 } 2227 (void)getreply(0); 2228 } 2229