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);
}