GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: usr.bin/ftp/ftp.c Lines: 0 1309 0.0 %
Date: 2017-11-07 Branches: 0 1016 0.0 %

Line Branch Exec Source
1
/*	$OpenBSD: ftp.c,v 1.100 2016/08/22 16:27:00 millert Exp $	*/
2
/*	$NetBSD: ftp.c,v 1.27 1997/08/18 10:20:23 lukem Exp $	*/
3
4
/*
5
 * Copyright (C) 1997 and 1998 WIDE Project.
6
 * All rights reserved.
7
 *
8
 * Redistribution and use in source and binary forms, with or without
9
 * modification, are permitted provided that the following conditions
10
 * are met:
11
 * 1. Redistributions of source code must retain the above copyright
12
 *    notice, this list of conditions and the following disclaimer.
13
 * 2. Redistributions in binary form must reproduce the above copyright
14
 *    notice, this list of conditions and the following disclaimer in the
15
 *    documentation and/or other materials provided with the distribution.
16
 * 3. Neither the name of the project nor the names of its contributors
17
 *    may be used to endorse or promote products derived from this software
18
 *    without specific prior written permission.
19
 *
20
 * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
21
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
24
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30
 * SUCH DAMAGE.
31
 */
32
33
/*
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>
64
#include <sys/socket.h>
65
66
#include <netinet/in.h>
67
#include <netinet/ip.h>
68
#include <arpa/inet.h>
69
#include <arpa/ftp.h>
70
#include <arpa/telnet.h>
71
72
#include <ctype.h>
73
#include <err.h>
74
#include <errno.h>
75
#include <netdb.h>
76
#include <poll.h>
77
#include <stdarg.h>
78
#include <stdio.h>
79
#include <stdlib.h>
80
#include <string.h>
81
#include <unistd.h>
82
#include <utime.h>
83
84
#include "ftp_var.h"
85
86
union sockaddr_union {
87
	struct sockaddr     sa;
88
	struct sockaddr_in  sin;
89
	struct sockaddr_in6 sin6;
90
};
91
92
union sockaddr_union myctladdr, hisctladdr, data_addr;
93
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;
100
101
102
FILE	*cin, *cout;
103
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);
154
	}
155
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);
192
		if (s < 0) {
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
			}
205
			if (bind(s, ares->ai_addr, ares->ai_addrlen) < 0) {
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;
238
	}
239
	if (s < 0) {
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 */
255
	if (getsockname(s, &myctladdr.sa, &namelen) < 0) {
256
		warn("getsockname");
257
		code = -1;
258
		goto bad;
259
	}
260
	if (hisctladdr.sa.sa_family == AF_INET) {
261
		tos = IPTOS_LOWDELAY;
262
		if (setsockopt(s, IPPROTO_IP, IP_TOS, (char *)&tos, sizeof(int)) < 0)
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
291
	if (ret < 0 && debug)
292
		warn("setsockopt");
293
#endif /* !SMALL */
294
	}
295
296
	return (hostname);
297
bad:
298
	(void)close(s);
299
	return (NULL);
300
}
301
302
/* ARGSUSED */
303
void
304
cmdabort(int signo)
305
{
306
	int save_errno = errno;
307
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
}
316
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);
344
	}
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
}
358
359
int keep_alive_timeout = 60;		/* 0 -> no timeout */
360
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;
380
	}
381
}
382
383
static void
384
may_reset_noop_timeout(void)
385
{
386
	if (keep_alive_timeout != 0)
387
		last_timestamp = time(NULL);
388
}
389
390
static void
391
may_receive_noop_ack(void)
392
{
393
	int i;
394
395
	if (cout == NULL) {
396
		/* Lost connection;  so just pretend we're fine. */
397
		current_nop_pos = full_noops_sent = 0;
398
		return;
399
	}
400
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);
415
416
	full_noops_sent = 0;
417
}
418
419
static void
420
may_send_noop_char(void)
421
{
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
}
435
436
char reply_string[BUFSIZ];		/* first line of previous reply */
437
438
int
439
getreply(int expecteof)
440
{
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 < &current_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;
544
			continue;
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');
555
	}
556
}
557
558
#ifndef SMALL
559
jmp_buf	sendabort;
560
561
/* ARGSUSED */
562
void
563
abortsend(int signo)
564
{
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
572
573
	errno = save_errno;
574
	longjmp(sendabort, 1);
575
}
576
577
void
578
sendrequest(const char *cmd, const char *local, const char *remote,
579
    int printnames)
580
{
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;
662
		if (fstat(fileno(fin), &st) < 0 ||
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;
686
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;
780
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;
839
	}
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 */
854
855
jmp_buf	recvabort;
856
857
/* ARGSUSED */
858
void
859
abortrecv(int signo)
860
{
861
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);
868
}
869
870
void
871
recvrequest(const char *cmd, const char * volatile local, const char *remote,
872
    const char *lmode, int printnames, int ignorespecial)
