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

📄 daemon.c

📁 操作系统SunOS 4.1.3版本的源码
💻 C
📖 第 1 页 / 共 2 页
字号:
/* * Copyright (c) 1988 Regents of the University of California. * All rights reserved. * * Redistribution and use in source and binary forms are permitted * provided that this notice is preserved and that due credit is given * to the University of California at Berkeley. The name of the University * may not be used to endorse or promote products derived from this * software without specific prior written permission. This software * is provided ``as is'' without express or implied warranty. * *  Sendmail *  Copyright (c) 1983  Eric P. Allman *  Berkeley, California */# include <errno.h># include "sendmail.h"#ifdef DAEMON#include "netdb.h"#include <sys/wait.h>#include <sys/param.h>#include <net/if.h>#include <sys/sockio.h>SCCSID(@(#)daemon.c 1.1 92/07/30 SMI (with daemon mode)); /* from UCB 5.25 4/1/88*//***  DAEMON.C -- routines to use when running as a daemon.****	This entire file is highly dependent on the 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)**		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 and errno describing the**		error.**	maphostname(hbuf, hbufsize)**		Convert the entry in hbuf into a canonical form.  It**		may not be larger than hbufsize.**	lookuphost(host)**		Look up the host to determine an address.  Return**		the address of a struct hostinfo about the host, which**		may be modified by the caller if desired.**	closeconnection(fd)**		Marks the host which we connected to via file desc 'fd'**		as closed, so we won't try to reuse the connection.**		Note that this does not actually close the file**		descriptor.  That's the caller's responsibility.*/static struct hostinfo *host_from_fd[NOFILE];	/* Host entry for each */static setuphost(sp, hp)    STAB *sp;    struct hostent *hp;  {# if BSD >= 43    int i;    for (i= 0; i < MAXMXHOSTS && *hp->h_addr_list; i++)	sp->s_value.sv_host.h_addrlist[ i ] = 		*(struct in_addr *)(*hp->h_addr_list++);    sp->s_value.sv_host.h_addrlist[ i ].s_addr = INADDR_ANY;# else     sp->s_value.sv_host.h_addrlist[ 0 ] = *(struct in_addr *)(hp->h_addr);    sp->s_value.sv_host.h_addrlist[ 1 ].s_addr = INADDR_ANY;# endif  }static jmp_buf NameTimeout;time_t nametime = 90;		/* seconds to wait for name server */nametimeout()  {longjmp(NameTimeout, 1);}/***  LOOKUPHOST -- determine host address and other remembered info.****	Parameters:**		host -- a char * providing a host name or [a.b.c.d].****	Returns:**		The address of a struct hostinfo for this host.**		The caller may modify h_fd, h_down, and h_open in**		this structure.  h_addr and h_exists should not be**		modified.****	Side Effects:**		If the hostname has previously been looked up, the**		existing symbol table entry is returned immediately.**		Otherwise, a new symbol table entry is created, **		a system-dependent hostname->address lookup is done,**		and the new entry is returned.****		Note that for information to be remembered in the**		symbol table, the process must do several lookups**		without forking and exiting.*/struct hostinfo *lookuphost(host)	char *host;			/* Host name */{	register struct hostent *hp = (struct hostent *)NULL;	extern char *inet_ntoa();	STAB	*sp;			/* Symbol table entry */	EVENT *ev;	sp = stab(host, ST_HOST, ST_ENTER);	if (sp->s_value.sv_host.h_valid) {		AlreadyKnown = sp->s_value.sv_host.h_down;		return &sp->s_value.sv_host;	}	/*	**  Create a new symbol table entry.  Initially it is cleared,	**  thus h_exists is 0.  Ditto for the other flags.	**  Then look up the address for the host.	**	Accept "[a.b.c.d]" syntax for host name.	*/	sp->s_value.sv_host.h_valid = 1;	if (host[0] == '[')	{		long hid;		register char *p = index(host, ']');		if (p != NULL)		{			*p = '\0';			hid = inet_addr(&host[1]);			*p = ']';		}		if (p == NULL || hid == -1)		{			sp->s_value.sv_host.h_exists = 0;		}		else		{			sp->s_value.sv_host.h_addrlist[0].s_addr = hid;			sp->s_value.sv_host.h_index = 0;			sp->s_value.sv_host.h_exists = 1;		}		return &sp->s_value.sv_host;		/* Return [] entry */	}	if (setjmp(NameTimeout) != 0) {		sp->s_value.sv_host.h_exists = 1;		sp->s_value.sv_host.h_down = 1;		sp->s_value.sv_host.h_errno = ENAMESER;		return &sp->s_value.sv_host;	}	ev = setevent(nametime, nametimeout, 0);	hp = gethostbyname(host);	if (hp != NULL && hp->h_addrtype == AF_INET)	{		setuphost(sp, hp);		sp->s_value.sv_host.h_index = 0;		sp->s_value.sv_host.h_exists = 1;	}   /*    * The gethostbyname failed -- in 4.2BSD we just return    * a hard error.  4.3BSD gives us more infomation on the failure.    * This failure can be returned by the YP library as of 4.1    */	else if (h_errno == TRY_AGAIN) 	{		sp->s_value.sv_host.h_exists = 1;		sp->s_value.sv_host.h_down = 1;		sp->s_value.sv_host.h_errno = ENAMESER;	}	clrevent(ev);	return &sp->s_value.sv_host;		/* Return new entry */}/***  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 */char	*NetName;			/* name of home (local?) network */getrequests(){	int t;	union wait status;	struct sockaddr_in	addr;	int on = 1;	extern reapchild();	/*	**  Try to actually open the connection.	*/	addr.sin_family = AF_INET;	addr.sin_addr.s_addr = INADDR_ANY;	addr.sin_port = htons(IPPORT_SMTP);	/* get a socket for the SMTP connection */	DaemonSocket = socket(AF_INET, SOCK_STREAM, 0);	if (DaemonSocket < 0)	{		/* probably another daemon already */		syserr("getrequests: can't create socket");	  severe:# ifdef LOG# ifdef LOG_SALERT		if (LogLevel > 0)			syslog(LOG_SALERT, "cannot get connection");# else LOG_SALERT		if (LogLevel > 0)			syslog(LOG_CRIT|LOG_MAIL, "cannot get connection");# endif LOG_SALERT# endif LOG		finis();	}#ifdef DEBUG	/* turn on network debugging? */	if (tTd(15, 15))		(void) setsockopt(DaemonSocket, SOL_SOCKET, SO_DEBUG, (char *)&on, sizeof on);#endif DEBUG	(void) setsockopt(DaemonSocket, SOL_SOCKET, SO_REUSEADDR, (char *)&on, sizeof on);	(void) setsockopt(DaemonSocket, SOL_SOCKET, SO_KEEPALIVE, (char *)&on, sizeof on);	if (bind(DaemonSocket, &addr, sizeof addr) < 0)	{		syserr("getrequests: cannot bind");		(void) close(DaemonSocket);		goto severe;	}	if (listen(DaemonSocket, 5) < 0)	{		syserr("getrequests: cannot listen");		(void) close(DaemonSocket);		goto severe;	}	(void) signal(SIGCHLD, reapchild);# ifdef DEBUG	if (tTd(15, 1))		printf("getrequests: %d\n", DaemonSocket);# endif DEBUG# ifdef LOG	/* Tell the log that a new daemon has started. */	syslog(LOG_INFO, "network daemon starting");# endif LOG	for (;;)	{		register int pid;		auto int lotherend;		struct sockaddr_in otherend;		extern int RefuseLA;		/* see if we are rejecting connections */		while (RefuseLA > 0 && getla() > RefuseLA)			sleep(5);		/* wait for a connection */		do		{			errno = 0;			lotherend = sizeof otherend;			t = accept(DaemonSocket, &otherend, &lotherend);		} while (t < 0 && errno == EINTR);		if (t < 0)		{			syserr("getrequests: accept");			sleep(5);			continue;		}		/*		**  Create a subprocess to process the mail.		*/# ifdef DEBUG		if (tTd(15, 2))			printf("getrequests: forking (fd = %d)\n", t);# endif DEBUG		pid = fork();		if (pid < 0)		{			syserr("daemon: cannot fork");			sleep(10);			(void) close(t);			continue;		}		if (pid == 0)		{			extern struct hostent *gethostbyaddr();			register struct hostent *hp;			char buf[MAXNAME];			EVENT *ev;			/*			**  CHILD -- return to caller.			**	Collect verified idea of sending host.			**	Verify calling user id if possible here.			*/			(void) signal(SIGCHLD, SIG_DFL);			/* determine host name with timeout */			if (setjmp(NameTimeout) != 0) {			    hp = NULL;			}			else {			    ev = setevent(nametime, nametimeout, 0);			    hp = gethostbyaddr(		&otherend.sin_addr, sizeof otherend.sin_addr, AF_INET);			    clrevent(ev);			}			if (hp != NULL)			{				(void) strcpy(buf, hp->h_name);				if (NetName != NULL && NetName[0] != '\0' &&				    index(hp->h_name, '.') == NULL)				{					(void) strcat(buf, ".");					(void) strcat(buf, NetName);				}			}			else			{				extern char *inet_ntoa();				/* produce a dotted quad */				(void) sprintf(buf, "[%s]",					inet_ntoa(otherend.sin_addr));			}			/* should we check for illegal connection here? XXX */			RealHostName = newstr(buf);			(void) close(DaemonSocket);			setproctitle("From %s", (int)RealHostName);			define('r', "TCP", CurEnv);			InChannel = fdopen(t, "r");			OutChannel = fdopen(t, "w");# ifdef DEBUG			if (tTd(15, 2))				printf("getreq: returning\n");# endif DEBUG# ifdef LOG			if (LogLevel > 11)				syslog(LOG_DEBUG, "connected, pid=%d", getpid());# endif LOG			return;		}		/* close the port so that others will hang (for a while) */		(void) close(t);	}	/*NOTREACHED*/}/***  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;}/***  MAKECONNECTION -- make a connection to an SMTP socket on another machine.****	Parameters:**		host -- the name of the host.

⌨️ 快捷键说明

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