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