xref: /csrg-svn/usr.bin/ftp/ftp.c (revision 37458)
121739Sdist /*
236942Skarels  * Copyright (c) 1985, 1989 Regents of the University of California.
333737Sbostic  * All rights reserved.
433737Sbostic  *
533737Sbostic  * Redistribution and use in source and binary forms are permitted
634901Sbostic  * provided that the above copyright notice and this paragraph are
734901Sbostic  * duplicated in all such forms and that any documentation,
834901Sbostic  * advertising materials, and other materials related to such
934901Sbostic  * distribution and use acknowledge that the software was developed
1034901Sbostic  * by the University of California, Berkeley.  The name of the
1134901Sbostic  * University may not be used to endorse or promote products derived
1234901Sbostic  * from this software without specific prior written permission.
1334901Sbostic  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
1434901Sbostic  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
1536935Skarels  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
1621739Sdist  */
1721739Sdist 
1810296Ssam #ifndef lint
19*37458Skarels static char sccsid[] = "@(#)ftp.c	5.28 (Berkeley) 04/20/89";
2033737Sbostic #endif /* not lint */
2110296Ssam 
2236940Skarels #include <sys/param.h>
2310296Ssam #include <sys/stat.h>
2410296Ssam #include <sys/ioctl.h>
2510296Ssam #include <sys/socket.h>
2613614Ssam #include <sys/time.h>
2736935Skarels #include <sys/file.h>
2810296Ssam 
2910296Ssam #include <netinet/in.h>
3012397Ssam #include <arpa/ftp.h>
3126048Sminshall #include <arpa/telnet.h>
3210296Ssam 
3310296Ssam #include <stdio.h>
3410296Ssam #include <signal.h>
3510296Ssam #include <errno.h>
3610296Ssam #include <netdb.h>
3726048Sminshall #include <fcntl.h>
3826048Sminshall #include <pwd.h>
3910296Ssam 
4036940Skarels #include "ftp_var.h"
4136940Skarels 
4210296Ssam struct	sockaddr_in hisctladdr;
4310296Ssam struct	sockaddr_in data_addr;
4410296Ssam int	data = -1;
4526048Sminshall int	abrtflag = 0;
4626048Sminshall int	ptflag = 0;
4710296Ssam int	connected;
48*37458Skarels int	allbinary;
4910296Ssam struct	sockaddr_in myctladdr;
5026496Sminshall uid_t	getuid();
5137225Skarels off_t	restart_point = 0;
5210296Ssam 
5310296Ssam FILE	*cin, *cout;
5410296Ssam FILE	*dataconn();
5510296Ssam 
5625904Skarels char *
5710296Ssam hookup(host, port)
5810296Ssam 	char *host;
5910296Ssam 	int port;
6010296Ssam {
6125904Skarels 	register struct hostent *hp = 0;
6227687Sminshall 	int s,len;
6325904Skarels 	static char hostnamebuf[80];
6410296Ssam 
6510296Ssam 	bzero((char *)&hisctladdr, sizeof (hisctladdr));
6625904Skarels 	hisctladdr.sin_addr.s_addr = inet_addr(host);
6725904Skarels 	if (hisctladdr.sin_addr.s_addr != -1) {
6825904Skarels 		hisctladdr.sin_family = AF_INET;
6936940Skarels 		(void) strncpy(hostnamebuf, host, sizeof(hostnamebuf));
7036940Skarels 	} else {
7125100Sbloom 		hp = gethostbyname(host);
7225904Skarels 		if (hp == NULL) {
7335792Sbostic 			fprintf(stderr, "ftp: %s: ", host);
7435792Sbostic 			herror((char *)NULL);
7526048Sminshall 			code = -1;
7626048Sminshall 			return((char *) 0);
7725904Skarels 		}
7825904Skarels 		hisctladdr.sin_family = hp->h_addrtype;
7925904Skarels 		bcopy(hp->h_addr_list[0],
8025904Skarels 		    (caddr_t)&hisctladdr.sin_addr, hp->h_length);
8136940Skarels 		(void) strncpy(hostnamebuf, hp->h_name, sizeof(hostnamebuf));
8210296Ssam 	}
8325904Skarels 	hostname = hostnamebuf;
8425904Skarels 	s = socket(hisctladdr.sin_family, SOCK_STREAM, 0);
8510296Ssam 	if (s < 0) {
8610296Ssam 		perror("ftp: socket");
8726048Sminshall 		code = -1;
8810296Ssam 		return (0);
8910296Ssam 	}
9010296Ssam 	hisctladdr.sin_port = port;
9126496Sminshall 	while (connect(s, &hisctladdr, sizeof (hisctladdr)) < 0) {
9225904Skarels 		if (hp && hp->h_addr_list[1]) {
9325904Skarels 			int oerrno = errno;
9425904Skarels 
9525904Skarels 			fprintf(stderr, "ftp: connect to address %s: ",
9625904Skarels 				inet_ntoa(hisctladdr.sin_addr));
9725904Skarels 			errno = oerrno;
9826496Sminshall 			perror((char *) 0);
9925904Skarels 			hp->h_addr_list++;
10025904Skarels 			bcopy(hp->h_addr_list[0],
10126048Sminshall 			     (caddr_t)&hisctladdr.sin_addr, hp->h_length);
10226496Sminshall 			fprintf(stdout, "Trying %s...\n",
10325904Skarels 				inet_ntoa(hisctladdr.sin_addr));
10426813Skarels 			(void) close(s);
10526813Skarels 			s = socket(hisctladdr.sin_family, SOCK_STREAM, 0);
10626813Skarels 			if (s < 0) {
10726813Skarels 				perror("ftp: socket");
10826813Skarels 				code = -1;
10926813Skarels 				return (0);
11026813Skarels 			}
11125904Skarels 			continue;
11225904Skarels 		}
11310296Ssam 		perror("ftp: connect");
11426048Sminshall 		code = -1;
11510296Ssam 		goto bad;
11610296Ssam 	}
11711627Ssam 	len = sizeof (myctladdr);
11811627Ssam 	if (getsockname(s, (char *)&myctladdr, &len) < 0) {
11911627Ssam 		perror("ftp: getsockname");
12026048Sminshall 		code = -1;
12110296Ssam 		goto bad;
12210296Ssam 	}
12310296Ssam 	cin = fdopen(s, "r");
12410296Ssam 	cout = fdopen(s, "w");
12511219Ssam 	if (cin == NULL || cout == NULL) {
12610296Ssam 		fprintf(stderr, "ftp: fdopen failed.\n");
12710296Ssam 		if (cin)
12826496Sminshall 			(void) fclose(cin);
12910296Ssam 		if (cout)
13026496Sminshall 			(void) fclose(cout);
13126048Sminshall 		code = -1;
13210296Ssam 		goto bad;
13310296Ssam 	}
13410296Ssam 	if (verbose)
13526067Sminshall 		printf("Connected to %s.\n", hostname);
13627687Sminshall 	if (getreply(0) > 2) { 	/* read startup message from server */
13726048Sminshall 		if (cin)
13826496Sminshall 			(void) fclose(cin);
13926048Sminshall 		if (cout)
14026496Sminshall 			(void) fclose(cout);
14126048Sminshall 		code = -1;
14226048Sminshall 		goto bad;
14326048Sminshall 	}
14427687Sminshall #ifdef SO_OOBINLINE
14527687Sminshall 	{
14627687Sminshall 	int on = 1;
14726048Sminshall 
14827687Sminshall 	if (setsockopt(s, SOL_SOCKET, SO_OOBINLINE, &on, sizeof(on))
14927687Sminshall 		< 0 && debug) {
15027687Sminshall 			perror("ftp: setsockopt");
15127687Sminshall 		}
15227687Sminshall 	}
15327687Sminshall #endif SO_OOBINLINE
15426048Sminshall 
15525904Skarels 	return (hostname);
15610296Ssam bad:
15726496Sminshall 	(void) close(s);
15825904Skarels 	return ((char *)0);
15910296Ssam }
16010296Ssam 
16125904Skarels login(host)
16225904Skarels 	char *host;
16310296Ssam {
16426048Sminshall 	char tmp[80];
16535659Sbostic 	char *user, *pass, *acct, *getlogin(), *getpass();
16626048Sminshall 	int n, aflag = 0;
16710296Ssam 
16826048Sminshall 	user = pass = acct = 0;
16926048Sminshall 	if (ruserpass(host, &user, &pass, &acct) < 0) {
17026048Sminshall 		code = -1;
17126048Sminshall 		return(0);
17226048Sminshall 	}
173*37458Skarels 	while (user == NULL) {
17426048Sminshall 		char *myname = getlogin();
17526048Sminshall 
17626048Sminshall 		if (myname == NULL) {
17726048Sminshall 			struct passwd *pp = getpwuid(getuid());
17826048Sminshall 
17926448Slepreau 			if (pp != NULL)
18026048Sminshall 				myname = pp->pw_name;
18126048Sminshall 		}
182*37458Skarels 		if (myname)
183*37458Skarels 			printf("Name (%s:%s): ", host, myname);
184*37458Skarels 		else
185*37458Skarels 			printf("Name (%s): ", host);
18626048Sminshall 		(void) fgets(tmp, sizeof(tmp) - 1, stdin);
18726048Sminshall 		tmp[strlen(tmp) - 1] = '\0';
18826448Slepreau 		if (*tmp == '\0')
18926048Sminshall 			user = myname;
19026448Slepreau 		else
19126048Sminshall 			user = tmp;
19226048Sminshall 	}
19310296Ssam 	n = command("USER %s", user);
19426048Sminshall 	if (n == CONTINUE) {
19526448Slepreau 		if (pass == NULL)
19635659Sbostic 			pass = getpass("Password:");
19710296Ssam 		n = command("PASS %s", pass);
19826048Sminshall 	}
19910296Ssam 	if (n == CONTINUE) {
20026048Sminshall 		aflag++;
20135659Sbostic 		acct = getpass("Account:");
20210296Ssam 		n = command("ACCT %s", acct);
20310296Ssam 	}
20410296Ssam 	if (n != COMPLETE) {
20510296Ssam 		fprintf(stderr, "Login failed.\n");
20610296Ssam 		return (0);
20710296Ssam 	}
20826448Slepreau 	if (!aflag && acct != NULL)
20926048Sminshall 		(void) command("ACCT %s", acct);
21026448Slepreau 	if (proxy)
21126048Sminshall 		return(1);
21226048Sminshall 	for (n = 0; n < macnum; ++n) {
21326048Sminshall 		if (!strcmp("init", macros[n].mac_name)) {
21426496Sminshall 			(void) strcpy(line, "$init");
21526048Sminshall 			makeargv();
21626048Sminshall 			domacro(margc, margv);
21726048Sminshall 			break;
21826048Sminshall 		}
21926048Sminshall 	}
22010296Ssam 	return (1);
22110296Ssam }
22210296Ssam 
22326048Sminshall cmdabort()
22426048Sminshall {
22526048Sminshall 	extern jmp_buf ptabort;
22626048Sminshall 
22726048Sminshall 	printf("\n");
22826048Sminshall 	(void) fflush(stdout);
22926048Sminshall 	abrtflag++;
23026448Slepreau 	if (ptflag)
23126048Sminshall 		longjmp(ptabort,1);
23226048Sminshall }
23326048Sminshall 
23426496Sminshall /*VARARGS1*/
23510296Ssam command(fmt, args)
23610296Ssam 	char *fmt;
23710296Ssam {
23826048Sminshall 	int r, (*oldintr)(), cmdabort();
23910296Ssam 
24026048Sminshall 	abrtflag = 0;
24110296Ssam 	if (debug) {
24210296Ssam 		printf("---> ");
24310296Ssam 		_doprnt(fmt, &args, stdout);
24410296Ssam 		printf("\n");
24510296Ssam 		(void) fflush(stdout);
24610296Ssam 	}
24711219Ssam 	if (cout == NULL) {
24811219Ssam 		perror ("No control connection for command");
24926048Sminshall 		code = -1;
25011219Ssam 		return (0);
25111219Ssam 	}
25226048Sminshall 	oldintr = signal(SIGINT,cmdabort);
25310296Ssam 	_doprnt(fmt, &args, cout);
25410296Ssam 	fprintf(cout, "\r\n");
25510296Ssam 	(void) fflush(cout);
25626048Sminshall 	cpend = 1;
25726048Sminshall 	r = getreply(!strcmp(fmt, "QUIT"));
25826448Slepreau 	if (abrtflag && oldintr != SIG_IGN)
25926048Sminshall 		(*oldintr)();
26026048Sminshall 	(void) signal(SIGINT, oldintr);
26126048Sminshall 	return(r);
26210296Ssam }
26310296Ssam 
26437229Skarels char reply_string[BUFSIZ];		/* last line of previous reply */
26536935Skarels 
26610296Ssam #include <ctype.h>
26710296Ssam 
26810296Ssam getreply(expecteof)
26910296Ssam 	int expecteof;
27010296Ssam {
27111219Ssam 	register int c, n;
27226048Sminshall 	register int dig;
27336935Skarels 	register char *cp;
27426048Sminshall 	int originalcode = 0, continuation = 0, (*oldintr)(), cmdabort();
27526048Sminshall 	int pflag = 0;
27626048Sminshall 	char *pt = pasv;
27710296Ssam 
27826048Sminshall 	oldintr = signal(SIGINT,cmdabort);
27910296Ssam 	for (;;) {
28010296Ssam 		dig = n = code = 0;
28137229Skarels 		cp = reply_string;
28210296Ssam 		while ((c = getc(cin)) != '\n') {
28327687Sminshall 			if (c == IAC) {     /* handle telnet commands */
28427687Sminshall 				switch (c = getc(cin)) {
28527687Sminshall 				case WILL:
28627687Sminshall 				case WONT:
28727687Sminshall 					c = getc(cin);
28836940Skarels 					fprintf(cout, "%c%c%c",IAC,DONT,c);
28927687Sminshall 					(void) fflush(cout);
29027687Sminshall 					break;
29127687Sminshall 				case DO:
29227687Sminshall 				case DONT:
29327687Sminshall 					c = getc(cin);
29436940Skarels 					fprintf(cout, "%c%c%c",IAC,WONT,c);
29527687Sminshall 					(void) fflush(cout);
29627687Sminshall 					break;
29727687Sminshall 				default:
29827687Sminshall 					break;
29927687Sminshall 				}
30027687Sminshall 				continue;
30127687Sminshall 			}
30210296Ssam 			dig++;
30310296Ssam 			if (c == EOF) {
30426048Sminshall 				if (expecteof) {
30526048Sminshall 					(void) signal(SIGINT,oldintr);
30626048Sminshall 					code = 221;
30710296Ssam 					return (0);
30826048Sminshall 				}
30910296Ssam 				lostpeer();
31026048Sminshall 				if (verbose) {
31126048Sminshall 					printf("421 Service not available, remote server has closed connection\n");
31226048Sminshall 					(void) fflush(stdout);
31326048Sminshall 				}
31433772Scsvsj 				code = 421;
31533772Scsvsj 				return(4);
31610296Ssam 			}
31726048Sminshall 			if (c != '\r' && (verbose > 0 ||
31826048Sminshall 			    (verbose > -1 && n == '5' && dig > 4))) {
31926448Slepreau 				if (proxflag &&
32026448Slepreau 				   (dig == 1 || dig == 5 && verbose == 0))
32126048Sminshall 					printf("%s:",hostname);
32226496Sminshall 				(void) putchar(c);
32326048Sminshall 			}
32410296Ssam 			if (dig < 4 && isdigit(c))
32510296Ssam 				code = code * 10 + (c - '0');
32626448Slepreau 			if (!pflag && code == 227)
32726048Sminshall 				pflag = 1;
32826448Slepreau 			if (dig > 4 && pflag == 1 && isdigit(c))
32926048Sminshall 				pflag = 2;
33026048Sminshall 			if (pflag == 2) {
33126448Slepreau 				if (c != '\r' && c != ')')
33226048Sminshall 					*pt++ = c;
33326048Sminshall 				else {
33426048Sminshall 					*pt = '\0';
33526048Sminshall 					pflag = 3;
33626048Sminshall 				}
33726048Sminshall 			}
33826048Sminshall 			if (dig == 4 && c == '-') {
33926448Slepreau 				if (continuation)
34026048Sminshall 					code = 0;
34110296Ssam 				continuation++;
34226048Sminshall 			}
34310296Ssam 			if (n == 0)
34410296Ssam 				n = c;
34537229Skarels 			if (cp < &reply_string[sizeof(reply_string) - 1])
34637229Skarels 				*cp++ = c;
34710296Ssam 		}
34826048Sminshall 		if (verbose > 0 || verbose > -1 && n == '5') {
34926496Sminshall 			(void) putchar(c);
35011346Ssam 			(void) fflush (stdout);
35111346Ssam 		}
35210296Ssam 		if (continuation && code != originalcode) {
35310296Ssam 			if (originalcode == 0)
35410296Ssam 				originalcode = code;
35510296Ssam 			continue;
35610296Ssam 		}
35736935Skarels 		*cp = '\0';
35826448Slepreau 		if (n != '1')
35926048Sminshall 			cpend = 0;
36026048Sminshall 		(void) signal(SIGINT,oldintr);
36126448Slepreau 		if (code == 421 || originalcode == 421)
36226048Sminshall 			lostpeer();
36326448Slepreau 		if (abrtflag && oldintr != cmdabort && oldintr != SIG_IGN)
36426048Sminshall 			(*oldintr)();
36525907Smckusick 		return (n - '0');
36610296Ssam 	}
36710296Ssam }
36810296Ssam 
36926048Sminshall empty(mask, sec)
37027687Sminshall 	struct fd_set *mask;
37126048Sminshall 	int sec;
37226048Sminshall {
37326048Sminshall 	struct timeval t;
37426048Sminshall 
37526048Sminshall 	t.tv_sec = (long) sec;
37626048Sminshall 	t.tv_usec = 0;
37727687Sminshall 	return(select(32, mask, (struct fd_set *) 0, (struct fd_set *) 0, &t));
37826048Sminshall }
37926048Sminshall 
38010296Ssam jmp_buf	sendabort;
38110296Ssam 
38210296Ssam abortsend()
38310296Ssam {
38410296Ssam 
38526048Sminshall 	mflag = 0;
38626048Sminshall 	abrtflag = 0;
38726048Sminshall 	printf("\nsend aborted\n");
38826048Sminshall 	(void) fflush(stdout);
38910296Ssam 	longjmp(sendabort, 1);
39010296Ssam }
39110296Ssam 
39236940Skarels #define HASHBYTES 1024
39336940Skarels 
39437225Skarels sendrequest(cmd, local, remote, printnames)
39510296Ssam 	char *cmd, *local, *remote;
39637225Skarels 	int printnames;
39710296Ssam {
39835659Sbostic 	FILE *fin, *dout = 0, *popen();
39935659Sbostic 	int (*closefunc)(), pclose(), fclose(), (*oldintr)(), (*oldintp)();
40026048Sminshall 	int abortsend();
40136942Skarels 	char buf[BUFSIZ], *bufp;
40236940Skarels 	long bytes = 0, hashbytes = HASHBYTES;
40311346Ssam 	register int c, d;
40410296Ssam 	struct stat st;
40510296Ssam 	struct timeval start, stop;
40636935Skarels 	char *mode;
40710296Ssam 
40837225Skarels 	if (verbose && printnames) {
40937225Skarels 		if (local && *local != '-')
41037225Skarels 			printf("local: %s ", local);
41137225Skarels 		if (remote)
41237225Skarels 			printf("remote: %s\n", remote);
41337225Skarels 	}
41426048Sminshall 	if (proxy) {
41526048Sminshall 		proxtrans(cmd, local, remote);
41626048Sminshall 		return;
41726048Sminshall 	}
41810296Ssam 	closefunc = NULL;
41926048Sminshall 	oldintr = NULL;
42026048Sminshall 	oldintp = NULL;
42136935Skarels 	mode = "w";
42226048Sminshall 	if (setjmp(sendabort)) {
42326048Sminshall 		while (cpend) {
42426048Sminshall 			(void) getreply(0);
42526048Sminshall 		}
42626048Sminshall 		if (data >= 0) {
42726048Sminshall 			(void) close(data);
42826048Sminshall 			data = -1;
42926048Sminshall 		}
43026448Slepreau 		if (oldintr)
43126048Sminshall 			(void) signal(SIGINT,oldintr);
43226448Slepreau 		if (oldintp)
43326048Sminshall 			(void) signal(SIGPIPE,oldintp);
43426048Sminshall 		code = -1;
43526048Sminshall 		return;
43626048Sminshall 	}
43710296Ssam 	oldintr = signal(SIGINT, abortsend);
43810296Ssam 	if (strcmp(local, "-") == 0)
43910296Ssam 		fin = stdin;
44010296Ssam 	else if (*local == '|') {
44126048Sminshall 		oldintp = signal(SIGPIPE,SIG_IGN);
44235659Sbostic 		fin = popen(local + 1, "r");
44310296Ssam 		if (fin == NULL) {
44426048Sminshall 			perror(local + 1);
44526048Sminshall 			(void) signal(SIGINT, oldintr);
44626048Sminshall 			(void) signal(SIGPIPE, oldintp);
44726048Sminshall 			code = -1;
44826048Sminshall 			return;
44910296Ssam 		}
45035659Sbostic 		closefunc = pclose;
45110296Ssam 	} else {
45210296Ssam 		fin = fopen(local, "r");
45310296Ssam 		if (fin == NULL) {
45410296Ssam 			perror(local);
45526048Sminshall 			(void) signal(SIGINT, oldintr);
45626048Sminshall 			code = -1;
45726048Sminshall 			return;
45810296Ssam 		}
45910296Ssam 		closefunc = fclose;
46010296Ssam 		if (fstat(fileno(fin), &st) < 0 ||
46110296Ssam 		    (st.st_mode&S_IFMT) != S_IFREG) {
46226496Sminshall 			fprintf(stdout, "%s: not a plain file.\n", local);
46326048Sminshall 			(void) signal(SIGINT, oldintr);
46436935Skarels 			fclose(fin);
46526048Sminshall 			code = -1;
46626048Sminshall 			return;
46710296Ssam 		}
46810296Ssam 	}
46926048Sminshall 	if (initconn()) {
47026048Sminshall 		(void) signal(SIGINT, oldintr);
47126448Slepreau 		if (oldintp)
47226048Sminshall 			(void) signal(SIGPIPE, oldintp);
47326048Sminshall 		code = -1;
47436935Skarels 		if (closefunc != NULL)
47536935Skarels 			(*closefunc)(fin);
47626048Sminshall 		return;
47726048Sminshall 	}
47826448Slepreau 	if (setjmp(sendabort))
47926048Sminshall 		goto abort;
48036935Skarels 
48137225Skarels 	if (restart_point &&
48237225Skarels 	    (strcmp(cmd, "STOR") == 0 || strcmp(cmd, "APPE") == 0)) {
48337225Skarels 		if (fseek(fin, (long) restart_point, 0) < 0) {
48437225Skarels 			perror(local);
48537225Skarels 			restart_point = 0;
48637225Skarels 			if (closefunc != NULL)
48737225Skarels 				(*closefunc)(fin);
48837225Skarels 			return;
48937225Skarels 		}
49037225Skarels 		if (command("REST %ld", (long) restart_point)
49137225Skarels 			!= CONTINUE) {
49237225Skarels 			restart_point = 0;
49337225Skarels 			if (closefunc != NULL)
49437225Skarels 				(*closefunc)(fin);
49537225Skarels 			return;
49637225Skarels 		}
49737225Skarels 		restart_point = 0;
49837225Skarels 		mode = "r+w";
49937225Skarels 	}
50010296Ssam 	if (remote) {
50126048Sminshall 		if (command("%s %s", cmd, remote) != PRELIM) {
50226048Sminshall 			(void) signal(SIGINT, oldintr);
50326448Slepreau 			if (oldintp)
50426048Sminshall 				(void) signal(SIGPIPE, oldintp);
50536935Skarels 			if (closefunc != NULL)
50636935Skarels 				(*closefunc)(fin);
50726048Sminshall 			return;
50826048Sminshall 		}
50910296Ssam 	} else
51026048Sminshall 		if (command("%s", cmd) != PRELIM) {
51126048Sminshall 			(void) signal(SIGINT, oldintr);
51226448Slepreau 			if (oldintp)
51326048Sminshall 				(void) signal(SIGPIPE, oldintp);
51436935Skarels 			if (closefunc != NULL)
51536935Skarels 				(*closefunc)(fin);
51626048Sminshall 			return;
51726048Sminshall 		}
51836935Skarels 	dout = dataconn(mode);
51926448Slepreau 	if (dout == NULL)
52026048Sminshall 		goto abort;
52126496Sminshall 	(void) gettimeofday(&start, (struct timezone *)0);
52236935Skarels 	oldintp = signal(SIGPIPE, SIG_IGN);
52311219Ssam 	switch (type) {
52411219Ssam 
52511219Ssam 	case TYPE_I:
52611219Ssam 	case TYPE_L:
52711346Ssam 		errno = d = 0;
52836942Skarels 		while ((c = read(fileno(fin), buf, sizeof (buf))) > 0) {
52911219Ssam 			bytes += c;
53036942Skarels 			for (bufp = buf; c > 0; c -= d, bufp += d)
53136942Skarels 				if ((d = write(fileno(dout), bufp, c)) <= 0)
53236942Skarels 					break;
53311651Ssam 			if (hash) {
53436940Skarels 				while (bytes >= hashbytes) {
53536940Skarels 					(void) putchar('#');
53636940Skarels 					hashbytes += HASHBYTES;
53736940Skarels 				}
53826496Sminshall 				(void) fflush(stdout);
53911651Ssam 			}
54011219Ssam 		}
54113213Ssam 		if (hash && bytes > 0) {
54236940Skarels 			if (bytes < HASHBYTES)
54336940Skarels 				(void) putchar('#');
54426496Sminshall 			(void) putchar('\n');
54526496Sminshall 			(void) fflush(stdout);
54611651Ssam 		}
54711219Ssam 		if (c < 0)
54811219Ssam 			perror(local);
54936942Skarels 		if (d <= 0) {
55036942Skarels 			if (d == 0)
55136942Skarels 				fprintf(stderr, "netout: write returned 0?\n");
55236942Skarels 			else if (errno != EPIPE)
55336935Skarels 				perror("netout");
55436935Skarels 			bytes = -1;
55536935Skarels 		}
55611219Ssam 		break;
55711219Ssam 
55811219Ssam 	case TYPE_A:
55911219Ssam 		while ((c = getc(fin)) != EOF) {
56011219Ssam 			if (c == '\n') {
56111651Ssam 				while (hash && (bytes >= hashbytes)) {
56226496Sminshall 					(void) putchar('#');
56326496Sminshall 					(void) fflush(stdout);
56436940Skarels 					hashbytes += HASHBYTES;
56511651Ssam 				}
56611219Ssam 				if (ferror(dout))
56711219Ssam 					break;
56826496Sminshall 				(void) putc('\r', dout);
56911219Ssam 				bytes++;
57011219Ssam 			}
57126496Sminshall 			(void) putc(c, dout);
57211219Ssam 			bytes++;
57326048Sminshall 	/*		if (c == '\r') {			  	*/
57426496Sminshall 	/*		(void)	putc('\0', dout);  /* this violates rfc */
57526048Sminshall 	/*			bytes++;				*/
57626048Sminshall 	/*		}                          			*/
57711219Ssam 		}
57811651Ssam 		if (hash) {
57913213Ssam 			if (bytes < hashbytes)
58026496Sminshall 				(void) putchar('#');
58126496Sminshall 			(void) putchar('\n');
58226496Sminshall 			(void) fflush(stdout);
58311651Ssam 		}
58411219Ssam 		if (ferror(fin))
58511219Ssam 			perror(local);
58636935Skarels 		if (ferror(dout)) {
58736935Skarels 			if (errno != EPIPE)
58836935Skarels 				perror("netout");
58936935Skarels 			bytes = -1;
59036935Skarels 		}
59111219Ssam 		break;
59210296Ssam 	}
59326496Sminshall 	(void) gettimeofday(&stop, (struct timezone *)0);
59410296Ssam 	if (closefunc != NULL)
59526048Sminshall 		(*closefunc)(fin);
59610296Ssam 	(void) fclose(dout);
59726048Sminshall 	(void) getreply(0);
59826048Sminshall 	(void) signal(SIGINT, oldintr);
59936935Skarels 	if (oldintp)
60036935Skarels 		(void) signal(SIGPIPE, oldintp);
60135699Sbostic 	if (bytes > 0)
60237225Skarels 		ptransfer("sent", bytes, &start, &stop);
60310296Ssam 	return;
60426048Sminshall abort:
60526496Sminshall 	(void) gettimeofday(&stop, (struct timezone *)0);
60626048Sminshall 	(void) signal(SIGINT, oldintr);
60726448Slepreau 	if (oldintp)
60826048Sminshall 		(void) signal(SIGPIPE, oldintp);
60926048Sminshall 	if (!cpend) {
61026048Sminshall 		code = -1;
61126048Sminshall 		return;
61226048Sminshall 	}
61326048Sminshall 	if (data >= 0) {
61426048Sminshall 		(void) close(data);
61526048Sminshall 		data = -1;
61626048Sminshall 	}
61726448Slepreau 	if (dout)
61826048Sminshall 		(void) fclose(dout);
61926048Sminshall 	(void) getreply(0);
62026048Sminshall 	code = -1;
62110296Ssam 	if (closefunc != NULL && fin != NULL)
62226048Sminshall 		(*closefunc)(fin);
62335699Sbostic 	if (bytes > 0)
62437225Skarels 		ptransfer("sent", bytes, &start, &stop);
62510296Ssam }
62610296Ssam 
62710296Ssam jmp_buf	recvabort;
62810296Ssam 
62910296Ssam abortrecv()
63010296Ssam {
63110296Ssam 
63226048Sminshall 	mflag = 0;
63326048Sminshall 	abrtflag = 0;
63426048Sminshall 	printf("\n");
63526048Sminshall 	(void) fflush(stdout);
63610296Ssam 	longjmp(recvabort, 1);
63710296Ssam }
63810296Ssam 
63937225Skarels recvrequest(cmd, local, remote, mode, printnames)
64011651Ssam 	char *cmd, *local, *remote, *mode;
64110296Ssam {
64235659Sbostic 	FILE *fout, *din = 0, *popen();
64335659Sbostic 	int (*closefunc)(), pclose(), fclose(), (*oldintr)(), (*oldintp)();
64436935Skarels 	int abortrecv(), oldverbose, oldtype = 0, is_retr, tcrflag, nfnd;
64536944Skarels 	char *bufp, *gunique(), msg;
64636944Skarels 	static char *buf;
64736940Skarels 	static int bufsize;
64836940Skarels 	long bytes = 0, hashbytes = HASHBYTES;
64926496Sminshall 	struct fd_set mask;
65011346Ssam 	register int c, d;
65110296Ssam 	struct timeval start, stop;
65236940Skarels 	struct stat st;
65336940Skarels 	extern char *malloc();
65410296Ssam 
65536935Skarels 	is_retr = strcmp(cmd, "RETR") == 0;
65637225Skarels 	if (is_retr && verbose && printnames) {
65737225Skarels 		if (local && *local != '-')
65837225Skarels 			printf("local: %s ", local);
65937225Skarels 		if (remote)
66037225Skarels 			printf("remote: %s\n", remote);
66137225Skarels 	}
66236935Skarels 	if (proxy && is_retr) {
66326048Sminshall 		proxtrans(cmd, local, remote);
66426048Sminshall 		return;
66526048Sminshall 	}
66610296Ssam 	closefunc = NULL;
66726048Sminshall 	oldintr = NULL;
66826048Sminshall 	oldintp = NULL;
66936935Skarels 	tcrflag = !crflag && is_retr;
67026048Sminshall 	if (setjmp(recvabort)) {
67126048Sminshall 		while (cpend) {
67226048Sminshall 			(void) getreply(0);
67326048Sminshall 		}
67426048Sminshall 		if (data >= 0) {
67526048Sminshall 			(void) close(data);
67626048Sminshall 			data = -1;
67726048Sminshall 		}
67826448Slepreau 		if (oldintr)
67926048Sminshall 			(void) signal(SIGINT, oldintr);
68026048Sminshall 		code = -1;
68126048Sminshall 		return;
68226048Sminshall 	}
68310296Ssam 	oldintr = signal(SIGINT, abortrecv);
68426048Sminshall 	if (strcmp(local, "-") && *local != '|') {
68510296Ssam 		if (access(local, 2) < 0) {
68626048Sminshall 			char *dir = rindex(local, '/');
68710296Ssam 
68826048Sminshall 			if (errno != ENOENT && errno != EACCES) {
68910296Ssam 				perror(local);
69026048Sminshall 				(void) signal(SIGINT, oldintr);
69126048Sminshall 				code = -1;
69226048Sminshall 				return;
69310296Ssam 			}
69426048Sminshall 			if (dir != NULL)
69526048Sminshall 				*dir = 0;
69626048Sminshall 			d = access(dir ? local : ".", 2);
69726048Sminshall 			if (dir != NULL)
69826048Sminshall 				*dir = '/';
69926048Sminshall 			if (d < 0) {
70026048Sminshall 				perror(local);
70126048Sminshall 				(void) signal(SIGINT, oldintr);
70226048Sminshall 				code = -1;
70326048Sminshall 				return;
70426048Sminshall 			}
70526048Sminshall 			if (!runique && errno == EACCES &&
70636935Skarels 			    chmod(local, 0600) < 0) {
70726048Sminshall 				perror(local);
70826048Sminshall 				(void) signal(SIGINT, oldintr);
70926048Sminshall 				code = -1;
71026048Sminshall 				return;
71126048Sminshall 			}
71226048Sminshall 			if (runique && errno == EACCES &&
71326048Sminshall 			   (local = gunique(local)) == NULL) {
71426048Sminshall 				(void) signal(SIGINT, oldintr);
71526048Sminshall 				code = -1;
71626048Sminshall 				return;
71726048Sminshall 			}
71810296Ssam 		}
71926048Sminshall 		else if (runique && (local = gunique(local)) == NULL) {
72026048Sminshall 			(void) signal(SIGINT, oldintr);
72126048Sminshall 			code = -1;
72226048Sminshall 			return;
72326048Sminshall 		}
72426048Sminshall 	}
72526048Sminshall 	if (initconn()) {
72626048Sminshall 		(void) signal(SIGINT, oldintr);
72726048Sminshall 		code = -1;
72826048Sminshall 		return;
72926048Sminshall 	}
73026448Slepreau 	if (setjmp(recvabort))
73126048Sminshall 		goto abort;
73236935Skarels 	if (!is_retr) {
733*37458Skarels 		if (type != TYPE_A && (allbinary == 0 || type != TYPE_I)) {
73436935Skarels 			oldtype = type;
73536935Skarels 			oldverbose = verbose;
73636935Skarels 			if (!debug)
73736935Skarels 				verbose = 0;
73836935Skarels 			setascii();
73936935Skarels 			verbose = oldverbose;
74036935Skarels 		}
74137225Skarels 	} else if (restart_point) {
74237225Skarels 		if (command("REST %ld", (long) restart_point) != CONTINUE)
74337225Skarels 			return;
74426048Sminshall 	}
74510296Ssam 	if (remote) {
74626048Sminshall 		if (command("%s %s", cmd, remote) != PRELIM) {
74726048Sminshall 			(void) signal(SIGINT, oldintr);
74826048Sminshall 			if (oldtype) {
74926448Slepreau 				if (!debug)
75026048Sminshall 					verbose = 0;
75126048Sminshall 				switch (oldtype) {
75226048Sminshall 					case TYPE_I:
75326048Sminshall 						setbinary();
75426048Sminshall 						break;
75526048Sminshall 					case TYPE_E:
75626048Sminshall 						setebcdic();
75726048Sminshall 						break;
75826048Sminshall 					case TYPE_L:
75926048Sminshall 						settenex();
76026048Sminshall 						break;
76136942Skarels 				}
76226048Sminshall 				verbose = oldverbose;
76326048Sminshall 			}
76426048Sminshall 			return;
76526048Sminshall 		}
76626048Sminshall 	} else {
76726048Sminshall 		if (command("%s", cmd) != PRELIM) {
76826048Sminshall 			(void) signal(SIGINT, oldintr);
76926048Sminshall 			if (oldtype) {
77026448Slepreau 				if (!debug)
77126048Sminshall 					verbose = 0;
77226048Sminshall 				switch (oldtype) {
77326048Sminshall 					case TYPE_I:
77426048Sminshall 						setbinary();
77526048Sminshall 						break;
77626048Sminshall 					case TYPE_E:
77726048Sminshall 						setebcdic();
77826048Sminshall 						break;
77926048Sminshall 					case TYPE_L:
78026048Sminshall 						settenex();
78126048Sminshall 						break;
78236942Skarels 				}
78326048Sminshall 				verbose = oldverbose;
78426048Sminshall 			}
78526048Sminshall 			return;
78626048Sminshall 		}
78726048Sminshall 	}
78826048Sminshall 	din = dataconn("r");
78926048Sminshall 	if (din == NULL)
79026048Sminshall 		goto abort;
79126448Slepreau 	if (strcmp(local, "-") == 0)
79210296Ssam 		fout = stdout;
79310296Ssam 	else if (*local == '|') {
79426048Sminshall 		oldintp = signal(SIGPIPE, SIG_IGN);
79535659Sbostic 		fout = popen(local + 1, "w");
79626048Sminshall 		if (fout == NULL) {
79726048Sminshall 			perror(local+1);
79826048Sminshall 			goto abort;
79926048Sminshall 		}
80035659Sbostic 		closefunc = pclose;
80136940Skarels 	} else {
80211651Ssam 		fout = fopen(local, mode);
80326048Sminshall 		if (fout == NULL) {
80426048Sminshall 			perror(local);
80526048Sminshall 			goto abort;
80626048Sminshall 		}
80710296Ssam 		closefunc = fclose;
80810296Ssam 	}
80936940Skarels 	if (fstat(fileno(fout), &st) < 0 || st.st_blksize == 0)
81036940Skarels 		st.st_blksize = BUFSIZ;
81136940Skarels 	if (st.st_blksize > bufsize) {
81236940Skarels 		if (buf)
81336940Skarels 			(void) free(buf);
81436940Skarels 		buf = malloc(st.st_blksize);
81536940Skarels 		if (buf == NULL) {
81636940Skarels 			perror("malloc");
81736944Skarels 			bufsize = 0;
81836940Skarels 			goto abort;
81936940Skarels 		}
82036940Skarels 		bufsize = st.st_blksize;
82136940Skarels 	}
82226496Sminshall 	(void) gettimeofday(&start, (struct timezone *)0);
82311219Ssam 	switch (type) {
82411219Ssam 
82511219Ssam 	case TYPE_I:
82611219Ssam 	case TYPE_L:
82737225Skarels 		if (restart_point &&
82837225Skarels 		    lseek(fileno(fout), (long) restart_point, L_SET) < 0) {
82937225Skarels 			perror(local);
83037225Skarels 			if (closefunc != NULL)
83137225Skarels 				(*closefunc)(fout);
83237225Skarels 			return;
83337225Skarels 		}
83411346Ssam 		errno = d = 0;
83536940Skarels 		while ((c = read(fileno(din), buf, bufsize)) > 0) {
83636944Skarels 			if ((d = write(fileno(fout), buf, c)) != c)
83711219Ssam 				break;
83811219Ssam 			bytes += c;
83911651Ssam 			if (hash) {
84036940Skarels 				while (bytes >= hashbytes) {
84136940Skarels 					(void) putchar('#');
84236940Skarels 					hashbytes += HASHBYTES;
84336940Skarels 				}
84426496Sminshall 				(void) fflush(stdout);
84511651Ssam 			}
84611219Ssam 		}
84713213Ssam 		if (hash && bytes > 0) {
84836940Skarels 			if (bytes < HASHBYTES)
84936940Skarels 				(void) putchar('#');
85026496Sminshall 			(void) putchar('\n');
85126496Sminshall 			(void) fflush(stdout);
85211651Ssam 		}
85336935Skarels 		if (c < 0) {
85436935Skarels 			if (errno != EPIPE)
85536935Skarels 				perror("netin");
85636935Skarels 			bytes = -1;
85736935Skarels 		}
85836942Skarels 		if (d < c) {
85936942Skarels 			if (d < 0)
86036942Skarels 				perror(local);
86136942Skarels 			else
86236942Skarels 				fprintf(stderr, "%s: short write\n", local);
86336942Skarels 		}
86411219Ssam 		break;
86511219Ssam 
86611219Ssam 	case TYPE_A:
86737225Skarels 		if (restart_point) {
86837225Skarels 			register int i, n, c;
86937225Skarels 
87037225Skarels 			if (fseek(fout, 0L, L_SET) < 0)
87137225Skarels 				goto done;
87237225Skarels 			n = restart_point;
87337225Skarels 			i = 0;
87437225Skarels 			while (i++ < n) {
87537225Skarels 				if ((c=getc(fout)) == EOF)
87637225Skarels 					goto done;
87737225Skarels 				if (c == '\n')
87837225Skarels 					i++;
87937225Skarels 			}
88037225Skarels 			if (fseek(fout, 0L, L_INCR) < 0) {
88137225Skarels done:
88237225Skarels 				perror(local);
88337225Skarels 				if (closefunc != NULL)
88437225Skarels 					(*closefunc)(fout);
88537225Skarels 				return;
88637225Skarels 			}
88737225Skarels 		}
88811219Ssam 		while ((c = getc(din)) != EOF) {
88927749Sminshall 			while (c == '\r') {
89011651Ssam 				while (hash && (bytes >= hashbytes)) {
89126496Sminshall 					(void) putchar('#');
89226496Sminshall 					(void) fflush(stdout);
89336940Skarels 					hashbytes += HASHBYTES;
89411651Ssam 				}
89510296Ssam 				bytes++;
89626048Sminshall 				if ((c = getc(din)) != '\n' || tcrflag) {
89736940Skarels 					if (ferror(fout))
89836940Skarels 						goto break2;
89936940Skarels 					(void) putc('\r', fout);
90036942Skarels 					if (c == '\0') {
90136942Skarels 						bytes++;
90236940Skarels 						goto contin2;
90336942Skarels 					}
90436942Skarels 					if (c == EOF)
90536942Skarels 						goto contin2;
90611219Ssam 				}
90711219Ssam 			}
90836940Skarels 			(void) putc(c, fout);
90911219Ssam 			bytes++;
91036940Skarels 	contin2:	;
91110296Ssam 		}
91236940Skarels break2:
91311651Ssam 		if (hash) {
91413213Ssam 			if (bytes < hashbytes)
91526496Sminshall 				(void) putchar('#');
91626496Sminshall 			(void) putchar('\n');
91726496Sminshall 			(void) fflush(stdout);
91811651Ssam 		}
91936944Skarels 		if (ferror(din)) {
92036935Skarels 			if (errno != EPIPE)
92136944Skarels 				perror("netin");
92236935Skarels 			bytes = -1;
92336935Skarels 		}
92436940Skarels 		if (ferror(fout))
92536944Skarels 			perror(local);
92611219Ssam 		break;
92710296Ssam 	}
92826448Slepreau 	if (closefunc != NULL)
92926048Sminshall 		(*closefunc)(fout);
93026496Sminshall 	(void) signal(SIGINT, oldintr);
93126448Slepreau 	if (oldintp)
93226048Sminshall 		(void) signal(SIGPIPE, oldintp);
93326496Sminshall 	(void) gettimeofday(&stop, (struct timezone *)0);
93410296Ssam 	(void) fclose(din);
93526048Sminshall 	(void) getreply(0);
93636935Skarels 	if (bytes > 0 && is_retr)
93737225Skarels 		ptransfer("received", bytes, &start, &stop);
93826048Sminshall 	if (oldtype) {
93926448Slepreau 		if (!debug)
94026048Sminshall 			verbose = 0;
94126048Sminshall 		switch (oldtype) {
94226048Sminshall 			case TYPE_I:
94326048Sminshall 				setbinary();
94426048Sminshall 				break;
94526048Sminshall 			case TYPE_E:
94626048Sminshall 				setebcdic();
94726048Sminshall 				break;
94826048Sminshall 			case TYPE_L:
94926048Sminshall 				settenex();
95026048Sminshall 				break;
95126048Sminshall 		}
95226048Sminshall 		verbose = oldverbose;
95326048Sminshall 	}
95426048Sminshall 	return;
95526048Sminshall abort:
95626048Sminshall 
95727687Sminshall /* abort using RFC959 recommended IP,SYNC sequence  */
95826048Sminshall 
95926496Sminshall 	(void) gettimeofday(&stop, (struct timezone *)0);
96026448Slepreau 	if (oldintp)
96126048Sminshall 		(void) signal(SIGPIPE, oldintr);
96226048Sminshall 	(void) signal(SIGINT,SIG_IGN);
96326048Sminshall 	if (oldtype) {
96426448Slepreau 		if (!debug)
96526048Sminshall 			verbose = 0;
96626048Sminshall 		switch (oldtype) {
96726048Sminshall 			case TYPE_I:
96826048Sminshall 				setbinary();
96926048Sminshall 				break;
97026048Sminshall 			case TYPE_E:
97126048Sminshall 				setebcdic();
97226048Sminshall 				break;
97326048Sminshall 			case TYPE_L:
97426048Sminshall 				settenex();
97526048Sminshall 				break;
97626048Sminshall 		}
97726048Sminshall 		verbose = oldverbose;
97826048Sminshall 	}
97926048Sminshall 	if (!cpend) {
98026048Sminshall 		code = -1;
98126048Sminshall 		(void) signal(SIGINT,oldintr);
98226048Sminshall 		return;
98326048Sminshall 	}
98426048Sminshall 
98527687Sminshall 	fprintf(cout,"%c%c",IAC,IP);
98627687Sminshall 	(void) fflush(cout);
98727687Sminshall 	msg = IAC;
98827687Sminshall /* send IAC in urgent mode instead of DM because UNIX places oob mark */
98927687Sminshall /* after urgent byte rather than before as now is protocol            */
99027687Sminshall 	if (send(fileno(cout),&msg,1,MSG_OOB) != 1) {
99127687Sminshall 		perror("abort");
99226048Sminshall 	}
99327687Sminshall 	fprintf(cout,"%cABOR\r\n",DM);
99426048Sminshall 	(void) fflush(cout);
99527687Sminshall 	FD_ZERO(&mask);
99626496Sminshall 	FD_SET(fileno(cin), &mask);
99726496Sminshall 	if (din) {
99826496Sminshall 		FD_SET(fileno(din), &mask);
99926496Sminshall 	}
100027687Sminshall 	if ((nfnd = empty(&mask,10)) <= 0) {
100127687Sminshall 		if (nfnd < 0) {
100227687Sminshall 			perror("abort");
100327687Sminshall 		}
100426048Sminshall 		code = -1;
100526048Sminshall 		lostpeer();
100626048Sminshall 	}
100726496Sminshall 	if (din && FD_ISSET(fileno(din), &mask)) {
100836940Skarels 		while ((c = read(fileno(din), buf, bufsize)) > 0)
100926448Slepreau 			;
101026496Sminshall 	}
101127687Sminshall 	if ((c = getreply(0)) == ERROR && code == 552) { /* needed for nic style abort */
101226048Sminshall 		if (data >= 0) {
101326496Sminshall 			(void) close(data);
101426048Sminshall 			data = -1;
101526048Sminshall 		}
101625907Smckusick 		(void) getreply(0);
101725907Smckusick 	}
101826048Sminshall 	(void) getreply(0);
101926048Sminshall 	code = -1;
102026048Sminshall 	if (data >= 0) {
102126048Sminshall 		(void) close(data);
102226048Sminshall 		data = -1;
102326048Sminshall 	}
102426448Slepreau 	if (closefunc != NULL && fout != NULL)
102526048Sminshall 		(*closefunc)(fout);
102626448Slepreau 	if (din)
102726048Sminshall 		(void) fclose(din);
102835699Sbostic 	if (bytes > 0)
102937225Skarels 		ptransfer("received", bytes, &start, &stop);
103026048Sminshall 	(void) signal(SIGINT,oldintr);
103110296Ssam }
103210296Ssam 
103310296Ssam /*
103410296Ssam  * Need to start a listen on the data channel
103510296Ssam  * before we send the command, otherwise the
103610296Ssam  * server's connect may fail.
103710296Ssam  */
103833224Sbostic int sendport = -1;
103911651Ssam 
104010296Ssam initconn()
104110296Ssam {
104210296Ssam 	register char *p, *a;
104326048Sminshall 	int result, len, tmpno = 0;
104426993Skarels 	int on = 1;
104510296Ssam 
104611651Ssam noport:
104710296Ssam 	data_addr = myctladdr;
104811651Ssam 	if (sendport)
104911651Ssam 		data_addr.sin_port = 0;	/* let system pick one */
105011651Ssam 	if (data != -1)
105111651Ssam 		(void) close (data);
105218287Sralph 	data = socket(AF_INET, SOCK_STREAM, 0);
105310296Ssam 	if (data < 0) {
105410296Ssam 		perror("ftp: socket");
105526448Slepreau 		if (tmpno)
105626048Sminshall 			sendport = 1;
105710296Ssam 		return (1);
105810296Ssam 	}
105912397Ssam 	if (!sendport)
106027687Sminshall 		if (setsockopt(data, SOL_SOCKET, SO_REUSEADDR, (char *)&on, sizeof (on)) < 0) {
106133224Sbostic 			perror("ftp: setsockopt (reuse address)");
106212397Ssam 			goto bad;
106312397Ssam 		}
106426496Sminshall 	if (bind(data, (struct sockaddr *)&data_addr, sizeof (data_addr)) < 0) {
106510296Ssam 		perror("ftp: bind");
106610296Ssam 		goto bad;
106710296Ssam 	}
106810296Ssam 	if (options & SO_DEBUG &&
106927687Sminshall 	    setsockopt(data, SOL_SOCKET, SO_DEBUG, (char *)&on, sizeof (on)) < 0)
107010296Ssam 		perror("ftp: setsockopt (ignored)");
107111627Ssam 	len = sizeof (data_addr);
107211627Ssam 	if (getsockname(data, (char *)&data_addr, &len) < 0) {
107311627Ssam 		perror("ftp: getsockname");
107410296Ssam 		goto bad;
107510296Ssam 	}
107626448Slepreau 	if (listen(data, 1) < 0)
107710296Ssam 		perror("ftp: listen");
107811651Ssam 	if (sendport) {
107911651Ssam 		a = (char *)&data_addr.sin_addr;
108011651Ssam 		p = (char *)&data_addr.sin_port;
108110296Ssam #define	UC(b)	(((int)b)&0xff)
108211651Ssam 		result =
108311651Ssam 		    command("PORT %d,%d,%d,%d,%d,%d",
108411651Ssam 		      UC(a[0]), UC(a[1]), UC(a[2]), UC(a[3]),
108511651Ssam 		      UC(p[0]), UC(p[1]));
108611651Ssam 		if (result == ERROR && sendport == -1) {
108711651Ssam 			sendport = 0;
108826048Sminshall 			tmpno = 1;
108911651Ssam 			goto noport;
109011651Ssam 		}
109111651Ssam 		return (result != COMPLETE);
109211651Ssam 	}
109326448Slepreau 	if (tmpno)
109426048Sminshall 		sendport = 1;
109511651Ssam 	return (0);
109610296Ssam bad:
109710296Ssam 	(void) close(data), data = -1;
109826448Slepreau 	if (tmpno)
109926048Sminshall 		sendport = 1;
110010296Ssam 	return (1);
110110296Ssam }
110210296Ssam 
110310296Ssam FILE *
110410296Ssam dataconn(mode)
110510296Ssam 	char *mode;
110610296Ssam {
110710296Ssam 	struct sockaddr_in from;
110810296Ssam 	int s, fromlen = sizeof (from);
110910296Ssam 
111026496Sminshall 	s = accept(data, (struct sockaddr *) &from, &fromlen);
111110296Ssam 	if (s < 0) {
111210296Ssam 		perror("ftp: accept");
111310296Ssam 		(void) close(data), data = -1;
111410296Ssam 		return (NULL);
111510296Ssam 	}
111610296Ssam 	(void) close(data);
111710296Ssam 	data = s;
111810296Ssam 	return (fdopen(data, mode));
111910296Ssam }
112010296Ssam 
112137225Skarels ptransfer(direction, bytes, t0, t1)
112237225Skarels 	char *direction;
112311651Ssam 	long bytes;
112410296Ssam 	struct timeval *t0, *t1;
112510296Ssam {
112610296Ssam 	struct timeval td;
112716437Sleres 	float s, bs;
112810296Ssam 
112935699Sbostic 	if (verbose) {
113035699Sbostic 		tvsub(&td, t1, t0);
113135699Sbostic 		s = td.tv_sec + (td.tv_usec / 1000000.);
113210296Ssam #define	nz(x)	((x) == 0 ? 1 : (x))
113335699Sbostic 		bs = bytes / nz(s);
113435699Sbostic 		printf("%ld bytes %s in %.2g seconds (%.2g Kbytes/s)\n",
113535699Sbostic 		    bytes, direction, s, bs / 1024.);
113635699Sbostic 	}
113710296Ssam }
113810296Ssam 
113926496Sminshall /*tvadd(tsum, t0)
114010296Ssam 	struct timeval *tsum, *t0;
114110296Ssam {
114210296Ssam 
114310296Ssam 	tsum->tv_sec += t0->tv_sec;
114410296Ssam 	tsum->tv_usec += t0->tv_usec;
114510296Ssam 	if (tsum->tv_usec > 1000000)
114610296Ssam 		tsum->tv_sec++, tsum->tv_usec -= 1000000;
114726496Sminshall } */
114810296Ssam 
114910296Ssam tvsub(tdiff, t1, t0)
115010296Ssam 	struct timeval *tdiff, *t1, *t0;
115110296Ssam {
115210296Ssam 
115310296Ssam 	tdiff->tv_sec = t1->tv_sec - t0->tv_sec;
115410296Ssam 	tdiff->tv_usec = t1->tv_usec - t0->tv_usec;
115510296Ssam 	if (tdiff->tv_usec < 0)
115610296Ssam 		tdiff->tv_sec--, tdiff->tv_usec += 1000000;
115710296Ssam }
115826048Sminshall 
115926048Sminshall psabort()
116026048Sminshall {
116126048Sminshall 	extern int abrtflag;
116226048Sminshall 
116326048Sminshall 	abrtflag++;
116426048Sminshall }
116526048Sminshall 
116626048Sminshall pswitch(flag)
116726048Sminshall 	int flag;
116826048Sminshall {
116926048Sminshall 	extern int proxy, abrtflag;
117026048Sminshall 	int (*oldintr)();
117126048Sminshall 	static struct comvars {
117226048Sminshall 		int connect;
117328469Skarels 		char name[MAXHOSTNAMELEN];
117426048Sminshall 		struct sockaddr_in mctl;
117526048Sminshall 		struct sockaddr_in hctl;
117626048Sminshall 		FILE *in;
117726048Sminshall 		FILE *out;
117826048Sminshall 		int tpe;
117926048Sminshall 		int cpnd;
118026048Sminshall 		int sunqe;
118126048Sminshall 		int runqe;
118226048Sminshall 		int mcse;
118326048Sminshall 		int ntflg;
118426048Sminshall 		char nti[17];
118526048Sminshall 		char nto[17];
118626048Sminshall 		int mapflg;
118726048Sminshall 		char mi[MAXPATHLEN];
118826048Sminshall 		char mo[MAXPATHLEN];
118926048Sminshall 		} proxstruct, tmpstruct;
119026048Sminshall 	struct comvars *ip, *op;
119126048Sminshall 
119226048Sminshall 	abrtflag = 0;
119326048Sminshall 	oldintr = signal(SIGINT, psabort);
119426048Sminshall 	if (flag) {
119526448Slepreau 		if (proxy)
119626048Sminshall 			return;
119726048Sminshall 		ip = &tmpstruct;
119826048Sminshall 		op = &proxstruct;
119926048Sminshall 		proxy++;
120026048Sminshall 	}
120126048Sminshall 	else {
120226448Slepreau 		if (!proxy)
120326048Sminshall 			return;
120426048Sminshall 		ip = &proxstruct;
120526048Sminshall 		op = &tmpstruct;
120626048Sminshall 		proxy = 0;
120726048Sminshall 	}
120826048Sminshall 	ip->connect = connected;
120926048Sminshall 	connected = op->connect;
121028469Skarels 	if (hostname) {
121128469Skarels 		(void) strncpy(ip->name, hostname, sizeof(ip->name) - 1);
121228469Skarels 		ip->name[strlen(ip->name)] = '\0';
121328469Skarels 	} else
121428469Skarels 		ip->name[0] = 0;
121526048Sminshall 	hostname = op->name;
121626048Sminshall 	ip->hctl = hisctladdr;
121726048Sminshall 	hisctladdr = op->hctl;
121826048Sminshall 	ip->mctl = myctladdr;
121926048Sminshall 	myctladdr = op->mctl;
122026048Sminshall 	ip->in = cin;
122126048Sminshall 	cin = op->in;
122226048Sminshall 	ip->out = cout;
122326048Sminshall 	cout = op->out;
122426048Sminshall 	ip->tpe = type;
122526048Sminshall 	type = op->tpe;
122626448Slepreau 	if (!type)
122726048Sminshall 		type = 1;
122826048Sminshall 	ip->cpnd = cpend;
122926048Sminshall 	cpend = op->cpnd;
123026048Sminshall 	ip->sunqe = sunique;
123126048Sminshall 	sunique = op->sunqe;
123226048Sminshall 	ip->runqe = runique;
123326048Sminshall 	runique = op->runqe;
123426048Sminshall 	ip->mcse = mcase;
123526048Sminshall 	mcase = op->mcse;
123626048Sminshall 	ip->ntflg = ntflag;
123726048Sminshall 	ntflag = op->ntflg;
123826496Sminshall 	(void) strncpy(ip->nti, ntin, 16);
123926048Sminshall 	(ip->nti)[strlen(ip->nti)] = '\0';
124026496Sminshall 	(void) strcpy(ntin, op->nti);
124126496Sminshall 	(void) strncpy(ip->nto, ntout, 16);
124226048Sminshall 	(ip->nto)[strlen(ip->nto)] = '\0';
124326496Sminshall 	(void) strcpy(ntout, op->nto);
124426048Sminshall 	ip->mapflg = mapflag;
124526048Sminshall 	mapflag = op->mapflg;
124626496Sminshall 	(void) strncpy(ip->mi, mapin, MAXPATHLEN - 1);
124726048Sminshall 	(ip->mi)[strlen(ip->mi)] = '\0';
124826496Sminshall 	(void) strcpy(mapin, op->mi);
124926496Sminshall 	(void) strncpy(ip->mo, mapout, MAXPATHLEN - 1);
125026048Sminshall 	(ip->mo)[strlen(ip->mo)] = '\0';
125126496Sminshall 	(void) strcpy(mapout, op->mo);
125226048Sminshall 	(void) signal(SIGINT, oldintr);
125326048Sminshall 	if (abrtflag) {
125426048Sminshall 		abrtflag = 0;
125526048Sminshall 		(*oldintr)();
125626448Slepreau 	}
125726048Sminshall }
125826048Sminshall 
125926048Sminshall jmp_buf ptabort;
126026048Sminshall int ptabflg;
126126048Sminshall 
126226048Sminshall abortpt()
126326048Sminshall {
126426048Sminshall 	printf("\n");
126526496Sminshall 	(void) fflush(stdout);
126626048Sminshall 	ptabflg++;
126726048Sminshall 	mflag = 0;
126826048Sminshall 	abrtflag = 0;
126926048Sminshall 	longjmp(ptabort, 1);
127026048Sminshall }
127126048Sminshall 
127226048Sminshall proxtrans(cmd, local, remote)
127326048Sminshall 	char *cmd, *local, *remote;
127426048Sminshall {
127527687Sminshall 	int (*oldintr)(), abortpt(), tmptype, oldtype = 0, secndflag = 0, nfnd;
127626048Sminshall 	extern jmp_buf ptabort;
127726048Sminshall 	char *cmd2;
127826496Sminshall 	struct fd_set mask;
127926048Sminshall 
128026448Slepreau 	if (strcmp(cmd, "RETR"))
128126048Sminshall 		cmd2 = "RETR";
128226448Slepreau 	else
128326048Sminshall 		cmd2 = runique ? "STOU" : "STOR";
128426048Sminshall 	if (command("PASV") != COMPLETE) {
128526048Sminshall 		printf("proxy server does not support third part transfers.\n");
128626048Sminshall 		return;
128726048Sminshall 	}
128826048Sminshall 	tmptype = type;
128926048Sminshall 	pswitch(0);
129026048Sminshall 	if (!connected) {
129126048Sminshall 		printf("No primary connection\n");
129226048Sminshall 		pswitch(1);
129326048Sminshall 		code = -1;
129426048Sminshall 		return;
129526048Sminshall 	}
129626048Sminshall 	if (type != tmptype) {
129726048Sminshall 		oldtype = type;
129826048Sminshall 		switch (tmptype) {
129926048Sminshall 			case TYPE_A:
130026048Sminshall 				setascii();
130126048Sminshall 				break;
130226048Sminshall 			case TYPE_I:
130326048Sminshall 				setbinary();
130426048Sminshall 				break;
130526048Sminshall 			case TYPE_E:
130626048Sminshall 				setebcdic();
130726048Sminshall 				break;
130826048Sminshall 			case TYPE_L:
130926048Sminshall 				settenex();
131026048Sminshall 				break;
131126048Sminshall 		}
131226048Sminshall 	}
131326048Sminshall 	if (command("PORT %s", pasv) != COMPLETE) {
131426048Sminshall 		switch (oldtype) {
131526048Sminshall 			case 0:
131626048Sminshall 				break;
131726048Sminshall 			case TYPE_A:
131826048Sminshall 				setascii();
131926048Sminshall 				break;
132026048Sminshall 			case TYPE_I:
132126048Sminshall 				setbinary();
132226048Sminshall 				break;
132326048Sminshall 			case TYPE_E:
132426048Sminshall 				setebcdic();
132526048Sminshall 				break;
132626048Sminshall 			case TYPE_L:
132726048Sminshall 				settenex();
132826048Sminshall 				break;
132926048Sminshall 		}
133026048Sminshall 		pswitch(1);
133126048Sminshall 		return;
133226048Sminshall 	}
133326448Slepreau 	if (setjmp(ptabort))
133426048Sminshall 		goto abort;
133526048Sminshall 	oldintr = signal(SIGINT, abortpt);
133626048Sminshall 	if (command("%s %s", cmd, remote) != PRELIM) {
133726048Sminshall 		(void) signal(SIGINT, oldintr);
133826048Sminshall 		switch (oldtype) {
133926048Sminshall 			case 0:
134026048Sminshall 				break;
134126048Sminshall 			case TYPE_A:
134226048Sminshall 				setascii();
134326048Sminshall 				break;
134426048Sminshall 			case TYPE_I:
134526048Sminshall 				setbinary();
134626048Sminshall 				break;
134726048Sminshall 			case TYPE_E:
134826048Sminshall 				setebcdic();
134926048Sminshall 				break;
135026048Sminshall 			case TYPE_L:
135126048Sminshall 				settenex();
135226048Sminshall 				break;
135326048Sminshall 		}
135426048Sminshall 		pswitch(1);
135526048Sminshall 		return;
135626048Sminshall 	}
135726048Sminshall 	sleep(2);
135826048Sminshall 	pswitch(1);
135926048Sminshall 	secndflag++;
136026448Slepreau 	if (command("%s %s", cmd2, local) != PRELIM)
136126048Sminshall 		goto abort;
136226048Sminshall 	ptflag++;
136326048Sminshall 	(void) getreply(0);
136426048Sminshall 	pswitch(0);
136526048Sminshall 	(void) getreply(0);
136626048Sminshall 	(void) signal(SIGINT, oldintr);
136726048Sminshall 	switch (oldtype) {
136826048Sminshall 		case 0:
136926048Sminshall 			break;
137026048Sminshall 		case TYPE_A:
137126048Sminshall 			setascii();
137226048Sminshall 			break;
137326048Sminshall 		case TYPE_I:
137426048Sminshall 			setbinary();
137526048Sminshall 			break;
137626048Sminshall 		case TYPE_E:
137726048Sminshall 			setebcdic();
137826048Sminshall 			break;
137926048Sminshall 		case TYPE_L:
138026048Sminshall 			settenex();
138126048Sminshall 			break;
138226048Sminshall 	}
138326048Sminshall 	pswitch(1);
138426048Sminshall 	ptflag = 0;
138526048Sminshall 	printf("local: %s remote: %s\n", local, remote);
138626048Sminshall 	return;
138726048Sminshall abort:
138826048Sminshall 	(void) signal(SIGINT, SIG_IGN);
138926048Sminshall 	ptflag = 0;
139026448Slepreau 	if (strcmp(cmd, "RETR") && !proxy)
139126048Sminshall 		pswitch(1);
139226448Slepreau 	else if (!strcmp(cmd, "RETR") && proxy)
139326048Sminshall 		pswitch(0);
139426048Sminshall 	if (!cpend && !secndflag) {  /* only here if cmd = "STOR" (proxy=1) */
139526048Sminshall 		if (command("%s %s", cmd2, local) != PRELIM) {
139626048Sminshall 			pswitch(0);
139726048Sminshall 			switch (oldtype) {
139826048Sminshall 				case 0:
139926048Sminshall 					break;
140026048Sminshall 				case TYPE_A:
140126048Sminshall 					setascii();
140226048Sminshall 					break;
140326048Sminshall 				case TYPE_I:
140426048Sminshall 					setbinary();
140526048Sminshall 					break;
140626048Sminshall 				case TYPE_E:
140726048Sminshall 					setebcdic();
140826048Sminshall 					break;
140926048Sminshall 				case TYPE_L:
141026048Sminshall 					settenex();
141126048Sminshall 					break;
141226048Sminshall 			}
141327687Sminshall 			if (cpend) {
141426048Sminshall 				char msg[2];
141526048Sminshall 
141626048Sminshall 				fprintf(cout,"%c%c",IAC,IP);
141726048Sminshall 				(void) fflush(cout);
141826048Sminshall 				*msg = IAC;
141926048Sminshall 				*(msg+1) = DM;
142026448Slepreau 				if (send(fileno(cout),msg,2,MSG_OOB) != 2)
142126048Sminshall 					perror("abort");
142226048Sminshall 				fprintf(cout,"ABOR\r\n");
142326048Sminshall 				(void) fflush(cout);
142427687Sminshall 				FD_ZERO(&mask);
142526496Sminshall 				FD_SET(fileno(cin), &mask);
142627687Sminshall 				if ((nfnd = empty(&mask,10)) <= 0) {
142727687Sminshall 					if (nfnd < 0) {
142827687Sminshall 						perror("abort");
142927687Sminshall 					}
143026448Slepreau 					if (ptabflg)
143126048Sminshall 						code = -1;
143226048Sminshall 					lostpeer();
143326048Sminshall 				}
143426048Sminshall 				(void) getreply(0);
143526048Sminshall 				(void) getreply(0);
143626048Sminshall 			}
143726048Sminshall 		}
143826048Sminshall 		pswitch(1);
143926448Slepreau 		if (ptabflg)
144026048Sminshall 			code = -1;
144126048Sminshall 		(void) signal(SIGINT, oldintr);
144226048Sminshall 		return;
144326048Sminshall 	}
144427687Sminshall 	if (cpend) {
144526048Sminshall 		char msg[2];
144626048Sminshall 
144726048Sminshall 		fprintf(cout,"%c%c",IAC,IP);
144826048Sminshall 		(void) fflush(cout);
144926048Sminshall 		*msg = IAC;
145026048Sminshall 		*(msg+1) = DM;
145126448Slepreau 		if (send(fileno(cout),msg,2,MSG_OOB) != 2)
145226048Sminshall 			perror("abort");
145326048Sminshall 		fprintf(cout,"ABOR\r\n");
145426048Sminshall 		(void) fflush(cout);
145527687Sminshall 		FD_ZERO(&mask);
145626496Sminshall 		FD_SET(fileno(cin), &mask);
145727687Sminshall 		if ((nfnd = empty(&mask,10)) <= 0) {
145827687Sminshall 			if (nfnd < 0) {
145927687Sminshall 				perror("abort");
146027687Sminshall 			}
146126448Slepreau 			if (ptabflg)
146226048Sminshall 				code = -1;
146326048Sminshall 			lostpeer();
146426048Sminshall 		}
146526048Sminshall 		(void) getreply(0);
146626048Sminshall 		(void) getreply(0);
146726048Sminshall 	}
146826048Sminshall 	pswitch(!proxy);
146926048Sminshall 	if (!cpend && !secndflag) {  /* only if cmd = "RETR" (proxy=1) */
147026048Sminshall 		if (command("%s %s", cmd2, local) != PRELIM) {
147126048Sminshall 			pswitch(0);
147226048Sminshall 			switch (oldtype) {
147326048Sminshall 				case 0:
147426048Sminshall 					break;
147526048Sminshall 				case TYPE_A:
147626048Sminshall 					setascii();
147726048Sminshall 					break;
147826048Sminshall 				case TYPE_I:
147926048Sminshall 					setbinary();
148026048Sminshall 					break;
148126048Sminshall 				case TYPE_E:
148226048Sminshall 					setebcdic();
148326048Sminshall 					break;
148426048Sminshall 				case TYPE_L:
148526048Sminshall 					settenex();
148626048Sminshall 					break;
148726048Sminshall 			}
148827687Sminshall 			if (cpend) {
148926048Sminshall 				char msg[2];
149026048Sminshall 
149126048Sminshall 				fprintf(cout,"%c%c",IAC,IP);
149226048Sminshall 				(void) fflush(cout);
149326048Sminshall 				*msg = IAC;
149426048Sminshall 				*(msg+1) = DM;
149526448Slepreau 				if (send(fileno(cout),msg,2,MSG_OOB) != 2)
149626048Sminshall 					perror("abort");
149726048Sminshall 				fprintf(cout,"ABOR\r\n");
149826048Sminshall 				(void) fflush(cout);
149927687Sminshall 				FD_ZERO(&mask);
150026496Sminshall 				FD_SET(fileno(cin), &mask);
150127687Sminshall 				if ((nfnd = empty(&mask,10)) <= 0) {
150227687Sminshall 					if (nfnd < 0) {
150327687Sminshall 						perror("abort");
150427687Sminshall 					}
150526448Slepreau 					if (ptabflg)
150626048Sminshall 						code = -1;
150726048Sminshall 					lostpeer();
150826048Sminshall 				}
150926048Sminshall 				(void) getreply(0);
151026048Sminshall 				(void) getreply(0);
151126048Sminshall 			}
151226048Sminshall 			pswitch(1);
151326448Slepreau 			if (ptabflg)
151426048Sminshall 				code = -1;
151526048Sminshall 			(void) signal(SIGINT, oldintr);
151626048Sminshall 			return;
151726048Sminshall 		}
151826048Sminshall 	}
151927687Sminshall 	if (cpend) {
152026048Sminshall 		char msg[2];
152126048Sminshall 
152226048Sminshall 		fprintf(cout,"%c%c",IAC,IP);
152326048Sminshall 		(void) fflush(cout);
152426048Sminshall 		*msg = IAC;
152526048Sminshall 		*(msg+1) = DM;
152626448Slepreau 		if (send(fileno(cout),msg,2,MSG_OOB) != 2)
152726048Sminshall 			perror("abort");
152826048Sminshall 		fprintf(cout,"ABOR\r\n");
152926048Sminshall 		(void) fflush(cout);
153027687Sminshall 		FD_ZERO(&mask);
153126496Sminshall 		FD_SET(fileno(cin), &mask);
153227687Sminshall 		if ((nfnd = empty(&mask,10)) <= 0) {
153327687Sminshall 			if (nfnd < 0) {
153427687Sminshall 				perror("abort");
153527687Sminshall 			}
153626448Slepreau 			if (ptabflg)
153726048Sminshall 				code = -1;
153826048Sminshall 			lostpeer();
153926048Sminshall 		}
154026048Sminshall 		(void) getreply(0);
154126048Sminshall 		(void) getreply(0);
154226048Sminshall 	}
154326048Sminshall 	pswitch(!proxy);
154426048Sminshall 	if (cpend) {
154527687Sminshall 		FD_ZERO(&mask);
154626496Sminshall 		FD_SET(fileno(cin), &mask);
154727687Sminshall 		if ((nfnd = empty(&mask,10)) <= 0) {
154827687Sminshall 			if (nfnd < 0) {
154927687Sminshall 				perror("abort");
155027687Sminshall 			}
155126448Slepreau 			if (ptabflg)
155226048Sminshall 				code = -1;
155326048Sminshall 			lostpeer();
155426048Sminshall 		}
155526048Sminshall 		(void) getreply(0);
155626048Sminshall 		(void) getreply(0);
155726048Sminshall 	}
155826448Slepreau 	if (proxy)
155926048Sminshall 		pswitch(0);
156026048Sminshall 	switch (oldtype) {
156126048Sminshall 		case 0:
156226048Sminshall 			break;
156326048Sminshall 		case TYPE_A:
156426048Sminshall 			setascii();
156526048Sminshall 			break;
156626048Sminshall 		case TYPE_I:
156726048Sminshall 			setbinary();
156826048Sminshall 			break;
156926048Sminshall 		case TYPE_E:
157026048Sminshall 			setebcdic();
157126048Sminshall 			break;
157226048Sminshall 		case TYPE_L:
157326048Sminshall 			settenex();
157426048Sminshall 			break;
157526048Sminshall 	}
157626048Sminshall 	pswitch(1);
157726448Slepreau 	if (ptabflg)
157826048Sminshall 		code = -1;
157926048Sminshall 	(void) signal(SIGINT, oldintr);
158026048Sminshall }
158126048Sminshall 
158226048Sminshall reset()
158326048Sminshall {
158426496Sminshall 	struct fd_set mask;
158526496Sminshall 	int nfnd = 1;
158626048Sminshall 
158727687Sminshall 	FD_ZERO(&mask);
158830946Scsvsj 	while (nfnd > 0) {
158926496Sminshall 		FD_SET(fileno(cin), &mask);
159027687Sminshall 		if ((nfnd = empty(&mask,0)) < 0) {
159126048Sminshall 			perror("reset");
159226048Sminshall 			code = -1;
159326048Sminshall 			lostpeer();
159426048Sminshall 		}
159527687Sminshall 		else if (nfnd) {
159626048Sminshall 			(void) getreply(0);
159726496Sminshall 		}
159826048Sminshall 	}
159926048Sminshall }
160026048Sminshall 
160126048Sminshall char *
160226048Sminshall gunique(local)
160326048Sminshall 	char *local;
160426048Sminshall {
160526048Sminshall 	static char new[MAXPATHLEN];
160626048Sminshall 	char *cp = rindex(local, '/');
160726048Sminshall 	int d, count=0;
160826048Sminshall 	char ext = '1';
160926048Sminshall 
161026448Slepreau 	if (cp)
161126048Sminshall 		*cp = '\0';
161226048Sminshall 	d = access(cp ? local : ".", 2);
161326448Slepreau 	if (cp)
161426048Sminshall 		*cp = '/';
161526048Sminshall 	if (d < 0) {
161626048Sminshall 		perror(local);
161726048Sminshall 		return((char *) 0);
161826048Sminshall 	}
161926048Sminshall 	(void) strcpy(new, local);
162026048Sminshall 	cp = new + strlen(new);
162126048Sminshall 	*cp++ = '.';
162226048Sminshall 	while (!d) {
162326048Sminshall 		if (++count == 100) {
162426048Sminshall 			printf("runique: can't find unique file name.\n");
162526048Sminshall 			return((char *) 0);
162626048Sminshall 		}
162726048Sminshall 		*cp++ = ext;
162826048Sminshall 		*cp = '\0';
162926448Slepreau 		if (ext == '9')
163026048Sminshall 			ext = '0';
163126448Slepreau 		else
163226048Sminshall 			ext++;
163326448Slepreau 		if ((d = access(new, 0)) < 0)
163426048Sminshall 			break;
163526448Slepreau 		if (ext != '0')
163626048Sminshall 			cp--;
163726448Slepreau 		else if (*(cp - 2) == '.')
163826048Sminshall 			*(cp - 1) = '1';
163926048Sminshall 		else {
164026048Sminshall 			*(cp - 2) = *(cp - 2) + 1;
164126048Sminshall 			cp--;
164226048Sminshall 		}
164326048Sminshall 	}
164426048Sminshall 	return(new);
164526048Sminshall }
1646