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