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