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