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