#include #include #include #include #include "netconf.h" #include "daemoni.h" #include #include "netconf.m" #include #include "internal.h" static NETCONF_HELP_FILE helpf ("scope"); static DAEMON_INTERNAL *first = NULL; static char loaded = 0; /* Read a configuration file about command and path named (conf.daemons) */ static int daemon_readcf() { int nbdae = -1; char basepath[PATH_MAX]; snprintf (basepath,sizeof(basepath)-1,"%s/%s",USR_LIB_LINUXCONF,linuxconf_getdistdir()); SSTRINGS tb; int nb = dir_getlist (basepath,".daemons",tb); for (int i=0; iget()); FILE *fin = fopen (filepath,"r"); if (fin != NULL){ if (nbdae == -1) nbdae = 0; char buf[2000]; while (fgets(buf,sizeof(buf)-1,fin)!=NULL){ char nbuf[2000]; str_strip(buf,nbuf); char *pt = str_skip(nbuf); if (*pt != '\0'){ /* #Specification: files / ETC_CONF_DAEMONS / format This file has one line per daemon described. If the first character of the line is a !, it means that netconf won't start/stop this daemon. This character is optionnal. The rest of the line goes like this. (Note that this feature has been pushed in the file /etc/conf.linuxconf. This mean that the conf.daemons files are never written by linuxconf. The feature is kept for compatibility). The first field is the name (not the path) of the daemon. The next field is the full path and the rest of the line is the command line arguments to use to start the daemon. For now, there is no comments, nor continuation line. Empty line are supported. This file is useful to specify path, so it is used to control other commands, not just daemons. */ int managed = 1; if (*pt == '!'){ pt = str_skip(pt+1); managed = 0; } char name[PATH_MAX]; char *ptn = name; while (*pt > ' ') *ptn++ = *pt++; *ptn = '\0'; while (isspace(*pt)) pt++; DAEMON_INTERNAL *dae = daemon_new (managed,name,pt,first); if (dae != NULL && dae->isok()){ first = dae; nbdae++; }else{ delete dae; } } } fclose (fin); } } return nbdae; } /* Register a daemon or command. This is generally used by modules */ EXPORT void daemon_register (DAEMON_INTERNAL *dae, const char *name, const char *buf) { dae->init (1,name,buf,first); first = dae; } /* Register a daemon or command. This is generally used by modules */ void daemon_register (const char *name, const char *buf) { DAEMON_INTERNAL *dae = new DAEMON_INTERNAL; daemon_register (dae,name,buf); } static const char DAEMONS[] = "daemons"; static const char NOTMANAGED[] = "notmanaged"; static const char CMDSPEC[] = "cmdspec"; /* Read information about daemons and commands. */ static int daemon_read() { /* #Specification: conf.daemons / override The content of /usr/lib/linuxconf/conf.daemons can be overriden by the administrator. The override values (path and argument) are stored in /etc/conf.linuxconf. */ loaded = 1; int nbdae = daemon_readcf (); { SSTRINGS lst; linuxconf_getall (DAEMONS,NOTMANAGED,lst,0); int nb = lst.getnb(); for (int i=0; iget(); DAEMON_INTERNAL *next = first; while (next != NULL){ if (strcmp(pt,next->getname())==0){ next->set_managed(0); break; } next = next->getnext(); } } } { SSTRINGS lst; linuxconf_getall (DAEMONS,CMDSPEC,lst,0); int nb = lst.getnb(); for (int i=0; iget(),sizeof(name)); pt = str_copyword (path,pt,sizeof(path)); pt = str_skip(pt); DAEMON_INTERNAL *next = first; while (next != NULL){ if (strcmp(name,next->getname())==0){ if (strcmp(path,next->getpath())!=0 || strcmp(pt,next->getargs())!=0){ next->set_override (1); next->setspec (path,pt); } break; } next = next->getnext(); } } } return nbdae; } static void daemon_write() { linuxconf_removeall (DAEMONS,NOTMANAGED); linuxconf_removeall (DAEMONS,CMDSPEC); DAEMON_INTERNAL *next = first; while (next != NULL){ if (!next->is_managed()){ linuxconf_add (DAEMONS,NOTMANAGED,next->getname()); } if (next->is_overriden()){ char spec[3*PATH_MAX]; snprintf (spec,sizeof(spec)-1,"%s %s %s",next->getname(),next->getpath() ,next->getargs()); linuxconf_add (DAEMONS,CMDSPEC,spec); } next = next->getnext(); } linuxconf_save(); } /* Check if a process is running at least once Return -1 or the start time of this process. */ EXPORT DAEMON_INTERNAL *daemon_find (const char *name) { if (!loaded) daemon_read (); DAEMON_INTERNAL *ret = first; while (ret != NULL){ if (strcmp(name,ret->getname())==0){ break; }else{ ret = ret->getnext(); } } if (ret == NULL){ if (strcmp(name,"remadmin")==0){ // We always need this, because it controls the user // interface, even if the resource files are missing daemon_register ("remadmin","/bin/remadmin"); ret = first; }else{ xconf_error ( MSG_U(E_MISSINFO ,"Missing information about daemon or utility %s\n" "in configuration file %s\n") ,name,USR_LIB_CONF_DAEMONS); } } return ret; } /* Locate the path of a command. Return NULL if not found or not allowed (managed) to be used */ const char *daemon_findpath(const char *command) { const char *ret = NULL; DAEMON_INTERNAL *dae = daemon_find (command); if (dae != NULL && dae->is_managed() && dae->checkpath()!=-1){ ret = dae->getpath(); } return ret; } static int daemon_cmp(const void *pt1, const void *pt2) { DAEMON_INTERNAL *p1 = *(DAEMON_INTERNAL**)pt1; DAEMON_INTERNAL *p2 = *(DAEMON_INTERNAL**)pt2; return strcmp(p1->getname(),p2->getname()); } /* Edit the path and arguments of a daemon or command */ PUBLIC int DAEMON_INTERNAL::edit () { int ret = -1; DIALOG dia; SSTRING epath(cmd.path); SSTRING eargs(cmd.args); dia.newf_chk (MSG_U(F_MANAGED,"Managed"),managed ,MSG_U(I_MANAGED,"Linuxconf may operate it")); dia.newf_str (MSG_U(F_DAEPATH,"path of the command"),epath); dia.newf_str (MSG_U(F_DAEARGS,"arguments"),eargs); if (dia.edit (MSG_U(T_DAECONFIG,"Daemons and command config") ,MSG_U(I_DAECONFIG,"You are allowed to changed the way\n" "a daemon or command is invoked.") ,helpf)==MENU_ACCEPT){ if (epath.cmp(cmd.path)!=0 || eargs.cmp(cmd.args)!=0){ setspec (epath.get(),eargs.get()); set_override(1); } ret = 0; } return ret; } /* Let the user select which daemon or command netconf may operate */ void daemon_config() { if (!loaded) daemon_read(); int nof = 0; DIALOG_RECORDS dia; // How many items int nb = 0; { DAEMON_INTERNAL *next = first; while (next != NULL){ if (next->isok()) nb++; next = next->getnext(); } } DAEMON_INTERNAL *tb[nb]; { DAEMON_INTERNAL *next = first; int no = 0; while (next != NULL){ if (next->isok()) tb[no++] = next; next = next->getnext(); } qsort (tb,nb,sizeof(DAEMON*),daemon_cmp); } dia.newf_head ("",MSG_U(H_DAEMONS,"Name\tPath\tMod.")); while (1){ for (int i=0; igetpath() ,dae->is_overriden() || !dae->is_managed() ? "*" : ""); dia.set_menuitem (i,dae->getname(),buf); } dia.remove_last (nb+1); MENU_STATUS code = dia.editmenu ( MSG_U(T_SCOPE,"Commands and daemons") ,MSG_U(I_SCOPE,"This dialog let you configure the different commands\n" "and daemons linuxconf is using.\n" "If you deselect one command, then you must\n" "manage this yourself. This facility\n" "is provided to help integrate linuxconf into\n" "a custom Linux installation.\n" "*** Unless you know what you are doing ***\n" "*** fiddling here is not recommended ***\n") ,helpf ,nof,0); if (code == MENU_QUIT || code == MENU_ESCAPE){ break; }else{ DAEMON_INTERNAL *d = tb[nof]; if (d->edit() != -1){ daemon_write(); } } } } /* Let the user configure one daemon/command. Return 0 if the user did changed something. */ int daemon_configone(const char *name) { int ret = -1; DAEMON_INTERNAL *dae = daemon_find (name); if (dae == NULL){ xconf_error (MSG_U(E_DAEUNKNOWN,"Unknown command or daemon %s"),name); }else{ ret = dae->edit(); if (ret != -1) daemon_write(); } return ret; }