xref: /freebsd/libexec/ftpd/ftpd.c (revision 6e8394b8baa7d5d9153ab90de6824bcd19b3b4e1)
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 	"$Id: ftpd.c,v 1.54 1999/04/07 08:27:40 brian Exp $";
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 #include "pathnames.h"
98 #include "extern.h"
99 
100 #if __STDC__
101 #include <stdarg.h>
102 #else
103 #include <varargs.h>
104 #endif
105 
106 #ifdef	INTERNAL_LS
107 static char version[] = "Version 6.00LS";
108 #undef main
109 #else
110 static char version[] = "Version 6.00";
111 #endif
112 
113 extern	off_t restart_point;
114 extern	char cbuf[];
115 
116 struct	sockaddr_in server_addr;
117 struct	sockaddr_in ctrl_addr;
118 struct	sockaddr_in data_source;
119 struct	sockaddr_in data_dest;
120 struct	sockaddr_in his_addr;
121 struct	sockaddr_in pasv_addr;
122 
123 int	daemon_mode;
124 int	data;
125 jmp_buf	errcatch, urgcatch;
126 int	logged_in;
127 struct	passwd *pw;
128 int	debug;
129 int	timeout = 900;    /* timeout after 15 minutes of inactivity */
130 int	maxtimeout = 7200;/* don't allow idle time to be set beyond 2 hours */
131 int	logging;
132 int	restricted_data_ports = 1;
133 int	paranoid = 1;	  /* be extra careful about security */
134 int	anon_only = 0;    /* Only anonymous ftp allowed */
135 int	guest;
136 int	dochroot;
137 int	stats;
138 int	statfd = -1;
139 int	type;
140 int	form;
141 int	stru;			/* avoid C keyword */
142 int	mode;
143 int	usedefault = 1;		/* for data transfers */
144 int	pdata = -1;		/* for passive mode */
145 sig_atomic_t transflag;
146 off_t	file_size;
147 off_t	byte_count;
148 #if !defined(CMASK) || CMASK == 0
149 #undef CMASK
150 #define CMASK 027
151 #endif
152 int	defumask = CMASK;		/* default umask value */
153 char	tmpline[7];
154 char	*hostname;
155 #ifdef VIRTUAL_HOSTING
156 char	*ftpuser;
157 
158 static struct ftphost {
159 	struct ftphost	*next;
160 	struct in_addr	hostaddr;
161 	char		*hostname;
162 	char		*anonuser;
163 	char		*statfile;
164 	char		*welcome;
165 	char		*loginmsg;
166 } *thishost, *firsthost;
167 
168 #endif
169 char	remotehost[MAXHOSTNAMELEN];
170 char	*ident = NULL;
171 
172 static char ttyline[20];
173 char	*tty = ttyline;		/* for klogin */
174 
175 #ifdef KERBEROS
176 int	 klogin __P((struct passwd *, char *, char *, char *));
177 #endif
178 
179 struct	in_addr bind_address;
180 char	*pid_file = NULL;
181 
182 #if defined(KERBEROS)
183 int	notickets = 1;
184 int	noticketsdontcomplain = 1;
185 char	*krbtkfile_env = NULL;
186 #endif
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[20];	/* 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((struct in_addr *));
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_in *));
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 
276 	tzset();		/* in case no timezone database in ~ftp */
277 
278 #ifdef OLD_SETPROCTITLE
279 	/*
280 	 *  Save start and extent of argv for setproctitle.
281 	 */
282 	Argv = argv;
283 	while (*envp)
284 		envp++;
285 	LastArgv = envp[-1] + strlen(envp[-1]);
286 #endif /* OLD_SETPROCTITLE */
287 
288 
289 	bind_address.s_addr = htonl(INADDR_ANY);
290 	while ((ch = getopt(argc, argv, "AdlDSURt:T:u:va:p:")) != -1) {
291 		switch (ch) {
292 		case 'D':
293 			daemon_mode++;
294 			break;
295 
296 		case 'd':
297 			debug++;
298 			break;
299 
300 		case 'l':
301 			logging++;	/* > 1 == extra logging */
302 			break;
303 
304 		case 'R':
305 			paranoid = 0;
306 			break;
307 
308 		case 'S':
309 			stats++;
310 			break;
311 
312 		case 'T':
313 			maxtimeout = atoi(optarg);
314 			if (timeout > maxtimeout)
315 				timeout = maxtimeout;
316 			break;
317 
318 		case 't':
319 			timeout = atoi(optarg);
320 			if (maxtimeout < timeout)
321 				maxtimeout = timeout;
322 			break;
323 
324 		case 'U':
325 			restricted_data_ports = 0;
326 			break;
327 
328 		case 'a':
329 			if (!inet_aton(optarg, &bind_address))
330 				errx(1, "invalid address for -a");
331 			break;
332 
333 		case 'p':
334 			pid_file = optarg;
335 			break;
336 
337 		case 'u':
338 		    {
339 			long val = 0;
340 
341 			val = strtol(optarg, &optarg, 8);
342 			if (*optarg != '\0' || val < 0)
343 				warnx("bad value for -u");
344 			else
345 				defumask = val;
346 			break;
347 		    }
348 		case 'A':
349 			anon_only = 1;
350 			break;
351 
352 		case 'v':
353 			debug = 1;
354 			break;
355 
356 		default:
357 			warnx("unknown flag -%c ignored", optopt);
358 			break;
359 		}
360 	}
361 
362 #ifdef VIRTUAL_HOSTING
363 	inithosts();
364 #endif
365 	(void) freopen(_PATH_DEVNULL, "w", stderr);
366 
367 	/*
368 	 * LOG_NDELAY sets up the logging connection immediately,
369 	 * necessary for anonymous ftp's that chroot and can't do it later.
370 	 */
371 	openlog("ftpd", LOG_PID | LOG_NDELAY, LOG_FTP);
372 
373 	if (daemon_mode) {
374 		int ctl_sock, fd;
375 		struct servent *sv;
376 
377 		/*
378 		 * Detach from parent.
379 		 */
380 		if (daemon(1, 1) < 0) {
381 			syslog(LOG_ERR, "failed to become a daemon");
382 			exit(1);
383 		}
384 		(void) signal(SIGCHLD, reapchild);
385 		/*
386 		 * Get port number for ftp/tcp.
387 		 */
388 		sv = getservbyname("ftp", "tcp");
389 		if (sv == NULL) {
390 			syslog(LOG_ERR, "getservbyname for ftp failed");
391 			exit(1);
392 		}
393 		/*
394 		 * Open a socket, bind it to the FTP port, and start
395 		 * listening.
396 		 */
397 		ctl_sock = socket(AF_INET, SOCK_STREAM, 0);
398 		if (ctl_sock < 0) {
399 			syslog(LOG_ERR, "control socket: %m");
400 			exit(1);
401 		}
402 		if (setsockopt(ctl_sock, SOL_SOCKET, SO_REUSEADDR,
403 		    (char *)&on, sizeof(on)) < 0)
404 			syslog(LOG_ERR, "control setsockopt: %m");;
405 		server_addr.sin_family = AF_INET;
406 		server_addr.sin_addr = bind_address;
407 		server_addr.sin_port = sv->s_port;
408 		if (bind(ctl_sock, (struct sockaddr *)&server_addr, sizeof(server_addr))) {
409 			syslog(LOG_ERR, "control bind: %m");
410 			exit(1);
411 		}
412 		if (listen(ctl_sock, 32) < 0) {
413 			syslog(LOG_ERR, "control listen: %m");
414 			exit(1);
415 		}
416 		/*
417 		 * Atomically write process ID
418 		 */
419 		if (pid_file)
420 		{
421 			int fd;
422 			char buf[20];
423 
424 			fd = open(pid_file, O_CREAT | O_WRONLY | O_TRUNC
425 				| O_NONBLOCK | O_EXLOCK, 0644);
426 			if (fd < 0) {
427 				if (errno == EAGAIN)
428 					errx(1, "%s: file locked", pid_file);
429 				else
430 					err(1, "%s", pid_file);
431 			}
432 			snprintf(buf, sizeof(buf),
433 				"%lu\n", (unsigned long) getpid());
434 			if (write(fd, buf, strlen(buf)) < 0)
435 				err(1, "%s: write", pid_file);
436 			/* Leave the pid file open and locked */
437 		}
438 		/*
439 		 * Loop forever accepting connection requests and forking off
440 		 * children to handle them.
441 		 */
442 		while (1) {
443 			addrlen = sizeof(his_addr);
444 			fd = accept(ctl_sock, (struct sockaddr *)&his_addr, &addrlen);
445 			if (fork() == 0) {
446 				/* child */
447 				(void) dup2(fd, 0);
448 				(void) dup2(fd, 1);
449 				close(ctl_sock);
450 				break;
451 			}
452 			close(fd);
453 		}
454 	} else {
455 		addrlen = sizeof(his_addr);
456 		if (getpeername(0, (struct sockaddr *)&his_addr, &addrlen) < 0) {
457 			syslog(LOG_ERR, "getpeername (%s): %m",argv[0]);
458 			exit(1);
459 		}
460 	}
461 
462 	(void) signal(SIGCHLD, SIG_IGN);
463 	(void) signal(SIGPIPE, lostconn);
464 	if (signal(SIGURG, myoob) == SIG_ERR)
465 		syslog(LOG_ERR, "signal: %m");
466 
467 #ifdef SKEY
468 	strncpy(addr_string, inet_ntoa(his_addr.sin_addr), sizeof(addr_string));
469 #endif
470 	addrlen = sizeof(ctrl_addr);
471 	if (getsockname(0, (struct sockaddr *)&ctrl_addr, &addrlen) < 0) {
472 		syslog(LOG_ERR, "getsockname (%s): %m",argv[0]);
473 		exit(1);
474 	}
475 #ifdef VIRTUAL_HOSTING
476 	/* select our identity from virtual host table */
477 	selecthost(&ctrl_addr.sin_addr);
478 #endif
479 #ifdef IP_TOS
480 	tos = IPTOS_LOWDELAY;
481 	if (setsockopt(0, IPPROTO_IP, IP_TOS, (char *)&tos, sizeof(int)) < 0)
482 		syslog(LOG_WARNING, "setsockopt (IP_TOS): %m");
483 #endif
484 	/*
485 	 * Disable Nagle on the control channel so that we don't have to wait
486 	 * for peer's ACK before issuing our next reply.
487 	 */
488 	if (setsockopt(0, IPPROTO_TCP, TCP_NODELAY, &on, sizeof(on)) < 0)
489 		syslog(LOG_WARNING, "control setsockopt TCP_NODELAY: %m");
490 
491 	data_source.sin_port = htons(ntohs(ctrl_addr.sin_port) - 1);
492 
493 	/* set this here so klogin can use it... */
494 	(void)snprintf(ttyline, sizeof(ttyline), "ftp%d", getpid());
495 
496 	/* Try to handle urgent data inline */
497 #ifdef SO_OOBINLINE
498 	if (setsockopt(0, SOL_SOCKET, SO_OOBINLINE, (char *)&on, sizeof(on)) < 0)
499 		syslog(LOG_ERR, "setsockopt: %m");
500 #endif
501 
502 #ifdef	F_SETOWN
503 	if (fcntl(fileno(stdin), F_SETOWN, getpid()) == -1)
504 		syslog(LOG_ERR, "fcntl F_SETOWN: %m");
505 #endif
506 	dolog(&his_addr);
507 	/*
508 	 * Set up default state
509 	 */
510 	data = -1;
511 	type = TYPE_A;
512 	form = FORM_N;
513 	stru = STRU_F;
514 	mode = MODE_S;
515 	tmpline[0] = '\0';
516 
517 	/* If logins are disabled, print out the message. */
518 	if ((fd = fopen(_PATH_NOLOGIN,"r")) != NULL) {
519 		while (fgets(line, sizeof(line), fd) != NULL) {
520 			if ((cp = strchr(line, '\n')) != NULL)
521 				*cp = '\0';
522 			lreply(530, "%s", line);
523 		}
524 		(void) fflush(stdout);
525 		(void) fclose(fd);
526 		reply(530, "System not available.");
527 		exit(0);
528 	}
529 #ifdef VIRTUAL_HOSTING
530 	if ((fd = fopen(thishost->welcome, "r")) != NULL) {
531 #else
532 	if ((fd = fopen(_PATH_FTPWELCOME, "r")) != NULL) {
533 #endif
534 		while (fgets(line, sizeof(line), fd) != NULL) {
535 			if ((cp = strchr(line, '\n')) != NULL)
536 				*cp = '\0';
537 			lreply(220, "%s", line);
538 		}
539 		(void) fflush(stdout);
540 		(void) fclose(fd);
541 		/* reply(220,) must follow */
542 	}
543 #ifndef VIRTUAL_HOSTING
544 	if ((hostname = malloc(MAXHOSTNAMELEN)) == NULL)
545 		fatal("Ran out of memory.");
546 	(void) gethostname(hostname, MAXHOSTNAMELEN - 1);
547 	hostname[MAXHOSTNAMELEN - 1] = '\0';
548 #endif
549 	reply(220, "%s FTP server (%s) ready.", hostname, version);
550 	(void) setjmp(errcatch);
551 	for (;;)
552 		(void) yyparse();
553 	/* NOTREACHED */
554 }
555 
556 static void
557 lostconn(signo)
558 	int signo;
559 {
560 
561 	if (debug)
562 		syslog(LOG_DEBUG, "lost connection");
563 	dologout(1);
564 }
565 
566 #ifdef VIRTUAL_HOSTING
567 /*
568  * read in virtual host tables (if they exist)
569  */
570 
571 static void
572 inithosts()
573 {
574 	FILE *fp;
575 	char *cp;
576 	struct hostent *hp;
577 	struct ftphost *hrp, *lhrp;
578 	char line[1024];
579 
580 	/*
581 	 * Fill in the default host information
582 	 */
583 	if (gethostname(line, sizeof(line)) < 0)
584 		line[0] = '\0';
585 	if ((hrp = malloc(sizeof(struct ftphost))) == NULL ||
586 	    (hrp->hostname = strdup(line)) == NULL)
587 		fatal("Ran out of memory.");
588 	memset(&hrp->hostaddr, 0, sizeof hrp->hostaddr);
589 	if ((hp = gethostbyname(hrp->hostname)) != NULL)
590 		(void) memcpy(&hrp->hostaddr,
591 			      hp->h_addr_list[0],
592 			      sizeof(hrp->hostaddr));
593 	hrp->statfile = _PATH_FTPDSTATFILE;
594 	hrp->welcome  = _PATH_FTPWELCOME;
595 	hrp->loginmsg = _PATH_FTPLOGINMESG;
596 	hrp->anonuser = "ftp";
597 	hrp->next = NULL;
598 	thishost = firsthost = lhrp = hrp;
599 	if ((fp = fopen(_PATH_FTPHOSTS, "r")) != NULL) {
600 		while (fgets(line, sizeof(line), fp) != NULL) {
601 			int	i;
602 
603 			if ((cp = strchr(line, '\n')) == NULL) {
604 				/* ignore long lines */
605 				while (fgets(line, sizeof(line), fp) != NULL &&
606 					strchr(line, '\n') == NULL)
607 					;
608 				continue;
609 			}
610 			*cp = '\0';
611 			cp = strtok(line, " \t");
612 			/* skip comments and empty lines */
613 			if (cp == NULL || line[0] == '#')
614 				continue;
615 			/* first, try a standard gethostbyname() */
616 			if ((hp = gethostbyname(cp)) == NULL)
617 				continue;
618 			for (hrp = firsthost; hrp != NULL; hrp = hrp->next) {
619 				if (memcmp(&hrp->hostaddr,
620 					   hp->h_addr_list[0],
621 					   sizeof(hrp->hostaddr)) == 0)
622 					break;
623 			}
624 			if (hrp == NULL) {
625 				if ((hrp = malloc(sizeof(struct ftphost))) == NULL)
626 					continue;
627 				/* defaults */
628 				hrp->statfile = _PATH_FTPDSTATFILE;
629 				hrp->welcome  = _PATH_FTPWELCOME;
630 				hrp->loginmsg = _PATH_FTPLOGINMESG;
631 				hrp->anonuser = "ftp";
632 				hrp->next     = NULL;
633 				lhrp->next = hrp;
634 				lhrp = hrp;
635 			}
636 			(void) memcpy(&hrp->hostaddr,
637 				      hp->h_addr_list[0],
638 				      sizeof(hrp->hostaddr));
639 			/*
640 			 * determine hostname to use.
641 			 * force defined name if it is a valid alias
642 			 * otherwise fallback to primary hostname
643 			 */
644 			if ((hp = gethostbyaddr((char*)&hrp->hostaddr,
645 						sizeof(hrp->hostaddr),
646 						AF_INET)) != NULL) {
647 				if (strcmp(cp, hp->h_name) != 0) {
648 					if (hp->h_aliases == NULL)
649 						cp = hp->h_name;
650 					else {
651 						i = 0;
652 						while (hp->h_aliases[i] &&
653 						       strcmp(cp, hp->h_aliases[i]) != 0)
654 							++i;
655 						if (hp->h_aliases[i] == NULL)
656 							cp = hp->h_name;
657 					}
658 				}
659 			}
660 			hrp->hostname = strdup(cp);
661 			/* ok, now we now peel off the rest */
662 			i = 0;
663 			while (i < 4 && (cp = strtok(NULL, " \t")) != NULL) {
664 				if (*cp != '-' && (cp = strdup(cp)) != NULL) {
665 					switch (i) {
666 					case 0:	/* anon user permissions */
667 						hrp->anonuser = cp;
668 						break;
669 					case 1: /* statistics file */
670 						hrp->statfile = cp;
671 						break;
672 					case 2: /* welcome message */
673 						hrp->welcome  = cp;
674 						break;
675 					case 3: /* login message */
676 						hrp->loginmsg = cp;
677 						break;
678 					}
679 				}
680 				++i;
681 			}
682 		}
683 		(void) fclose(fp);
684 	}
685 }
686 
687 static void
688 selecthost(a)
689 	struct in_addr *a;
690 {
691 	struct ftphost	*hrp;
692 
693 	hrp = thishost = firsthost;	/* default */
694 	while (hrp != NULL) {
695 		if (memcmp(a, &hrp->hostaddr, sizeof(hrp->hostaddr)) == 0) {
696 			thishost = hrp;
697 			break;
698 		}
699 		hrp = hrp->next;
700 	}
701 	/* setup static variables as appropriate */
702 	hostname = thishost->hostname;
703 	ftpuser = thishost->anonuser;
704 }
705 #endif
706 
707 /*
708  * Helper function for sgetpwnam().
709  */
710 static char *
711 sgetsave(s)
712 	char *s;
713 {
714 	char *new = malloc((unsigned) strlen(s) + 1);
715 
716 	if (new == NULL) {
717 		perror_reply(421, "Local resource failure: malloc");
718 		dologout(1);
719 		/* NOTREACHED */
720 	}
721 	(void) strcpy(new, s);
722 	return (new);
723 }
724 
725 /*
726  * Save the result of a getpwnam.  Used for USER command, since
727  * the data returned must not be clobbered by any other command
728  * (e.g., globbing).
729  */
730 static struct passwd *
731 sgetpwnam(name)
732 	char *name;
733 {
734 	static struct passwd save;
735 	struct passwd *p;
736 
737 	if ((p = getpwnam(name)) == NULL)
738 		return (p);
739 	if (save.pw_name) {
740 		free(save.pw_name);
741 		free(save.pw_passwd);
742 		free(save.pw_gecos);
743 		free(save.pw_dir);
744 		free(save.pw_shell);
745 	}
746 	save = *p;
747 	save.pw_name = sgetsave(p->pw_name);
748 	save.pw_passwd = sgetsave(p->pw_passwd);
749 	save.pw_gecos = sgetsave(p->pw_gecos);
750 	save.pw_dir = sgetsave(p->pw_dir);
751 	save.pw_shell = sgetsave(p->pw_shell);
752 	return (&save);
753 }
754 
755 static int login_attempts;	/* number of failed login attempts */
756 static int askpasswd;		/* had user command, ask for passwd */
757 static char curname[10];	/* current USER name */
758 
759 /*
760  * USER command.
761  * Sets global passwd pointer pw if named account exists and is acceptable;
762  * sets askpasswd if a PASS command is expected.  If logged in previously,
763  * need to reset state.  If name is "ftp" or "anonymous", the name is not in
764  * _PATH_FTPUSERS, and ftp account exists, set guest and pw, then just return.
765  * If account doesn't exist, ask for passwd anyway.  Otherwise, check user
766  * requesting login privileges.  Disallow anyone who does not have a standard
767  * shell as returned by getusershell().  Disallow anyone mentioned in the file
768  * _PATH_FTPUSERS to allow people such as root and uucp to be avoided.
769  */
770 void
771 user(name)
772 	char *name;
773 {
774 	char *cp, *shell;
775 
776 	if (logged_in) {
777 		if (guest) {
778 			reply(530, "Can't change user from guest login.");
779 			return;
780 		} else if (dochroot) {
781 			reply(530, "Can't change user from chroot user.");
782 			return;
783 		}
784 		end_login();
785 	}
786 
787 	guest = 0;
788 	if (strcmp(name, "ftp") == 0 || strcmp(name, "anonymous") == 0) {
789 		if (checkuser(_PATH_FTPUSERS, "ftp", 0) ||
790 		    checkuser(_PATH_FTPUSERS, "anonymous", 0))
791 			reply(530, "User %s access denied.", name);
792 #ifdef VIRTUAL_HOSTING
793 		else if ((pw = sgetpwnam(thishost->anonuser)) != NULL) {
794 #else
795 		else if ((pw = sgetpwnam("ftp")) != NULL) {
796 #endif
797 			guest = 1;
798 			askpasswd = 1;
799 			reply(331,
800 			"Guest login ok, send your email address as password.");
801 		} else
802 			reply(530, "User %s unknown.", name);
803 		if (!askpasswd && logging)
804 			syslog(LOG_NOTICE,
805 			    "ANONYMOUS FTP LOGIN REFUSED FROM %s", remotehost);
806 		return;
807 	}
808 	if (anon_only != 0) {
809 		reply(530, "Sorry, only anonymous ftp allowed.");
810 		return;
811 	}
812 
813 	if ((pw = sgetpwnam(name))) {
814 		if ((shell = pw->pw_shell) == NULL || *shell == 0)
815 			shell = _PATH_BSHELL;
816 		while ((cp = getusershell()) != NULL)
817 			if (strcmp(cp, shell) == 0)
818 				break;
819 		endusershell();
820 
821 		if (cp == NULL || checkuser(_PATH_FTPUSERS, name, 1)) {
822 			reply(530, "User %s access denied.", name);
823 			if (logging)
824 				syslog(LOG_NOTICE,
825 				    "FTP LOGIN REFUSED FROM %s, %s",
826 				    remotehost, name);
827 			pw = (struct passwd *) NULL;
828 			return;
829 		}
830 	}
831 	if (logging)
832 		strncpy(curname, name, sizeof(curname)-1);
833 #ifdef SKEY
834 	pwok = skeyaccess(name, NULL, remotehost, addr_string);
835 	reply(331, "%s", skey_challenge(name, pw, pwok));
836 #else
837 	reply(331, "Password required for %s.", name);
838 #endif
839 	askpasswd = 1;
840 	/*
841 	 * Delay before reading passwd after first failed
842 	 * attempt to slow down passwd-guessing programs.
843 	 */
844 	if (login_attempts)
845 		sleep((unsigned) login_attempts);
846 }
847 
848 /*
849  * Check if a user is in the file "fname"
850  */
851 static int
852 checkuser(fname, name, pwset)
853 	char *fname;
854 	char *name;
855 	int pwset;
856 {
857 	FILE *fd;
858 	int found = 0;
859 	char *p, line[BUFSIZ];
860 
861 	if ((fd = fopen(fname, "r")) != NULL) {
862 		while (!found && fgets(line, sizeof(line), fd) != NULL)
863 			if ((p = strchr(line, '\n')) != NULL) {
864 				*p = '\0';
865 				if (line[0] == '#')
866 					continue;
867 				/*
868 				 * if first chr is '@', check group membership
869 				 */
870 				if (line[0] == '@') {
871 					int i = 0;
872 					struct group *grp;
873 
874 					if ((grp = getgrnam(line+1)) == NULL)
875 						continue;
876 					/*
877 					 * Check user's default group
878 					 */
879 					if (pwset && grp->gr_gid == pw->pw_gid)
880 						found = 1;
881 					/*
882 					 * Check supplementary groups
883 					 */
884 					while (!found && grp->gr_mem[i])
885 						found = strcmp(name,
886 							grp->gr_mem[i++])
887 							== 0;
888 				}
889 				/*
890 				 * Otherwise, just check for username match
891 				 */
892 				else
893 					found = strcmp(line, name) == 0;
894 			}
895 		(void) fclose(fd);
896 	}
897 	return (found);
898 }
899 
900 /*
901  * Terminate login as previous user, if any, resetting state;
902  * used when USER command is given or login fails.
903  */
904 static void
905 end_login()
906 {
907 
908 	(void) seteuid((uid_t)0);
909 	if (logged_in)
910 		ftpd_logwtmp(ttyline, "", "");
911 	pw = NULL;
912 #ifdef	LOGIN_CAP
913 	setusercontext(NULL, getpwuid(0), (uid_t)0,
914 		       LOGIN_SETPRIORITY|LOGIN_SETRESOURCES|LOGIN_SETUMASK);
915 #endif
916 	logged_in = 0;
917 	guest = 0;
918 	dochroot = 0;
919 }
920 
921 void
922 pass(passwd)
923 	char *passwd;
924 {
925 	int rval;
926 	FILE *fd;
927 #ifdef	LOGIN_CAP
928 	login_cap_t *lc = NULL;
929 #endif
930 
931 	if (logged_in || askpasswd == 0) {
932 		reply(503, "Login with USER first.");
933 		return;
934 	}
935 	askpasswd = 0;
936 	if (!guest) {		/* "ftp" is only account allowed no password */
937 		if (pw == NULL) {
938 			rval = 1;	/* failure below */
939 			goto skip;
940 		}
941 #if defined(KERBEROS)
942 		rval = klogin(pw, "", hostname, passwd);
943 		if (rval == 0)
944 			goto skip;
945 #endif
946 #ifdef SKEY
947 		rval = strcmp(skey_crypt(passwd, pw->pw_passwd, pw, pwok),
948 			      pw->pw_passwd);
949 		pwok = 0;
950 #else
951 		rval = strcmp(crypt(passwd, pw->pw_passwd), pw->pw_passwd);
952 #endif
953 		/* The strcmp does not catch null passwords! */
954 		if (*pw->pw_passwd == '\0' ||
955 		    (pw->pw_expire && time(NULL) >= pw->pw_expire))
956 			rval = 1;	/* failure */
957 skip:
958 		/*
959 		 * If rval == 1, the user failed the authentication check
960 		 * above.  If rval == 0, either Kerberos or local authentication
961 		 * succeeded.
962 		 */
963 		if (rval) {
964 			reply(530, "Login incorrect.");
965 			if (logging)
966 				syslog(LOG_NOTICE,
967 				    "FTP LOGIN FAILED FROM %s, %s",
968 				    remotehost, curname);
969 			pw = NULL;
970 			if (login_attempts++ >= 5) {
971 				syslog(LOG_NOTICE,
972 				    "repeated login failures from %s",
973 				    remotehost);
974 				exit(0);
975 			}
976 			return;
977 		}
978 	}
979 	login_attempts = 0;		/* this time successful */
980 	if (setegid((gid_t)pw->pw_gid) < 0) {
981 		reply(550, "Can't set gid.");
982 		return;
983 	}
984 	/* May be overridden by login.conf */
985 	(void) umask(defumask);
986 #ifdef	LOGIN_CAP
987 	if ((lc = login_getpwclass(pw)) != NULL) {
988 		char	remote_ip[MAXHOSTNAMELEN];
989 
990 		strncpy(remote_ip, inet_ntoa(his_addr.sin_addr),
991 			sizeof(remote_ip) - 1);
992 		remote_ip[sizeof(remote_ip) - 1] = 0;
993 		if (!auth_hostok(lc, remotehost, remote_ip)) {
994 			syslog(LOG_INFO|LOG_AUTH,
995 			    "FTP LOGIN FAILED (HOST) as %s: permission denied.",
996 			    pw->pw_name);
997 			reply(530, "Permission denied.\n");
998 			pw = NULL;
999 			return;
1000 		}
1001 		if (!auth_timeok(lc, time(NULL))) {
1002 			reply(530, "Login not available right now.\n");
1003 			pw = NULL;
1004 			return;
1005 		}
1006 	}
1007 	setusercontext(lc, pw, (uid_t)0,
1008 		LOGIN_SETLOGIN|LOGIN_SETGROUP|LOGIN_SETPRIORITY|
1009 		LOGIN_SETRESOURCES|LOGIN_SETUMASK);
1010 #else
1011 	setlogin(pw->pw_name);
1012 	(void) initgroups(pw->pw_name, pw->pw_gid);
1013 #endif
1014 
1015 	/* open wtmp before chroot */
1016 	ftpd_logwtmp(ttyline, pw->pw_name, remotehost);
1017 	logged_in = 1;
1018 
1019 	if (guest && stats && statfd < 0)
1020 #ifdef VIRTUAL_HOSTING
1021 		if ((statfd = open(thishost->statfile, O_WRONLY|O_APPEND)) < 0)
1022 #else
1023 		if ((statfd = open(_PATH_FTPDSTATFILE, O_WRONLY|O_APPEND)) < 0)
1024 #endif
1025 			stats = 0;
1026 
1027 	dochroot =
1028 #ifdef	LOGIN_CAP	/* Allow login.conf configuration as well */
1029 		login_getcapbool(lc, "ftp-chroot", 0) ||
1030 #endif
1031 		checkuser(_PATH_FTPCHROOT, pw->pw_name, 1);
1032 	if (guest) {
1033 		/*
1034 		 * We MUST do a chdir() after the chroot. Otherwise
1035 		 * the old current directory will be accessible as "."
1036 		 * outside the new root!
1037 		 */
1038 		if (chroot(pw->pw_dir) < 0 || chdir("/") < 0) {
1039 			reply(550, "Can't set guest privileges.");
1040 			goto bad;
1041 		}
1042 	} else if (dochroot) {
1043 		if (chroot(pw->pw_dir) < 0 || chdir("/") < 0) {
1044 			reply(550, "Can't change root.");
1045 			goto bad;
1046 		}
1047 	} else if (chdir(pw->pw_dir) < 0) {
1048 		if (chdir("/") < 0) {
1049 			reply(530, "User %s: can't change directory to %s.",
1050 			    pw->pw_name, pw->pw_dir);
1051 			goto bad;
1052 		} else
1053 			lreply(230, "No directory! Logging in with home=/");
1054 	}
1055 	if (seteuid((uid_t)pw->pw_uid) < 0) {
1056 		reply(550, "Can't set uid.");
1057 		goto bad;
1058 	}
1059 
1060 	/*
1061 	 * Display a login message, if it exists.
1062 	 * N.B. reply(230,) must follow the message.
1063 	 */
1064 #ifdef VIRTUAL_HOSTING
1065 	if ((fd = fopen(thishost->loginmsg, "r")) != NULL) {
1066 #else
1067 	if ((fd = fopen(_PATH_FTPLOGINMESG, "r")) != NULL) {
1068 #endif
1069 		char *cp, line[LINE_MAX];
1070 
1071 		while (fgets(line, sizeof(line), fd) != NULL) {
1072 			if ((cp = strchr(line, '\n')) != NULL)
1073 				*cp = '\0';
1074 			lreply(230, "%s", line);
1075 		}
1076 		(void) fflush(stdout);
1077 		(void) fclose(fd);
1078 	}
1079 	if (guest) {
1080 		if (ident != NULL)
1081 			free(ident);
1082 		ident = strdup(passwd);
1083 		if (ident == NULL)
1084 			fatal("Ran out of memory.");
1085 
1086 		reply(230, "Guest login ok, access restrictions apply.");
1087 #ifdef SETPROCTITLE
1088 #ifdef VIRTUAL_HOSTING
1089 		if (thishost != firsthost)
1090 			snprintf(proctitle, sizeof(proctitle),
1091 				 "%s: anonymous(%s)/%.*s", remotehost, hostname,
1092 				 sizeof(proctitle) - sizeof(remotehost) -
1093 				 sizeof(": anonymous/"), passwd);
1094 		else
1095 #endif
1096 			snprintf(proctitle, sizeof(proctitle),
1097 				 "%s: anonymous/%.*s", remotehost,
1098 				 sizeof(proctitle) - sizeof(remotehost) -
1099 				 sizeof(": anonymous/"), passwd);
1100 		setproctitle("%s", proctitle);
1101 #endif /* SETPROCTITLE */
1102 		if (logging)
1103 			syslog(LOG_INFO, "ANONYMOUS FTP LOGIN FROM %s, %s",
1104 			    remotehost, passwd);
1105 	} else {
1106 	    if (dochroot)
1107 		reply(230, "User %s logged in, access restrictions apply.",
1108 			pw->pw_name);
1109 	    else
1110 		reply(230, "User %s logged in.", pw->pw_name);
1111 
1112 #ifdef SETPROCTITLE
1113 		snprintf(proctitle, sizeof(proctitle),
1114 			 "%s: %s", remotehost, pw->pw_name);
1115 		setproctitle("%s", proctitle);
1116 #endif /* SETPROCTITLE */
1117 		if (logging)
1118 			syslog(LOG_INFO, "FTP LOGIN FROM %s as %s",
1119 			    remotehost, pw->pw_name);
1120 	}
1121 #ifdef	LOGIN_CAP
1122 	login_close(lc);
1123 #endif
1124 	return;
1125 bad:
1126 	/* Forget all about it... */
1127 #ifdef	LOGIN_CAP
1128 	login_close(lc);
1129 #endif
1130 	end_login();
1131 }
1132 
1133 void
1134 retrieve(cmd, name)
1135 	char *cmd, *name;
1136 {
1137 	FILE *fin, *dout;
1138 	struct stat st;
1139 	int (*closefunc) __P((FILE *));
1140 	time_t start;
1141 
1142 	if (cmd == 0) {
1143 		fin = fopen(name, "r"), closefunc = fclose;
1144 		st.st_size = 0;
1145 	} else {
1146 		char line[BUFSIZ];
1147 
1148 		(void) snprintf(line, sizeof(line), cmd, name), name = line;
1149 		fin = ftpd_popen(line, "r"), closefunc = ftpd_pclose;
1150 		st.st_size = -1;
1151 		st.st_blksize = BUFSIZ;
1152 	}
1153 	if (fin == NULL) {
1154 		if (errno != 0) {
1155 			perror_reply(550, name);
1156 			if (cmd == 0) {
1157 				LOGCMD("get", name);
1158 			}
1159 		}
1160 		return;
1161 	}
1162 	byte_count = -1;
1163 	if (cmd == 0 && (fstat(fileno(fin), &st) < 0 || !S_ISREG(st.st_mode))) {
1164 		reply(550, "%s: not a plain file.", name);
1165 		goto done;
1166 	}
1167 	if (restart_point) {
1168 		if (type == TYPE_A) {
1169 			off_t i, n;
1170 			int c;
1171 
1172 			n = restart_point;
1173 			i = 0;
1174 			while (i++ < n) {
1175 				if ((c=getc(fin)) == EOF) {
1176 					perror_reply(550, name);
1177 					goto done;
1178 				}
1179 				if (c == '\n')
1180 					i++;
1181 			}
1182 		} else if (lseek(fileno(fin), restart_point, L_SET) < 0) {
1183 			perror_reply(550, name);
1184 			goto done;
1185 		}
1186 	}
1187 	dout = dataconn(name, st.st_size, "w");
1188 	if (dout == NULL)
1189 		goto done;
1190 	time(&start);
1191 	send_data(fin, dout, st.st_blksize, st.st_size,
1192 		  restart_point == 0 && cmd == 0 && S_ISREG(st.st_mode));
1193 	if (cmd == 0 && guest && stats)
1194 		logxfer(name, st.st_size, start);
1195 	(void) fclose(dout);
1196 	data = -1;
1197 	pdata = -1;
1198 done:
1199 	if (cmd == 0)
1200 		LOGBYTES("get", name, byte_count);
1201 	(*closefunc)(fin);
1202 }
1203 
1204 void
1205 store(name, mode, unique)
1206 	char *name, *mode;
1207 	int unique;
1208 {
1209 	FILE *fout, *din;
1210 	struct stat st;
1211 	int (*closefunc) __P((FILE *));
1212 
1213 	if ((unique || guest) && stat(name, &st) == 0 &&
1214 	    (name = gunique(name)) == NULL) {
1215 		LOGCMD(*mode == 'w' ? "put" : "append", name);
1216 		return;
1217 	}
1218 
1219 	if (restart_point)
1220 		mode = "r+";
1221 	fout = fopen(name, mode);
1222 	closefunc = fclose;
1223 	if (fout == NULL) {
1224 		perror_reply(553, name);
1225 		LOGCMD(*mode == 'w' ? "put" : "append", name);
1226 		return;
1227 	}
1228 	byte_count = -1;
1229 	if (restart_point) {
1230 		if (type == TYPE_A) {
1231 			off_t i, n;
1232 			int c;
1233 
1234 			n = restart_point;
1235 			i = 0;
1236 			while (i++ < n) {
1237 				if ((c=getc(fout)) == EOF) {
1238 					perror_reply(550, name);
1239 					goto done;
1240 				}
1241 				if (c == '\n')
1242 					i++;
1243 			}
1244 			/*
1245 			 * We must do this seek to "current" position
1246 			 * because we are changing from reading to
1247 			 * writing.
1248 			 */
1249 			if (fseek(fout, 0L, L_INCR) < 0) {
1250 				perror_reply(550, name);
1251 				goto done;
1252 			}
1253 		} else if (lseek(fileno(fout), restart_point, L_SET) < 0) {
1254 			perror_reply(550, name);
1255 			goto done;
1256 		}
1257 	}
1258 	din = dataconn(name, (off_t)-1, "r");
1259 	if (din == NULL)
1260 		goto done;
1261 	if (receive_data(din, fout) == 0) {
1262 		if (unique)
1263 			reply(226, "Transfer complete (unique file name:%s).",
1264 			    name);
1265 		else
1266 			reply(226, "Transfer complete.");
1267 	}
1268 	(void) fclose(din);
1269 	data = -1;
1270 	pdata = -1;
1271 done:
1272 	LOGBYTES(*mode == 'w' ? "put" : "append", name, byte_count);
1273 	(*closefunc)(fout);
1274 }
1275 
1276 static FILE *
1277 getdatasock(mode)
1278 	char *mode;
1279 {
1280 	int on = 1, s, t, tries;
1281 
1282 	if (data >= 0)
1283 		return (fdopen(data, mode));
1284 	(void) seteuid((uid_t)0);
1285 	s = socket(AF_INET, SOCK_STREAM, 0);
1286 	if (s < 0)
1287 		goto bad;
1288 	if (setsockopt(s, SOL_SOCKET, SO_REUSEADDR,
1289 	    (char *) &on, sizeof(on)) < 0)
1290 		goto bad;
1291 	/* anchor socket to avoid multi-homing problems */
1292 	data_source.sin_len = sizeof(struct sockaddr_in);
1293 	data_source.sin_family = AF_INET;
1294 	data_source.sin_addr = ctrl_addr.sin_addr;
1295 	for (tries = 1; ; tries++) {
1296 		if (bind(s, (struct sockaddr *)&data_source,
1297 		    sizeof(data_source)) >= 0)
1298 			break;
1299 		if (errno != EADDRINUSE || tries > 10)
1300 			goto bad;
1301 		sleep(tries);
1302 	}
1303 	(void) seteuid((uid_t)pw->pw_uid);
1304 #ifdef IP_TOS
1305 	on = IPTOS_THROUGHPUT;
1306 	if (setsockopt(s, IPPROTO_IP, IP_TOS, (char *)&on, sizeof(int)) < 0)
1307 		syslog(LOG_WARNING, "setsockopt (IP_TOS): %m");
1308 #endif
1309 #ifdef TCP_NOPUSH
1310 	/*
1311 	 * Turn off push flag to keep sender TCP from sending short packets
1312 	 * at the boundaries of each write().  Should probably do a SO_SNDBUF
1313 	 * to set the send buffer size as well, but that may not be desirable
1314 	 * in heavy-load situations.
1315 	 */
1316 	on = 1;
1317 	if (setsockopt(s, IPPROTO_TCP, TCP_NOPUSH, (char *)&on, sizeof on) < 0)
1318 		syslog(LOG_WARNING, "setsockopt (TCP_NOPUSH): %m");
1319 #endif
1320 #ifdef SO_SNDBUF
1321 	on = 65536;
1322 	if (setsockopt(s, SOL_SOCKET, SO_SNDBUF, (char *)&on, sizeof on) < 0)
1323 		syslog(LOG_WARNING, "setsockopt (SO_SNDBUF): %m");
1324 #endif
1325 
1326 	return (fdopen(s, mode));
1327 bad:
1328 	/* Return the real value of errno (close may change it) */
1329 	t = errno;
1330 	(void) seteuid((uid_t)pw->pw_uid);
1331 	(void) close(s);
1332 	errno = t;
1333 	return (NULL);
1334 }
1335 
1336 static FILE *
1337 dataconn(name, size, mode)
1338 	char *name;
1339 	off_t size;
1340 	char *mode;
1341 {
1342 	char sizebuf[32];
1343 	FILE *file;
1344 	int retry = 0, tos;
1345 
1346 	file_size = size;
1347 	byte_count = 0;
1348 	if (size != (off_t) -1)
1349 		(void) snprintf(sizebuf, sizeof(sizebuf), " (%qd bytes)", size);
1350 	else
1351 		*sizebuf = '\0';
1352 	if (pdata >= 0) {
1353 		struct sockaddr_in from;
1354 		int s, fromlen = sizeof(from);
1355 		struct timeval timeout;
1356 		fd_set set;
1357 
1358 		FD_ZERO(&set);
1359 		FD_SET(pdata, &set);
1360 
1361 		timeout.tv_usec = 0;
1362 		timeout.tv_sec = 120;
1363 
1364 		if (select(pdata+1, &set, (fd_set *) 0, (fd_set *) 0, &timeout) == 0 ||
1365 		    (s = accept(pdata, (struct sockaddr *) &from, &fromlen)) < 0) {
1366 			reply(425, "Can't open data connection.");
1367 			(void) close(pdata);
1368 			pdata = -1;
1369 			return (NULL);
1370 		}
1371 		(void) close(pdata);
1372 		pdata = s;
1373 #ifdef IP_TOS
1374 		tos = IPTOS_THROUGHPUT;
1375 		(void) setsockopt(s, IPPROTO_IP, IP_TOS, (char *)&tos,
1376 		    sizeof(int));
1377 #endif
1378 		reply(150, "Opening %s mode data connection for '%s'%s.",
1379 		     type == TYPE_A ? "ASCII" : "BINARY", name, sizebuf);
1380 		return (fdopen(pdata, mode));
1381 	}
1382 	if (data >= 0) {
1383 		reply(125, "Using existing data connection for '%s'%s.",
1384 		    name, sizebuf);
1385 		usedefault = 1;
1386 		return (fdopen(data, mode));
1387 	}
1388 	if (usedefault)
1389 		data_dest = his_addr;
1390 	usedefault = 1;
1391 	file = getdatasock(mode);
1392 	if (file == NULL) {
1393 		reply(425, "Can't create data socket (%s,%d): %s.",
1394 		    inet_ntoa(data_source.sin_addr),
1395 		    ntohs(data_source.sin_port), strerror(errno));
1396 		return (NULL);
1397 	}
1398 	data = fileno(file);
1399 	while (connect(data, (struct sockaddr *)&data_dest,
1400 	    sizeof(data_dest)) < 0) {
1401 		if (errno == EADDRINUSE && retry < swaitmax) {
1402 			sleep((unsigned) swaitint);
1403 			retry += swaitint;
1404 			continue;
1405 		}
1406 		perror_reply(425, "Can't build data connection");
1407 		(void) fclose(file);
1408 		data = -1;
1409 		return (NULL);
1410 	}
1411 	reply(150, "Opening %s mode data connection for '%s'%s.",
1412 	     type == TYPE_A ? "ASCII" : "BINARY", name, sizebuf);
1413 	return (file);
1414 }
1415 
1416 /*
1417  * Tranfer the contents of "instr" to "outstr" peer using the appropriate
1418  * encapsulation of the data subject to Mode, Structure, and Type.
1419  *
1420  * NB: Form isn't handled.
1421  */
1422 static void
1423 send_data(instr, outstr, blksize, filesize, isreg)
1424 	FILE *instr, *outstr;
1425 	off_t blksize;
1426 	off_t filesize;
1427 	int isreg;
1428 {
1429 	int c, cnt, filefd, netfd;
1430 	char *buf, *bp;
1431 	size_t len;
1432 
1433 	transflag++;
1434 	if (setjmp(urgcatch)) {
1435 		transflag = 0;
1436 		return;
1437 	}
1438 	switch (type) {
1439 
1440 	case TYPE_A:
1441 		while ((c = getc(instr)) != EOF) {
1442 			byte_count++;
1443 			if (c == '\n') {
1444 				if (ferror(outstr))
1445 					goto data_err;
1446 				(void) putc('\r', outstr);
1447 			}
1448 			(void) putc(c, outstr);
1449 		}
1450 		fflush(outstr);
1451 		transflag = 0;
1452 		if (ferror(instr))
1453 			goto file_err;
1454 		if (ferror(outstr))
1455 			goto data_err;
1456 		reply(226, "Transfer complete.");
1457 		return;
1458 
1459 	case TYPE_I:
1460 	case TYPE_L:
1461 		/*
1462 		 * isreg is only set if we are not doing restart and we
1463 		 * are sending a regular file
1464 		 */
1465 		netfd = fileno(outstr);
1466 		filefd = fileno(instr);
1467 
1468 		if (isreg && filesize < (off_t)16 * 1024 * 1024) {
1469 			buf = mmap(0, filesize, PROT_READ, MAP_SHARED, filefd,
1470 				   (off_t)0);
1471 			if (buf == MAP_FAILED) {
1472 				syslog(LOG_WARNING, "mmap(%lu): %m",
1473 				       (unsigned long)filesize);
1474 				goto oldway;
1475 			}
1476 			bp = buf;
1477 			len = filesize;
1478 			do {
1479 				cnt = write(netfd, bp, len);
1480 				len -= cnt;
1481 				bp += cnt;
1482 				if (cnt > 0) byte_count += cnt;
1483 			} while(cnt > 0 && len > 0);
1484 
1485 			transflag = 0;
1486 			munmap(buf, (size_t)filesize);
1487 			if (cnt < 0)
1488 				goto data_err;
1489 			reply(226, "Transfer complete.");
1490 			return;
1491 		}
1492 
1493 oldway:
1494 		if ((buf = malloc((u_int)blksize)) == NULL) {
1495 			transflag = 0;
1496 			perror_reply(451, "Local resource failure: malloc");
1497 			return;
1498 		}
1499 
1500 		while ((cnt = read(filefd, buf, (u_int)blksize)) > 0 &&
1501 		    write(netfd, buf, cnt) == cnt)
1502 			byte_count += cnt;
1503 		transflag = 0;
1504 		(void)free(buf);
1505 		if (cnt != 0) {
1506 			if (cnt < 0)
1507 				goto file_err;
1508 			goto data_err;
1509 		}
1510 		reply(226, "Transfer complete.");
1511 		return;
1512 	default:
1513 		transflag = 0;
1514 		reply(550, "Unimplemented TYPE %d in send_data", type);
1515 		return;
1516 	}
1517 
1518 data_err:
1519 	transflag = 0;
1520 	perror_reply(426, "Data connection");
1521 	return;
1522 
1523 file_err:
1524 	transflag = 0;
1525 	perror_reply(551, "Error on input file");
1526 }
1527 
1528 /*
1529  * Transfer data from peer to "outstr" using the appropriate encapulation of
1530  * the data subject to Mode, Structure, and Type.
1531  *
1532  * N.B.: Form isn't handled.
1533  */
1534 static int
1535 receive_data(instr, outstr)
1536 	FILE *instr, *outstr;
1537 {
1538 	int c;
1539 	int cnt, bare_lfs;
1540 	char buf[BUFSIZ];
1541 
1542 	transflag++;
1543 	if (setjmp(urgcatch)) {
1544 		transflag = 0;
1545 		return (-1);
1546 	}
1547 
1548 	bare_lfs = 0;
1549 
1550 	switch (type) {
1551 
1552 	case TYPE_I:
1553 	case TYPE_L:
1554 		while ((cnt = read(fileno(instr), buf, sizeof(buf))) > 0) {
1555 			if (write(fileno(outstr), buf, cnt) != cnt)
1556 				goto file_err;
1557 			byte_count += cnt;
1558 		}
1559 		if (cnt < 0)
1560 			goto data_err;
1561 		transflag = 0;
1562 		return (0);
1563 
1564 	case TYPE_E:
1565 		reply(553, "TYPE E not implemented.");
1566 		transflag = 0;
1567 		return (-1);
1568 
1569 	case TYPE_A:
1570 		while ((c = getc(instr)) != EOF) {
1571 			byte_count++;
1572 			if (c == '\n')
1573 				bare_lfs++;
1574 			while (c == '\r') {
1575 				if (ferror(outstr))
1576 					goto data_err;
1577 				if ((c = getc(instr)) != '\n') {
1578 					(void) putc ('\r', outstr);
1579 					if (c == '\0' || c == EOF)
1580 						goto contin2;
1581 				}
1582 			}
1583 			(void) putc(c, outstr);
1584 	contin2:	;
1585 		}
1586 		fflush(outstr);
1587 		if (ferror(instr))
1588 			goto data_err;
1589 		if (ferror(outstr))
1590 			goto file_err;
1591 		transflag = 0;
1592 		if (bare_lfs) {
1593 			lreply(226,
1594 		"WARNING! %d bare linefeeds received in ASCII mode",
1595 			    bare_lfs);
1596 		(void)printf("   File may not have transferred correctly.\r\n");
1597 		}
1598 		return (0);
1599 	default:
1600 		reply(550, "Unimplemented TYPE %d in receive_data", type);
1601 		transflag = 0;
1602 		return (-1);
1603 	}
1604 
1605 data_err:
1606 	transflag = 0;
1607 	perror_reply(426, "Data Connection");
1608 	return (-1);
1609 
1610 file_err:
1611 	transflag = 0;
1612 	perror_reply(452, "Error writing file");
1613 	return (-1);
1614 }
1615 
1616 void
1617 statfilecmd(filename)
1618 	char *filename;
1619 {
1620 	FILE *fin;
1621 	int c;
1622 	char line[LINE_MAX];
1623 
1624 	(void)snprintf(line, sizeof(line), _PATH_LS " -lgA %s", filename);
1625 	fin = ftpd_popen(line, "r");
1626 	lreply(211, "status of %s:", filename);
1627 	while ((c = getc(fin)) != EOF) {
1628 		if (c == '\n') {
1629 			if (ferror(stdout)){
1630 				perror_reply(421, "control connection");
1631 				(void) ftpd_pclose(fin);
1632 				dologout(1);
1633 				/* NOTREACHED */
1634 			}
1635 			if (ferror(fin)) {
1636 				perror_reply(551, filename);
1637 				(void) ftpd_pclose(fin);
1638 				return;
1639 			}
1640 			(void) putc('\r', stdout);
1641 		}
1642 		(void) putc(c, stdout);
1643 	}
1644 	(void) ftpd_pclose(fin);
1645 	reply(211, "End of Status");
1646 }
1647 
1648 void
1649 statcmd()
1650 {
1651 	struct sockaddr_in *sin;
1652 	u_char *a, *p;
1653 
1654 	lreply(211, "%s FTP server status:", hostname, version);
1655 	printf("     %s\r\n", version);
1656 	printf("     Connected to %s", remotehost);
1657 	if (!isdigit(remotehost[0]))
1658 		printf(" (%s)", inet_ntoa(his_addr.sin_addr));
1659 	printf("\r\n");
1660 	if (logged_in) {
1661 		if (guest)
1662 			printf("     Logged in anonymously\r\n");
1663 		else
1664 			printf("     Logged in as %s\r\n", pw->pw_name);
1665 	} else if (askpasswd)
1666 		printf("     Waiting for password\r\n");
1667 	else
1668 		printf("     Waiting for user name\r\n");
1669 	printf("     TYPE: %s", typenames[type]);
1670 	if (type == TYPE_A || type == TYPE_E)
1671 		printf(", FORM: %s", formnames[form]);
1672 	if (type == TYPE_L)
1673 #if NBBY == 8
1674 		printf(" %d", NBBY);
1675 #else
1676 		printf(" %d", bytesize);	/* need definition! */
1677 #endif
1678 	printf("; STRUcture: %s; transfer MODE: %s\r\n",
1679 	    strunames[stru], modenames[mode]);
1680 	if (data != -1)
1681 		printf("     Data connection open\r\n");
1682 	else if (pdata != -1) {
1683 		printf("     in Passive mode");
1684 		sin = &pasv_addr;
1685 		goto printaddr;
1686 	} else if (usedefault == 0) {
1687 		printf("     PORT");
1688 		sin = &data_dest;
1689 printaddr:
1690 		a = (u_char *) &sin->sin_addr;
1691 		p = (u_char *) &sin->sin_port;
1692 #define UC(b) (((int) b) & 0xff)
1693 		printf(" (%d,%d,%d,%d,%d,%d)\r\n", UC(a[0]),
1694 			UC(a[1]), UC(a[2]), UC(a[3]), UC(p[0]), UC(p[1]));
1695 #undef UC
1696 	} else
1697 		printf("     No data connection\r\n");
1698 	reply(211, "End of status");
1699 }
1700 
1701 void
1702 fatal(s)
1703 	char *s;
1704 {
1705 
1706 	reply(451, "Error in server: %s\n", s);
1707 	reply(221, "Closing connection due to server error.");
1708 	dologout(0);
1709 	/* NOTREACHED */
1710 }
1711 
1712 void
1713 #if __STDC__
1714 reply(int n, const char *fmt, ...)
1715 #else
1716 reply(n, fmt, va_alist)
1717 	int n;
1718 	char *fmt;
1719         va_dcl
1720 #endif
1721 {
1722 	va_list ap;
1723 #if __STDC__
1724 	va_start(ap, fmt);
1725 #else
1726 	va_start(ap);
1727 #endif
1728 	(void)printf("%d ", n);
1729 	(void)vprintf(fmt, ap);
1730 	(void)printf("\r\n");
1731 	(void)fflush(stdout);
1732 	if (debug) {
1733 		syslog(LOG_DEBUG, "<--- %d ", n);
1734 		vsyslog(LOG_DEBUG, fmt, ap);
1735 	}
1736 }
1737 
1738 void
1739 #if __STDC__
1740 lreply(int n, const char *fmt, ...)
1741 #else
1742 lreply(n, fmt, va_alist)
1743 	int n;
1744 	char *fmt;
1745         va_dcl
1746 #endif
1747 {
1748 	va_list ap;
1749 #if __STDC__
1750 	va_start(ap, fmt);
1751 #else
1752 	va_start(ap);
1753 #endif
1754 	(void)printf("%d- ", n);
1755 	(void)vprintf(fmt, ap);
1756 	(void)printf("\r\n");
1757 	(void)fflush(stdout);
1758 	if (debug) {
1759 		syslog(LOG_DEBUG, "<--- %d- ", n);
1760 		vsyslog(LOG_DEBUG, fmt, ap);
1761 	}
1762 }
1763 
1764 static void
1765 ack(s)
1766 	char *s;
1767 {
1768 
1769 	reply(250, "%s command successful.", s);
1770 }
1771 
1772 void
1773 nack(s)
1774 	char *s;
1775 {
1776 
1777 	reply(502, "%s command not implemented.", s);
1778 }
1779 
1780 /* ARGSUSED */
1781 void
1782 yyerror(s)
1783 	char *s;
1784 {
1785 	char *cp;
1786 
1787 	if ((cp = strchr(cbuf,'\n')))
1788 		*cp = '\0';
1789 	reply(500, "'%s': command not understood.", cbuf);
1790 }
1791 
1792 void
1793 delete(name)
1794 	char *name;
1795 {
1796 	struct stat st;
1797 
1798 	LOGCMD("delete", name);
1799 	if (stat(name, &st) < 0) {
1800 		perror_reply(550, name);
1801 		return;
1802 	}
1803 	if ((st.st_mode&S_IFMT) == S_IFDIR) {
1804 		if (rmdir(name) < 0) {
1805 			perror_reply(550, name);
1806 			return;
1807 		}
1808 		goto done;
1809 	}
1810 	if (unlink(name) < 0) {
1811 		perror_reply(550, name);
1812 		return;
1813 	}
1814 done:
1815 	ack("DELE");
1816 }
1817 
1818 void
1819 cwd(path)
1820 	char *path;
1821 {
1822 
1823 	if (chdir(path) < 0)
1824 		perror_reply(550, path);
1825 	else
1826 		ack("CWD");
1827 }
1828 
1829 void
1830 makedir(name)
1831 	char *name;
1832 {
1833 
1834 	LOGCMD("mkdir", name);
1835 	if (mkdir(name, 0777) < 0)
1836 		perror_reply(550, name);
1837 	else
1838 		reply(257, "MKD command successful.");
1839 }
1840 
1841 void
1842 removedir(name)
1843 	char *name;
1844 {
1845 
1846 	LOGCMD("rmdir", name);
1847 	if (rmdir(name) < 0)
1848 		perror_reply(550, name);
1849 	else
1850 		ack("RMD");
1851 }
1852 
1853 void
1854 pwd()
1855 {
1856 	char path[MAXPATHLEN + 1];
1857 
1858 	if (getwd(path) == (char *)NULL)
1859 		reply(550, "%s.", path);
1860 	else
1861 		reply(257, "\"%s\" is current directory.", path);
1862 }
1863 
1864 char *
1865 renamefrom(name)
1866 	char *name;
1867 {
1868 	struct stat st;
1869 
1870 	if (stat(name, &st) < 0) {
1871 		perror_reply(550, name);
1872 		return ((char *)0);
1873 	}
1874 	reply(350, "File exists, ready for destination name");
1875 	return (name);
1876 }
1877 
1878 void
1879 renamecmd(from, to)
1880 	char *from, *to;
1881 {
1882 	struct stat st;
1883 
1884 	LOGCMD2("rename", from, to);
1885 
1886 	if (guest && (stat(to, &st) == 0)) {
1887 		reply(550, "%s: permission denied", to);
1888 		return;
1889 	}
1890 
1891 	if (rename(from, to) < 0)
1892 		perror_reply(550, "rename");
1893 	else
1894 		ack("RNTO");
1895 }
1896 
1897 static void
1898 dolog(sin)
1899 	struct sockaddr_in *sin;
1900 {
1901 	realhostname(remotehost, sizeof(remotehost) - 1, &sin->sin_addr);
1902 
1903 #ifdef SETPROCTITLE
1904 #ifdef VIRTUAL_HOSTING
1905 	if (thishost != firsthost)
1906 		snprintf(proctitle, sizeof(proctitle), "%s: connected (to %s)",
1907 			 remotehost, hostname);
1908 	else
1909 #endif
1910 		snprintf(proctitle, sizeof(proctitle), "%s: connected",
1911 			 remotehost);
1912 	setproctitle("%s", proctitle);
1913 #endif /* SETPROCTITLE */
1914 
1915 	if (logging) {
1916 #ifdef VIRTUAL_HOSTING
1917 		if (thishost != firsthost)
1918 			syslog(LOG_INFO, "connection from %s (to %s)",
1919 			       remotehost, hostname);
1920 		else
1921 #endif
1922 			syslog(LOG_INFO, "connection from %s (%s)", remotehost,
1923 				inet_ntoa(sin->sin_addr));
1924 	}
1925 }
1926 
1927 /*
1928  * Record logout in wtmp file
1929  * and exit with supplied status.
1930  */
1931 void
1932 dologout(status)
1933 	int status;
1934 {
1935 	/*
1936 	 * Prevent reception of SIGURG from resulting in a resumption
1937 	 * back to the main program loop.
1938 	 */
1939 	transflag = 0;
1940 
1941 	if (logged_in) {
1942 		(void) seteuid((uid_t)0);
1943 		ftpd_logwtmp(ttyline, "", "");
1944 #if defined(KERBEROS)
1945 		if (!notickets && krbtkfile_env)
1946 			unlink(krbtkfile_env);
1947 #endif
1948 	}
1949 	/* beware of flushing buffers after a SIGPIPE */
1950 	_exit(status);
1951 }
1952 
1953 static void
1954 myoob(signo)
1955 	int signo;
1956 {
1957 	char *cp;
1958 
1959 	/* only process if transfer occurring */
1960 	if (!transflag)
1961 		return;
1962 	cp = tmpline;
1963 	if (getline(cp, 7, stdin) == NULL) {
1964 		reply(221, "You could at least say goodbye.");
1965 		dologout(0);
1966 	}
1967 	upper(cp);
1968 	if (strcmp(cp, "ABOR\r\n") == 0) {
1969 		tmpline[0] = '\0';
1970 		reply(426, "Transfer aborted. Data connection closed.");
1971 		reply(226, "Abort successful");
1972 		longjmp(urgcatch, 1);
1973 	}
1974 	if (strcmp(cp, "STAT\r\n") == 0) {
1975 		if (file_size != (off_t) -1)
1976 			reply(213, "Status: %qd of %qd bytes transferred",
1977 			    byte_count, file_size);
1978 		else
1979 			reply(213, "Status: %qd bytes transferred", byte_count);
1980 	}
1981 }
1982 
1983 /*
1984  * Note: a response of 425 is not mentioned as a possible response to
1985  *	the PASV command in RFC959. However, it has been blessed as
1986  *	a legitimate response by Jon Postel in a telephone conversation
1987  *	with Rick Adams on 25 Jan 89.
1988  */
1989 void
1990 passive()
1991 {
1992 	int len;
1993 	char *p, *a;
1994 
1995 	if (pdata >= 0)		/* close old port if one set */
1996 		close(pdata);
1997 
1998 	pdata = socket(AF_INET, SOCK_STREAM, 0);
1999 	if (pdata < 0) {
2000 		perror_reply(425, "Can't open passive connection");
2001 		return;
2002 	}
2003 
2004 	(void) seteuid((uid_t)0);
2005 
2006 #ifdef IP_PORTRANGE
2007 	{
2008 	    int on = restricted_data_ports ? IP_PORTRANGE_HIGH
2009 					   : IP_PORTRANGE_DEFAULT;
2010 
2011 	    if (setsockopt(pdata, IPPROTO_IP, IP_PORTRANGE,
2012 			    (char *)&on, sizeof(on)) < 0)
2013 		    goto pasv_error;
2014 	}
2015 #endif
2016 
2017 	pasv_addr = ctrl_addr;
2018 	pasv_addr.sin_port = 0;
2019 	if (bind(pdata, (struct sockaddr *)&pasv_addr,
2020 		 sizeof(pasv_addr)) < 0)
2021 		goto pasv_error;
2022 
2023 	(void) seteuid((uid_t)pw->pw_uid);
2024 
2025 	len = sizeof(pasv_addr);
2026 	if (getsockname(pdata, (struct sockaddr *) &pasv_addr, &len) < 0)
2027 		goto pasv_error;
2028 	if (listen(pdata, 1) < 0)
2029 		goto pasv_error;
2030 	a = (char *) &pasv_addr.sin_addr;
2031 	p = (char *) &pasv_addr.sin_port;
2032 
2033 #define UC(b) (((int) b) & 0xff)
2034 
2035 	reply(227, "Entering Passive Mode (%d,%d,%d,%d,%d,%d)", UC(a[0]),
2036 		UC(a[1]), UC(a[2]), UC(a[3]), UC(p[0]), UC(p[1]));
2037 	return;
2038 
2039 pasv_error:
2040 	(void) seteuid((uid_t)pw->pw_uid);
2041 	(void) close(pdata);
2042 	pdata = -1;
2043 	perror_reply(425, "Can't open passive connection");
2044 	return;
2045 }
2046 
2047 /*
2048  * Generate unique name for file with basename "local".
2049  * The file named "local" is already known to exist.
2050  * Generates failure reply on error.
2051  */
2052 static char *
2053 gunique(local)
2054 	char *local;
2055 {
2056 	static char new[MAXPATHLEN];
2057 	struct stat st;
2058 	int count;
2059 	char *cp;
2060 
2061 	cp = strrchr(local, '/');
2062 	if (cp)
2063 		*cp = '\0';
2064 	if (stat(cp ? local : ".", &st) < 0) {
2065 		perror_reply(553, cp ? local : ".");
2066 		return ((char *) 0);
2067 	}
2068 	if (cp)
2069 		*cp = '/';
2070 	/* -4 is for the .nn<null> we put on the end below */
2071 	(void) snprintf(new, sizeof(new) - 4, "%s", local);
2072 	cp = new + strlen(new);
2073 	*cp++ = '.';
2074 	for (count = 1; count < 100; count++) {
2075 		(void)sprintf(cp, "%d", count);
2076 		if (stat(new, &st) < 0)
2077 			return (new);
2078 	}
2079 	reply(452, "Unique file name cannot be created.");
2080 	return (NULL);
2081 }
2082 
2083 /*
2084  * Format and send reply containing system error number.
2085  */
2086 void
2087 perror_reply(code, string)
2088 	int code;
2089 	char *string;
2090 {
2091 
2092 	reply(code, "%s: %s.", string, strerror(errno));
2093 }
2094 
2095 static char *onefile[] = {
2096 	"",
2097 	0
2098 };
2099 
2100 void
2101 send_file_list(whichf)
2102 	char *whichf;
2103 {
2104 	struct stat st;
2105 	DIR *dirp = NULL;
2106 	struct dirent *dir;
2107 	FILE *dout = NULL;
2108 	char **dirlist, *dirname;
2109 	int simple = 0;
2110 	int freeglob = 0;
2111 	glob_t gl;
2112 
2113 	if (strpbrk(whichf, "~{[*?") != NULL) {
2114 		int flags = GLOB_BRACE|GLOB_NOCHECK|GLOB_QUOTE|GLOB_TILDE;
2115 
2116 		memset(&gl, 0, sizeof(gl));
2117 		freeglob = 1;
2118 		if (glob(whichf, flags, 0, &gl)) {
2119 			reply(550, "not found");
2120 			goto out;
2121 		} else if (gl.gl_pathc == 0) {
2122 			errno = ENOENT;
2123 			perror_reply(550, whichf);
2124 			goto out;
2125 		}
2126 		dirlist = gl.gl_pathv;
2127 	} else {
2128 		onefile[0] = whichf;
2129 		dirlist = onefile;
2130 		simple = 1;
2131 	}
2132 
2133 	if (setjmp(urgcatch)) {
2134 		transflag = 0;
2135 		goto out;
2136 	}
2137 	while ((dirname = *dirlist++)) {
2138 		if (stat(dirname, &st) < 0) {
2139 			/*
2140 			 * If user typed "ls -l", etc, and the client
2141 			 * used NLST, do what the user meant.
2142 			 */
2143 			if (dirname[0] == '-' && *dirlist == NULL &&
2144 			    transflag == 0) {
2145 				retrieve(_PATH_LS " %s", dirname);
2146 				goto out;
2147 			}
2148 			perror_reply(550, whichf);
2149 			if (dout != NULL) {
2150 				(void) fclose(dout);
2151 				transflag = 0;
2152 				data = -1;
2153 				pdata = -1;
2154 			}
2155 			goto out;
2156 		}
2157 
2158 		if (S_ISREG(st.st_mode)) {
2159 			if (dout == NULL) {
2160 				dout = dataconn("file list", (off_t)-1, "w");
2161 				if (dout == NULL)
2162 					goto out;
2163 				transflag++;
2164 			}
2165 			fprintf(dout, "%s%s\n", dirname,
2166 				type == TYPE_A ? "\r" : "");
2167 			byte_count += strlen(dirname) + 1;
2168 			continue;
2169 		} else if (!S_ISDIR(st.st_mode))
2170 			continue;
2171 
2172 		if ((dirp = opendir(dirname)) == NULL)
2173 			continue;
2174 
2175 		while ((dir = readdir(dirp)) != NULL) {
2176 			char nbuf[MAXPATHLEN];
2177 
2178 			if (dir->d_name[0] == '.' && dir->d_namlen == 1)
2179 				continue;
2180 			if (dir->d_name[0] == '.' && dir->d_name[1] == '.' &&
2181 			    dir->d_namlen == 2)
2182 				continue;
2183 
2184 			snprintf(nbuf, sizeof(nbuf),
2185 				"%s/%s", dirname, dir->d_name);
2186 
2187 			/*
2188 			 * We have to do a stat to insure it's
2189 			 * not a directory or special file.
2190 			 */
2191 			if (simple || (stat(nbuf, &st) == 0 &&
2192 			    S_ISREG(st.st_mode))) {
2193 				if (dout == NULL) {
2194 					dout = dataconn("file list", (off_t)-1,
2195 						"w");
2196 					if (dout == NULL)
2197 						goto out;
2198 					transflag++;
2199 				}
2200 				if (nbuf[0] == '.' && nbuf[1] == '/')
2201 					fprintf(dout, "%s%s\n", &nbuf[2],
2202 						type == TYPE_A ? "\r" : "");
2203 				else
2204 					fprintf(dout, "%s%s\n", nbuf,
2205 						type == TYPE_A ? "\r" : "");
2206 				byte_count += strlen(nbuf) + 1;
2207 			}
2208 		}
2209 		(void) closedir(dirp);
2210 	}
2211 
2212 	if (dout == NULL)
2213 		reply(550, "No files found.");
2214 	else if (ferror(dout) != 0)
2215 		perror_reply(550, "Data connection");
2216 	else
2217 		reply(226, "Transfer complete.");
2218 
2219 	transflag = 0;
2220 	if (dout != NULL)
2221 		(void) fclose(dout);
2222 	data = -1;
2223 	pdata = -1;
2224 out:
2225 	if (freeglob) {
2226 		freeglob = 0;
2227 		globfree(&gl);
2228 	}
2229 }
2230 
2231 void
2232 reapchild(signo)
2233 	int signo;
2234 {
2235 	while (wait3(NULL, WNOHANG, NULL) > 0);
2236 }
2237 
2238 #ifdef OLD_SETPROCTITLE
2239 /*
2240  * Clobber argv so ps will show what we're doing.  (Stolen from sendmail.)
2241  * Warning, since this is usually started from inetd.conf, it often doesn't
2242  * have much of an environment or arglist to overwrite.
2243  */
2244 void
2245 #if __STDC__
2246 setproctitle(const char *fmt, ...)
2247 #else
2248 setproctitle(fmt, va_alist)
2249 	char *fmt;
2250         va_dcl
2251 #endif
2252 {
2253 	int i;
2254 	va_list ap;
2255 	char *p, *bp, ch;
2256 	char buf[LINE_MAX];
2257 
2258 #if __STDC__
2259 	va_start(ap, fmt);
2260 #else
2261 	va_start(ap);
2262 #endif
2263 	(void)vsnprintf(buf, sizeof(buf), fmt, ap);
2264 
2265 	/* make ps print our process name */
2266 	p = Argv[0];
2267 	*p++ = '-';
2268 
2269 	i = strlen(buf);
2270 	if (i > LastArgv - p - 2) {
2271 		i = LastArgv - p - 2;
2272 		buf[i] = '\0';
2273 	}
2274 	bp = buf;
2275 	while (ch = *bp++)
2276 		if (ch != '\n' && ch != '\r')
2277 			*p++ = ch;
2278 	while (p < LastArgv)
2279 		*p++ = ' ';
2280 }
2281 #endif /* OLD_SETPROCTITLE */
2282 
2283 static void
2284 logxfer(name, size, start)
2285 	char *name;
2286 	long size;
2287 	long start;
2288 {
2289 	char buf[1024];
2290 	char path[MAXPATHLEN + 1];
2291 	time_t now;
2292 
2293 	if (statfd >= 0 && getwd(path) != NULL) {
2294 		time(&now);
2295 		snprintf(buf, sizeof(buf), "%.20s!%s!%s!%s/%s!%ld!%ld\n",
2296 			ctime(&now)+4, ident, remotehost,
2297 			path, name, size, now - start + (now == start));
2298 		write(statfd, buf, strlen(buf));
2299 	}
2300 }
2301