#include #include #include #include #include #include "netconf.h" #include "daemoni.h" #include "internal.h" #include "../paths.h" #include "netconf.m" #include #include static NETCONF_HELP_FILE help_inetd("inetd"); static CONFIG_FILE f_inetd (ETC_INETD_CONF,help_inetd,CONFIGF_PROBED ,subsys_netaccess); static CONFIG_FILE f_services (ETC_SERVICES,help_inetd,CONFIGF_PROBED ,subsys_netaccess); static NETCONF_HELP_FILE help_amd("amd"); static CONFIG_FILE f_conf_amd (ETC_CONF_AMD_MAP,help_amd,CONFIGF_PROBED ,subsys_netclient); static NETCONF_HELP_FILE help_gated("gated"); static CONFIG_FILE f_gated (ETC_GATED_CONF,help_gated,CONFIGF_PROBED); static NETCONF_HELP_FILE help_syslog ("syslog"); static CONFIG_FILE f_syslog (ETC_SYSLOG_CONF,help_syslog ,CONFIGF_PROBED|CONFIGF_OPTIONAL); /* #Specification: daemon / classes The class DAEMON is the base class. Each daemon (portmap, inetd, ...) may have its own class where it generally overide the method startif and stop. */ # class DAEMON_INETD: public DAEMON_INTERNAL{ /*~PROTOBEG~ DAEMON_INETD */ public: int restart (void); int startif (void); /*~PROTOEND~ DAEMON_INETD */ }; /* Tell inetd to reread its configuration file */ PUBLIC int DAEMON_INETD::restart() { int ret = -1; bool problem; PROC *prc = findprocess(problem); if (prc != NULL){ #if 0 long last_sigdate = file_date (VAR_RUN_INETD_SIGHUP); if (last_sigdate < f_inetd.getdate() || last_sigdate < f_services.getdate()){ ret = signal (SIGHUP,"Signaling",VAR_RUN_INETD_SIGHUP); } #else ret = signal (SIGHUP,"Signaling",VAR_RUN_INETD_SIGHUP); #endif } return ret; } PUBLIC int DAEMON_INETD::startif() { /* #Specification: inetd / strategy inetd depend on /etc/inetd.conf. If the file is empty or do not exist, then inetd is not need. It will be killed, or not started. If inetd.conf is not empty, it will be started. If it is already running and exports is younger than the process, the signal SIGHUP is sent so inetd will reread inetd.conf. */ SSTRINGS tb; tb.add (new SSTRING(f_inetd.getpath())); tb.add (new SSTRING(f_services.getpath())); return startif_file(tb); } class DAEMON_PORTMAP: public DAEMON_INTERNAL{ /*~PROTOBEG~ DAEMON_PORTMAP */ /*~PROTOEND~ DAEMON_PORTMAP */ }; class DAEMON_AMD: public DAEMON_INTERNAL{ /*~PROTOBEG~ DAEMON_AMD */ public: int restart (void); int startif (void); int stop (void); /*~PROTOEND~ DAEMON_AMD */ }; /* Stop the automounter */ PUBLIC int DAEMON_AMD::stop () { return cmd.kill(SIGINT); } /* Tell the automounter to reread its configuration file. */ PUBLIC int DAEMON_AMD::restart () { /* #Specification: amd / restarting When the map (/etc/conf.amd.map) is changed, amd is simply restarted. It is killed with SIGINT and restarted. This is weak as it is unmounting everything. On the other hand I suspect that amd will be managed only in single user mode so it does not matter. Some amd guru want to comment. */ int ret = stop(); if (ret != -1) ret = start(); return ret; } /* Restart amd if ETC_CONF_AMD_MAP is newer than the process */ PUBLIC int DAEMON_AMD::startif () { /* #Specification: amd automounter / strategy amd depends on /etc/conf.amd.map. If the file is empty or do not exist, then amd is not need. It will be killed, or not started. If /etc/conf.amd.map is not empty, it will be started. If it is already running and exports is younger than the process, it will be kill and restart */ return startif_file (f_conf_amd); } class DAEMON_LPD: public DAEMON_INTERNAL{ /*~PROTOBEG~ DAEMON_LPD */ /*~PROTOEND~ DAEMON_LPD */ }; class DAEMON_GATED: public DAEMON_INTERNAL{ /*~PROTOBEG~ DAEMON_GATED */ public: PROC *findprocess (bool&problem); int restart (void); int start (void); int startif (void); int stop (void); /*~PROTOEND~ DAEMON_GATED */ }; PUBLIC PROC *DAEMON_GATED::findprocess(bool &problem) { problem = false; return process_find ("gated",NULL); } /* Restart gated if ETC_GATED_CONF is newer than the process */ PUBLIC int DAEMON_GATED::startif () { /* #Specification: gated / strategy gated depends on /etc/gated.conf. If the file is empty or do not exist, then gated is not need. It will be killed, or not started. If gated.conf is not empty, it will be started. If it is already running and gated.conf is younger than the process, it will be kill and restart. */ return startif_file(f_gated); } /* Tell gated to reread its configuration file */ PUBLIC int DAEMON_GATED::restart() { char buf[2000]; snprintf (buf,sizeof(buf)-1,"%s restart",cmd.path.get()); return cmd.system (buf); } /* Tell gated to stop */ PUBLIC int DAEMON_GATED::stop() { int ret = 0; bool problem; if (findprocess(problem)!=NULL){ char buf[2000]; snprintf (buf,sizeof(buf)-1,"%s stop",cmd.path.get()); ret = cmd.system (buf); } return ret; } /* Tell gated to start */ PUBLIC int DAEMON_GATED::start() { char buf[2000]; snprintf (buf,sizeof(buf)-1,"%s start",cmd.path.get()); return cmd.system (buf); } class DAEMON_ROUTED: public DAEMON_INTERNAL{ /*~PROTOBEG~ DAEMON_ROUTED */ private: void setcmdline (ROUTED&rt, char cmdline[PATH_MAX]); public: int start (void); int startif (void); /*~PROTOEND~ DAEMON_ROUTED */ }; PRIVATE void DAEMON_ROUTED::setcmdline(ROUTED &rt, char cmdline[PATH_MAX]) { char buf[20]; rt.setoptions (buf); snprintf (cmdline,PATH_MAX-1,"%s %s %s",cmd.path.get(),cmd.args.get(),buf); strip_end (cmdline); } PUBLIC int DAEMON_ROUTED::start() { ROUTED rt; char cmdline[PATH_MAX]; setcmdline (rt,cmdline); recordargs (cmdline); return cmd.system (cmdline); } PUBLIC int DAEMON_ROUTED::startif() { int ret = 0; ROUTED rt; if (!rt.is_required()){ ret = stop(); recordargs (NULL); }else{ bool problem; PROC *prc = findprocess(problem); if (problem){ ret = restart(); }else if (prc == NULL){ ret = start(); }else{ /* #Specification: netconf / routed / /var/run/routed.options netconf save the command line option of routed in the file /var/run/routed.options each time it is started. When checking the configuration, netconf read back the command line and compare with the configured one. If there is any difference, routed will be restarted. I am not sure how appropriate it is to restarted. Maybe there is a clean way to kill routed so it will remove all routes and put it back when restart. Not sure here... */ const char *old_cmdline = getlastargs(); char cmdline[PATH_MAX]; setcmdline (rt,cmdline); if (strcmp(cmdline,old_cmdline)!=0) ret = restart(); } } return ret; } class DAEMON_KLOGD: public DAEMON_INTERNAL{ /*~PROTOBEG~ DAEMON_KLOGD */ /*~PROTOEND~ DAEMON_KLOGD */ }; class DAEMON_SYSLOGD: public DAEMON_INTERNAL{ /*~PROTOBEG~ DAEMON_SYSLOGD */ public: int startif (void); /*~PROTOEND~ DAEMON_SYSLOGD */ }; /* Restart syslogd is ETC_SYSLOG_CONF is newer than the process */ PUBLIC int DAEMON_SYSLOGD::startif () { /* #Specification: syslogd / strategy syslogd depends on /etc/syslog.conf. If the file is empty or do not exist, then syslogd is not need. It will be killed, or not started. If syslog.conf is not empty, it will be started. If it is already running and the file is younger than the process, it will be kill and restart. */ return startif_file(f_syslog); } // Not really a daemon, but a system command class DAEMON_COMMAND: public DAEMON_INTERNAL{ /*~PROTOBEG~ DAEMON_COMMAND */ /*~PROTOEND~ DAEMON_COMMAND */ }; class DAEMON_CROND: public DAEMON_INTERNAL{ /*~PROTOBEG~ DAEMON_CROND */ /*~PROTOEND~ DAEMON_CROND */ }; class DAEMON_KERNELD: public DAEMON_INTERNAL{ /*~PROTOBEG~ DAEMON_KERNELD */ /*~PROTOEND~ DAEMON_KERNELD */ }; #if 0 class DAEMON_SSHD: public DAEMON_INTERNAL{ /*~PROTOBEG~ DAEMON_SSHD */ /*~PROTOEND~ DAEMON_SSHD */ }; /* Restart sshd if ETC_SSH_HOST_KEY is newer than the process */ PUBLIC int DAEMON_SSHD::startif () { /* #Specification: sshd / strategy sshd depends on /etc/ssh_host_key at least. If the file is empty or do not exist, then sshd is not need. It will be killed, or not started. If ssh_host_key is not empty, it will be started. If it is already running and the file is younger than the process, it will be kill and restart. */ return startif_file(f_ssh_host_key); } #endif /* Create an instance of a sub-class of DAEMON based on its name. */ DAEMON_INTERNAL *daemon_new ( int managed, const char *name, const char *buf, DAEMON_INTERNAL *next) { DAEMON_INTERNAL *ret = NULL; #define NEWD(n,c) if(strcmp(name,n)==0){ \ ret = new DAEMON_##c; \ } NEWD("inetd",INETD) else NEWD ("crond",CROND) else NEWD ("rpc.portmap",PORTMAP) else NEWD ("routed",ROUTED) else NEWD ("amd",AMD) else NEWD ("klogd",KLOGD) else NEWD ("syslogd",SYSLOGD) else NEWD ("lpd",LPD) else NEWD ("kerneld",KERNELD) else NEWD ("gated",GATED) // else NEWD ("sshd",SSHD) else{ ret = new DAEMON_COMMAND; #if 0 xconf_error (MSG_U(E_UNKNOWNDAEMON ,"Unknown daemon :%s:....\ndon't know how to support it\n") ,name); #endif } if (ret != NULL){ ret->init(managed,name,buf,next); if(strcmp(name,"ifconfig")==0) ret->settimeout (30); //if(strcmp(name,"lilo")==0) ret->settimeout (15); if(strcmp(name,"quotacheck")==0) ret->settimeout (10000); } return ret; }