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