873
{
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 != '|')) {
932
		if (access(local, W_OK) < 0) {
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 = '/';
948
			if (d < 0) {
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 &&
956
			    chmod(local, (S_IRUSR|S_IWUSR)) < 0) {
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;
991
	}
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
	}
1035
	if (fstat(fileno(fout), &st) < 0 || st.st_blksize == 0)
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 &&
1059
		    lseek(fileno(fout), restart_point, SEEK_SET) < 0) {
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;
1114
1115
	case TYPE_A:
1116
		if (restart_point) {
1117
			int i, n, ch;
1118
1119
			if (fseek(fout, 0L, SEEK_SET) < 0)
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
			}
1131
			if (fseek(fout, 0L, SEEK_CUR) < 0) {
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);
1194
		break;
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) {
1214
				struct utimbuf ut;
1215
1216
				ut.actime = time(NULL);
1217
				ut.modtime = mtime;
1218
				if (utime(local, &ut) == -1)
1219
					fprintf(ttyout,
1220
				"Can't change modification time on %s to %s",
1221
					    local, asctime(localtime(&mtime)));
1222
			}
1223
		}
1224
	}
1225
	return;
1226
1227
abort:
1228
	/* abort using RFC959 recommended IP,SYNC sequence */
1229
	progress = oprogress;
1230
	preserve = opreserve;
1231
	if (oldintp)
1232
		(void)signal(SIGPIPE, oldintp);
1233
	(void)signal(SIGINT, SIG_IGN);
1234
	if (!cpend) {
1235
		code = -1;
1236
		(void)signal(SIGINT, oldintr);
1237
		(void)signal(SIGINFO, oldinti);
1238
		return;
1239
	}
1240
1241
	abort_remote(din);
1242
	code = -1;
1243
	if (data >= 0) {
1244
		(void)close(data);
1245
		data = -1;
1246
	}
1247
	if (closefunc != NULL && fout != NULL)
1248
		(*closefunc)(fout);
1249
	if (din)
1250
		(void)fclose(din);
1251
	if (bytes > 0)
1252
		ptransfer(0);
1253
	(void)signal(SIGINT, oldintr);
1254
	(void)signal(SIGINFO, oldinti);
1255
}
1256
1257
/*
1258
 * Need to start a listen on the data channel before we send the command,
1259
 * otherwise the server's connect may fail.
1260
 */
