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