OSSP CVS Repository

ossp - ossp-pkg/rc/rc_config.c
Not logged in
[Honeypot]  [Browse]  [Directory]  [Home]  [Login
[Reports]  [Search]  [Ticket]  [Timeline
  [Raw

ossp-pkg/rc/rc_config.c
/*  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 <http://www.ossp.org/>
**
**  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 <stdlib.h>
#include <string.h>
#include <dirent.h>     /* For opendir(3) */

#include "rc.h"
#include "rc_config.h"
#include "rc_const.h"   /* String constants */

/* Cludge the version id */
#define _RC_VERSION_C_AS_HEADER_
#include "rc_version.c"
#undef  _RC_VERSION_C_AS_HEADER_


static int m_nLocks = 0;    /* Server locks, not thread-safe FIXME  */

/***************************************
* configNew(void)                      *
* Construct a configuration            *
***************************************/
rc_config_t configNew(void)
{
    ex_t Except;
    rc_config_t *pRetobj = NULL;

    if (m_nLocks == 0) {                            /* If we don't have one yet */
        pRetobj = malloc(sizeof (rc_config_t));     /* then construct a new one */
        if (pRetobj) {
            try {
                pRetobj->m_pCliopts = clioptNew();  /* Member cliopt instance   */
            }
            catch(Except)
                rethrow;
        }
        else
            RC_THROW(RC_ERR_MEM);
    }
    m_nLocks++;                             /* FIXME not threadsafe     */
    return(pRetobj);

/* Warn: Experimental design pattern code abstracts operations from config */
/*    configVisit(pfnSetdefaults);
    configVisit(pfnGetoptinfo);*/
}

/* 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.v_short);
            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(rc_config_t *)          *
* Destruct a configuration             *
***************************************/
rc_return_t configDelete(rc_config_t *this)
{
    ex_t Except;

    if (--m_nLocks == 0) {          /* If m_nLocks is 0, deallocate */
        try {                       /* FIXME, not thread-safe       */
            clioptDelete(this->m_pCliopts);
        }
        catch(Except)
            rethrow;
    }
    else
        return(RC_THROW(RC_ERR_USE));

    return(RC_THROW(RC_OK));
}

CVSTrac 2.0.1