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