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