[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
>
>
>