xref: /csrg-svn/usr.bin/ftp/ftp.c (revision 37225)
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.26 (Berkeley) 03/21/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];
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 	cp = reply_string;
275 	oldintr = signal(SIGINT,cmdabort);
276 	for (;;) {
277 		dig = n = code = 0;
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 			*cp++ = c;
342 		}
343 		if (verbose > 0 || verbose > -1 && n == '5') {
344 			(void) putchar(c);
345 			(void) fflush (stdout);
346 		}
347 		if (continuation && code != originalcode) {
348 			if (originalcode == 0)
349 				originalcode = code;
350 			continue;
351 		}
352 		*cp = '\0';
353 		if (n != '1')
354 			cpend = 0;
355 		(void) signal(SIGINT,oldintr);
356 		if (code == 421 || originalcode == 421)
357 			lostpeer();
358 		if (abrtflag && oldintr != cmdabort && oldintr != SIG_IGN)
359 			(*oldintr)();
360 		return (n - '0');
361 	}
362 }
363 
364 empty(mask, sec)
365 	struct fd_set *mask;
366 	int sec;
367 {
368 	struct timeval t;
369 
370 	t.tv_sec = (long) sec;
371 	t.tv_usec = 0;
372 	return(select(32, mask, (struct fd_set *) 0, (struct fd_set *) 0, &t));
373 }
374 
375 jmp_buf	sendabort;
376 
377 abortsend()
378 {
379 
380 	mflag = 0;
381 	abrtflag = 0;
382 	printf("\nsend aborted\n");
383 	(void) fflush(stdout);
384 	longjmp(sendabort, 1);
385 }
386 
387 #define HASHBYTES 1024
388 
389 sendrequest(cmd, local, remote, printnames)
390 	char *cmd, *local, *remote;
391 	int printnames;
392 {
393 	FILE *fin, *dout = 0, *popen();
394 	int (*closefunc)(), pclose(), fclose(), (*oldintr)(), (*oldintp)();
395 	int abortsend();
396 	char buf[BUFSIZ], *bufp;
397 	long bytes = 0, hashbytes = HASHBYTES;
398 	register int c, d;
399 	struct stat st;
400 	struct timeval start, stop;
401 	char *mode;
402 
403 	if (verbose && printnames) {
404 		if (local && *local != '-')
405 			printf("local: %s ", local);
406 		if (remote)
407 			printf("remote: %s\n", remote);
408 	}
409 	if (proxy) {
410 		proxtrans(cmd, local, remote);
411 		return;
412 	}
413 	closefunc = NULL;
414 	oldintr = NULL;
415 	oldintp = NULL;
416 	mode = "w";
417 	if (setjmp(sendabort)) {
418 		while (cpend) {
419 			(void) getreply(0);
420 		}
421 		if (data >= 0) {
422 			(void) close(data);
423 			data = -1;
424 		}
425 		if (oldintr)
426 			(void) signal(SIGINT,oldintr);
427 		if (oldintp)
428 			(void) signal(SIGPIPE,oldintp);
429 		code = -1;
430 		return;
431 	}
432 	oldintr = signal(SIGINT, abortsend);
433 	if (strcmp(local, "-") == 0)
434 		fin = stdin;
435 	else if (*local == '|') {
436 		oldintp = signal(SIGPIPE,SIG_IGN);
437 		fin = popen(local + 1, "r");
438 		if (fin == NULL) {
439 			perror(local + 1);
440 			(void) signal(SIGINT, oldintr);
441 			(void) signal(SIGPIPE, oldintp);
442 			code = -1;
443 			return;
444 		}
445 		closefunc = pclose;
446 	} else {
447 		fin = fopen(local, "r");
448 		if (fin == NULL) {
449 			perror(local);
450 			(void) signal(SIGINT, oldintr);
451 			code = -1;
452 			return;
453 		}
454 		closefunc = fclose;
455 		if (fstat(fileno(fin), &st) < 0 ||
456 		    (st.st_mode&S_IFMT) != S_IFREG) {
457 			fprintf(stdout, "%s: not a plain file.\n", local);
458 			(void) signal(SIGINT, oldintr);
459 			fclose(fin);
460 			code = -1;
461 			return;
462 		}
463 	}
464 	if (initconn()) {
465 		(void) signal(SIGINT, oldintr);
466 		if (oldintp)
467 			(void) signal(SIGPIPE, oldintp);
468 		code = -1;
469 		if (closefunc != NULL)
470 			(*closefunc)(fin);
471 		return;
472 	}
473 	if (setjmp(sendabort))
474 		goto abort;
475 
476 	if (restart_point &&
477 	    (strcmp(cmd, "STOR") == 0 || strcmp(cmd, "APPE") == 0)) {
478 		if (fseek(fin, (long) restart_point, 0) < 0) {
479 			perror(local);
480 			restart_point = 0;
481 			if (closefunc != NULL)
482 				(*closefunc)(fin);
483 			return;
484 		}
485 		if (command("REST %ld", (long) restart_point)
486 			!= CONTINUE) {
487 			restart_point = 0;
488 			if (closefunc != NULL)
489 				(*closefunc)(fin);
490 			return;
491 		}
492 		restart_point = 0;
493 		mode = "r+w";
494 	}
495 	if (remote) {
496 		if (command("%s %s", cmd, remote) != PRELIM) {
497 			(void) signal(SIGINT, oldintr);
498 			if (oldintp)
499 				(void) signal(SIGPIPE, oldintp);
500 			if (closefunc != NULL)
501 				(*closefunc)(fin);
502 			return;
503 		}
504 	} else
505 		if (command("%s", cmd) != PRELIM) {
506 			(void) signal(SIGINT, oldintr);
507 			if (oldintp)
508 				(void) signal(SIGPIPE, oldintp);
509 			if (closefunc != NULL)
510 				(*closefunc)(fin);
511 			return;
512 		}
513 	dout = dataconn(mode);
514 	if (dout == NULL)
515 		goto abort;
516 	(void) gettimeofday(&start, (struct timezone *)0);
517 	oldintp = signal(SIGPIPE, SIG_IGN);
518 	switch (type) {
519 
520 	case TYPE_I:
521 	case TYPE_L:
522 		errno = d = 0;
523 		while ((c = read(fileno(fin), buf, sizeof (buf))) > 0) {
524 			bytes += c;
525 			for (bufp = buf; c > 0; c -= d, bufp += d)
526 				if ((d = write(fileno(dout), bufp, c)) <= 0)
527 					break;
528 			if (hash) {
529 				while (bytes >= hashbytes) {
530 					(void) putchar('#');
531 					hashbytes += HASHBYTES;
532 				}
533 				(void) fflush(stdout);
534 			}
535 		}
536 		if (hash && bytes > 0) {
537 			if (bytes < HASHBYTES)
538 				(void) putchar('#');
539 			(void) putchar('\n');
540 			(void) fflush(stdout);
541 		}
542 		if (c < 0)
543 			perror(local);
544 		if (d <= 0) {
545 			if (d == 0)
546 				fprintf(stderr, "netout: write returned 0?\n");
547 			else if (errno != EPIPE)
548 				perror("netout");
549 			bytes = -1;
550 		}
551 		break;
552 
553 	case TYPE_A:
554 		while ((c = getc(fin)) != EOF) {
555 			if (c == '\n') {
556 				while (hash && (bytes >= hashbytes)) {
557 					(void) putchar('#');
558 					(void) fflush(stdout);
559 					hashbytes += HASHBYTES;
560 				}
561 				if (ferror(dout))
562 					break;
563 				(void) putc('\r', dout);
564 				bytes++;
565 			}
566 			(void) putc(c, dout);
567 			bytes++;
568 	/*		if (c == '\r') {			  	*/
569 	/*		(void)	putc('\0', dout);  /* this violates rfc */
570 	/*			bytes++;				*/
571 	/*		}                          			*/
572 		}
573 		if (hash) {
574 			if (bytes < hashbytes)
575 				(void) putchar('#');
576 			(void) putchar('\n');
577 			(void) fflush(stdout);
578 		}
579 		if (ferror(fin))
580 			perror(local);
581 		if (ferror(dout)) {
582 			if (errno != EPIPE)
583 				perror("netout");
584 			bytes = -1;
585 		}
586 		break;
587 	}
588 	(void) gettimeofday(&stop, (struct timezone *)0);
589 	if (closefunc != NULL)
590 		(*closefunc)(fin);
591 	(void) fclose(dout);
592 	(void) getreply(0);
593 	(void) signal(SIGINT, oldintr);
594 	if (oldintp)
595 		(void) signal(SIGPIPE, oldintp);
596 	if (bytes > 0)
597 		ptransfer("sent", bytes, &start, &stop);
598 	return;
599 abort:
600 	(void) gettimeofday(&stop, (struct timezone *)0);
601 	(void) signal(SIGINT, oldintr);
602 	if (oldintp)
603 		(void) signal(SIGPIPE, oldintp);
604 	if (!cpend) {
605 		code = -1;
606 		return;
607 	}
608 	if (data >= 0) {
609 		(void) close(data);
610 		data = -1;
611 	}
612 	if (dout)
613 		(void) fclose(dout);
614 	(void) getreply(0);
615 	code = -1;
616 	if (closefunc != NULL && fin != NULL)
617 		(*closefunc)(fin);
618 	if (bytes > 0)
619 		ptransfer("sent", bytes, &start, &stop);
620 }
621 
622 jmp_buf	recvabort;
623 
624 abortrecv()
625 {
626 
627 	mflag = 0;
628 	abrtflag = 0;
629 	printf("\n");
630 	(void) fflush(stdout);
631 	longjmp(recvabort, 1);
632 }
633 
634 recvrequest(cmd, local, remote, mode, printnames)
635 	char *cmd, *local, *remote, *mode;
636 {
637 	FILE *fout, *din = 0, *popen();
638 	int (*closefunc)(), pclose(), fclose(), (*oldintr)(), (*oldintp)();
639 	int abortrecv(), oldverbose, oldtype = 0, is_retr, tcrflag, nfnd;
640 	char *bufp, *gunique(), msg;
641 	static char *buf;
642 	static int bufsize;
643 	long bytes = 0, hashbytes = HASHBYTES;
644 	struct fd_set mask;
645 	register int c, d;
646 	struct timeval start, stop;
647 	struct stat st;
648 	extern char *malloc();
649 
650 	is_retr = strcmp(cmd, "RETR") == 0;
651 	if (is_retr && verbose && printnames) {
652 		if (local && *local != '-')
653 			printf("local: %s ", local);
654 		if (remote)
655 			printf("remote: %s\n", remote);
656 	}
657 	if (proxy && is_retr) {
658 		proxtrans(cmd, local, remote);
659 		return;
660 	}
661 	closefunc = NULL;
662 	oldintr = NULL;
663 	oldintp = NULL;
664 	tcrflag = !crflag && is_retr;
665 	if (setjmp(recvabort)) {
666 		while (cpend) {
667 			(void) getreply(0);
668 		}
669 		if (data >= 0) {
670 			(void) close(data);
671 			data = -1;
672 		}
673 		if (oldintr)
674 			(void) signal(SIGINT, oldintr);
675 		code = -1;
676 		return;
677 	}
678 	oldintr = signal(SIGINT, abortrecv);
679 	if (strcmp(local, "-") && *local != '|') {
680 		if (access(local, 2) < 0) {
681 			char *dir = rindex(local, '/');
682 
683 			if (errno != ENOENT && errno != EACCES) {
684 				perror(local);
685 				(void) signal(SIGINT, oldintr);
686 				code = -1;
687 				return;
688 			}
689 			if (dir != NULL)
690 				*dir = 0;
691 			d = access(dir ? local : ".", 2);
692 			if (dir != NULL)
693 				*dir = '/';
694 			if (d < 0) {
695 				perror(local);
696 				(void) signal(SIGINT, oldintr);
697 				code = -1;
698 				return;
699 			}
700 			if (!runique && errno == EACCES &&
701 			    chmod(local, 0600) < 0) {
702 				perror(local);
703 				(void) signal(SIGINT, oldintr);
704 				code = -1;
705 				return;
706 			}
707 			if (runique && errno == EACCES &&
708 			   (local = gunique(local)) == NULL) {
709 				(void) signal(SIGINT, oldintr);
710 				code = -1;
711 				return;
712 			}
713 		}
714 		else if (runique && (local = gunique(local)) == NULL) {
715 			(void) signal(SIGINT, oldintr);
716 			code = -1;
717 			return;
718 		}
719 	}
720 	if (initconn()) {
721 		(void) signal(SIGINT, oldintr);
722 		code = -1;
723 		return;
724 	}
725 	if (setjmp(recvabort))
726 		goto abort;
727 	if (!is_retr) {
728 		if (type != TYPE_A) {
729 			oldtype = type;
730 			oldverbose = verbose;
731 			if (!debug)
732 				verbose = 0;
733 			setascii();
734 			verbose = oldverbose;
735 		}
736 	} else if (restart_point) {
737 		if (command("REST %ld", (long) restart_point) != CONTINUE)
738 			return;
739 	}
740 	if (remote) {
741 		if (command("%s %s", cmd, remote) != PRELIM) {
742 			(void) signal(SIGINT, oldintr);
743 			if (oldtype) {
744 				if (!debug)
745 					verbose = 0;
746 				switch (oldtype) {
747 					case TYPE_I:
748 						setbinary();
749 						break;
750 					case TYPE_E:
751 						setebcdic();
752 						break;
753 					case TYPE_L:
754 						settenex();
755 						break;
756 				}
757 				verbose = oldverbose;
758 			}
759 			return;
760 		}
761 	} else {
762 		if (command("%s", cmd) != PRELIM) {
763 			(void) signal(SIGINT, oldintr);
764 			if (oldtype) {
765 				if (!debug)
766 					verbose = 0;
767 				switch (oldtype) {
768 					case TYPE_I:
769 						setbinary();
770 						break;
771 					case TYPE_E:
772 						setebcdic();
773 						break;
774 					case TYPE_L:
775 						settenex();
776 						break;
777 				}
778 				verbose = oldverbose;
779 			}
780 			return;
781 		}
782 	}
783 	din = dataconn("r");
784 	if (din == NULL)
785 		goto abort;
786 	if (strcmp(local, "-") == 0)
787 		fout = stdout;
788 	else if (*local == '|') {
789 		oldintp = signal(SIGPIPE, SIG_IGN);
790 		fout = popen(local + 1, "w");
791 		if (fout == NULL) {
792 			perror(local+1);
793 			goto abort;
794 		}
795 		closefunc = pclose;
796 	} else {
797 		fout = fopen(local, mode);
798 		if (fout == NULL) {
799 			perror(local);
800 			goto abort;
801 		}
802 		closefunc = fclose;
803 	}
804 	if (fstat(fileno(fout), &st) < 0 || st.st_blksize == 0)
805 		st.st_blksize = BUFSIZ;
806 	if (st.st_blksize > bufsize) {
807 		if (buf)
808 			(void) free(buf);
809 		buf = malloc(st.st_blksize);
810 		if (buf == NULL) {
811 			perror("malloc");
812 			bufsize = 0;
813 			goto abort;
814 		}
815 		bufsize = st.st_blksize;
816 	}
817 	(void) gettimeofday(&start, (struct timezone *)0);
818 	switch (type) {
819 
820 	case TYPE_I:
821 	case TYPE_L:
822 		if (restart_point &&
823 		    lseek(fileno(fout), (long) restart_point, L_SET) < 0) {
824 			perror(local);
825 			if (closefunc != NULL)
826 				(*closefunc)(fout);
827 			return;
828 		}
829 		errno = d = 0;
830 		while ((c = read(fileno(din), buf, bufsize)) > 0) {
831 			if ((d = write(fileno(fout), buf, c)) != c)
832 				break;
833 			bytes += c;
834 			if (hash) {
835 				while (bytes >= hashbytes) {
836 					(void) putchar('#');
837 					hashbytes += HASHBYTES;
838 				}
839 				(void) fflush(stdout);
840 			}
841 		}
842 		if (hash && bytes > 0) {
843 			if (bytes < HASHBYTES)
844 				(void) putchar('#');
845 			(void) putchar('\n');
846 			(void) fflush(stdout);
847 		}
848 		if (c < 0) {
849 			if (errno != EPIPE)
850 				perror("netin");
851 			bytes = -1;
852 		}
853 		if (d < c) {
854 			if (d < 0)
855 				perror(local);
856 			else
857 				fprintf(stderr, "%s: short write\n", local);
858 		}
859 		break;
860 
861 	case TYPE_A:
862 		if (restart_point) {
863 			register int i, n, c;
864 
865 			if (fseek(fout, 0L, L_SET) < 0)
866 				goto done;
867 			n = restart_point;
868 			i = 0;
869 			while (i++ < n) {
870 				if ((c=getc(fout)) == EOF)
871 					goto done;
872 				if (c == '\n')
873 					i++;
874 			}
875 			if (fseek(fout, 0L, L_INCR) < 0) {
876 done:
877 				perror(local);
878 				if (closefunc != NULL)
879 					(*closefunc)(fout);
880 				return;
881 			}
882 		}
883 		while ((c = getc(din)) != EOF) {
884 			while (c == '\r') {
885 				while (hash && (bytes >= hashbytes)) {
886 					(void) putchar('#');
887 					(void) fflush(stdout);
888 					hashbytes += HASHBYTES;
889 				}
890 				bytes++;
891 				if ((c = getc(din)) != '\n' || tcrflag) {
892 					if (ferror(fout))
893 						goto break2;
894 					(void) putc('\r', fout);
895 					if (c == '\0') {
896 						bytes++;
897 						goto contin2;
898 					}
899 					if (c == EOF)
900 						goto contin2;
901 				}
902 			}
903 			(void) putc(c, fout);
904 			bytes++;
905 	contin2:	;
906 		}
907 break2:
908 		if (hash) {
909 			if (bytes < hashbytes)
910 				(void) putchar('#');
911 			(void) putchar('\n');
912 			(void) fflush(stdout);
913 		}
914 		if (ferror(din)) {
915 			if (errno != EPIPE)
916 				perror("netin");
917 			bytes = -1;
918 		}
919 		if (ferror(fout))
920 			perror(local);
921 		break;
922 	}
923 	if (closefunc != NULL)
924 		(*closefunc)(fout);
925 	(void) signal(SIGINT, oldintr);
926 	if (oldintp)
927 		(void) signal(SIGPIPE, oldintp);
928 	(void) gettimeofday(&stop, (struct timezone *)0);
929 	(void) fclose(din);
930 	(void) getreply(0);
931 	if (bytes > 0 && is_retr)
932 		ptransfer("received", bytes, &start, &stop);
933 	if (oldtype) {
934 		if (!debug)
935 			verbose = 0;
936 		switch (oldtype) {
937 			case TYPE_I:
938 				setbinary();
939 				break;
940 			case TYPE_E:
941 				setebcdic();
942 				break;
943 			case TYPE_L:
944 				settenex();
945 				break;
946 		}
947 		verbose = oldverbose;
948 	}
949 	return;
950 abort:
951 
952 /* abort using RFC959 recommended IP,SYNC sequence  */
953 
954 	(void) gettimeofday(&stop, (struct timezone *)0);
955 	if (oldintp)
956 		(void) signal(SIGPIPE, oldintr);
957 	(void) signal(SIGINT,SIG_IGN);
958 	if (oldtype) {
959 		if (!debug)
960 			verbose = 0;
961 		switch (oldtype) {
962 			case TYPE_I:
963 				setbinary();
964 				break;
965 			case TYPE_E:
966 				setebcdic();
967 				break;
968 			case TYPE_L:
969 				settenex();
970 				break;
971 		}
972 		verbose = oldverbose;
973 	}
974 	if (!cpend) {
975 		code = -1;
976 		(void) signal(SIGINT,oldintr);
977 		return;
978 	}
979 
980 	fprintf(cout,"%c%c",IAC,IP);
981 	(void) fflush(cout);
982 	msg = IAC;
983 /* send IAC in urgent mode instead of DM because UNIX places oob mark */
984 /* after urgent byte rather than before as now is protocol            */
985 	if (send(fileno(cout),&msg,1,MSG_OOB) != 1) {
986 		perror("abort");
987 	}
988 	fprintf(cout,"%cABOR\r\n",DM);
989 	(void) fflush(cout);
990 	FD_ZERO(&mask);
991 	FD_SET(fileno(cin), &mask);
992 	if (din) {
993 		FD_SET(fileno(din), &mask);
994 	}
995 	if ((nfnd = empty(&mask,10)) <= 0) {
996 		if (nfnd < 0) {
997 			perror("abort");
998 		}
999 		code = -1;
1000 		lostpeer();
1001 	}
1002 	if (din && FD_ISSET(fileno(din), &mask)) {
1003 		while ((c = read(fileno(din), buf, bufsize)) > 0)
1004 			;
1005 	}
1006 	if ((c = getreply(0)) == ERROR && code == 552) { /* needed for nic style abort */
1007 		if (data >= 0) {
1008 			(void) close(data);
1009 			data = -1;
1010 		}
1011 		(void) getreply(0);
1012 	}
1013 	(void) getreply(0);
1014 	code = -1;
1015 	if (data >= 0) {
1016 		(void) close(data);
1017 		data = -1;
1018 	}
1019 	if (closefunc != NULL && fout != NULL)
1020 		(*closefunc)(fout);
1021 	if (din)
1022 		(void) fclose(din);
1023 	if (bytes > 0)
1024 		ptransfer("received", bytes, &start, &stop);
1025 	(void) signal(SIGINT,oldintr);
1026 }
1027 
1028 /*
1029  * Need to start a listen on the data channel
1030  * before we send the command, otherwise the
1031  * server's connect may fail.
1032  */
1033 int sendport = -1;
1034 
1035 initconn()
1036 {
1037 	register char *p, *a;
1038 	int result, len, tmpno = 0;
1039 	int on = 1;
1040 
1041 noport:
1042 	data_addr = myctladdr;
1043 	if (sendport)
1044 		data_addr.sin_port = 0;	/* let system pick one */
1045 	if (data != -1)
1046 		(void) close (data);
1047 	data = socket(AF_INET, SOCK_STREAM, 0);
1048 	if (data < 0) {
1049 		perror("ftp: socket");
1050 		if (tmpno)
1051 			sendport = 1;
1052 		return (1);
1053 	}
1054 	if (!sendport)
1055 		if (setsockopt(data, SOL_SOCKET, SO_REUSEADDR, (char *)&on, sizeof (on)) < 0) {
1056 			perror("ftp: setsockopt (reuse address)");
1057 			goto bad;
1058 		}
1059 	if (bind(data, (struct sockaddr *)&data_addr, sizeof (data_addr)) < 0) {
1060 		perror("ftp: bind");
1061 		goto bad;
1062 	}
1063 	if (options & SO_DEBUG &&
1064 	    setsockopt(data, SOL_SOCKET, SO_DEBUG, (char *)&on, sizeof (on)) < 0)
1065 		perror("ftp: setsockopt (ignored)");
1066 	len = sizeof (data_addr);
1067 	if (getsockname(data, (char *)&data_addr, &len) < 0) {
1068 		perror("ftp: getsockname");
1069 		goto bad;
1070 	}
1071 	if (listen(data, 1) < 0)
1072 		perror("ftp: listen");
1073 	if (sendport) {
1074 		a = (char *)&data_addr.sin_addr;
1075 		p = (char *)&data_addr.sin_port;
1076 #define	UC(b)	(((int)b)&0xff)
1077 		result =
1078 		    command("PORT %d,%d,%d,%d,%d,%d",
1079 		      UC(a[0]), UC(a[1]), UC(a[2]), UC(a[3]),
1080 		      UC(p[0]), UC(p[1]));
1081 		if (result == ERROR && sendport == -1) {
1082 			sendport = 0;
1083 			tmpno = 1;
1084 			goto noport;
1085 		}
1086 		return (result != COMPLETE);
1087 	}
1088 	if (tmpno)
1089 		sendport = 1;
1090 	return (0);
1091 bad:
1092 	(void) close(data), data = -1;
1093 	if (tmpno)
1094 		sendport = 1;
1095 	return (1);
1096 }
1097 
1098 FILE *
1099 dataconn(mode)
1100 	char *mode;
1101 {
1102 	struct sockaddr_in from;
1103 	int s, fromlen = sizeof (from);
1104 
1105 	s = accept(data, (struct sockaddr *) &from, &fromlen);
1106 	if (s < 0) {
1107 		perror("ftp: accept");
1108 		(void) close(data), data = -1;
1109 		return (NULL);
1110 	}
1111 	(void) close(data);
1112 	data = s;
1113 	return (fdopen(data, mode));
1114 }
1115 
1116 ptransfer(direction, bytes, t0, t1)
1117 	char *direction;
1118 	long bytes;
1119 	struct timeval *t0, *t1;
1120 {
1121 	struct timeval td;
1122 	float s, bs;
1123 
1124 	if (verbose) {
1125 		tvsub(&td, t1, t0);
1126 		s = td.tv_sec + (td.tv_usec / 1000000.);
1127 #define	nz(x)	((x) == 0 ? 1 : (x))
1128 		bs = bytes / nz(s);
1129 		printf("%ld bytes %s in %.2g seconds (%.2g Kbytes/s)\n",
1130 		    bytes, direction, s, bs / 1024.);
1131 	}
1132 }
1133 
1134 /*tvadd(tsum, t0)
1135 	struct timeval *tsum, *t0;
1136 {
1137 
1138 	tsum->tv_sec += t0->tv_sec;
1139 	tsum->tv_usec += t0->tv_usec;
1140 	if (tsum->tv_usec > 1000000)
1141 		tsum->tv_sec++, tsum->tv_usec -= 1000000;
1142 } */
1143 
1144 tvsub(tdiff, t1, t0)
1145 	struct timeval *tdiff, *t1, *t0;
1146 {
1147 
1148 	tdiff->tv_sec = t1->tv_sec - t0->tv_sec;
1149 	tdiff->tv_usec = t1->tv_usec - t0->tv_usec;
1150 	if (tdiff->tv_usec < 0)
1151 		tdiff->tv_sec--, tdiff->tv_usec += 1000000;
1152 }
1153 
1154 psabort()
1155 {
1156 	extern int abrtflag;
1157 
1158 	abrtflag++;
1159 }
1160 
1161 pswitch(flag)
1162 	int flag;
1163 {
1164 	extern int proxy, abrtflag;
1165 	int (*oldintr)();
1166 	static struct comvars {
1167 		int connect;
1168 		char name[MAXHOSTNAMELEN];
1169 		struct sockaddr_in mctl;
1170 		struct sockaddr_in hctl;
1171 		FILE *in;
1172 		FILE *out;
1173 		int tpe;
1174 		int cpnd;
1175 		int sunqe;
1176 		int runqe;
1177 		int mcse;
1178 		int ntflg;
1179 		char nti[17];
1180 		char nto[17];
1181 		int mapflg;
1182 		char mi[MAXPATHLEN];
1183 		char mo[MAXPATHLEN];
1184 		} proxstruct, tmpstruct;
1185 	struct comvars *ip, *op;
1186 
1187 	abrtflag = 0;
1188 	oldintr = signal(SIGINT, psabort);
1189 	if (flag) {
1190 		if (proxy)
1191 			return;
1192 		ip = &tmpstruct;
1193 		op = &proxstruct;
1194 		proxy++;
1195 	}
1196 	else {
1197 		if (!proxy)
1198 			return;
1199 		ip = &proxstruct;
1200 		op = &tmpstruct;
1201 		proxy = 0;
1202 	}
1203 	ip->connect = connected;
1204 	connected = op->connect;
1205 	if (hostname) {
1206 		(void) strncpy(ip->name, hostname, sizeof(ip->name) - 1);
1207 		ip->name[strlen(ip->name)] = '\0';
1208 	} else
1209 		ip->name[0] = 0;
1210 	hostname = op->name;
1211 	ip->hctl = hisctladdr;
1212 	hisctladdr = op->hctl;
1213 	ip->mctl = myctladdr;
1214 	myctladdr = op->mctl;
1215 	ip->in = cin;
1216 	cin = op->in;
1217 	ip->out = cout;
1218 	cout = op->out;
1219 	ip->tpe = type;
1220 	type = op->tpe;
1221 	if (!type)
1222 		type = 1;
1223 	ip->cpnd = cpend;
1224 	cpend = op->cpnd;
1225 	ip->sunqe = sunique;
1226 	sunique = op->sunqe;
1227 	ip->runqe = runique;
1228 	runique = op->runqe;
1229 	ip->mcse = mcase;
1230 	mcase = op->mcse;
1231 	ip->ntflg = ntflag;
1232 	ntflag = op->ntflg;
1233 	(void) strncpy(ip->nti, ntin, 16);
1234 	(ip->nti)[strlen(ip->nti)] = '\0';
1235 	(void) strcpy(ntin, op->nti);
1236 	(void) strncpy(ip->nto, ntout, 16);
1237 	(ip->nto)[strlen(ip->nto)] = '\0';
1238 	(void) strcpy(ntout, op->nto);
1239 	ip->mapflg = mapflag;
1240 	mapflag = op->mapflg;
1241 	(void) strncpy(ip->mi, mapin, MAXPATHLEN - 1);
1242 	(ip->mi)[strlen(ip->mi)] = '\0';
1243 	(void) strcpy(mapin, op->mi);
1244 	(void) strncpy(ip->mo, mapout, MAXPATHLEN - 1);
1245 	(ip->mo)[strlen(ip->mo)] = '\0';
1246 	(void) strcpy(mapout, op->mo);
1247 	(void) signal(SIGINT, oldintr);
1248 	if (abrtflag) {
1249 		abrtflag = 0;
1250 		(*oldintr)();
1251 	}
1252 }
1253 
1254 jmp_buf ptabort;
1255 int ptabflg;
1256 
1257 abortpt()
1258 {
1259 	printf("\n");
1260 	(void) fflush(stdout);
1261 	ptabflg++;
1262 	mflag = 0;
1263 	abrtflag = 0;
1264 	longjmp(ptabort, 1);
1265 }
1266 
1267 proxtrans(cmd, local, remote)
1268 	char *cmd, *local, *remote;
1269 {
1270 	int (*oldintr)(), abortpt(), tmptype, oldtype = 0, secndflag = 0, nfnd;
1271 	extern jmp_buf ptabort;
1272 	char *cmd2;
1273 	struct fd_set mask;
1274 
1275 	if (strcmp(cmd, "RETR"))
1276 		cmd2 = "RETR";
1277 	else
1278 		cmd2 = runique ? "STOU" : "STOR";
1279 	if (command("PASV") != COMPLETE) {
1280 		printf("proxy server does not support third part transfers.\n");
1281 		return;
1282 	}
1283 	tmptype = type;
1284 	pswitch(0);
1285 	if (!connected) {
1286 		printf("No primary connection\n");
1287 		pswitch(1);
1288 		code = -1;
1289 		return;
1290 	}
1291 	if (type != tmptype) {
1292 		oldtype = type;
1293 		switch (tmptype) {
1294 			case TYPE_A:
1295 				setascii();
1296 				break;
1297 			case TYPE_I:
1298 				setbinary();
1299 				break;
1300 			case TYPE_E:
1301 				setebcdic();
1302 				break;
1303 			case TYPE_L:
1304 				settenex();
1305 				break;
1306 		}
1307 	}
1308 	if (command("PORT %s", pasv) != COMPLETE) {
1309 		switch (oldtype) {
1310 			case 0:
1311 				break;
1312 			case TYPE_A:
1313 				setascii();
1314 				break;
1315 			case TYPE_I:
1316 				setbinary();
1317 				break;
1318 			case TYPE_E:
1319 				setebcdic();
1320 				break;
1321 			case TYPE_L:
1322 				settenex();
1323 				break;
1324 		}
1325 		pswitch(1);
1326 		return;
1327 	}
1328 	if (setjmp(ptabort))
1329 		goto abort;
1330 	oldintr = signal(SIGINT, abortpt);
1331 	if (command("%s %s", cmd, remote) != PRELIM) {
1332 		(void) signal(SIGINT, oldintr);
1333 		switch (oldtype) {
1334 			case 0:
1335 				break;
1336 			case TYPE_A:
1337 				setascii();
1338 				break;
1339 			case TYPE_I:
1340 				setbinary();
1341 				break;
1342 			case TYPE_E:
1343 				setebcdic();
1344 				break;
1345 			case TYPE_L:
1346 				settenex();
1347 				break;
1348 		}
1349 		pswitch(1);
1350 		return;
1351 	}
1352 	sleep(2);
1353 	pswitch(1);
1354 	secndflag++;
1355 	if (command("%s %s", cmd2, local) != PRELIM)
1356 		goto abort;
1357 	ptflag++;
1358 	(void) getreply(0);
1359 	pswitch(0);
1360 	(void) getreply(0);
1361 	(void) signal(SIGINT, oldintr);
1362 	switch (oldtype) {
1363 		case 0:
1364 			break;
1365 		case TYPE_A:
1366 			setascii();
1367 			break;
1368 		case TYPE_I:
1369 			setbinary();
1370 			break;
1371 		case TYPE_E:
1372 			setebcdic();
1373 			break;
1374 		case TYPE_L:
1375 			settenex();
1376 			break;
1377 	}
1378 	pswitch(1);
1379 	ptflag = 0;
1380 	printf("local: %s remote: %s\n", local, remote);
1381 	return;
1382 abort:
1383 	(void) signal(SIGINT, SIG_IGN);
1384 	ptflag = 0;
1385 	if (strcmp(cmd, "RETR") && !proxy)
1386 		pswitch(1);
1387 	else if (!strcmp(cmd, "RETR") && proxy)
1388 		pswitch(0);
1389 	if (!cpend && !secndflag) {  /* only here if cmd = "STOR" (proxy=1) */
1390 		if (command("%s %s", cmd2, local) != PRELIM) {
1391 			pswitch(0);
1392 			switch (oldtype) {
1393 				case 0:
1394 					break;
1395 				case TYPE_A:
1396 					setascii();
1397 					break;
1398 				case TYPE_I:
1399 					setbinary();
1400 					break;
1401 				case TYPE_E:
1402 					setebcdic();
1403 					break;
1404 				case TYPE_L:
1405 					settenex();
1406 					break;
1407 			}
1408 			if (cpend) {
1409 				char msg[2];
1410 
1411 				fprintf(cout,"%c%c",IAC,IP);
1412 				(void) fflush(cout);
1413 				*msg = IAC;
1414 				*(msg+1) = DM;
1415 				if (send(fileno(cout),msg,2,MSG_OOB) != 2)
1416 					perror("abort");
1417 				fprintf(cout,"ABOR\r\n");
1418 				(void) fflush(cout);
1419 				FD_ZERO(&mask);
1420 				FD_SET(fileno(cin), &mask);
1421 				if ((nfnd = empty(&mask,10)) <= 0) {
1422 					if (nfnd < 0) {
1423 						perror("abort");
1424 					}
1425 					if (ptabflg)
1426 						code = -1;
1427 					lostpeer();
1428 				}
1429 				(void) getreply(0);
1430 				(void) getreply(0);
1431 			}
1432 		}
1433 		pswitch(1);
1434 		if (ptabflg)
1435 			code = -1;
1436 		(void) signal(SIGINT, oldintr);
1437 		return;
1438 	}
1439 	if (cpend) {
1440 		char msg[2];
1441 
1442 		fprintf(cout,"%c%c",IAC,IP);
1443 		(void) fflush(cout);
1444 		*msg = IAC;
1445 		*(msg+1) = DM;
1446 		if (send(fileno(cout),msg,2,MSG_OOB) != 2)
1447 			perror("abort");
1448 		fprintf(cout,"ABOR\r\n");
1449 		(void) fflush(cout);
1450 		FD_ZERO(&mask);
1451 		FD_SET(fileno(cin), &mask);
1452 		if ((nfnd = empty(&mask,10)) <= 0) {
1453 			if (nfnd < 0) {
1454 				perror("abort");
1455 			}
1456 			if (ptabflg)
1457 				code = -1;
1458 			lostpeer();
1459 		}
1460 		(void) getreply(0);
1461 		(void) getreply(0);
1462 	}
1463 	pswitch(!proxy);
1464 	if (!cpend && !secndflag) {  /* only if cmd = "RETR" (proxy=1) */
1465 		if (command("%s %s", cmd2, local) != PRELIM) {
1466 			pswitch(0);
1467 			switch (oldtype) {
1468 				case 0:
1469 					break;
1470 				case TYPE_A:
1471 					setascii();
1472 					break;
1473 				case TYPE_I:
1474 					setbinary();
1475 					break;
1476 				case TYPE_E:
1477 					setebcdic();
1478 					break;
1479 				case TYPE_L:
1480 					settenex();
1481 					break;
1482 			}
1483 			if (cpend) {
1484 				char msg[2];
1485 
1486 				fprintf(cout,"%c%c",IAC,IP);
1487 				(void) fflush(cout);
1488 				*msg = IAC;
1489 				*(msg+1) = DM;
1490 				if (send(fileno(cout),msg,2,MSG_OOB) != 2)
1491 					perror("abort");
1492 				fprintf(cout,"ABOR\r\n");
1493 				(void) fflush(cout);
1494 				FD_ZERO(&mask);
1495 				FD_SET(fileno(cin), &mask);
1496 				if ((nfnd = empty(&mask,10)) <= 0) {
1497 					if (nfnd < 0) {
1498 						perror("abort");
1499 					}
1500 					if (ptabflg)
1501 						code = -1;
1502 					lostpeer();
1503 				}
1504 				(void) getreply(0);
1505 				(void) getreply(0);
1506 			}
1507 			pswitch(1);
1508 			if (ptabflg)
1509 				code = -1;
1510 			(void) signal(SIGINT, oldintr);
1511 			return;
1512 		}
1513 	}
1514 	if (cpend) {
1515 		char msg[2];
1516 
1517 		fprintf(cout,"%c%c",IAC,IP);
1518 		(void) fflush(cout);
1519 		*msg = IAC;
1520 		*(msg+1) = DM;
1521 		if (send(fileno(cout),msg,2,MSG_OOB) != 2)
1522 			perror("abort");
1523 		fprintf(cout,"ABOR\r\n");
1524 		(void) fflush(cout);
1525 		FD_ZERO(&mask);
1526 		FD_SET(fileno(cin), &mask);
1527 		if ((nfnd = empty(&mask,10)) <= 0) {
1528 			if (nfnd < 0) {
1529 				perror("abort");
1530 			}
1531 			if (ptabflg)
1532 				code = -1;
1533 			lostpeer();
1534 		}
1535 		(void) getreply(0);
1536 		(void) getreply(0);
1537 	}
1538 	pswitch(!proxy);
1539 	if (cpend) {
1540 		FD_ZERO(&mask);
1541 		FD_SET(fileno(cin), &mask);
1542 		if ((nfnd = empty(&mask,10)) <= 0) {
1543 			if (nfnd < 0) {
1544 				perror("abort");
1545 			}
1546 			if (ptabflg)
1547 				code = -1;
1548 			lostpeer();
1549 		}
1550 		(void) getreply(0);
1551 		(void) getreply(0);
1552 	}
1553 	if (proxy)
1554 		pswitch(0);
1555 	switch (oldtype) {
1556 		case 0:
1557 			break;
1558 		case TYPE_A:
1559 			setascii();
1560 			break;
1561 		case TYPE_I:
1562 			setbinary();
1563 			break;
1564 		case TYPE_E:
1565 			setebcdic();
1566 			break;
1567 		case TYPE_L:
1568 			settenex();
1569 			break;
1570 	}
1571 	pswitch(1);
1572 	if (ptabflg)
1573 		code = -1;
1574 	(void) signal(SIGINT, oldintr);
1575 }
1576 
1577 reset()
1578 {
1579 	struct fd_set mask;
1580 	int nfnd = 1;
1581 
1582 	FD_ZERO(&mask);
1583 	while (nfnd > 0) {
1584 		FD_SET(fileno(cin), &mask);
1585 		if ((nfnd = empty(&mask,0)) < 0) {
1586 			perror("reset");
1587 			code = -1;
1588 			lostpeer();
1589 		}
1590 		else if (nfnd) {
1591 			(void) getreply(0);
1592 		}
1593 	}
1594 }
1595 
1596 char *
1597 gunique(local)
1598 	char *local;
1599 {
1600 	static char new[MAXPATHLEN];
1601 	char *cp = rindex(local, '/');
1602 	int d, count=0;
1603 	char ext = '1';
1604 
1605 	if (cp)
1606 		*cp = '\0';
1607 	d = access(cp ? local : ".", 2);
1608 	if (cp)
1609 		*cp = '/';
1610 	if (d < 0) {
1611 		perror(local);
1612 		return((char *) 0);
1613 	}
1614 	(void) strcpy(new, local);
1615 	cp = new + strlen(new);
1616 	*cp++ = '.';
1617 	while (!d) {
1618 		if (++count == 100) {
1619 			printf("runique: can't find unique file name.\n");
1620 			return((char *) 0);
1621 		}
1622 		*cp++ = ext;
1623 		*cp = '\0';
1624 		if (ext == '9')
1625 			ext = '0';
1626 		else
1627 			ext++;
1628 		if ((d = access(new, 0)) < 0)
1629 			break;
1630 		if (ext != '0')
1631 			cp--;
1632 		else if (*(cp - 2) == '.')
1633 			*(cp - 1) = '1';
1634 		else {
1635 			*(cp - 2) = *(cp - 2) + 1;
1636 			cp--;
1637 		}
1638 	}
1639 	return(new);
1640 }
1641