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