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