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