Annotation of src/usr.bin/ftp/ftp.c, Revision 1.91
1.91 ! tedu 1: /* $OpenBSD: ftp.c,v 1.90 2015/01/30 04:45:45 tedu Exp $ */
1.22 millert 2: /* $NetBSD: ftp.c,v 1.27 1997/08/18 10:20:23 lukem Exp $ */
1.1 deraadt 3:
4: /*
1.34 itojun 5: * Copyright (C) 1997 and 1998 WIDE Project.
6: * All rights reserved.
7: *
8: * Redistribution and use in source and binary forms, with or without
9: * modification, are permitted provided that the following conditions
10: * are met:
11: * 1. Redistributions of source code must retain the above copyright
12: * notice, this list of conditions and the following disclaimer.
13: * 2. Redistributions in binary form must reproduce the above copyright
14: * notice, this list of conditions and the following disclaimer in the
15: * documentation and/or other materials provided with the distribution.
16: * 3. Neither the name of the project nor the names of its contributors
17: * may be used to endorse or promote products derived from this software
18: * without specific prior written permission.
19: *
20: * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
21: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23: * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
24: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30: * SUCH DAMAGE.
31: */
32:
33: /*
1.1 deraadt 34: * Copyright (c) 1985, 1989, 1993, 1994
35: * The Regents of the University of California. All rights reserved.
36: *
37: * Redistribution and use in source and binary forms, with or without
38: * modification, are permitted provided that the following conditions
39: * are met:
40: * 1. Redistributions of source code must retain the above copyright
41: * notice, this list of conditions and the following disclaimer.
42: * 2. Redistributions in binary form must reproduce the above copyright
43: * notice, this list of conditions and the following disclaimer in the
44: * documentation and/or other materials provided with the distribution.
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.34 itojun 184:
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.1 deraadt 283: if (getreply(0) > 2) { /* read startup message from server */
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: /*VARARGS*/
323: int
1.13 millert 324: command(const char *fmt, ...)
1.1 deraadt 325: {
326: va_list ap;
327: int r;
328: sig_t oldintr;
329:
330: abrtflag = 0;
1.73 martynas 331: #ifndef SMALL
1.1 deraadt 332: if (debug) {
1.18 deraadt 333: fputs("---> ", ttyout);
1.13 millert 334: va_start(ap, fmt);
1.1 deraadt 335: if (strncmp("PASS ", fmt, 5) == 0)
1.18 deraadt 336: fputs("PASS XXXX", ttyout);
1.10 millert 337: else if (strncmp("ACCT ", fmt, 5) == 0)
1.18 deraadt 338: fputs("ACCT XXXX", ttyout);
1.10 millert 339: else
1.28 millert 340: vfprintf(ttyout, fmt, ap);
1.1 deraadt 341: va_end(ap);
1.18 deraadt 342: putc('\n', ttyout);
343: (void)fflush(ttyout);
1.1 deraadt 344: }
1.73 martynas 345: #endif /* !SMALL */
1.1 deraadt 346: if (cout == NULL) {
1.13 millert 347: warnx("No control connection for command.");
1.1 deraadt 348: code = -1;
349: return (0);
350: }
351: oldintr = signal(SIGINT, cmdabort);
1.13 millert 352: va_start(ap, fmt);
1.1 deraadt 353: vfprintf(cout, fmt, ap);
354: va_end(ap);
1.11 millert 355: fputs("\r\n", cout);
356: (void)fflush(cout);
1.1 deraadt 357: cpend = 1;
358: r = getreply(!strcmp(fmt, "QUIT"));
359: if (abrtflag && oldintr != SIG_IGN)
360: (*oldintr)(SIGINT);
1.11 millert 361: (void)signal(SIGINT, oldintr);
1.1 deraadt 362: return (r);
363: }
364:
1.68 espie 365: int keep_alive_timeout = 60; /* 0 -> no timeout */
1.67 espie 366:
367: static int full_noops_sent = 0;
368: static time_t last_timestamp = 0; /* 0 -> no measurement yet */
369: static char noop[] = "NOOP\r\n";
370: #define NOOP_LENGTH (sizeof noop - 1)
371: static int current_nop_pos = 0; /* 0 -> no noop started */
372:
373: /* to achieve keep alive, we send noop one byte at a time */
1.83 deraadt 374: static void
375: send_noop_char(void)
1.67 espie 376: {
1.73 martynas 377: #ifndef SMALL
1.67 espie 378: if (debug)
379: fprintf(ttyout, "---> %c\n", noop[current_nop_pos]);
1.73 martynas 380: #endif /* !SMALL */
1.67 espie 381: fputc(noop[current_nop_pos++], cout);
382: (void)fflush(cout);
383: if (current_nop_pos >= NOOP_LENGTH) {
384: full_noops_sent++;
385: current_nop_pos = 0;
386: }
387: }
388:
1.83 deraadt 389: static void
390: may_reset_noop_timeout(void)
1.67 espie 391: {
392: if (keep_alive_timeout != 0)
393: last_timestamp = time(NULL);
394: }
395:
1.83 deraadt 396: static void
397: may_receive_noop_ack(void)
1.67 espie 398: {
399: int i;
1.74 martynas 400:
401: if (cout == NULL) {
402: /* Lost connection; so just pretend we're fine. */
403: current_nop_pos = full_noops_sent = 0;
404: return;
405: }
1.67 espie 406:
407: /* finish sending last incomplete noop */
408: if (current_nop_pos != 0) {
409: fputs(&(noop[current_nop_pos]), cout);
1.73 martynas 410: #ifndef SMALL
1.67 espie 411: if (debug)
412: fprintf(ttyout, "---> %s\n", &(noop[current_nop_pos]));
1.73 martynas 413: #endif /* !SMALL */
1.67 espie 414: (void)fflush(cout);
415: current_nop_pos = 0;
416: full_noops_sent++;
417: }
418: /* and get the replies */
419: for (i = 0; i < full_noops_sent; i++)
420: (void)getreply(0);
421:
422: full_noops_sent = 0;
423: }
424:
1.83 deraadt 425: static void
426: may_send_noop_char(void)
1.67 espie 427: {
428: if (keep_alive_timeout != 0) {
429: if (last_timestamp != 0) {
430: time_t t = time(NULL);
431:
432: if (t - last_timestamp >= keep_alive_timeout) {
433: last_timestamp = t;
434: send_noop_char();
435: }
436: } else {
437: last_timestamp = time(NULL);
438: }
439: }
440: }
441:
1.10 millert 442: char reply_string[BUFSIZ]; /* first line of previous reply */
1.1 deraadt 443:
444: int
1.56 deraadt 445: getreply(int expecteof)
1.1 deraadt 446: {
1.10 millert 447: char current_line[BUFSIZ]; /* last line of previous reply */
1.64 ray 448: int c, n, lineno;
1.1 deraadt 449: int dig;
450: int originalcode = 0, continuation = 0;
451: sig_t oldintr;
452: int pflag = 0;
453: char *cp, *pt = pasv;
454:
1.25 weingart 455: memset(current_line, 0, sizeof(current_line));
1.1 deraadt 456: oldintr = signal(SIGINT, cmdabort);
1.64 ray 457: for (lineno = 0 ;; lineno++) {
1.1 deraadt 458: dig = n = code = 0;
1.10 millert 459: cp = current_line;
1.23 millert 460: while ((c = fgetc(cin)) != '\n') {
1.1 deraadt 461: if (c == IAC) { /* handle telnet commands */
1.23 millert 462: switch (c = fgetc(cin)) {
1.1 deraadt 463: case WILL:
464: case WONT:
1.23 millert 465: c = fgetc(cin);
1.1 deraadt 466: fprintf(cout, "%c%c%c", IAC, DONT, c);
1.11 millert 467: (void)fflush(cout);
1.1 deraadt 468: break;
469: case DO:
470: case DONT:
1.23 millert 471: c = fgetc(cin);
1.1 deraadt 472: fprintf(cout, "%c%c%c", IAC, WONT, c);
1.11 millert 473: (void)fflush(cout);
1.1 deraadt 474: break;
475: default:
476: break;
477: }
478: continue;
479: }
480: dig++;
481: if (c == EOF) {
482: if (expecteof) {
1.11 millert 483: (void)signal(SIGINT, oldintr);
1.1 deraadt 484: code = 221;
485: return (0);
486: }
487: lostpeer();
488: if (verbose) {
1.18 deraadt 489: fputs(
490: "421 Service not available, remote server has closed connection.\n", ttyout);
491: (void)fflush(ttyout);
1.1 deraadt 492: }
493: code = 421;
494: return (4);
495: }
1.10 millert 496: if (c != '\r' && (verbose > 0 ||
1.71 martynas 497: ((verbose > -1 && n == '5' && dig > 4) &&
1.21 mickey 498: (((!n && c < '5') || (n && n < '5'))
1.71 martynas 499: || !retry_connect)))) {
1.1 deraadt 500: if (proxflag &&
1.10 millert 501: (dig == 1 || (dig == 5 && verbose == 0)))
1.18 deraadt 502: fprintf(ttyout, "%s:", hostname);
503: (void)putc(c, ttyout);
1.1 deraadt 504: }
505: if (dig < 4 && isdigit(c))
506: code = code * 10 + (c - '0');
1.34 itojun 507: if (!pflag && (code == 227 || code == 228))
1.1 deraadt 508: pflag = 1;
1.34 itojun 509: else if (!pflag && code == 229)
510: pflag = 100;
1.1 deraadt 511: if (dig > 4 && pflag == 1 && isdigit(c))
512: pflag = 2;
513: if (pflag == 2) {
1.44 itojun 514: if (c != '\r' && c != ')') {
515: if (pt < &pasv[sizeof(pasv) - 1])
516: *pt++ = c;
517: } else {
1.1 deraadt 518: *pt = '\0';
519: pflag = 3;
520: }
521: }
1.34 itojun 522: if (pflag == 100 && c == '(')
523: pflag = 2;
1.1 deraadt 524: if (dig == 4 && c == '-') {
525: if (continuation)
526: code = 0;
527: continuation++;
528: }
1.10 millert 529: if (n == 0)
530: n = c;
531: if (cp < ¤t_line[sizeof(current_line) - 1])
1.1 deraadt 532: *cp++ = c;
533: }
1.11 millert 534: if (verbose > 0 || ((verbose > -1 && n == '5') &&
535: (n < '5' || !retry_connect))) {
1.18 deraadt 536: (void)putc(c, ttyout);
537: (void)fflush (ttyout);
1.1 deraadt 538: }
1.64 ray 539: if (lineno == 0) {
1.10 millert 540: size_t len = cp - current_line;
541:
542: if (len > sizeof(reply_string))
543: len = sizeof(reply_string);
544:
1.48 itojun 545: (void)strlcpy(reply_string, current_line, len);
1.10 millert 546: }
1.1 deraadt 547: if (continuation && code != originalcode) {
548: if (originalcode == 0)
549: originalcode = code;
550: continue;
551: }
552: *cp = '\0';
553: if (n != '1')
554: cpend = 0;
1.11 millert 555: (void)signal(SIGINT, oldintr);
1.1 deraadt 556: if (code == 421 || originalcode == 421)
557: lostpeer();
558: if (abrtflag && oldintr != cmdabort && oldintr != SIG_IGN)
559: (*oldintr)(SIGINT);
560: return (n - '0');
561: }
562: }
563:
1.77 martynas 564: #ifndef SMALL
1.1 deraadt 565: jmp_buf sendabort;
566:
1.57 deraadt 567: /* ARGSUSED */
1.1 deraadt 568: void
1.57 deraadt 569: abortsend(int signo)
1.1 deraadt 570: {
1.87 deraadt 571: int save_errno = errno;
1.10 millert 572: alarmtimer(0);
1.1 deraadt 573: mflag = 0;
574: abrtflag = 0;
1.87 deraadt 575: #define MSG "\nsend aborted\nwaiting for remote to finish abort.\n"
576: (void) write(fileno(ttyout), MSG, strlen(MSG));
577: #undef MSG
578:
579: errno = save_errno;
1.1 deraadt 580: longjmp(sendabort, 1);
581: }
582:
583: void
1.56 deraadt 584: sendrequest(const char *cmd, const char *local, const char *remote,
585: int printnames)
1.1 deraadt 586: {
587: struct stat st;
588: int c, d;
1.40 millert 589: FILE * volatile fin, * volatile dout;
1.42 millert 590: int (* volatile closefunc)(FILE *);
1.40 millert 591: volatile sig_t oldinti, oldintr, oldintp;
1.20 millert 592: volatile off_t hashbytes;
1.40 millert 593: char * volatile lmode;
594: char buf[BUFSIZ], *bufp;
1.69 ray 595: int oprogress, serrno;
1.1 deraadt 596:
1.10 millert 597: hashbytes = mark;
598: direction = "sent";
1.20 millert 599: dout = NULL;
1.10 millert 600: bytes = 0;
601: filesize = -1;
1.13 millert 602: oprogress = progress;
1.1 deraadt 603: if (verbose && printnames) {
604: if (local && *local != '-')
1.18 deraadt 605: fprintf(ttyout, "local: %s ", local);
1.1 deraadt 606: if (remote)
1.18 deraadt 607: fprintf(ttyout, "remote: %s\n", remote);
1.1 deraadt 608: }
609: if (proxy) {
610: proxtrans(cmd, local, remote);
611: return;
612: }
613: if (curtype != type)
614: changetype(type, 0);
615: closefunc = NULL;
616: oldintr = NULL;
617: oldintp = NULL;
1.10 millert 618: oldinti = NULL;
1.1 deraadt 619: lmode = "w";
620: if (setjmp(sendabort)) {
621: while (cpend) {
1.11 millert 622: (void)getreply(0);
1.1 deraadt 623: }
624: if (data >= 0) {
1.11 millert 625: (void)close(data);
1.1 deraadt 626: data = -1;
627: }
628: if (oldintr)
1.11 millert 629: (void)signal(SIGINT, oldintr);
1.1 deraadt 630: if (oldintp)
1.11 millert 631: (void)signal(SIGPIPE, oldintp);
1.10 millert 632: if (oldinti)
1.11 millert 633: (void)signal(SIGINFO, oldinti);
1.13 millert 634: progress = oprogress;
1.1 deraadt 635: code = -1;
636: return;
637: }
638: oldintr = signal(SIGINT, abortsend);
1.10 millert 639: oldinti = signal(SIGINFO, psummary);
1.13 millert 640: if (strcmp(local, "-") == 0) {
1.1 deraadt 641: fin = stdin;
1.31 millert 642: if (progress == 1)
643: progress = 0;
1.13 millert 644: } else if (*local == '|') {
1.10 millert 645: oldintp = signal(SIGPIPE, SIG_IGN);
1.1 deraadt 646: fin = popen(local + 1, "r");
647: if (fin == NULL) {
648: warn("%s", local + 1);
1.11 millert 649: (void)signal(SIGINT, oldintr);
650: (void)signal(SIGPIPE, oldintp);
651: (void)signal(SIGINFO, oldinti);
1.1 deraadt 652: code = -1;
653: return;
654: }
1.31 millert 655: if (progress == 1)
656: progress = 0;
1.1 deraadt 657: closefunc = pclose;
658: } else {
659: fin = fopen(local, "r");
660: if (fin == NULL) {
661: warn("local: %s", local);
1.11 millert 662: (void)signal(SIGINT, oldintr);
663: (void)signal(SIGINFO, oldinti);
1.1 deraadt 664: code = -1;
665: return;
666: }
667: closefunc = fclose;
668: if (fstat(fileno(fin), &st) < 0 ||
1.14 millert 669: (st.st_mode & S_IFMT) != S_IFREG) {
1.18 deraadt 670: fprintf(ttyout, "%s: not a plain file.\n", local);
1.11 millert 671: (void)signal(SIGINT, oldintr);
672: (void)signal(SIGINFO, oldinti);
1.1 deraadt 673: fclose(fin);
674: code = -1;
675: return;
676: }
1.10 millert 677: filesize = st.st_size;
1.1 deraadt 678: }
679: if (initconn()) {
1.11 millert 680: (void)signal(SIGINT, oldintr);
681: (void)signal(SIGINFO, oldinti);
1.1 deraadt 682: if (oldintp)
1.11 millert 683: (void)signal(SIGPIPE, oldintp);
1.1 deraadt 684: code = -1;
1.13 millert 685: progress = oprogress;
1.1 deraadt 686: if (closefunc != NULL)
687: (*closefunc)(fin);
688: return;
689: }
690: if (setjmp(sendabort))
691: goto abort;
692:
693: if (restart_point &&
694: (strcmp(cmd, "STOR") == 0 || strcmp(cmd, "APPE") == 0)) {
1.59 deraadt 695: int rc = -1;
1.1 deraadt 696:
697: switch (curtype) {
698: case TYPE_A:
1.58 sturm 699: rc = fseeko(fin, restart_point, SEEK_SET);
1.1 deraadt 700: break;
701: case TYPE_I:
1.59 deraadt 702: if (lseek(fileno(fin), restart_point, SEEK_SET) != -1)
703: rc = 0;
1.1 deraadt 704: break;
705: }
1.59 deraadt 706: if (rc == -1) {
1.1 deraadt 707: warn("local: %s", local);
1.13 millert 708: progress = oprogress;
1.1 deraadt 709: if (closefunc != NULL)
710: (*closefunc)(fin);
711: return;
712: }
1.58 sturm 713: if (command("REST %lld", (long long) restart_point)
1.1 deraadt 714: != CONTINUE) {
1.13 millert 715: progress = oprogress;
1.1 deraadt 716: if (closefunc != NULL)
717: (*closefunc)(fin);
718: return;
719: }
720: lmode = "r+w";
721: }
722: if (remote) {
723: if (command("%s %s", cmd, remote) != PRELIM) {
1.11 millert 724: (void)signal(SIGINT, oldintr);
725: (void)signal(SIGINFO, oldinti);
1.13 millert 726: progress = oprogress;
1.1 deraadt 727: if (oldintp)
1.11 millert 728: (void)signal(SIGPIPE, oldintp);
1.1 deraadt 729: if (closefunc != NULL)
730: (*closefunc)(fin);
731: return;
732: }
733: } else
734: if (command("%s", cmd) != PRELIM) {
1.11 millert 735: (void)signal(SIGINT, oldintr);
736: (void)signal(SIGINFO, oldinti);
1.13 millert 737: progress = oprogress;
1.1 deraadt 738: if (oldintp)
1.11 millert 739: (void)signal(SIGPIPE, oldintp);
1.1 deraadt 740: if (closefunc != NULL)
741: (*closefunc)(fin);
742: return;
743: }
744: dout = dataconn(lmode);
745: if (dout == NULL)
746: goto abort;
1.75 martynas 747: progressmeter(-1, remote);
1.67 espie 748: may_reset_noop_timeout();
1.1 deraadt 749: oldintp = signal(SIGPIPE, SIG_IGN);
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.1 deraadt 1059: switch (curtype) {
1060:
1061: case TYPE_I:
1062: if (restart_point &&
1063: lseek(fileno(fout), restart_point, SEEK_SET) < 0) {
1064: warn("local: %s", local);
1.13 millert 1065: progress = oprogress;
1.16 millert 1066: preserve = opreserve;
1.1 deraadt 1067: if (closefunc != NULL)
1068: (*closefunc)(fout);
1069: return;
1070: }
1071: errno = d = 0;
1072: while ((c = read(fileno(din), buf, bufsize)) > 0) {
1.57 deraadt 1073: ssize_t wr;
1.32 deraadt 1074: size_t rd = c;
1075:
1.67 espie 1076: may_send_noop_char();
1.32 deraadt 1077: d = 0;
1078: do {
1079: wr = write(fileno(fout), buf + d, rd);
1.84 jca 1080: if (wr == -1) {
1081: d = -1;
1.32 deraadt 1082: break;
1.84 jca 1083: }
1.32 deraadt 1084: d += wr;
1085: rd -= wr;
1086: } while (d < c);
1087: if (rd != 0)
1.1 deraadt 1088: break;
1089: bytes += c;
1.10 millert 1090: if (hash && (!progress || filesize < 0)) {
1.1 deraadt 1091: while (bytes >= hashbytes) {
1.18 deraadt 1092: (void)putc('#', ttyout);
1.7 kstailey 1093: hashbytes += mark;
1.1 deraadt 1094: }
1.18 deraadt 1095: (void)fflush(ttyout);
1.1 deraadt 1096: }
1097: }
1.69 ray 1098: if (c == -1 || d < c)
1099: serrno = errno;
1.10 millert 1100: if (hash && (!progress || filesize < 0) && bytes > 0) {
1.7 kstailey 1101: if (bytes < mark)
1.18 deraadt 1102: (void)putc('#', ttyout);
1103: (void)putc('\n', ttyout);
1104: (void)fflush(ttyout);
1.1 deraadt 1105: }
1106: if (c < 0) {
1.69 ray 1107: if (serrno != EPIPE)
1.86 guenther 1108: warnc(serrno, "netin");
1.1 deraadt 1109: bytes = -1;
1110: }
1111: if (d < c) {
1112: if (d < 0)
1.86 guenther 1113: warnc(serrno, "local: %s", local);
1.1 deraadt 1114: else
1115: warnx("%s: short write", local);
1116: }
1117: break;
1118:
1119: case TYPE_A:
1120: if (restart_point) {
1121: int i, n, ch;
1122:
1123: if (fseek(fout, 0L, SEEK_SET) < 0)
1124: goto done;
1125: n = restart_point;
1126: for (i = 0; i++ < n;) {
1.69 ray 1127: if ((ch = fgetc(fout)) == EOF) {
1128: if (!ferror(fout))
1129: errno = 0;
1.1 deraadt 1130: goto done;
1.69 ray 1131: }
1.1 deraadt 1132: if (ch == '\n')
1133: i++;
1134: }
1135: if (fseek(fout, 0L, SEEK_CUR) < 0) {
1136: done:
1.69 ray 1137: if (errno)
1138: warn("local: %s", local);
1139: else
1140: warnx("local: %s", local);
1.13 millert 1141: progress = oprogress;
1.16 millert 1142: preserve = opreserve;
1.1 deraadt 1143: if (closefunc != NULL)
1144: (*closefunc)(fout);
1145: return;
1146: }
1147: }
1.23 millert 1148: while ((c = fgetc(din)) != EOF) {
1.67 espie 1149: may_send_noop_char();
1.1 deraadt 1150: if (c == '\n')
1151: bare_lfs++;
1152: while (c == '\r') {
1.10 millert 1153: while (hash && (!progress || filesize < 0) &&
1154: (bytes >= hashbytes)) {
1.18 deraadt 1155: (void)putc('#', ttyout);
1156: (void)fflush(ttyout);
1.7 kstailey 1157: hashbytes += mark;
1.1 deraadt 1158: }
1159: bytes++;
1.23 millert 1160: if ((c = fgetc(din)) != '\n' || tcrflag) {
1.1 deraadt 1161: if (ferror(fout))
1162: goto break2;
1.11 millert 1163: (void)putc('\r', fout);
1.1 deraadt 1164: if (c == '\0') {
1165: bytes++;
1166: goto contin2;
1167: }
1168: if (c == EOF)
1169: goto contin2;
1170: }
1171: }
1.11 millert 1172: (void)putc(c, fout);
1.1 deraadt 1173: bytes++;
1174: contin2: ;
1175: }
1176: break2:
1.69 ray 1177: if (ferror(din) || ferror(fout))
1178: serrno = errno;
1.1 deraadt 1179: if (bare_lfs) {
1.22 millert 1180: fprintf(ttyout,
1.13 millert 1181: "WARNING! %d bare linefeeds received in ASCII mode.\n", bare_lfs);
1.22 millert 1182: fputs("File may not have transferred correctly.\n",
1183: ttyout);
1.1 deraadt 1184: }
1.10 millert 1185: if (hash && (!progress || filesize < 0)) {
1.1 deraadt 1186: if (bytes < hashbytes)
1.18 deraadt 1187: (void)putc('#', ttyout);
1188: (void)putc('\n', ttyout);
1189: (void)fflush(ttyout);
1.1 deraadt 1190: }
1191: if (ferror(din)) {
1.69 ray 1192: if (serrno != EPIPE)
1.86 guenther 1193: warnc(serrno, "netin");
1.1 deraadt 1194: bytes = -1;
1195: }
1196: if (ferror(fout))
1.86 guenther 1197: warnc(serrno, "local: %s", local);
1.1 deraadt 1198: break;
1199: }
1.75 martynas 1200: progressmeter(1, NULL);
1.13 millert 1201: progress = oprogress;
1.16 millert 1202: preserve = opreserve;
1.1 deraadt 1203: if (closefunc != NULL)
1204: (*closefunc)(fout);
1.11 millert 1205: (void)signal(SIGINT, oldintr);
1206: (void)signal(SIGINFO, oldinti);
1.1 deraadt 1207: if (oldintp)
1.11 millert 1208: (void)signal(SIGPIPE, oldintp);
1209: (void)fclose(din);
1210: (void)getreply(0);
1.67 espie 1211: may_receive_noop_ack();
1.10 millert 1212: if (bytes >= 0 && is_retr) {
1213: if (bytes > 0)
1214: ptransfer(0);
1215: if (preserve && (closefunc == fclose)) {
1216: mtime = remotemodtime(remote, 0);
1217: if (mtime != -1) {
1.12 millert 1218: struct utimbuf ut;
1219:
1220: ut.actime = time(NULL);
1221: ut.modtime = mtime;
1222: if (utime(local, &ut) == -1)
1.22 millert 1223: fprintf(ttyout,
1.13 millert 1224: "Can't change modification time on %s to %s",
1.11 millert 1225: local, asctime(localtime(&mtime)));
1.10 millert 1226: }
1227: }
1228: }
1.1 deraadt 1229: return;
1.13 millert 1230:
1.1 deraadt 1231: abort:
1.79 martynas 1232: /* abort using RFC959 recommended IP,SYNC sequence */
1.13 millert 1233: progress = oprogress;
1.16 millert 1234: preserve = opreserve;
1.1 deraadt 1235: if (oldintp)
1.11 millert 1236: (void)signal(SIGPIPE, oldintp);
1237: (void)signal(SIGINT, SIG_IGN);
1.1 deraadt 1238: if (!cpend) {
1239: code = -1;
1.11 millert 1240: (void)signal(SIGINT, oldintr);
1241: (void)signal(SIGINFO, oldinti);
1.1 deraadt 1242: return;
1243: }
1244:
1245: abort_remote(din);
1246: code = -1;
1247: if (data >= 0) {
1.11 millert 1248: (void)close(data);
1.1 deraadt 1249: data = -1;
1250: }
1251: if (closefunc != NULL && fout != NULL)
1252: (*closefunc)(fout);
1253: if (din)
1.11 millert 1254: (void)fclose(din);
1.1 deraadt 1255: if (bytes > 0)
1.10 millert 1256: ptransfer(0);
1.11 millert 1257: (void)signal(SIGINT, oldintr);
1258: (void)signal(SIGINFO, oldinti);
1.1 deraadt 1259: }
1260:
1261: /*
1262: * Need to start a listen on the data channel before we send the command,
1263: * otherwise the server's connect may fail.
1264: */
1265: int
1.56 deraadt 1266: initconn(void)
1.1 deraadt 1267: {
1268: char *p, *a;
1.57 deraadt 1269: int result = ERROR, tmpno = 0;
1.1 deraadt 1270: int on = 1;
1.34 itojun 1271: int error;
1272: u_int addr[16], port[2];
1273: u_int af, hal, pal;
1274: char *pasvcmd = NULL;
1.57 deraadt 1275: socklen_t namelen;
1.82 haesbaer 1276: struct addrinfo *ares;
1.34 itojun 1277:
1278: if (myctladdr.su_family == AF_INET6
1279: && (IN6_IS_ADDR_LINKLOCAL(&myctladdr.su_sin6.sin6_addr)
1280: || IN6_IS_ADDR_SITELOCAL(&myctladdr.su_sin6.sin6_addr))) {
1281: warnx("use of scoped address can be troublesome");
1282: }
1.82 haesbaer 1283: #ifndef SMALL
1284: if (srcaddr) {
1285: struct addrinfo ahints;
1286:
1287: memset(&ahints, 0, sizeof(ahints));
1288: ahints.ai_family = family;
1289: ahints.ai_socktype = SOCK_STREAM;
1290: ahints.ai_flags |= AI_NUMERICHOST;
1291: ahints.ai_protocol = 0;
1292:
1293: error = getaddrinfo(srcaddr, NULL, &ahints, &ares);
1294: if (error) {
1.86 guenther 1295: warnx("%s: %s", srcaddr, gai_strerror(error));
1.82 haesbaer 1296: code = -1;
1297: return (0);
1298: }
1299: }
1300: #endif /* !SMALL */
1.24 millert 1301: reinit:
1.1 deraadt 1302: if (passivemode) {
1.34 itojun 1303: data_addr = myctladdr;
1304: data = socket(data_addr.su_family, SOCK_STREAM, 0);
1.1 deraadt 1305: if (data < 0) {
1.10 millert 1306: warn("socket");
1307: return (1);
1.1 deraadt 1308: }
1.73 martynas 1309: #ifndef SMALL
1.82 haesbaer 1310: if (srcaddr) {
1311: if (bind(data, ares->ai_addr, ares->ai_addrlen) < 0) {
1312: warn("bind");
1313: close(data);
1314: return (1);
1315: }
1316: }
1.1 deraadt 1317: if ((options & SO_DEBUG) &&
1318: setsockopt(data, SOL_SOCKET, SO_DEBUG, (char *)&on,
1.11 millert 1319: sizeof(on)) < 0)
1.10 millert 1320: warn("setsockopt (ignored)");
1.73 martynas 1321: #endif /* !SMALL */
1.34 itojun 1322: switch (data_addr.su_family) {
1323: case AF_INET:
1.36 itojun 1324: if (epsv4 && !epsv4bad) {
1.66 beck 1325: int ov;
1326: /* shut this command up in case it fails */
1327: ov = verbose;
1328: verbose = -1;
1.36 itojun 1329: result = command(pasvcmd = "EPSV");
1.66 beck 1330: /*
1331: * now back to whatever verbosity we had before
1332: * and we can try PASV
1333: */
1334: verbose = ov;
1.36 itojun 1335: if (code / 10 == 22 && code != 229) {
1336: fputs(
1.34 itojun 1337: "wrong server: return code must be 229\n",
1.36 itojun 1338: ttyout);
1339: result = COMPLETE + 1;
1340: }
1341: if (result != COMPLETE) {
1342: epsv4bad = 1;
1.73 martynas 1343: #ifndef SMALL
1.36 itojun 1344: if (debug) {
1345: fputs(
1346: "disabling epsv4 for this connection\n",
1347: ttyout);
1348: }
1.73 martynas 1349: #endif /* !SMALL */
1.36 itojun 1350: }
1.34 itojun 1351: }
1352: if (result != COMPLETE)
1353: result = command(pasvcmd = "PASV");
1354: break;
1355: case AF_INET6:
1356: result = command(pasvcmd = "EPSV");
1357: if (code / 10 == 22 && code != 229) {
1358: fputs(
1359: "wrong server: return code must be 229\n",
1360: ttyout);
1361: result = COMPLETE + 1;
1362: }
1363: if (result != COMPLETE)
1364: result = command(pasvcmd = "LPSV");
1365: break;
1366: default:
1367: result = COMPLETE + 1;
1368: break;
1369: }
1370: if (result != COMPLETE) {
1.24 millert 1371: if (activefallback) {
1372: (void)close(data);
1373: data = -1;
1374: passivemode = 0;
1375: activefallback = 0;
1376: goto reinit;
1377: }
1.18 deraadt 1378: fputs("Passive mode refused.\n", ttyout);
1.1 deraadt 1379: goto bad;
1380: }
1381:
1.34 itojun 1382: #define pack2(var, off) \
1383: (((var[(off) + 0] & 0xff) << 8) | ((var[(off) + 1] & 0xff) << 0))
1384: #define pack4(var, off) \
1385: (((var[(off) + 0] & 0xff) << 24) | ((var[(off) + 1] & 0xff) << 16) | \
1386: ((var[(off) + 2] & 0xff) << 8) | ((var[(off) + 3] & 0xff) << 0))
1387:
1.1 deraadt 1388: /*
1.34 itojun 1389: * What we've got at this point is a string of comma separated
1390: * one-byte unsigned integer values, separated by commas.
1.1 deraadt 1391: */
1.38 millert 1392: if (!pasvcmd)
1393: goto bad;
1.34 itojun 1394: if (strcmp(pasvcmd, "PASV") == 0) {
1395: if (data_addr.su_family != AF_INET) {
1396: fputs(
1397: "Passive mode AF mismatch. Shouldn't happen!\n", ttyout);
1398: goto bad;
1399: }
1400: if (code / 10 == 22 && code != 227) {
1401: fputs("wrong server: return code must be 227\n",
1402: ttyout);
1403: goto bad;
1404: }
1405: error = sscanf(pasv, "%u,%u,%u,%u,%u,%u",
1406: &addr[0], &addr[1], &addr[2], &addr[3],
1407: &port[0], &port[1]);
1408: if (error != 6) {
1409: fputs(
1410: "Passive mode address scan failure. Shouldn't happen!\n", ttyout);
1411: goto bad;
1412: }
1413: memset(&data_addr, 0, sizeof(data_addr));
1414: data_addr.su_family = AF_INET;
1415: data_addr.su_len = sizeof(struct sockaddr_in);
1416: data_addr.su_sin.sin_addr.s_addr =
1417: htonl(pack4(addr, 0));
1418: data_addr.su_port = htons(pack2(port, 0));
1419: } else if (strcmp(pasvcmd, "LPSV") == 0) {
1420: if (code / 10 == 22 && code != 228) {
1421: fputs("wrong server: return code must be 228\n",
1422: ttyout);
1423: goto bad;
1424: }
1425: switch (data_addr.su_family) {
1426: case AF_INET:
1427: error = sscanf(pasv,
1428: "%u,%u,%u,%u,%u,%u,%u,%u,%u",
1429: &af, &hal,
1430: &addr[0], &addr[1], &addr[2], &addr[3],
1431: &pal, &port[0], &port[1]);
1432: if (error != 9) {
1433: fputs(
1434: "Passive mode address scan failure. Shouldn't happen!\n", ttyout);
1435: goto bad;
1436: }
1437: if (af != 4 || hal != 4 || pal != 2) {
1438: fputs(
1439: "Passive mode AF mismatch. Shouldn't happen!\n", ttyout);
1440: error = 1;
1441: goto bad;
1442: }
1.1 deraadt 1443:
1.34 itojun 1444: memset(&data_addr, 0, sizeof(data_addr));
1445: data_addr.su_family = AF_INET;
1446: data_addr.su_len = sizeof(struct sockaddr_in);
1447: data_addr.su_sin.sin_addr.s_addr =
1448: htonl(pack4(addr, 0));
1449: data_addr.su_port = htons(pack2(port, 0));
1450: break;
1451: case AF_INET6:
1452: error = sscanf(pasv,
1453: "%u,%u,%u,%u,%u,%u,%u,%u,%u,%u,%u,%u,%u,%u,%u,%u,%u,%u,%u,%u,%u",
1454: &af, &hal,
1455: &addr[0], &addr[1], &addr[2], &addr[3],
1456: &addr[4], &addr[5], &addr[6], &addr[7],
1457: &addr[8], &addr[9], &addr[10],
1458: &addr[11], &addr[12], &addr[13],
1459: &addr[14], &addr[15],
1460: &pal, &port[0], &port[1]);
1461: if (error != 21) {
1462: fputs(
1.18 deraadt 1463: "Passive mode address scan failure. Shouldn't happen!\n", ttyout);
1.34 itojun 1464: goto bad;
1465: }
1466: if (af != 6 || hal != 16 || pal != 2) {
1467: fputs(
1468: "Passive mode AF mismatch. Shouldn't happen!\n", ttyout);
1469: goto bad;
1470: }
1471:
1472: memset(&data_addr, 0, sizeof(data_addr));
1473: data_addr.su_family = AF_INET6;
1474: data_addr.su_len = sizeof(struct sockaddr_in6);
1475: {
1476: u_int32_t *p32;
1477: p32 = (u_int32_t *)&data_addr.su_sin6.sin6_addr;
1478: p32[0] = htonl(pack4(addr, 0));
1479: p32[1] = htonl(pack4(addr, 4));
1480: p32[2] = htonl(pack4(addr, 8));
1481: p32[3] = htonl(pack4(addr, 12));
1482: }
1483: data_addr.su_port = htons(pack2(port, 0));
1484: break;
1485: default:
1.85 tedu 1486: fputs("Bad family!\n", ttyout);
1487: goto bad;
1.34 itojun 1488: }
1489: } else if (strcmp(pasvcmd, "EPSV") == 0) {
1490: char delim[4];
1491:
1492: port[0] = 0;
1493: if (code / 10 == 22 && code != 229) {
1494: fputs("wrong server: return code must be 229\n",
1495: ttyout);
1496: goto bad;
1497: }
1498: if (sscanf(pasv, "%c%c%c%d%c", &delim[0],
1499: &delim[1], &delim[2], &port[1],
1500: &delim[3]) != 5) {
1501: fputs("parse error!\n", ttyout);
1502: goto bad;
1503: }
1504: if (delim[0] != delim[1] || delim[0] != delim[2]
1505: || delim[0] != delim[3]) {
1506: fputs("parse error!\n", ttyout);
1507: goto bad;
1508: }
1509: data_addr = hisctladdr;
1510: data_addr.su_port = htons(port[1]);
1511: } else
1.1 deraadt 1512: goto bad;
1513:
1.27 deraadt 1514: while (connect(data, (struct sockaddr *)&data_addr,
1.34 itojun 1515: data_addr.su_len) < 0) {
1.27 deraadt 1516: if (errno == EINTR)
1517: continue;
1.33 millert 1518: if (activefallback) {
1519: (void)close(data);
1520: data = -1;
1521: passivemode = 0;
1522: activefallback = 0;
1523: goto reinit;
1524: }
1.10 millert 1525: warn("connect");
1.1 deraadt 1526: goto bad;
1527: }
1.34 itojun 1528: if (data_addr.su_family == AF_INET) {
1529: on = IPTOS_THROUGHPUT;
1530: if (setsockopt(data, IPPROTO_IP, IP_TOS, (char *)&on,
1531: sizeof(int)) < 0)
1532: warn("setsockopt TOS (ignored)");
1533: }
1.10 millert 1534: return (0);
1.1 deraadt 1535: }
1536:
1537: noport:
1538: data_addr = myctladdr;
1539: if (sendport)
1.34 itojun 1540: data_addr.su_port = 0; /* let system pick one */
1.1 deraadt 1541: if (data != -1)
1.11 millert 1542: (void)close(data);
1.34 itojun 1543: data = socket(data_addr.su_family, SOCK_STREAM, 0);
1.1 deraadt 1544: if (data < 0) {
1545: warn("socket");
1546: if (tmpno)
1547: sendport = 1;
1548: return (1);
1549: }
1550: if (!sendport)
1.10 millert 1551: if (setsockopt(data, SOL_SOCKET, SO_REUSEADDR, (char *)&on,
1.11 millert 1552: sizeof(on)) < 0) {
1.1 deraadt 1553: warn("setsockopt (reuse address)");
1554: goto bad;
1555: }
1.49 jakob 1556: switch (data_addr.su_family) {
1557: case AF_INET:
1558: on = IP_PORTRANGE_HIGH;
1559: if (setsockopt(data, IPPROTO_IP, IP_PORTRANGE,
1560: (char *)&on, sizeof(on)) < 0)
1561: warn("setsockopt IP_PORTRANGE (ignored)");
1562: break;
1563: case AF_INET6:
1564: on = IPV6_PORTRANGE_HIGH;
1565: if (setsockopt(data, IPPROTO_IPV6, IPV6_PORTRANGE,
1566: (char *)&on, sizeof(on)) < 0)
1567: warn("setsockopt IPV6_PORTRANGE (ignored)");
1568: break;
1569: }
1.34 itojun 1570: if (bind(data, (struct sockaddr *)&data_addr, data_addr.su_len) < 0) {
1.1 deraadt 1571: warn("bind");
1572: goto bad;
1573: }
1.73 martynas 1574: #ifndef SMALL
1.1 deraadt 1575: if (options & SO_DEBUG &&
1.10 millert 1576: setsockopt(data, SOL_SOCKET, SO_DEBUG, (char *)&on,
1.11 millert 1577: sizeof(on)) < 0)
1.1 deraadt 1578: warn("setsockopt (ignored)");
1.73 martynas 1579: #endif /* !SMALL */
1.57 deraadt 1580: namelen = sizeof(data_addr);
1581: if (getsockname(data, (struct sockaddr *)&data_addr, &namelen) < 0) {
1.1 deraadt 1582: warn("getsockname");
1583: goto bad;
1584: }
1585: if (listen(data, 1) < 0)
1586: warn("listen");
1.34 itojun 1587:
1588: #define UC(b) (((int)b)&0xff)
1589:
1.1 deraadt 1590: if (sendport) {
1.47 itojun 1591: char hname[NI_MAXHOST], pbuf[NI_MAXSERV];
1.64 ray 1592: int af_tmp;
1.47 itojun 1593: union sockunion tmp;
1.34 itojun 1594:
1.47 itojun 1595: tmp = data_addr;
1596: switch (tmp.su_family) {
1.34 itojun 1597: case AF_INET:
1.36 itojun 1598: if (!epsv4 || epsv4bad) {
1599: result = COMPLETE +1;
1600: break;
1601: }
1602: /*FALLTHROUGH*/
1.34 itojun 1603: case AF_INET6:
1.47 itojun 1604: if (tmp.su_family == AF_INET6)
1605: tmp.su_sin6.sin6_scope_id = 0;
1.64 ray 1606: af_tmp = (tmp.su_family == AF_INET) ? 1 : 2;
1.47 itojun 1607: if (getnameinfo((struct sockaddr *)&tmp,
1608: tmp.su_len, hname, sizeof(hname),
1609: pbuf, sizeof(pbuf), NI_NUMERICHOST | NI_NUMERICSERV)) {
1.34 itojun 1610: result = ERROR;
1611: } else {
1.47 itojun 1612: result = command("EPRT |%d|%s|%s|",
1.64 ray 1613: af_tmp, hname, pbuf);
1.36 itojun 1614: if (result != COMPLETE) {
1615: epsv4bad = 1;
1.73 martynas 1616: #ifndef SMALL
1.36 itojun 1617: if (debug) {
1618: fputs(
1619: "disabling epsv4 for this connection\n",
1620: ttyout);
1621: }
1.73 martynas 1622: #endif /* !SMALL */
1.36 itojun 1623: }
1.34 itojun 1624: }
1625: break;
1626: default:
1627: result = COMPLETE + 1;
1628: break;
1629: }
1630: if (result == COMPLETE)
1631: goto skip_port;
1632:
1633: switch (data_addr.su_family) {
1634: case AF_INET:
1635: a = (char *)&data_addr.su_sin.sin_addr;
1636: p = (char *)&data_addr.su_port;
1637: result = command("PORT %d,%d,%d,%d,%d,%d",
1638: UC(a[0]), UC(a[1]), UC(a[2]), UC(a[3]),
1639: UC(p[0]), UC(p[1]));
1640: break;
1641: case AF_INET6:
1642: a = (char *)&data_addr.su_sin6.sin6_addr;
1643: p = (char *)&data_addr.su_port;
1644: result = command(
1645: "LPRT %d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d",
1646: 6, 16,
1647: UC(a[0]),UC(a[1]),UC(a[2]),UC(a[3]),
1648: UC(a[4]),UC(a[5]),UC(a[6]),UC(a[7]),
1649: UC(a[8]),UC(a[9]),UC(a[10]),UC(a[11]),
1650: UC(a[12]),UC(a[13]),UC(a[14]),UC(a[15]),
1651: 2, UC(p[0]), UC(p[1]));
1652: break;
1653: default:
1654: result = COMPLETE + 1; /* xxx */
1655: }
1656: skip_port:
1657:
1.1 deraadt 1658: if (result == ERROR && sendport == -1) {
1659: sendport = 0;
1660: tmpno = 1;
1661: goto noport;
1662: }
1663: return (result != COMPLETE);
1664: }
1665: if (tmpno)
1666: sendport = 1;
1.34 itojun 1667: if (data_addr.su_family == AF_INET) {
1668: on = IPTOS_THROUGHPUT;
1669: if (setsockopt(data, IPPROTO_IP, IP_TOS, (char *)&on,
1670: sizeof(int)) < 0)
1671: warn("setsockopt TOS (ignored)");
1672: }
1.1 deraadt 1673: return (0);
1674: bad:
1.11 millert 1675: (void)close(data), data = -1;
1.1 deraadt 1676: if (tmpno)
1677: sendport = 1;
1678: return (1);
1679: }
1680:
1681: FILE *
1.56 deraadt 1682: dataconn(const char *lmode)
1.1 deraadt 1683: {
1.34 itojun 1684: union sockunion from;
1.57 deraadt 1685: socklen_t fromlen = myctladdr.su_len;
1686: int s;
1.1 deraadt 1687:
1688: if (passivemode)
1689: return (fdopen(data, lmode));
1690:
1691: s = accept(data, (struct sockaddr *) &from, &fromlen);
1692: if (s < 0) {
1693: warn("accept");
1.11 millert 1694: (void)close(data), data = -1;
1.1 deraadt 1695: return (NULL);
1696: }
1.11 millert 1697: (void)close(data);
1.1 deraadt 1698: data = s;
1.34 itojun 1699: if (from.su_family == AF_INET) {
1700: int tos = IPTOS_THROUGHPUT;
1701: if (setsockopt(s, IPPROTO_IP, IP_TOS, (char *)&tos,
1702: sizeof(int)) < 0) {
1703: warn("setsockopt TOS (ignored)");
1704: }
1705: }
1.1 deraadt 1706: return (fdopen(data, lmode));
1707: }
1708:
1.57 deraadt 1709: /* ARGSUSED */
1.1 deraadt 1710: void
1.57 deraadt 1711: psummary(int signo)
1.1 deraadt 1712: {
1.26 deraadt 1713: int save_errno = errno;
1.10 millert 1714:
1715: if (bytes > 0)
1716: ptransfer(1);
1.26 deraadt 1717: errno = save_errno;
1.1 deraadt 1718: }
1719:
1.57 deraadt 1720: /* ARGSUSED */
1.1 deraadt 1721: void
1.57 deraadt 1722: psabort(int signo)
1.1 deraadt 1723: {
1724:
1.10 millert 1725: alarmtimer(0);
1.1 deraadt 1726: abrtflag++;
1727: }
1728:
1729: void
1.56 deraadt 1730: pswitch(int flag)
1.1 deraadt 1731: {
1732: sig_t oldintr;
1733: static struct comvars {
1734: int connect;
1.89 deraadt 1735: char name[HOST_NAME_MAX+1];
1.34 itojun 1736: union sockunion mctl;
1737: union sockunion hctl;
1.1 deraadt 1738: FILE *in;
1739: FILE *out;
1740: int tpe;
1741: int curtpe;
1742: int cpnd;
1743: int sunqe;
1744: int runqe;
1745: int mcse;
1746: int ntflg;
1747: char nti[17];
1748: char nto[17];
1749: int mapflg;
1.89 deraadt 1750: char mi[PATH_MAX];
1751: char mo[PATH_MAX];
1.1 deraadt 1752: } proxstruct, tmpstruct;
1753: struct comvars *ip, *op;
1754:
1755: abrtflag = 0;
1756: oldintr = signal(SIGINT, psabort);
1757: if (flag) {
1758: if (proxy)
1759: return;
1760: ip = &tmpstruct;
1761: op = &proxstruct;
1762: proxy++;
1763: } else {
1764: if (!proxy)
1765: return;
1766: ip = &proxstruct;
1767: op = &tmpstruct;
1768: proxy = 0;
1769: }
1770: ip->connect = connected;
1771: connected = op->connect;
1772: if (hostname) {
1.41 lebel 1773: (void)strlcpy(ip->name, hostname, sizeof(ip->name));
1.1 deraadt 1774: } else
1.11 millert 1775: ip->name[0] = '\0';
1.1 deraadt 1776: hostname = op->name;
1777: ip->hctl = hisctladdr;
1778: hisctladdr = op->hctl;
1779: ip->mctl = myctladdr;
1780: myctladdr = op->mctl;
1781: ip->in = cin;
1782: cin = op->in;
1783: ip->out = cout;
1784: cout = op->out;
1785: ip->tpe = type;
1786: type = op->tpe;
1787: ip->curtpe = curtype;
1788: curtype = op->curtpe;
1789: ip->cpnd = cpend;
1790: cpend = op->cpnd;
1791: ip->sunqe = sunique;
1792: sunique = op->sunqe;
1793: ip->runqe = runique;
1794: runique = op->runqe;
1795: ip->mcse = mcase;
1796: mcase = op->mcse;
1797: ip->ntflg = ntflag;
1798: ntflag = op->ntflg;
1.41 lebel 1799: (void)strlcpy(ip->nti, ntin, sizeof(ip->nti));
1.52 deraadt 1800: (void)strlcpy(ntin, op->nti, sizeof ntin);
1.41 lebel 1801: (void)strlcpy(ip->nto, ntout, sizeof(ip->nto));
1.52 deraadt 1802: (void)strlcpy(ntout, op->nto, sizeof ntout);
1.1 deraadt 1803: ip->mapflg = mapflag;
1804: mapflag = op->mapflg;
1.41 lebel 1805: (void)strlcpy(ip->mi, mapin, sizeof(ip->mi));
1.52 deraadt 1806: (void)strlcpy(mapin, op->mi, sizeof mapin);
1.41 lebel 1807: (void)strlcpy(ip->mo, mapout, sizeof(ip->mo));
1.52 deraadt 1808: (void)strlcpy(mapout, op->mo, sizeof mapout);
1.11 millert 1809: (void)signal(SIGINT, oldintr);
1.1 deraadt 1810: if (abrtflag) {
1811: abrtflag = 0;
1812: (*oldintr)(SIGINT);
1813: }
1814: }
1815:
1.57 deraadt 1816: /* ARGSUSED */
1.1 deraadt 1817: void
1.57 deraadt 1818: abortpt(int signo)
1.1 deraadt 1819: {
1820:
1.10 millert 1821: alarmtimer(0);
1.18 deraadt 1822: putc('\n', ttyout);
1823: (void)fflush(ttyout);
1.1 deraadt 1824: ptabflg++;
1825: mflag = 0;
1826: abrtflag = 0;
1827: longjmp(ptabort, 1);
1828: }
1829:
1830: void
1.56 deraadt 1831: proxtrans(const char *cmd, const char *local, const char *remote)
1.1 deraadt 1832: {
1.40 millert 1833: volatile sig_t oldintr;
1.20 millert 1834: int prox_type, nfnd;
1835: volatile int secndflag;
1.40 millert 1836: char * volatile cmd2;
1.54 millert 1837: struct pollfd pfd[1];
1.20 millert 1838:
1839: oldintr = NULL;
1840: secndflag = 0;
1.1 deraadt 1841: if (strcmp(cmd, "RETR"))
1842: cmd2 = "RETR";
1843: else
1844: cmd2 = runique ? "STOU" : "STOR";
1845: if ((prox_type = type) == 0) {
1846: if (unix_server && unix_proxy)
1847: prox_type = TYPE_I;
1848: else
1849: prox_type = TYPE_A;
1850: }
1851: if (curtype != prox_type)
1852: changetype(prox_type, 1);
1853: if (command("PASV") != COMPLETE) {
1.18 deraadt 1854: fputs("proxy server does not support third party transfers.\n",
1855: ttyout);
1.1 deraadt 1856: return;
1857: }
1858: pswitch(0);
1859: if (!connected) {
1.18 deraadt 1860: fputs("No primary connection.\n", ttyout);
1.1 deraadt 1861: pswitch(1);
1862: code = -1;
1863: return;
1864: }
1865: if (curtype != prox_type)
1866: changetype(prox_type, 1);
1867: if (command("PORT %s", pasv) != COMPLETE) {
1868: pswitch(1);
1869: return;
1870: }
1871: if (setjmp(ptabort))
1872: goto abort;
1873: oldintr = signal(SIGINT, abortpt);
1874: if (command("%s %s", cmd, remote) != PRELIM) {
1.11 millert 1875: (void)signal(SIGINT, oldintr);
1.1 deraadt 1876: pswitch(1);
1877: return;
1878: }
1879: sleep(2);
1880: pswitch(1);
1881: secndflag++;
1882: if (command("%s %s", cmd2, local) != PRELIM)
1883: goto abort;
1884: ptflag++;
1.11 millert 1885: (void)getreply(0);
1.1 deraadt 1886: pswitch(0);
1.11 millert 1887: (void)getreply(0);
1888: (void)signal(SIGINT, oldintr);
1.1 deraadt 1889: pswitch(1);
1890: ptflag = 0;
1.18 deraadt 1891: fprintf(ttyout, "local: %s remote: %s\n", local, remote);
1.1 deraadt 1892: return;
1893: abort:
1.11 millert 1894: (void)signal(SIGINT, SIG_IGN);
1.1 deraadt 1895: ptflag = 0;
1896: if (strcmp(cmd, "RETR") && !proxy)
1897: pswitch(1);
1898: else if (!strcmp(cmd, "RETR") && proxy)
1899: pswitch(0);
1900: if (!cpend && !secndflag) { /* only here if cmd = "STOR" (proxy=1) */
1901: if (command("%s %s", cmd2, local) != PRELIM) {
1902: pswitch(0);
1903: if (cpend)
1.19 kstailey 1904: abort_remote(NULL);
1.1 deraadt 1905: }
1906: pswitch(1);
1907: if (ptabflg)
1908: code = -1;
1.11 millert 1909: (void)signal(SIGINT, oldintr);
1.1 deraadt 1910: return;
1911: }
1912: if (cpend)
1.19 kstailey 1913: abort_remote(NULL);
1.1 deraadt 1914: pswitch(!proxy);
1915: if (!cpend && !secndflag) { /* only if cmd = "RETR" (proxy=1) */
1916: if (command("%s %s", cmd2, local) != PRELIM) {
1917: pswitch(0);
1918: if (cpend)
1.19 kstailey 1919: abort_remote(NULL);
1.1 deraadt 1920: pswitch(1);
1921: if (ptabflg)
1922: code = -1;
1.11 millert 1923: (void)signal(SIGINT, oldintr);
1.1 deraadt 1924: return;
1925: }
1926: }
1927: if (cpend)
1.19 kstailey 1928: abort_remote(NULL);
1.1 deraadt 1929: pswitch(!proxy);
1930: if (cpend) {
1.54 millert 1931: pfd[0].fd = fileno(cin);
1932: pfd[0].events = POLLIN;
1933: if ((nfnd = poll(pfd, 1, 10 * 1000)) <= 0) {
1934: if (nfnd < 0)
1.1 deraadt 1935: warn("abort");
1936: if (ptabflg)
1937: code = -1;
1938: lostpeer();
1939: }
1.11 millert 1940: (void)getreply(0);
1941: (void)getreply(0);
1.1 deraadt 1942: }
1943: if (proxy)
1944: pswitch(0);
1945: pswitch(1);
1946: if (ptabflg)
1947: code = -1;
1.11 millert 1948: (void)signal(SIGINT, oldintr);
1.1 deraadt 1949: }
1950:
1.80 deraadt 1951: #ifndef SMALL
1.57 deraadt 1952: /* ARGSUSED */
1.1 deraadt 1953: void
1.56 deraadt 1954: reset(int argc, char *argv[])
1.1 deraadt 1955: {
1.54 millert 1956: struct pollfd pfd[1];
1.1 deraadt 1957: int nfnd = 1;
1958:
1.54 millert 1959: pfd[0].fd = fileno(cin);
1960: pfd[0].events = POLLIN;
1.1 deraadt 1961: while (nfnd > 0) {
1.54 millert 1962: if ((nfnd = poll(pfd, 1, 0)) < 0) {
1.1 deraadt 1963: warn("reset");
1964: code = -1;
1965: lostpeer();
1.54 millert 1966: } else if (nfnd) {
1.11 millert 1967: (void)getreply(0);
1.1 deraadt 1968: }
1969: }
1970: }
1.80 deraadt 1971: #endif
1.1 deraadt 1972:
1973: char *
1.56 deraadt 1974: gunique(const char *local)
1.1 deraadt 1975: {
1.89 deraadt 1976: static char new[PATH_MAX];
1.1 deraadt 1977: char *cp = strrchr(local, '/');
1978: int d, count=0;
1979: char ext = '1';
1980:
1981: if (cp)
1982: *cp = '\0';
1.22 millert 1983: d = access(cp == local ? "/" : cp ? local : ".", W_OK);
1.1 deraadt 1984: if (cp)
1985: *cp = '/';
1986: if (d < 0) {
1987: warn("local: %s", local);
1988: return ((char *) 0);
1989: }
1.52 deraadt 1990: (void)strlcpy(new, local, sizeof new);
1.1 deraadt 1991: cp = new + strlen(new);
1992: *cp++ = '.';
1993: while (!d) {
1994: if (++count == 100) {
1.18 deraadt 1995: fputs("runique: can't find unique file name.\n", ttyout);
1.1 deraadt 1996: return ((char *) 0);
1997: }
1998: *cp++ = ext;
1999: *cp = '\0';
2000: if (ext == '9')
2001: ext = '0';
2002: else
2003: ext++;
1.22 millert 2004: if ((d = access(new, F_OK)) < 0)
1.1 deraadt 2005: break;
2006: if (ext != '0')
2007: cp--;
2008: else if (*(cp - 2) == '.')
2009: *(cp - 1) = '1';
2010: else {
2011: *(cp - 2) = *(cp - 2) + 1;
2012: cp--;
2013: }
2014: }
2015: return (new);
2016: }
2017:
1.79 martynas 2018: jmp_buf forceabort;
2019:
2020: /* ARGSUSED */
1.83 deraadt 2021: static void
1.79 martynas 2022: abortforce(int signo)
2023: {
1.87 deraadt 2024: int save_errno = errno;
1.79 martynas 2025:
1.87 deraadt 2026: #define MSG "Forced abort. The connection will be closed.\n"
2027: (void) write(fileno(ttyout), MSG, strlen(MSG));
2028: #undef MSG
1.79 martynas 2029:
1.87 deraadt 2030: errno = save_errno;
1.79 martynas 2031: longjmp(forceabort, 1);
2032: }
2033:
1.1 deraadt 2034: void
1.56 deraadt 2035: abort_remote(FILE *din)
1.1 deraadt 2036: {
2037: char buf[BUFSIZ];
1.81 lum 2038: nfds_t nfds;
1.1 deraadt 2039: int nfnd;
1.54 millert 2040: struct pollfd pfd[2];
1.79 martynas 2041: sig_t oldintr;
1.13 millert 2042:
1.79 martynas 2043: if (cout == NULL || setjmp(forceabort)) {
1.87 deraadt 2044: if (cout)
2045: fclose(cout);
1.13 millert 2046: warnx("Lost control connection for abort.");
2047: if (ptabflg)
2048: code = -1;
2049: lostpeer();
2050: return;
2051: }
1.1 deraadt 2052:
1.79 martynas 2053: oldintr = signal(SIGINT, abortforce);
2054:
1.1 deraadt 2055: /*
2056: * send IAC in urgent mode instead of DM because 4.3BSD places oob mark
2057: * after urgent byte rather than before as is protocol now
2058: */
1.46 deraadt 2059: snprintf(buf, sizeof buf, "%c%c%c", IAC, IP, IAC);
1.1 deraadt 2060: if (send(fileno(cout), buf, 3, MSG_OOB) != 3)
2061: warn("abort");
1.10 millert 2062: fprintf(cout, "%cABOR\r\n", DM);
1.11 millert 2063: (void)fflush(cout);
1.54 millert 2064: pfd[0].fd = fileno(cin);
2065: pfd[0].events = POLLIN;
1.81 lum 2066: nfds = 1;
1.10 millert 2067: if (din) {
1.54 millert 2068: pfd[1].fd = fileno(din);
2069: pfd[1].events = POLLIN;
1.81 lum 2070: nfds++;
1.1 deraadt 2071: }
1.81 lum 2072: if ((nfnd = poll(pfd, nfds, 10 * 1000)) <= 0) {
1.54 millert 2073: if (nfnd < 0)
1.1 deraadt 2074: warn("abort");
2075: if (ptabflg)
2076: code = -1;
2077: lostpeer();
2078: }
1.54 millert 2079: if (din && (pfd[1].revents & POLLIN)) {
1.1 deraadt 2080: while (read(fileno(din), buf, BUFSIZ) > 0)
2081: /* LOOP */;
2082: }
2083: if (getreply(0) == ERROR && code == 552) {
2084: /* 552 needed for nic style abort */
1.11 millert 2085: (void)getreply(0);
1.1 deraadt 2086: }
1.11 millert 2087: (void)getreply(0);
1.79 martynas 2088: (void)signal(SIGINT, oldintr);
1.1 deraadt 2089: }