• Main Page
  • Data Structures
  • Files
  • File List
  • Globals

/srv/bpo/opendnssec/opendnssec-1.3.2/enforcer/common/daemon.c

Go to the documentation of this file.
00001 /*
00002  * $Id: daemon.c 4269 2010-12-15 10:59:36Z sion $
00003  *
00004  * Copyright (c) 2008-2009 Nominet UK. All rights reserved.
00005  *
00006  * Redistribution and use in source and binary forms, with or without
00007  * modification, are permitted provided that the following conditions
00008  * are met:
00009  * 1. Redistributions of source code must retain the above copyright
00010  *    notice, this list of conditions and the following disclaimer.
00011  * 2. Redistributions in binary form must reproduce the above copyright
00012  *    notice, this list of conditions and the following disclaimer in the
00013  *    documentation and/or other materials provided with the distribution.
00014  *
00015  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
00016  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
00017  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
00018  * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
00019  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
00020  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
00021  * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
00022  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
00023  * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
00024  * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
00025  * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00026  *
00027  */
00028 
00029 /* 
00030  * daemon.c code needed to get a daemon up and running
00031  *
00032  * edit the DAEMONCONFIG and cmlParse function
00033  * in daemon_util.[c|h] to add options specific
00034  * to your app
00035  *
00036  * gcc -o daemon daemon_util.c daemon.c
00037  *
00038  * Most of this is based on stuff I have seen in NSD
00039  */
00040 
00041 #include "config.h"
00042 
00043 #include <sys/types.h>
00044 #include <sys/param.h>
00045 #include <syslog.h>
00046 #include <stdarg.h>
00047 #include <errno.h>
00048 #include <unistd.h>
00049 #include <fcntl.h>
00050 #include <stdlib.h>
00051 #include <string.h>
00052 #include <signal.h>
00053 
00054 #include "daemon.h"
00055 #include "daemon_util.h"
00056 #include "privdrop.h"
00057 
00058 #include "ksm/ksm.h"
00059 #include "ksm/dbsmsg.h"
00060 #include "ksm/dbsdef.h"
00061 #include "ksm/kmemsg.h"
00062 #include "ksm/kmedef.h"
00063 #include "ksm/message.h"
00064 #include "ksm/string_util.h"
00065 
00066 #ifndef MAXPATHLEN
00067 # define MAXPATHLEN 4096
00068 #endif
00069 
00070 extern int server_init(DAEMONCONFIG *config);
00071 extern void server_main(DAEMONCONFIG *config);
00072 
00073 DAEMONCONFIG config;
00074 
00075 void 
00076 sig_handler (int sig)
00077 {
00078     switch (sig) {
00079         case SIGCHLD:
00080             return;
00081         case SIGHUP:
00082             return;
00083         case SIGALRM:
00084             break;
00085         case SIGILL:
00086             break;
00087         case SIGUSR1:
00088             break;
00089         case SIGINT:
00090             config.term = 2;
00091             break;
00092         case SIGTERM:
00093             config.term = 1;
00094             break;
00095         default:      
00096             break;
00097     }
00098 }
00099 
00100 void
00101 exit_function(void)
00102 {
00103     unlink(config.pidfile);
00104 }
00105 
00106 int
00107 main(int argc, char *argv[]){
00108     int fd;
00109     struct sigaction action;
00110     const char* program;                /* Temporary for program name */
00111    
00112     config.debug = false;
00113     config.once = false;
00114 
00115     config.pidfile = NULL;
00116     config.program = NULL;
00117     config.host = NULL;
00118     config.port = NULL;
00119     config.user = (unsigned char *)calloc(MAX_USER_LENGTH, sizeof(char));
00120     config.password = (unsigned char *)calloc(MAX_PASSWORD_LENGTH, sizeof(char));
00121     config.schema = (unsigned char *)calloc(MAX_SCHEMA_LENGTH, sizeof(char));
00122     config.DSSubmitCmd = (char *)calloc(MAXPATHLEN + 1024, sizeof(char));
00123 
00124     if (config.user == NULL || config.password == NULL || config.schema == NULL) {
00125         log_msg(&config, LOG_ERR, "Malloc for config struct failed");
00126         exit(1);
00127     }
00128     config.term = 0;
00129 
00130     /* Lets set up the logging first */
00131     /* The program name is the last component of the program file name */
00132     if ((program = strrchr(argv[0], '/'))) {    /* EQUALS */
00133         ++program;                      /* Point to character after last "/" */
00134         }
00135         else {
00136                 program = argv[0];      /* No slash, so use string given */
00137         }
00138     config.program = program;
00139     config.log_user = DEFAULT_LOG_FACILITY;
00140 
00141     log_init(config.log_user, config.program);
00142                 
00143     /* useful message */
00144     log_msg(&config, LOG_INFO, "%s starting...", PACKAGE_NAME);
00145 
00146 #ifdef ENFORCER_TIMESHIFT
00147     if (getenv("ENFORCER_TIMESHIFT")) {
00148         log_msg(&config, LOG_INFO, "Timeshift mode detected, running once only!");
00149         fprintf(stderr, "WARNING: Timeshift mode detected, running once only!\n");
00150         config.once = true;
00151         config.debug = true;
00152     }
00153 #endif /* ENFORCER_TIMESHIFT */
00154 
00155     /* Process command line */
00156     cmdlParse(&config, &argc, argv);
00157     if(config.debug) log_msg(&config, LOG_INFO, "%s DEBUG ON.", PACKAGE_NAME);
00158 
00159     /* If we dont debug then fork */
00160     if(!config.debug){
00161         /* Fork */
00162         switch ((config.pid = fork())) {
00163             case 0:
00164                 break;
00165             case -1:
00166                 log_msg(&config, LOG_ERR, "fork failed: %s", strerror(errno));
00167                 unlink(config.pidfile);
00168                 exit(1);
00169             default:
00170                 fprintf(stdout, "OpenDNSSEC ods-enforcerd started (version %s), pid %d\n", PACKAGE_VERSION, (int) config.pid);
00171                 log_msg(&config, LOG_INFO, "%s Parent exiting...", PACKAGE_NAME);
00172                 exit(0);
00173         }
00174 
00175         /* Detach ourselves... */
00176         if (setsid() == -1) {
00177             log_msg(&config, LOG_ERR, "setsid() failed: %s", strerror(errno));
00178             exit(1);
00179         }
00180 
00181         if ((fd = open("/dev/null", O_RDWR, 0)) != -1) {
00182             (void)dup2(fd, STDIN_FILENO);
00183             (void)dup2(fd, STDOUT_FILENO);
00184             (void)dup2(fd, STDERR_FILENO);
00185             if (fd > 2)
00186                 (void)close(fd);
00187         }
00188         log_msg(&config, LOG_INFO, "%s forked OK...", PACKAGE_NAME);
00189     } else {
00190         log_msg(&config, LOG_INFO, "%s in debug mode - not forking...", PACKAGE_NAME);
00191     }
00192 
00193     action.sa_handler = sig_handler;
00194     sigfillset(&action.sa_mask);
00195     action.sa_flags = 0;
00196     sigaction(SIGTERM, &action, NULL);
00197     sigaction(SIGHUP, &action, NULL);
00198     sigaction(SIGINT, &action, NULL);
00199     sigaction(SIGILL, &action, NULL);
00200     sigaction(SIGUSR1, &action, NULL);
00201     sigaction(SIGALRM, &action, NULL);
00202     sigaction(SIGCHLD, &action, NULL);
00203     action.sa_handler = SIG_IGN;
00204     sigaction(SIGPIPE, &action, NULL);
00205 
00206     /* Get perms that we will be dropping to */
00207     if (getPermsForDrop(&config) != 0) {
00208         exit(1);
00209     }
00210     
00211     /* Run the server specific code. You need to provide this function somewhere
00212         this sets our pidfile */
00213     if (server_init(&config) != 0) {
00214         exit(1);
00215     }
00216 
00217     /* make the directory for the pidfile if required; do this before we drop
00218        privs */
00219     if (createPidDir(&config) != 0) {
00220         exit(1);
00221     }
00222 
00223     /* 
00224      * Drop permissions.
00225      * This function exits if something goes wrong
00226      */
00227     privdrop(config.username, config.groupname, NULL);
00228 
00229     config.uid = geteuid();
00230     config.gid = getegid();
00231 
00232     /* write the pidfile */
00233     config.pid = getpid();
00234     if (writepid(&config) == -1) {
00235         log_msg(&config, LOG_ERR, "cannot write the pidfile %s: %s",
00236                 config.pidfile, strerror(errno));
00237                                                         exit(1);
00238     }
00239 
00240     atexit(exit_function);
00241 
00242     log_msg(&config, LOG_NOTICE, "%s started (version %s), pid %d", PACKAGE_NAME, PACKAGE_VERSION, 
00243             (int) config.pid);
00244 
00245     MsgInit();
00246     MsgRegister(KME_MIN_VALUE, KME_MAX_VALUE, m_messages, ksm_log_msg);
00247     MsgRegister(DBS_MIN_VALUE, DBS_MAX_VALUE, d_messages, ksm_log_msg);
00248 
00249     /* Do something. You need to provide this function somewhere */
00250     server_main(&config);
00251 
00252     /* Free stuff here (exit from sigs pass through) */
00253     MsgRundown();
00254     if (config.host) free(config.host);
00255     if (config.port) free(config.port);
00256     free(config.user);
00257     free(config.password);
00258     free(config.schema);
00259     free(config.DSSubmitCmd);
00260 
00261     StrFree(config.username);
00262     StrFree(config.groupname);
00263 #if 0
00264     StrFree(config.chrootdir);
00265 #endif
00266 
00267     exit(0);
00268 
00269 }
00270 

Generated on Mon Oct 31 2011 14:38:30 for OpenDNSSEC-enforcer by  doxygen 1.7.1