GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: usr.bin/ftp/ftp.c Lines: 0 1260 0.0 %
Date: 2016-12-06 Branches: 0 1067 0.0 %

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