xref: /csrg-svn/usr.bin/ftp/ftp.c (revision 37229)
1 /*
2  * Copyright (c) 1985, 1989 Regents of the University of California.
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms are permitted
6  * provided that the above copyright notice and this paragraph are
7  * duplicated in all such forms and that any documentation,
8  * advertising materials, and other materials related to such
9  * distribution and use acknowledge that the software was developed
10  * by the University of California, Berkeley.  The name of the
11  * University may not be used to endorse or promote products derived
12  * from this software without specific prior written permission.
13  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
14  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
15  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
16  */
17 
18 #ifndef lint
19 static char sccsid[] = "@(#)ftp.c	5.27 (Berkeley) 03/23/89";
20 #endif /* not lint */
21 
22 #include <sys/param.h>
23 #include <sys/stat.h>
24 #include <sys/ioctl.h>
25 #include <sys/socket.h>
26 #include <sys/time.h>
27 #include <sys/file.h>
28 
29 #include <netinet/in.h>
30 #include <arpa/ftp.h>
31 #include <arpa/telnet.h>
32 
33 #include <stdio.h>
34 #include <signal.h>
35 #include <errno.h>
36 #include <netdb.h>
37 #include <fcntl.h>
38 #include <pwd.h>
39 
40 #include "ftp_var.h"
41 
42 struct	sockaddr_in hisctladdr;
43 struct	sockaddr_in data_addr;
44 int	data = -1;
45 int	abrtflag = 0;
46 int	ptflag = 0;
47 int	connected;
48 struct	sockaddr_in myctladdr;
49 uid_t	getuid();
50 off_t	restart_point = 0;
51 
52 FILE	*cin, *cout;
53 FILE	*dataconn();
54 
55 char *
56 hookup(host, port)
57 	char *host;
58 	int port;
59 {
60 	register struct hostent *hp = 0;
61 	int s,len;
62 	static char hostnamebuf[80];
63 
64 	bzero((char *)&hisctladdr, sizeof (hisctladdr));
65 	hisctladdr.sin_addr.s_addr = inet_addr(host);
66 	if (hisctladdr.sin_addr.s_addr != -1) {
67 		hisctladdr.sin_family = AF_INET;
68 		(void) strncpy(hostnamebuf, host, sizeof(hostnamebuf));
69 	} else {
70 		hp = gethostbyname(host);
71 		if (hp == NULL) {
72 			fprintf(stderr, "ftp: %s: ", host);
73 			herror((char *)NULL);
74 			code = -1;
75 			return((char *) 0);
76 		}
77 		hisctladdr.sin_family = hp->h_addrtype;
78 		bcopy(hp->h_addr_list[0],
79 		    (caddr_t)&hisctladdr.sin_addr, hp->h_length);
80 		(void) strncpy(hostnamebuf, hp->h_name, sizeof(hostnamebuf));
81 	}
82 	hostname = hostnamebuf;
83 	s = socket(hisctladdr.sin_family, SOCK_STREAM, 0);
84 	if (s < 0) {
85 		perror("ftp: socket");
86 		code = -1;
87 		return (0);
88 	}
89 	hisctladdr.sin_port = port;
90 	while (connect(s, &hisctladdr, sizeof (hisctladdr)) < 0) {
91 		if (hp && hp->h_addr_list[1]) {
92 			int oerrno = errno;
93 
94 			fprintf(stderr, "ftp: connect to address %s: ",
95 				inet_ntoa(hisctladdr.sin_addr));
96 			errno = oerrno;
97 			perror((char *) 0);
98 			hp->h_addr_list++;
99 			bcopy(hp->h_addr_list[0],
100 			     (caddr_t)&hisctladdr.sin_addr, hp->h_length);
101 			fprintf(stdout, "Trying %s...\n",
102 				inet_ntoa(hisctladdr.sin_addr));
103 			(void) close(s);
104 			s = socket(hisctladdr.sin_family, SOCK_STREAM, 0);
105 			if (s < 0) {
106 				perror("ftp: socket");
107 				code = -1;
108 				return (0);
109 			}
110 			continue;
111 		}
112 		perror("ftp: connect");
113 		code = -1;
114 		goto bad;
115 	}
116 	len = sizeof (myctladdr);
117 	if (getsockname(s, (char *)&myctladdr, &len) < 0) {
118 		perror("ftp: getsockname");
119 		code = -1;
120 		goto bad;
121 	}
122 	cin = fdopen(s, "r");
123 	cout = fdopen(s, "w");
124 	if (cin == NULL || cout == NULL) {
125 		fprintf(stderr, "ftp: fdopen failed.\n");
126 		if (cin)
127 			(void) fclose(cin);
128 		if (cout)
129 			(void) fclose(cout);
130 		code = -1;
131 		goto bad;
132 	}
133 	if (verbose)
134 		printf("Connected to %s.\n", hostname);
135 	if (getreply(0) > 2) { 	/* read startup message from server */
136 		if (cin)
137 			(void) fclose(cin);
138 		if (cout)
139 			(void) fclose(cout);
140 		code = -1;
141 		goto bad;
142 	}
143 #ifdef SO_OOBINLINE
144 	{
145 	int on = 1;
146 
147 	if (setsockopt(s, SOL_SOCKET, SO_OOBINLINE, &on, sizeof(on))
148 		< 0 && debug) {
149 			perror("ftp: setsockopt");
150 		}
151 	}
152 #endif SO_OOBINLINE
153 
154 	return (hostname);
155 bad:
156 	(void) close(s);
157 	return ((char *)0);
158 }
159 
160 login(host)
161 	char *host;
162 {
163 	char tmp[80];
164 	char *user, *pass, *acct, *getlogin(), *getpass();
165 	int n, aflag = 0;
166 
167 	user = pass = acct = 0;
168 	if (ruserpass(host, &user, &pass, &acct) < 0) {
169 		code = -1;
170 		return(0);
171 	}
172 	if (user == NULL) {
173 		char *myname = getlogin();
174 
175 		if (myname == NULL) {
176 			struct passwd *pp = getpwuid(getuid());
177 
178 			if (pp != NULL)
179 				myname = pp->pw_name;
180 		}
181 		printf("Name (%s:%s): ", host, myname);
182 		(void) fgets(tmp, sizeof(tmp) - 1, stdin);
183 		tmp[strlen(tmp) - 1] = '\0';
184 		if (*tmp == '\0')
185 			user = myname;
186 		else
187 			user = tmp;
188 	}
189 	n = command("USER %s", user);
190 	if (n == CONTINUE) {
191 		if (pass == NULL)
192 			pass = getpass("Password:");
193 		n = command("PASS %s", pass);
194 	}
195 	if (n == CONTINUE) {
196 		aflag++;
197 		acct = getpass("Account:");
198 		n = command("ACCT %s", acct);
199 	}
200 	if (n != COMPLETE) {
201 		fprintf(stderr, "Login failed.\n");
202 		return (0);
203 	}
204 	if (!aflag && acct != NULL)
205 		(void) command("ACCT %s", acct);
206 	if (proxy)
207 		return(1);
208 	for (n = 0; n < macnum; ++n) {
209 		if (!strcmp("init", macros[n].mac_name)) {
210 			(void) strcpy(line, "$init");
211 			makeargv();
212 			domacro(margc, margv);
213 			break;
214 		}
215 	}
216 	return (1);
217 }
218 
219 cmdabort()
220 {
221 	extern jmp_buf ptabort;
222 
223 	printf("\n");
224 	(void) fflush(stdout);
225 	abrtflag++;
226 	if (ptflag)
227 		longjmp(ptabort,1);
228 }
229 
230 /*VARARGS1*/
231 command(fmt, args)
232 	char *fmt;
233 {
234 	int r, (*oldintr)(), cmdabort();
235 
236 	abrtflag = 0;
237 	if (debug) {
238 		printf("---> ");
239 		_doprnt(fmt, &args, stdout);
240 		printf("\n");
241 		(void) fflush(stdout);
242 	}
243 	if (cout == NULL) {
244 		perror ("No control connection for command");
245 		code = -1;
246 		return (0);
247 	}
248 	oldintr = signal(SIGINT,cmdabort);
249 	_doprnt(fmt, &args, cout);
250 	fprintf(cout, "\r\n");
251 	(void) fflush(cout);
252 	cpend = 1;
253 	r = getreply(!strcmp(fmt, "QUIT"));
254 	if (abrtflag && oldintr != SIG_IGN)
255 		(*oldintr)();
256 	(void) signal(SIGINT, oldintr);
257 	return(r);
258 }
259 
260 char reply_string[BUFSIZ];		/* last line of previous reply */
261 
262 #include <ctype.h>
263 
264 getreply(expecteof)
265 	int expecteof;
266 {
267 	register int c, n;
268 	register int dig;
269 	register char *cp;
270 	int originalcode = 0, continuation = 0, (*oldintr)(), cmdabort();
271 	int pflag = 0;
272 	char *pt = pasv;
273 
274 	oldintr = signal(SIGINT,cmdabort);
275 	for (;;) {
276 		dig = n = code = 0;
277 		cp = reply_string;
278 		while ((c = getc(cin)) != '\n') {
279 			if (c == IAC) {     /* handle telnet commands */
280 				switch (c = getc(cin)) {
281 				case WILL:
282 				case WONT:
283 					c = getc(cin);
284 					fprintf(cout, "%c%c%c",IAC,DONT,c);
285 					(void) fflush(cout);
286 					break;
287 				case DO:
288 				case DONT:
289 					c = getc(cin);
290 					fprintf(cout, "%c%c%c",IAC,WONT,c);
291 					(void) fflush(cout);
292 					break;
293 				default:
294 					break;
295 				}
296 				continue;
297 			}
298 			dig++;
299 			if (c == EOF) {
300 				if (expecteof) {
301 					(void) signal(SIGINT,oldintr);
302 					code = 221;
303 					return (0);
304 				}
305 				lostpeer();
306 				if (verbose) {
307 					printf("421 Service not available, remote server has closed connection\n");
308 					(void) fflush(stdout);
309 				}
310 				code = 421;
311 				return(4);
312 			}
313 			if (c != '\r' && (verbose > 0 ||
314 			    (verbose > -1 && n == '5' && dig > 4))) {
315 				if (proxflag &&
316 				   (dig == 1 || dig == 5 && verbose == 0))
317 					printf("%s:",hostname);
318 				(void) putchar(c);
319 			}
320 			if (dig < 4 && isdigit(c))
321 				code = code * 10 + (c - '0');
322 			if (!pflag && code == 227)
323 				pflag = 1;
324 			if (dig > 4 && pflag == 1 && isdigit(c))
325 				pflag = 2;
326 			if (pflag == 2) {
327 				if (c != '\r' && c != ')')
328 					*pt++ = c;
329 				else {
330 					*pt = '\0';
331 					pflag = 3;
332 				}
333 			}
334 			if (dig == 4 && c == '-') {
335 				if (continuation)
336 					code = 0;
337 				continuation++;
338 			}
339 			if (n == 0)
340 				n = c;
341 			if (cp < &reply_string[sizeof(reply_string) - 1])
342 				*cp++ = c;
343 		}
344 		if (verbose > 0 || verbose > -1 && n == '5') {
345 			(void) putchar(c);
346 			(void) fflush (stdout);
347 		}
348 		if (continuation && code != originalcode) {
349 			if (originalcode == 0)
350 				originalcode = code;
351 			continue;
352 		}
353 		*cp = '\0';
354 		if (n != '1')
355 			cpend = 0;
356 		(void) signal(SIGINT,oldintr);
357 		if (code == 421 || originalcode == 421)
358 			lostpeer();
359 		if (abrtflag && oldintr != cmdabort && oldintr != SIG_IGN)
360 			(*oldintr)();
361 		return (n - '0');
362 	}
363 }
364 
365 empty(mask, sec)
366 	struct fd_set *mask;
367 	int sec;
368 {
369 	struct timeval t;
370 
371 	t.tv_sec = (long) sec;
372 	t.tv_usec = 0;
373 	return(select(32, mask, (struct fd_set *) 0, (struct fd_set *) 0, &t));
374 }
375 
376 jmp_buf	sendabort;
377 
378 abortsend()
379 {
380 
381 	mflag = 0;
382 	abrtflag = 0;
383 	printf("\nsend aborted\n");
384 	(void) fflush(stdout);
385 	longjmp(sendabort, 1);
386 }
387 
388 #define HASHBYTES 1024
389 
390 sendrequest(cmd, local, remote, printnames)
391 	char *cmd, *local, *remote;
392 	int printnames;
393 {
394 	FILE *fin, *dout = 0, *popen();
395 	int (*closefunc)(), pclose(), fclose(), (*oldintr)(), (*oldintp)();
396 	int abortsend();
397 	char buf[BUFSIZ], *bufp;
398 	long bytes = 0, hashbytes = HASHBYTES;
399 	register int c, d;
400 	struct stat st;
401 	struct timeval start, stop;
402 	char *mode;
403 
404 	if (verbose && printnames) {
405 		if (local && *local != '-')
406 			printf("local: %s ", local);
407 		if (remote)
408 			printf("remote: %s\n", remote);
409 	}
410 	if (proxy) {
411 		proxtrans(cmd, local, remote);
412 		return;
413 	}
414 	closefunc = NULL;
415 	oldintr = NULL;
416 	oldintp = NULL;
417 	mode = "w";
418 	if (setjmp(sendabort)) {
419 		while (cpend) {
420 			(void) getreply(0);
421 		}
422 		if (data >= 0) {
423 			(void) close(data);
424 			data = -1;
425 		}
426 		if (oldintr)
427 			(void) signal(SIGINT,oldintr);
428 		if (oldintp)
429 			(void) signal(SIGPIPE,oldintp);
430 		code = -1;
431 		return;
432 	}
433 	oldintr = signal(SIGINT, abortsend);
434 	if (strcmp(local, "-") == 0)
435 		fin = stdin;
436 	else if (*local == '|') {
437 		oldintp = signal(SIGPIPE,SIG_IGN);
438 		fin = popen(local + 1, "r");
439 		if (fin == NULL) {
440 			perror(local + 1);
441 			(void) signal(SIGINT, oldintr);
442 			(void) signal(SIGPIPE, oldintp);
443 			code = -1;
444 			return;
445 		}
446 		closefunc = pclose;
447 	} else {
448 		fin = fopen(local, "r");
449 		if (fin == NULL) {
450 			perror(local);
451 			(void) signal(SIGINT, oldintr);
452 			code = -1;
453 			return;
454 		}
455 		closefunc = fclose;
456 		if (fstat(fileno(fin), &st) < 0 ||
457 		    (st.st_mode&S_IFMT) != S_IFREG) {
458 			fprintf(stdout, "%s: not a plain file.\n", local);
459 			(void) signal(SIGINT, oldintr);
460 			fclose(fin);
461 			code = -1;
462 			return;
463 		}
464 	}
465 	if (initconn()) {
466 		(void) signal(SIGINT, oldintr);
467 		if (oldintp)
468 			(void) signal(SIGPIPE, oldintp);
469 		code = -1;
470 		if (closefunc != NULL)
471 			(*closefunc)(fin);
472 		return;
473 	}
474 	if (setjmp(sendabort))
475 		goto abort;
476 
477 	if (restart_point &&
478 	    (strcmp(cmd, "STOR") == 0 || strcmp(cmd, "APPE") == 0)) {
479 		if (fseek(fin, (long) restart_point, 0) < 0) {
480 			perror(local);
481 			restart_point = 0;
482 			if (closefunc != NULL)
483 				(*closefunc)(fin);
484 			return;
485 		}
486 		if (command("REST %ld", (long) restart_point)
487 			!= CONTINUE) {
488 			restart_point = 0;
489 			if (closefunc != NULL)
490 				(*closefunc)(fin);
491 			return;
492 		}
493 		restart_point = 0;
494 		mode = "r+w";
495 	}
496 	if (remote) {
497 		if (command("%s %s", cmd, remote) != PRELIM) {
498 			(void) signal(SIGINT, oldintr);
499 			if (oldintp)
500 				(void) signal(SIGPIPE, oldintp);
501 			if (closefunc != NULL)
502 				(*closefunc)(fin);
503 			return;
504 		}
505 	} else
506 		if (command("%s", cmd) != PRELIM) {
507 			(void) signal(SIGINT, oldintr);
508 			if (oldintp)
509 				(void) signal(SIGPIPE, oldintp);
510 			if (closefunc != NULL)
511 				(*closefunc)(fin);
512 			return;
513 		}
514 	dout = dataconn(mode);
515 	if (dout == NULL)
516 		goto abort;
517 	(void) gettimeofday(&start, (struct timezone *)0);
518 	oldintp = signal(SIGPIPE, SIG_IGN);
519 	switch (type) {
520 
521 	case TYPE_I:
522 	case TYPE_L:
523 		errno = d = 0;
524 		while ((c = read(fileno(fin), buf, sizeof (buf))) > 0) {
525 			bytes += c;
526 			for (bufp = buf; c > 0; c -= d, bufp += d)
527 				if ((d = write(fileno(dout), bufp, c)) <= 0)
528 					break;
529 			if (hash) {
530 				while (bytes >= hashbytes) {
531 					(void) putchar('#');
532 					hashbytes += HASHBYTES;
533 				}
534 				(void) fflush(stdout);
535 			}
536 		}
537 		if (hash && bytes > 0) {
538 			if (bytes < HASHBYTES)
539 				(void) putchar('#');
540 			(void) putchar('\n');
541 			(void) fflush(stdout);
542 		}
543 		if (c < 0)
544 			perror(local);
545 		if (d <= 0) {
546 			if (d == 0)
547 				fprintf(stderr, "netout: write returned 0?\n");
548 			else if (errno != EPIPE)
549 				perror("netout");
550 			bytes = -1;
551 		}
552 		break;
553 
554 	case TYPE_A:
555 		while ((c = getc(fin)) != EOF) {
556 			if (c == '\n') {
557 				while (hash && (bytes >= hashbytes)) {
558 					(void) putchar('#');
559 					(void) fflush(stdout);
560 					hashbytes += HASHBYTES;
561 				}
562 				if (ferror(dout))
563 					break;
564 				(void) putc('\r', dout);
565 				bytes++;
566 			}
567 			(void) putc(c, dout);
568 			bytes++;
569 	/*		if (c == '\r') {			  	*/
570 	/*		(void)	putc('\0', dout);  /* this violates rfc */
571 	/*			bytes++;				*/
572 	/*		}                          			*/
573 		}
574 		if (hash) {
575 			if (bytes < hashbytes)
576 				(void) putchar('#');
577 			(void) putchar('\n');
578 			(void) fflush(stdout);
579 		}
580 		if (ferror(fin))
581 			perror(local);
582 		if (ferror(dout)) {
583 			if (errno != EPIPE)
584 				perror("netout");
585 			bytes = -1;
586 		}
587 		break;
588 	}
589 	(void) gettimeofday(&stop, (struct timezone *)0);
590 	if (closefunc != NULL)
591 		(*closefunc)(fin);
592 	(void) fclose(dout);
593 	(void) getreply(0);
594 	(void) signal(SIGINT, oldintr);
595 	if (oldintp)
596 		(void) signal(SIGPIPE, oldintp);
597 	if (bytes > 0)
598 		ptransfer("sent", bytes, &start, &stop);
599 	return;
600 abort:
601 	(void) gettimeofday(&stop, (struct timezone *)0);
602 	(void) signal(SIGINT, oldintr);
603 	if (oldintp)
604 		(void) signal(SIGPIPE, oldintp);
605 	if (!cpend) {
606 		code = -1;
607 		return;
608 	}
609 	if (data >= 0) {
610 		(void) close(data);
611 		data = -1;
612 	}
613 	if (dout)
614 		(void) fclose(dout);
615 	(void) getreply(0);
616 	code = -1;
617 	if (closefunc != NULL && fin != NULL)
618 		(*closefunc)(fin);
619 	if (bytes > 0)
620 		ptransfer("sent", bytes, &start, &stop);
621 }
622 
623 jmp_buf	recvabort;
624 
625 abortrecv()
626 {
627 
628 	mflag = 0;
629 	abrtflag = 0;
630 	printf("\n");
631 	(void) fflush(stdout);
632 	longjmp(recvabort, 1);
633 }
634 
635 recvrequest(cmd, local, remote, mode, printnames)
636 	char *cmd, *local, *remote, *mode;
637 {
638 	FILE *fout, *din = 0, *popen();
639 	int (*closefunc)(), pclose(), fclose(), (*oldintr)(), (*oldintp)();
640 	int abortrecv(), oldverbose, oldtype = 0, is_retr, tcrflag, nfnd;
641 	char *bufp, *gunique(), msg;
642 	static char *buf;
643 	static int bufsize;
644 	long bytes = 0, hashbytes = HASHBYTES;
645 	struct fd_set mask;
646 	register int c, d;
647 	struct timeval start, stop;
648 	struct stat st;
649 	extern char *malloc();
650 
651 	is_retr = strcmp(cmd, "RETR") == 0;
652 	if (is_retr && verbose && printnames) {
653 		if (local && *local != '-')
654 			printf("local: %s ", local);
655 		if (remote)
656 			printf("remote: %s\n", remote);
657 	}
658 	if (proxy && is_retr) {
659 		proxtrans(cmd, local, remote);
660 		return;
661 	}
662 	closefunc = NULL;
663 	oldintr = NULL;
664 	oldintp = NULL;
665 	tcrflag = !crflag && is_retr;
666 	if (setjmp(recvabort)) {
667 		while (cpend) {
668 			(void) getreply(0);
669 		}
670 		if (data >= 0) {
671 			(void) close(data);
672 			data = -1;
673 		}
674 		if (oldintr)
675 			(void) signal(SIGINT, oldintr);
676 		code = -1;
677 		return;
678 	}
679 	oldintr = signal(SIGINT, abortrecv);
680 	if (strcmp(local, "-") && *local != '|') {
681 		if (access(local, 2) < 0) {
682 			char *dir = rindex(local, '/');
683 
684 			if (errno != ENOENT && errno != EACCES) {
685 				perror(local);
686 				(void) signal(SIGINT, oldintr);
687 				code = -1;
688 				return;
689 			}
690 			if (dir != NULL)
691 				*dir = 0;
692 			d = access(dir ? local : ".", 2);
693 			if (dir != NULL)
694 				*dir = '/';
695 			if (d < 0) {
696 				perror(local);
697 				(void) signal(SIGINT, oldintr);
698 				code = -1;
699 				return;
700 			}
701 			if (!runique && errno == EACCES &&
702 			    chmod(local, 0600) < 0) {
703 				perror(local);
704 				(void) signal(SIGINT, oldintr);
705 				code = -1;
706 				return;
707 			}
708 			if (runique && errno == EACCES &&
709 			   (local = gunique(local)) == NULL) {
710 				(void) signal(SIGINT, oldintr);
711 				code = -1;
712 				return;
713 			}
714 		}
715 		else if (runique && (local = gunique(local)) == NULL) {
716 			(void) signal(SIGINT, oldintr);
717 			code = -1;
718 			return;
719 		}
720 	}
721 	if (initconn()) {
722 		(void) signal(SIGINT, oldintr);
723 		code = -1;
724 		return;
725 	}
726 	if (setjmp(recvabort))
727 		goto abort;
728 	if (!is_retr) {
729 		if (type != TYPE_A) {
730 			oldtype = type;
731 			oldverbose = verbose;
732 			if (!debug)
733 				verbose = 0;
734 			setascii();
735 			verbose = oldverbose;
736 		}
737 	} else if (restart_point) {
738 		if (command("REST %ld", (long) restart_point) != CONTINUE)
739 			return;
740 	}
741 	if (remote) {
742 		if (command("%s %s", cmd, remote) != PRELIM) {
743 			(void) signal(SIGINT, oldintr);
744 			if (oldtype) {
745 				if (!debug)
746 					verbose = 0;
747 				switch (oldtype) {
748 					case TYPE_I:
749 						setbinary();
750 						break;
751 					case TYPE_E:
752 						setebcdic();
753 						break;
754 					case TYPE_L:
755 						settenex();
756 						break;
757 				}
758 				verbose = oldverbose;
759 			}
760 			return;
761 		}
762 	} else {
763 		if (command("%s", cmd) != PRELIM) {
764 			(void) signal(SIGINT, oldintr);
765 			if (oldtype) {
766 				if (!debug)
767 					verbose = 0;
768 				switch (oldtype) {
769 					case TYPE_I:
770 						setbinary();
771 						break;
772 					case TYPE_E:
773 						setebcdic();
774 						break;
775 					case TYPE_L:
776 						settenex();
777 						break;
778 				}
779 				verbose = oldverbose;
780 			}
781 			return;
782 		}
783 	}
784 	din = dataconn("r");
785 	if (din == NULL)
786 		goto abort;
787 	if (strcmp(local, "-") == 0)
788 		fout = stdout;
789 	else if (*local == '|') {
790 		oldintp = signal(SIGPIPE, SIG_IGN);
791 		fout = popen(local + 1, "w");
792 		if (fout == NULL) {
793 			perror(local+1);
794 			goto abort;
795 		}
796 		closefunc = pclose;
797 	} else {
798 		fout = fopen(local, mode);
799 		if (fout == NULL) {
800 			perror(local);
801 			goto abort;
802 		}
803 		closefunc = fclose;
804 	}
805 	if (fstat(fileno(fout), &st) < 0 || st.st_blksize == 0)
806 		st.st_blksize = BUFSIZ;
807 	if (st.st_blksize > bufsize) {
808 		if (buf)
809 			(void) free(buf);
810 		buf = malloc(st.st_blksize);
811 		if (buf == NULL) {
812 			perror("malloc");
813 			bufsize = 0;
814 			goto abort;
815 		}
816 		bufsize = st.st_blksize;
817 	}
818 	(void) gettimeofday(&start, (struct timezone *)0);
819 	switch (type) {
820 
821 	case TYPE_I:
822 	case TYPE_L:
823 		if (restart_point &&
824 		    lseek(fileno(fout), (long) restart_point, L_SET) < 0) {
825 			perror(local);
826 			if (closefunc != NULL)
827 				(*closefunc)(fout);
828 			return;
829 		}
830 		errno = d = 0;
831 		while ((c = read(fileno(din), buf, bufsize)) > 0) {
832 			if ((d = write(fileno(fout), buf, c)) != c)
833 				break;
834 			bytes += c;
835 			if (hash) {
836 				while (bytes >= hashbytes) {
837 					(void) putchar('#');
838 					hashbytes += HASHBYTES;
839 				}
840 				(void) fflush(stdout);
841 			}
842 		}
843 		if (hash && bytes > 0) {
844 			if (bytes < HASHBYTES)
845 				(void) putchar('#');
846 			(void) putchar('\n');
847 			(void) fflush(stdout);
848 		}
849 		if (c < 0) {
850 			if (errno != EPIPE)
851 				perror("netin");
852 			bytes = -1;
853 		}
854 		if (d < c) {
855 			if (d < 0)
856 				perror(local);
857 			else
858 				fprintf(stderr, "%s: short write\n", local);
859 		}
860 		break;
861 
862 	case TYPE_A:
863 		if (restart_point) {
864 			register int i, n, c;
865 
866 			if (fseek(fout, 0L, L_SET) < 0)
867 				goto done;
868 			n = restart_point;
869 			i = 0;
870 			while (i++ < n) {
871 				if ((c=getc(fout)) == EOF)
872 					goto done;
873 				if (c == '\n')
874 					i++;
875 			}
876 			if (fseek(fout, 0L, L_INCR) < 0) {
877 done:
878 				perror(local);
879 				if (closefunc != NULL)
880 					(*closefunc)(fout);
881 				return;
882 			}
883 		}
884 		while ((c = getc(din)) != EOF) {
885 			while (c == '\r') {
886 				while (hash && (bytes >= hashbytes)) {
887 					(void) putchar('#');
888 					(void) fflush(stdout);
889 					hashbytes += HASHBYTES;
890 				}
891 				bytes++;
892 				if ((c = getc(din)) != '\n' || tcrflag) {
893 					if (ferror(fout))
894 						goto break2;
895 					(void) putc('\r', fout);
896 					if (c == '\0') {
897 						bytes++;
898 						goto contin2;
899 					}
900 					if (c == EOF)
901 						goto contin2;
902 				}
903 			}
904 			(void) putc(c, fout);
905 			bytes++;
906 	contin2:	;
907 		}
908 break2:
909 		if (hash) {
910 			if (bytes < hashbytes)
911 				(void) putchar('#');
912 			(void) putchar('\n');
913 			(void) fflush(stdout);
914 		}
915 		if (ferror(din)) {
916 			if (errno != EPIPE)
917 				perror("netin");
918 			bytes = -1;
919 		}
920 		if (ferror(fout))
921 			perror(local);
922 		break;
923 	}
924 	if (closefunc != NULL)
925 		(*closefunc)(fout);
926 	(void) signal(SIGINT, oldintr);
927 	if (oldintp)
928 		(void) signal(SIGPIPE, oldintp);
929 	(void) gettimeofday(&stop, (struct timezone *)0);
930 	(void) fclose(din);
931 	(void) getreply(0);
932 	if (bytes > 0 && is_retr)
933 		ptransfer("received", bytes, &start, &stop);
934 	if (oldtype) {
935 		if (!debug)
936 			verbose = 0;
937 		switch (oldtype) {
938 			case TYPE_I:
939 				setbinary();
940 				break;
941 			case TYPE_E:
942 				setebcdic();
943 				break;
944 			case TYPE_L:
945 				settenex();
946 				break;
947 		}
948 		verbose = oldverbose;
949 	}
950 	return;
951 abort:
952 
953 /* abort using RFC959 recommended IP,SYNC sequence  */
954 
955 	(void) gettimeofday(&stop, (struct timezone *)0);
956 	if (oldintp)
957 		(void) signal(SIGPIPE, oldintr);
958 	(void) signal(SIGINT,SIG_IGN);
959 	if (oldtype) {
960 		if (!debug)
961 			verbose = 0;
962 		switch (oldtype) {
963 			case TYPE_I:
964 				setbinary();
965 				break;
966 			case TYPE_E:
967 				setebcdic();
968 				break;
969 			case TYPE_L:
970 				settenex();
971 				break;
972 		}
973 		verbose = oldverbose;
974 	}
975 	if (!cpend) {
976 		code = -1;
977 		(void) signal(SIGINT,oldintr);
978 		return;
979 	}
980 
981 	fprintf(cout,"%c%c",IAC,IP);
982 	(void) fflush(cout);
983 	msg = IAC;
984 /* send IAC in urgent mode instead of DM because UNIX places oob mark */
985 /* after urgent byte rather than before as now is protocol            */
986 	if (send(fileno(cout),&msg,1,MSG_OOB) != 1) {
987 		perror("abort");
988 	}
989 	fprintf(cout,"%cABOR\r\n",DM);
990 	(void) fflush(cout);
991 	FD_ZERO(&mask);
992 	FD_SET(fileno(cin), &mask);
993 	if (din) {
994 		FD_SET(fileno(din), &mask);
995 	}
996 	if ((nfnd = empty(&mask,10)) <= 0) {
997 		if (nfnd < 0) {
998 			perror("abort");
999 		}
1000 		code = -1;
1001 		lostpeer();
1002 	}
1003 	if (din && FD_ISSET(fileno(din), &mask)) {
1004 		while ((c = read(fileno(din), buf, bufsize)) > 0)
1005 			;
1006 	}
1007 	if ((c = getreply(0)) == ERROR && code == 552) { /* needed for nic style abort */
1008 		if (data >= 0) {
1009 			(void) close(data);
1010 			data = -1;
1011 		}
1012 		(void) getreply(0);
1013 	}
1014 	(void) getreply(0);
1015 	code = -1;
1016 	if (data >= 0) {
1017 		(void) close(data);
1018 		data = -1;
1019 	}
1020 	if (closefunc != NULL && fout != NULL)
1021 		(*closefunc)(fout);
1022 	if (din)
1023 		(void) fclose(din);
1024 	if (bytes > 0)
1025 		ptransfer("received", bytes, &start, &stop);
1026 	(void) signal(SIGINT,oldintr);
1027 }
1028 
1029 /*
1030  * Need to start a listen on the data channel
1031  * before we send the command, otherwise the
1032  * server's connect may fail.
1033  */
1034 int sendport = -1;
1035 
1036 initconn()
1037 {
1038 	register char *p, *a;
1039 	int result, len, tmpno = 0;
1040 	int on = 1;
1041 
1042 noport:
1043 	data_addr = myctladdr;
1044 	if (sendport)
1045 		data_addr.sin_port = 0;	/* let system pick one */
1046 	if (data != -1)
1047 		(void) close (data);
1048 	data = socket(AF_INET, SOCK_STREAM, 0);
1049 	if (data < 0) {
1050 		perror("ftp: socket");
1051 		if (tmpno)
1052 			sendport = 1;
1053 		return (1);
1054 	}
1055 	if (!sendport)
1056 		if (setsockopt(data, SOL_SOCKET, SO_REUSEADDR, (char *)&on, sizeof (on)) < 0) {
1057 			perror("ftp: setsockopt (reuse address)");
1058 			goto bad;
1059 		}
1060 	if (bind(data, (struct sockaddr *)&data_addr, sizeof (data_addr)) < 0) {
1061 		perror("ftp: bind");
1062 		goto bad;
1063 	}
1064 	if (options & SO_DEBUG &&
1065 	    setsockopt(data, SOL_SOCKET, SO_DEBUG, (char *)&on, sizeof (on)) < 0)
1066 		perror("ftp: setsockopt (ignored)");
1067 	len = sizeof (data_addr);
1068 	if (getsockname(data, (char *)&data_addr, &len) < 0) {
1069 		perror("ftp: getsockname");
1070 		goto bad;
1071 	}
1072 	if (listen(data, 1) < 0)
1073 		perror("ftp: listen");
1074 	if (sendport) {
1075 		a = (char *)&data_addr.sin_addr;
1076 		p = (char *)&data_addr.sin_port;
1077 #define	UC(b)	(((int)b)&0xff)
1078 		result =
1079 		    command("PORT %d,%d,%d,%d,%d,%d",
1080 		      UC(a[0]), UC(a[1]), UC(a[2]), UC(a[3]),
1081 		      UC(p[0]), UC(p[1]));
1082 		if (result == ERROR && sendport == -1) {
1083 			sendport = 0;
1084 			tmpno = 1;
1085 			goto noport;
1086 		}
1087 		return (result != COMPLETE);
1088 	}
1089 	if (tmpno)
1090 		sendport = 1;
1091 	return (0);
1092 bad:
1093 	(void) close(data), data = -1;
1094 	if (tmpno)
1095 		sendport = 1;
1096 	return (1);
1097 }
1098 
1099 FILE *
1100 dataconn(mode)
1101 	char *mode;
1102 {
1103 	struct sockaddr_in from;
1104 	int s, fromlen = sizeof (from);
1105 
1106 	s = accept(data, (struct sockaddr *) &from, &fromlen);
1107 	if (s < 0) {
1108 		perror("ftp: accept");
1109 		(void) close(data), data = -1;
1110 		return (NULL);
1111 	}
1112 	(void) close(data);
1113 	data = s;
1114 	return (fdopen(data, mode));
1115 }
1116 
1117 ptransfer(direction, bytes, t0, t1)
1118 	char *direction;
1119 	long bytes;
1120 	struct timeval *t0, *t1;
1121 {
1122 	struct timeval td;
1123 	float s, bs;
1124 
1125 	if (verbose) {
1126 		tvsub(&td, t1, t0);
1127 		s = td.tv_sec + (td.tv_usec / 1000000.);
1128 #define	nz(x)	((x) == 0 ? 1 : (x))
1129 		bs = bytes / nz(s);
1130 		printf("%ld bytes %s in %.2g seconds (%.2g Kbytes/s)\n",
1131 		    bytes, direction, s, bs / 1024.);
1132 	}
1133 }
1134 
1135 /*tvadd(tsum, t0)
1136 	struct timeval *tsum, *t0;
1137 {
1138 
1139 	tsum->tv_sec += t0->tv_sec;
1140 	tsum->tv_usec += t0->tv_usec;
1141 	if (tsum->tv_usec > 1000000)
1142 		tsum->tv_sec++, tsum->tv_usec -= 1000000;
1143 } */
1144 
1145 tvsub(tdiff, t1, t0)
1146 	struct timeval *tdiff, *t1, *t0;
1147 {
1148 
1149 	tdiff->tv_sec = t1->tv_sec - t0->tv_sec;
1150 	tdiff->tv_usec = t1->tv_usec - t0->tv_usec;
1151 	if (tdiff->tv_usec < 0)
1152 		tdiff->tv_sec--, tdiff->tv_usec += 1000000;
1153 }
1154 
1155 psabort()
1156 {
1157 	extern int abrtflag;
1158 
1159 	abrtflag++;
1160 }
1161 
1162 pswitch(flag)
1163 	int flag;
1164 {
1165 	extern int proxy, abrtflag;
1166 	int (*oldintr)();
1167 	static struct comvars {
1168 		int connect;
1169 		char name[MAXHOSTNAMELEN];
1170 		struct sockaddr_in mctl;
1171 		struct sockaddr_in hctl;
1172 		FILE *in;
1173 		FILE *out;
1174 		int tpe;
1175 		int cpnd;
1176 		int sunqe;
1177 		int runqe;
1178 		int mcse;
1179 		int ntflg;
1180 		char nti[17];
1181 		char nto[17];
1182 		int mapflg;
1183 		char mi[MAXPATHLEN];
1184 		char mo[MAXPATHLEN];
1185 		} proxstruct, tmpstruct;
1186 	struct comvars *ip, *op;
1187 
1188 	abrtflag = 0;
1189 	oldintr = signal(SIGINT, psabort);
1190 	if (flag) {
1191 		if (proxy)
1192 			return;
1193 		ip = &tmpstruct;
1194 		op = &proxstruct;
1195 		proxy++;
1196 	}
1197 	else {
1198 		if (!proxy)
1199 			return;
1200 		ip = &proxstruct;
1201 		op = &tmpstruct;
1202 		proxy = 0;
1203 	}
1204 	ip->connect = connected;
1205 	connected = op->connect;
1206 	if (hostname) {
1207 		(void) strncpy(ip->name, hostname, sizeof(ip->name) - 1);
1208 		ip->name[strlen(ip->name)] = '\0';
1209 	} else
1210 		ip->name[0] = 0;
1211 	hostname = op->name;
1212 	ip->hctl = hisctladdr;
1213 	hisctladdr = op->hctl;
1214 	ip->mctl = myctladdr;
1215 	myctladdr = op->mctl;
1216 	ip->in = cin;
1217 	cin = op->in;
1218 	ip->out = cout;
1219 	cout = op->out;
1220 	ip->tpe = type;
1221 	type = op->tpe;
1222 	if (!type)
1223 		type = 1;
1224 	ip->cpnd = cpend;
1225 	cpend = op->cpnd;
1226 	ip->sunqe = sunique;
1227 	sunique = op->sunqe;
1228 	ip->runqe = runique;
1229 	runique = op->runqe;
1230 	ip->mcse = mcase;
1231 	mcase = op->mcse;
1232 	ip->ntflg = ntflag;
1233 	ntflag = op->ntflg;
1234 	(void) strncpy(ip->nti, ntin, 16);
1235 	(ip->nti)[strlen(ip->nti)] = '\0';
1236 	(void) strcpy(ntin, op->nti);
1237 	(void) strncpy(ip->nto, ntout, 16);
1238 	(ip->nto)[strlen(ip->nto)] = '\0';
1239 	(void) strcpy(ntout, op->nto);
1240 	ip->mapflg = mapflag;
1241 	mapflag = op->mapflg;
1242 	(void) strncpy(ip->mi, mapin, MAXPATHLEN - 1);
1243 	(ip->mi)[strlen(ip->mi)] = '\0';
1244 	(void) strcpy(mapin, op->mi);
1245 	(void) strncpy(ip->mo, mapout, MAXPATHLEN - 1);
1246 	(ip->mo)[strlen(ip->mo)] = '\0';
1247 	(void) strcpy(mapout, op->mo);
1248 	(void) signal(SIGINT, oldintr);
1249 	if (abrtflag) {
1250 		abrtflag = 0;
1251 		(*oldintr)();
1252 	}
1253 }
1254 
1255 jmp_buf ptabort;
1256 int ptabflg;
1257 
1258 abortpt()
1259 {
1260 	printf("\n");
1261 	(void) fflush(stdout);
1262 	ptabflg++;
1263 	mflag = 0;
1264 	abrtflag = 0;
1265 	longjmp(ptabort, 1);
1266 }
1267 
1268 proxtrans(cmd, local, remote)
1269 	char *cmd, *local, *remote;
1270 {
1271 	int (*oldintr)(), abortpt(), tmptype, oldtype = 0, secndflag = 0, nfnd;
1272 	extern jmp_buf ptabort;
1273 	char *cmd2;
1274 	struct fd_set mask;
1275 
1276 	if (strcmp(cmd, "RETR"))
1277 		cmd2 = "RETR";
1278 	else
1279 		cmd2 = runique ? "STOU" : "STOR";
1280 	if (command("PASV") != COMPLETE) {
1281 		printf("proxy server does not support third part transfers.\n");
1282 		return;
1283 	}
1284 	tmptype = type;
1285 	pswitch(0);
1286 	if (!connected) {
1287 		printf("No primary connection\n");
1288 		pswitch(1);
1289 		code = -1;
1290 		return;
1291 	}
1292 	if (type != tmptype) {
1293 		oldtype = type;
1294 		switch (tmptype) {
1295 			case TYPE_A:
1296 				setascii();
1297 				break;
1298 			case TYPE_I:
1299 				setbinary();
1300 				break;
1301 			case TYPE_E:
1302 				setebcdic();
1303 				break;
1304 			case TYPE_L:
1305 				settenex();
1306 				break;
1307 		}
1308 	}
1309 	if (command("PORT %s", pasv) != COMPLETE) {
1310 		switch (oldtype) {
1311 			case 0:
1312 				break;
1313 			case TYPE_A:
1314 				setascii();
1315 				break;
1316 			case TYPE_I:
1317 				setbinary();
1318 				break;
1319 			case TYPE_E:
1320 				setebcdic();
1321 				break;
1322 			case TYPE_L:
1323 				settenex();
1324 				break;
1325 		}
1326 		pswitch(1);
1327 		return;
1328 	}
1329 	if (setjmp(ptabort))
1330 		goto abort;
1331 	oldintr = signal(SIGINT, abortpt);
1332 	if (command("%s %s", cmd, remote) != PRELIM) {
1333 		(void) signal(SIGINT, oldintr);
1334 		switch (oldtype) {
1335 			case 0:
1336 				break;
1337 			case TYPE_A:
1338 				setascii();
1339 				break;
1340 			case TYPE_I:
1341 				setbinary();
1342 				break;
1343 			case TYPE_E:
1344 				setebcdic();
1345 				break;
1346 			case TYPE_L:
1347 				settenex();
1348 				break;
1349 		}
1350 		pswitch(1);
1351 		return;
1352 	}
1353 	sleep(2);
1354 	pswitch(1);
1355 	secndflag++;
1356 	if (command("%s %s", cmd2, local) != PRELIM)
1357 		goto abort;
1358 	ptflag++;
1359 	(void) getreply(0);
1360 	pswitch(0);
1361 	(void) getreply(0);
1362 	(void) signal(SIGINT, oldintr);
1363 	switch (oldtype) {
1364 		case 0:
1365 			break;
1366 		case TYPE_A:
1367 			setascii();
1368 			break;
1369 		case TYPE_I:
1370 			setbinary();
1371 			break;
1372 		case TYPE_E:
1373 			setebcdic();
1374 			break;
1375 		case TYPE_L:
1376 			settenex();
1377 			break;
1378 	}
1379 	pswitch(1);
1380 	ptflag = 0;
1381 	printf("local: %s remote: %s\n", local, remote);
1382 	return;
1383 abort:
1384 	(void) signal(SIGINT, SIG_IGN);
1385 	ptflag = 0;
1386 	if (strcmp(cmd, "RETR") && !proxy)
1387 		pswitch(1);
1388 	else if (!strcmp(cmd, "RETR") && proxy)
1389 		pswitch(0);
1390 	if (!cpend && !secndflag) {  /* only here if cmd = "STOR" (proxy=1) */
1391 		if (command("%s %s", cmd2, local) != PRELIM) {
1392 			pswitch(0);
1393 			switch (oldtype) {
1394 				case 0:
1395 					break;
1396 				case TYPE_A:
1397 					setascii();
1398 					break;
1399 				case TYPE_I:
1400 					setbinary();
1401 					break;
1402 				case TYPE_E:
1403 					setebcdic();
1404 					break;
1405 				case TYPE_L:
1406 					settenex();
1407 					break;
1408 			}
1409 			if (cpend) {
1410 				char msg[2];
1411 
1412 				fprintf(cout,"%c%c",IAC,IP);
1413 				(void) fflush(cout);
1414 				*msg = IAC;
1415 				*(msg+1) = DM;
1416 				if (send(fileno(cout),msg,2,MSG_OOB) != 2)
1417 					perror("abort");
1418 				fprintf(cout,"ABOR\r\n");
1419 				(void) fflush(cout);
1420 				FD_ZERO(&mask);
1421 				FD_SET(fileno(cin), &mask);
1422 				if ((nfnd = empty(&mask,10)) <= 0) {
1423 					if (nfnd < 0) {
1424 						perror("abort");
1425 					}
1426 					if (ptabflg)
1427 						code = -1;
1428 					lostpeer();
1429 				}
1430 				(void) getreply(0);
1431 				(void) getreply(0);
1432 			}
1433 		}
1434 		pswitch(1);
1435 		if (ptabflg)
1436 			code = -1;
1437 		(void) signal(SIGINT, oldintr);
1438 		return;
1439 	}
1440 	if (cpend) {
1441 		char msg[2];
1442 
1443 		fprintf(cout,"%c%c",IAC,IP);
1444 		(void) fflush(cout);
1445 		*msg = IAC;
1446 		*(msg+1) = DM;
1447 		if (send(fileno(cout),msg,2,MSG_OOB) != 2)
1448 			perror("abort");
1449 		fprintf(cout,"ABOR\r\n");
1450 		(void) fflush(cout);
1451 		FD_ZERO(&mask);
1452 		FD_SET(fileno(cin), &mask);
1453 		if ((nfnd = empty(&mask,10)) <= 0) {
1454 			if (nfnd < 0) {
1455 				perror("abort");
1456 			}
1457 			if (ptabflg)
1458 				code = -1;
1459 			lostpeer();
1460 		}
1461 		(void) getreply(0);
1462 		(void) getreply(0);
1463 	}
1464 	pswitch(!proxy);
1465 	if (!cpend && !secndflag) {  /* only if cmd = "RETR" (proxy=1) */
1466 		if (command("%s %s", cmd2, local) != PRELIM) {
1467 			pswitch(0);
1468 			switch (oldtype) {
1469 				case 0:
1470 					break;
1471 				case TYPE_A:
1472 					setascii();
1473 					break;
1474 				case TYPE_I:
1475 					setbinary();
1476 					break;
1477 				case TYPE_E:
1478 					setebcdic();
1479 					break;
1480 				case TYPE_L:
1481 					settenex();
1482 					break;
1483 			}
1484 			if (cpend) {
1485 				char msg[2];
1486 
1487 				fprintf(cout,"%c%c",IAC,IP);
1488 				(void) fflush(cout);
1489 				*msg = IAC;
1490 				*(msg+1) = DM;
1491 				if (send(fileno(cout),msg,2,MSG_OOB) != 2)
1492 					perror("abort");
1493 				fprintf(cout,"ABOR\r\n");
1494 				(void) fflush(cout);
1495 				FD_ZERO(&mask);
1496 				FD_SET(fileno(cin), &mask);
1497 				if ((nfnd = empty(&mask,10)) <= 0) {
1498 					if (nfnd < 0) {
1499 						perror("abort");
1500 					}
1501 					if (ptabflg)
1502 						code = -1;
1503 					lostpeer();
1504 				}
1505 				(void) getreply(0);
1506 				(void) getreply(0);
1507 			}
1508 			pswitch(1);
1509 			if (ptabflg)
1510 				code = -1;
1511 			(void) signal(SIGINT, oldintr);
1512 			return;
1513 		}
1514 	}
1515 	if (cpend) {
1516 		char msg[2];
1517 
1518 		fprintf(cout,"%c%c",IAC,IP);
1519 		(void) fflush(cout);
1520 		*msg = IAC;
1521 		*(msg+1) = DM;
1522 		if (send(fileno(cout),msg,2,MSG_OOB) != 2)
1523 			perror("abort");
1524 		fprintf(cout,"ABOR\r\n");
1525 		(void) fflush(cout);
1526 		FD_ZERO(&mask);
1527 		FD_SET(fileno(cin), &mask);
1528 		if ((nfnd = empty(&mask,10)) <= 0) {
1529 			if (nfnd < 0) {
1530 				perror("abort");
1531 			}
1532 			if (ptabflg)
1533 				code = -1;
1534 			lostpeer();
1535 		}
1536 		(void) getreply(0);
1537 		(void) getreply(0);
1538 	}
1539 	pswitch(!proxy);
1540 	if (cpend) {
1541 		FD_ZERO(&mask);
1542 		FD_SET(fileno(cin), &mask);
1543 		if ((nfnd = empty(&mask,10)) <= 0) {
1544 			if (nfnd < 0) {
1545 				perror("abort");
1546 			}
1547 			if (ptabflg)
1548 				code = -1;
1549 			lostpeer();
1550 		}
1551 		(void) getreply(0);
1552 		(void) getreply(0);
1553 	}
1554 	if (proxy)
1555 		pswitch(0);
1556 	switch (oldtype) {
1557 		case 0:
1558 			break;
1559 		case TYPE_A:
1560 			setascii();
1561 			break;
1562 		case TYPE_I:
1563 			setbinary();
1564 			break;
1565 		case TYPE_E:
1566 			setebcdic();
1567 			break;
1568 		case TYPE_L:
1569 			settenex();
1570 			break;
1571 	}
1572 	pswitch(1);
1573 	if (ptabflg)
1574 		code = -1;
1575 	(void) signal(SIGINT, oldintr);
1576 }
1577 
1578 reset()
1579 {
1580 	struct fd_set mask;
1581 	int nfnd = 1;
1582 
1583 	FD_ZERO(&mask);
1584 	while (nfnd > 0) {
1585 		FD_SET(fileno(cin), &mask);
1586 		if ((nfnd = empty(&mask,0)) < 0) {
1587 			perror("reset");
1588 			code = -1;
1589 			lostpeer();
1590 		}
1591 		else if (nfnd) {
1592 			(void) getreply(0);
1593 		}
1594 	}
1595 }
1596 
1597 char *
1598 gunique(local)
1599 	char *local;
1600 {
1601 	static char new[MAXPATHLEN];
1602 	char *cp = rindex(local, '/');
1603 	int d, count=0;
1604 	char ext = '1';
1605 
1606 	if (cp)
1607 		*cp = '\0';
1608 	d = access(cp ? local : ".", 2);
1609 	if (cp)
1610 		*cp = '/';
1611 	if (d < 0) {
1612 		perror(local);
1613 		return((char *) 0);
1614 	}
1615 	(void) strcpy(new, local);
1616 	cp = new + strlen(new);
1617 	*cp++ = '.';
1618 	while (!d) {
1619 		if (++count == 100) {
1620 			printf("runique: can't find unique file name.\n");
1621 			return((char *) 0);
1622 		}
1623 		*cp++ = ext;
1624 		*cp = '\0';
1625 		if (ext == '9')
1626 			ext = '0';
1627 		else
1628 			ext++;
1629 		if ((d = access(new, 0)) < 0)
1630 			break;
1631 		if (ext != '0')
1632 			cp--;
1633 		else if (*(cp - 2) == '.')
1634 			*(cp - 1) = '1';
1635 		else {
1636 			*(cp - 2) = *(cp - 2) + 1;
1637 			cp--;
1638 		}
1639 	}
1640 	return(new);
1641 }
1642