1 /* $NetBSD: ftp.c,v 1.39 1999/01/05 23:33:44 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.39 1999/01/05 23:33:44 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 if (activefallback) { 1154 (void)close(data); 1155 data = -1; 1156 passivemode = 0; 1157 activefallback = 0; 1158 goto reinit; 1159 } 1160 warn("connect"); 1161 goto bad; 1162 } 1163 #ifdef IP_TOS 1164 on = IPTOS_THROUGHPUT; 1165 if (setsockopt(data, IPPROTO_IP, IP_TOS, (char *)&on, 1166 sizeof(int)) < 0) 1167 warn("setsockopt TOS (ignored)"); 1168 #endif 1169 return (0); 1170 } 1171 1172 noport: 1173 data_addr = myctladdr; 1174 if (sendport) 1175 data_addr.sin_port = 0; /* let system pick one */ 1176 if (data != -1) 1177 (void)close(data); 1178 data = socket(AF_INET, SOCK_STREAM, 0); 1179 if (data < 0) { 1180 warn("socket"); 1181 if (tmpno) 1182 sendport = 1; 1183 return (1); 1184 } 1185 if (!sendport) 1186 if (setsockopt(data, SOL_SOCKET, SO_REUSEADDR, (char *)&on, 1187 sizeof(on)) < 0) { 1188 warn("setsockopt (reuse address)"); 1189 goto bad; 1190 } 1191 if (bind(data, (struct sockaddr *)&data_addr, sizeof(data_addr)) < 0) { 1192 warn("bind"); 1193 goto bad; 1194 } 1195 if (options & SO_DEBUG && 1196 setsockopt(data, SOL_SOCKET, SO_DEBUG, (char *)&on, 1197 sizeof(on)) < 0) 1198 warn("setsockopt (ignored)"); 1199 len = sizeof(data_addr); 1200 if (getsockname(data, (struct sockaddr *)&data_addr, &len) < 0) { 1201 warn("getsockname"); 1202 goto bad; 1203 } 1204 if (xlisten(data, 1) < 0) 1205 warn("listen"); 1206 if (sendport) { 1207 a = (char *)&data_addr.sin_addr; 1208 p = (char *)&data_addr.sin_port; 1209 #define UC(b) (((int)b)&0xff) 1210 result = 1211 command("PORT %d,%d,%d,%d,%d,%d", 1212 UC(a[0]), UC(a[1]), UC(a[2]), UC(a[3]), 1213 UC(p[0]), UC(p[1])); 1214 if (result == ERROR && sendport == -1) { 1215 sendport = 0; 1216 tmpno = 1; 1217 goto noport; 1218 } 1219 return (result != COMPLETE); 1220 } 1221 if (tmpno) 1222 sendport = 1; 1223 #ifdef IP_TOS 1224 on = IPTOS_THROUGHPUT; 1225 if (setsockopt(data, IPPROTO_IP, IP_TOS, (char *)&on, sizeof(int)) < 0) 1226 warn("setsockopt TOS (ignored)"); 1227 #endif 1228 return (0); 1229 bad: 1230 (void)close(data), data = -1; 1231 if (tmpno) 1232 sendport = 1; 1233 return (1); 1234 } 1235 1236 FILE * 1237 dataconn(lmode) 1238 const char *lmode; 1239 { 1240 struct sockaddr_in from; 1241 int s, fromlen, tos; 1242 1243 fromlen = sizeof(from); 1244 1245 if (passivemode) 1246 return (fdopen(data, lmode)); 1247 1248 s = accept(data, (struct sockaddr *) &from, &fromlen); 1249 if (s < 0) { 1250 warn("accept"); 1251 (void)close(data), data = -1; 1252 return (NULL); 1253 } 1254 (void)close(data); 1255 data = s; 1256 #ifdef IP_TOS 1257 tos = IPTOS_THROUGHPUT; 1258 if (setsockopt(s, IPPROTO_IP, IP_TOS, (char *)&tos, sizeof(int)) < 0) 1259 warn("setsockopt TOS (ignored)"); 1260 #endif 1261 return (fdopen(data, lmode)); 1262 } 1263 1264 void 1265 psummary(notused) 1266 int notused; 1267 { 1268 1269 if (bytes > 0) 1270 ptransfer(1); 1271 } 1272 1273 void 1274 psabort(notused) 1275 int notused; 1276 { 1277 1278 alarmtimer(0); 1279 abrtflag++; 1280 } 1281 1282 void 1283 pswitch(flag) 1284 int flag; 1285 { 1286 sig_t oldintr; 1287 static struct comvars { 1288 int connect; 1289 char name[MAXHOSTNAMELEN]; 1290 struct sockaddr_in mctl; 1291 struct sockaddr_in hctl; 1292 FILE *in; 1293 FILE *out; 1294 int tpe; 1295 int curtpe; 1296 int cpnd; 1297 int sunqe; 1298 int runqe; 1299 int mcse; 1300 int ntflg; 1301 char nti[17]; 1302 char nto[17]; 1303 int mapflg; 1304 char mi[MAXPATHLEN]; 1305 char mo[MAXPATHLEN]; 1306 } proxstruct, tmpstruct; 1307 struct comvars *ip, *op; 1308 1309 abrtflag = 0; 1310 oldintr = signal(SIGINT, psabort); 1311 if (flag) { 1312 if (proxy) 1313 return; 1314 ip = &tmpstruct; 1315 op = &proxstruct; 1316 proxy++; 1317 } else { 1318 if (!proxy) 1319 return; 1320 ip = &proxstruct; 1321 op = &tmpstruct; 1322 proxy = 0; 1323 } 1324 ip->connect = connected; 1325 connected = op->connect; 1326 if (hostname) { 1327 (void)strncpy(ip->name, hostname, sizeof(ip->name) - 1); 1328 ip->name[sizeof(ip->name) - 1] = '\0'; 1329 } else 1330 ip->name[0] = '\0'; 1331 hostname = op->name; 1332 ip->hctl = hisctladdr; 1333 hisctladdr = op->hctl; 1334 ip->mctl = myctladdr; 1335 myctladdr = op->mctl; 1336 ip->in = cin; 1337 cin = op->in; 1338 ip->out = cout; 1339 cout = op->out; 1340 ip->tpe = type; 1341 type = op->tpe; 1342 ip->curtpe = curtype; 1343 curtype = op->curtpe; 1344 ip->cpnd = cpend; 1345 cpend = op->cpnd; 1346 ip->sunqe = sunique; 1347 sunique = op->sunqe; 1348 ip->runqe = runique; 1349 runique = op->runqe; 1350 ip->mcse = mcase; 1351 mcase = op->mcse; 1352 ip->ntflg = ntflag; 1353 ntflag = op->ntflg; 1354 (void)strncpy(ip->nti, ntin, sizeof(ip->nti) - 1); 1355 (ip->nti)[sizeof(ip->nti) - 1] = '\0'; 1356 (void)strcpy(ntin, op->nti); 1357 (void)strncpy(ip->nto, ntout, sizeof(ip->nto) - 1); 1358 (ip->nto)[sizeof(ip->nto) - 1] = '\0'; 1359 (void)strcpy(ntout, op->nto); 1360 ip->mapflg = mapflag; 1361 mapflag = op->mapflg; 1362 (void)strncpy(ip->mi, mapin, sizeof(ip->mi) - 1); 1363 (ip->mi)[sizeof(ip->mi) - 1] = '\0'; 1364 (void)strcpy(mapin, op->mi); 1365 (void)strncpy(ip->mo, mapout, sizeof(ip->mo) - 1); 1366 (ip->mo)[sizeof(ip->mo) - 1] = '\0'; 1367 (void)strcpy(mapout, op->mo); 1368 (void)signal(SIGINT, oldintr); 1369 if (abrtflag) { 1370 abrtflag = 0; 1371 (*oldintr)(SIGINT); 1372 } 1373 } 1374 1375 void 1376 abortpt(notused) 1377 int notused; 1378 { 1379 1380 alarmtimer(0); 1381 putc('\n', ttyout); 1382 (void)fflush(ttyout); 1383 ptabflg++; 1384 mflag = 0; 1385 abrtflag = 0; 1386 longjmp(ptabort, 1); 1387 } 1388 1389 void 1390 proxtrans(cmd, local, remote) 1391 const char *cmd, *local, *remote; 1392 { 1393 sig_t oldintr; 1394 int prox_type, nfnd; 1395 volatile int secndflag; 1396 char *cmd2; 1397 struct fd_set mask; 1398 1399 #ifdef __GNUC__ /* to shut up gcc warnings */ 1400 (void)&oldintr; 1401 (void)&cmd2; 1402 #endif 1403 1404 oldintr = NULL; 1405 secndflag = 0; 1406 if (strcmp(cmd, "RETR")) 1407 cmd2 = "RETR"; 1408 else 1409 cmd2 = runique ? "STOU" : "STOR"; 1410 if ((prox_type = type) == 0) { 1411 if (unix_server && unix_proxy) 1412 prox_type = TYPE_I; 1413 else 1414 prox_type = TYPE_A; 1415 } 1416 if (curtype != prox_type) 1417 changetype(prox_type, 1); 1418 if (command("PASV") != COMPLETE) { 1419 fputs("proxy server does not support third party transfers.\n", 1420 ttyout); 1421 return; 1422 } 1423 pswitch(0); 1424 if (!connected) { 1425 fputs("No primary connection.\n", ttyout); 1426 pswitch(1); 1427 code = -1; 1428 return; 1429 } 1430 if (curtype != prox_type) 1431 changetype(prox_type, 1); 1432 if (command("PORT %s", pasv) != COMPLETE) { 1433 pswitch(1); 1434 return; 1435 } 1436 if (setjmp(ptabort)) 1437 goto abort; 1438 oldintr = signal(SIGINT, abortpt); 1439 if (command("%s %s", cmd, remote) != PRELIM) { 1440 (void)signal(SIGINT, oldintr); 1441 pswitch(1); 1442 return; 1443 } 1444 sleep(2); 1445 pswitch(1); 1446 secndflag++; 1447 if (command("%s %s", cmd2, local) != PRELIM) 1448 goto abort; 1449 ptflag++; 1450 (void)getreply(0); 1451 pswitch(0); 1452 (void)getreply(0); 1453 (void)signal(SIGINT, oldintr); 1454 pswitch(1); 1455 ptflag = 0; 1456 fprintf(ttyout, "local: %s remote: %s\n", local, remote); 1457 return; 1458 abort: 1459 (void)signal(SIGINT, SIG_IGN); 1460 ptflag = 0; 1461 if (strcmp(cmd, "RETR") && !proxy) 1462 pswitch(1); 1463 else if (!strcmp(cmd, "RETR") && proxy) 1464 pswitch(0); 1465 if (!cpend && !secndflag) { /* only here if cmd = "STOR" (proxy=1) */ 1466 if (command("%s %s", cmd2, local) != PRELIM) { 1467 pswitch(0); 1468 if (cpend) 1469 abort_remote(NULL); 1470 } 1471 pswitch(1); 1472 if (ptabflg) 1473 code = -1; 1474 (void)signal(SIGINT, oldintr); 1475 return; 1476 } 1477 if (cpend) 1478 abort_remote(NULL); 1479 pswitch(!proxy); 1480 if (!cpend && !secndflag) { /* only if cmd = "RETR" (proxy=1) */ 1481 if (command("%s %s", cmd2, local) != PRELIM) { 1482 pswitch(0); 1483 if (cpend) 1484 abort_remote(NULL); 1485 pswitch(1); 1486 if (ptabflg) 1487 code = -1; 1488 (void)signal(SIGINT, oldintr); 1489 return; 1490 } 1491 } 1492 if (cpend) 1493 abort_remote(NULL); 1494 pswitch(!proxy); 1495 if (cpend) { 1496 FD_ZERO(&mask); 1497 FD_SET(fileno(cin), &mask); 1498 if ((nfnd = empty(&mask, 10)) <= 0) { 1499 if (nfnd < 0) { 1500 warn("abort"); 1501 } 1502 if (ptabflg) 1503 code = -1; 1504 lostpeer(); 1505 } 1506 (void)getreply(0); 1507 (void)getreply(0); 1508 } 1509 if (proxy) 1510 pswitch(0); 1511 pswitch(1); 1512 if (ptabflg) 1513 code = -1; 1514 (void)signal(SIGINT, oldintr); 1515 } 1516 1517 void 1518 reset(argc, argv) 1519 int argc; 1520 char *argv[]; 1521 { 1522 struct fd_set mask; 1523 int nfnd = 1; 1524 1525 FD_ZERO(&mask); 1526 while (nfnd > 0) { 1527 FD_SET(fileno(cin), &mask); 1528 if ((nfnd = empty(&mask, 0)) < 0) { 1529 warn("reset"); 1530 code = -1; 1531 lostpeer(); 1532 } 1533 else if (nfnd) { 1534 (void)getreply(0); 1535 } 1536 } 1537 } 1538 1539 char * 1540 gunique(local) 1541 const char *local; 1542 { 1543 static char new[MAXPATHLEN]; 1544 char *cp = strrchr(local, '/'); 1545 int d, count=0; 1546 char ext = '1'; 1547 1548 if (cp) 1549 *cp = '\0'; 1550 d = access(cp == local ? "/" : cp ? local : ".", W_OK); 1551 if (cp) 1552 *cp = '/'; 1553 if (d < 0) { 1554 warn("local: %s", local); 1555 return (NULL); 1556 } 1557 (void)strcpy(new, local); 1558 cp = new + strlen(new); 1559 *cp++ = '.'; 1560 while (!d) { 1561 if (++count == 100) { 1562 fputs("runique: can't find unique file name.\n", 1563 ttyout); 1564 return (NULL); 1565 } 1566 *cp++ = ext; 1567 *cp = '\0'; 1568 if (ext == '9') 1569 ext = '0'; 1570 else 1571 ext++; 1572 if ((d = access(new, F_OK)) < 0) 1573 break; 1574 if (ext != '0') 1575 cp--; 1576 else if (*(cp - 2) == '.') 1577 *(cp - 1) = '1'; 1578 else { 1579 *(cp - 2) = *(cp - 2) + 1; 1580 cp--; 1581 } 1582 } 1583 return (new); 1584 } 1585 1586 void 1587 abort_remote(din) 1588 FILE *din; 1589 { 1590 char buf[BUFSIZ]; 1591 int nfnd; 1592 struct fd_set mask; 1593 1594 if (cout == NULL) { 1595 warnx("Lost control connection for abort."); 1596 if (ptabflg) 1597 code = -1; 1598 lostpeer(); 1599 return; 1600 } 1601 /* 1602 * send IAC in urgent mode instead of DM because 4.3BSD places oob mark 1603 * after urgent byte rather than before as is protocol now 1604 */ 1605 sprintf(buf, "%c%c%c", IAC, IP, IAC); 1606 if (send(fileno(cout), buf, 3, MSG_OOB) != 3) 1607 warn("abort"); 1608 fprintf(cout, "%cABOR\r\n", DM); 1609 (void)fflush(cout); 1610 FD_ZERO(&mask); 1611 FD_SET(fileno(cin), &mask); 1612 if (din) { 1613 FD_SET(fileno(din), &mask); 1614 } 1615 if ((nfnd = empty(&mask, 10)) <= 0) { 1616 if (nfnd < 0) { 1617 warn("abort"); 1618 } 1619 if (ptabflg) 1620 code = -1; 1621 lostpeer(); 1622 } 1623 if (din && FD_ISSET(fileno(din), &mask)) { 1624 while (read(fileno(din), buf, BUFSIZ) > 0) 1625 /* LOOP */; 1626 } 1627 if (getreply(0) == ERROR && code == 552) { 1628 /* 552 needed for nic style abort */ 1629 (void)getreply(0); 1630 } 1631 (void)getreply(0); 1632 } 1633