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