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