xref: /csrg-svn/usr.bin/ftp/ftp.c (revision 36942)
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.24.1.1 (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 #ifdef RESTART
51 off_t	restart_point = 0;
52 #endif
53 
54 FILE	*cin, *cout;
55 FILE	*dataconn();
56 
57 char *
58 hookup(host, port)
59 	char *host;
60 	int port;
61 {
62 	register struct hostent *hp = 0;
63 	int s,len;
64 	static char hostnamebuf[80];
65 
66 	bzero((char *)&hisctladdr, sizeof (hisctladdr));
67 	hisctladdr.sin_addr.s_addr = inet_addr(host);
68 	if (hisctladdr.sin_addr.s_addr != -1) {
69 		hisctladdr.sin_family = AF_INET;
70 		(void) strncpy(hostnamebuf, host, sizeof(hostnamebuf));
71 	} else {
72 		hp = gethostbyname(host);
73 		if (hp == NULL) {
74 			fprintf(stderr, "ftp: %s: ", host);
75 			herror((char *)NULL);
76 			code = -1;
77 			return((char *) 0);
78 		}
79 		hisctladdr.sin_family = hp->h_addrtype;
80 		bcopy(hp->h_addr_list[0],
81 		    (caddr_t)&hisctladdr.sin_addr, hp->h_length);
82 		(void) strncpy(hostnamebuf, hp->h_name, sizeof(hostnamebuf));
83 	}
84 	hostname = hostnamebuf;
85 	s = socket(hisctladdr.sin_family, SOCK_STREAM, 0);
86 	if (s < 0) {
87 		perror("ftp: socket");
88 		code = -1;
89 		return (0);
90 	}
91 	hisctladdr.sin_port = port;
92 	while (connect(s, &hisctladdr, sizeof (hisctladdr)) < 0) {
93 		if (hp && hp->h_addr_list[1]) {
94 			int oerrno = errno;
95 
96 			fprintf(stderr, "ftp: connect to address %s: ",
97 				inet_ntoa(hisctladdr.sin_addr));
98 			errno = oerrno;
99 			perror((char *) 0);
100 			hp->h_addr_list++;
101 			bcopy(hp->h_addr_list[0],
102 			     (caddr_t)&hisctladdr.sin_addr, hp->h_length);
103 			fprintf(stdout, "Trying %s...\n",
104 				inet_ntoa(hisctladdr.sin_addr));
105 			(void) close(s);
106 			s = socket(hisctladdr.sin_family, SOCK_STREAM, 0);
107 			if (s < 0) {
108 				perror("ftp: socket");
109 				code = -1;
110 				return (0);
111 			}
112 			continue;
113 		}
114 		perror("ftp: connect");
115 		code = -1;
116 		goto bad;
117 	}
118 	len = sizeof (myctladdr);
119 	if (getsockname(s, (char *)&myctladdr, &len) < 0) {
120 		perror("ftp: getsockname");
121 		code = -1;
122 		goto bad;
123 	}
124 	cin = fdopen(s, "r");
125 	cout = fdopen(s, "w");
126 	if (cin == NULL || cout == NULL) {
127 		fprintf(stderr, "ftp: fdopen failed.\n");
128 		if (cin)
129 			(void) fclose(cin);
130 		if (cout)
131 			(void) fclose(cout);
132 		code = -1;
133 		goto bad;
134 	}
135 	if (verbose)
136 		printf("Connected to %s.\n", hostname);
137 	if (getreply(0) > 2) { 	/* read startup message from server */
138 		if (cin)
139 			(void) fclose(cin);
140 		if (cout)
141 			(void) fclose(cout);
142 		code = -1;
143 		goto bad;
144 	}
145 #ifdef SO_OOBINLINE
146 	{
147 	int on = 1;
148 
149 	if (setsockopt(s, SOL_SOCKET, SO_OOBINLINE, &on, sizeof(on))
150 		< 0 && debug) {
151 			perror("ftp: setsockopt");
152 		}
153 	}
154 #endif SO_OOBINLINE
155 
156 	return (hostname);
157 bad:
158 	(void) close(s);
159 	return ((char *)0);
160 }
161 
162 login(host)
163 	char *host;
164 {
165 	char tmp[80];
166 	char *user, *pass, *acct, *getlogin(), *getpass();
167 	int n, aflag = 0;
168 
169 	user = pass = acct = 0;
170 	if (ruserpass(host, &user, &pass, &acct) < 0) {
171 		code = -1;
172 		return(0);
173 	}
174 	if (user == NULL) {
175 		char *myname = getlogin();
176 
177 		if (myname == NULL) {
178 			struct passwd *pp = getpwuid(getuid());
179 
180 			if (pp != NULL)
181 				myname = pp->pw_name;
182 		}
183 		printf("Name (%s:%s): ", host, myname);
184 		(void) fgets(tmp, sizeof(tmp) - 1, stdin);
185 		tmp[strlen(tmp) - 1] = '\0';
186 		if (*tmp == '\0')
187 			user = myname;
188 		else
189 			user = tmp;
190 	}
191 	n = command("USER %s", user);
192 	if (n == CONTINUE) {
193 		if (pass == NULL)
194 			pass = getpass("Password:");
195 		n = command("PASS %s", pass);
196 	}
197 	if (n == CONTINUE) {
198 		aflag++;
199 		acct = getpass("Account:");
200 		n = command("ACCT %s", acct);
201 	}
202 	if (n != COMPLETE) {
203 		fprintf(stderr, "Login failed.\n");
204 		return (0);
205 	}
206 	if (!aflag && acct != NULL)
207 		(void) command("ACCT %s", acct);
208 	if (proxy)
209 		return(1);
210 	for (n = 0; n < macnum; ++n) {
211 		if (!strcmp("init", macros[n].mac_name)) {
212 			(void) strcpy(line, "$init");
213 			makeargv();
214 			domacro(margc, margv);
215 			break;
216 		}
217 	}
218 	return (1);
219 }
220 
221 cmdabort()
222 {
223 	extern jmp_buf ptabort;
224 
225 	printf("\n");
226 	(void) fflush(stdout);
227 	abrtflag++;
228 	if (ptflag)
229 		longjmp(ptabort,1);
230 }
231 
232 /*VARARGS1*/
233 command(fmt, args)
234 	char *fmt;
235 {
236 	int r, (*oldintr)(), cmdabort();
237 
238 	abrtflag = 0;
239 	if (debug) {
240 		printf("---> ");
241 		_doprnt(fmt, &args, stdout);
242 		printf("\n");
243 		(void) fflush(stdout);
244 	}
245 	if (cout == NULL) {
246 		perror ("No control connection for command");
247 		code = -1;
248 		return (0);
249 	}
250 	oldintr = signal(SIGINT,cmdabort);
251 	_doprnt(fmt, &args, cout);
252 	fprintf(cout, "\r\n");
253 	(void) fflush(cout);
254 	cpend = 1;
255 	r = getreply(!strcmp(fmt, "QUIT"));
256 	if (abrtflag && oldintr != SIG_IGN)
257 		(*oldintr)();
258 	(void) signal(SIGINT, oldintr);
259 	return(r);
260 }
261 
262 char reply_string[BUFSIZ];
263 
264 #include <ctype.h>
265 
266 getreply(expecteof)
267 	int expecteof;
268 {
269 	register int c, n;
270 	register int dig;
271 	register char *cp;
272 	int originalcode = 0, continuation = 0, (*oldintr)(), cmdabort();
273 	int pflag = 0;
274 	char *pt = pasv;
275 
276 	cp = reply_string;
277 	oldintr = signal(SIGINT,cmdabort);
278 	for (;;) {
279 		dig = n = code = 0;
280 		while ((c = getc(cin)) != '\n') {
281 			if (c == IAC) {     /* handle telnet commands */
282 				switch (c = getc(cin)) {
283 				case WILL:
284 				case WONT:
285 					c = getc(cin);
286 					fprintf(cout, "%c%c%c",IAC,DONT,c);
287 					(void) fflush(cout);
288 					break;
289 				case DO:
290 				case DONT:
291 					c = getc(cin);
292 					fprintf(cout, "%c%c%c",IAC,WONT,c);
293 					(void) fflush(cout);
294 					break;
295 				default:
296 					break;
297 				}
298 				continue;
299 			}
300 			dig++;
301 			if (c == EOF) {
302 				if (expecteof) {
303 					(void) signal(SIGINT,oldintr);
304 					code = 221;
305 					return (0);
306 				}
307 				lostpeer();
308 				if (verbose) {
309 					printf("421 Service not available, remote server has closed connection\n");
310 					(void) fflush(stdout);
311 				}
312 				code = 421;
313 				return(4);
314 			}
315 			if (c != '\r' && (verbose > 0 ||
316 			    (verbose > -1 && n == '5' && dig > 4))) {
317 				if (proxflag &&
318 				   (dig == 1 || dig == 5 && verbose == 0))
319 					printf("%s:",hostname);
320 				(void) putchar(c);
321 			}
322 			if (dig < 4 && isdigit(c))
323 				code = code * 10 + (c - '0');
324 			if (!pflag && code == 227)
325 				pflag = 1;
326 			if (dig > 4 && pflag == 1 && isdigit(c))
327 				pflag = 2;
328 			if (pflag == 2) {
329 				if (c != '\r' && c != ')')
330 					*pt++ = c;
331 				else {
332 					*pt = '\0';
333 					pflag = 3;
334 				}
335 			}
336 			if (dig == 4 && c == '-') {
337 				if (continuation)
338 					code = 0;
339 				continuation++;
340 			}
341 			if (n == 0)
342 				n = c;
343 			*cp++ = c;
344 		}
345 		if (verbose > 0 || verbose > -1 && n == '5') {
346 			(void) putchar(c);
347 			(void) fflush (stdout);
348 		}
349 		if (continuation && code != originalcode) {
350 			if (originalcode == 0)
351 				originalcode = code;
352 			continue;
353 		}
354 		*cp = '\0';
355 		if (n != '1')
356 			cpend = 0;
357 		(void) signal(SIGINT,oldintr);
358 		if (code == 421 || originalcode == 421)
359 			lostpeer();
360 		if (abrtflag && oldintr != cmdabort && oldintr != SIG_IGN)
361 			(*oldintr)();
362 		return (n - '0');
363 	}
364 }
365 
366 empty(mask, sec)
367 	struct fd_set *mask;
368 	int sec;
369 {
370 	struct timeval t;
371 
372 	t.tv_sec = (long) sec;
373 	t.tv_usec = 0;
374 	return(select(32, mask, (struct fd_set *) 0, (struct fd_set *) 0, &t));
375 }
376 
377 jmp_buf	sendabort;
378 
379 abortsend()
380 {
381 
382 	mflag = 0;
383 	abrtflag = 0;
384 	printf("\nsend aborted\n");
385 	(void) fflush(stdout);
386 	longjmp(sendabort, 1);
387 }
388 
389 #define HASHBYTES 1024
390 
391 sendrequest(cmd, local, remote)
392 	char *cmd, *local, *remote;
393 {
394 	FILE *fin, *dout = 0, *popen();
395 	int (*closefunc)(), pclose(), fclose(), (*oldintr)(), (*oldintp)();
396 	int abortsend();
397 	char buf[BUFSIZ], *bufp;
398 	long bytes = 0, hashbytes = HASHBYTES;
399 	register int c, d;
400 	struct stat st;
401 	struct timeval start, stop;
402 	char *mode;
403 
404 	if (proxy) {
405 		proxtrans(cmd, local, remote);
406 		return;
407 	}
408 	closefunc = NULL;
409 	oldintr = NULL;
410 	oldintp = NULL;
411 	mode = "w";
412 	if (setjmp(sendabort)) {
413 		while (cpend) {
414 			(void) getreply(0);
415 		}
416 		if (data >= 0) {
417 			(void) close(data);
418 			data = -1;
419 		}
420 		if (oldintr)
421 			(void) signal(SIGINT,oldintr);
422 		if (oldintp)
423 			(void) signal(SIGPIPE,oldintp);
424 		code = -1;
425 		return;
426 	}
427 	oldintr = signal(SIGINT, abortsend);
428 	if (strcmp(local, "-") == 0)
429 		fin = stdin;
430 	else if (*local == '|') {
431 		oldintp = signal(SIGPIPE,SIG_IGN);
432 		fin = popen(local + 1, "r");
433 		if (fin == NULL) {
434 			perror(local + 1);
435 			(void) signal(SIGINT, oldintr);
436 			(void) signal(SIGPIPE, oldintp);
437 			code = -1;
438 			return;
439 		}
440 		closefunc = pclose;
441 	} else {
442 		fin = fopen(local, "r");
443 		if (fin == NULL) {
444 			perror(local);
445 			(void) signal(SIGINT, oldintr);
446 			code = -1;
447 			return;
448 		}
449 		closefunc = fclose;
450 		if (fstat(fileno(fin), &st) < 0 ||
451 		    (st.st_mode&S_IFMT) != S_IFREG) {
452 			fprintf(stdout, "%s: not a plain file.\n", local);
453 			(void) signal(SIGINT, oldintr);
454 			fclose(fin);
455 			code = -1;
456 			return;
457 		}
458 	}
459 	if (initconn()) {
460 		(void) signal(SIGINT, oldintr);
461 		if (oldintp)
462 			(void) signal(SIGPIPE, oldintp);
463 		code = -1;
464 		if (closefunc != NULL)
465 			(*closefunc)(fin);
466 		return;
467 	}
468 	if (setjmp(sendabort))
469 		goto abort;
470 
471 #ifdef RESTART
472 	if (restart_point &&
473 	    (strcmp(cmd, "STOR") == 0 || strcmp(cmd, "APPE") == 0)) {
474 		if (fseek(fin, (long) restart_point, 0) < 0) {
475 			perror(local);
476 			restart_point = 0;
477 			if (closefunc != NULL)
478 				(*closefunc)(fin);
479 			return;
480 		}
481 		if (command("REST %ld", (long) restart_point)
482 			!= CONTINUE) {
483 			restart_point = 0;
484 			if (closefunc != NULL)
485 				(*closefunc)(fin);
486 			return;
487 		}
488 		restart_point = 0;
489 		mode = "r+w";
490 	}
491 #endif
492 	if (remote) {
493 		if (command("%s %s", cmd, remote) != PRELIM) {
494 			(void) signal(SIGINT, oldintr);
495 			if (oldintp)
496 				(void) signal(SIGPIPE, oldintp);
497 			if (closefunc != NULL)
498 				(*closefunc)(fin);
499 			return;
500 		}
501 	} else
502 		if (command("%s", cmd) != PRELIM) {
503 			(void) signal(SIGINT, oldintr);
504 			if (oldintp)
505 				(void) signal(SIGPIPE, oldintp);
506 			if (closefunc != NULL)
507 				(*closefunc)(fin);
508 			return;
509 		}
510 	dout = dataconn(mode);
511 	if (dout == NULL)
512 		goto abort;
513 	(void) gettimeofday(&start, (struct timezone *)0);
514 	oldintp = signal(SIGPIPE, SIG_IGN);
515 	switch (type) {
516 
517 	case TYPE_I:
518 	case TYPE_L:
519 		errno = d = 0;
520 		while ((c = read(fileno(fin), buf, sizeof (buf))) > 0) {
521 			bytes += c;
522 			for (bufp = buf; c > 0; c -= d, bufp += d)
523 				if ((d = write(fileno(dout), bufp, c)) <= 0)
524 					break;
525 			if (hash) {
526 				while (bytes >= hashbytes) {
527 					(void) putchar('#');
528 					hashbytes += HASHBYTES;
529 				}
530 				(void) fflush(stdout);
531 			}
532 		}
533 		if (hash && bytes > 0) {
534 			if (bytes < HASHBYTES)
535 				(void) putchar('#');
536 			(void) putchar('\n');
537 			(void) fflush(stdout);
538 		}
539 		if (c < 0)
540 			perror(local);
541 		if (d <= 0) {
542 			if (d == 0)
543 				fprintf(stderr, "netout: write returned 0?\n");
544 			else if (errno != EPIPE)
545 				perror("netout");
546 			bytes = -1;
547 		}
548 		break;
549 
550 	case TYPE_A:
551 		while ((c = getc(fin)) != EOF) {
552 			if (c == '\n') {
553 				while (hash && (bytes >= hashbytes)) {
554 					(void) putchar('#');
555 					(void) fflush(stdout);
556 					hashbytes += HASHBYTES;
557 				}
558 				if (ferror(dout))
559 					break;
560 				(void) putc('\r', dout);
561 				bytes++;
562 			}
563 			(void) putc(c, dout);
564 			bytes++;
565 	/*		if (c == '\r') {			  	*/
566 	/*		(void)	putc('\0', dout);  /* this violates rfc */
567 	/*			bytes++;				*/
568 	/*		}                          			*/
569 		}
570 		if (hash) {
571 			if (bytes < hashbytes)
572 				(void) putchar('#');
573 			(void) putchar('\n');
574 			(void) fflush(stdout);
575 		}
576 		if (ferror(fin))
577 			perror(local);
578 		if (ferror(dout)) {
579 			if (errno != EPIPE)
580 				perror("netout");
581 			bytes = -1;
582 		}
583 		break;
584 	}
585 	(void) gettimeofday(&stop, (struct timezone *)0);
586 	if (closefunc != NULL)
587 		(*closefunc)(fin);
588 	(void) fclose(dout);
589 	(void) getreply(0);
590 	(void) signal(SIGINT, oldintr);
591 	if (oldintp)
592 		(void) signal(SIGPIPE, oldintp);
593 	if (bytes > 0)
594 		ptransfer("sent", bytes, &start, &stop, local, remote);
595 	return;
596 abort:
597 	(void) gettimeofday(&stop, (struct timezone *)0);
598 	(void) signal(SIGINT, oldintr);
599 	if (oldintp)
600 		(void) signal(SIGPIPE, oldintp);
601 	if (!cpend) {
602 		code = -1;
603 		return;
604 	}
605 	if (data >= 0) {
606 		(void) close(data);
607 		data = -1;
608 	}
609 	if (dout)
610 		(void) fclose(dout);
611 	(void) getreply(0);
612 	code = -1;
613 	if (closefunc != NULL && fin != NULL)
614 		(*closefunc)(fin);
615 	if (bytes > 0)
616 		ptransfer("sent", bytes, &start, &stop, local, remote);
617 }
618 
619 jmp_buf	recvabort;
620 
621 abortrecv()
622 {
623 
624 	mflag = 0;
625 	abrtflag = 0;
626 	printf("\n");
627 	(void) fflush(stdout);
628 	longjmp(recvabort, 1);
629 }
630 
631 recvrequest(cmd, local, remote, mode)
632 	char *cmd, *local, *remote, *mode;
633 {
634 	FILE *fout, *din = 0, *popen();
635 	int (*closefunc)(), pclose(), fclose(), (*oldintr)(), (*oldintp)();
636 	int abortrecv(), oldverbose, oldtype = 0, is_retr, tcrflag, nfnd;
637 	char *buf, *bufp, *gunique(), msg;
638 	static int bufsize;
639 	long bytes = 0, hashbytes = HASHBYTES;
640 	struct fd_set mask;
641 	register int c, d;
642 	struct timeval start, stop;
643 	struct stat st;
644 	extern char *malloc();
645 
646 	is_retr = strcmp(cmd, "RETR") == 0;
647 	if (proxy && is_retr) {
648 		proxtrans(cmd, local, remote);
649 		return;
650 	}
651 	closefunc = NULL;
652 	oldintr = NULL;
653 	oldintp = NULL;
654 	tcrflag = !crflag && is_retr;
655 	if (setjmp(recvabort)) {
656 		while (cpend) {
657 			(void) getreply(0);
658 		}
659 		if (data >= 0) {
660 			(void) close(data);
661 			data = -1;
662 		}
663 		if (oldintr)
664 			(void) signal(SIGINT, oldintr);
665 		code = -1;
666 		return;
667 	}
668 	oldintr = signal(SIGINT, abortrecv);
669 	if (strcmp(local, "-") && *local != '|') {
670 		if (access(local, 2) < 0) {
671 			char *dir = rindex(local, '/');
672 
673 			if (errno != ENOENT && errno != EACCES) {
674 				perror(local);
675 				(void) signal(SIGINT, oldintr);
676 				code = -1;
677 				return;
678 			}
679 			if (dir != NULL)
680 				*dir = 0;
681 			d = access(dir ? local : ".", 2);
682 			if (dir != NULL)
683 				*dir = '/';
684 			if (d < 0) {
685 				perror(local);
686 				(void) signal(SIGINT, oldintr);
687 				code = -1;
688 				return;
689 			}
690 			if (!runique && errno == EACCES &&
691 			    chmod(local, 0600) < 0) {
692 				perror(local);
693 				(void) signal(SIGINT, oldintr);
694 				code = -1;
695 				return;
696 			}
697 			if (runique && errno == EACCES &&
698 			   (local = gunique(local)) == NULL) {
699 				(void) signal(SIGINT, oldintr);
700 				code = -1;
701 				return;
702 			}
703 		}
704 		else if (runique && (local = gunique(local)) == NULL) {
705 			(void) signal(SIGINT, oldintr);
706 			code = -1;
707 			return;
708 		}
709 	}
710 	if (initconn()) {
711 		(void) signal(SIGINT, oldintr);
712 		code = -1;
713 		return;
714 	}
715 	if (setjmp(recvabort))
716 		goto abort;
717 	if (!is_retr) {
718 		if (type != TYPE_A) {
719 			oldtype = type;
720 			oldverbose = verbose;
721 			if (!debug)
722 				verbose = 0;
723 			setascii();
724 			verbose = oldverbose;
725 		}
726 #ifdef RESTART
727 	} else if (restart_point) {
728 		if (command("REST %ld", (long) restart_point) != CONTINUE)
729 			return;
730 #endif
731 	}
732 	if (remote) {
733 		if (command("%s %s", cmd, remote) != PRELIM) {
734 			(void) signal(SIGINT, oldintr);
735 			if (oldtype) {
736 				if (!debug)
737 					verbose = 0;
738 				switch (oldtype) {
739 					case TYPE_I:
740 						setbinary();
741 						break;
742 					case TYPE_E:
743 						setebcdic();
744 						break;
745 					case TYPE_L:
746 						settenex();
747 						break;
748 				}
749 				verbose = oldverbose;
750 			}
751 			return;
752 		}
753 	} else {
754 		if (command("%s", cmd) != PRELIM) {
755 			(void) signal(SIGINT, oldintr);
756 			if (oldtype) {
757 				if (!debug)
758 					verbose = 0;
759 				switch (oldtype) {
760 					case TYPE_I:
761 						setbinary();
762 						break;
763 					case TYPE_E:
764 						setebcdic();
765 						break;
766 					case TYPE_L:
767 						settenex();
768 						break;
769 				}
770 				verbose = oldverbose;
771 			}
772 			return;
773 		}
774 	}
775 	din = dataconn("r");
776 	if (din == NULL)
777 		goto abort;
778 	if (strcmp(local, "-") == 0)
779 		fout = stdout;
780 	else if (*local == '|') {
781 		oldintp = signal(SIGPIPE, SIG_IGN);
782 		fout = popen(local + 1, "w");
783 		if (fout == NULL) {
784 			perror(local+1);
785 			goto abort;
786 		}
787 		closefunc = pclose;
788 	} else {
789 		fout = fopen(local, mode);
790 		if (fout == NULL) {
791 			perror(local);
792 			goto abort;
793 		}
794 		closefunc = fclose;
795 	}
796 	if (fstat(fileno(fout), &st) < 0 || st.st_blksize == 0)
797 		st.st_blksize = BUFSIZ;
798 	if (st.st_blksize > bufsize) {
799 		if (buf)
800 			(void) free(buf);
801 		buf = malloc(st.st_blksize);
802 		if (buf == NULL) {
803 			perror("malloc");
804 			goto abort;
805 		}
806 		bufsize = st.st_blksize;
807 	}
808 	(void) gettimeofday(&start, (struct timezone *)0);
809 	switch (type) {
810 
811 	case TYPE_I:
812 	case TYPE_L:
813 #ifdef RESTART
814 		if (restart_point &&
815 		    lseek(fileno(fout), (long) restart_point, L_SET) < 0) {
816 			perror(local);
817 			if (closefunc != NULL)
818 				(*closefunc)(fout);
819 			return;
820 		}
821 #endif
822 		errno = d = 0;
823 		while ((c = read(fileno(din), buf, bufsize)) > 0) {
824 			if ((d = write(fileno(fout), bufp, c)) != c)
825 				break;
826 			bytes += c;
827 			if (hash) {
828 				while (bytes >= hashbytes) {
829 					(void) putchar('#');
830 					hashbytes += HASHBYTES;
831 				}
832 				(void) fflush(stdout);
833 			}
834 		}
835 		if (hash && bytes > 0) {
836 			if (bytes < HASHBYTES)
837 				(void) putchar('#');
838 			(void) putchar('\n');
839 			(void) fflush(stdout);
840 		}
841 		if (c < 0) {
842 			if (errno != EPIPE)
843 				perror("netin");
844 			bytes = -1;
845 		}
846 		if (d < c) {
847 			if (d < 0)
848 				perror(local);
849 			else
850 				fprintf(stderr, "%s: short write\n", local);
851 		}
852 		break;
853 
854 	case TYPE_A:
855 #ifdef RESTART
856 		if (restart_point) {
857 			register int i, n, c;
858 
859 			if (fseek(fout, 0L, L_SET) < 0)
860 				goto done;
861 			n = restart_point;
862 			i = 0;
863 			while (i++ < n) {
864 				if ((c=getc(fout)) == EOF)
865 					goto done;
866 				if (c == '\n')
867 					i++;
868 			}
869 			if (fseek(fout, 0L, L_INCR) < 0) {
870 done:
871 				perror(local);
872 				if (closefunc != NULL)
873 					(*closefunc)(fout);
874 				return;
875 			}
876 		}
877 #endif
878 		while ((c = getc(din)) != EOF) {
879 			while (c == '\r') {
880 				while (hash && (bytes >= hashbytes)) {
881 					(void) putchar('#');
882 					(void) fflush(stdout);
883 					hashbytes += HASHBYTES;
884 				}
885 				bytes++;
886 				if ((c = getc(din)) != '\n' || tcrflag) {
887 					if (ferror(fout))
888 						goto break2;
889 					(void) putc('\r', fout);
890 					if (c == '\0') {
891 						bytes++;
892 						goto contin2;
893 					}
894 					if (c == EOF)
895 						goto contin2;
896 				}
897 			}
898 			(void) putc(c, fout);
899 			bytes++;
900 	contin2:	;
901 		}
902 break2:
903 		if (hash) {
904 			if (bytes < hashbytes)
905 				(void) putchar('#');
906 			(void) putchar('\n');
907 			(void) fflush(stdout);
908 		}
909 		if (ferror(din)){
910 			if (errno != EPIPE)
911 				perror ("netin");
912 			bytes = -1;
913 		}
914 		if (ferror(fout))
915 			perror (local);
916 		break;
917 	}
918 	if (closefunc != NULL)
919 		(*closefunc)(fout);
920 	(void) signal(SIGINT, oldintr);
921 	if (oldintp)
922 		(void) signal(SIGPIPE, oldintp);
923 	(void) gettimeofday(&stop, (struct timezone *)0);
924 	(void) fclose(din);
925 	(void) getreply(0);
926 	if (bytes > 0 && is_retr)
927 		ptransfer("received", bytes, &start, &stop, local, remote);
928 	if (oldtype) {
929 		if (!debug)
930 			verbose = 0;
931 		switch (oldtype) {
932 			case TYPE_I:
933 				setbinary();
934 				break;
935 			case TYPE_E:
936 				setebcdic();
937 				break;
938 			case TYPE_L:
939 				settenex();
940 				break;
941 		}
942 		verbose = oldverbose;
943 	}
944 	return;
945 abort:
946 
947 /* abort using RFC959 recommended IP,SYNC sequence  */
948 
949 	(void) gettimeofday(&stop, (struct timezone *)0);
950 	if (oldintp)
951 		(void) signal(SIGPIPE, oldintr);
952 	(void) signal(SIGINT,SIG_IGN);
953 	if (oldtype) {
954 		if (!debug)
955 			verbose = 0;
956 		switch (oldtype) {
957 			case TYPE_I:
958 				setbinary();
959 				break;
960 			case TYPE_E:
961 				setebcdic();
962 				break;
963 			case TYPE_L:
964 				settenex();
965 				break;
966 		}
967 		verbose = oldverbose;
968 	}
969 	if (!cpend) {
970 		code = -1;
971 		(void) signal(SIGINT,oldintr);
972 		return;
973 	}
974 
975 	fprintf(cout,"%c%c",IAC,IP);
976 	(void) fflush(cout);
977 	msg = IAC;
978 /* send IAC in urgent mode instead of DM because UNIX places oob mark */
979 /* after urgent byte rather than before as now is protocol            */
980 	if (send(fileno(cout),&msg,1,MSG_OOB) != 1) {
981 		perror("abort");
982 	}
983 	fprintf(cout,"%cABOR\r\n",DM);
984 	(void) fflush(cout);
985 	FD_ZERO(&mask);
986 	FD_SET(fileno(cin), &mask);
987 	if (din) {
988 		FD_SET(fileno(din), &mask);
989 	}
990 	if ((nfnd = empty(&mask,10)) <= 0) {
991 		if (nfnd < 0) {
992 			perror("abort");
993 		}
994 		code = -1;
995 		lostpeer();
996 	}
997 	if (din && FD_ISSET(fileno(din), &mask)) {
998 		while ((c = read(fileno(din), buf, bufsize)) > 0)
999 			;
1000 	}
1001 	if ((c = getreply(0)) == ERROR && code == 552) { /* needed for nic style abort */
1002 		if (data >= 0) {
1003 			(void) close(data);
1004 			data = -1;
1005 		}
1006 		(void) getreply(0);
1007 	}
1008 	(void) getreply(0);
1009 	code = -1;
1010 	if (data >= 0) {
1011 		(void) close(data);
1012 		data = -1;
1013 	}
1014 	if (closefunc != NULL && fout != NULL)
1015 		(*closefunc)(fout);
1016 	if (din)
1017 		(void) fclose(din);
1018 	if (bytes > 0)
1019 		ptransfer("received", bytes, &start, &stop, local, remote);
1020 	(void) signal(SIGINT,oldintr);
1021 }
1022 
1023 /*
1024  * Need to start a listen on the data channel
1025  * before we send the command, otherwise the
1026  * server's connect may fail.
1027  */
1028 int sendport = -1;
1029 
1030 initconn()
1031 {
1032 	register char *p, *a;
1033 	int result, len, tmpno = 0;
1034 	int on = 1;
1035 
1036 noport:
1037 	data_addr = myctladdr;
1038 	if (sendport)
1039 		data_addr.sin_port = 0;	/* let system pick one */
1040 	if (data != -1)
1041 		(void) close (data);
1042 	data = socket(AF_INET, SOCK_STREAM, 0);
1043 	if (data < 0) {
1044 		perror("ftp: socket");
1045 		if (tmpno)
1046 			sendport = 1;
1047 		return (1);
1048 	}
1049 	if (!sendport)
1050 		if (setsockopt(data, SOL_SOCKET, SO_REUSEADDR, (char *)&on, sizeof (on)) < 0) {
1051 			perror("ftp: setsockopt (reuse address)");
1052 			goto bad;
1053 		}
1054 	if (bind(data, (struct sockaddr *)&data_addr, sizeof (data_addr)) < 0) {
1055 		perror("ftp: bind");
1056 		goto bad;
1057 	}
1058 	if (options & SO_DEBUG &&
1059 	    setsockopt(data, SOL_SOCKET, SO_DEBUG, (char *)&on, sizeof (on)) < 0)
1060 		perror("ftp: setsockopt (ignored)");
1061 	len = sizeof (data_addr);
1062 	if (getsockname(data, (char *)&data_addr, &len) < 0) {
1063 		perror("ftp: getsockname");
1064 		goto bad;
1065 	}
1066 	if (listen(data, 1) < 0)
1067 		perror("ftp: listen");
1068 	if (sendport) {
1069 		a = (char *)&data_addr.sin_addr;
1070 		p = (char *)&data_addr.sin_port;
1071 #define	UC(b)	(((int)b)&0xff)
1072 		result =
1073 		    command("PORT %d,%d,%d,%d,%d,%d",
1074 		      UC(a[0]), UC(a[1]), UC(a[2]), UC(a[3]),
1075 		      UC(p[0]), UC(p[1]));
1076 		if (result == ERROR && sendport == -1) {
1077 			sendport = 0;
1078 			tmpno = 1;
1079 			goto noport;
1080 		}
1081 		return (result != COMPLETE);
1082 	}
1083 	if (tmpno)
1084 		sendport = 1;
1085 	return (0);
1086 bad:
1087 	(void) close(data), data = -1;
1088 	if (tmpno)
1089 		sendport = 1;
1090 	return (1);
1091 }
1092 
1093 FILE *
1094 dataconn(mode)
1095 	char *mode;
1096 {
1097 	struct sockaddr_in from;
1098 	int s, fromlen = sizeof (from);
1099 
1100 	s = accept(data, (struct sockaddr *) &from, &fromlen);
1101 	if (s < 0) {
1102 		perror("ftp: accept");
1103 		(void) close(data), data = -1;
1104 		return (NULL);
1105 	}
1106 	(void) close(data);
1107 	data = s;
1108 	return (fdopen(data, mode));
1109 }
1110 
1111 ptransfer(direction, bytes, t0, t1, local, remote)
1112 	char *direction, *local, *remote;
1113 	long bytes;
1114 	struct timeval *t0, *t1;
1115 {
1116 	struct timeval td;
1117 	float s, bs;
1118 
1119 	if (verbose) {
1120 		tvsub(&td, t1, t0);
1121 		s = td.tv_sec + (td.tv_usec / 1000000.);
1122 #define	nz(x)	((x) == 0 ? 1 : (x))
1123 		bs = bytes / nz(s);
1124 		printf("%ld bytes %s in %.2g seconds (%.2g Kbytes/s)\n",
1125 		    bytes, direction, s, bs / 1024.);
1126 	} else {
1127 		if (local && *local != '-')
1128 			printf("local: %s ", local);
1129 		if (remote)
1130 			printf("remote: %s\n", remote);
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