1261
int
1262
initconn(void)
1263
{
1264
	char *p, *a;
1265
	int result = ERROR, tmpno = 0;
1266
	int on = 1;
1267
	int error;
1268
	u_int addr[16], port[2];
1269
	u_int af, hal, pal;
1270
	char *pasvcmd = NULL;
1271
	socklen_t namelen;
1272
#ifndef SMALL
1273
	struct addrinfo *ares;
1274
#endif
1275
1276
	if (myctladdr.sa.sa_family == AF_INET6
1277
	 && (IN6_IS_ADDR_LINKLOCAL(&myctladdr.sin6.sin6_addr)
1278
	  || IN6_IS_ADDR_SITELOCAL(&myctladdr.sin6.sin6_addr))) {
1279
		warnx("use of scoped address can be troublesome");
1280
	}
1281
#ifndef SMALL
1282
	if (srcaddr) {
1283
		struct addrinfo ahints;
1284
1285
		memset(&ahints, 0, sizeof(ahints));
1286
		ahints.ai_family = family;
1287
		ahints.ai_socktype = SOCK_STREAM;
1288
		ahints.ai_flags |= AI_NUMERICHOST;
1289
		ahints.ai_protocol = 0;
1290
1291
		error = getaddrinfo(srcaddr, NULL, &ahints, &ares);
1292
		if (error) {
1293
			warnx("%s: %s", srcaddr, gai_strerror(error));
1294
			code = -1;
1295
			return (0);
1296
		}
1297
	}
1298
#endif /* !SMALL */
1299
reinit:
1300
	if (passivemode) {
1301
		data_addr = myctladdr;
1302
		data = socket(data_addr.sa.sa_family, SOCK_STREAM, 0);
1303
		if (data < 0) {
1304
			warn("socket");
1305
			return (1);
1306
		}
1307
#ifndef SMALL
1308
		if (srcaddr) {
1309
			if (bind(data, ares->ai_addr, ares->ai_addrlen) < 0) {
1310
				warn("bind");
1311
				close(data);
1312
				return (1);
1313
			}
1314
		}
1315
		if ((options & SO_DEBUG) &&
1316
		    setsockopt(data, SOL_SOCKET, SO_DEBUG, (char *)&on,
1317
			       sizeof(on)) < 0)
1318
			warn("setsockopt (ignored)");
1319
#endif /* !SMALL */
1320
		switch (data_addr.sa.sa_family) {
1321
		case AF_INET:
1322
			if (epsv4 && !epsv4bad) {
1323
				int ov;
1324
				/* shut this command up in case it fails */
1325
				ov = verbose;
1326
				verbose = -1;
1327
				result = command(pasvcmd = "EPSV");
1328
				/*
1329
				 * now back to whatever verbosity we had before
1330
				 * and we can try PASV
1331
				 */
1332
				verbose = ov;
1333
				if (code / 10 == 22 && code != 229) {
1334
					fputs(
1335
"wrong server: return code must be 229\n",
1336
						ttyout);
1337
					result = COMPLETE + 1;
1338
				}
1339
				if (result != COMPLETE) {
1340
					epsv4bad = 1;
1341
#ifndef SMALL
1342
					if (debug) {
1343
						fputs(
1344
"disabling epsv4 for this connection\n",
1345
						    ttyout);
1346
					}
1347
#endif /* !SMALL */
1348
				}
1349
			}
1350
			if (result != COMPLETE)
1351
				result = command(pasvcmd = "PASV");
1352
			break;
1353
		case AF_INET6:
1354
			result = command(pasvcmd = "EPSV");
1355
			if (code / 10 == 22 && code != 229) {
1356
				fputs(
1357
"wrong server: return code must be 229\n",
1358
					ttyout);
1359
				result = COMPLETE + 1;
1360
			}
1361
			if (result != COMPLETE)
1362
				result = command(pasvcmd = "LPSV");
1363
			break;
1364
		default:
1365
			result = COMPLETE + 1;
1366
			break;
1367
		}
1368
		if (result != COMPLETE) {
1369
			if (activefallback) {
1370
				(void)close(data);
1371
				data = -1;
1372
				passivemode = 0;
1373
				activefallback = 0;
1374
				goto reinit;
1375
			}
1376
			fputs("Passive mode refused.\n", ttyout);
1377
			goto bad;
1378
		}
1379
1380
#define pack2(var, off) \
1381
	(((var[(off) + 0] & 0xff) << 8) | ((var[(off) + 1] & 0xff) << 0))
1382
#define pack4(var, off) \
1383
	(((var[(off) + 0] & 0xff) << 24) | ((var[(off) + 1] & 0xff) << 16) | \
1384
	 ((var[(off) + 2] & 0xff) << 8) | ((var[(off) + 3] & 0xff) << 0))
1385
1386
		/*
1387
		 * What we've got at this point is a string of comma separated
1388
		 * one-byte unsigned integer values, separated by commas.
1389
		 */
1390
		if (!pasvcmd)
1391
			goto bad;
1392
		if (strcmp(pasvcmd, "PASV") == 0) {
1393
			if (data_addr.sa.sa_family != AF_INET) {
1394
				fputs(
1395
"Passive mode AF mismatch. Shouldn't happen!\n", ttyout);
1396
				goto bad;
1397
			}
1398
			if (code / 10 == 22 && code != 227) {
1399
				fputs("wrong server: return code must be 227\n",
1400
					ttyout);
1401
				goto bad;
1402
			}
1403
			error = sscanf(pasv, "%u,%u,%u,%u,%u,%u",
1404
					&addr[0], &addr[1], &addr[2], &addr[3],
1405
					&port[0], &port[1]);
1406
			if (error != 6) {
1407
				fputs(
1408
"Passive mode address scan failure. Shouldn't happen!\n", ttyout);
1409
				goto bad;
1410
			}
1411
			memset(&data_addr, 0, sizeof(data_addr));
1412
			data_addr.sin.sin_family = AF_INET;
1413
			data_addr.sin.sin_len = sizeof(struct sockaddr_in);
1414
			data_addr.sin.sin_addr.s_addr =
1415
				htonl(pack4(addr, 0));
1416
			data_addr.sin.sin_port = htons(pack2(port, 0));
1417
		} else if (strcmp(pasvcmd, "LPSV") == 0) {
1418
			if (code / 10 == 22 && code != 228) {
1419
				fputs("wrong server: return code must be 228\n",
1420
					ttyout);
1421
				goto bad;
1422
			}
1423
			switch (data_addr.sa.sa_family) {
1424
			case AF_INET:
1425
				error = sscanf(pasv,
1426
"%u,%u,%u,%u,%u,%u,%u,%u,%u",
1427
					&af, &hal,
1428
					&addr[0], &addr[1], &addr[2], &addr[3],
1429
					&pal, &port[0], &port[1]);
1430
				if (error != 9) {
1431
					fputs(
1432
"Passive mode address scan failure. Shouldn't happen!\n", ttyout);
1433
					goto bad;
1434
				}
1435
				if (af != 4 || hal != 4 || pal != 2) {
1436
					fputs(
1437
"Passive mode AF mismatch. Shouldn't happen!\n", ttyout);
1438
					error = 1;
1439
					goto bad;
1440
				}
1441
1442
				memset(&data_addr, 0, sizeof(data_addr));
1443
				data_addr.sin.sin_family = AF_INET;
1444
				data_addr.sin.sin_len = sizeof(struct sockaddr_in);
1445
				data_addr.sin.sin_addr.s_addr =
1446
					htonl(pack4(addr, 0));
1447
				data_addr.sin.sin_port = htons(pack2(port, 0));
1448
				break;
1449
			case AF_INET6:
1450
				error = sscanf(pasv,
1451
"%u,%u,%u,%u,%u,%u,%u,%u,%u,%u,%u,%u,%u,%u,%u,%u,%u,%u,%u,%u,%u",
1452
					&af, &hal,
1453
					&addr[0], &addr[1], &addr[2], &addr[3],
1454
					&addr[4], &addr[5], &addr[6], &addr[7],
1455
					&addr[8], &addr[9], &addr[10],
1456
					&addr[11], &addr[12], &addr[13],
1457
					&addr[14], &addr[15],
1458
					&pal, &port[0], &port[1]);
1459
				if (error != 21) {
1460
					fputs(
1461
"Passive mode address scan failure. Shouldn't happen!\n", ttyout);
1462
					goto bad;
1463
				}
1464
				if (af != 6 || hal != 16 || pal != 2) {
1465
					fputs(
1466
"Passive mode AF mismatch. Shouldn't happen!\n", ttyout);
1467
					goto bad;
1468
				}
1469
1470
				memset(&data_addr, 0, sizeof(data_addr));
1471
				data_addr.sin6.sin6_family = AF_INET6;
1472
				data_addr.sin6.sin6_len = sizeof(struct sockaddr_in6);
1473
			    {
1474
				u_int32_t *p32;
1475
				p32 = (u_int32_t *)&data_addr.sin6.sin6_addr;
1476
				p32[0] = htonl(pack4(addr, 0));
1477
				p32[1] = htonl(pack4(addr, 4));
1478
				p32[2] = htonl(pack4(addr, 8));
1479
				p32[3] = htonl(pack4(addr, 12));
1480
			    }
1481
				data_addr.sin6.sin6_port = htons(pack2(port, 0));
1482
				break;
1483
			default:
1484
				fputs("Bad family!\n", ttyout);
1485
				goto bad;
1486
			}
1487
		} else if (strcmp(pasvcmd, "EPSV") == 0) {
1488
			char delim[4];
1489
1490
			port[0] = 0;
1491
			if (code / 10 == 22 && code != 229) {
1492
				fputs("wrong server: return code must be 229\n",
1493
					ttyout);
1494
				goto bad;
1495
			}
1496
			if (sscanf(pasv, "%c%c%c%d%c", &delim[0],
1497
					&delim[1], &delim[2], &port[1],
1498
					&delim[3]) != 5) {
1499
				fputs("parse error!\n", ttyout);
1500
				goto bad;
1501
			}
1502
			if (delim[0] != delim[1] || delim[0] != delim[2]
1503
			 || delim[0] != delim[3]) {
1504
				fputs("parse error!\n", ttyout);
1505
				goto bad;
1506
			}
1507
			data_addr = hisctladdr;
1508
			data_addr.sin.sin_port = htons(port[1]);
1509
		} else
1510
			goto bad;
1511
1512
		for (error = connect(data, &data_addr.sa, data_addr.sa.sa_len);
1513
		    error != 0 && errno == EINTR;
1514
		    error = connect_wait(data))
1515
			continue;
1516
		if (error != 0) {
1517
			if (activefallback) {
1518
				(void)close(data);
1519
				data = -1;
1520
				passivemode = 0;
1521
				activefallback = 0;
1522
				goto reinit;
1523
			}
1524
			warn("connect");
1525
			goto bad;
1526
		}
1527
		if (data_addr.sa.sa_family == AF_INET) {
1528
			on = IPTOS_THROUGHPUT;
1529
			if (setsockopt(data, IPPROTO_IP, IP_TOS, (char *)&on,
1530
				       sizeof(int)) < 0)
1531
				warn("setsockopt TOS (ignored)");
1532
		}
1533
		return (0);
1534
	}
1535
1536
noport:
1537
	data_addr = myctladdr;
1538
	if (sendport)
1539
		data_addr.sin.sin_port = 0;	/* let system pick one */
1540
	if (data != -1)
1541
		(void)close(data);
1542
	data = socket(data_addr.sa.sa_family, SOCK_STREAM, 0);
1543
	if (data < 0) {
1544
		warn("socket");
1545
		if (tmpno)
1546
			sendport = 1;
1547
		return (1);
1548
	}
1549
	if (!sendport)
1550
		if (setsockopt(data, SOL_SOCKET, SO_REUSEADDR, (char *)&on,
1551
				sizeof(on)) < 0) {
1552
			warn("setsockopt (reuse address)");
1553
			goto bad;
1554
		}
1555
	switch (data_addr.sa.sa_family) {
1556
	case AF_INET:
1557
		on = IP_PORTRANGE_HIGH;
1558
		if (setsockopt(data, IPPROTO_IP, IP_PORTRANGE,
1559
		    (char *)&on, sizeof(on)) < 0)
1560
			warn("setsockopt IP_PORTRANGE (ignored)");
1561
		break;
1562
	case AF_INET6:
1563
		on = IPV6_PORTRANGE_HIGH;
1564
		if (setsockopt(data, IPPROTO_IPV6, IPV6_PORTRANGE,
1565
		    (char *)&on, sizeof(on)) < 0)
1566
			warn("setsockopt IPV6_PORTRANGE (ignored)");
1567
		break;
1568
	}
1569
	if (bind(data, &data_addr.sa, data_addr.sa.sa_len) < 0) {
1570
		warn("bind");
1571
		goto bad;
1572
	}
1573
#ifndef SMALL
1574
	if (options & SO_DEBUG &&
1575
	    setsockopt(data, SOL_SOCKET, SO_DEBUG, (char *)&on,
1576
			sizeof(on)) < 0)
1577
		warn("setsockopt (ignored)");
1578
#endif /* !SMALL */
1579
	namelen = sizeof(data_addr);
1580
	if (getsockname(data, &data_addr.sa, &namelen) < 0) {
1581
		warn("getsockname");
1582
		goto bad;
1583
	}
1584
	if (listen(data, 1) < 0)
1585
		warn("listen");
1586
1587
#define	UC(b)	(((int)b)&0xff)
1588
1589
	if (sendport) {
1590
		char hname[NI_MAXHOST], pbuf[NI_MAXSERV];
1591
		int af_tmp;
1592
		union sockaddr_union tmp;
1593
1594
		tmp = data_addr;
1595
		switch (tmp.sa.sa_family) {
1596
		case AF_INET:
1597
			if (!epsv4 || epsv4bad) {
1598
				result = COMPLETE +1;
1599
				break;
1600
			}
1601
			/*FALLTHROUGH*/
1602
		case AF_INET6:
1603
			if (tmp.sa.sa_family == AF_INET6)
1604
				tmp.sin6.sin6_scope_id = 0;
1605
			af_tmp = (tmp.sa.sa_family == AF_INET) ? 1 : 2;
1606
			if (getnameinfo(&tmp.sa, tmp.sa.sa_len, hname,
1607
			    sizeof(hname), pbuf, sizeof(pbuf),
1608
			    NI_NUMERICHOST | NI_NUMERICSERV)) {
1609
				result = ERROR;
1610
			} else {
1611
				result = command("EPRT |%d|%s|%s|",
1612
				    af_tmp, hname, pbuf);
1613
				if (result != COMPLETE) {
1614
					epsv4bad = 1;
1615
#ifndef SMALL
1616
					if (debug) {
1617
						fputs(
1618
"disabling epsv4 for this connection\n",
1619
						    ttyout);
1620
					}
1621
#endif /* !SMALL */
1622
				}
1623
			}
1624
			break;
1625
		default:
1626
			result = COMPLETE + 1;
1627
			break;
1628
		}
1629
		if (result == COMPLETE)
1630
			goto skip_port;
1631
1632
		switch (data_addr.sa.sa_family) {
1633
		case AF_INET:
1634
			a = (char *)&data_addr.sin.sin_addr;
1635
			p = (char *)&data_addr.sin.sin_port;
1636
			result = command("PORT %d,%d,%d,%d,%d,%d",
1637
				 UC(a[0]), UC(a[1]), UC(a[2]), UC(a[3]),
1638
				 UC(p[0]), UC(p[1]));
1639
			break;
1640
		case AF_INET6:
1641
			a = (char *)&data_addr.sin6.sin6_addr;
1642
			p = (char *)&data_addr.sin6.sin6_port;
1643
			result = command(
1644
"LPRT %d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d",
1645
				 6, 16,
1646
				 UC(a[0]),UC(a[1]),UC(a[2]),UC(a[3]),
1647
				 UC(a[4]),UC(a[5]),UC(a[6]),UC(a[7]),
1648
				 UC(a[8]),UC(a[9]),UC(a[10]),UC(a[11]),
1649
				 UC(a[12]),UC(a[13]),UC(a[14]),UC(a[15]),
1650
				 2, UC(p[0]), UC(p[1]));
1651
			break;
1652
		default:
1653
			result = COMPLETE + 1; /* xxx */
1654
		}
1655
	skip_port:
1656
1657
		if (result == ERROR && sendport == -1) {
1658
			sendport = 0;
1659
			tmpno = 1;
1660
			goto noport;
1661
		}
1662
		return (result != COMPLETE);
1663
	}
1664
	if (tmpno)
1665
		sendport = 1;
1666
	if (data_addr.sa.sa_family == AF_INET) {
1667
		on = IPTOS_THROUGHPUT;
1668
		if (setsockopt(data, IPPROTO_IP, IP_TOS, (char *)&on,
1669
			       sizeof(int)) < 0)
1670
			warn("setsockopt TOS (ignored)");
1671
	}
1672
	return (0);
1673
bad:
1674
	(void)close(data), data = -1;
1675
	if (tmpno)
1676
		sendport = 1;
1677
	return (1);
1678
}
1679
1680
FILE *
1681
dataconn(const char *lmode)
1682
{
1683
	union sockaddr_union from;
1684
	socklen_t fromlen = myctladdr.sa.sa_len;
1685
	int s;
1686
1687
	if (passivemode)
1688
		return (fdopen(data, lmode));
1689
1690
	s = accept(data, &from.sa, &fromlen);
1691
	if (s < 0) {
1692
		warn("accept");
1693
		(void)close(data), data = -1;
1694
		return (NULL);
1695
	}
1696
	(void)close(data);
1697
	data = s;
1698
	if (from.sa.sa_family == AF_INET) {
1699
		int tos = IPTOS_THROUGHPUT;
1700
		if (setsockopt(s, IPPROTO_IP, IP_TOS, (char *)&tos,
1701
				sizeof(int)) < 0) {
1702
			warn("setsockopt TOS (ignored)");
1703
		}
1704
	}
1705
	return (fdopen(data, lmode));
1706
}
1707
1708
/* ARGSUSED */
1709
void
1710
psummary(int signo)
1711
{
1712
	int save_errno = errno;
1713
1714
	if (bytes > 0)
1715
		ptransfer(1);
1716
	errno = save_errno;
1717
}
1718
1719
/* ARGSUSED */
1720
void
1721
psabort(int signo)
1722
{
1723
1724
	alarmtimer(0);
1725
	abrtflag++;
1726
}
1727
1728
void
1729
pswitch(int flag)
1730
{
1731
	sig_t oldintr;
1732
	static struct comvars {
1733
		int connect;
1734
		char name[HOST_NAME_MAX+1];
1735
		union sockaddr_union mctl;
1736
		union sockaddr_union hctl;
1737
		FILE *in;
1738
		FILE *out;
1739
		int tpe;
1740
		int curtpe;
1741
		int cpnd;
1742
		int sunqe;
1743
		int runqe;
1744
		int mcse;
1745
		int ntflg;
1746
		char nti[17];
1747
		char nto[17];
1748
		int mapflg;
1749
		char mi[PATH_MAX];
1750
		char mo[PATH_MAX];
1751
	} proxstruct, tmpstruct;
1752
	struct comvars *ip, *op;
1753
1754
	abrtflag = 0;
1755
	oldintr = signal(SIGINT, psabort);
1756
	if (flag) {
1757
		if (proxy)
1758
			return;
1759
		ip = &tmpstruct;
1760
		op = &proxstruct;
1761
		proxy++;
1762
	} else {
1763
		if (!proxy)
1764
			return;
1765
		ip = &proxstruct;
1766
		op = &tmpstruct;
1767
		proxy = 0;
1768
	}
1769
	ip->connect = connected;
1770
	connected = op->connect;
1771
	if (hostname) {
1772
		(void)strlcpy(ip->name, hostname, sizeof(ip->name));
1773
	} else
1774
		ip->name[0] = '\0';
1775
	hostname = op->name;
1776
	ip->hctl = hisctladdr;
1777
	hisctladdr = op->hctl;
1778
	ip->mctl = myctladdr;
1779
	myctladdr = op->mctl;
1780
	ip->in = cin;
1781
	cin = op->in;
1782
	ip->out = cout;
1783
	cout = op->out;
1784
	ip->tpe = type;
1785
	type = op->tpe;
1786
	ip->curtpe = curtype;
1787
	curtype = op->curtpe;
1788
	ip->cpnd = cpend;
1789
	cpend = op->cpnd;
1790
	ip->sunqe = sunique;
1791
	sunique = op->sunqe;
1792
	ip->runqe = runique;
1793
	runique = op->runqe;
1794
	ip->mcse = mcase;
1795
	mcase = op->mcse;
1796
	ip->ntflg = ntflag;
1797
	ntflag = op->ntflg;
1798
	(void)strlcpy(ip->nti, ntin, sizeof(ip->nti));
1799
	(void)strlcpy(ntin, op->nti, sizeof ntin);
1800
	(void)strlcpy(ip->nto, ntout, sizeof(ip->nto));
1801
	(void)strlcpy(ntout, op->nto, sizeof ntout);
1802
	ip->mapflg = mapflag;
1803
	mapflag = op->mapflg;
1804
	(void)strlcpy(ip->mi, mapin, sizeof(ip->mi));
1805
	(void)strlcpy(mapin, op->mi, sizeof mapin);
1806
	(void)strlcpy(ip->mo, mapout, sizeof(ip->mo));
1807
	(void)strlcpy(mapout, op->mo, sizeof mapout);
1808
	(void)signal(SIGINT, oldintr);
1809
	if (abrtflag) {
1810
		abrtflag = 0;
1811
		(*oldintr)(SIGINT);
1812
	}
1813
}
1814
1815
/* ARGSUSED */
1816
void
1817
abortpt(int signo)
1818
{
1819
1820
	alarmtimer(0);
1821
	putc('\n', ttyout);
1822
	(void)fflush(ttyout);
1823
	ptabflg++;
1824
	mflag = 0;
1825
	abrtflag = 0;
1826
	longjmp(ptabort, 1);
1827
}
1828
1829
void
1830
proxtrans(const char *cmd, const char *local, const char *remote)
1831
{
1832
	volatile sig_t oldintr;
1833
	int prox_type, nfnd;
1834
	volatile int secndflag;
1835
	char * volatile cmd2;
1836
	struct pollfd pfd[1];
1837
1838
	oldintr = NULL;
1839
	secndflag = 0;
1840
	if (strcmp(cmd, "RETR"))
1841
		cmd2 = "RETR";
1842
	else
1843
		cmd2 = runique ? "STOU" : "STOR";
1844
	if ((prox_type = type) == 0) {
1845
		if (unix_server && unix_proxy)
1846
			prox_type = TYPE_I;
1847
		else
1848
			prox_type = TYPE_A;
1849
	}
1850
	if (curtype != prox_type)
1851
		changetype(prox_type, 1);
1852
	if (command("PASV") != COMPLETE) {
1853
		fputs("proxy server does not support third party transfers.\n",
1854
		    ttyout);
1855
		return;
1856
	}
1857
	pswitch(0);
1858
	if (!connected) {
1859
		fputs("No primary connection.\n", ttyout);
1860
		pswitch(1);
1861
		code = -1;
1862
		return;
1863
	}
1864
	if (curtype != prox_type)
1865
		changetype(prox_type, 1);
1866
	if (command("PORT %s", pasv) != COMPLETE) {
1867
		pswitch(1);
1868
		return;
1869
	}
1870
	if (setjmp(ptabort))
1871
		goto abort;
1872
	oldintr = signal(SIGINT, abortpt);
1873
	if (command("%s %s", cmd, remote) != PRELIM) {
1874
		(void)signal(SIGINT, oldintr);
1875
		pswitch(1);
1876
		return;
1877
	}
1878
	sleep(2);
1879
	pswitch(1);
1880
	secndflag++;
1881
	if (command("%s %s", cmd2, local) != PRELIM)
1882
		goto abort;
1883
	ptflag++;
1884
	(void)getreply(0);
1885
	pswitch(0);
1886
	(void)getreply(0);
1887
	(void)signal(SIGINT, oldintr);
1888
	pswitch(1);
1889
	ptflag = 0;
1890
	fprintf(ttyout, "local: %s remote: %s\n", local, remote);
1891
	return;
1892
abort:
1893
	(void)signal(SIGINT, SIG_IGN);
1894
	ptflag = 0;
1895
	if (strcmp(cmd, "RETR") && !proxy)
1896
		pswitch(1);
1897
	else if (!strcmp(cmd, "RETR") && proxy)
1898
		pswitch(0);
1899
	if (!cpend && !secndflag) {  /* only here if cmd = "STOR" (proxy=1) */
1900
		if (command("%s %s", cmd2, local) != PRELIM) {
1901
			pswitch(0);
1902
			if (cpend)
1903
				abort_remote(NULL);
1904
		}
1905
		pswitch(1);
1906
		if (ptabflg)
1907
			code = -1;
1908
		(void)signal(SIGINT, oldintr);
1909
		return;
1910
	}
1911
	if (cpend)
1912
		abort_remote(NULL);
1913
	pswitch(!proxy);
1914
	if (!cpend && !secndflag) {  /* only if cmd = "RETR" (proxy=1) */
1915
		if (command("%s %s", cmd2, local) != PRELIM) {
1916
			pswitch(0);
1917
			if (cpend)
1918
				abort_remote(NULL);
1919
			pswitch(1);
1920
			if (ptabflg)
1921
				code = -1;
1922
			(void)signal(SIGINT, oldintr);
1923
			return;
1924
		}
1925
	}
1926
	if (cpend)
1927
		abort_remote(NULL);
1928
	pswitch(!proxy);
1929
	if (cpend) {
1930
		pfd[0].fd = fileno(cin);
1931
		pfd[0].events = POLLIN;
1932
		if ((nfnd = poll(pfd, 1, 10 * 1000)) <= 0) {
1933
			if (nfnd < 0)
1934
				warn("abort");
1935
			if (ptabflg)
1936
				code = -1;
1937
			lostpeer();
1938
		}
1939
		(void)getreply(0);
1940
		(void)getreply(0);
1941
	}
1942
	if (proxy)
1943
		pswitch(0);
1944
	pswitch(1);
1945
	if (ptabflg)
1946
		code = -1;
1947
	(void)signal(SIGINT, oldintr);
1948
}
1949
1950
#ifndef SMALL
1951
/* ARGSUSED */
1952
void
1953
reset(int argc, char *argv[])
1954
{
1955
	struct pollfd pfd[1];
1956
	int nfnd = 1;
1957
1958
	pfd[0].fd = fileno(cin);
1959
	pfd[0].events = POLLIN;
1960
	while (nfnd > 0) {
1961
		if ((nfnd = poll(pfd, 1, 0)) < 0) {
1962
			warn("reset");
1963
			code = -1;
1964
			lostpeer();
1965
		} else if (nfnd) {
1966
			(void)getreply(0);
1967
		}
1968
	}
1969
}
1970
#endif
1971
1972
char *
1973
gunique(const char *local)
1974
{
1975
	static char new[PATH_MAX];
1976
	char *cp = strrchr(local, '/');
1977
	int d, count=0;
1978
	char ext = '1';
1979
1980
	if (cp)
1981
		*cp = '\0';
1982
	d = access(cp == local ? "/" : cp ? local : ".", W_OK);
1983
	if (cp)
1984
		*cp = '/';
1985
	if (d < 0) {
1986
		warn("local: %s", local);
1987
		return ((char *) 0);
1988
	}
1989
	(void)strlcpy(new, local, sizeof new);
1990
	cp = new + strlen(new);
1991
	*cp++ = '.';
1992
	while (!d) {
1993
		if (++count == 100) {
1994
			fputs("runique: can't find unique file name.\n", ttyout);
1995
			return ((char *) 0);
1996
		}
1997
		*cp++ = ext;
1998
		*cp = '\0';
1999
		if (ext == '9')
2000
			ext = '0';
2001
		else
2002
			ext++;
2003
		if ((d = access(new, F_OK)) < 0)
2004
			break;
2005
		if (ext != '0')
2006
			cp--;
2007
		else if (*(cp - 2) == '.')
2008
			*(cp - 1) = '1';
2009
		else {
2010
			*(cp - 2) = *(cp - 2) + 1;
2011
			cp--;
2012
		}
2013
	}
2014
	return (new);
2015
}
2016
2017
jmp_buf forceabort;
2018
2019
/* ARGSUSED */
2020
static void
2021
abortforce(int signo)
2022
{
2023
	int save_errno = errno;
2024
2025
#define MSG	"Forced abort.  The connection will be closed.\n"
2026
	(void) write(fileno(ttyout), MSG, strlen(MSG));
2027
#undef MSG
2028
2029
	errno = save_errno;
2030
	longjmp(forceabort, 1);
2031
}
2032
2033
void
2034
abort_remote(FILE *din)
2035
{
2036
	char buf[BUFSIZ];
2037
	nfds_t nfds;
2038
	int nfnd;
2039
	struct pollfd pfd[2];
2040
	sig_t oldintr;
2041
2042
	if (cout == NULL || setjmp(forceabort)) {
2043
		if (cout)
2044
			fclose(cout);
2045
		warnx("Lost control connection for abort.");
2046
		if (ptabflg)
2047
			code = -1;
2048
		lostpeer();
2049
		return;
2050
	}
2051
2052
	oldintr = signal(SIGINT, abortforce);
2053
2054
	/*
2055
	 * send IAC in urgent mode instead of DM because 4.3BSD places oob mark
2056
	 * after urgent byte rather than before as is protocol now
2057
	 */
2058
	snprintf(buf, sizeof buf, "%c%c%c", IAC, IP, IAC);
2059
	if (send(fileno(cout), buf, 3, MSG_OOB) != 3)
2060
		warn("abort");
2061
	fprintf(cout, "%cABOR\r\n", DM);
2062
	(void)fflush(cout);
2063
	pfd[0].fd = fileno(cin);
2064
	pfd[0].events = POLLIN;
2065
	nfds = 1;
2066
	if (din) {
2067
		pfd[1].fd = fileno(din);
2068
		pfd[1].events = POLLIN;
2069
		nfds++;
2070
	}
2071
	if ((nfnd = poll(pfd, nfds, 10 * 1000)) <= 0) {
2072
		if (nfnd < 0)
2073
			warn("abort");
2074
		if (ptabflg)
2075
			code = -1;
2076
		lostpeer();
2077
	}
2078
	if (din && (pfd[1].revents & POLLIN)) {
2079
		while (read(fileno(din), buf, BUFSIZ) > 0)
2080
			/* LOOP */;
2081
	}
2082
	if (getreply(0) == ERROR && code == 552) {
2083
		/* 552 needed for nic style abort */
2084
		(void)getreply(0);
2085
	}
2086
	(void)getreply(0);
2087
	(void)signal(SIGINT, oldintr);
2088
}