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