diff options
Diffstat (limited to 'src/daemon/daemon.c')
-rw-r--r-- | src/daemon/daemon.c | 129 |
1 files changed, 68 insertions, 61 deletions
diff --git a/src/daemon/daemon.c b/src/daemon/daemon.c index c79d43a..ad35298 100644 --- a/src/daemon/daemon.c +++ b/src/daemon/daemon.c @@ -23,32 +23,38 @@ static int exit_code_pipe[2] = { -1, -1 }; int daemon_parent_pipe[2] = { -1, -1 }; -#define TERMINATE_EXIT_CODE 99 -#define TERMINATE_PARENT 98 +typedef enum { + TERMINATE_OK, + TERMINATE_ERROR, + TERMINATE_EXIT_CODE, + TERMINATE_PARENT +} daemon_state_t; struct daemon_t { daemon_params_t params; /**< the parameters for creation */ - error_t error; /**< error of last start */ + daemon_state_t state; /**< last status of the daemon */ + wolf_error_t error; /**< error of last start */ struct pidfile_t pidfile; /**< pid/lock file of the daemon */ struct group *groupent; /**< group entry */ struct passwd *userent; /**< password entry */ }; daemon_p daemon_new( daemon_params_t params, - error_t *error ) { + wolf_error_t *error ) { daemon_p d; d = (struct daemon_t *)malloc( sizeof ( struct daemon_t ) ); if( d == NULL ) { - *error = ERR_OUT_OF_MEMORY; + *error = WOLF_ERR_OUT_OF_MEMORY; return NULL; } - d->error = -1; + d->state = TERMINATE_ERROR; + d->error = WOLF_ERR_INTERNAL; d->params = params; if( params.daemon_name == NULL ) { - *error = ERR_INVALID_VALUE; + *error = WOLF_ERR_INVALID_VALUE; return NULL; } @@ -58,7 +64,7 @@ daemon_p daemon_new( daemon_params_t params, pidfile_set_from_filename( &d->pidfile, params.pid_filename ); } - *error = OK; + *error = WOLF_OK; return d; } @@ -67,7 +73,7 @@ void daemon_free( daemon_p d ) { d = NULL; } -static error_t close_fd( int fd ) { +static wolf_error_t close_fd( int fd ) { if( close( fd ) < 0 ) { switch( errno ) { case EBADF: @@ -77,34 +83,34 @@ static error_t close_fd( int fd ) { default: LOG( log_EMERG, "Error while closing file descriptor %d: %s (%d)", fd, strerror( errno ), errno ); - return ERR_INTERNAL; + return WOLF_ERR_INTERNAL; } } - return OK; + return WOLF_OK; } -static error_t daemon_close_standard_fds( void ) { - error_t error; +static wolf_error_t daemon_close_standard_fds( void ) { + wolf_error_t error; - if( ( error = close_fd( STDIN_FILENO ) ) != OK ) return error; - if( ( error = close_fd( STDOUT_FILENO ) ) != OK ) return error; - if( ( error = close_fd( STDERR_FILENO ) ) != OK ) return error; + if( ( error = close_fd( STDIN_FILENO ) ) != WOLF_OK ) return error; + if( ( error = close_fd( STDOUT_FILENO ) ) != WOLF_OK ) return error; + if( ( error = close_fd( STDERR_FILENO ) ) != WOLF_OK ) return error; - return OK; + return WOLF_OK; } -static error_t daemon_close_all_fds( void ) { +static wolf_error_t daemon_close_all_fds( void ) { long nof_files; int i; - error_t error; + wolf_error_t error; nof_files = sysconf( _SC_OPEN_MAX ); if( nof_files < 0 ) { LOG( log_EMERG, "Unable to retrieve maximal number of files: %s (%d)", strerror( errno ), errno ); - return ERR_INTERNAL; + return WOLF_ERR_INTERNAL; } LOG( log_DEBUG, "Closing all filedescriptors up to %ld", nof_files ); @@ -120,28 +126,28 @@ static error_t daemon_close_all_fds( void ) { ( i == exit_code_pipe[1] ) ) { continue; } - if( ( error = close_fd( i ) ) != OK ) return error; + if( ( error = close_fd( i ) ) != WOLF_OK ) return error; } - return OK; + return WOLF_OK; } -static error_t open_null_fd( int must_fd, int flags ) { +static wolf_error_t open_null_fd( int must_fd, int flags ) { int fd; fd = open( "/dev/null", flags ); if( fd < 0 ) { LOG( log_EMERG, "Unable to open fd %d as /dev/null: %s (%d)", must_fd, strerror( errno ), errno ); - return ERR_INTERNAL; + return WOLF_ERR_INTERNAL; } if( fd != must_fd ) { LOG( log_EMERG, "Something is wrong with the file descriptors (expecting %d,got %d)!", must_fd, fd ); - return ERR_PROGRAMMING; + return WOLF_ERR_PROGRAMMING; } - return OK; + return WOLF_OK; } static void atomar_write( int fd, void *data, size_t data_len ) { @@ -174,10 +180,10 @@ atomar_read_again: } } -error_t daemon_start( daemon_p d ) { +wolf_error_t daemon_start( daemon_p d ) { pid_t pid; mode_t mode; - error_t error; + wolf_error_t error; int exit_code; /* Our parent is already the init process (which has pid 1 by @@ -186,7 +192,7 @@ error_t daemon_start( daemon_p d ) { */ if( getppid( ) == 1 ) { LOG( log_EMERG, "Already running as daemon!" ); - return( d->error = ERR_PROGRAMMING ); + return( d->error = WOLF_ERR_PROGRAMMING ); } /* Are we starting as root? If not, bail out, we need root @@ -197,7 +203,7 @@ error_t daemon_start( daemon_p d ) { */ if( geteuid( ) != 0 ) { LOG( log_EMERG, "Unable to start daemon as not root user!" ); - return( d->error = ERR_INVALID_STATE ); + return( d->error = WOLF_ERR_INVALID_STATE ); } /* We fork so SIGCHLD signals get to the parent and grandfather. @@ -223,7 +229,7 @@ error_t daemon_start( daemon_p d ) { if( pipe( exit_code_pipe ) < 0 ) { LOG( log_EMERG, "Unable to create exit code pipe: %s (%d)", strerror( errno ), errno ); - return ( d->error = ERR_INTERNAL ); + return ( d->error = WOLF_ERR_INTERNAL ); } LOG( log_DEBUG, "Created exit code pipe (%d,%d)", exit_code_pipe[0], exit_code_pipe[1] ); @@ -234,7 +240,7 @@ error_t daemon_start( daemon_p d ) { case -1: /* error */ LOG( log_EMERG, "Unable to fork the first time: %s", strerror( errno ) ); - return ( d->error = ERR_INTERNAL ); + return ( d->error = WOLF_ERR_INTERNAL ); case 0: /* the child becomes the daemon */ @@ -249,7 +255,7 @@ error_t daemon_start( daemon_p d ) { * code from the error pipe */ LOG( log_DEBUG, "Parent after first fork: child is %d", pid ); - return ( d->error = TERMINATE_EXIT_CODE ); + return ( d->state = TERMINATE_EXIT_CODE ); } /* second pipe communicates from the daemon back to its parent @@ -258,7 +264,7 @@ error_t daemon_start( daemon_p d ) { if( pipe( daemon_parent_pipe ) < 0 ) { LOG( log_EMERG, "Unable to create parent pipe: %s (%d)", strerror( errno ), errno ); - return ( d->error = ERR_INTERNAL ); + return ( d->error = WOLF_ERR_INTERNAL ); } LOG( log_DEBUG, "Created parent pipe (%d,%d)", daemon_parent_pipe[0], daemon_parent_pipe[1] ); @@ -269,7 +275,7 @@ error_t daemon_start( daemon_p d ) { if( setsid( ) < 0 ) { /* should actually never fail */ LOG( log_EMERG, "Starting new process group session for the parent of the daemon failed: %s", strerror( errno ) ); - return ERR_INTERNAL; + return WOLF_ERR_INTERNAL; } /* We fork so SIGCHLD signals get to the parent and grandfather. @@ -296,7 +302,7 @@ error_t daemon_start( daemon_p d ) { case -1: /* error */ LOG( log_EMERG, "Unable to fork the second time: %s", strerror( errno ) ); - return ( d->error = ERR_INTERNAL ); + return ( d->error = WOLF_ERR_INTERNAL ); case 0: /* the child becomes the daemon */ @@ -306,13 +312,13 @@ error_t daemon_start( daemon_p d ) { default: (void)signal_install_handlers_parent( ); LOG( log_DEBUG, "Parent after second fork: child (and daemon) is %d", pid ); - return ( d->error = TERMINATE_PARENT ); + return ( d->state = TERMINATE_PARENT ); } /* Now install signal handlers */ - if( ( error = signal_initialize( ) ) != OK ) + if( ( error = signal_initialize( ) ) != WOLF_OK ) return ( d->error = error ); - if( ( error = signal_install_handlers_daemon( ) ) != OK ) + if( ( error = signal_install_handlers_daemon( ) ) != WOLF_OK ) return ( d->error = error ); /* Put the daemon in it's own process group and finally detach it @@ -322,7 +328,7 @@ error_t daemon_start( daemon_p d ) { if( setsid( ) < 0 ) { /* should actually never fail */ LOG( log_EMERG, "Starting new process group for daemon session failed: %s", strerror( errno ) ); - return ERR_INTERNAL; + return WOLF_ERR_INTERNAL; } /* Change to the root directory for several reasons: @@ -335,7 +341,7 @@ error_t daemon_start( daemon_p d ) { */ if( chdir( "/" ) < 0 ) { LOG( log_EMERG, "Changing to root diretory failed: %s", strerror( errno ) ); - return ERR_INTERNAL; + return WOLF_ERR_INTERNAL; } LOG( log_DEBUG, "Changed to root directory /" ); @@ -348,11 +354,11 @@ error_t daemon_start( daemon_p d ) { LOG( log_DEBUG, "Switched umask from %04o to %04o", mode, 0133 ); /* check if another daemon is already running, if yes, bail out */ - if( is_daemon_running( &d->pidfile, &pid, &error ) || ( error != OK ) ) { - if( error == OK ) { + if( is_daemon_running( &d->pidfile, &pid, &error ) || ( error != WOLF_OK ) ) { + if( error == WOLF_OK ) { LOG( log_EMERG, "Another daemon is already running with pid '%d', can't start!", pid ); } - return ERR_INTERNAL; + return WOLF_ERR_INTERNAL; } /* we loose logfile and syslog file descriptors anyway, so close @@ -362,16 +368,16 @@ error_t daemon_start( daemon_p d ) { closelogtostderr( ); /* close all filedescriptors */ - if( daemon_close_all_fds( ) != OK ) - return ERR_INTERNAL; + if( daemon_close_all_fds( ) != WOLF_OK ) + return WOLF_ERR_INTERNAL; /* reopen the logs to the logfile and syslog (not stderr) */ reopenlogtosyslog( ); reopenlogtofile( ); /* create and lock the pidfile now, write pid of daemon into it */ - if( pidfile_create( &d->pidfile ) != OK ) { - return ERR_INTERNAL; + if( pidfile_create( &d->pidfile ) != WOLF_OK ) { + return WOLF_ERR_INTERNAL; } /* Install the final permissions for new files. The reason is @@ -399,7 +405,7 @@ error_t daemon_start( daemon_p d ) { LOG( log_EMERG, "Unable to retrieve group information for group '%s': %s (%d)", d->params.group_name, strerror( errno ), errno ); } - return ERR_INTERNAL; + return WOLF_ERR_INTERNAL; } errno = 0; @@ -411,19 +417,19 @@ error_t daemon_start( daemon_p d ) { LOG( log_EMERG, "Unable to retrieve user information for user '%s': %s (%d)", d->params.user_name, strerror( errno ), errno ); } - return ERR_INTERNAL; + return WOLF_ERR_INTERNAL; } if( setgid( d->userent->pw_gid ) < 0 ) { LOG( log_EMERG, "Setting unprivileged group failed: %s (%d)", strerror( errno ), errno ); - return ERR_INTERNAL; + return WOLF_ERR_INTERNAL; } if( setuid( d->userent->pw_uid ) < 0 ) { LOG( log_EMERG, "Setting unprivileged user failed: %s (%d)", strerror( errno ), errno ); - return ERR_INTERNAL; + return WOLF_ERR_INTERNAL; } /* TODO: setsid and setting all groups of the user */ @@ -440,10 +446,10 @@ error_t daemon_start( daemon_p d ) { * starting the daemon by hand still gets error messages * on stderr. */ - if( ( error = daemon_close_standard_fds( ) ) != OK ) return error; - if( ( error = open_null_fd( STDIN_FILENO, O_RDONLY ) ) != OK ) return error; - if( ( error = open_null_fd( STDOUT_FILENO, O_WRONLY ) ) != OK ) return error; - if( ( error = open_null_fd( STDERR_FILENO, O_WRONLY ) ) != OK ) return error; + if( ( error = daemon_close_standard_fds( ) ) != WOLF_OK ) return error; + if( ( error = open_null_fd( STDIN_FILENO, O_RDONLY ) ) != WOLF_OK ) return error; + if( ( error = open_null_fd( STDOUT_FILENO, O_WRONLY ) ) != WOLF_OK ) return error; + if( ( error = open_null_fd( STDERR_FILENO, O_WRONLY ) ) != WOLF_OK ) return error; /* signal the grand-parent process, that he can return 0 to * the calling shell/script @@ -451,7 +457,8 @@ error_t daemon_start( daemon_p d ) { exit_code = EXIT_SUCCESS; atomar_write( exit_code_pipe[1], &exit_code, sizeof( int ) ); - return ( d->error = OK ); + d->state = TERMINATE_OK; + return ( d->error = WOLF_OK ); } NORETURN void daemon_exit( daemon_p d ) { @@ -460,7 +467,7 @@ NORETURN void daemon_exit( daemon_p d ) { LOG( log_DEBUG, "daemon_exit called with error %d", d->error ); - switch( d->error ) { + switch( d->state ) { case TERMINATE_EXIT_CODE: /* wait here for exit code in exit_code_pipe * so we can return the correct exit code to @@ -504,7 +511,7 @@ NORETURN void daemon_exit( daemon_p d ) { /* exit code is irrelevant here.. */ exit( EXIT_SUCCESS ); - case OK: + case TERMINATE_OK: /* close and unlock the pidfile here */ (void)pidfile_release( &d->pidfile ); @@ -519,8 +526,8 @@ NORETURN void daemon_exit( daemon_p d ) { /* exit code is irrelevant here */ _exit( EXIT_SUCCESS ); - - default: + + case TERMINATE_ERROR: /* no exit_code_pipe exists yet, we are before the * first fork, so terminate with proper exit code */ |