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