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

📄 daemon.c

📁 < linux网络编程工具>>配套源码
💻 C
📖 第 1 页 / 共 5 页
字号:
		if (pid == 0)
		{
			char *p;
			FILE *inchannel, *outchannel = NULL;

			/*
			**  CHILD -- return to caller.
			**	Collect verified idea of sending host.
			**	Verify calling user id if possible here.
			*/

			if (!control)
			{
				define(macid("{daemon_addr}", NULL),
				       newstr(anynet_ntoa(&Daemons[curdaemon].d_addr)),
				       &BlankEnvelope);
				(void) snprintf(status, sizeof status, "%d",
						ntohs(Daemons[curdaemon].d_port));
				define(macid("{daemon_port}", NULL),
				       newstr(status), &BlankEnvelope);
			}

			(void) releasesignal(SIGALRM);
			(void) releasesignal(SIGCHLD);
			(void) setsignal(SIGCHLD, SIG_DFL);
			(void) setsignal(SIGHUP, intsig);
			for (idx = 0; idx < ndaemons; idx++)
			{
				if (Daemons[idx].d_socket >= 0)
					(void) close(Daemons[idx].d_socket);
			}
			clrcontrol();

			/* Avoid SMTP daemon actions if control command */
			if (control)
			{
				/* Add control socket process */
				proc_list_add(getpid(), "console socket child",
					PROC_CONTROL_CHILD);
			}
			else
			{
				proc_list_clear();

				/* Add parent process as first child item */
				proc_list_add(getpid(), "daemon child",
					      PROC_DAEMON_CHILD);

				/* don't schedule queue runs if ETRN */
				QueueIntvl = 0;

				sm_setproctitle(TRUE, e, "startup with %s",
						anynet_ntoa(&RealHostAddr));
			}

			if (pipefd[0] != -1)
			{
				auto char c;

				/*
				**  Wait for the parent to close the write end
				**  of the pipe, which we will see as an EOF.
				**  This guarantees that we won't write to the
				**  socket until after the parent has closed
				**  the pipe.
				*/

				/* close the write end of the pipe */
				(void) close(pipefd[1]);

				/* we shouldn't be interrupted, but ... */
				while (read(pipefd[0], &c, 1) < 0 &&
				       errno == EINTR)
					continue;
				(void) close(pipefd[0]);
			}

			/* control socket processing */
			if (control)
			{
				control_command(t, e);

				/* NOTREACHED */
				exit(EX_SOFTWARE);
			}

			/* determine host name */
			p = hostnamebyanyaddr(&RealHostAddr);
			if (strlen(p) > (SIZE_T) MAXNAME)
				p[MAXNAME] = '\0';
			RealHostName = newstr(p);
			if (RealHostName[0] == '[')
			{
				/* TEMP, FAIL: which one? */
				define(macid("{client_resolve}", NULL),
				       (h_errno == TRY_AGAIN) ? "TEMP" : "FAIL",
				       &BlankEnvelope);
			}
			else
				define(macid("{client_resolve}", NULL), "OK",
				       &BlankEnvelope);
			sm_setproctitle(TRUE, e, "startup with %s", p);

			if ((inchannel = fdopen(t, "r")) == NULL ||
			    (t = dup(t)) < 0 ||
			    (outchannel = fdopen(t, "w")) == NULL)
			{
				syserr("cannot open SMTP server channel, fd=%d", t);
				finis(FALSE, EX_OK);
			}

			InChannel = inchannel;
			OutChannel = outchannel;
			DisConnected = FALSE;

# ifdef XLA
			if (!xla_host_ok(RealHostName))
			{
				message("421 4.4.5 Too many SMTP sessions for this host");
				finis(FALSE, EX_OK);
			}
# endif /* XLA */
			/* find out name for interface of connection */
			if (getsockname(fileno(InChannel), &sa.sa,
					&len) == 0)
			{
				p = hostnamebyanyaddr(&sa);
				if (tTd(15, 9))
					dprintf("getreq: got name %s\n", p);
				define(macid("{if_name}", NULL),
				       newstr(p), &BlankEnvelope);

				/* do this only if it is not the loopback */
				/* interface: how to figure out? XXX */
				if (!isloopback(sa))
				{
					define(macid("{if_addr}", NULL),
					       newstr(anynet_ntoa(&sa)),
					       &BlankEnvelope);
					p = xalloc(5);
					snprintf(p, 4, "%d", sa.sa.sa_family);
					define(macid("{if_family}", NULL), p,
					       &BlankEnvelope);
					if (tTd(15, 7))
						dprintf("getreq: got addr %s and family %s\n",
							macvalue(macid("{if_addr}", NULL),
								 &BlankEnvelope),
							macvalue(macid("{if_addr}", NULL),
								 &BlankEnvelope));
				}
				else
				{
					define(macid("{if_addr}", NULL), NULL,
					       &BlankEnvelope);
					define(macid("{if_family}", NULL), NULL,
					       &BlankEnvelope);
				}
			}
			else
			{
				if (tTd(15, 7))
					dprintf("getreq: getsockname failed\n");
				define(macid("{if_name}", NULL), NULL,
				       &BlankEnvelope);
				define(macid("{if_addr}", NULL), NULL,
				       &BlankEnvelope);
				define(macid("{if_family}", NULL), NULL,
				       &BlankEnvelope);
			}
			break;
		}

		/* parent -- keep track of children */
		if (control)
		{
			snprintf(status, sizeof status, "control socket server child");
			proc_list_add(pid, status, PROC_CONTROL);
		}
		else
		{
			snprintf(status, sizeof status,
				 "SMTP server child for %s",
				 anynet_ntoa(&RealHostAddr));
			proc_list_add(pid, status, PROC_DAEMON);
		}
		(void) releasesignal(SIGCHLD);

		/* close the read end of the synchronization pipe */
		if (pipefd[0] != -1)
		{
			(void) close(pipefd[0]);
			pipefd[0] = -1;
		}

		/* close the port so that others will hang (for a while) */
		(void) close(t);

		/* release the child by closing the read end of the sync pipe */
		if (pipefd[1] != -1)
		{
			(void) close(pipefd[1]);
			pipefd[1] = -1;
		}
	}

	if (tTd(15, 2))
		dprintf("getreq: returning\n");
	return &Daemons[curdaemon].d_flags;
}
/*
**  OPENDAEMONSOCKET -- open SMTP socket
**
**	Deals with setting all appropriate options.
**
**	Parameters:
**		d -- the structure for the daemon to open.
**		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 */

