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