Welcome to Dream.In.Code
Become a C++ Expert!

Join 137,427 C++ Programmers for FREE! Get instant access to thousands of C++ experts, tutorials, code snippets, and more! There are 1,901 people online right now. Registration is fast and FREE... Join Now!




Passing Commands to a Daemonized Program

 
Reply to this topicStart new topic

Passing Commands to a Daemonized Program

GigaRoc
16 Jan, 2008 - 07:27 PM
Post #1

New D.I.C Head
*

Joined: 16 Jan, 2008
Posts: 6

CODE
#include <stdio.h>
#include <string.h>
#include <time.h>
#include <inotifytools/inotifytools.h>
#include <inotifytools/inotify.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <syslog.h>
#include <errno.h>
#include <pwd.h>
#include <signal.h>


#define DAEMON_NAME "gnotify"

// Change this to the user under which to run
#define RUN_AS_USER "gigaroc"

#define EXIT_SUCCESS 0
#define EXIT_FAILURE 1
FILE *oFile;

static void child_handler(int signum)
{
    switch(signum) {
    case SIGALRM: exit(EXIT_FAILURE); break;
    case SIGUSR1: exit(EXIT_SUCCESS); break;
    case SIGCHLD: exit(EXIT_FAILURE); break;
    }
}

static void daemonize( const char *lockfile )
{
    pid_t pid, sid, parent;
    int lfp = -1;

    // already a daemon
    if ( getppid() == 1 ) return;
    // Create the lock file as the current user
    if ( lockfile && lockfile[0] ) {
        lfp = open(lockfile,O_RDWR|O_CREAT,0640);
        if ( lfp < 0 ) {
            printf("unable to create lock file %s, code=%d (%s)",
                    lockfile, errno, strerror(errno));
            syslog( LOG_ERR, "unable to create lock file %s, code=%d (%s)",
                    lockfile, errno, strerror(errno) );
            exit(EXIT_FAILURE);
        }
    }
    // Drop user if there is one, and we were run as root
    if ( getuid() == 0 || geteuid() == 0 ) {
        struct passwd *pw = getpwnam(RUN_AS_USER);
        if ( pw ) {
            syslog( LOG_NOTICE, "setting user to " RUN_AS_USER );
            setuid( pw->pw_uid );
        }
    }
    // Trap signals that we expect to recieve
    signal(SIGCHLD,child_handler);
    signal(SIGUSR1,child_handler);
    signal(SIGALRM,child_handler);
    // Fork off the parent process
    pid = fork();
    if (pid < 0) {
        syslog( LOG_ERR, "unable to fork daemon, code=%d (%s)",
                errno, strerror(errno) );
        exit(EXIT_FAILURE);
    }
    // If we got a good PID, then we can exit the parent process.
    if (pid > 0) {

        // Wait for confirmation from the child via SIGTERM or SIGCHLD, or
        //   for two seconds to elapse (SIGALRM).  pause() should not return.
        alarm(2);
        pause();

        exit(EXIT_FAILURE);
    }
    // At this point we are executing as the child process
    parent = getppid();

    // Cancel certain signals
    signal(SIGCHLD,SIG_DFL); // A child process dies
    signal(SIGTSTP,SIG_IGN); // Various TTY signals
    signal(SIGTTOU,SIG_IGN);
    signal(SIGTTIN,SIG_IGN);
    signal(SIGHUP, SIG_IGN); // Ignore hangup signal
    signal(SIGTERM,SIG_DFL); // Die on SIGTERM

    // Change the file mode mask
    umask(0);
    // Create a new SID for the child process
    sid = setsid();
    if (sid < 0) {
        syslog( LOG_ERR, "unable to create a new session, code %d (%s)",
                errno, strerror(errno) );
        exit(EXIT_FAILURE);
    }
    // Change the current working directory.  This prevents the current
    //   directory from being locked; hence not being able to remove it.
    if ((chdir("/")) < 0) {
        syslog( LOG_ERR, "unable to change directory to %s, code %d (%s)",
                "/", errno, strerror(errno) );
        exit(EXIT_FAILURE);
    }
  
    // Tell the parent process that we are A-okay
    kill( parent, SIGUSR1 );
}


