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