xref: /freebsd/libexec/ftpd/ftpd.c (revision 48991a368427cadb9cdac39581d1676c29619c52)
1 /*
2  * Copyright (c) 1985, 1988, 1990, 1992, 1993, 1994
3  *	The Regents of the University of California.  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  *	$Id: ftpd.c,v 1.12 1995/08/28 21:30:49 mpp Exp $
34  */
35 
36 #ifndef lint
37 static char copyright[] =
38 "@(#) Copyright (c) 1985, 1988, 1990, 1992, 1993, 1994\n\
39 	The Regents of the University of California.  All rights reserved.\n";
40 #endif /* not lint */
41 
42 #ifndef lint
43 static char sccsid[] = "@(#)ftpd.c	8.4 (Berkeley) 4/16/94";
44 #endif /* not lint */
45 
46 /*
47  * FTP server.
48  */
49 #include <sys/param.h>
50 #include <sys/stat.h>
51 #include <sys/ioctl.h>
52 #include <sys/socket.h>
53 #include <sys/wait.h>
54 #include <sys/mman.h>
55 
56 #include <netinet/in.h>
57 #include <netinet/in_systm.h>
58 #include <netinet/ip.h>
59 #include <netinet/tcp.h>
60 
61 #define	FTP_NAMES
62 #include <arpa/ftp.h>
63 #include <arpa/inet.h>
64 #include <arpa/telnet.h>
65 
66 #include <ctype.h>
67 #include <dirent.h>
68 #include <err.h>
69 #include <errno.h>
70 #include <fcntl.h>
71 #include <glob.h>
72 #include <limits.h>
73 #include <netdb.h>
74 #include <pwd.h>
75 #include <setjmp.h>
76 #include <signal.h>
77 #include <stdio.h>
78 #include <stdlib.h>
79 #include <string.h>
80 #include <syslog.h>
81 #include <time.h>
82 #include <unistd.h>
83 
84 #ifdef	SKEY
85 #include <skey.h>
86 #endif
87 
88 #include "pathnames.h"
89 #include "extern.h"
90 
91 #if __STDC__
92 #include <stdarg.h>
93 #else
94 #include <varargs.h>
95 #endif
96 
97 static char version[] = "Version 6.00";
98 
99 extern	off_t restart_point;
100 extern	char cbuf[];
101 
102 struct	sockaddr_in ctrl_addr;
103 struct	sockaddr_in data_source;
104 struct	sockaddr_in data_dest;
105 struct	sockaddr_in his_addr;
106 struct	sockaddr_in pasv_addr;
107 
108 int	data;
109 jmp_buf	errcatch, urgcatch;
110 int	logged_in;
111 struct	passwd *pw;
112 int	debug;
113 int	timeout = 900;    /* timeout after 15 minutes of inactivity */
114 int	maxtimeout = 7200;/* don't allow idle time to be set beyond 2 hours */
115 int	logging;
116 int	restricted_data_ports = 1;
117 int	guest;
118 #ifdef STATS
119 int	stats;
120 int	statfd = -1;
121 #endif
122 int	type;
123 int	form;
124 int	stru;			/* avoid C keyword */
125 int	mode;
126 int	usedefault = 1;		/* for data transfers */
127 int	pdata = -1;		/* for passive mode */
128 sig_atomic_t transflag;
129 off_t	file_size;
130 off_t	byte_count;
131 #if !defined(CMASK) || CMASK == 0
132 #undef CMASK
133 #define CMASK 027
134 #endif
135 int	defumask = CMASK;		/* default umask value */
136 char	tmpline[7];
137 char	hostname[MAXHOSTNAMELEN];
138 char	remotehost[MAXHOSTNAMELEN];
139 #ifdef STATS
140 char	*ident = NULL;
141 #endif
142 
143 /*
144  * Timeout intervals for retrying connections
145  * to hosts that don't accept PORT cmds.  This
146  * is a kludge, but given the problems with TCP...
147  */
148 #define	SWAITMAX	90	/* wait at most 90 seconds */
149 #define	SWAITINT	5	/* interval between retries */
150 
151 int	swaitmax = SWAITMAX;
152 int	swaitint = SWAITINT;
153 
154 #ifdef SETPROCTITLE
155 char	**Argv = NULL;		/* pointer to argument vector */
156 char	*LastArgv = NULL;	/* end of argv */
157 char	proctitle[LINE_MAX];	/* initial part of title */
158 #endif /* SETPROCTITLE */
159 
160 #ifdef SKEY
161 int	pwok = 0;
162 char	addr_string[20];	/* XXX */
163 #endif
164 
165 #define LOGCMD(cmd, file) \
166 	if (logging > 1) \
167 	    syslog(LOG_INFO,"%s %s%s", cmd, \
168 		*(file) == '/' ? "" : curdir(), file);
169 #define LOGCMD2(cmd, file1, file2) \
170 	 if (logging > 1) \
171 	    syslog(LOG_INFO,"%s %s%s %s%s", cmd, \
172 		*(file1) == '/' ? "" : curdir(), file1, \
173 		*(file2) == '/' ? "" : curdir(), file2);
174 #define LOGBYTES(cmd, file, cnt) \
175 	if (logging > 1) { \
176 		if (cnt == (off_t)-1) \
177 		    syslog(LOG_INFO,"%s %s%s", cmd, \
178 			*(file) == '/' ? "" : curdir(), file); \
179 		else \
180 		    syslog(LOG_INFO, "%s %s%s = %qd bytes", \
181 			cmd, (*(file) == '/') ? "" : curdir(), file, cnt); \
182 	}
183 
184 static void	 ack __P((char *));
185 static void	 myoob __P((int));
186 static int	 checkuser __P((char *));
187 static FILE	*dataconn __P((char *, off_t, char *));
188 static void	 dolog __P((struct sockaddr_in *));
189 static char	*curdir __P((void));
190 static void	 end_login __P((void));
191 static FILE	*getdatasock __P((char *));
192 static char	*gunique __P((char *));
193 static void	 lostconn __P((int));
194 static int	 receive_data __P((FILE *, FILE *));
195 static void	 send_data __P((FILE *, FILE *, off_t, off_t, int));
196 static struct passwd *
197 		 sgetpwnam __P((char *));
198 static char	*sgetsave __P((char *));
199 
200 static char *
201 curdir()
202 {
203 	static char path[MAXPATHLEN+1+1];	/* path + '/' + '\0' */
204 
205 	if (getcwd(path, sizeof(path)-2) == NULL)
206 		return ("");
207 	if (path[1] != '\0')		/* special case for root dir. */
208 		strcat(path, "/");
209 	/* For guest account, skip / since it's chrooted */
210 	return (guest ? path+1 : path);
211 }
212 
213 int
214 main(argc, argv, envp)
215 	int argc;
216 	char *argv[];
217 	char **envp;
218 {
219 	int addrlen, ch, on = 1, tos;
220 	char *cp, line[LINE_MAX];
221 	FILE *fd;
222 
223 	tzset();		/* in case no timezone database in ~ftp */
224 
225 	/*
226 	 * LOG_NDELAY sets up the logging connection immediately,
227 	 * necessary for anonymous ftp's that chroot and can't do it later.
228 	 */
229 	openlog("ftpd", LOG_PID | LOG_NDELAY, LOG_FTP);
230 	addrlen = sizeof(his_addr);
231 	if (getpeername(0, (struct sockaddr *)&his_addr, &addrlen) < 0) {
232 		syslog(LOG_ERR, "getpeername (%s): %m",argv[0]);
233 		exit(1);
234 	}
235 #ifdef SKEY
236 	strcpy(addr_string, inet_ntoa(his_addr.sin_addr));
237 #endif
238 	addrlen = sizeof(ctrl_addr);
239 	if (getsockname(0, (struct sockaddr *)&ctrl_addr, &addrlen) < 0) {
240 		syslog(LOG_ERR, "getsockname (%s): %m",argv[0]);
241 		exit(1);
242 	}
243 #ifdef IP_TOS
244 	tos = IPTOS_LOWDELAY;
245 	if (setsockopt(0, IPPROTO_IP, IP_TOS, (char *)&tos, sizeof(int)) < 0)
246 		syslog(LOG_WARNING, "setsockopt (IP_TOS): %m");
247 #endif
248 	data_source.sin_port = htons(ntohs(ctrl_addr.sin_port) - 1);
249 	debug = 0;
250 #ifdef SETPROCTITLE
251 	/*
252 	 *  Save start and extent of argv for setproctitle.
253 	 */
254 	Argv = argv;
255 	while (*envp)
256 		envp++;
257 	LastArgv = envp[-1] + strlen(envp[-1]);
258 #endif /* SETPROCTITLE */
259 
260 
261 #ifdef STATS
262 	while ((ch = getopt(argc, argv, "dlSt:T:u:v")) != EOF) {
263 #else
264 	while ((ch = getopt(argc, argv, "dlUt:T:u:v")) != EOF) {
265 #endif
266 		switch (ch) {
267 		case 'd':
268 			debug = 1;
269 			break;
270 
271 		case 'l':
272 			logging++;	/* > 1 == extra logging */
273 			break;
274 
275 		case 'U':
276 			restricted_data_ports = 0;
277 			break;
278 
279 		case 't':
280 			timeout = atoi(optarg);
281 			if (maxtimeout < timeout)
282 				maxtimeout = timeout;
283 			break;
284 #ifdef STATS
285 		case 'S':
286 			stats =  1;
287 			break;
288 #endif
289 		case 'T':
290 			maxtimeout = atoi(optarg);
291 			if (timeout > maxtimeout)
292 				timeout = maxtimeout;
293 			break;
294 
295 		case 'u':
296 		    {
297 			long val = 0;
298 
299 			val = strtol(optarg, &optarg, 8);
300 			if (*optarg != '\0' || val < 0)
301 				warnx("bad value for -u");
302 			else
303 				defumask = val;
304 			break;
305 		    }
306 
307 		case 'v':
308 			debug = 1;
309 			break;
310 
311 		default:
312 			warnx("unknown flag -%c ignored", optopt);
313 			break;
314 		}
315 	}
316 	(void) freopen(_PATH_DEVNULL, "w", stderr);
317 	(void) signal(SIGPIPE, lostconn);
318 	(void) signal(SIGCHLD, SIG_IGN);
319 	if ((int)signal(SIGURG, myoob) < 0)
320 		syslog(LOG_ERR, "signal: %m");
321 
322 	/* Try to handle urgent data inline */
323 #ifdef SO_OOBINLINE
324 	if (setsockopt(0, SOL_SOCKET, SO_OOBINLINE, (char *)&on, sizeof(on)) < 0)
325 		syslog(LOG_ERR, "setsockopt: %m");
326 #endif
327 
328 #ifdef	F_SETOWN
329 	if (fcntl(fileno(stdin), F_SETOWN, getpid()) == -1)
330 		syslog(LOG_ERR, "fcntl F_SETOWN: %m");
331 #endif
332 	dolog(&his_addr);
333 	/*
334 	 * Set up default state
335 	 */
336 	data = -1;
337 	type = TYPE_A;
338 	form = FORM_N;
339 	stru = STRU_F;
340 	mode = MODE_S;
341 	tmpline[0] = '\0';
342 
343 	/* If logins are disabled, print out the message. */
344 	if ((fd = fopen(_PATH_NOLOGIN,"r")) != NULL) {
345 		while (fgets(line, sizeof(line), fd) != NULL) {
346 			if ((cp = strchr(line, '\n')) != NULL)
347 				*cp = '\0';
348 			lreply(530, "%s", line);
349 		}
350 		(void) fflush(stdout);
351 		(void) fclose(fd);
352 		reply(530, "System not available.");
353 		exit(0);
354 	}
355 	if ((fd = fopen(_PATH_FTPWELCOME, "r")) != NULL) {
356 		while (fgets(line, sizeof(line), fd) != NULL) {
357 			if ((cp = strchr(line, '\n')) != NULL)
358 				*cp = '\0';
359 			lreply(220, "%s", line);
360 		}
361 		(void) fflush(stdout);
362 		(void) fclose(fd);
363 		/* reply(220,) must follow */
364 	}
365 	(void) gethostname(hostname, sizeof(hostname));
366 	reply(220, "%s FTP server (%s) ready.", hostname, version);
367 	(void) setjmp(errcatch);
368 	for (;;)
369 		(void) yyparse();
370 	/* NOTREACHED */
371 }
372 
373 static void
374 lostconn(signo)
375 	int signo;
376 {
377 
378 	if (debug)
379 		syslog(LOG_DEBUG, "lost connection");
380 	dologout(-1);
381 }
382 
383 static char ttyline[20];
384 
385 /*
386  * Helper function for sgetpwnam().
387  */
388 static char *
389 sgetsave(s)
390 	char *s;
391 {
392 	char *new = malloc((unsigned) strlen(s) + 1);
393 
394 	if (new == NULL) {
395 		perror_reply(421, "Local resource failure: malloc");
396 		dologout(1);
397 		/* NOTREACHED */
398 	}
399 	(void) strcpy(new, s);
400 	return (new);
401 }
402 
403 /*
404  * Save the result of a getpwnam.  Used for USER command, since
405  * the data returned must not be clobbered by any other command
406  * (e.g., globbing).
407  */
408 static struct passwd *
409 sgetpwnam(name)
410 	char *name;
411 {
412 	static struct passwd save;
413 	struct passwd *p;
414 
415 	if ((p = getpwnam(name)) == NULL)
416 		return (p);
417 	if (save.pw_name) {
418 		free(save.pw_name);
419 		free(save.pw_passwd);
420 		free(save.pw_gecos);
421 		free(save.pw_dir);
422 		free(save.pw_shell);
423 	}
424 	save = *p;
425 	save.pw_name = sgetsave(p->pw_name);
426 	save.pw_passwd = sgetsave(p->pw_passwd);
427 	save.pw_gecos = sgetsave(p->pw_gecos);
428 	save.pw_dir = sgetsave(p->pw_dir);
429 	save.pw_shell = sgetsave(p->pw_shell);
430 	return (&save);
431 }
432 
433 static int login_attempts;	/* number of failed login attempts */
434 static int askpasswd;		/* had user command, ask for passwd */
435 static char curname[10];	/* current USER name */
436 
437 /*
438  * USER command.
439  * Sets global passwd pointer pw if named account exists and is acceptable;
440  * sets askpasswd if a PASS command is expected.  If logged in previously,
441  * need to reset state.  If name is "ftp" or "anonymous", the name is not in
442  * _PATH_FTPUSERS, and ftp account exists, set guest and pw, then just return.
443  * If account doesn't exist, ask for passwd anyway.  Otherwise, check user
444  * requesting login privileges.  Disallow anyone who does not have a standard
445  * shell as returned by getusershell().  Disallow anyone mentioned in the file
446  * _PATH_FTPUSERS to allow people such as root and uucp to be avoided.
447  */
448 void
449 user(name)
450 	char *name;
451 {
452 	char *cp, *shell;
453 
454 	if (logged_in) {
455 		if (guest) {
456 			reply(530, "Can't change user from guest login.");
457 			return;
458 		}
459 		end_login();
460 	}
461 
462 	guest = 0;
463 	if (strcmp(name, "ftp") == 0 || strcmp(name, "anonymous") == 0) {
464 		if (checkuser("ftp") || checkuser("anonymous"))
465 			reply(530, "User %s access denied.", name);
466 		else if ((pw = sgetpwnam("ftp")) != NULL) {
467 			guest = 1;
468 			askpasswd = 1;
469 			reply(331,
470 			"Guest login ok, send your email address as password.");
471 		} else
472 			reply(530, "User %s unknown.", name);
473 		if (!askpasswd && logging)
474 			syslog(LOG_NOTICE,
475 			    "ANONYMOUS FTP LOGIN REFUSED FROM %s", remotehost);
476 		return;
477 	}
478 	if (pw = sgetpwnam(name)) {
479 		if ((shell = pw->pw_shell) == NULL || *shell == 0)
480 			shell = _PATH_BSHELL;
481 		while ((cp = getusershell()) != NULL)
482 			if (strcmp(cp, shell) == 0)
483 				break;
484 		endusershell();
485 
486 		if (cp == NULL || checkuser(name)) {
487 			reply(530, "User %s access denied.", name);
488 			if (logging)
489 				syslog(LOG_NOTICE,
490 				    "FTP LOGIN REFUSED FROM %s, %s",
491 				    remotehost, name);
492 			pw = (struct passwd *) NULL;
493 			return;
494 		}
495 	}
496 	if (logging)
497 		strncpy(curname, name, sizeof(curname)-1);
498 #ifdef SKEY
499 	pwok = skeyaccess(name, NULL, remotehost, addr_string);
500 	reply(331, "%s", skey_challenge(name, pw, pwok));
501 #else
502 	reply(331, "Password required for %s.", name);
503 #endif
504 	askpasswd = 1;
505 	/*
506 	 * Delay before reading passwd after first failed
507 	 * attempt to slow down passwd-guessing programs.
508 	 */
509 	if (login_attempts)
510 		sleep((unsigned) login_attempts);
511 }
512 
513 /*
514  * Check if a user is in the file _PATH_FTPUSERS
515  */
516 static int
517 checkuser(name)
518 	char *name;
519 {
520 	FILE *fd;
521 	int found = 0;
522 	char *p, line[BUFSIZ];
523 
524 	if ((fd = fopen(_PATH_FTPUSERS, "r")) != NULL) {
525 		while (fgets(line, sizeof(line), fd) != NULL)
526 			if ((p = strchr(line, '\n')) != NULL) {
527 				*p = '\0';
528 				if (line[0] == '#')
529 					continue;
530 				if (strcmp(line, name) == 0) {
531 					found = 1;
532 					break;
533 				}
534 			}
535 		(void) fclose(fd);
536 	}
537 	return (found);
538 }
539 
540 /*
541  * Terminate login as previous user, if any, resetting state;
542  * used when USER command is given or login fails.
543  */
544 static void
545 end_login()
546 {
547 
548 	(void) seteuid((uid_t)0);
549 	if (logged_in)
550 		logwtmp(ttyline, "", "");
551 	pw = NULL;
552 	logged_in = 0;
553 	guest = 0;
554 }
555 
556 void
557 pass(passwd)
558 	char *passwd;
559 {
560 	char *salt, *xpasswd;
561 	FILE *fd;
562 	static char homedir[MAXPATHLEN];
563 
564 	if (logged_in || askpasswd == 0) {
565 		reply(503, "Login with USER first.");
566 		return;
567 	}
568 	askpasswd = 0;
569 	if (!guest) {		/* "ftp" is only account allowed no password */
570 		if (pw == NULL)
571 			salt = "xx";
572 		else
573 			salt = pw->pw_passwd;
574 #ifdef SKEY
575 		xpasswd = skey_crypt(passwd, salt, pw, pwok);
576 		pwok = 0;
577 #else
578 		xpasswd = crypt(passwd, salt);
579 #endif
580 		/* The strcmp does not catch null passwords! */
581 		if (pw == NULL || *pw->pw_passwd == '\0' ||
582 		    (pw->pw_expire && time(NULL) >= pw->pw_expire) ||
583 		    strcmp(xpasswd, pw->pw_passwd)) {
584 			reply(530, "Login incorrect.");
585 			if (logging)
586 				syslog(LOG_NOTICE,
587 				    "FTP LOGIN FAILED FROM %s, %s",
588 				    remotehost, curname);
589 			pw = NULL;
590 			if (login_attempts++ >= 5) {
591 				syslog(LOG_NOTICE,
592 				    "repeated login failures from %s",
593 				    remotehost);
594 				exit(0);
595 			}
596 			return;
597 		}
598 	}
599 	login_attempts = 0;		/* this time successful */
600 	if (setegid((gid_t)pw->pw_gid) < 0) {
601 		reply(550, "Can't set gid.");
602 		return;
603 	}
604 	(void) initgroups(pw->pw_name, pw->pw_gid);
605 
606 	/* open wtmp before chroot */
607 	(void)sprintf(ttyline, "ftp%d", getpid());
608 	logwtmp(ttyline, pw->pw_name, remotehost);
609 	logged_in = 1;
610 
611 #ifdef STATS
612 	if (guest && stats == 1 && statfd < 0)
613 		if ((statfd = open(_PATH_FTPDSTATFILE, O_WRONLY|O_APPEND)) < 0)
614 			stats = 0;
615 #endif
616 
617 	if (guest) {
618 		/*
619 		 * We MUST do a chdir() after the chroot. Otherwise
620 		 * the old current directory will be accessible as "."
621 		 * outside the new root!
622 		 */
623 		if (chroot(pw->pw_dir) < 0 || chdir("/") < 0) {
624 			reply(550, "Can't set guest privileges.");
625 			goto bad;
626 		}
627 	} else if (chdir(pw->pw_dir) < 0) {
628 		if (chdir("/") < 0) {
629 			reply(530, "User %s: can't change directory to %s.",
630 			    pw->pw_name, pw->pw_dir);
631 			goto bad;
632 		} else
633 			lreply(230, "No directory! Logging in with home=/");
634 	}
635 	if (seteuid((uid_t)pw->pw_uid) < 0) {
636 		reply(550, "Can't set uid.");
637 		goto bad;
638 	}
639 
640 	/*
641 	 * Set home directory so that use of ~ (tilde) works correctly.
642 	 */
643 	if (getcwd(homedir, MAXPATHLEN) != NULL)
644 		setenv("HOME", homedir, 1);
645 
646 	/*
647 	 * Display a login message, if it exists.
648 	 * N.B. reply(230,) must follow the message.
649 	 */
650 	if ((fd = fopen(_PATH_FTPLOGINMESG, "r")) != NULL) {
651 		char *cp, line[LINE_MAX];
652 
653 		while (fgets(line, sizeof(line), fd) != NULL) {
654 			if ((cp = strchr(line, '\n')) != NULL)
655 				*cp = '\0';
656 			lreply(230, "%s", line);
657 		}
658 		(void) fflush(stdout);
659 		(void) fclose(fd);
660 	}
661 	if (guest) {
662 #ifdef STATS
663 		char * copy();
664 
665 		if (ident != NULL)
666 			free(ident);
667 		ident = (char *) copy(passwd);
668 #endif
669 		reply(230, "Guest login ok, access restrictions apply.");
670 #ifdef SETPROCTITLE
671 		snprintf(proctitle, sizeof(proctitle),
672 		    "%s: anonymous/%.*s", remotehost,
673 		    sizeof(proctitle) - sizeof(remotehost) -
674 		    sizeof(": anonymous/"), passwd);
675 		setproctitle(proctitle);
676 #endif /* SETPROCTITLE */
677 		if (logging)
678 			syslog(LOG_INFO, "ANONYMOUS FTP LOGIN FROM %s, %s",
679 			    remotehost, passwd);
680 	} else {
681 		reply(230, "User %s logged in.", pw->pw_name);
682 #ifdef SETPROCTITLE
683 		snprintf(proctitle, sizeof(proctitle),
684 		    "%s: %s", remotehost, pw->pw_name);
685 		setproctitle(proctitle);
686 #endif /* SETPROCTITLE */
687 		if (logging)
688 			syslog(LOG_INFO, "FTP LOGIN FROM %s as %s",
689 			    remotehost, pw->pw_name);
690 	}
691 	(void) umask(defumask);
692 	return;
693 bad:
694 	/* Forget all about it... */
695 	end_login();
696 }
697 
698 void
699 retrieve(cmd, name)
700 	char *cmd, *name;
701 {
702 	FILE *fin, *dout;
703 	struct stat st;
704 	int (*closefunc) __P((FILE *));
705 #ifdef STATS
706 	long start;
707 #endif
708 
709 	if (cmd == 0) {
710 		fin = fopen(name, "r"), closefunc = fclose;
711 		st.st_size = 0;
712 	} else {
713 		char line[BUFSIZ];
714 
715 		(void) sprintf(line, cmd, name), name = line;
716 		fin = ftpd_popen(line, "r"), closefunc = ftpd_pclose;
717 		st.st_size = -1;
718 		st.st_blksize = BUFSIZ;
719 	}
720 	if (fin == NULL) {
721 		if (errno != 0) {
722 			perror_reply(550, name);
723 			if (cmd == 0) {
724 				LOGCMD("get", name);
725 			}
726 		}
727 		return;
728 	}
729 	byte_count = -1;
730 	if (cmd == 0 && (fstat(fileno(fin), &st) < 0 || !S_ISREG(st.st_mode))) {
731 		reply(550, "%s: not a plain file.", name);
732 		goto done;
733 	}
734 	if (restart_point) {
735 		if (type == TYPE_A) {
736 			off_t i, n;
737 			int c;
738 
739 			n = restart_point;
740 			i = 0;
741 			while (i++ < n) {
742 				if ((c=getc(fin)) == EOF) {
743 					perror_reply(550, name);
744 					goto done;
745 				}
746 				if (c == '\n')
747 					i++;
748 			}
749 		} else if (lseek(fileno(fin), restart_point, L_SET) < 0) {
750 			perror_reply(550, name);
751 			goto done;
752 		}
753 	}
754 	dout = dataconn(name, st.st_size, "w");
755 	if (dout == NULL)
756 		goto done;
757 #ifdef STATS
758 	time(&start);
759 #endif
760 	send_data(fin, dout, st.st_blksize, st.st_size,
761 		  restart_point == 0 && cmd == 0 && S_ISREG(st.st_mode));
762 #ifdef STATS
763 	if (cmd == 0 && guest && stats)
764 		logxfer( name, st.st_size, start);
765 #endif
766 	(void) fclose(dout);
767 	data = -1;
768 	pdata = -1;
769 done:
770 	if (cmd == 0)
771 		LOGBYTES("get", name, byte_count);
772 	(*closefunc)(fin);
773 }
774 
775 void
776 store(name, mode, unique)
777 	char *name, *mode;
778 	int unique;
779 {
780 	FILE *fout, *din;
781 	struct stat st;
782 	int (*closefunc) __P((FILE *));
783 
784 	if (unique && stat(name, &st) == 0 &&
785 	    (name = gunique(name)) == NULL) {
786 		LOGCMD(*mode == 'w' ? "put" : "append", name);
787 		return;
788 	}
789 
790 	if (restart_point)
791 		mode = "r+";
792 	fout = fopen(name, mode);
793 	closefunc = fclose;
794 	if (fout == NULL) {
795 		perror_reply(553, name);
796 		LOGCMD(*mode == 'w' ? "put" : "append", name);
797 		return;
798 	}
799 	byte_count = -1;
800 	if (restart_point) {
801 		if (type == TYPE_A) {
802 			off_t i, n;
803 			int c;
804 
805 			n = restart_point;
806 			i = 0;
807 			while (i++ < n) {
808 				if ((c=getc(fout)) == EOF) {
809 					perror_reply(550, name);
810 					goto done;
811 				}
812 				if (c == '\n')
813 					i++;
814 			}
815 			/*
816 			 * We must do this seek to "current" position
817 			 * because we are changing from reading to
818 			 * writing.
819 			 */
820 			if (fseek(fout, 0L, L_INCR) < 0) {
821 				perror_reply(550, name);
822 				goto done;
823 			}
824 		} else if (lseek(fileno(fout), restart_point, L_SET) < 0) {
825 			perror_reply(550, name);
826 			goto done;
827 		}
828 	}
829 	din = dataconn(name, (off_t)-1, "r");
830 	if (din == NULL)
831 		goto done;
832 	if (receive_data(din, fout) == 0) {
833 		if (unique)
834 			reply(226, "Transfer complete (unique file name:%s).",
835 			    name);
836 		else
837 			reply(226, "Transfer complete.");
838 	}
839 	(void) fclose(din);
840 	data = -1;
841 	pdata = -1;
842 done:
843 	LOGBYTES(*mode == 'w' ? "put" : "append", name, byte_count);
844 	(*closefunc)(fout);
845 }
846 
847 static FILE *
848 getdatasock(mode)
849 	char *mode;
850 {
851 	int on = 1, s, t, tries;
852 
853 	if (data >= 0)
854 		return (fdopen(data, mode));
855 	(void) seteuid((uid_t)0);
856 	s = socket(AF_INET, SOCK_STREAM, 0);
857 	if (s < 0)
858 		goto bad;
859 	if (setsockopt(s, SOL_SOCKET, SO_REUSEADDR,
860 	    (char *) &on, sizeof(on)) < 0)
861 		goto bad;
862 	/* anchor socket to avoid multi-homing problems */
863 	data_source.sin_family = AF_INET;
864 	data_source.sin_addr = ctrl_addr.sin_addr;
865 	for (tries = 1; ; tries++) {
866 		if (bind(s, (struct sockaddr *)&data_source,
867 		    sizeof(data_source)) >= 0)
868 			break;
869 		if (errno != EADDRINUSE || tries > 10)
870 			goto bad;
871 		sleep(tries);
872 	}
873 	(void) seteuid((uid_t)pw->pw_uid);
874 #ifdef IP_TOS
875 	on = IPTOS_THROUGHPUT;
876 	if (setsockopt(s, IPPROTO_IP, IP_TOS, (char *)&on, sizeof(int)) < 0)
877 		syslog(LOG_WARNING, "setsockopt (IP_TOS): %m");
878 #endif
879 #ifdef TCP_NOPUSH
880 	/*
881 	 * Turn off push flag to keep sender TCP from sending short packets
882 	 * at the boundaries of each write().  Should probably do a SO_SNDBUF
883 	 * to set the send buffer size as well, but that may not be desirable
884 	 * in heavy-load situations.
885 	 */
886 	on = 1;
887 	if (setsockopt(s, IPPROTO_TCP, TCP_NOPUSH, (char *)&on, sizeof on) < 0)
888 		syslog(LOG_WARNING, "setsockopt (TCP_NOPUSH): %m");
889 #endif
890 #ifdef SO_SNDBUF
891 	on = 65536;
892 	if (setsockopt(s, SOL_SOCKET, SO_SNDBUF, (char *)&on, sizeof on) < 0)
893 		syslog(LOG_WARNING, "setsockopt (SO_SNDBUF): %m");
894 #endif
895 
896 	return (fdopen(s, mode));
897 bad:
898 	/* Return the real value of errno (close may change it) */
899 	t = errno;
900 	(void) seteuid((uid_t)pw->pw_uid);
901 	(void) close(s);
902 	errno = t;
903 	return (NULL);
904 }
905 
906 static FILE *
907 dataconn(name, size, mode)
908 	char *name;
909 	off_t size;
910 	char *mode;
911 {
912 	char sizebuf[32];
913 	FILE *file;
914 	int retry = 0, tos;
915 
916 	file_size = size;
917 	byte_count = 0;
918 	if (size != (off_t) -1)
919 		(void) sprintf(sizebuf, " (%qd bytes)", size);
920 	else
921 		(void) strcpy(sizebuf, "");
922 	if (pdata >= 0) {
923 		struct sockaddr_in from;
924 		int s, fromlen = sizeof(from);
925 		struct timeval timeout;
926 		fd_set set;
927 
928 		FD_ZERO(&set);
929 		FD_SET(pdata, &set);
930 
931 		timeout.tv_usec = 0;
932 		timeout.tv_sec = 120;
933 
934 		if (select(pdata+1, &set, (fd_set *) 0, (fd_set *) 0, &timeout) == 0 ||
935 		    (s = accept(pdata, (struct sockaddr *) &from, &fromlen)) < 0) {
936 			reply(425, "Can't open data connection.");
937 			(void) close(pdata);
938 			pdata = -1;
939 			return (NULL);
940 		}
941 		(void) close(pdata);
942 		pdata = s;
943 #ifdef IP_TOS
944 		tos = IPTOS_LOWDELAY;
945 		(void) setsockopt(s, IPPROTO_IP, IP_TOS, (char *)&tos,
946 		    sizeof(int));
947 #endif
948 		reply(150, "Opening %s mode data connection for '%s'%s.",
949 		     type == TYPE_A ? "ASCII" : "BINARY", name, sizebuf);
950 		return (fdopen(pdata, mode));
951 	}
952 	if (data >= 0) {
953 		reply(125, "Using existing data connection for '%s'%s.",
954 		    name, sizebuf);
955 		usedefault = 1;
956 		return (fdopen(data, mode));
957 	}
958 	if (usedefault)
959 		data_dest = his_addr;
960 	usedefault = 1;
961 	file = getdatasock(mode);
962 	if (file == NULL) {
963 		reply(425, "Can't create data socket (%s,%d): %s.",
964 		    inet_ntoa(data_source.sin_addr),
965 		    ntohs(data_source.sin_port), strerror(errno));
966 		return (NULL);
967 	}
968 	data = fileno(file);
969 	while (connect(data, (struct sockaddr *)&data_dest,
970 	    sizeof(data_dest)) < 0) {
971 		if (errno == EADDRINUSE && retry < swaitmax) {
972 			sleep((unsigned) swaitint);
973 			retry += swaitint;
974 			continue;
975 		}
976 		perror_reply(425, "Can't build data connection");
977 		(void) fclose(file);
978 		data = -1;
979 		return (NULL);
980 	}
981 	reply(150, "Opening %s mode data connection for '%s'%s.",
982 	     type == TYPE_A ? "ASCII" : "BINARY", name, sizebuf);
983 	return (file);
984 }
985 
986 /*
987  * Tranfer the contents of "instr" to "outstr" peer using the appropriate
988  * encapsulation of the data subject to Mode, Structure, and Type.
989  *
990  * NB: Form isn't handled.
991  */
992 static void
993 send_data(instr, outstr, blksize, filesize, isreg)
994 	FILE *instr, *outstr;
995 	off_t blksize;
996 	off_t filesize;
997 	int isreg;
998 {
999 	int c, cnt, filefd, netfd;
1000 	char *buf, *bp;
1001 	size_t len;
1002 
1003 	transflag++;
1004 	if (setjmp(urgcatch)) {
1005 		transflag = 0;
1006 		return;
1007 	}
1008 	switch (type) {
1009 
1010 	case TYPE_A:
1011 		while ((c = getc(instr)) != EOF) {
1012 			byte_count++;
1013 			if (c == '\n') {
1014 				if (ferror(outstr))
1015 					goto data_err;
1016 				(void) putc('\r', outstr);
1017 			}
1018 			(void) putc(c, outstr);
1019 		}
1020 		fflush(outstr);
1021 		transflag = 0;
1022 		if (ferror(instr))
1023 			goto file_err;
1024 		if (ferror(outstr))
1025 			goto data_err;
1026 		reply(226, "Transfer complete.");
1027 		return;
1028 
1029 	case TYPE_I:
1030 	case TYPE_L:
1031 		/*
1032 		 * isreg is only set if we are not doing restart and we
1033 		 * are sending a regular file
1034 		 */
1035 		netfd = fileno(outstr);
1036 		filefd = fileno(instr);
1037 
1038 		if (isreg && filesize < (off_t)16 * 1024 * 1024) {
1039 			buf = mmap(0, filesize, PROT_READ, MAP_SHARED, filefd,
1040 				   (off_t)0);
1041 			if (!buf) {
1042 				syslog(LOG_WARNING, "mmap(%lu): %m",
1043 				       (unsigned long)filesize);
1044 				goto oldway;
1045 			}
1046 			bp = buf;
1047 			len = filesize;
1048 			do {
1049 				cnt = write(netfd, bp, len);
1050 				len -= cnt;
1051 				bp += cnt;
1052 				if (cnt > 0) byte_count += cnt;
1053 			} while(cnt > 0 && len > 0);
1054 
1055 			transflag = 0;
1056 			munmap(buf, (size_t)filesize);
1057 			if (cnt < 0)
1058 				goto data_err;
1059 			reply(226, "Transfer complete.");
1060 			return;
1061 		}
1062 
1063 oldway:
1064 		if ((buf = malloc((u_int)blksize)) == NULL) {
1065 			transflag = 0;
1066 			perror_reply(451, "Local resource failure: malloc");
1067 			return;
1068 		}
1069 
1070 		while ((cnt = read(filefd, buf, (u_int)blksize)) > 0 &&
1071 		    write(netfd, buf, cnt) == cnt)
1072 			byte_count += cnt;
1073 		transflag = 0;
1074 		(void)free(buf);
1075 		if (cnt != 0) {
1076 			if (cnt < 0)
1077 				goto file_err;
1078 			goto data_err;
1079 		}
1080 		reply(226, "Transfer complete.");
1081 		return;
1082 	default:
1083 		transflag = 0;
1084 		reply(550, "Unimplemented TYPE %d in send_data", type);
1085 		return;
1086 	}
1087 
1088 data_err:
1089 	transflag = 0;
1090 	perror_reply(426, "Data connection");
1091 	return;
1092 
1093 file_err:
1094 	transflag = 0;
1095 	perror_reply(551, "Error on input file");
1096 }
1097 
1098 /*
1099  * Transfer data from peer to "outstr" using the appropriate encapulation of
1100  * the data subject to Mode, Structure, and Type.
1101  *
1102  * N.B.: Form isn't handled.
1103  */
1104 static int
1105 receive_data(instr, outstr)
1106 	FILE *instr, *outstr;
1107 {
1108 	int c;
1109 	int cnt, bare_lfs = 0;
1110 	char buf[BUFSIZ];
1111 
1112 	transflag++;
1113 	if (setjmp(urgcatch)) {
1114 		transflag = 0;
1115 		return (-1);
1116 	}
1117 	switch (type) {
1118 
1119 	case TYPE_I:
1120 	case TYPE_L:
1121 		while ((cnt = read(fileno(instr), buf, sizeof(buf))) > 0) {
1122 			if (write(fileno(outstr), buf, cnt) != cnt)
1123 				goto file_err;
1124 			byte_count += cnt;
1125 		}
1126 		if (cnt < 0)
1127 			goto data_err;
1128 		transflag = 0;
1129 		return (0);
1130 
1131 	case TYPE_E:
1132 		reply(553, "TYPE E not implemented.");
1133 		transflag = 0;
1134 		return (-1);
1135 
1136 	case TYPE_A:
1137 		while ((c = getc(instr)) != EOF) {
1138 			byte_count++;
1139 			if (c == '\n')
1140 				bare_lfs++;
1141 			while (c == '\r') {
1142 				if (ferror(outstr))
1143 					goto data_err;
1144 				if ((c = getc(instr)) != '\n') {
1145 					(void) putc ('\r', outstr);
1146 					if (c == '\0' || c == EOF)
1147 						goto contin2;
1148 				}
1149 			}
1150 			(void) putc(c, outstr);
1151 	contin2:	;
1152 		}
1153 		fflush(outstr);
1154 		if (ferror(instr))
1155 			goto data_err;
1156 		if (ferror(outstr))
1157 			goto file_err;
1158 		transflag = 0;
1159 		if (bare_lfs) {
1160 			lreply(226,
1161 		"WARNING! %d bare linefeeds received in ASCII mode",
1162 			    bare_lfs);
1163 		(void)printf("   File may not have transferred correctly.\r\n");
1164 		}
1165 		return (0);
1166 	default:
1167 		reply(550, "Unimplemented TYPE %d in receive_data", type);
1168 		transflag = 0;
1169 		return (-1);
1170 	}
1171 
1172 data_err:
1173 	transflag = 0;
1174 	perror_reply(426, "Data Connection");
1175 	return (-1);
1176 
1177 file_err:
1178 	transflag = 0;
1179 	perror_reply(452, "Error writing file");
1180 	return (-1);
1181 }
1182 
1183 void
1184 statfilecmd(filename)
1185 	char *filename;
1186 {
1187 	FILE *fin;
1188 	int c;
1189 	char line[LINE_MAX];
1190 
1191 	(void)snprintf(line, sizeof(line), "/bin/ls -lgA %s", filename);
1192 	fin = ftpd_popen(line, "r");
1193 	lreply(211, "status of %s:", filename);
1194 	while ((c = getc(fin)) != EOF) {
1195 		if (c == '\n') {
1196 			if (ferror(stdout)){
1197 				perror_reply(421, "control connection");
1198 				(void) ftpd_pclose(fin);
1199 				dologout(1);
1200 				/* NOTREACHED */
1201 			}
1202 			if (ferror(fin)) {
1203 				perror_reply(551, filename);
1204 				(void) ftpd_pclose(fin);
1205 				return;
1206 			}
1207 			(void) putc('\r', stdout);
1208 		}
1209 		(void) putc(c, stdout);
1210 	}
1211 	(void) ftpd_pclose(fin);
1212 	reply(211, "End of Status");
1213 }
1214 
1215 void
1216 statcmd()
1217 {
1218 	struct sockaddr_in *sin;
1219 	u_char *a, *p;
1220 
1221 	lreply(211, "%s FTP server status:", hostname, version);
1222 	printf("     %s\r\n", version);
1223 	printf("     Connected to %s", remotehost);
1224 	if (!isdigit(remotehost[0]))
1225 		printf(" (%s)", inet_ntoa(his_addr.sin_addr));
1226 	printf("\r\n");
1227 	if (logged_in) {
1228 		if (guest)
1229 			printf("     Logged in anonymously\r\n");
1230 		else
1231 			printf("     Logged in as %s\r\n", pw->pw_name);
1232 	} else if (askpasswd)
1233 		printf("     Waiting for password\r\n");
1234 	else
1235 		printf("     Waiting for user name\r\n");
1236 	printf("     TYPE: %s", typenames[type]);
1237 	if (type == TYPE_A || type == TYPE_E)
1238 		printf(", FORM: %s", formnames[form]);
1239 	if (type == TYPE_L)
1240 #if NBBY == 8
1241 		printf(" %d", NBBY);
1242 #else
1243 		printf(" %d", bytesize);	/* need definition! */
1244 #endif
1245 	printf("; STRUcture: %s; transfer MODE: %s\r\n",
1246 	    strunames[stru], modenames[mode]);
1247 	if (data != -1)
1248 		printf("     Data connection open\r\n");
1249 	else if (pdata != -1) {
1250 		printf("     in Passive mode");
1251 		sin = &pasv_addr;
1252 		goto printaddr;
1253 	} else if (usedefault == 0) {
1254 		printf("     PORT");
1255 		sin = &data_dest;
1256 printaddr:
1257 		a = (u_char *) &sin->sin_addr;
1258 		p = (u_char *) &sin->sin_port;
1259 #define UC(b) (((int) b) & 0xff)
1260 		printf(" (%d,%d,%d,%d,%d,%d)\r\n", UC(a[0]),
1261 			UC(a[1]), UC(a[2]), UC(a[3]), UC(p[0]), UC(p[1]));
1262 #undef UC
1263 	} else
1264 		printf("     No data connection\r\n");
1265 	reply(211, "End of status");
1266 }
1267 
1268 void
1269 fatal(s)
1270 	char *s;
1271 {
1272 
1273 	reply(451, "Error in server: %s\n", s);
1274 	reply(221, "Closing connection due to server error.");
1275 	dologout(0);
1276 	/* NOTREACHED */
1277 }
1278 
1279 void
1280 #if __STDC__
1281 reply(int n, const char *fmt, ...)
1282 #else
1283 reply(n, fmt, va_alist)
1284 	int n;
1285 	char *fmt;
1286         va_dcl
1287 #endif
1288 {
1289 	va_list ap;
1290 #if __STDC__
1291 	va_start(ap, fmt);
1292 #else
1293 	va_start(ap);
1294 #endif
1295 	(void)printf("%d ", n);
1296 	(void)vprintf(fmt, ap);
1297 	(void)printf("\r\n");
1298 	(void)fflush(stdout);
1299 	if (debug) {
1300 		syslog(LOG_DEBUG, "<--- %d ", n);
1301 		vsyslog(LOG_DEBUG, fmt, ap);
1302 	}
1303 }
1304 
1305 void
1306 #if __STDC__
1307 lreply(int n, const char *fmt, ...)
1308 #else
1309 lreply(n, fmt, va_alist)
1310 	int n;
1311 	char *fmt;
1312         va_dcl
1313 #endif
1314 {
1315 	va_list ap;
1316 #if __STDC__
1317 	va_start(ap, fmt);
1318 #else
1319 	va_start(ap);
1320 #endif
1321 	(void)printf("%d- ", n);
1322 	(void)vprintf(fmt, ap);
1323 	(void)printf("\r\n");
1324 	(void)fflush(stdout);
1325 	if (debug) {
1326 		syslog(LOG_DEBUG, "<--- %d- ", n);
1327 		vsyslog(LOG_DEBUG, fmt, ap);
1328 	}
1329 }
1330 
1331 static void
1332 ack(s)
1333 	char *s;
1334 {
1335 
1336 	reply(250, "%s command successful.", s);
1337 }
1338 
1339 void
1340 nack(s)
1341 	char *s;
1342 {
1343 
1344 	reply(502, "%s command not implemented.", s);
1345 }
1346 
1347 /* ARGSUSED */
1348 void
1349 yyerror(s)
1350 	char *s;
1351 {
1352 	char *cp;
1353 
1354 	if (cp = strchr(cbuf,'\n'))
1355 		*cp = '\0';
1356 	reply(500, "'%s': command not understood.", cbuf);
1357 }
1358 
1359 void
1360 delete(name)
1361 	char *name;
1362 {
1363 	struct stat st;
1364 
1365 	LOGCMD("delete", name);
1366 	if (stat(name, &st) < 0) {
1367 		perror_reply(550, name);
1368 		return;
1369 	}
1370 	if ((st.st_mode&S_IFMT) == S_IFDIR) {
1371 		if (rmdir(name) < 0) {
1372 			perror_reply(550, name);
1373 			return;
1374 		}
1375 		goto done;
1376 	}
1377 	if (unlink(name) < 0) {
1378 		perror_reply(550, name);
1379 		return;
1380 	}
1381 done:
1382 	ack("DELE");
1383 }
1384 
1385 void
1386 cwd(path)
1387 	char *path;
1388 {
1389 
1390 	if (chdir(path) < 0)
1391 		perror_reply(550, path);
1392 	else
1393 		ack("CWD");
1394 }
1395 
1396 void
1397 makedir(name)
1398 	char *name;
1399 {
1400 
1401 	LOGCMD("mkdir", name);
1402 	if (mkdir(name, 0777) < 0)
1403 		perror_reply(550, name);
1404 	else
1405 		reply(257, "MKD command successful.");
1406 }
1407 
1408 void
1409 removedir(name)
1410 	char *name;
1411 {
1412 
1413 	LOGCMD("rmdir", name);
1414 	if (rmdir(name) < 0)
1415 		perror_reply(550, name);
1416 	else
1417 		ack("RMD");
1418 }
1419 
1420 void
1421 pwd()
1422 {
1423 	char path[MAXPATHLEN + 1];
1424 
1425 	if (getwd(path) == (char *)NULL)
1426 		reply(550, "%s.", path);
1427 	else
1428 		reply(257, "\"%s\" is current directory.", path);
1429 }
1430 
1431 char *
1432 renamefrom(name)
1433 	char *name;
1434 {
1435 	struct stat st;
1436 
1437 	if (stat(name, &st) < 0) {
1438 		perror_reply(550, name);
1439 		return ((char *)0);
1440 	}
1441 	reply(350, "File exists, ready for destination name");
1442 	return (name);
1443 }
1444 
1445 void
1446 renamecmd(from, to)
1447 	char *from, *to;
1448 {
1449 
1450 	LOGCMD2("rename", from, to);
1451 	if (rename(from, to) < 0)
1452 		perror_reply(550, "rename");
1453 	else
1454 		ack("RNTO");
1455 }
1456 
1457 static void
1458 dolog(sin)
1459 	struct sockaddr_in *sin;
1460 {
1461 	struct hostent *hp = gethostbyaddr((char *)&sin->sin_addr,
1462 		sizeof(struct in_addr), AF_INET);
1463 
1464 	if (hp)
1465 		(void) strncpy(remotehost, hp->h_name, sizeof(remotehost));
1466 	else
1467 		(void) strncpy(remotehost, inet_ntoa(sin->sin_addr),
1468 		    sizeof(remotehost));
1469 #ifdef SETPROCTITLE
1470 	snprintf(proctitle, sizeof(proctitle), "%s: connected", remotehost);
1471 	setproctitle(proctitle);
1472 #endif /* SETPROCTITLE */
1473 
1474 	if (logging)
1475 		syslog(LOG_INFO, "connection from %s", remotehost);
1476 }
1477 
1478 /*
1479  * Record logout in wtmp file
1480  * and exit with supplied status.
1481  */
1482 void
1483 dologout(status)
1484 	int status;
1485 {
1486 
1487 	if (logged_in) {
1488 		(void) seteuid((uid_t)0);
1489 		logwtmp(ttyline, "", "");
1490 	}
1491 	/* beware of flushing buffers after a SIGPIPE */
1492 	_exit(status);
1493 }
1494 
1495 static void
1496 myoob(signo)
1497 	int signo;
1498 {
1499 	char *cp;
1500 
1501 	/* only process if transfer occurring */
1502 	if (!transflag)
1503 		return;
1504 	cp = tmpline;
1505 	if (getline(cp, 7, stdin) == NULL) {
1506 		reply(221, "You could at least say goodbye.");
1507 		dologout(0);
1508 	}
1509 	upper(cp);
1510 	if (strcmp(cp, "ABOR\r\n") == 0) {
1511 		tmpline[0] = '\0';
1512 		reply(426, "Transfer aborted. Data connection closed.");
1513 		reply(226, "Abort successful");
1514 		longjmp(urgcatch, 1);
1515 	}
1516 	if (strcmp(cp, "STAT\r\n") == 0) {
1517 		if (file_size != (off_t) -1)
1518 			reply(213, "Status: %qd of %qd bytes transferred",
1519 			    byte_count, file_size);
1520 		else
1521 			reply(213, "Status: %qd bytes transferred", byte_count);
1522 	}
1523 }
1524 
1525 /*
1526  * Note: a response of 425 is not mentioned as a possible response to
1527  *	the PASV command in RFC959. However, it has been blessed as
1528  *	a legitimate response by Jon Postel in a telephone conversation
1529  *	with Rick Adams on 25 Jan 89.
1530  */
1531 void
1532 passive()
1533 {
1534 	int len;
1535 	u_short port;
1536 	char *p, *a;
1537 
1538 	pdata = socket(AF_INET, SOCK_STREAM, 0);
1539 	if (pdata < 0) {
1540 		perror_reply(425, "Can't open passive connection");
1541 		return;
1542 	}
1543 
1544 	if (restricted_data_ports) {
1545 		for (port = FTP_DATA_BOTTOM; port <= FTP_DATA_TOP; port++) {
1546 			pasv_addr = ctrl_addr;
1547 			pasv_addr.sin_port = htons(port);
1548 			(void) seteuid((uid_t)0);
1549 			if (bind(pdata, (struct sockaddr *)&pasv_addr,
1550 				 sizeof(pasv_addr)) < 0) {
1551 				(void) seteuid((uid_t)pw->pw_uid);
1552 				if (errno == EADDRINUSE)
1553 					continue;
1554 				else
1555 					goto pasv_error;
1556 			}
1557 			(void) seteuid((uid_t)pw->pw_uid);
1558 			break;
1559 		}
1560 		if (port > FTP_DATA_TOP)
1561 			goto pasv_error;
1562 	} else {
1563 		pasv_addr = ctrl_addr;
1564 		pasv_addr.sin_port = 0;
1565 		(void) seteuid((uid_t)0);
1566 		if (bind(pdata, (struct sockaddr *)&pasv_addr,
1567 			 sizeof(pasv_addr)) < 0) {
1568 			(void) seteuid((uid_t)pw->pw_uid);
1569 			goto pasv_error;
1570 		}
1571 		(void) seteuid((uid_t)pw->pw_uid);
1572 	}
1573 
1574 	len = sizeof(pasv_addr);
1575 	if (getsockname(pdata, (struct sockaddr *) &pasv_addr, &len) < 0)
1576 		goto pasv_error;
1577 	if (listen(pdata, 1) < 0)
1578 		goto pasv_error;
1579 	a = (char *) &pasv_addr.sin_addr;
1580 	p = (char *) &pasv_addr.sin_port;
1581 
1582 #define UC(b) (((int) b) & 0xff)
1583 
1584 	reply(227, "Entering Passive Mode (%d,%d,%d,%d,%d,%d)", UC(a[0]),
1585 		UC(a[1]), UC(a[2]), UC(a[3]), UC(p[0]), UC(p[1]));
1586 	return;
1587 
1588 pasv_error:
1589 	(void) close(pdata);
1590 	pdata = -1;
1591 	perror_reply(425, "Can't open passive connection");
1592 	return;
1593 }
1594 
1595 /*
1596  * Generate unique name for file with basename "local".
1597  * The file named "local" is already known to exist.
1598  * Generates failure reply on error.
1599  */
1600 static char *
1601 gunique(local)
1602 	char *local;
1603 {
1604 	static char new[MAXPATHLEN];
1605 	struct stat st;
1606 	int count;
1607 	char *cp;
1608 
1609 	cp = strrchr(local, '/');
1610 	if (cp)
1611 		*cp = '\0';
1612 	if (stat(cp ? local : ".", &st) < 0) {
1613 		perror_reply(553, cp ? local : ".");
1614 		return ((char *) 0);
1615 	}
1616 	if (cp)
1617 		*cp = '/';
1618 	(void) strcpy(new, local);
1619 	cp = new + strlen(new);
1620 	*cp++ = '.';
1621 	for (count = 1; count < 100; count++) {
1622 		(void)sprintf(cp, "%d", count);
1623 		if (stat(new, &st) < 0)
1624 			return (new);
1625 	}
1626 	reply(452, "Unique file name cannot be created.");
1627 	return (NULL);
1628 }
1629 
1630 /*
1631  * Format and send reply containing system error number.
1632  */
1633 void
1634 perror_reply(code, string)
1635 	int code;
1636 	char *string;
1637 {
1638 
1639 	reply(code, "%s: %s.", string, strerror(errno));
1640 }
1641 
1642 static char *onefile[] = {
1643 	"",
1644 	0
1645 };
1646 
1647 void
1648 send_file_list(whichf)
1649 	char *whichf;
1650 {
1651 	struct stat st;
1652 	DIR *dirp = NULL;
1653 	struct dirent *dir;
1654 	FILE *dout = NULL;
1655 	char **dirlist, *dirname;
1656 	int simple = 0;
1657 	int freeglob = 0;
1658 	glob_t gl;
1659 
1660 	if (strpbrk(whichf, "~{[*?") != NULL) {
1661 		int flags = GLOB_BRACE|GLOB_NOCHECK|GLOB_QUOTE|GLOB_TILDE;
1662 
1663 		memset(&gl, 0, sizeof(gl));
1664 		freeglob = 1;
1665 		if (glob(whichf, flags, 0, &gl)) {
1666 			reply(550, "not found");
1667 			goto out;
1668 		} else if (gl.gl_pathc == 0) {
1669 			errno = ENOENT;
1670 			perror_reply(550, whichf);
1671 			goto out;
1672 		}
1673 		dirlist = gl.gl_pathv;
1674 	} else {
1675 		onefile[0] = whichf;
1676 		dirlist = onefile;
1677 		simple = 1;
1678 	}
1679 
1680 	if (setjmp(urgcatch)) {
1681 		transflag = 0;
1682 		goto out;
1683 	}
1684 	while (dirname = *dirlist++) {
1685 		if (stat(dirname, &st) < 0) {
1686 			/*
1687 			 * If user typed "ls -l", etc, and the client
1688 			 * used NLST, do what the user meant.
1689 			 */
1690 			if (dirname[0] == '-' && *dirlist == NULL &&
1691 			    transflag == 0) {
1692 				retrieve("/bin/ls %s", dirname);
1693 				goto out;
1694 			}
1695 			perror_reply(550, whichf);
1696 			if (dout != NULL) {
1697 				(void) fclose(dout);
1698 				transflag = 0;
1699 				data = -1;
1700 				pdata = -1;
1701 			}
1702 			goto out;
1703 		}
1704 
1705 		if (S_ISREG(st.st_mode)) {
1706 			if (dout == NULL) {
1707 				dout = dataconn("file list", (off_t)-1, "w");
1708 				if (dout == NULL)
1709 					goto out;
1710 				transflag++;
1711 			}
1712 			fprintf(dout, "%s%s\n", dirname,
1713 				type == TYPE_A ? "\r" : "");
1714 			byte_count += strlen(dirname) + 1;
1715 			continue;
1716 		} else if (!S_ISDIR(st.st_mode))
1717 			continue;
1718 
1719 		if ((dirp = opendir(dirname)) == NULL)
1720 			continue;
1721 
1722 		while ((dir = readdir(dirp)) != NULL) {
1723 			char nbuf[MAXPATHLEN];
1724 
1725 			if (dir->d_name[0] == '.' && dir->d_namlen == 1)
1726 				continue;
1727 			if (dir->d_name[0] == '.' && dir->d_name[1] == '.' &&
1728 			    dir->d_namlen == 2)
1729 				continue;
1730 
1731 			sprintf(nbuf, "%s/%s", dirname, dir->d_name);
1732 
1733 			/*
1734 			 * We have to do a stat to insure it's
1735 			 * not a directory or special file.
1736 			 */
1737 			if (simple || (stat(nbuf, &st) == 0 &&
1738 			    S_ISREG(st.st_mode))) {
1739 				if (dout == NULL) {
1740 					dout = dataconn("file list", (off_t)-1,
1741 						"w");
1742 					if (dout == NULL)
1743 						goto out;
1744 					transflag++;
1745 				}
1746 				if (nbuf[0] == '.' && nbuf[1] == '/')
1747 					fprintf(dout, "%s%s\n", &nbuf[2],
1748 						type == TYPE_A ? "\r" : "");
1749 				else
1750 					fprintf(dout, "%s%s\n", nbuf,
1751 						type == TYPE_A ? "\r" : "");
1752 				byte_count += strlen(nbuf) + 1;
1753 			}
1754 		}
1755 		(void) closedir(dirp);
1756 	}
1757 
1758 	if (dout == NULL)
1759 		reply(550, "No files found.");
1760 	else if (ferror(dout) != 0)
1761 		perror_reply(550, "Data connection");
1762 	else
1763 		reply(226, "Transfer complete.");
1764 
1765 	transflag = 0;
1766 	if (dout != NULL)
1767 		(void) fclose(dout);
1768 	data = -1;
1769 	pdata = -1;
1770 out:
1771 	if (freeglob) {
1772 		freeglob = 0;
1773 		globfree(&gl);
1774 	}
1775 }
1776 
1777 #ifdef SETPROCTITLE
1778 /*
1779  * Clobber argv so ps will show what we're doing.  (Stolen from sendmail.)
1780  * Warning, since this is usually started from inetd.conf, it often doesn't
1781  * have much of an environment or arglist to overwrite.
1782  */
1783 void
1784 #if __STDC__
1785 setproctitle(const char *fmt, ...)
1786 #else
1787 setproctitle(fmt, va_alist)
1788 	char *fmt;
1789         va_dcl
1790 #endif
1791 {
1792 	int i;
1793 	va_list ap;
1794 	char *p, *bp, ch;
1795 	char buf[LINE_MAX];
1796 
1797 #if __STDC__
1798 	va_start(ap, fmt);
1799 #else
1800 	va_start(ap);
1801 #endif
1802 	(void)vsnprintf(buf, sizeof(buf), fmt, ap);
1803 
1804 	/* make ps print our process name */
1805 	p = Argv[0];
1806 	*p++ = '-';
1807 
1808 	i = strlen(buf);
1809 	if (i > LastArgv - p - 2) {
1810 		i = LastArgv - p - 2;
1811 		buf[i] = '\0';
1812 	}
1813 	bp = buf;
1814 	while (ch = *bp++)
1815 		if (ch != '\n' && ch != '\r')
1816 			*p++ = ch;
1817 	while (p < LastArgv)
1818 		*p++ = ' ';
1819 }
1820 #endif /* SETPROCTITLE */
1821 
1822 #ifdef STATS
1823 logxfer(name, size, start)
1824 	char *name;
1825 	long size;
1826 	long start;
1827 {
1828 	char buf[1024];
1829 	char path[MAXPATHLEN + 1];
1830 	long now;
1831 
1832 	if (statfd >= 0 && getwd(path) != NULL) {
1833 		time(&now);
1834 		sprintf(buf, "%.20s!%s!%s!%s/%s!%ld!%ld\n",
1835 			ctime(&now)+4, ident, remotehost,
1836 			path, name, size, now - start + (now == start));
1837 		write(statfd, buf, strlen(buf));
1838 	}
1839 }
1840 
1841 char *
1842 copy(s)
1843 	char *s;
1844 {
1845 	char *p;
1846 
1847 	p = malloc((unsigned) strlen(s) + 1);
1848 	if (p == NULL)
1849 		fatal("Ran out of memory.");
1850 	(void) strcpy(p, s);
1851 	return (p);
1852 }
1853 #endif
1854