/* OSSP rc - Run-Command Processor ** Copyright (c) 2002-2003 Ralf S. Engelschall ** Copyright (c) 2002-2003 Cable & Wireless Deutschland GmbH ** Copyright (c) 2002-2003 The OSSP Project ** ** This file is part of OSSP rc, a portable run-command processor ** which can be found at http://www.ossp.org/pkg/lib/rc/ ** ** Permission to use, copy, modify, and distribute this software for ** any purpose with or without fee is hereby granted, provided that ** the above copyright notice and this permission notice appear in all ** copies. ** ** THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED ** WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF ** MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. ** IN NO EVENT SHALL THE AUTHORS AND COPYRIGHT HOLDERS AND THEIR ** CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF ** USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ** ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, ** OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT ** OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF ** SUCH DAMAGE. ** ** rc_config.c: Run-Command Processor ISO C source file */ #include #include #include /* For opendir(3) */ #include "rc.h" #include "rc_config.h" #include "rc_const.h" /* String constants */ static int m_nLocks = 0; /* Server locks, not thread-safe FIXME */ /*************************************** * configNew(void) * * Construct a configuration * ***************************************/ rc_return_t configNew(void) { ex_t Except; if (m_nLocks == 0) { /* If we don't have one yet */ try { /* then construct a new one */ clioptNew(); /* Member cliopt instance */ } catch(Except) rethrow; } m_nLocks++; /* FIXME not threadsafe */ /* Warn: Experimental design pattern code abstracts operations from config */ /* configVisit(pfnSetdefaults); configVisit(pfnGetoptinfo);*/ return(RC_THROW(RC_OK)); } /* FIXME: Make into configVisit, using callbacks to get and set option info */ /*************************************** * configInfo(void) * * Print the configuration information * ***************************************/ rc_return_t configInfo(void) { ex_t Except; int i = 0; char **pszTemp = NULL; /* For holding the section string vector */ try { fprintf(stderr, "# Run command file: %s\n", configGetrcfile()); pszTemp = (char **)configGetsecs(); fprintf(stderr, "# Sections:"); for (i = 0; pszTemp[i]; i++) fprintf(stderr, " %s", pszTemp[i]); fputc('\n', stderr); /* FIXME Not threadsafe, wrap with crit section */ for (i = 0; i < RC_NUMOPTS; i++) { if (configGetval(i) == NULL); /* NOP */ else if (!(strcmp(configGetval(i), "1"))) fprintf(stderr, "# Option %s is on.\n", configGetname(i)); else fprintf(stderr, "# Option %s is %s.\n", configGetname(i),\ configGetval(i)); } fputc('\n', stderr); } catch(Except) rethrow; return(RC_THROW(RC_OK)); } /*************************************** * configGetXXX(rc_opt_t) * * Configuration accessors * ***************************************/ const char *configGetval(rc_opt_t Optname) { ex_t Except; char *szTemp = NULL; if (m_nLocks) { /* Make sure config exists */ try { if ((szTemp = (char *)clioptGetval(Optname))); /* else if (szTemp = envoptGetval(Optname)); else if (szTemp = cnfoptGetval(Optname));*/ } catch(Except) rethrow; return((const char *)szTemp); } else { RC_THROW(RC_ERR_USE); } return(NULL); /* Not reached */ } const char *configGetname(rc_opt_t Optname) { static char *s_szOptnametab[] = { /* NULL is for alignment */ NULL, RC_USE_NAME, RC_DBG_NAME, RC_VER_NAME, RC_EVL_NAME, RC_HLP_NAME, RC_INF_NAME, RC_LBL_NAME, RC_PRN_NAME, RC_PAR_NAME, RC_SIL_NAME, RC_RAW_NAME, RC_VRB_NAME, RC_EXC_NAME, RC_LOC_NAME, RC_CNF_NAME, RC_FNC_NAME, RC_QRY_NAME, RC_TMP_NAME, RC_OWN_NAME, RC_GRP_NAME, RC_MSK_NAME, RC_ASS_NAME, RC_DEF_NAME, RC_REF_NAME, RC_PRM_NAME, RC_TRM_NAME, RC_NCF_NAME, RC_CMN_NAME, RC_DFL_NAME, RC_ERR_NAME }; if (m_nLocks) { /* Make sure config exists */ return((const char *)s_szOptnametab[Optname]); } else { RC_THROW(RC_ERR_USE); } return(NULL); /* Not reached */ } const char *configGetrcfile(void) { ex_t Except; char *szRcname = NULL; if (m_nLocks) { /* Make sure config exists */ try { /* Because (1) only one rc file can be specified and */ /* (2) it must be specified on the command line, */ /* we don't bother checking the environment or conf file */ /* contrary to the behaviour of Getval earlier */ szRcname = (char *)clioptGetrcfile(); } catch(Except) rethrow; return((const char *)szRcname); } else RC_THROW(RC_ERR_USE); return(NULL); /* Not reached */ } const char **configGetsecs(void) { ex_t Except; char **pszSecname = NULL; if (m_nLocks) { /* Make sure config exists */ try { /* FIXME Might need to check */ pszSecname = (char **)clioptGetsecs(); /* FIXME env, conf, configs */ } catch(Except) rethrow; return((const char **)pszSecname); } else RC_THROW(RC_ERR_USE); return(NULL); /* Not reached */ } /************************************************ * configLoad(int, const char **) * * Load a configuration * ************************************************/ rc_return_t configLoad(int nTotal, const char *szArgvec[]) { ex_t Except; try { /* Parse option groups in order of priority */ clioptParseopts(nTotal, szArgvec); /* Command line options */ configVerify(); /* Test for usage, help and version options */ clioptParseargs(); /* Command line args */ /* envoptParse(m_nLocks->pOpt);*/ /* Environment options */ /* cnfoptParse(m_nLocks->pOpt);*/ /* Configfile options */ /* Test if information is asked of the operating environment */ if (configGetval(RC_INF_VAL)) { /* These lines must come after */ configInfo(); /* option parsing is finished! */ } } catch(Except) rethrow; return(RC_THROW(RC_OK)); } /************************************************ * configVerify(void) * * Verify config options help, usage, or version * * and ensure that no uncompatible option * * combinations were given * ************************************************/ rc_return_t configVerify(void) { ex_t Except; short bStop = FALSE; try { /* Checks for legal option combination */ /* I'm too braindead to remember digital logic theory from the */ /* Uni, so I'll hack my own XOR gates with plain math instead */ /* Exec XOR Eval XOR Print */ if (!configGetval(RC_EVL_VAL) \ + !configGetval(RC_EXC_VAL) \ + !configGetval(RC_PRN_VAL) \ + !configGetval(RC_PAR_VAL) < 3) { /* Warning! Magic number */ fprintf(stderr, RC_EEP_TEXT); bStop = TRUE; } /* Silent XOR OutputOptions */ if (configGetval(RC_SIL_VAL) && (configGetval(RC_DBG_VAL) \ || configGetval(RC_VER_VAL) || configGetval(RC_EVL_VAL) \ || configGetval(RC_HLP_VAL) || configGetval(RC_INF_VAL) \ || configGetval(RC_LBL_VAL) || configGetval(RC_PRN_VAL) \ || configGetval(RC_PAR_VAL) || configGetval(RC_RAW_VAL) \ || configGetval(RC_VRB_VAL) || configGetval(RC_QRY_VAL))) { fprintf(stderr, RC_SLO_TEXT); bStop = TRUE; } } catch(Except) rethrow; if (bStop) { /* Did user blow an option rule? */ clioptPrintusage(); /* Yes, so announce it as SUE. */ return(RC_THROW(RC_ERR_TRM)); } try { /* Basic checks of version, usage, and help options */ if (configGetval(RC_USE_VAL)) { clioptPrintusage(); bStop = TRUE; } else if (configGetval(RC_HLP_VAL)) { clioptPrintusage(); /* FIXME Replace with real help FIXME */ bStop = TRUE; } else if (configGetval(RC_VER_VAL)) { fprintf(stdout, "OSSP rc %s\n", RC_VERSION); bStop = TRUE; } } catch(Except) rethrow; if (bStop) /* Did user request a non-operation? */ return(RC_THROW(RC_ERR_TRM)); /* Yes, so terminate after handling. */ else return(RC_THROW(RC_OK)); /* No, we should continue processing. */ } /************************************************ * configDefaults(void) * * Write default values to empty config members * ************************************************/ rc_return_t configDefaults(void) { ex_t Except; DIR *pDir = NULL; /* For detecting our temp dir with opendir(3) */ try { /* Test members for empty attributes */ if (!configGetval(RC_EVL_VAL) && !configGetval(RC_EXC_VAL) \ && !configGetval(RC_PRN_VAL) && !configGetval(RC_PAR_VAL)) clioptSetval(RC_EXC_VAL, RC_DEF_ON); /* if (!configGetval(RC_LBL_VAL)) if (!configGetval(RC_SIL_VAL)) if (!configGetval(RC_RAW_VAL)) if (!configGetval(RC_VRB_VAL))*/ if (configGetval(RC_LOC_VAL)) { if ((pDir = opendir(configGetval(RC_LOC_VAL))) == NULL) return(RC_THROW(RC_ERR_LOC)); /* Failure, dir doesn't exist */ else closedir(pDir); /* Success, directory exists */ } else clioptSetval(RC_LOC_VAL, "./"); /* if (!configGetval(RC_CNF_VAL)) { If exists '/etc/rcconf' clioptSetval(RC_CNF_VAL, "/etc/rcconf"); Else RC_NOP; } if (!configGetval(RC_FNC_VAL)) { If exists '/etc/rc.func' clioptSetval(RC_FNC_VAL, "/etc/rc.func"); Else RC_NOP; } */ /* if (!configGetval(RC_QRY_VAL))*/ if (configGetval(RC_TMP_VAL)) { if ((pDir = opendir(configGetval(RC_TMP_VAL))) == NULL) return(RC_THROW(RC_ERR_TMP)); /* Failure, tmp doesn't exist */ else closedir(pDir); /* Success, tmp dir exists */ } else { /* User didn't set tmp so */ clioptSetval(RC_TMP_VAL, RC_DEF_TMP); /* set it for them here */ if ((pDir = opendir(RC_DEF_TMP)) == NULL) /* Try using default */ return(RC_THROW(RC_ERR_TMP)); /* Failure, default not there */ else closedir(pDir); } if (!configGetval(RC_TMP_VAL)) { pDir = opendir(RC_DEF_TMP); if (pDir) clioptSetval(RC_TMP_VAL, RC_DEF_TMP); closedir(pDir); } /* if (!configGetval(RC_OWN_VAL)) if (!configGetval(RC_GRP_VAL)) if (!configGetval(RC_MSK_VAL)) if (!configGetval(RC_ASS_VAL))*/ if (!configGetval(RC_DEF_VAL)) clioptSetval(RC_DEF_VAL, RC_DEF_DEF); /* if (!configGetval(RC_REF_VAL)) if (!configGetval(RC_PRM_VAL)) if (!configGetval(RC_TRM_VAL))*/ if (!configGetval(RC_NCF_VAL)) clioptSetval(RC_NCF_VAL, RC_DEF_NCF); if (!configGetval(RC_CMN_VAL)) clioptSetval(RC_CMN_VAL, RC_DEF_CMN); /* if (!configGetval(RC_DFL_VAL)) if (!configGetval(RC_ERR_VAL))*/ } catch(Except) rethrow; return(RC_THROW(RC_OK)); /* Normal response */ } /*************************************** * configDelete(void) * * Destruct a configuration * ***************************************/ rc_return_t configDelete(void) { ex_t Except; if (--m_nLocks == 0) { /* If m_nLocks is 0, deallocate */ try { /* FIXME, not thread-safe */ clioptDelete(); } catch(Except) rethrow; } else return(RC_THROW(RC_ERR_USE)); return(RC_THROW(RC_OK)); }