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