⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 daemon.c

📁 早期freebsd实现
💻 C
📖 第 1 页 / 共 3 页
字号:
/* * Copyright (c) 1983 Eric P. Allman * Copyright (c) 1988, 1993 *	The Regents of the University of California.  All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright *    notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright *    notice, this list of conditions and the following disclaimer in the *    documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software *    must display the following acknowledgement: *	This product includes software developed by the University of *	California, Berkeley and its contributors. * 4. Neither the name of the University nor the names of its contributors *    may be used to endorse or promote products derived from this software *    without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */#include <errno.h>#include "sendmail.h"#ifndef lint#ifdef DAEMONstatic char sccsid[] = "@(#)daemon.c	8.48 (Berkeley) 4/18/94 (with daemon mode)";#elsestatic char sccsid[] = "@(#)daemon.c	8.48 (Berkeley) 4/18/94 (without daemon mode)";#endif#endif /* not lint */#ifdef DAEMON# include <netdb.h># include <arpa/inet.h>#if NAMED_BIND# include <arpa/nameser.h># include <resolv.h>#endif/***  DAEMON.C -- routines to use when running as a daemon.****	This entire file is highly dependent on the 4.2 BSD**	interprocess communication primitives.  No attempt has**	been made to make this file portable to Version 7,**	Version 6, MPX files, etc.  If you should try such a**	thing yourself, I recommend chucking the entire file**	and starting from scratch.  Basic semantics are:****	getrequests()**		Opens a port and initiates a connection.**		Returns in a child.  Must set InChannel and**		OutChannel appropriately.**	clrdaemon()**		Close any open files associated with getting**		the connection; this is used when running the queue,**		etc., to avoid having extra file descriptors during**		the queue run and to avoid confusing the network**		code (if it cares).**	makeconnection(host, port, outfile, infile, usesecureport)**		Make a connection to the named host on the given**		port.  Set *outfile and *infile to the files**		appropriate for communication.  Returns zero on**		success, else an exit status describing the**		error.**	host_map_lookup(map, hbuf, avp, pstat)**		Convert the entry in hbuf into a canonical form.*//***  GETREQUESTS -- open mail IPC port and get requests.****	Parameters:**		none.****	Returns:**		none.****	Side Effects:**		Waits until some interesting activity occurs.  When**		it does, a child is created to process it, and the**		parent waits for completion.  Return from this**		routine is always in the child.  The file pointers**		"InChannel" and "OutChannel" should be set to point**		to the communication channel.*/int		DaemonSocket	= -1;		/* fd describing socket */SOCKADDR	DaemonAddr;			/* socket for incoming */int		ListenQueueSize = 10;		/* size of listen queue */int		TcpRcvBufferSize = 0;		/* size of TCP receive buffer */int		TcpSndBufferSize = 0;		/* size of TCP send buffer */getrequests(){	int t;	bool refusingconnections = TRUE;	FILE *pidf;	int socksize;#ifdef XDEBUG	bool j_has_dot;#endif	extern void reapchild();	/*	**  Set up the address for the mailer.	*/	if (DaemonAddr.sin.sin_family == 0)		DaemonAddr.sin.sin_family = AF_INET;	if (DaemonAddr.sin.sin_addr.s_addr == 0)		DaemonAddr.sin.sin_addr.s_addr = INADDR_ANY;	if (DaemonAddr.sin.sin_port == 0)	{		register struct servent *sp;		sp = getservbyname("smtp", "tcp");		if (sp == NULL)		{			syserr("554 service \"smtp\" unknown");			DaemonAddr.sin.sin_port = htons(25);		}		else			DaemonAddr.sin.sin_port = sp->s_port;	}	/*	**  Try to actually open the connection.	*/	if (tTd(15, 1))		printf("getrequests: port 0x%x\n", DaemonAddr.sin.sin_port);	/* get a socket for the SMTP connection */	socksize = opendaemonsocket(TRUE);	(void) setsignal(SIGCHLD, reapchild);	/* write the pid to the log file for posterity */	pidf = fopen(PidFile, "w");	if (pidf != NULL)	{		extern char *CommandLineArgs;		/* write the process id on line 1 */		fprintf(pidf, "%d\n", getpid());		/* line 2 contains all command line flags */		fprintf(pidf, "%s\n", CommandLineArgs);		/* flush and close */		fclose(pidf);	}#ifdef XDEBUG	{		char jbuf[MAXHOSTNAMELEN];		expand("\201j", jbuf, &jbuf[sizeof jbuf - 1], CurEnv);		j_has_dot = strchr(jbuf, '.') != NULL;	}#endif	if (tTd(15, 1))		printf("getrequests: %d\n", DaemonSocket);	for (;;)	{		register int pid;		auto int lotherend;		extern bool refuseconnections();		/* see if we are rejecting connections */		CurrentLA = getla();		if (refuseconnections())		{			if (DaemonSocket >= 0)			{				/* close socket so peer will fail quickly */				(void) close(DaemonSocket);				DaemonSocket = -1;			}			refusingconnections = TRUE;			setproctitle("rejecting connections: load average: %d",				CurrentLA);			sleep(15);			continue;		}		if (refusingconnections)		{			/* start listening again */			(void) opendaemonsocket(FALSE);			setproctitle("accepting connections");			refusingconnections = FALSE;		}#ifdef XDEBUG		/* check for disaster */		{			register STAB *s;			char jbuf[MAXHOSTNAMELEN];			expand("\201j", jbuf, &jbuf[sizeof jbuf - 1], CurEnv);			if ((s = stab(jbuf, ST_CLASS, ST_FIND)) == NULL ||			    !bitnset('w', s->s_class))			{				dumpstate("daemon lost $j");				syslog(LOG_ALERT, "daemon process doesn't have $j in $=w; see syslog");				abort();			}			else if (j_has_dot && strchr(jbuf, '.') == NULL)			{				dumpstate("daemon $j lost dot");				syslog(LOG_ALERT, "daemon process $j lost dot; see syslog");				abort();			}		}#endif		/* wait for a connection */		do		{			errno = 0;			lotherend = socksize;			t = accept(DaemonSocket,			    (struct sockaddr *)&RealHostAddr, &lotherend);		} while (t < 0 && errno == EINTR);		if (t < 0)		{			syserr("getrequests: accept");			sleep(5);			continue;		}		/*		**  Create a subprocess to process the mail.		*/		if (tTd(15, 2))			printf("getrequests: forking (fd = %d)\n", t);		pid = fork();		if (pid < 0)		{			syserr("daemon: cannot fork");			sleep(10);			(void) close(t);			continue;		}		if (pid == 0)		{			char *p;			extern char *hostnamebyanyaddr();			/*			**  CHILD -- return to caller.			**	Collect verified idea of sending host.			**	Verify calling user id if possible here.			*/			(void) setsignal(SIGCHLD, SIG_DFL);			DisConnected = FALSE;			setproctitle("startup with %s",				anynet_ntoa(&RealHostAddr));			/* determine host name */			p = hostnamebyanyaddr(&RealHostAddr);			RealHostName = newstr(p);			setproctitle("startup with %s", p);#ifdef LOG			if (LogLevel > 11)			{				/* log connection information */				syslog(LOG_INFO, "connect from %s (%s)",					RealHostName, anynet_ntoa(&RealHostAddr));			}#endif			(void) close(DaemonSocket);			if ((InChannel = fdopen(t, "r")) == NULL ||			    (t = dup(t)) < 0 ||			    (OutChannel = fdopen(t, "w")) == NULL)			{				syserr("cannot open SMTP server channel, fd=%d", t);				exit(0);			}			/* should we check for illegal connection here? XXX */#ifdef XLA			if (!xla_host_ok(RealHostName))			{				message("421 Too many SMTP sessions for this host");				exit(0);			}#endif			if (tTd(15, 2))				printf("getreq: returning\n");			return;		}		/* close the port so that others will hang (for a while) */		(void) close(t);	}	/*NOTREACHED*/}/***  OPENDAEMONSOCKET -- open the SMTP socket****	Deals with setting all appropriate options.  DaemonAddr must**	be set up in advance.****	Parameters:**		firsttime -- set if this is the initial open.****	Returns:**		Size in bytes of the daemon socket addr.****	Side Effects:**		Leaves DaemonSocket set to the open socket.**		Exits if the socket cannot be created.*/#define MAXOPENTRIES	10	/* maximum number of tries to open connection */intopendaemonsocket(firsttime)	bool firsttime;{	int on = 1;	int socksize;	int ntries = 0;	int saveerrno;	if (tTd(15, 2))		printf("opendaemonsocket()\n");	do	{		if (ntries > 0)			sleep(5);		if (firsttime || DaemonSocket < 0)		{			DaemonSocket = socket(DaemonAddr.sa.sa_family, SOCK_STREAM, 0);			if (DaemonSocket < 0)			{				/* probably another daemon already */				saveerrno = errno;				syserr("opendaemonsocket: can't create server SMTP socket");			  severe:# ifdef LOG				if (LogLevel > 0)					syslog(LOG_ALERT, "problem creating SMTP socket");# endif /* LOG */				DaemonSocket = -1;				continue;			}			/* turn on network debugging? */			if (tTd(15, 101))				(void) setsockopt(DaemonSocket, SOL_SOCKET,						  SO_DEBUG, (char *)&on,						  sizeof on);			(void) setsockopt(DaemonSocket, SOL_SOCKET,					  SO_REUSEADDR, (char *)&on, sizeof on);			(void) setsockopt(DaemonSocket, SOL_SOCKET,					  SO_KEEPALIVE, (char *)&on, sizeof on);#ifdef SO_RCVBUF			if (TcpRcvBufferSize > 0)			{				if (setsockopt(DaemonSocket, SOL_SOCKET,					       SO_RCVBUF,					       (char *) &TcpRcvBufferSize,					       sizeof(TcpRcvBufferSize)) < 0)					syserr("getrequests: setsockopt(SO_RCVBUF)");			}#endif			switch (DaemonAddr.sa.sa_family)			{# ifdef NETINET			  case AF_INET:				socksize = sizeof DaemonAddr.sin;				break;# endif# ifdef NETISO			  case AF_ISO:				socksize = sizeof DaemonAddr.siso;				break;# endif			  default:				socksize = sizeof DaemonAddr;				break;			}			if (bind(DaemonSocket, &DaemonAddr.sa, socksize) < 0)			{				saveerrno = errno;				syserr("getrequests: cannot bind");				(void) close(DaemonSocket);				goto severe;			}		}		if (!firsttime && listen(DaemonSocket, ListenQueueSize) < 0)		{			saveerrno = errno;			syserr("getrequests: cannot listen");			(void) close(DaemonSocket);			goto severe;		}		return socksize;	} while (ntries++ < MAXOPENTRIES && transienterror(saveerrno));	finis();}/***  CLRDAEMON -- reset the daemon connection****	Parameters:**		none.****	Returns:**		none.****	Side Effects:**		releases any resources used by the passive daemon.*/clrdaemon(){	if (DaemonSocket >= 0)		(void) close(DaemonSocket);	DaemonSocket = -1;}/***  SETDAEMONOPTIONS -- set options for running the daemon****	Parameters:**		p -- the options line.****	Returns:**		none.*/setdaemonoptions(p)	register char *p;{	if (DaemonAddr.sa.sa_family == AF_UNSPEC)		DaemonAddr.sa.sa_family = AF_INET;	while (p != NULL)	{		register char *f;		register char *v;		while (isascii(*p) && isspace(*p))			p++;		if (*p == '\0')			break;		f = p;		p = strchr(p, ',');		if (p != NULL)			*p++ = '\0';		v = strchr(f, '=');		if (v == NULL)			continue;		while (isascii(*++v) && isspace(*v))			continue;		switch (*f)		{		  case 'F':		/* address family */			if (isascii(*v) && isdigit(*v))				DaemonAddr.sa.sa_family = atoi(v);#ifdef NETINET			else if (strcasecmp(v, "inet") == 0)				DaemonAddr.sa.sa_family = AF_INET;#endif#ifdef NETISO			else if (strcasecmp(v, "iso") == 0)				DaemonAddr.sa.sa_family = AF_ISO;#endif#ifdef NETNS			else if (strcasecmp(v, "ns") == 0)				DaemonAddr.sa.sa_family = AF_NS;#endif#ifdef NETX25			else if (strcasecmp(v, "x.25") == 0)				DaemonAddr.sa.sa_family = AF_CCITT;#endif			else				syserr("554 Unknown address family %s in Family=option", v);			break;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -