xref: /freebsd/libexec/ftpd/ftpd.c (revision 09e8dea79366f1e5b3a73e8a271b26e4b6bf2e6a)
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 
34 #if 0
35 #ifndef lint
36 static char copyright[] =
37 "@(#) Copyright (c) 1985, 1988, 1990, 1992, 1993, 1994\n\
38 	The Regents of the University of California.  All rights reserved.\n";
39 #endif /* not lint */
40 #endif
41 
42 #ifndef lint
43 #if 0
44 static char sccsid[] = "@(#)ftpd.c	8.4 (Berkeley) 4/16/94";
45 #endif
46 static const char rcsid[] =
47   "$FreeBSD$";
48 #endif /* not lint */
49 
50 /*
51  * FTP server.
52  */
53 #include <sys/param.h>
54 #include <sys/ioctl.h>
55 #include <sys/mman.h>
56 #include <sys/socket.h>
57 #include <sys/stat.h>
58 #include <sys/time.h>
59 #include <sys/wait.h>
60 
61 #include <netinet/in.h>
62 #include <netinet/in_systm.h>
63 #include <netinet/ip.h>
64 #include <netinet/tcp.h>
65 
66 #define	FTP_NAMES
67 #include <arpa/ftp.h>
68 #include <arpa/inet.h>
69 #include <arpa/telnet.h>
70 
71 #include <ctype.h>
72 #include <dirent.h>
73 #include <err.h>
74 #include <errno.h>
75 #include <fcntl.h>
76 #include <glob.h>
77 #include <limits.h>
78 #include <netdb.h>
79 #include <pwd.h>
80 #include <grp.h>
81 #include <opie.h>
82 #include <signal.h>
83 #include <stdio.h>
84 #include <stdlib.h>
85 #include <string.h>
86 #include <syslog.h>
87 #include <time.h>
88 #include <unistd.h>
89 #include <libutil.h>
90 #ifdef	LOGIN_CAP
91 #include <login_cap.h>
92 #endif
93 
94 #ifdef USE_PAM
95 #include <security/pam_appl.h>
96 #endif
97 
98 #include "pathnames.h"
99 #include "extern.h"
100 
101 #include <stdarg.h>
102 
103 static char version[] = "Version 6.00LS";
104 #undef main
105 
106 /* wrapper for KAME-special getnameinfo() */
107 #ifndef NI_WITHSCOPEID
108 #define	NI_WITHSCOPEID	0
109 #endif
110 
111 extern	off_t restart_point;
112 extern	char cbuf[];
113 
114 union sockunion server_addr;
115 union sockunion ctrl_addr;
116 union sockunion data_source;
117 union sockunion data_dest;
118 union sockunion his_addr;
119 union sockunion pasv_addr;
120 
121 int	daemon_mode;
122 int	data;
123 int	logged_in;
124 struct	passwd *pw;
125 int	ftpdebug;
126 int	timeout = 900;    /* timeout after 15 minutes of inactivity */
127 int	maxtimeout = 7200;/* don't allow idle time to be set beyond 2 hours */
128 int	logging;
129 int	restricted_data_ports = 1;
130 int	paranoid = 1;	  /* be extra careful about security */
131 int	anon_only = 0;    /* Only anonymous ftp allowed */
132 int	guest;
133 int	dochroot;
134 int	stats;
135 int	statfd = -1;
136 int	type;
137 int	form;
138 int	stru;			/* avoid C keyword */
139 int	mode;
140 int	usedefault = 1;		/* for data transfers */
141 int	pdata = -1;		/* for passive mode */
142 int	readonly=0;		/* Server is in readonly mode.	*/
143 int	noepsv=0;		/* EPSV command is disabled.	*/
144 int	noretr=0;		/* RETR command is disabled.	*/
145 int	noguestretr=0;		/* RETR command is disabled for anon users. */
146 
147 static volatile sig_atomic_t recvurg;
148 sig_atomic_t transflag;
149 off_t	file_size;
150 off_t	byte_count;
151 #if !defined(CMASK) || CMASK == 0
152 #undef CMASK
153 #define CMASK 027
154 #endif
155 int	defumask = CMASK;		/* default umask value */
156 char	tmpline[7];
157 char	*hostname;
158 int	epsvall = 0;
159 
160 #ifdef VIRTUAL_HOSTING
161 char	*ftpuser;
162 
163 static struct ftphost {
164 	struct ftphost	*next;
165 	struct addrinfo *hostinfo;
166 	char		*hostname;
167 	char		*anonuser;
168 	char		*statfile;
169 	char		*welcome;
170 	char		*loginmsg;
171 } *thishost, *firsthost;
172 
173 #endif
174 char	remotehost[MAXHOSTNAMELEN];
175 char	*ident = NULL;
176 
177 static char ttyline[20];
178 char	*tty = ttyline;		/* for klogin */
179 
180 #ifdef USE_PAM
181 static int	auth_pam(struct passwd**, const char*);
182 pam_handle_t *pamh = NULL;
183 #endif
184 
185 static struct opie opiedata;
186 static char opieprompt[OPIE_CHALLENGE_MAX+1];
187 static int pwok;
188 
189 char	*pid_file = NULL;
190 
191 /*
192  * Limit number of pathnames that glob can return.
193  * A limit of 0 indicates the number of pathnames is unlimited.
194  */
195 #define MAXGLOBARGS	16384
196 #
197 
198 /*
199  * Timeout intervals for retrying connections
200  * to hosts that don't accept PORT cmds.  This
201  * is a kludge, but given the problems with TCP...
202  */
203 #define	SWAITMAX	90	/* wait at most 90 seconds */
204 #define	SWAITINT	5	/* interval between retries */
205 
206 int	swaitmax = SWAITMAX;
207 int	swaitint = SWAITINT;
208 
209 #ifdef SETPROCTITLE
210 #ifdef OLD_SETPROCTITLE
211 char	**Argv = NULL;		/* pointer to argument vector */
212 char	*LastArgv = NULL;	/* end of argv */
213 #endif /* OLD_SETPROCTITLE */
214 char	proctitle[LINE_MAX];	/* initial part of title */
215 #endif /* SETPROCTITLE */
216 
217 #define LOGCMD(cmd, file) \
218 	if (logging > 1) \
219 	    syslog(LOG_INFO,"%s %s%s", cmd, \
220 		*(file) == '/' ? "" : curdir(), file);
221 #define LOGCMD2(cmd, file1, file2) \
222 	 if (logging > 1) \
223 	    syslog(LOG_INFO,"%s %s%s %s%s", cmd, \
224 		*(file1) == '/' ? "" : curdir(), file1, \
225 		*(file2) == '/' ? "" : curdir(), file2);
226 #define LOGBYTES(cmd, file, cnt) \
227 	if (logging > 1) { \
228 		if (cnt == (off_t)-1) \
229 		    syslog(LOG_INFO,"%s %s%s", cmd, \
230 			*(file) == '/' ? "" : curdir(), file); \
231 		else \
232 		    syslog(LOG_INFO, "%s %s%s = %qd bytes", \
233 			cmd, (*(file) == '/') ? "" : curdir(), file, cnt); \
234 	}
235 
236 #ifdef VIRTUAL_HOSTING
237 static void	 inithosts(void);
238 static void	selecthost(union sockunion *);
239 #endif
240 static void	 ack(char *);
241 static void	 sigurg(int);
242 static void	 myoob(void);
243 static int	 checkuser(char *, char *, int);
244 static FILE	*dataconn(char *, off_t, char *);
245 static void	 dolog(struct sockaddr *);
246 static char	*curdir(void);
247 static void	 end_login(void);
248 static FILE	*getdatasock(char *);
249 static char	*gunique(char *);
250 static void	 lostconn(int);
251 static void	 sigquit(int);
252 static int	 receive_data(FILE *, FILE *);
253 static int	 send_data(FILE *, FILE *, off_t, off_t, int);
254 static struct passwd *
255 		 sgetpwnam(char *);
256 static char	*sgetsave(char *);
257 static void	 reapchild(int);
258 static void      logxfer(char *, off_t, time_t);
259 
260 static char *
261 curdir(void)
262 {
263 	static char path[MAXPATHLEN+1+1];	/* path + '/' + '\0' */
264 
265 	if (getcwd(path, sizeof(path)-2) == NULL)
266 		return ("");
267 	if (path[1] != '\0')		/* special case for root dir. */
268 		strcat(path, "/");
269 	/* For guest account, skip / since it's chrooted */
270 	return (guest ? path+1 : path);
271 }
272 
273 int
274 main(int argc, char *argv[], char **envp)
275 {
276 	int addrlen, ch, on = 1, tos;
277 	char *cp, line[LINE_MAX];
278 	FILE *fd;
279 	int error;
280 	char	*bindname = NULL;
281 	int	family = AF_UNSPEC;
282 	int	enable_v4 = 0;
283 	struct sigaction sa;
284 
285 	tzset();		/* in case no timezone database in ~ftp */
286 	sigemptyset(&sa.sa_mask);
287 	sa.sa_flags = SA_RESTART;
288 
289 #ifdef OLD_SETPROCTITLE
290 	/*
291 	 *  Save start and extent of argv for setproctitle.
292 	 */
293 	Argv = argv;
294 	while (*envp)
295 		envp++;
296 	LastArgv = envp[-1] + strlen(envp[-1]);
297 #endif /* OLD_SETPROCTITLE */
298 
299 
300 	while ((ch = getopt(argc, argv, "AdlDESURrt:T:u:vOoa:p:46")) != -1) {
301 		switch (ch) {
302 		case 'D':
303 			daemon_mode++;
304 			break;
305 
306 		case 'd':
307 			ftpdebug++;
308 			break;
309 
310 		case 'E':
311 			noepsv = 1;
312 			break;
313 
314 		case 'l':
315 			logging++;	/* > 1 == extra logging */
316 			break;
317 
318 		case 'r':
319 			readonly = 1;
320 			break;
321 
322 		case 'R':
323 			paranoid = 0;
324 			break;
325 
326 		case 'S':
327 			stats++;
328 			break;
329 
330 		case 'T':
331 			maxtimeout = atoi(optarg);
332 			if (timeout > maxtimeout)
333 				timeout = maxtimeout;
334 			break;
335 
336 		case 't':
337 			timeout = atoi(optarg);
338 			if (maxtimeout < timeout)
339 				maxtimeout = timeout;
340 			break;
341 
342 		case 'U':
343 			restricted_data_ports = 0;
344 			break;
345 
346 		case 'a':
347 			bindname = optarg;
348 			break;
349 
350 		case 'p':
351 			pid_file = optarg;
352 			break;
353 
354 		case 'u':
355 		    {
356 			long val = 0;
357 
358 			val = strtol(optarg, &optarg, 8);
359 			if (*optarg != '\0' || val < 0)
360 				warnx("bad value for -u");
361 			else
362 				defumask = val;
363 			break;
364 		    }
365 		case 'A':
366 			anon_only = 1;
367 			break;
368 
369 		case 'v':
370 			ftpdebug = 1;
371 			break;
372 
373 		case '4':
374 			enable_v4 = 1;
375 			if (family == AF_UNSPEC)
376 				family = AF_INET;
377 			break;
378 
379 		case '6':
380 			family = AF_INET6;
381 			break;
382 
383 		case 'O':
384 			noguestretr = 1;
385 			break;
386 
387 		case 'o':
388 			noretr = 1;
389 			break;
390 
391 		default:
392 			warnx("unknown flag -%c ignored", optopt);
393 			break;
394 		}
395 	}
396 
397 #ifdef VIRTUAL_HOSTING
398 	inithosts();
399 #endif
400 	(void) freopen(_PATH_DEVNULL, "w", stderr);
401 
402 	/*
403 	 * LOG_NDELAY sets up the logging connection immediately,
404 	 * necessary for anonymous ftp's that chroot and can't do it later.
405 	 */
406 	openlog("ftpd", LOG_PID | LOG_NDELAY, LOG_FTP);
407 
408 	if (daemon_mode) {
409 		int ctl_sock, fd;
410 		struct addrinfo hints, *res;
411 
412 		/*
413 		 * Detach from parent.
414 		 */
415 		if (daemon(1, 1) < 0) {
416 			syslog(LOG_ERR, "failed to become a daemon");
417 			exit(1);
418 		}
419 		sa.sa_handler = reapchild;
420 		(void)sigaction(SIGCHLD, &sa, NULL);
421 		/* init bind_sa */
422 		memset(&hints, 0, sizeof(hints));
423 
424 		hints.ai_family = family == AF_UNSPEC ? AF_INET : family;
425 		hints.ai_socktype = SOCK_STREAM;
426 		hints.ai_protocol = 0;
427 		hints.ai_flags = AI_PASSIVE;
428 		error = getaddrinfo(bindname, "ftp", &hints, &res);
429 		if (error) {
430 			if (family == AF_UNSPEC) {
431 				hints.ai_family = AF_UNSPEC;
432 				error = getaddrinfo(bindname, "ftp", &hints,
433 						    &res);
434 			}
435 		}
436 		if (error) {
437 			syslog(LOG_ERR, "%s", gai_strerror(error));
438 			if (error == EAI_SYSTEM)
439 				syslog(LOG_ERR, "%s", strerror(errno));
440 			exit(1);
441 		}
442 		if (res->ai_addr == NULL) {
443 			syslog(LOG_ERR, "-a %s: getaddrinfo failed", hostname);
444 			exit(1);
445 		} else
446 			family = res->ai_addr->sa_family;
447 		/*
448 		 * Open a socket, bind it to the FTP port, and start
449 		 * listening.
450 		 */
451 		ctl_sock = socket(family, SOCK_STREAM, 0);
452 		if (ctl_sock < 0) {
453 			syslog(LOG_ERR, "control socket: %m");
454 			exit(1);
455 		}
456 		if (setsockopt(ctl_sock, SOL_SOCKET, SO_REUSEADDR,
457 		    (char *)&on, sizeof(on)) < 0)
458 			syslog(LOG_ERR, "control setsockopt: %m");
459 #ifdef IPV6_BINDV6ONLY
460 		if (family == AF_INET6 && enable_v4 == 0) {
461 			if (setsockopt(ctl_sock, IPPROTO_IPV6, IPV6_BINDV6ONLY,
462 				       (char *)&on, sizeof (on)) < 0)
463 				syslog(LOG_ERR,
464 				       "control setsockopt(IPV6_BINDV6ONLY): %m");
465 		}
466 #endif /* IPV6_BINDV6ONLY */
467 		memcpy(&server_addr, res->ai_addr, res->ai_addr->sa_len);
468 		if (bind(ctl_sock, (struct sockaddr *)&server_addr,
469 			 server_addr.su_len) < 0) {
470 			syslog(LOG_ERR, "control bind: %m");
471 			exit(1);
472 		}
473 		if (listen(ctl_sock, 32) < 0) {
474 			syslog(LOG_ERR, "control listen: %m");
475 			exit(1);
476 		}
477 		/*
478 		 * Atomically write process ID
479 		 */
480 		if (pid_file)
481 		{
482 			int fd;
483 			char buf[20];
484 
485 			fd = open(pid_file, O_CREAT | O_WRONLY | O_TRUNC
486 				| O_NONBLOCK | O_EXLOCK, 0644);
487 			if (fd < 0) {
488 				if (errno == EAGAIN)
489 					errx(1, "%s: file locked", pid_file);
490 				else
491 					err(1, "%s", pid_file);
492 			}
493 			snprintf(buf, sizeof(buf),
494 				"%lu\n", (unsigned long) getpid());
495 			if (write(fd, buf, strlen(buf)) < 0)
496 				err(1, "%s: write", pid_file);
497 			/* Leave the pid file open and locked */
498 		}
499 		/*
500 		 * Loop forever accepting connection requests and forking off
501 		 * children to handle them.
502 		 */
503 		while (1) {
504 			addrlen = server_addr.su_len;
505 			fd = accept(ctl_sock, (struct sockaddr *)&his_addr, &addrlen);
506 			if (fork() == 0) {
507 				/* child */
508 				(void) dup2(fd, 0);
509 				(void) dup2(fd, 1);
510 				close(ctl_sock);
511 				break;
512 			}
513 			close(fd);
514 		}
515 	} else {
516 		addrlen = sizeof(his_addr);
517 		if (getpeername(0, (struct sockaddr *)&his_addr, &addrlen) < 0) {
518 			syslog(LOG_ERR, "getpeername (%s): %m",argv[0]);
519 			exit(1);
520 		}
521 	}
522 
523 	sa.sa_handler = SIG_DFL;
524 	(void)sigaction(SIGCHLD, &sa, NULL);
525 
526 	sa.sa_handler = sigurg;
527 	sa.sa_flags = 0;		/* don't restart syscalls for SIGURG */
528 	(void)sigaction(SIGURG, &sa, NULL);
529 
530 	sigfillset(&sa.sa_mask);	/* block all signals in handler */
531 	sa.sa_flags = SA_RESTART;
532 	sa.sa_handler = sigquit;
533 	(void)sigaction(SIGHUP, &sa, NULL);
534 	(void)sigaction(SIGINT, &sa, NULL);
535 	(void)sigaction(SIGQUIT, &sa, NULL);
536 	(void)sigaction(SIGTERM, &sa, NULL);
537 
538 	sa.sa_handler = lostconn;
539 	(void)sigaction(SIGPIPE, &sa, NULL);
540 
541 	addrlen = sizeof(ctrl_addr);
542 	if (getsockname(0, (struct sockaddr *)&ctrl_addr, &addrlen) < 0) {
543 		syslog(LOG_ERR, "getsockname (%s): %m",argv[0]);
544 		exit(1);
545 	}
546 #ifdef VIRTUAL_HOSTING
547 	/* select our identity from virtual host table */
548 	selecthost(&ctrl_addr);
549 #endif
550 #ifdef IP_TOS
551 	if (ctrl_addr.su_family == AF_INET)
552       {
553 	tos = IPTOS_LOWDELAY;
554 	if (setsockopt(0, IPPROTO_IP, IP_TOS, (char *)&tos, sizeof(int)) < 0)
555 		syslog(LOG_WARNING, "setsockopt (IP_TOS): %m");
556       }
557 #endif
558 	/*
559 	 * Disable Nagle on the control channel so that we don't have to wait
560 	 * for peer's ACK before issuing our next reply.
561 	 */
562 	if (setsockopt(0, IPPROTO_TCP, TCP_NODELAY, &on, sizeof(on)) < 0)
563 		syslog(LOG_WARNING, "control setsockopt TCP_NODELAY: %m");
564 
565 	data_source.su_port = htons(ntohs(ctrl_addr.su_port) - 1);
566 
567 	/* set this here so klogin can use it... */
568 	(void)snprintf(ttyline, sizeof(ttyline), "ftp%d", getpid());
569 
570 	/* Try to handle urgent data inline */
571 #ifdef SO_OOBINLINE
572 	if (setsockopt(0, SOL_SOCKET, SO_OOBINLINE, (char *)&on, sizeof(on)) < 0)
573 		syslog(LOG_ERR, "setsockopt: %m");
574 #endif
575 
576 #ifdef	F_SETOWN
577 	if (fcntl(fileno(stdin), F_SETOWN, getpid()) == -1)
578 		syslog(LOG_ERR, "fcntl F_SETOWN: %m");
579 #endif
580 	dolog((struct sockaddr *)&his_addr);
581 	/*
582 	 * Set up default state
583 	 */
584 	data = -1;
585 	type = TYPE_A;
586 	form = FORM_N;
587 	stru = STRU_F;
588 	mode = MODE_S;
589 	tmpline[0] = '\0';
590 
591 	/* If logins are disabled, print out the message. */
592 	if ((fd = fopen(_PATH_NOLOGIN,"r")) != NULL) {
593 		while (fgets(line, sizeof(line), fd) != NULL) {
594 			if ((cp = strchr(line, '\n')) != NULL)
595 				*cp = '\0';
596 			lreply(530, "%s", line);
597 		}
598 		(void) fflush(stdout);
599 		(void) fclose(fd);
600 		reply(530, "System not available.");
601 		exit(0);
602 	}
603 #ifdef VIRTUAL_HOSTING
604 	if ((fd = fopen(thishost->welcome, "r")) != NULL) {
605 #else
606 	if ((fd = fopen(_PATH_FTPWELCOME, "r")) != NULL) {
607 #endif
608 		while (fgets(line, sizeof(line), fd) != NULL) {
609 			if ((cp = strchr(line, '\n')) != NULL)
610 				*cp = '\0';
611 			lreply(220, "%s", line);
612 		}
613 		(void) fflush(stdout);
614 		(void) fclose(fd);
615 		/* reply(220,) must follow */
616 	}
617 #ifndef VIRTUAL_HOSTING
618 	if ((hostname = malloc(MAXHOSTNAMELEN)) == NULL)
619 		fatalerror("Ran out of memory.");
620 	(void) gethostname(hostname, MAXHOSTNAMELEN - 1);
621 	hostname[MAXHOSTNAMELEN - 1] = '\0';
622 #endif
623 	reply(220, "%s FTP server (%s) ready.", hostname, version);
624 	for (;;)
625 		(void) yyparse();
626 	/* NOTREACHED */
627 }
628 
629 static void
630 lostconn(int signo)
631 {
632 
633 	if (ftpdebug)
634 		syslog(LOG_DEBUG, "lost connection");
635 	dologout(1);
636 }
637 
638 static void
639 sigquit(int signo)
640 {
641 
642 	syslog(LOG_ERR, "got signal %d", signo);
643 	dologout(1);
644 }
645 
646 #ifdef VIRTUAL_HOSTING
647 /*
648  * read in virtual host tables (if they exist)
649  */
650 
651 static void
652 inithosts(void)
653 {
654 	FILE *fp;
655 	char *cp;
656 	struct ftphost *hrp, *lhrp;
657 	char line[1024];
658 	struct addrinfo hints, *res, *ai;
659 
660 	/*
661 	 * Fill in the default host information
662 	 */
663 	if (gethostname(line, sizeof(line)) < 0)
664 		line[0] = '\0';
665 	if ((hrp = malloc(sizeof(struct ftphost))) == NULL ||
666 	    (hrp->hostname = strdup(line)) == NULL)
667 		fatalerror("Ran out of memory.");
668 	hrp->hostinfo = NULL;
669 
670 	memset(&hints, 0, sizeof(hints));
671 	hints.ai_flags = AI_CANONNAME;
672 	hints.ai_family = AF_UNSPEC;
673 	getaddrinfo(hrp->hostname, NULL, &hints, &res);
674 	if (res)
675 		hrp->hostinfo = res;
676 	hrp->statfile = _PATH_FTPDSTATFILE;
677 	hrp->welcome  = _PATH_FTPWELCOME;
678 	hrp->loginmsg = _PATH_FTPLOGINMESG;
679 	hrp->anonuser = "ftp";
680 	hrp->next = NULL;
681 	thishost = firsthost = lhrp = hrp;
682 	if ((fp = fopen(_PATH_FTPHOSTS, "r")) != NULL) {
683 		int addrsize, error, gothost;
684 		void *addr;
685 		struct hostent *hp;
686 
687 		while (fgets(line, sizeof(line), fp) != NULL) {
688 			int	i, hp_error;
689 
690 			if ((cp = strchr(line, '\n')) == NULL) {
691 				/* ignore long lines */
692 				while (fgets(line, sizeof(line), fp) != NULL &&
693 					strchr(line, '\n') == NULL)
694 					;
695 				continue;
696 			}
697 			*cp = '\0';
698 			cp = strtok(line, " \t");
699 			/* skip comments and empty lines */
700 			if (cp == NULL || line[0] == '#')
701 				continue;
702 
703 			hints.ai_flags = 0;
704 			hints.ai_family = AF_UNSPEC;
705 			hints.ai_flags = AI_PASSIVE;
706 			error = getaddrinfo(cp, NULL, &hints, &res);
707 			if (error != NULL)
708 				continue;
709 			for (ai = res; ai != NULL && ai->ai_addr != NULL;
710 			     ai = ai->ai_next) {
711 
712 			gothost = 0;
713 			for (hrp = firsthost; hrp != NULL; hrp = hrp->next) {
714 				struct addrinfo *hi;
715 
716 				for (hi = hrp->hostinfo; hi != NULL;
717 				     hi = hi->ai_next)
718 					if (hi->ai_addrlen == ai->ai_addrlen &&
719 					    memcmp(hi->ai_addr,
720 						   ai->ai_addr,
721 						   ai->ai_addr->sa_len) == 0) {
722 						gothost++;
723 						break;
724 				}
725 				if (gothost)
726 					break;
727 			}
728 			if (hrp == NULL) {
729 				if ((hrp = malloc(sizeof(struct ftphost))) == NULL)
730 					continue;
731 				/* defaults */
732 				hrp->statfile = _PATH_FTPDSTATFILE;
733 				hrp->welcome  = _PATH_FTPWELCOME;
734 				hrp->loginmsg = _PATH_FTPLOGINMESG;
735 				hrp->anonuser = "ftp";
736 				hrp->next     = NULL;
737 				lhrp->next = hrp;
738 				lhrp = hrp;
739 			}
740 			hrp->hostinfo = res;
741 
742 			/*
743 			 * determine hostname to use.
744 			 * force defined name if there is a valid alias
745 			 * otherwise fallback to primary hostname
746 			 */
747 			/* XXX: getaddrinfo() can't do alias check */
748 			switch(hrp->hostinfo->ai_family) {
749 			case AF_INET:
750 				addr = &((struct sockaddr_in *)&hrp->hostinfo->ai_addr)->sin_addr;
751 				addrsize = sizeof(struct sockaddr_in);
752 				break;
753 			case AF_INET6:
754 				addr = &((struct sockaddr_in6 *)&hrp->hostinfo->ai_addr)->sin6_addr;
755 				addrsize = sizeof(struct sockaddr_in6);
756 				break;
757 			default:
758 				/* should not reach here */
759 				if (hrp->hostinfo != NULL)
760 					freeaddrinfo(hrp->hostinfo);
761 				free(hrp);
762 				continue;
763 				/* NOTREACHED */
764 			}
765 			if ((hp = getipnodebyaddr((char*)addr, addrsize,
766 						  hrp->hostinfo->ai_family,
767 						  &hp_error)) != NULL) {
768 				if (strcmp(cp, hp->h_name) != 0) {
769 					if (hp->h_aliases == NULL)
770 						cp = hp->h_name;
771 					else {
772 						i = 0;
773 						while (hp->h_aliases[i] &&
774 						       strcmp(cp, hp->h_aliases[i]) != 0)
775 							++i;
776 						if (hp->h_aliases[i] == NULL)
777 							cp = hp->h_name;
778 					}
779 				}
780 			}
781 			hrp->hostname = strdup(cp);
782 			freehostent(hp);
783 			/* ok, now we now peel off the rest */
784 			i = 0;
785 			while (i < 4 && (cp = strtok(NULL, " \t")) != NULL) {
786 				if (*cp != '-' && (cp = strdup(cp)) != NULL) {
787 					switch (i) {
788 					case 0:	/* anon user permissions */
789 						hrp->anonuser = cp;
790 						break;
791 					case 1: /* statistics file */
792 						hrp->statfile = cp;
793 						break;
794 					case 2: /* welcome message */
795 						hrp->welcome  = cp;
796 						break;
797 					case 3: /* login message */
798 						hrp->loginmsg = cp;
799 						break;
800 					}
801 				}
802 				++i;
803 			}
804 			/* XXX: re-initialization for getaddrinfo() loop */
805 			cp = strtok(line, " \t");
806 		      }
807 		}
808 		(void) fclose(fp);
809 	}
810 }
811 
812 static void
813 selecthost(union sockunion *su)
814 {
815 	struct ftphost	*hrp;
816 	u_int16_t port;
817 #ifdef INET6
818 	struct in6_addr *mapped_in6 = NULL;
819 #endif
820 	struct addrinfo *hi;
821 
822 #ifdef INET6
823 	/*
824 	 * XXX IPv4 mapped IPv6 addr consideraton,
825 	 * specified in rfc2373.
826 	 */
827 	if (su->su_family == AF_INET6 &&
828 	    IN6_IS_ADDR_V4MAPPED(&su->su_sin6.sin6_addr))
829 		mapped_in6 = &su->su_sin6.sin6_addr;
830 #endif
831 
832 	hrp = thishost = firsthost;	/* default */
833 	port = su->su_port;
834 	su->su_port = 0;
835 	while (hrp != NULL) {
836 	    for (hi = hrp->hostinfo; hi != NULL; hi = hi->ai_next) {
837 		if (memcmp(su, hi->ai_addr, hi->ai_addrlen) == 0) {
838 			thishost = hrp;
839 			break;
840 		}
841 #ifdef INET6
842 		/* XXX IPv4 mapped IPv6 addr consideraton */
843 		if (hi->ai_addr->sa_family == AF_INET && mapped_in6 != NULL &&
844 		    (memcmp(&mapped_in6->s6_addr[12],
845 			    &((struct sockaddr_in *)hi->ai_addr)->sin_addr,
846 			    sizeof(struct in_addr)) == 0)) {
847 			thishost = hrp;
848 			break;
849 		}
850 #endif
851 	    }
852 	    hrp = hrp->next;
853 	}
854 	su->su_port = port;
855 	/* setup static variables as appropriate */
856 	hostname = thishost->hostname;
857 	ftpuser = thishost->anonuser;
858 }
859 #endif
860 
861 /*
862  * Helper function for sgetpwnam().
863  */
864 static char *
865 sgetsave(char *s)
866 {
867 	char *new = malloc((unsigned) strlen(s) + 1);
868 
869 	if (new == NULL) {
870 		perror_reply(421, "Local resource failure: malloc");
871 		dologout(1);
872 		/* NOTREACHED */
873 	}
874 	(void) strcpy(new, s);
875 	return (new);
876 }
877 
878 /*
879  * Save the result of a getpwnam.  Used for USER command, since
880  * the data returned must not be clobbered by any other command
881  * (e.g., globbing).
882  */
883 static struct passwd *
884 sgetpwnam(char *name)
885 {
886 	static struct passwd save;
887 	struct passwd *p;
888 
889 	if ((p = getpwnam(name)) == NULL)
890 		return (p);
891 	if (save.pw_name) {
892 		free(save.pw_name);
893 		free(save.pw_passwd);
894 		free(save.pw_gecos);
895 		free(save.pw_dir);
896 		free(save.pw_shell);
897 	}
898 	save = *p;
899 	save.pw_name = sgetsave(p->pw_name);
900 	save.pw_passwd = sgetsave(p->pw_passwd);
901 	save.pw_gecos = sgetsave(p->pw_gecos);
902 	save.pw_dir = sgetsave(p->pw_dir);
903 	save.pw_shell = sgetsave(p->pw_shell);
904 	return (&save);
905 }
906 
907 static int login_attempts;	/* number of failed login attempts */
908 static int askpasswd;		/* had user command, ask for passwd */
909 static char curname[MAXLOGNAME];	/* current USER name */
910 
911 /*
912  * USER command.
913  * Sets global passwd pointer pw if named account exists and is acceptable;
914  * sets askpasswd if a PASS command is expected.  If logged in previously,
915  * need to reset state.  If name is "ftp" or "anonymous", the name is not in
916  * _PATH_FTPUSERS, and ftp account exists, set guest and pw, then just return.
917  * If account doesn't exist, ask for passwd anyway.  Otherwise, check user
918  * requesting login privileges.  Disallow anyone who does not have a standard
919  * shell as returned by getusershell().  Disallow anyone mentioned in the file
920  * _PATH_FTPUSERS to allow people such as root and uucp to be avoided.
921  */
922 void
923 user(char *name)
924 {
925 	char *cp, *shell;
926 
927 	if (logged_in) {
928 		if (guest) {
929 			reply(530, "Can't change user from guest login.");
930 			return;
931 		} else if (dochroot) {
932 			reply(530, "Can't change user from chroot user.");
933 			return;
934 		}
935 		end_login();
936 	}
937 
938 	guest = 0;
939 	if (strcmp(name, "ftp") == 0 || strcmp(name, "anonymous") == 0) {
940 		if (checkuser(_PATH_FTPUSERS, "ftp", 0) ||
941 		    checkuser(_PATH_FTPUSERS, "anonymous", 0))
942 			reply(530, "User %s access denied.", name);
943 #ifdef VIRTUAL_HOSTING
944 		else if ((pw = sgetpwnam(thishost->anonuser)) != NULL) {
945 #else
946 		else if ((pw = sgetpwnam("ftp")) != NULL) {
947 #endif
948 			guest = 1;
949 			askpasswd = 1;
950 			reply(331,
951 			"Guest login ok, send your email address as password.");
952 		} else
953 			reply(530, "User %s unknown.", name);
954 		if (!askpasswd && logging)
955 			syslog(LOG_NOTICE,
956 			    "ANONYMOUS FTP LOGIN REFUSED FROM %s", remotehost);
957 		return;
958 	}
959 	if (anon_only != 0) {
960 		reply(530, "Sorry, only anonymous ftp allowed.");
961 		return;
962 	}
963 
964 	if ((pw = sgetpwnam(name))) {
965 		if ((shell = pw->pw_shell) == NULL || *shell == 0)
966 			shell = _PATH_BSHELL;
967 		while ((cp = getusershell()) != NULL)
968 			if (strcmp(cp, shell) == 0)
969 				break;
970 		endusershell();
971 
972 		if (cp == NULL || checkuser(_PATH_FTPUSERS, name, 1)) {
973 			reply(530, "User %s access denied.", name);
974 			if (logging)
975 				syslog(LOG_NOTICE,
976 				    "FTP LOGIN REFUSED FROM %s, %s",
977 				    remotehost, name);
978 			pw = (struct passwd *) NULL;
979 			return;
980 		}
981 	}
982 	if (logging)
983 		strncpy(curname, name, sizeof(curname)-1);
984 
985 	pwok = 0;
986 #ifdef USE_PAM
987 	/* XXX Kluge! The conversation mechanism needs to be fixed. */
988 #endif
989 	if (opiechallenge(&opiedata, name, opieprompt) == 0) {
990 		pwok = (pw != NULL) &&
991 		       opieaccessfile(remotehost) &&
992 		       opiealways(pw->pw_dir);
993 		reply(331, "Response to %s %s for %s.",
994 		      opieprompt, pwok ? "requested" : "required", name);
995 	} else {
996 		pwok = 1;
997 		reply(331, "Password required for %s.", name);
998 	}
999 	askpasswd = 1;
1000 	/*
1001 	 * Delay before reading passwd after first failed
1002 	 * attempt to slow down passwd-guessing programs.
1003 	 */
1004 	if (login_attempts)
1005 		sleep((unsigned) login_attempts);
1006 }
1007 
1008 /*
1009  * Check if a user is in the file "fname"
1010  */
1011 static int
1012 checkuser(char *fname, char *name, int pwset)
1013 {
1014 	FILE *fd;
1015 	int found = 0;
1016 	char *p, line[BUFSIZ];
1017 
1018 	if ((fd = fopen(fname, "r")) != NULL) {
1019 		while (!found && fgets(line, sizeof(line), fd) != NULL)
1020 			if ((p = strchr(line, '\n')) != NULL) {
1021 				*p = '\0';
1022 				if (line[0] == '#')
1023 					continue;
1024 				/*
1025 				 * if first chr is '@', check group membership
1026 				 */
1027 				if (line[0] == '@') {
1028 					int i = 0;
1029 					struct group *grp;
1030 
1031 					if ((grp = getgrnam(line+1)) == NULL)
1032 						continue;
1033 					/*
1034 					 * Check user's default group
1035 					 */
1036 					if (pwset && grp->gr_gid == pw->pw_gid)
1037 						found = 1;
1038 					/*
1039 					 * Check supplementary groups
1040 					 */
1041 					while (!found && grp->gr_mem[i])
1042 						found = strcmp(name,
1043 							grp->gr_mem[i++])
1044 							== 0;
1045 				}
1046 				/*
1047 				 * Otherwise, just check for username match
1048 				 */
1049 				else
1050 					found = strcmp(line, name) == 0;
1051 			}
1052 		(void) fclose(fd);
1053 	}
1054 	return (found);
1055 }
1056 
1057 /*
1058  * Terminate login as previous user, if any, resetting state;
1059  * used when USER command is given or login fails.
1060  */
1061 static void
1062 end_login(void)
1063 {
1064 #ifdef USE_PAM
1065 	int e;
1066 #endif
1067 
1068 	(void) seteuid((uid_t)0);
1069 	if (logged_in)
1070 		ftpd_logwtmp(ttyline, "", NULL);
1071 	pw = NULL;
1072 #ifdef	LOGIN_CAP
1073 	setusercontext(NULL, getpwuid(0), (uid_t)0,
1074 		       LOGIN_SETPRIORITY|LOGIN_SETRESOURCES|LOGIN_SETUMASK);
1075 #endif
1076 #ifdef USE_PAM
1077 	if ((e = pam_setcred(pamh, PAM_DELETE_CRED)) != PAM_SUCCESS)
1078 		syslog(LOG_ERR, "pam_setcred: %s", pam_strerror(pamh, e));
1079 	if ((e = pam_close_session(pamh,0)) != PAM_SUCCESS)
1080 		syslog(LOG_ERR, "pam_close_session: %s", pam_strerror(pamh, e));
1081 	if ((e = pam_end(pamh, e)) != PAM_SUCCESS)
1082 		syslog(LOG_ERR, "pam_end: %s", pam_strerror(pamh, e));
1083 	pamh = NULL;
1084 #endif
1085 	logged_in = 0;
1086 	guest = 0;
1087 	dochroot = 0;
1088 }
1089 
1090 #ifdef USE_PAM
1091 
1092 /*
1093  * the following code is stolen from imap-uw PAM authentication module and
1094  * login.c
1095  */
1096 #define COPY_STRING(s) (s ? strdup(s) : NULL)
1097 
1098 struct cred_t {
1099 	const char *uname;		/* user name */
1100 	const char *pass;		/* password */
1101 };
1102 typedef struct cred_t cred_t;
1103 
1104 static int
1105 auth_conv(int num_msg, const struct pam_message **msg,
1106 	  struct pam_response **resp, void *appdata)
1107 {
1108 	int i;
1109 	cred_t *cred = (cred_t *) appdata;
1110 	struct pam_response *reply;
1111 
1112 	reply = calloc(num_msg, sizeof *reply);
1113 	if (reply == NULL)
1114 		return PAM_BUF_ERR;
1115 
1116 	for (i = 0; i < num_msg; i++) {
1117 		switch (msg[i]->msg_style) {
1118 		case PAM_PROMPT_ECHO_ON:	/* assume want user name */
1119 			reply[i].resp_retcode = PAM_SUCCESS;
1120 			reply[i].resp = COPY_STRING(cred->uname);
1121 			/* PAM frees resp. */
1122 			break;
1123 		case PAM_PROMPT_ECHO_OFF:	/* assume want password */
1124 			reply[i].resp_retcode = PAM_SUCCESS;
1125 			reply[i].resp = COPY_STRING(cred->pass);
1126 			/* PAM frees resp. */
1127 			break;
1128 		case PAM_TEXT_INFO:
1129 		case PAM_ERROR_MSG:
1130 			reply[i].resp_retcode = PAM_SUCCESS;
1131 			reply[i].resp = NULL;
1132 			break;
1133 		default:			/* unknown message style */
1134 			free(reply);
1135 			return PAM_CONV_ERR;
1136 		}
1137 	}
1138 
1139 	*resp = reply;
1140 	return PAM_SUCCESS;
1141 }
1142 
1143 /*
1144  * Attempt to authenticate the user using PAM.  Returns 0 if the user is
1145  * authenticated, or 1 if not authenticated.  If some sort of PAM system
1146  * error occurs (e.g., the "/etc/pam.conf" file is missing) then this
1147  * function returns -1.  This can be used as an indication that we should
1148  * fall back to a different authentication mechanism.
1149  */
1150 static int
1151 auth_pam(struct passwd **ppw, const char *pass)
1152 {
1153 	pam_handle_t *pamh = NULL;
1154 	const char *tmpl_user;
1155 	const void *item;
1156 	int rval;
1157 	int e;
1158 	cred_t auth_cred = { (*ppw)->pw_name, pass };
1159 	struct pam_conv conv = { &auth_conv, &auth_cred };
1160 
1161 	e = pam_start("ftpd", (*ppw)->pw_name, &conv, &pamh);
1162 	if (e != PAM_SUCCESS) {
1163 		syslog(LOG_ERR, "pam_start: %s", pam_strerror(pamh, e));
1164 		return -1;
1165 	}
1166 
1167 	e = pam_set_item(pamh, PAM_RHOST, remotehost);
1168 	if (e != PAM_SUCCESS) {
1169 		syslog(LOG_ERR, "pam_set_item(PAM_RHOST): %s",
1170 			pam_strerror(pamh, e));
1171 		return -1;
1172 	}
1173 
1174 	e = pam_authenticate(pamh, 0);
1175 	switch (e) {
1176 	case PAM_SUCCESS:
1177 		/*
1178 		 * With PAM we support the concept of a "template"
1179 		 * user.  The user enters a login name which is
1180 		 * authenticated by PAM, usually via a remote service
1181 		 * such as RADIUS or TACACS+.  If authentication
1182 		 * succeeds, a different but related "template" name
1183 		 * is used for setting the credentials, shell, and
1184 		 * home directory.  The name the user enters need only
1185 		 * exist on the remote authentication server, but the
1186 		 * template name must be present in the local password
1187 		 * database.
1188 		 *
1189 		 * This is supported by two various mechanisms in the
1190 		 * individual modules.  However, from the application's
1191 		 * point of view, the template user is always passed
1192 		 * back as a changed value of the PAM_USER item.
1193 		 */
1194 		if ((e = pam_get_item(pamh, PAM_USER, &item)) ==
1195 		    PAM_SUCCESS) {
1196 			tmpl_user = (const char *) item;
1197 			if (strcmp((*ppw)->pw_name, tmpl_user) != 0)
1198 				*ppw = getpwnam(tmpl_user);
1199 		} else
1200 			syslog(LOG_ERR, "Couldn't get PAM_USER: %s",
1201 			    pam_strerror(pamh, e));
1202 		rval = 0;
1203 		break;
1204 
1205 	case PAM_AUTH_ERR:
1206 	case PAM_USER_UNKNOWN:
1207 	case PAM_MAXTRIES:
1208 		rval = 1;
1209 		break;
1210 
1211 	default:
1212 		syslog(LOG_ERR, "pam_authenticate: %s", pam_strerror(pamh, e));
1213 		rval = -1;
1214 		break;
1215 	}
1216 
1217 	if (rval == 0) {
1218 		e = pam_acct_mgmt(pamh, 0);
1219 		if (e == PAM_NEW_AUTHTOK_REQD) {
1220 			e = pam_chauthtok(pamh, PAM_CHANGE_EXPIRED_AUTHTOK);
1221 			if (e != PAM_SUCCESS) {
1222 				syslog(LOG_ERR, "pam_chauthtok: %s", pam_strerror(pamh, e));
1223 				rval = 1;
1224 			}
1225 		} else if (e != PAM_SUCCESS) {
1226 			rval = 1;
1227 		}
1228 	}
1229 
1230 	if (rval != 0) {
1231 		if ((e = pam_end(pamh, e)) != PAM_SUCCESS) {
1232 			syslog(LOG_ERR, "pam_end: %s", pam_strerror(pamh, e));
1233 		}
1234 		pamh = NULL;
1235 	}
1236 	return rval;
1237 }
1238 
1239 #endif /* USE_PAM */
1240 
1241 void
1242 pass(char *passwd)
1243 {
1244 	int rval;
1245 	FILE *fd;
1246 #ifdef	LOGIN_CAP
1247 	login_cap_t *lc = NULL;
1248 #endif
1249 #ifdef USE_PAM
1250 	int e;
1251 #endif
1252 	char *xpasswd;
1253 
1254 	if (logged_in || askpasswd == 0) {
1255 		reply(503, "Login with USER first.");
1256 		return;
1257 	}
1258 	askpasswd = 0;
1259 	if (!guest) {		/* "ftp" is only account allowed no password */
1260 		if (pw == NULL) {
1261 			rval = 1;	/* failure below */
1262 			goto skip;
1263 		}
1264 #ifdef USE_PAM
1265 		rval = auth_pam(&pw, passwd);
1266 		if (rval >= 0) {
1267 			opieunlock();
1268 			goto skip;
1269 		}
1270 #endif
1271 		if (opieverify(&opiedata, passwd) == 0)
1272 			xpasswd = pw->pw_passwd;
1273 		else if (pwok) {
1274 			xpasswd = crypt(passwd, pw->pw_passwd);
1275 			if (passwd[0] == '\0' && pw->pw_passwd[0] != '\0')
1276 				xpasswd = ":";
1277 		} else {
1278 			rval = 1;
1279 			goto skip;
1280 		}
1281 		rval = strcmp(pw->pw_passwd, xpasswd);
1282 		if (pw->pw_expire && time(NULL) >= pw->pw_expire)
1283 			rval = 1;	/* failure */
1284 skip:
1285 		/*
1286 		 * If rval == 1, the user failed the authentication check
1287 		 * above.  If rval == 0, either PAM or local authentication
1288 		 * succeeded.
1289 		 */
1290 		if (rval) {
1291 			reply(530, "Login incorrect.");
1292 			if (logging)
1293 				syslog(LOG_NOTICE,
1294 				    "FTP LOGIN FAILED FROM %s, %s",
1295 				    remotehost, curname);
1296 			pw = NULL;
1297 			if (login_attempts++ >= 5) {
1298 				syslog(LOG_NOTICE,
1299 				    "repeated login failures from %s",
1300 				    remotehost);
1301 				exit(0);
1302 			}
1303 			return;
1304 		}
1305 	}
1306 	login_attempts = 0;		/* this time successful */
1307 	if (setegid((gid_t)pw->pw_gid) < 0) {
1308 		reply(550, "Can't set gid.");
1309 		return;
1310 	}
1311 	/* May be overridden by login.conf */
1312 	(void) umask(defumask);
1313 #ifdef	LOGIN_CAP
1314 	if ((lc = login_getpwclass(pw)) != NULL) {
1315 		char	remote_ip[MAXHOSTNAMELEN];
1316 
1317 		getnameinfo((struct sockaddr *)&his_addr, his_addr.su_len,
1318 			remote_ip, sizeof(remote_ip) - 1, NULL, 0,
1319 			NI_NUMERICHOST|NI_WITHSCOPEID);
1320 		remote_ip[sizeof(remote_ip) - 1] = 0;
1321 		if (!auth_hostok(lc, remotehost, remote_ip)) {
1322 			syslog(LOG_INFO|LOG_AUTH,
1323 			    "FTP LOGIN FAILED (HOST) as %s: permission denied.",
1324 			    pw->pw_name);
1325 			reply(530, "Permission denied.\n");
1326 			pw = NULL;
1327 			return;
1328 		}
1329 		if (!auth_timeok(lc, time(NULL))) {
1330 			reply(530, "Login not available right now.\n");
1331 			pw = NULL;
1332 			return;
1333 		}
1334 	}
1335 	setusercontext(lc, pw, (uid_t)0,
1336 		LOGIN_SETLOGIN|LOGIN_SETGROUP|LOGIN_SETPRIORITY|
1337 		LOGIN_SETRESOURCES|LOGIN_SETUMASK);
1338 #else
1339 	setlogin(pw->pw_name);
1340 	(void) initgroups(pw->pw_name, pw->pw_gid);
1341 #endif
1342 
1343 #ifdef USE_PAM
1344 	if (pamh) {
1345 		if ((e = pam_open_session(pamh, 0)) != PAM_SUCCESS) {
1346 			syslog(LOG_ERR, "pam_open_session: %s", pam_strerror(pamh, e));
1347 		} else if ((e = pam_setcred(pamh, PAM_ESTABLISH_CRED)) != PAM_SUCCESS) {
1348 			syslog(LOG_ERR, "pam_setcred: %s", pam_strerror(pamh, e));
1349 		}
1350 	}
1351 #endif
1352 
1353 	/* open wtmp before chroot */
1354 	ftpd_logwtmp(ttyline, pw->pw_name, (struct sockaddr *)&his_addr);
1355 	logged_in = 1;
1356 
1357 	if (guest && stats && statfd < 0)
1358 #ifdef VIRTUAL_HOSTING
1359 		if ((statfd = open(thishost->statfile, O_WRONLY|O_APPEND)) < 0)
1360 #else
1361 		if ((statfd = open(_PATH_FTPDSTATFILE, O_WRONLY|O_APPEND)) < 0)
1362 #endif
1363 			stats = 0;
1364 
1365 	dochroot =
1366 #ifdef	LOGIN_CAP	/* Allow login.conf configuration as well */
1367 		login_getcapbool(lc, "ftp-chroot", 0) ||
1368 #endif
1369 		checkuser(_PATH_FTPCHROOT, pw->pw_name, 1);
1370 	if (guest) {
1371 		/*
1372 		 * We MUST do a chdir() after the chroot. Otherwise
1373 		 * the old current directory will be accessible as "."
1374 		 * outside the new root!
1375 		 */
1376 		if (chroot(pw->pw_dir) < 0 || chdir("/") < 0) {
1377 			reply(550, "Can't set guest privileges.");
1378 			goto bad;
1379 		}
1380 	} else if (dochroot) {
1381 		if (chroot(pw->pw_dir) < 0 || chdir("/") < 0) {
1382 			reply(550, "Can't change root.");
1383 			goto bad;
1384 		}
1385 	} else if (chdir(pw->pw_dir) < 0) {
1386 		if (chdir("/") < 0) {
1387 			reply(530, "User %s: can't change directory to %s.",
1388 			    pw->pw_name, pw->pw_dir);
1389 			goto bad;
1390 		} else
1391 			lreply(230, "No directory! Logging in with home=/");
1392 	}
1393 	if (seteuid((uid_t)pw->pw_uid) < 0) {
1394 		reply(550, "Can't set uid.");
1395 		goto bad;
1396 	}
1397 
1398 	/*
1399 	 * Display a login message, if it exists.
1400 	 * N.B. reply(230,) must follow the message.
1401 	 */
1402 #ifdef VIRTUAL_HOSTING
1403 	if ((fd = fopen(thishost->loginmsg, "r")) != NULL) {
1404 #else
1405 	if ((fd = fopen(_PATH_FTPLOGINMESG, "r")) != NULL) {
1406 #endif
1407 		char *cp, line[LINE_MAX];
1408 
1409 		while (fgets(line, sizeof(line), fd) != NULL) {
1410 			if ((cp = strchr(line, '\n')) != NULL)
1411 				*cp = '\0';
1412 			lreply(230, "%s", line);
1413 		}
1414 		(void) fflush(stdout);
1415 		(void) fclose(fd);
1416 	}
1417 	if (guest) {
1418 		if (ident != NULL)
1419 			free(ident);
1420 		ident = strdup(passwd);
1421 		if (ident == NULL)
1422 			fatalerror("Ran out of memory.");
1423 
1424 		reply(230, "Guest login ok, access restrictions apply.");
1425 #ifdef SETPROCTITLE
1426 #ifdef VIRTUAL_HOSTING
1427 		if (thishost != firsthost)
1428 			snprintf(proctitle, sizeof(proctitle),
1429 				 "%s: anonymous(%s)/%s", remotehost, hostname,
1430 				 passwd);
1431 		else
1432 #endif
1433 			snprintf(proctitle, sizeof(proctitle),
1434 				 "%s: anonymous/%s", remotehost, passwd);
1435 		setproctitle("%s", proctitle);
1436 #endif /* SETPROCTITLE */
1437 		if (logging)
1438 			syslog(LOG_INFO, "ANONYMOUS FTP LOGIN FROM %s, %s",
1439 			    remotehost, passwd);
1440 	} else {
1441 		if (dochroot)
1442 			reply(230, "User %s logged in, "
1443 				   "access restrictions apply.", pw->pw_name);
1444 		else
1445 			reply(230, "User %s logged in.", pw->pw_name);
1446 
1447 #ifdef SETPROCTITLE
1448 		snprintf(proctitle, sizeof(proctitle),
1449 			 "%s: user/%s", remotehost, pw->pw_name);
1450 		setproctitle("%s", proctitle);
1451 #endif /* SETPROCTITLE */
1452 		if (logging)
1453 			syslog(LOG_INFO, "FTP LOGIN FROM %s as %s",
1454 			    remotehost, pw->pw_name);
1455 	}
1456 #ifdef	LOGIN_CAP
1457 	login_close(lc);
1458 #endif
1459 	return;
1460 bad:
1461 	/* Forget all about it... */
1462 #ifdef	LOGIN_CAP
1463 	login_close(lc);
1464 #endif
1465 	end_login();
1466 }
1467 
1468 void
1469 retrieve(char *cmd, char *name)
1470 {
1471 	FILE *fin, *dout;
1472 	struct stat st;
1473 	int (*closefunc)(FILE *);
1474 	time_t start;
1475 
1476 	if (cmd == 0) {
1477 		fin = fopen(name, "r"), closefunc = fclose;
1478 		st.st_size = 0;
1479 	} else {
1480 		char line[BUFSIZ];
1481 
1482 		(void) snprintf(line, sizeof(line), cmd, name), name = line;
1483 		fin = ftpd_popen(line, "r"), closefunc = ftpd_pclose;
1484 		st.st_size = -1;
1485 		st.st_blksize = BUFSIZ;
1486 	}
1487 	if (fin == NULL) {
1488 		if (errno != 0) {
1489 			perror_reply(550, name);
1490 			if (cmd == 0) {
1491 				LOGCMD("get", name);
1492 			}
1493 		}
1494 		return;
1495 	}
1496 	byte_count = -1;
1497 	if (cmd == 0 && (fstat(fileno(fin), &st) < 0 || !S_ISREG(st.st_mode))) {
1498 		reply(550, "%s: not a plain file.", name);
1499 		goto done;
1500 	}
1501 	if (restart_point) {
1502 		if (type == TYPE_A) {
1503 			off_t i, n;
1504 			int c;
1505 
1506 			n = restart_point;
1507 			i = 0;
1508 			while (i++ < n) {
1509 				if ((c=getc(fin)) == EOF) {
1510 					perror_reply(550, name);
1511 					goto done;
1512 				}
1513 				if (c == '\n')
1514 					i++;
1515 			}
1516 		} else if (lseek(fileno(fin), restart_point, L_SET) < 0) {
1517 			perror_reply(550, name);
1518 			goto done;
1519 		}
1520 	}
1521 	dout = dataconn(name, st.st_size, "w");
1522 	if (dout == NULL)
1523 		goto done;
1524 	time(&start);
1525 	send_data(fin, dout, st.st_blksize, st.st_size,
1526 		  restart_point == 0 && cmd == 0 && S_ISREG(st.st_mode));
1527 	if (cmd == 0 && guest && stats)
1528 		logxfer(name, st.st_size, start);
1529 	(void) fclose(dout);
1530 	data = -1;
1531 	pdata = -1;
1532 done:
1533 	if (cmd == 0)
1534 		LOGBYTES("get", name, byte_count);
1535 	(*closefunc)(fin);
1536 }
1537 
1538 void
1539 store(char *name, char *mode, int unique)
1540 {
1541 	FILE *fout, *din;
1542 	struct stat st;
1543 	int (*closefunc)(FILE *);
1544 
1545 	if ((unique || guest) && stat(name, &st) == 0 &&
1546 	    (name = gunique(name)) == NULL) {
1547 		LOGCMD(*mode == 'w' ? "put" : "append", name);
1548 		return;
1549 	}
1550 
1551 	if (restart_point)
1552 		mode = "r+";
1553 	fout = fopen(name, mode);
1554 	closefunc = fclose;
1555 	if (fout == NULL) {
1556 		perror_reply(553, name);
1557 		LOGCMD(*mode == 'w' ? "put" : "append", name);
1558 		return;
1559 	}
1560 	byte_count = -1;
1561 	if (restart_point) {
1562 		if (type == TYPE_A) {
1563 			off_t i, n;
1564 			int c;
1565 
1566 			n = restart_point;
1567 			i = 0;
1568 			while (i++ < n) {
1569 				if ((c=getc(fout)) == EOF) {
1570 					perror_reply(550, name);
1571 					goto done;
1572 				}
1573 				if (c == '\n')
1574 					i++;
1575 			}
1576 			/*
1577 			 * We must do this seek to "current" position
1578 			 * because we are changing from reading to
1579 			 * writing.
1580 			 */
1581 			if (fseeko(fout, (off_t)0, SEEK_CUR) < 0) {
1582 				perror_reply(550, name);
1583 				goto done;
1584 			}
1585 		} else if (lseek(fileno(fout), restart_point, L_SET) < 0) {
1586 			perror_reply(550, name);
1587 			goto done;
1588 		}
1589 	}
1590 	din = dataconn(name, (off_t)-1, "r");
1591 	if (din == NULL)
1592 		goto done;
1593 	if (receive_data(din, fout) == 0) {
1594 		if (unique)
1595 			reply(226, "Transfer complete (unique file name:%s).",
1596 			    name);
1597 		else
1598 			reply(226, "Transfer complete.");
1599 	}
1600 	(void) fclose(din);
1601 	data = -1;
1602 	pdata = -1;
1603 done:
1604 	LOGBYTES(*mode == 'w' ? "put" : "append", name, byte_count);
1605 	(*closefunc)(fout);
1606 }
1607 
1608 static FILE *
1609 getdatasock(char *mode)
1610 {
1611 	int on = 1, s, t, tries;
1612 
1613 	if (data >= 0)
1614 		return (fdopen(data, mode));
1615 	(void) seteuid((uid_t)0);
1616 
1617 	s = socket(data_dest.su_family, SOCK_STREAM, 0);
1618 	if (s < 0)
1619 		goto bad;
1620 	if (setsockopt(s, SOL_SOCKET, SO_REUSEADDR,
1621 	    (char *) &on, sizeof(on)) < 0)
1622 		goto bad;
1623 	/* anchor socket to avoid multi-homing problems */
1624 	data_source = ctrl_addr;
1625 	data_source.su_port = htons(20); /* ftp-data port */
1626 	for (tries = 1; ; tries++) {
1627 		if (bind(s, (struct sockaddr *)&data_source,
1628 		    data_source.su_len) >= 0)
1629 			break;
1630 		if (errno != EADDRINUSE || tries > 10)
1631 			goto bad;
1632 		sleep(tries);
1633 	}
1634 	(void) seteuid((uid_t)pw->pw_uid);
1635 #ifdef IP_TOS
1636 	if (data_source.su_family == AF_INET)
1637       {
1638 	on = IPTOS_THROUGHPUT;
1639 	if (setsockopt(s, IPPROTO_IP, IP_TOS, (char *)&on, sizeof(int)) < 0)
1640 		syslog(LOG_WARNING, "setsockopt (IP_TOS): %m");
1641       }
1642 #endif
1643 #ifdef TCP_NOPUSH
1644 	/*
1645 	 * Turn off push flag to keep sender TCP from sending short packets
1646 	 * at the boundaries of each write().  Should probably do a SO_SNDBUF
1647 	 * to set the send buffer size as well, but that may not be desirable
1648 	 * in heavy-load situations.
1649 	 */
1650 	on = 1;
1651 	if (setsockopt(s, IPPROTO_TCP, TCP_NOPUSH, (char *)&on, sizeof on) < 0)
1652 		syslog(LOG_WARNING, "setsockopt (TCP_NOPUSH): %m");
1653 #endif
1654 #ifdef SO_SNDBUF
1655 	on = 65536;
1656 	if (setsockopt(s, SOL_SOCKET, SO_SNDBUF, (char *)&on, sizeof on) < 0)
1657 		syslog(LOG_WARNING, "setsockopt (SO_SNDBUF): %m");
1658 #endif
1659 
1660 	return (fdopen(s, mode));
1661 bad:
1662 	/* Return the real value of errno (close may change it) */
1663 	t = errno;
1664 	(void) seteuid((uid_t)pw->pw_uid);
1665 	(void) close(s);
1666 	errno = t;
1667 	return (NULL);
1668 }
1669 
1670 static FILE *
1671 dataconn(char *name, off_t size, char *mode)
1672 {
1673 	char sizebuf[32];
1674 	FILE *file;
1675 	int retry = 0, tos;
1676 
1677 	file_size = size;
1678 	byte_count = 0;
1679 	if (size != (off_t) -1)
1680 		(void) snprintf(sizebuf, sizeof(sizebuf), " (%qd bytes)", size);
1681 	else
1682 		*sizebuf = '\0';
1683 	if (pdata >= 0) {
1684 		union sockunion from;
1685 		int flags;
1686 		int s, fromlen = ctrl_addr.su_len;
1687 		struct timeval timeout;
1688 		fd_set set;
1689 
1690 		FD_ZERO(&set);
1691 		FD_SET(pdata, &set);
1692 
1693 		timeout.tv_usec = 0;
1694 		timeout.tv_sec = 120;
1695 
1696 		/*
1697 		 * Granted a socket is in the blocking I/O mode,
1698 		 * accept() will block after a successful select()
1699 		 * if the selected connection dies in between.
1700 		 * Therefore set the non-blocking I/O flag here.
1701 		 */
1702 		if ((flags = fcntl(pdata, F_GETFL, 0)) == -1 ||
1703 		    fcntl(pdata, F_SETFL, flags | O_NONBLOCK) == -1)
1704 			goto pdata_err;
1705 		if (select(pdata+1, &set, (fd_set *) 0, (fd_set *) 0, &timeout) <= 0 ||
1706 		    (s = accept(pdata, (struct sockaddr *) &from, &fromlen)) < 0)
1707 			goto pdata_err;
1708 		(void) close(pdata);
1709 		pdata = s;
1710 		/*
1711 		 * Unset the blocking I/O flag on the child socket
1712 		 * again so stdio can work on it.
1713 		 */
1714 		if ((flags = fcntl(pdata, F_GETFL, 0)) == -1 ||
1715 		    fcntl(pdata, F_SETFL, flags & ~O_NONBLOCK) == -1)
1716 			goto pdata_err;
1717 #ifdef IP_TOS
1718 		if (from.su_family == AF_INET)
1719 	      {
1720 		tos = IPTOS_THROUGHPUT;
1721 		(void) setsockopt(s, IPPROTO_IP, IP_TOS, (char *)&tos,
1722 		    sizeof(int));
1723 	      }
1724 #endif
1725 		reply(150, "Opening %s mode data connection for '%s'%s.",
1726 		     type == TYPE_A ? "ASCII" : "BINARY", name, sizebuf);
1727 		return (fdopen(pdata, mode));
1728 pdata_err:
1729 		reply(425, "Can't open data connection.");
1730 		(void) close(pdata);
1731 		pdata = -1;
1732 		return (NULL);
1733 	}
1734 	if (data >= 0) {
1735 		reply(125, "Using existing data connection for '%s'%s.",
1736 		    name, sizebuf);
1737 		usedefault = 1;
1738 		return (fdopen(data, mode));
1739 	}
1740 	if (usedefault)
1741 		data_dest = his_addr;
1742 	usedefault = 1;
1743 	file = getdatasock(mode);
1744 	if (file == NULL) {
1745 		char hostbuf[BUFSIZ], portbuf[BUFSIZ];
1746 		getnameinfo((struct sockaddr *)&data_source,
1747 			data_source.su_len, hostbuf, sizeof(hostbuf) - 1,
1748 			portbuf, sizeof(portbuf),
1749 			NI_NUMERICHOST|NI_NUMERICSERV|NI_WITHSCOPEID);
1750 		reply(425, "Can't create data socket (%s,%s): %s.",
1751 			hostbuf, portbuf, strerror(errno));
1752 		return (NULL);
1753 	}
1754 	data = fileno(file);
1755 	while (connect(data, (struct sockaddr *)&data_dest,
1756 	    data_dest.su_len) < 0) {
1757 		if (errno == EADDRINUSE && retry < swaitmax) {
1758 			sleep((unsigned) swaitint);
1759 			retry += swaitint;
1760 			continue;
1761 		}
1762 		perror_reply(425, "Can't build data connection");
1763 		(void) fclose(file);
1764 		data = -1;
1765 		return (NULL);
1766 	}
1767 	reply(150, "Opening %s mode data connection for '%s'%s.",
1768 	     type == TYPE_A ? "ASCII" : "BINARY", name, sizebuf);
1769 	return (file);
1770 }
1771 
1772 /*
1773  * Tranfer the contents of "instr" to "outstr" peer using the appropriate
1774  * encapsulation of the data subject to Mode, Structure, and Type.
1775  *
1776  * NB: Form isn't handled.
1777  */
1778 static int
1779 send_data(FILE *instr, FILE *outstr, off_t blksize, off_t filesize, int isreg)
1780 {
1781 	int c, filefd, netfd;
1782 	char *buf;
1783 	off_t cnt;
1784 
1785 	transflag++;
1786 	switch (type) {
1787 
1788 	case TYPE_A:
1789 		while ((c = getc(instr)) != EOF) {
1790 			if (recvurg)
1791 				goto got_oob;
1792 			byte_count++;
1793 			if (c == '\n') {
1794 				if (ferror(outstr))
1795 					goto data_err;
1796 				(void) putc('\r', outstr);
1797 			}
1798 			(void) putc(c, outstr);
1799 		}
1800 		if (recvurg)
1801 			goto got_oob;
1802 		fflush(outstr);
1803 		transflag = 0;
1804 		if (ferror(instr))
1805 			goto file_err;
1806 		if (ferror(outstr))
1807 			goto data_err;
1808 		reply(226, "Transfer complete.");
1809 		return (0);
1810 
1811 	case TYPE_I:
1812 	case TYPE_L:
1813 		/*
1814 		 * isreg is only set if we are not doing restart and we
1815 		 * are sending a regular file
1816 		 */
1817 		netfd = fileno(outstr);
1818 		filefd = fileno(instr);
1819 
1820 		if (isreg) {
1821 
1822 			off_t offset;
1823 			int err;
1824 
1825 			err = cnt = offset = 0;
1826 
1827 			while (err != -1 && filesize > 0) {
1828 				err = sendfile(filefd, netfd, offset, 0,
1829 					(struct sf_hdtr *) NULL, &cnt, 0);
1830 				if (recvurg)
1831 					goto got_oob;
1832 				byte_count += cnt;
1833 				offset += cnt;
1834 				filesize -= cnt;
1835 
1836 				if (err == -1) {
1837 					if (!cnt)
1838 						goto oldway;
1839 
1840 					goto data_err;
1841 				}
1842 			}
1843 
1844 			reply(226, "Transfer complete.");
1845 			return (0);
1846 		}
1847 
1848 oldway:
1849 		if ((buf = malloc((u_int)blksize)) == NULL) {
1850 			transflag = 0;
1851 			perror_reply(451, "Local resource failure: malloc");
1852 			return (-1);
1853 		}
1854 
1855 		while ((cnt = read(filefd, buf, (u_int)blksize)) > 0 &&
1856 		    write(netfd, buf, cnt) == cnt)
1857 			byte_count += cnt;
1858 		transflag = 0;
1859 		(void)free(buf);
1860 		if (cnt != 0) {
1861 			if (cnt < 0)
1862 				goto file_err;
1863 			goto data_err;
1864 		}
1865 		reply(226, "Transfer complete.");
1866 		return (0);
1867 	default:
1868 		transflag = 0;
1869 		reply(550, "Unimplemented TYPE %d in send_data", type);
1870 		return (-1);
1871 	}
1872 
1873 data_err:
1874 	transflag = 0;
1875 	perror_reply(426, "Data connection");
1876 	return (-1);
1877 
1878 file_err:
1879 	transflag = 0;
1880 	perror_reply(551, "Error on input file");
1881 	return (-1);
1882 
1883 got_oob:
1884 	myoob();
1885 	recvurg = 0;
1886 	transflag = 0;
1887 	return (-1);
1888 }
1889 
1890 /*
1891  * Transfer data from peer to "outstr" using the appropriate encapulation of
1892  * the data subject to Mode, Structure, and Type.
1893  *
1894  * N.B.: Form isn't handled.
1895  */
1896 static int
1897 receive_data(FILE *instr, FILE *outstr)
1898 {
1899 	int c;
1900 	int cnt, bare_lfs;
1901 	char buf[BUFSIZ];
1902 
1903 	transflag++;
1904 	bare_lfs = 0;
1905 
1906 	switch (type) {
1907 
1908 	case TYPE_I:
1909 	case TYPE_L:
1910 		while ((cnt = read(fileno(instr), buf, sizeof(buf))) > 0) {
1911 			if (recvurg)
1912 				goto got_oob;
1913 			if (write(fileno(outstr), buf, cnt) != cnt)
1914 				goto file_err;
1915 			byte_count += cnt;
1916 		}
1917 		if (recvurg)
1918 			goto got_oob;
1919 		if (cnt < 0)
1920 			goto data_err;
1921 		transflag = 0;
1922 		return (0);
1923 
1924 	case TYPE_E:
1925 		reply(553, "TYPE E not implemented.");
1926 		transflag = 0;
1927 		return (-1);
1928 
1929 	case TYPE_A:
1930 		while ((c = getc(instr)) != EOF) {
1931 			if (recvurg)
1932 				goto got_oob;
1933 			byte_count++;
1934 			if (c == '\n')
1935 				bare_lfs++;
1936 			while (c == '\r') {
1937 				if (ferror(outstr))
1938 					goto data_err;
1939 				if ((c = getc(instr)) != '\n') {
1940 					(void) putc ('\r', outstr);
1941 					if (c == '\0' || c == EOF)
1942 						goto contin2;
1943 				}
1944 			}
1945 			(void) putc(c, outstr);
1946 	contin2:	;
1947 		}
1948 		if (recvurg)
1949 			goto got_oob;
1950 		fflush(outstr);
1951 		if (ferror(instr))
1952 			goto data_err;
1953 		if (ferror(outstr))
1954 			goto file_err;
1955 		transflag = 0;
1956 		if (bare_lfs) {
1957 			lreply(226,
1958 		"WARNING! %d bare linefeeds received in ASCII mode",
1959 			    bare_lfs);
1960 		(void)printf("   File may not have transferred correctly.\r\n");
1961 		}
1962 		return (0);
1963 	default:
1964 		reply(550, "Unimplemented TYPE %d in receive_data", type);
1965 		transflag = 0;
1966 		return (-1);
1967 	}
1968 
1969 data_err:
1970 	transflag = 0;
1971 	perror_reply(426, "Data Connection");
1972 	return (-1);
1973 
1974 file_err:
1975 	transflag = 0;
1976 	perror_reply(452, "Error writing file");
1977 	return (-1);
1978 
1979 got_oob:
1980 	myoob();
1981 	recvurg = 0;
1982 	transflag = 0;
1983 	return (-1);
1984 }
1985 
1986 void
1987 statfilecmd(char *filename)
1988 {
1989 	FILE *fin;
1990 	int c;
1991 	char line[LINE_MAX];
1992 
1993 	(void)snprintf(line, sizeof(line), _PATH_LS " -lgA %s", filename);
1994 	fin = ftpd_popen(line, "r");
1995 	lreply(211, "status of %s:", filename);
1996 	while ((c = getc(fin)) != EOF) {
1997 		if (c == '\n') {
1998 			if (ferror(stdout)){
1999 				perror_reply(421, "control connection");
2000 				(void) ftpd_pclose(fin);
2001 				dologout(1);
2002 				/* NOTREACHED */
2003 			}
2004 			if (ferror(fin)) {
2005 				perror_reply(551, filename);
2006 				(void) ftpd_pclose(fin);
2007 				return;
2008 			}
2009 			(void) putc('\r', stdout);
2010 		}
2011 		(void) putc(c, stdout);
2012 	}
2013 	(void) ftpd_pclose(fin);
2014 	reply(211, "End of Status");
2015 }
2016 
2017 void
2018 statcmd(void)
2019 {
2020 	union sockunion *su;
2021 	u_char *a, *p;
2022 	char hname[INET6_ADDRSTRLEN];
2023 	int ispassive;
2024 
2025 	lreply(211, "%s FTP server status:", hostname, version);
2026 	printf("     %s\r\n", version);
2027 	printf("     Connected to %s", remotehost);
2028 	if (!getnameinfo((struct sockaddr *)&his_addr, his_addr.su_len,
2029 			 hname, sizeof(hname) - 1, NULL, 0,
2030 			 NI_NUMERICHOST|NI_WITHSCOPEID)) {
2031 		if (strcmp(hname, remotehost) != 0)
2032 			printf(" (%s)", hname);
2033 	}
2034 	printf("\r\n");
2035 	if (logged_in) {
2036 		if (guest)
2037 			printf("     Logged in anonymously\r\n");
2038 		else
2039 			printf("     Logged in as %s\r\n", pw->pw_name);
2040 	} else if (askpasswd)
2041 		printf("     Waiting for password\r\n");
2042 	else
2043 		printf("     Waiting for user name\r\n");
2044 	printf("     TYPE: %s", typenames[type]);
2045 	if (type == TYPE_A || type == TYPE_E)
2046 		printf(", FORM: %s", formnames[form]);
2047 	if (type == TYPE_L)
2048 #if NBBY == 8
2049 		printf(" %d", NBBY);
2050 #else
2051 		printf(" %d", bytesize);	/* need definition! */
2052 #endif
2053 	printf("; STRUcture: %s; transfer MODE: %s\r\n",
2054 	    strunames[stru], modenames[mode]);
2055 	if (data != -1)
2056 		printf("     Data connection open\r\n");
2057 	else if (pdata != -1) {
2058 		ispassive = 1;
2059 		su = &pasv_addr;
2060 		goto printaddr;
2061 	} else if (usedefault == 0) {
2062 		ispassive = 0;
2063 		su = &data_dest;
2064 printaddr:
2065 #define UC(b) (((int) b) & 0xff)
2066 		if (epsvall) {
2067 			printf("     EPSV only mode (EPSV ALL)\r\n");
2068 			goto epsvonly;
2069 		}
2070 
2071 		/* PORT/PASV */
2072 		if (su->su_family == AF_INET) {
2073 			a = (u_char *) &su->su_sin.sin_addr;
2074 			p = (u_char *) &su->su_sin.sin_port;
2075 			printf("     %s (%d,%d,%d,%d,%d,%d)\r\n",
2076 				ispassive ? "PASV" : "PORT",
2077 				UC(a[0]), UC(a[1]), UC(a[2]), UC(a[3]),
2078 				UC(p[0]), UC(p[1]));
2079 		}
2080 
2081 		/* LPRT/LPSV */
2082 	    {
2083 		int alen, af, i;
2084 
2085 		switch (su->su_family) {
2086 		case AF_INET:
2087 			a = (u_char *) &su->su_sin.sin_addr;
2088 			p = (u_char *) &su->su_sin.sin_port;
2089 			alen = sizeof(su->su_sin.sin_addr);
2090 			af = 4;
2091 			break;
2092 		case AF_INET6:
2093 			a = (u_char *) &su->su_sin6.sin6_addr;
2094 			p = (u_char *) &su->su_sin6.sin6_port;
2095 			alen = sizeof(su->su_sin6.sin6_addr);
2096 			af = 6;
2097 			break;
2098 		default:
2099 			af = 0;
2100 			break;
2101 		}
2102 		if (af) {
2103 			printf("     %s (%d,%d,", ispassive ? "LPSV" : "LPRT",
2104 				af, alen);
2105 			for (i = 0; i < alen; i++)
2106 				printf("%d,", UC(a[i]));
2107 			printf("%d,%d,%d)\r\n", 2, UC(p[0]), UC(p[1]));
2108 		}
2109 	    }
2110 
2111 epsvonly:;
2112 		/* EPRT/EPSV */
2113 	    {
2114 		int af;
2115 
2116 		switch (su->su_family) {
2117 		case AF_INET:
2118 			af = 1;
2119 			break;
2120 		case AF_INET6:
2121 			af = 2;
2122 			break;
2123 		default:
2124 			af = 0;
2125 			break;
2126 		}
2127 		if (af) {
2128 			if (!getnameinfo((struct sockaddr *)su, su->su_len,
2129 					hname, sizeof(hname) - 1, NULL, 0,
2130 					NI_NUMERICHOST)) {
2131 				printf("     %s |%d|%s|%d|\r\n",
2132 					ispassive ? "EPSV" : "EPRT",
2133 					af, hname, htons(su->su_port));
2134 			}
2135 		}
2136 	    }
2137 #undef UC
2138 	} else
2139 		printf("     No data connection\r\n");
2140 	reply(211, "End of status");
2141 }
2142 
2143 void
2144 fatalerror(char *s)
2145 {
2146 
2147 	reply(451, "Error in server: %s\n", s);
2148 	reply(221, "Closing connection due to server error.");
2149 	dologout(0);
2150 	/* NOTREACHED */
2151 }
2152 
2153 void
2154 reply(int n, const char *fmt, ...)
2155 {
2156 	va_list ap;
2157 
2158 	va_start(ap, fmt);
2159 	(void)printf("%d ", n);
2160 	(void)vprintf(fmt, ap);
2161 	(void)printf("\r\n");
2162 	(void)fflush(stdout);
2163 	if (ftpdebug) {
2164 		syslog(LOG_DEBUG, "<--- %d ", n);
2165 		vsyslog(LOG_DEBUG, fmt, ap);
2166 	}
2167 }
2168 
2169 void
2170 lreply(int n, const char *fmt, ...)
2171 {
2172 	va_list ap;
2173 
2174 	va_start(ap, fmt);
2175 	(void)printf("%d- ", n);
2176 	(void)vprintf(fmt, ap);
2177 	(void)printf("\r\n");
2178 	(void)fflush(stdout);
2179 	if (ftpdebug) {
2180 		syslog(LOG_DEBUG, "<--- %d- ", n);
2181 		vsyslog(LOG_DEBUG, fmt, ap);
2182 	}
2183 }
2184 
2185 static void
2186 ack(char *s)
2187 {
2188 
2189 	reply(250, "%s command successful.", s);
2190 }
2191 
2192 void
2193 nack(char *s)
2194 {
2195 
2196 	reply(502, "%s command not implemented.", s);
2197 }
2198 
2199 /* ARGSUSED */
2200 void
2201 yyerror(char *s)
2202 {
2203 	char *cp;
2204 
2205 	if ((cp = strchr(cbuf,'\n')))
2206 		*cp = '\0';
2207 	reply(500, "'%s': command not understood.", cbuf);
2208 }
2209 
2210 void
2211 delete(char *name)
2212 {
2213 	struct stat st;
2214 
2215 	LOGCMD("delete", name);
2216 	if (stat(name, &st) < 0) {
2217 		perror_reply(550, name);
2218 		return;
2219 	}
2220 	if ((st.st_mode&S_IFMT) == S_IFDIR) {
2221 		if (rmdir(name) < 0) {
2222 			perror_reply(550, name);
2223 			return;
2224 		}
2225 		goto done;
2226 	}
2227 	if (unlink(name) < 0) {
2228 		perror_reply(550, name);
2229 		return;
2230 	}
2231 done:
2232 	ack("DELE");
2233 }
2234 
2235 void
2236 cwd(char *path)
2237 {
2238 
2239 	if (chdir(path) < 0)
2240 		perror_reply(550, path);
2241 	else
2242 		ack("CWD");
2243 }
2244 
2245 void
2246 makedir(char *name)
2247 {
2248 
2249 	LOGCMD("mkdir", name);
2250 	if (mkdir(name, 0777) < 0)
2251 		perror_reply(550, name);
2252 	else
2253 		reply(257, "MKD command successful.");
2254 }
2255 
2256 void
2257 removedir(char *name)
2258 {
2259 
2260 	LOGCMD("rmdir", name);
2261 	if (rmdir(name) < 0)
2262 		perror_reply(550, name);
2263 	else
2264 		ack("RMD");
2265 }
2266 
2267 void
2268 pwd(void)
2269 {
2270 	char path[MAXPATHLEN + 1];
2271 
2272 	if (getwd(path) == (char *)NULL)
2273 		reply(550, "%s.", path);
2274 	else
2275 		reply(257, "\"%s\" is current directory.", path);
2276 }
2277 
2278 char *
2279 renamefrom(char *name)
2280 {
2281 	struct stat st;
2282 
2283 	if (stat(name, &st) < 0) {
2284 		perror_reply(550, name);
2285 		return ((char *)0);
2286 	}
2287 	reply(350, "File exists, ready for destination name");
2288 	return (name);
2289 }
2290 
2291 void
2292 renamecmd(char *from, char *to)
2293 {
2294 	struct stat st;
2295 
2296 	LOGCMD2("rename", from, to);
2297 
2298 	if (guest && (stat(to, &st) == 0)) {
2299 		reply(550, "%s: permission denied", to);
2300 		return;
2301 	}
2302 
2303 	if (rename(from, to) < 0)
2304 		perror_reply(550, "rename");
2305 	else
2306 		ack("RNTO");
2307 }
2308 
2309 static void
2310 dolog(struct sockaddr *who)
2311 {
2312 	int error;
2313 
2314 	realhostname_sa(remotehost, sizeof(remotehost) - 1, who, who->sa_len);
2315 
2316 #ifdef SETPROCTITLE
2317 #ifdef VIRTUAL_HOSTING
2318 	if (thishost != firsthost)
2319 		snprintf(proctitle, sizeof(proctitle), "%s: connected (to %s)",
2320 			 remotehost, hostname);
2321 	else
2322 #endif
2323 		snprintf(proctitle, sizeof(proctitle), "%s: connected",
2324 			 remotehost);
2325 	setproctitle("%s", proctitle);
2326 #endif /* SETPROCTITLE */
2327 
2328 	if (logging) {
2329 #ifdef VIRTUAL_HOSTING
2330 		if (thishost != firsthost)
2331 			syslog(LOG_INFO, "connection from %s (to %s)",
2332 			       remotehost, hostname);
2333 		else
2334 #endif
2335 		{
2336 			char	who_name[MAXHOSTNAMELEN];
2337 
2338 			error = getnameinfo(who, who->sa_len,
2339 					    who_name, sizeof(who_name) - 1,
2340 					    NULL, 0,
2341 					    NI_NUMERICHOST|NI_WITHSCOPEID);
2342 			syslog(LOG_INFO, "connection from %s (%s)", remotehost,
2343 			       error == 0 ? who_name : "");
2344 		}
2345 	}
2346 }
2347 
2348 /*
2349  * Record logout in wtmp file
2350  * and exit with supplied status.
2351  */
2352 void
2353 dologout(int status)
2354 {
2355 	/*
2356 	 * Prevent reception of SIGURG from resulting in a resumption
2357 	 * back to the main program loop.
2358 	 */
2359 	transflag = 0;
2360 
2361 	if (logged_in) {
2362 		(void) seteuid((uid_t)0);
2363 		ftpd_logwtmp(ttyline, "", NULL);
2364 	}
2365 	/* beware of flushing buffers after a SIGPIPE */
2366 	_exit(status);
2367 }
2368 
2369 static void
2370 sigurg(int signo)
2371 {
2372 
2373 	recvurg = 1;
2374 }
2375 
2376 static void
2377 myoob(void)
2378 {
2379 	char *cp;
2380 
2381 	/* only process if transfer occurring */
2382 	if (!transflag)
2383 		return;
2384 	cp = tmpline;
2385 	if (getline(cp, 7, stdin) == NULL) {
2386 		reply(221, "You could at least say goodbye.");
2387 		dologout(0);
2388 	}
2389 	upper(cp);
2390 	if (strcmp(cp, "ABOR\r\n") == 0) {
2391 		tmpline[0] = '\0';
2392 		reply(426, "Transfer aborted. Data connection closed.");
2393 		reply(226, "Abort successful");
2394 	}
2395 	if (strcmp(cp, "STAT\r\n") == 0) {
2396 		tmpline[0] = '\0';
2397 		if (file_size != (off_t) -1)
2398 			reply(213, "Status: %qd of %qd bytes transferred",
2399 			    byte_count, file_size);
2400 		else
2401 			reply(213, "Status: %qd bytes transferred", byte_count);
2402 	}
2403 }
2404 
2405 /*
2406  * Note: a response of 425 is not mentioned as a possible response to
2407  *	the PASV command in RFC959. However, it has been blessed as
2408  *	a legitimate response by Jon Postel in a telephone conversation
2409  *	with Rick Adams on 25 Jan 89.
2410  */
2411 void
2412 passive(void)
2413 {
2414 	int len;
2415 	char *p, *a;
2416 
2417 	if (pdata >= 0)		/* close old port if one set */
2418 		close(pdata);
2419 
2420 	pdata = socket(ctrl_addr.su_family, SOCK_STREAM, 0);
2421 	if (pdata < 0) {
2422 		perror_reply(425, "Can't open passive connection");
2423 		return;
2424 	}
2425 
2426 	(void) seteuid((uid_t)0);
2427 
2428 #ifdef IP_PORTRANGE
2429 	if (ctrl_addr.su_family == AF_INET) {
2430 	    int on = restricted_data_ports ? IP_PORTRANGE_HIGH
2431 					   : IP_PORTRANGE_DEFAULT;
2432 
2433 	    if (setsockopt(pdata, IPPROTO_IP, IP_PORTRANGE,
2434 			    (char *)&on, sizeof(on)) < 0)
2435 		    goto pasv_error;
2436 	}
2437 #endif
2438 #ifdef IPV6_PORTRANGE
2439 	if (ctrl_addr.su_family == AF_INET6) {
2440 	    int on = restricted_data_ports ? IPV6_PORTRANGE_HIGH
2441 					   : IPV6_PORTRANGE_DEFAULT;
2442 
2443 	    if (setsockopt(pdata, IPPROTO_IPV6, IPV6_PORTRANGE,
2444 			    (char *)&on, sizeof(on)) < 0)
2445 		    goto pasv_error;
2446 	}
2447 #endif
2448 
2449 	pasv_addr = ctrl_addr;
2450 	pasv_addr.su_port = 0;
2451 	if (bind(pdata, (struct sockaddr *)&pasv_addr, pasv_addr.su_len) < 0)
2452 		goto pasv_error;
2453 
2454 	(void) seteuid((uid_t)pw->pw_uid);
2455 
2456 	len = sizeof(pasv_addr);
2457 	if (getsockname(pdata, (struct sockaddr *) &pasv_addr, &len) < 0)
2458 		goto pasv_error;
2459 	if (listen(pdata, 1) < 0)
2460 		goto pasv_error;
2461 	if (pasv_addr.su_family == AF_INET)
2462 		a = (char *) &pasv_addr.su_sin.sin_addr;
2463 	else if (pasv_addr.su_family == AF_INET6 &&
2464 		 IN6_IS_ADDR_V4MAPPED(&pasv_addr.su_sin6.sin6_addr))
2465 		a = (char *) &pasv_addr.su_sin6.sin6_addr.s6_addr[12];
2466 	else
2467 		goto pasv_error;
2468 
2469 	p = (char *) &pasv_addr.su_port;
2470 
2471 #define UC(b) (((int) b) & 0xff)
2472 
2473 	reply(227, "Entering Passive Mode (%d,%d,%d,%d,%d,%d)", UC(a[0]),
2474 		UC(a[1]), UC(a[2]), UC(a[3]), UC(p[0]), UC(p[1]));
2475 	return;
2476 
2477 pasv_error:
2478 	(void) seteuid((uid_t)pw->pw_uid);
2479 	(void) close(pdata);
2480 	pdata = -1;
2481 	perror_reply(425, "Can't open passive connection");
2482 	return;
2483 }
2484 
2485 /*
2486  * Long Passive defined in RFC 1639.
2487  *     228 Entering Long Passive Mode
2488  *         (af, hal, h1, h2, h3,..., pal, p1, p2...)
2489  */
2490 
2491 void
2492 long_passive(char *cmd, int pf)
2493 {
2494 	int len;
2495 	char *p, *a;
2496 
2497 	if (pdata >= 0)		/* close old port if one set */
2498 		close(pdata);
2499 
2500 	if (pf != PF_UNSPEC) {
2501 		if (ctrl_addr.su_family != pf) {
2502 			switch (ctrl_addr.su_family) {
2503 			case AF_INET:
2504 				pf = 1;
2505 				break;
2506 			case AF_INET6:
2507 				pf = 2;
2508 				break;
2509 			default:
2510 				pf = 0;
2511 				break;
2512 			}
2513 			/*
2514 			 * XXX
2515 			 * only EPRT/EPSV ready clients will understand this
2516 			 */
2517 			if (strcmp(cmd, "EPSV") == 0 && pf) {
2518 				reply(522, "Network protocol mismatch, "
2519 					"use (%d)", pf);
2520 			} else
2521 				reply(501, "Network protocol mismatch"); /*XXX*/
2522 
2523 			return;
2524 		}
2525 	}
2526 
2527 	pdata = socket(ctrl_addr.su_family, SOCK_STREAM, 0);
2528 	if (pdata < 0) {
2529 		perror_reply(425, "Can't open passive connection");
2530 		return;
2531 	}
2532 
2533 	(void) seteuid((uid_t)0);
2534 
2535 	pasv_addr = ctrl_addr;
2536 	pasv_addr.su_port = 0;
2537 	len = pasv_addr.su_len;
2538 
2539 #ifdef IP_PORTRANGE
2540 	if (ctrl_addr.su_family == AF_INET) {
2541 	    int on = restricted_data_ports ? IP_PORTRANGE_HIGH
2542 					   : IP_PORTRANGE_DEFAULT;
2543 
2544 	    if (setsockopt(pdata, IPPROTO_IP, IP_PORTRANGE,
2545 			    (char *)&on, sizeof(on)) < 0)
2546 		    goto pasv_error;
2547 	}
2548 #endif
2549 #ifdef IPV6_PORTRANGE
2550 	if (ctrl_addr.su_family == AF_INET6) {
2551 	    int on = restricted_data_ports ? IPV6_PORTRANGE_HIGH
2552 					   : IPV6_PORTRANGE_DEFAULT;
2553 
2554 	    if (setsockopt(pdata, IPPROTO_IPV6, IPV6_PORTRANGE,
2555 			    (char *)&on, sizeof(on)) < 0)
2556 		    goto pasv_error;
2557 	}
2558 #endif
2559 
2560 	if (bind(pdata, (struct sockaddr *)&pasv_addr, len) < 0)
2561 		goto pasv_error;
2562 
2563 	(void) seteuid((uid_t)pw->pw_uid);
2564 
2565 	if (getsockname(pdata, (struct sockaddr *) &pasv_addr, &len) < 0)
2566 		goto pasv_error;
2567 	if (listen(pdata, 1) < 0)
2568 		goto pasv_error;
2569 
2570 #define UC(b) (((int) b) & 0xff)
2571 
2572 	if (strcmp(cmd, "LPSV") == 0) {
2573 		p = (char *)&pasv_addr.su_port;
2574 		switch (pasv_addr.su_family) {
2575 		case AF_INET:
2576 			a = (char *) &pasv_addr.su_sin.sin_addr;
2577 		v4_reply:
2578 			reply(228,
2579 "Entering Long Passive Mode (%d,%d,%d,%d,%d,%d,%d,%d,%d)",
2580 			      4, 4, UC(a[0]), UC(a[1]), UC(a[2]), UC(a[3]),
2581 			      2, UC(p[0]), UC(p[1]));
2582 			return;
2583 		case AF_INET6:
2584 			if (IN6_IS_ADDR_V4MAPPED(&pasv_addr.su_sin6.sin6_addr)) {
2585 				a = (char *) &pasv_addr.su_sin6.sin6_addr.s6_addr[12];
2586 				goto v4_reply;
2587 			}
2588 			a = (char *) &pasv_addr.su_sin6.sin6_addr;
2589 			reply(228,
2590 "Entering Long Passive Mode "
2591 "(%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d)",
2592 			      6, 16, UC(a[0]), UC(a[1]), UC(a[2]), UC(a[3]),
2593 			      UC(a[4]), UC(a[5]), UC(a[6]), UC(a[7]),
2594 			      UC(a[8]), UC(a[9]), UC(a[10]), UC(a[11]),
2595 			      UC(a[12]), UC(a[13]), UC(a[14]), UC(a[15]),
2596 			      2, UC(p[0]), UC(p[1]));
2597 			return;
2598 		}
2599 	} else if (strcmp(cmd, "EPSV") == 0) {
2600 		switch (pasv_addr.su_family) {
2601 		case AF_INET:
2602 		case AF_INET6:
2603 			reply(229, "Entering Extended Passive Mode (|||%d|)",
2604 				ntohs(pasv_addr.su_port));
2605 			return;
2606 		}
2607 	} else {
2608 		/* more proper error code? */
2609 	}
2610 
2611 pasv_error:
2612 	(void) seteuid((uid_t)pw->pw_uid);
2613 	(void) close(pdata);
2614 	pdata = -1;
2615 	perror_reply(425, "Can't open passive connection");
2616 	return;
2617 }
2618 
2619 /*
2620  * Generate unique name for file with basename "local".
2621  * The file named "local" is already known to exist.
2622  * Generates failure reply on error.
2623  */
2624 static char *
2625 gunique(char *local)
2626 {
2627 	static char new[MAXPATHLEN];
2628 	struct stat st;
2629 	int count;
2630 	char *cp;
2631 
2632 	cp = strrchr(local, '/');
2633 	if (cp)
2634 		*cp = '\0';
2635 	if (stat(cp ? local : ".", &st) < 0) {
2636 		perror_reply(553, cp ? local : ".");
2637 		return ((char *) 0);
2638 	}
2639 	if (cp)
2640 		*cp = '/';
2641 	/* -4 is for the .nn<null> we put on the end below */
2642 	(void) snprintf(new, sizeof(new) - 4, "%s", local);
2643 	cp = new + strlen(new);
2644 	*cp++ = '.';
2645 	for (count = 1; count < 100; count++) {
2646 		(void)sprintf(cp, "%d", count);
2647 		if (stat(new, &st) < 0)
2648 			return (new);
2649 	}
2650 	reply(452, "Unique file name cannot be created.");
2651 	return (NULL);
2652 }
2653 
2654 /*
2655  * Format and send reply containing system error number.
2656  */
2657 void
2658 perror_reply(int code, char *string)
2659 {
2660 
2661 	reply(code, "%s: %s.", string, strerror(errno));
2662 }
2663 
2664 static char *onefile[] = {
2665 	"",
2666 	0
2667 };
2668 
2669 void
2670 send_file_list(char *whichf)
2671 {
2672 	struct stat st;
2673 	DIR *dirp = NULL;
2674 	struct dirent *dir;
2675 	FILE *dout = NULL;
2676 	char **dirlist, *dirname;
2677 	int simple = 0;
2678 	int freeglob = 0;
2679 	glob_t gl;
2680 
2681 	if (strpbrk(whichf, "~{[*?") != NULL) {
2682 		int flags = GLOB_BRACE|GLOB_NOCHECK|GLOB_QUOTE|GLOB_TILDE;
2683 
2684 		memset(&gl, 0, sizeof(gl));
2685 		gl.gl_matchc = MAXGLOBARGS;
2686 		flags |= GLOB_LIMIT;
2687 		freeglob = 1;
2688 		if (glob(whichf, flags, 0, &gl)) {
2689 			reply(550, "not found");
2690 			goto out;
2691 		} else if (gl.gl_pathc == 0) {
2692 			errno = ENOENT;
2693 			perror_reply(550, whichf);
2694 			goto out;
2695 		}
2696 		dirlist = gl.gl_pathv;
2697 	} else {
2698 		onefile[0] = whichf;
2699 		dirlist = onefile;
2700 		simple = 1;
2701 	}
2702 
2703 	while ((dirname = *dirlist++)) {
2704 		if (stat(dirname, &st) < 0) {
2705 			/*
2706 			 * If user typed "ls -l", etc, and the client
2707 			 * used NLST, do what the user meant.
2708 			 */
2709 			if (dirname[0] == '-' && *dirlist == NULL &&
2710 			    transflag == 0) {
2711 				retrieve(_PATH_LS " %s", dirname);
2712 				goto out;
2713 			}
2714 			perror_reply(550, whichf);
2715 			if (dout != NULL) {
2716 				(void) fclose(dout);
2717 				transflag = 0;
2718 				data = -1;
2719 				pdata = -1;
2720 			}
2721 			goto out;
2722 		}
2723 
2724 		if (S_ISREG(st.st_mode)) {
2725 			if (dout == NULL) {
2726 				dout = dataconn("file list", (off_t)-1, "w");
2727 				if (dout == NULL)
2728 					goto out;
2729 				transflag++;
2730 			}
2731 			fprintf(dout, "%s%s\n", dirname,
2732 				type == TYPE_A ? "\r" : "");
2733 			byte_count += strlen(dirname) + 1;
2734 			continue;
2735 		} else if (!S_ISDIR(st.st_mode))
2736 			continue;
2737 
2738 		if ((dirp = opendir(dirname)) == NULL)
2739 			continue;
2740 
2741 		while ((dir = readdir(dirp)) != NULL) {
2742 			char nbuf[MAXPATHLEN];
2743 
2744 			if (recvurg) {
2745 				myoob();
2746 				recvurg = 0;
2747 				transflag = 0;
2748 				goto out;
2749 			}
2750 
2751 			if (dir->d_name[0] == '.' && dir->d_namlen == 1)
2752 				continue;
2753 			if (dir->d_name[0] == '.' && dir->d_name[1] == '.' &&
2754 			    dir->d_namlen == 2)
2755 				continue;
2756 
2757 			snprintf(nbuf, sizeof(nbuf),
2758 				"%s/%s", dirname, dir->d_name);
2759 
2760 			/*
2761 			 * We have to do a stat to insure it's
2762 			 * not a directory or special file.
2763 			 */
2764 			if (simple || (stat(nbuf, &st) == 0 &&
2765 			    S_ISREG(st.st_mode))) {
2766 				if (dout == NULL) {
2767 					dout = dataconn("file list", (off_t)-1,
2768 						"w");
2769 					if (dout == NULL)
2770 						goto out;
2771 					transflag++;
2772 				}
2773 				if (nbuf[0] == '.' && nbuf[1] == '/')
2774 					fprintf(dout, "%s%s\n", &nbuf[2],
2775 						type == TYPE_A ? "\r" : "");
2776 				else
2777 					fprintf(dout, "%s%s\n", nbuf,
2778 						type == TYPE_A ? "\r" : "");
2779 				byte_count += strlen(nbuf) + 1;
2780 			}
2781 		}
2782 		(void) closedir(dirp);
2783 	}
2784 
2785 	if (dout == NULL)
2786 		reply(550, "No files found.");
2787 	else if (ferror(dout) != 0)
2788 		perror_reply(550, "Data connection");
2789 	else
2790 		reply(226, "Transfer complete.");
2791 
2792 	transflag = 0;
2793 	if (dout != NULL)
2794 		(void) fclose(dout);
2795 	data = -1;
2796 	pdata = -1;
2797 out:
2798 	if (freeglob) {
2799 		freeglob = 0;
2800 		globfree(&gl);
2801 	}
2802 }
2803 
2804 void
2805 reapchild(int signo)
2806 {
2807 	while (wait3(NULL, WNOHANG, NULL) > 0);
2808 }
2809 
2810 #ifdef OLD_SETPROCTITLE
2811 /*
2812  * Clobber argv so ps will show what we're doing.  (Stolen from sendmail.)
2813  * Warning, since this is usually started from inetd.conf, it often doesn't
2814  * have much of an environment or arglist to overwrite.
2815  */
2816 void
2817 setproctitle(const char *fmt, ...)
2818 {
2819 	int i;
2820 	va_list ap;
2821 	char *p, *bp, ch;
2822 	char buf[LINE_MAX];
2823 
2824 	va_start(ap, fmt);
2825 	(void)vsnprintf(buf, sizeof(buf), fmt, ap);
2826 
2827 	/* make ps print our process name */
2828 	p = Argv[0];
2829 	*p++ = '-';
2830 
2831 	i = strlen(buf);
2832 	if (i > LastArgv - p - 2) {
2833 		i = LastArgv - p - 2;
2834 		buf[i] = '\0';
2835 	}
2836 	bp = buf;
2837 	while (ch = *bp++)
2838 		if (ch != '\n' && ch != '\r')
2839 			*p++ = ch;
2840 	while (p < LastArgv)
2841 		*p++ = ' ';
2842 }
2843 #endif /* OLD_SETPROCTITLE */
2844 
2845 static void
2846 logxfer(char *name, off_t size, time_t start)
2847 {
2848 	char buf[1024];
2849 	char path[MAXPATHLEN + 1];
2850 	time_t now;
2851 
2852 	if (statfd >= 0 && getwd(path) != NULL) {
2853 		time(&now);
2854 		snprintf(buf, sizeof(buf), "%.20s!%s!%s!%s/%s!%qd!%ld\n",
2855 			ctime(&now)+4, ident, remotehost,
2856 			path, name, (long long)size,
2857 			(long)(now - start + (now == start)));
2858 		write(statfd, buf, strlen(buf));
2859 	}
2860 }
2861