On Thursday 23 May 2002 06:40 pm, Peter Long reputedly wrote:

> Hi all,
>
> I have a console application that I want to turn into a daemon. Does anyone
> know where I can find documentation on how to do that.
>
> Thanks in advance.


Here's my daemon launcher.  It is more than a basic daemon launcher because I 
have N daemons that all talk to each other.  Furthermore, I don't want any 
daemons to start doing business until all the other daemons are ready.

-- 
Mike Mueller
www.ss7box.com
#include	<sys/stat.h>
#include	<sys/msg.h>
#include	<fcntl.h>
#include	<syslog.h>
#include	<stdio.h>
#include	<unistd.h>
#include	<errno.h>
#include	"ipc_mq.h"

#define		MAX_DAEMONS	5
#define		DAEMON_PATH	"usr/local/ss7t/bin/"

char		*env_init[] = {"USER=mtp3d", "PATH=/tmp", NULL};
char		*daemon_names[][MAX_DAEMONS] = {
			"mtp3_d",
			"tali_d",
//			"sctp_d",
			"oam_d",
			"mr_d",
			"ps_d"
		};

int			sockfd;
struct sockaddr_in	myaddr, peeraddr;
t_ipc_mqbuf		mb;
socklen_t		sockaddrlen;

void get_busy (unsigned int daemon_id)
/******************************************************************************
******************************************************************************/
{
int	r;

	bzero(&peeraddr, sizeof(peeraddr));
	peeraddr.sin_family = AF_INET;
	peeraddr.sin_port = htons(daemon_id);
	r = inet_pton(AF_INET, IPC_ADDR_STR, &peeraddr.sin_addr.s_addr);
	if (r == -1)
		{
		syslog (LOG_INFO, "F:daemon_launcher:get_busy:inet_pton failed:%s",
				strerror(errno));
		exit (-1);
		}

	bzero (&mb, sizeof(mb));
	mb.mhdr.s_id = DLAUNCH_ID; // this is the letter sender
	mb.mhdr.mcode = IPC_PROCEED; 
	mb.mhdr.mlen = sizeof(t_ipc_mb_hdr);

	r = sendto (sockfd, &mb, mb.mhdr.mlen, NOFLAGS, 
			&peeraddr, sizeof (peeraddr));
	if (r == -1)
		{
		syslog (LOG_INFO, "F:get busy:sendto failed:cause %s target: %s", 
				strerror(errno), daemon_id);
		exit (-1);
		}
}

int daemon_init(char *p_daemon_fname)
/******************************************************************************
******************************************************************************/
{
char	daemon_pathname [128];
	pid_t	pid;

	if ( (pid = fork()) < 0)
		return(-1);
	else if (pid != 0)
		return (0);	/* the parent process returns from this function here */

// the child process continues here

	setsid();		/* become session leader */
	chdir("/");		/* change working directory */
	umask(0);		/* clear our file mode creation mask */

	if ((strlen (p_daemon_fname) + strlen (DAEMON_PATH)+ 1) > sizeof (daemon_pathname))
		{
		syslog (LOG_INFO, "daemon pathname too long");
		exit (-1);
		}

// exec the daemon in the child process 

	execl 	(
		strcat (strcpy (daemon_pathname,DAEMON_PATH), p_daemon_fname), 
		p_daemon_fname,
		(char *) 0
		);
	
// should never reach this statement

	exit(0);
}

int daemon_comm_ready (void)
/******************************************************************************
******************************************************************************/
{
ssize_t	bw;
u_long	daemons_ready;

	daemons_ready = 0;

	for (;;)
		{
// blocking read; wait for a daemon to report for duty; if this becomes
// a block-forever condition, then one must resort to killing process
// use "ps -axj" as superuser to find the processes to be killed

		bw = recvfrom (sockfd, &mb, sizeof (mb), NOFLAGS, 
			&peeraddr, &sockaddrlen);
		if (bw == -1)
			{
			syslog (LOG_INFO, "F:daemon_comm_ready:recvfrom failed");
			exit (-1);
			}

// show who's ready for duty; add a string termination

		//mb.mdata[mb.mhdr.mlen - sizeof(t_ipc_mb_hdr)] = '\0';
		syslog (LOG_INFO, "I:mb contents:s_id %d daemon on duty: %s", 
				mb.mhdr.s_id, 
				&mb.mdata);
		
		daemons_ready = daemons_ready | mb.mhdr.s_id;
		if (daemons_ready == ALL_DAEMONS_READY)
			{
			syslog (LOG_INFO, "I:daemon_comm_ready:all daemons ready");
			break;
			}
		} // end of for loop

// tell the daemons that IPC may proceed

	get_busy (MTP3_PORT);
	get_busy (TALI_PORT);
//	get_busy (SCTP_IPC_PORT);
	get_busy (OAM_PORT);
	get_busy (MR_PORT);
	get_busy (PS_PORT);
}

int	configure_dl()
/******************************************************************************
******************************************************************************/
{
	//dlConf = new c_confReader("dl");
	//delete dlConf
}

int main (int argc, char **argv)
/******************************************************************************
******************************************************************************/
{
int	d;
int	r;

	openlog ("daemon_init" ,LOG_PID, LOG_USER);
	syslog (LOG_INFO ,"Daemon launcher starting");

// read daemon launcher conf file
	
	configure_dl();
	
	sockfd = socket(AF_INET, SOCK_DGRAM, 0);
	if (sockfd == -1)
		{
		syslog (LOG_INFO, "socket failed");
		exit (-1);
		}

// create an Internet Protocol address

	bzero(&myaddr, sizeof(myaddr));
	myaddr.sin_family = AF_INET;
	myaddr.sin_port = htons(DLAUNCH_PORT);
	r = inet_pton(AF_INET, IPC_ADDR_STR, &myaddr.sin_addr.s_addr);
	if (r == -1)
		{
		syslog (LOG_INFO, "I:daemon_launcher:main:inet_pton failed:%s",
				strerror(errno));
		exit (-1);
		}

	r = bind (sockfd, (const struct sockaddr *) &myaddr, sizeof(myaddr));
	if (r == -1)
		{
		syslog (LOG_INFO, "bind failed");
		exit (-1);
		}

	for (d = 0; d < MAX_DAEMONS; d++) 
		{
		if (daemon_init (daemon_names [0][d]) == -1)
			{
			syslog (LOG_INFO, "fork failed; daemon ID: %s\n", daemon_names[d]);
			return (-1);
			}
		}

	if (daemon_comm_ready () == -1)
		{
		}
	return (0);
}

Reply via email to