static int
opendaemonsocket(d, firsttime)
	struct daemon *d;
	bool firsttime;
{
	int on = 1;
	int fdflags;
	SOCKADDR_LEN_T socksize = 0;
	int ntries = 0;
	int save_errno;

	if (tTd(15, 2))
		dprintf("opendaemonsocket(%s)\n", d->d_name);

	do
	{
		if (ntries > 0)
			(void) sleep(5);
		if (firsttime || d->d_socket < 0)
		{
			d->d_socket = socket(d->d_addr.sa.sa_family,
					     SOCK_STREAM, 0);
			if (d->d_socket < 0)
			{
				save_errno = errno;
				syserr("opendaemonsocket: daemon %s: can't create server SMTP socket", d->d_name);
			  severe:
				if (LogLevel > 0)
					sm_syslog(LOG_ALERT, NOQID,
						  "daemon %s: problem creating SMTP socket", d->d_name);
				d->d_socket = -1;
				continue;
			}

			/* turn on network debugging? */
			if (tTd(15, 101))
				(void) setsockopt(d->d_socket, SOL_SOCKET,
						  SO_DEBUG, (char *)&on,
						  sizeof on);

			(void) setsockopt(d->d_socket, SOL_SOCKET,
					  SO_REUSEADDR, (char *)&on, sizeof on);
			(void) setsockopt(d->d_socket, SOL_SOCKET,
					  SO_KEEPALIVE, (char *)&on, sizeof on);

# ifdef SO_RCVBUF
			if (d->d_tcprcvbufsize > 0)
			{
				if (setsockopt(d->d_socket, SOL_SOCKET,
					       SO_RCVBUF,
					       (char *) &d->d_tcprcvbufsize,
					       sizeof(d->d_tcprcvbufsize)) < 0)
					syserr("opendaemonsocket: daemon %s: setsockopt(SO_RCVBUF)", d->d_name);
			}
# endif /* SO_RCVBUF */
# ifdef SO_SNDBUF
			if (d->d_tcpsndbufsize > 0)
			{
				if (setsockopt(d->d_socket, SOL_SOCKET,
					       SO_SNDBUF,
					       (char *) &d->d_tcpsndbufsize,
					       sizeof(d->d_tcpsndbufsize)) < 0)
					syserr("opendaemonsocket: daemon %s: setsockopt(SO_SNDBUF)", d->d_name);
			}
# endif /* SO_SNDBUF */

			if ((fdflags = fcntl(d->d_socket, F_GETFD, 0)) == -1 ||
			    fcntl(d->d_socket, F_SETFD,
				  fdflags | FD_CLOEXEC) == -1)
			{
				save_errno = errno;
				syserr("opendaemonsocket: daemon %s: failed to %s close-on-exec flag: %s",
				       d->d_name,
				       fdflags == -1 ? "get" : "set",
				       errstring(save_errno));
				(void) close(d->d_socket);
				goto severe;
			}

			switch (d->d_addr.sa.sa_family)
			{
# if NETINET
			  case AF_INET:
				socksize = sizeof d->d_addr.sin;
				break;
# endif /* NETINET */

# if NETINET6
			  case AF_INET6:
				socksize = sizeof d->d_addr.sin6;
				break;
# endif /* NETINET6 */

# if NETISO
			  case AF_ISO:
				socksize = sizeof d->d_addr.siso;
				break;
# endif /* NETISO */

			  default:
				socksize = sizeof d->d_addr;
				break;
			}

			if (bind(d->d_socket, &d->d_addr.sa, socksize) < 0)
			{
				/* probably another daemon already */
				save_errno = errno;
				syserr("opendaemonsocket: daemon %s: cannot bind",
				       d->d_name);
				(void) close(d->d_socket);
				goto severe;
			}
		}
		if (!firsttime &&
		    listen(d->d_socket, d->d_listenqueue) < 0)
		{
			save_errno = errno;
			syserr("opendaemonsocket: daemon %s: cannot listen",
			       d->d_name);
			(void) close(d->d_socket);
			goto severe;
		}
		return socksize;
	} while (ntries++ < MAXOPENTRIES && transienterror(save_errno));
	syserr("!opendaemonsocket: daemon %s: server SMTP socket wedged: exiting",
	       d->d_name);
	/* NOTREACHED */
	return -1;  /* avoid compiler warning on IRIX */
}
/*
**  SETUPDAEMON -- setup socket for daemon
**
**	Parameters:
**		daemonaddr -- socket for daemon
**		daemon -- number of daemon
**
**	Returns:
**		port number on which daemon should run
**
*/
static u_short
setupdaemon(daemonaddr)
	SOCKADDR *daemonaddr;
{
	u_short port;

	/*
	**  Set up the address for the mailer.
	*/

	if (daemonaddr->sa.sa_family == AF_UNSPEC)
	{
		memset(daemonaddr, '\0', sizeof *daemonaddr);
# if NETINET
		daemonaddr->sa.sa_family = AF_INET;
# endif /* NETINET */
	}

	switch (daemonaddr->sa.sa_family)
	{
# if NETINET
	  case AF_INET:
		if (daemonaddr->sin.sin_addr.s_addr == 0)
			daemonaddr->sin.sin_addr.s_addr = INADDR_ANY;
		port = daemonaddr->sin.sin_port;
		break;
# endif /* NETINET */

# if NETINET6
	  case AF_INET6:
		if (IN6_IS_ADDR_UNSPECIFIED(&daemonaddr->sin6.sin6_addr))
			daemonaddr->sin6.sin6_addr = in6addr_any;
		port = daemonaddr->sin6.sin6_port;
		break;
# endif /* NETINET6 */

	  default:
		/* unknown protocol */
		port = 0;
		break;
	}
	if (port == 0)
	{
# ifdef NO_GETSERVBYNAME
		port = htons(25);
# else /* NO_GETSERVBYNAME */
		{
			register struct servent *sp;

			sp = getservbyname("smtp", "tcp");
			if (sp == NULL)
			{
				syserr("554 5.3.5 service \"smtp\" unknown");
				port = htons(25);
			}
			else
				port = sp->s_port;
		}
# endif /* NO_GETSERVBYNAME */
	}

	switch (daemonaddr->sa.sa_family)
	{
# if NETINET
	  case AF_INET:
		daemonaddr->sin.sin_port = port;
		break;
# endif /* NETINET */

# if NETINET6
	  case AF_INET6:
		daemonaddr->sin6.sin6_port = port;
		break;
# endif /* NETINET6 */

	  default:
		/* unknown protocol */
		break;
	}
	return(port);
}
/*
**  CLRDAEMON -- reset the daemon connection
**
**	Parameters:
**		none.
**
**	Returns:
**		none.
**
**	Side Effects:
**		releases any resources used by the passive daemon.
*/

