if (restart_point) mode = "r+";
static FILE	*getdatasock __P((char *));static int	guniquefd __P((char *, char **));static void	 lostconn __P((int));static void	 sigquit __P((int));static int	 receive_data __P((FILE *, FILE *));static void	 replydirname __P((const char *, const char *));static void	 send_data __P((FILE *, FILE *, off_t, off_t, int));static struct passwd *		 sgetpwnam __P((char *));static char	*sgetsave __P((char *));static void	 reapchild __P((int));static int	 check_host __P((struct sockaddr_in *));static void	 usage __P((void));void	 logxfer __P((char *, off_t, time_t));static char *curdir(){	static char path[MAXPATHLEN+1];	/* path + '/' */	if (getcwd(path, sizeof(path)-1) == NULL)		return ("");	if (path[1] != '\0')		/* special case for root dir. */		strcat(path, "/");	/* For guest account, skip / since it's chrooted */	return (guest ? path+1 : path);}char *argstr = "AdDhlMSt:T:u:UvP";static voidusage(){	syslog(LOG_ERR,	    "usage: ftpd [-AdDhlMSUv] [-t timeout] [-T maxtimeout] [-u mask]");	exit(2);}intmain(argc, argv, envp)	int argc;	char *argv[];	char **envp;{	int addrlen, ch, on = 1, tos;	char *cp, line[LINE_MAX];	FILE *fd;	struct hostent *hp;	tzset();	/* in case no timezone database in ~ftp */	/* set this here so klogin can use it... */	(void)snprintf(ttyline, sizeof(ttyline), "ftp%d", getpid());	while ((ch = getopt(argc, argv, argstr)) != -1) {		switch (ch) {		case 'A':			anon_only = 1;			break;		case 'd':			debug = 1;			break;		case 'D':			daemon_mode = 1;			break;		case 'P':			portcheck = 0;			break;		case 'h':			high_data_ports = 1;			break;		case 'l':			logging++;	/* > 1 == extra logging */			break;		case 'M':			multihome = 1;			break;		case 'S':			stats = 1;			break;		case 't':			timeout = atoi(optarg);			if (maxtimeout < timeout)				maxtimeout = timeout;			break;		case 'T':			maxtimeout = atoi(optarg);			if (timeout > maxtimeout)				timeout = maxtimeout;			break;		case 'u':		    {			long val = 0;			char *p;			val = strtol(optarg, &p, 8);			if (*p != '\0' || val < 0 || (val & ~ACCESSPERMS)) {				syslog(LOG_ERR,				    "ftpd: %s is a bad value for -u, aborting..",				    optarg);				exit(2);			} else				defumask = val;			break;		    }		case 'U':			doutmp = 1;			break;		case 'v':			debug = 1;			break;		default:			usage();			break;		}	}	(void) freopen(_PATH_DEVNULL, "w", stderr);	/*	 * LOG_NDELAY sets up the logging connection immediately,	 * necessary for anonymous ftp's that chroot and can't do it later.	 */	openlog("ftpd", LOG_PID | LOG_NDELAY, LOG_FTP);	if (daemon_mode) {		int ctl_sock, fd;		struct servent *sv;		/*		 * Detach from parent.		 */		if (daemon(1, 1) < 0) {			syslog(LOG_ERR, "failed to become a daemon");			exit(1);		}		(void) signal(SIGCHLD, reapchild);		/*		 * Get port number for ftp/tcp.		 */		sv = getservbyname("ftp", "tcp");		if (sv == NULL) {			syslog(LOG_ERR, "getservbyname for ftp failed");			exit(1);		}		/*		 * Open a socket, bind it to the FTP port, and start		 * listening.		 */		ctl_sock = socket(AF_INET, SOCK_STREAM, 0);		if (ctl_sock < 0) {			syslog(LOG_ERR, "control socket: %m");			exit(1);		}		if (setsockopt(ctl_sock, SOL_SOCKET, SO_REUSEADDR,		    (char *)&on, sizeof(on)) < 0)			syslog(LOG_ERR, "control setsockopt: %m");;		server_addr.sin_family = AF_INET;		server_addr.sin_addr.s_addr = INADDR_ANY;		server_addr.sin_port = sv->s_port;		if (bind(ctl_sock, (struct sockaddr *)&server_addr,			 sizeof(server_addr))) {			syslog(LOG_ERR, "control bind: %m");			exit(1);		}		if (listen(ctl_sock, 32) < 0) {			syslog(LOG_ERR, "control listen: %m");			exit(1);		}		/*		 * Loop forever accepting connection requests and forking off		 * children to handle them.		 */		while (1) {			addrlen = sizeof(his_addr);			fd = accept(ctl_sock, (struct sockaddr *)&his_addr,				    &addrlen);			if (fork() == 0) {				/* child */				(void) dup2(fd, 0);				(void) dup2(fd, 1);				close(ctl_sock);				break;			}			close(fd);		}#if defined(TCPWRAPPERS)		/* ..in the child. */		if (!check_host(&his_addr))			exit(1);#endif	/* TCPWRAPPERS */	} else {		addrlen = sizeof(his_addr);		if (getpeername(0, (struct sockaddr *)&his_addr,				&addrlen) < 0) {			/* syslog(LOG_ERR, "getpeername (%s): %m", argv[0]); */			exit(1);		}	}	(void) signal(SIGHUP, sigquit);	(void) signal(SIGINT, sigquit);	(void) signal(SIGQUIT, sigquit);	(void) signal(SIGTERM, sigquit);	(void) signal(SIGPIPE, lostconn);	(void) signal(SIGCHLD, SIG_IGN);	if (signal(SIGURG, myoob) == SIG_ERR)		syslog(LOG_ERR, "signal: %m");	addrlen = sizeof(ctrl_addr);	if (getsockname(0, (struct sockaddr *)&ctrl_addr, &addrlen) < 0) {		syslog(LOG_ERR, "getsockname (%s): %m", argv[0]);		exit(1);	}#ifdef IP_TOS	tos = IPTOS_LOWDELAY;	if (setsockopt(0, IPPROTO_IP, IP_TOS, (char *)&tos, sizeof(int)) < 0)		syslog(LOG_WARNING, "setsockopt (IP_TOS): %m");#endif	data_source.sin_port = htons(ntohs(ctrl_addr.sin_port) - 1);	/* Try to handle urgent data inline */#ifdef SO_OOBINLINE	if (setsockopt(0, SOL_SOCKET, SO_OOBINLINE, (char *)&on, sizeof(on)) < 0)		syslog(LOG_ERR, "setsockopt: %m");#endif#ifdef	F_SETOWN	if (fcntl(fileno(stdin), F_SETOWN, getpid()) == -1)		syslog(LOG_ERR, "fcntl F_SETOWN: %m");#endif	dolog(&his_addr);	/*	 * Set up default state	 */	data = -1;	type = TYPE_A;	form = FORM_N;	stru = STRU_F;	mode = MODE_S;	tmpline[0] = '\0';	/* If logins are disabled, print out the message. */	if ((fd = fopen(_PATH_NOLOGIN,"r")) != NULL) {		while (fgets(line, sizeof(line), fd) != NULL) {			if ((cp = strchr(line, '\n')) != NULL)				*cp = '\0';			lreply(530, "%s", line);		}		(void) fflush(stdout);		(void) fclose(fd);		reply(530, "System not available.");		exit(0);	}	if ((fd = fopen(_PATH_FTPWELCOME, "r")) != NULL) {		while (fgets(line, sizeof(line), fd) != NULL) {			if ((cp = strchr(line, '\n')) != NULL)				*cp = '\0';			lreply(220, "%s", line);		}		(void) fflush(stdout);		(void) fclose(fd);		/* reply(220,) must follow */	}	(void) gethostname(hostname, sizeof(hostname));	/* Make sure hostname is fully qualified. */	hp = gethostbyname(hostname);	if (hp != NULL)		strcpy(hostname, hp->h_name);	if (multihome) {		hp = gethostbyaddr((char *) &ctrl_addr.sin_addr,		    sizeof (struct in_addr), AF_INET);		if (hp != NULL) {			strcpy(dhostname, hp->h_name);		} else {			/* Default. */			strcpy(dhostname, inet_ntoa(ctrl_addr.sin_addr));		}	}	reply(220, "%s FTP server (%s) ready.",	      (multihome ? dhostname : hostname), version);	(void) setjmp(errcatch);	for (;;)		(void) yyparse();	/* NOTREACHED */}/* * Signal handlers. */static voidlostconn(signo)	int signo;{	if (debug)		syslog(LOG_DEBUG, "lost connection");	dologout(-1);}static voidsigquit(signo)	int signo;{	syslog(LOG_ERR, "got signal %s", strsignal(signo));	dologout(-1);}/* * Helper function for sgetpwnam(). */static char *sgetsave(s)	char *s;{	char *new = malloc((unsigned) strlen(s) + 1);	if (new == NULL) {		perror_reply(421, "Local resource failure: malloc");		dologout(1);		/* NOTREACHED */	}	(void) strcpy(new, s);	return (new);}/* * Save the result of a getpwnam.  Used for USER command, since * the data returned must not be clobbered by any other command * (e.g., globbing). */static struct passwd *sgetpwnam(name)	char *name;{	static struct passwd save;	struct passwd *p;	if ((p = getpwnam(name)) == NULL)		return (p);	if (save.pw_name) {		free(save.pw_name);		memset(save.pw_passwd, 0, strlen(save.pw_passwd));		free(save.pw_passwd);		free(save.pw_gecos);		free(save.pw_dir);		free(save.pw_shell);	}	save = *p;	save.pw_name = sgetsave(p->pw_name);	save.pw_passwd = sgetsave(p->pw_passwd);	save.pw_gecos = sgetsave(p->pw_gecos);	save.pw_dir = sgetsave(p->pw_dir);	save.pw_shell = sgetsave(p->pw_shell);	return (&save);}static int login_attempts;	/* number of failed login attempts */static int askpasswd;		/* had user command, ask for passwd */static char curname[16];	/* current USER name *//* * USER command. * Sets global passwd pointer pw if named account exists and is acceptable; * sets askpasswd if a PASS command is expected.  If logged in previously, * need to reset state.  If name is "ftp" or "anonymous", the name is not in * _PATH_FTPUSERS, and ftp account exists, set guest and pw, then just return. * If account doesn't exist, ask for passwd anyway.  Otherwise, check user * requesting login privileges.  Disallow anyone who does not have a standard * shell as returned by getusershell().  Disallow anyone mentioned in the file * _PATH_FTPUSERS to allow people such as root and uucp to be avoided. */voiduser(name)	char *name;{	char *cp, *shell;	if (logged_in) {		if (guest) {			reply(530, "Can't change user from guest login.");			return;		} else if (dochroot) {			reply(530, "Can't change user from chroot user.");			return;		}		end_login();	}	guest = 0;	if (strcmp(name, "ftp") == 0 || strcmp(name, "anonymous") == 0) {		if (checkuser(_PATH_FTPUSERS, "ftp") ||		    checkuser(_PATH_FTPUSERS, "anonymous"))			reply(530, "User %s access denied.", name);		else if ((pw = sgetpwnam("ftp")) != NULL) {			guest = 1;			askpasswd = 1;			reply(331,			    "Guest login ok, type your name as password.");		} else			reply(530, "User %s unknown.", name);		if (!askpasswd && logging)			syslog(LOG_NOTICE,			    "ANONYMOUS FTP LOGIN REFUSED FROM %s", remotehost);		return;	}	if (anon_only && !checkuser(_PATH_FTPCHROOT, name)) {		reply(530, "Sorry, only anonymous ftp allowed.");		return;	}	if ((pw = sgetpwnam(name))) {		if ((shell = pw->pw_shell) == NULL || *shell == 0)			shell = _PATH_BSHELL;		while ((cp = getusershell()) != NULL)			if (strcmp(cp, shell) == 0)				break;		endusershell();		if (cp == NULL || checkuser(_PATH_FTPUSERS, name)) {			reply(530, "User %s access denied.", name);			if (logging)				syslog(LOG_NOTICE,				    "FTP LOGIN REFUSED FROM %s, %s",				    remotehost, name);			pw = (struct passwd *) NULL;			return;		}	}	if (logging) {		strncpy(curname, name, sizeof(curname)-1);		curname[sizeof(curname)-1] = '\0';	}#ifdef SKEY	if (!skey_haskey(name)) {		char *myskey, *skey_keyinfo __P((char *name));		myskey = skey_keyinfo(name);		reply(331, "Password [ %s ] for %s required.",		    myskey ? myskey : "error getting challenge", name);	} else#endif		reply(331, "Password required for %s.", name);	askpasswd = 1;	/*	 * Delay before reading passwd after first failed	 * attempt to slow down passwd-guessing programs.	 */	if (login_attempts)		sleep((unsigned) login_attempts);}/* * Check if a user is in the file "fname" */static intcheckuser(fname, name)	char *fname;	char *name;{	FILE *fd;	int found = 0;	char *p, line[BUFSIZ];	if ((fd = fopen(fname, "r")) != NULL) {		while (fgets(line, sizeof(line), fd) != NULL)			if ((p = strchr(line, '\n')) != NULL) {				*p = '\0';				if (line[0] == '#')					continue;				if (strcmp(line, name) == 0) {					found = 1;					break;				}			}		(void) fclose(fd);	}	return (found);}/* * Terminate login as previous user, if any, resetting state; * used when USER command is given or login fails. */static voidend_login(){	sigset_t allsigs;	sigfillset (&allsigs);	sigprocmask (SIG_BLOCK, &allsigs, NULL);	(void) seteuid((uid_t)0);	if (logged_in) {		ftpdlogwtmp(ttyline, "", "");		if (doutmp)			logout(utmp.ut_line);	}	pw = NULL;	logged_in = 0;	guest = 0;	dochroot = 0;}voidpass(passwd)	char *passwd;{	int rval;	FILE *fd;	static char homedir[MAXPATHLEN];	char rootdir[MAXPATHLEN];	sigset_t allsigs;	if (logged_in || askpasswd == 0) {		reply(503, "Login with USER first.");		return;	}	askpasswd = 0;	if (!guest) {		/* "ftp" is only account allowed no password */		if (pw == NULL) {			useconds_t us;			/* Sleep between 1 and 3 seconds to emulate a crypt. */			us = arc4random() % 3000000;			usleep(us);			rval = 1;	/* failure below */			goto skip;		}#if defined(KERBEROS)		rval = klogin(pw, "", hostname, passwd);		if (rval == 0)			goto skip;#endif#ifdef SKEY		if (skey_haskey(pw->pw_name) == 0 &&		   (skey_passcheck(pw->pw_name, passwd) != -1)) {			rval = 0;			goto skip;		}#endif		/* the strcmp does not catch null passwords! */		if (strcmp(crypt(passwd, pw->pw_passwd), pw->pw_passwd) ||		    *pw->pw_passwd == '\0') {			rval = 1;	 /* failure */			goto skip;		}		rval = 0;skip:		/*		 * If rval == 1, the user failed the authentication check		 * above.  If rval == 0, either Kerberos or local authentication		 * succeeded.		 */		if (rval) {			reply(530, "Login incorrect.");			if (logging)				syslog(LOG_NOTICE,				    "FTP LOGIN FAILED FROM %s, %s",				    remotehost, curname);			pw = NULL;			if (login_attempts++ >= 5) {				syslog(LOG_NOTICE,				    "repeated login failures from %s",				    remotehost);				exit(0);			}			return;		}	} else {		/* Save anonymous' password. */		guestpw = strdup(passwd);		if (guestpw == (char *)NULL)			fatal("Out of memory");	}	login_attempts = 0;		/* this time successful */	if (setegid((gid_t)pw->pw_gid) < 0) {		reply(550, "Can't set gid.");		return;	}	(void) initgroups(pw->pw_name, pw->pw_gid);	/* open wtmp before chroot */	ftpdlogwtmp(ttyline, pw->pw_name, remotehost);	/* open utmp before chroot */	if (doutmp) {		memset((void *)&utmp, 0, sizeof(utmp));		(void)time(&utmp.ut_time);		(void)strncpy(utmp.ut_name, pw->pw_name, sizeof(utmp.ut_name));		(void)strncpy(utmp.ut_host, remotehost, sizeof(utmp.ut_host));		(void)strncpy(utmp.ut_line, ttyline, sizeof(utmp.ut_line));		login(&utmp);	}	/* open stats file before chroot */	if (guest && (stats == 1) && (statfd < 0))		if ((statfd = open(_PATH_FTPDSTATFILE, O_WRONLY|O_APPEND)) < 0)			stats = 0;	logged_in = 1;	dochroot = checkuser(_PATH_FTPCHROOT, pw->pw_name);	if (guest || dochroot) {		if (multihome && guest) {			struct stat ts;			/* Compute root directory. */			snprintf(rootdir, sizeof(rootdir), "%s/%s",				  pw->pw_dir, dhostname);			if (stat(rootdir, &ts) < 0) {				snprintf(rootdir, sizeof(rootdir), "%s/%s",					  pw->pw_dir, hostname);			}		} else			strcpy(rootdir, pw->pw_dir);	}	if (guest) {		/*		 * We MUST do a chdir() after the chroot. Otherwise		 * the old current directory will be accessible as "."		 * outside the new root!		 */		if (chroot(rootdir) < 0 || chdir("/") < 0) {			reply(550, "Can't set guest privileges.");			goto bad;		}		strcpy(pw->pw_dir, "/");		setenv("HOME", "/", 1);	} else if (dochroot) {		if (chroot(rootdir) < 0 || chdir("/") < 0) {			reply(550, "Can't change root.");			goto bad;		}		strcpy(pw->pw_dir, "/");		setenv("HOME", "/", 1);	} else if (chdir(pw->pw_dir) < 0) {		if (chdir("/") < 0) {			reply(530, "User %s: can't change directory to %s.",			    pw->pw_name, pw->pw_dir);			goto bad;		} else			lreply(230, "No directory! Logging in with home=/");	}	if (seteuid((uid_t)pw->pw_uid) < 0) {		reply(550, "Can't set uid.");		goto bad;	}	sigfillset(&allsigs);	sigprocmask(SIG_UNBLOCK,&allsigs,NULL);	/*	 * Set home directory so that use of ~ (tilde) works correctly.	 */	if (getcwd(homedir, MAXPATHLEN) != NULL)		setenv("HOME", homedir, 1);	/*	 * Display a login message, if it exists.	 * N.B. reply(230,) must follow the message.	 */	if ((fd = fopen(_PATH_FTPLOGINMESG, "r")) != NULL) {		char *cp, line[LINE_MAX];		while (fgets(line, sizeof(line), fd) != NULL) {			if ((cp = strchr(line, '\n')) != NULL)				*cp = '\0';			lreply(230, "%s", line);		}		(void) fflush(stdout);		(void) fclose(fd);	}	if (guest) {		if (ident != NULL)			free(ident);		ident = strdup(passwd);		if (ident == (char *)NULL)			fatal("Ran out of memory.");		reply(230, "Guest login ok, access restrictions apply.");#ifdef HASSETPROCTITLE		snprintf(proctitle, sizeof(proctitle),		    "%s: anonymous/%.*s", remotehost,		    (int)(sizeof(proctitle) - sizeof(remotehost) -		    sizeof(": anonymous/")), passwd);		setproctitle(proctitle);#endif /* HASSETPROCTITLE */		if (logging)			syslog(LOG_INFO, "ANONYMOUS FTP LOGIN FROM %s, %s",			    remotehost, passwd);	} else {		reply(230, "User %s logged in.", pw->pw_name);#ifdef HASSETPROCTITLE		snprintf(proctitle, sizeof(proctitle),		    "%s: %s", remotehost, pw->pw_name);		setproctitle(proctitle);#endif /* HASSETPROCTITLE */		if (logging)			syslog(LOG_INFO, "FTP LOGIN FROM %s as %s",			    remotehost, pw->pw_name);	}	(void) umask(defumask);	return;bad:	/* Forget all about it... */	end_login();}voidretrieve(cmd, name)	char *cmd, *name;{	FILE *fin, *dout;	struct stat st;	int (*closefunc) __P((FILE *));	time_t start;	if (cmd == 0) {		fin = fopen(name, "r"), closefunc = fclose;		st.st_size = 0;	} else {		char line[BUFSIZ];		(void) snprintf(line, sizeof(line), cmd, name);		name = line;		fin = ftpd_popen(line, "r"), closefunc = ftpd_pclose;		st.st_size = -1;		st.st_blksize = BUFSIZ;	}	if (fin == NULL) {		if (errno != 0) {			perror_reply(550, name);			if (cmd == 0) {				LOGCMD("get", name);			}		}		return;	}	byte_count = -1;	if (cmd == 0 && (fstat(fileno(fin), &st) < 0 || !S_ISREG(st.st_mode))) {		reply(550, "%s: not a plain file.", name);		goto done;	}	if (restart_point) {		if (type == TYPE_A) {			off_t i, n;			int c;			n = restart_point;			i = 0;			while (i++ < n) {				if ((c=getc(fin)) == EOF) {					perror_reply(550, name);					goto done;				}				if (c == '\n')					i++;			}		} else if (lseek(fileno(fin), restart_point, SEEK_SET) < 0) {			perror_reply(550, name);			goto done;		}	}	dout = dataconn(name, st.st_size, "w");	if (dout == NULL)		goto done;	time(&start);	send_data(fin, dout, st.st_blksize, st.st_size,		  (restart_point == 0 && cmd == 0 && S_ISREG(st.st_mode)));	if ((cmd == 0) && stats)		logxfer(name, st.st_size, start);	(void) fclose(dout);	data = -1;	pdata = -1;done:	if (cmd == 0)		LOGBYTES("get", name, byte_count);	(*closefunc)(fin);}voidstore(name, mode, unique)	char *name, *mode;	int unique;{	FILE *fout, *din;	int (*closefunc) __P((FILE *));	struct stat st;	int fd;	if (unique && stat(name, &st) == 0) {		char *nam;		fd = guniquefd(name, &nam);		if (fd == -1) {			LOGCMD(*mode == 'w' ? "put" : "append", name);			return;		}		name = nam;		if (restart_point)			mode = "r+";		fout = fdopen(fd, mode);	} else		fout = fopen(name, mode);	closefunc = fclose;	if (fout == NULL) {		perror_reply(553, name);		LOGCMD(*mode == 'w' ? "put" : "append", name);		return;	}	byte_count = -1;	if (restart_point) {		if (type == TYPE_A) {			off_t i, n;			int c;			n = restart_point;			i = 0;			while (i++ < n) {				if ((c=getc(fout)) == EOF) {					perror_reply(550, name);					goto done;				}				if (c == '\n')					i++;			}			/*			 * We must do this seek to "current" position			 * because we are changing from reading to			 * writing.			 */			if (fseek(fout, 0L, SEEK_CUR) < 0) {				perror_reply(550, name);				goto done;			}		} else if (lseek(fileno(fout), restart_point, SEEK_SET) < 0) {			perror_reply(550, name);			goto done;		}	}	din = dataconn(name, (off_t)-1, "r");	if (din == NULL)		goto done;	if (receive_data(din, fout) == 0) {		if (unique)			reply(226, "Transfer complete (unique file name:%s).",			    name);		else			reply(226, "Transfer complete.");	}	(void) fclose(din);	data = -1;	pdata = -1;done:	LOGBYTES(*mode == 'w' ? "put" : "append", name, byte_count);	(*closefunc)(fout);}static FILE *getdatasock(mode)	char *mode;{	int on = 1, s, t, tries;	sigset_t allsigs;	if (data >= 0)		return (fdopen(data, mode));	sigfillset(&allsigs);	sigprocmask (SIG_BLOCK, &allsigs, NULL);	(void) seteuid((uid_t)0);	s = socket(AF_INET, SOCK_STREAM, 0);	if (s < 0)		goto bad;	if (setsockopt(s, SOL_SOCKET, SO_REUSEADDR,	    (char *) &on, sizeof(on)) < 0)		goto bad;	/* anchor socket to avoid multi-homing problems */	data_source.sin_len = sizeof(struct sockaddr_in);	data_source.sin_family = AF_INET;	data_source.sin_addr = ctrl_addr.sin_addr;	for (tries = 1; ; tries++) {		if (bind(s, (struct sockaddr *)&data_source,		    sizeof(data_source)) >= 0)			break;		if (errno != EADDRINUSE || tries > 10)			goto bad;		sleep(tries);	}	(void) seteuid((uid_t)pw->pw_uid);	sigfillset(&allsigs);	sigprocmask (SIG_UNBLOCK, &allsigs, NULL);#ifdef IP_TOS	on = IPTOS_THROUGHPUT;	if (setsockopt(s, IPPROTO_IP, IP_TOS, (char *)&on, sizeof(int)) < 0)		syslog(LOG_WARNING, "setsockopt (IP_TOS): %m");#endif#ifdef TCP_NOPUSH	/*	 * Turn off push flag to keep sender TCP from sending short packets	 * at the boundaries of each write().  Should probably do a SO_SNDBUF	 * to set the send buffer size as well, but that may not be desirable	 * in heavy-load situations.	 */	on = 1;	if (setsockopt(s, IPPROTO_TCP, TCP_NOPUSH, (char *)&on, sizeof on) < 0)		syslog(LOG_WARNING, "setsockopt (TCP_NOPUSH): %m");#endif#ifdef SO_SNDBUF	on = 65536;	if (setsockopt(s, SOL_SOCKET, SO_SNDBUF, (char *)&on, sizeof on) < 0)		syslog(LOG_WARNING, "setsockopt (SO_SNDBUF): %m");#endif	return (fdopen(s, mode));bad:	/* Return the real value of errno (close may change it) */	t = errno;	(void) seteuid((uid_t)pw->pw_uid);	sigfillset (&allsigs);	sigprocmask (SIG_UNBLOCK, &allsigs, NULL);	(void) close(s);	errno = t;	return (NULL);}