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