void
clrdaemon()
{
	int i;

	for (i = 0; i < ndaemons; i++)
	{
		if (Daemons[i].d_socket >= 0)
			(void) close(Daemons[i].d_socket);
		Daemons[i].d_socket = -1;
	}
}
/*
**  SETSOCKADDROPTIONS -- set options for SOCKADDR (daemon or client)
**
**	Parameters:
**		p -- the options line.
**		d -- the daemon structure to fill in.
**
**	Returns:
**		none.
*/

static void
setsockaddroptions(p, d)
	register char *p;
	struct daemon *d;
{
# if NETISO
	short port;
# endif /* NETISO */
	int l;
	char *h, *flags;

# if NETINET
	if (d->d_addr.sa.sa_family == AF_UNSPEC)
		d->d_addr.sa.sa_family = AF_INET;
# endif /* NETINET */

	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;
		if (isascii(*f) && islower(*f))
			*f = toupper(*f);

		switch (*f)
		{
		  case 'F':		/* address family */
			if (isascii(*v) && isdigit(*v))
				d->d_addr.sa.sa_family = atoi(v);
# if NETINET
			else if (strcasecmp(v, "inet") == 0)
				d->d_addr.sa.sa_family = AF_INET;
# endif /* NETINET */
# if NETINET6
			else if (strcasecmp(v, "inet6") == 0)
				d->d_addr.sa.sa_family = AF_INET6;
# endif /* NETINET6 */
# if NETISO
			else if (strcasecmp(v, "iso") == 0)
				d->d_addr.sa.sa_family = AF_ISO;
# endif /* NETISO */
# if NETNS
			else if (strcasecmp(v, "ns") == 0)
				d->d_addr.sa.sa_family = AF_NS;
# endif /* NETNS */
# if NETX25
			else if (strcasecmp(v, "x.25") == 0)
				d->d_addr.sa.sa_family = AF_CCITT;
# endif /* NETX25 */
			else
				syserr("554 5.3.5 Unknown address family %s in Family=option",
				       v);
			break;

		  case 'A':		/* address */
			switch (d->d_addr.sa.sa_family)

⌨️ 快捷键说明

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