[Dev] HOWTO write a daemon

Andrew C. Oliver dev@trilug.org
Fri, 24 May 2002 08:14:09 -0400


just make sure you start it as some other user than root.

David A. Cafaro wrote:

>Just curious but what is wrong with just writing a program that doesn't
>put out any text to the console and starting it with a script with a
>command like this:
>
>mydaemon&
>
>Besides the fact that it's a little less elegant?
>
>It's been a long long time since I did C/C++ coding and righting
>daemons.  I'm planning on writing up a little tcp/ip daemon for my
>Zaurus.  Thanks for any input.
>
>-David
>
>On Thu, 2002-05-23 at 19:13, M. Mueller wrote:
>  
>
>>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);
>>}
>>    
>>
>
>
>
>_______________________________________________
>Dev mailing list
>Dev@trilug.org
>http://www.trilug.org/mailman/listinfo/dev
>
>  
>