int main(int argc, char* argv[]) {
         int i=0;
        // Initialize the logging interface
        openlog( DAEMON_NAME, LOG_PID, LOG_LOCAL5 );
        syslog( LOG_INFO, "starting" );

        // process command line arguments
        char *WATCH_PATH;
        if (argv[1] != NULL)
        {
            WATCH_PATH = argv[1];
        }
        else
        {
            WATCH_PATH = "/mnt/";
        }
        
        // open outfile
        oFile = fopen("/home/gigaroc/gnotify/events.log", "w+");
        if (oFile == NULL)
        {
            printf("error\n");
            return -1;
        }

        // Daemonize
        daemonize( "/var/lock/subsys/" DAEMON_NAME );
        // Main program

        fflush( oFile );
        //Set events we are watching
        int eventnum = IN_MODIFY | IN_MOVED_FROM | IN_MOVED_TO | IN_CREATE | IN_DELETE;
        // initialize and watch the entire directory tree from the current working
        // directory downwards for all events
        if ( !inotifytools_initialize()
            || !inotifytools_watch_recursively( WATCH_PATH, eventnum ) ) {
                fprintf(stderr, "%s\n", strerror( inotifytools_error() ) );
                return -1;
        }
        //set time format to 24 hour time, HH:MM:SS
        inotifytools_set_printf_timefmt( "%T" );
        //Output all events as "<timestamp> <path> <events>"
        struct inotify_event * event = inotifytools_next_event( -1 );
        while ( event ) {
            //Gets time from the time.h and cuts it up for output later
                char* gTime="";
                char gDay[3]="";
                char gMonth[4]="";
                char gYear[5]="";
                char gTime1[26];
                time_t timer;
                timer=time(NULL);
                gTime = asctime(localtime(&timer));
                strcpy(gTime1,gTime);
                gMonth[0] = gTime1[4];
                gMonth[1] = gTime1[5];
                gMonth[2] = gTime1[6];
                gDay[0] = gTime1[8];
                gDay[1] = gTime1[9];
                gYear[0] = gTime1[20];
                gYear[1] = gTime1[21];
                gYear[2] = gTime1[22];
                gYear[3] = gTime1[23];

                //output handled in two steps
                fprintf(oFile,"%s %s %s ",gDay,gMonth,gYear);
                inotifytools_fprintf(oFile,event, "%T %w%f %e\n" );
                event = inotifytools_next_event( -1 );
                //because the file is always running we need to update the log file at all times
                fflush( oFile );
                i++;
        }
        fclose(oFile);
        syslog( LOG_NOTICE, "terminated" );
        closelog();
        
        return 0;
}


ok, two questions really
1st the big one
i fork the program and term the main program so that the program runs as a daemon
that works
but i'm tired of "ps -e |grep gnot"
then killing the program because there really is no way to terminate as there is no way to input commands
i could really use so help

I know some of the code is ugly, some there are things that are inefficient. but until i can get it to stop, thats moot

I'm running this under linux kernal 2.6.18-4-686 running debain

thanks
GigaRoc

P.S. sorry if it seems like an idiot question

This post has been edited by GigaRoc: 16 Jan, 2008 - 07:29 PM
User is offlineProfile CardPM
+Quote Post

Tom9729
RE: Passing Commands To A Daemonized Program
16 Jan, 2008 - 07:49 PM
Post #2

Debian guru
Group Icon

Joined: 30 Dec, 2007
Posts: 1,463



Thanked: 10 times
Dream Kudos: 325
My Contributions
I've had similar problems before. I've always used "state"-files, but I don't know if that's the best solution.

Could you have the daemon listen on a socket for a "quit" message?

One thing I noticed about your code btw, that shouldn't be causing any problems but is unnecessary is the definitions of "EXIT_SUCCESS" and "EXIT_FAILURE" at the top of your code. Those should already be defined in <stdlib.h>, and anyways you don't use "EXIT_SUCCESS" as the return variable for your main method, so they really just aren't doing anything. smile.gif
User is offlineProfile CardPM
+Quote Post

GigaRoc
RE: Passing Commands To A Daemonized Program
18 Jan, 2008 - 11:12 AM
Post #3

New D.I.C Head
*

Joined: 16 Jan, 2008
Posts: 6

that was supposed to play a bigger role then it did

Also... i don't know how to listen on a socket
do you have a tutorial on how do it?
User is offlineProfile CardPM
+Quote Post

Reply to this topicStart new topic
Time is now: 12/5/08 04:46AM

Live C++ Help!

C++ Tutorials

Reference Sheets

C++ Snippets

DIC Chatroom

Bye Bye Ads

Monthly Drawing

Thumb Drive

Top Contributors

Top 10 Kudos This Month