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