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