OSSP CVS Repository

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

ossp-pkg/rc/rc_proc.c 1.59
/*  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_proc.c: Run-command processor ISO C source file
*/

#include <stdlib.h>     /* Standard system headers    */
#include <fcntl.h>      /* For reading rc files       */
#include <unistd.h>     /* For reading rc files       */
#include <string.h>     /* For string manipulation    */
#include <signal.h>     /* For signal(3)              */
#include <sys/wait.h>   /* For waitpid(2) and fork(2) */

#include "rc.h"         /* Public interfaces          */
#include "rc_const.h"   /* String and value const     */
#include "rc_config.h"  /* Option definitions         */


/************************************************
* procNew(void)                                 *
* Construct a processor                         *
************************************************/
rc_proc_t *procNew(void)
{
    ex_t Except;
    rc_proc_t *pNewrc = NULL;

    ex_try {
        pNewrc = malloc(sizeof(rc_proc_t));
        pNewrc->m_pList = listNew();              /* Construct a rcfile list  */
        listPopulate(pNewrc->m_pList, configGetrcfile()); /* Prepopulate list */
        pNewrc->m_pScriptfunc = scriptNew(); /* Construct a functions script  */
        pNewrc->m_pScriptcnf  = scriptNew(); /* Construct a config script     */
    }
    ex_catch(Except)
        rethrow;

    return(pNewrc);
}

/************************************************
* procPopulate(rc_proc_t *)                     *
* Populate the processor with run commands      *
************************************************/
rc_return_t procPopulate(rc_proc_t *pRc)
{
    int nSect   = 0;
    int nFdfunc = -1;
    int nRet    = 0;
    int nRcs    = 0;
    ex_t Except;

    char         *sBuf        = NULL;
    rc_file_t    *pRcfile     = NULL;
    rc_section_t *pSec        = NULL;
    rc_section_t *pCom        = NULL;
    short         nTotalsecs  = vectorCount(configGetsecs());

    assert(pRc->m_pList->m_ppFilevec);
    sBuf = (char *)calloc(1, RC_READ_BUFSIZE);

    /* Open the func file if it exists in the configuration */
    if (configGetval(RC_FNC_VAL)) {
        /* FIXME: Funcfile data does not belong in config section data! */
        if ((nFdfunc = open(configGetval(RC_FNC_VAL), O_RDONLY)) >= 0) {
            /* Read data from the func file */
            while ((nRet = read(nFdfunc, sBuf, RC_READ_BUFSIZE)) > 0)
                scriptnAppend(pRc->m_pScriptfunc, sBuf, nRet);
            if (nRet == -1) /* Handle read errors */
                RC_THROW(RC_ERR_IO);
            scriptnAppend(pRc->m_pScriptfunc, "\n", sizeof("\n"));
            close(nFdfunc); /* Close Func file handle */
        }
        else
            RC_THROW(RC_ERR_FNC);
    }

    /* Iteratively read possibly globbed rc files */
    for (nRcs = 0; nRcs < pRc->m_pList->m_nFiles; nRcs++)
    {
        if (!pRc->m_pList->m_ppFilevec[nRcs])
            RC_THROW(RC_ERR_INT); /* Rcfile vector is missing its tail */

        pRcfile = rcfileNew(pRc->m_pList->m_ppFilevec[nRcs]->m_szName);
        rcfileParse(pRcfile);

        try { /* If it exists, append config section unconditionally */
            pSec = rcfileGetsec(pRcfile, configGetval(RC_NCF_VAL));
            if (pSec) { /* Only operate if the section lookup succeeds */
                scriptAdd(pRc->m_pScriptcnf, sectionGetscript(pSec));
                scriptnAppend(pRc->m_pScriptcnf, "\n", strlen ("\n"));
            }

            for (nSect = 0; nSect < nTotalsecs; nSect++) { /* Iterate over */
                /* Extract a section from the temp script, and append it */
                pSec = rcfileGetsec(pRcfile, configGetsecs()[nSect]);
                if (pSec) {
                    /* Append common section only if the target section matches */
                    pCom = rcfileGetsec(pRcfile, configGetval(RC_CMN_VAL));
                    if (pCom)   /* Only append if the common lookup succeeds */
                        rcfileAppendsec(pRc->m_pList->m_ppFilevec[nRcs], pCom);
                    /* Only copy if the section lookup succeeds */
                    rcfileAppendsec(pRc->m_pList->m_ppFilevec[nRcs], pSec);
                }
                else if (configGetval(RC_DBG_VAL)) /* Only show if debug set */
                    fprintf(stderr, "#Warning: Missing section '%s' in %s!\n",\
                        configGetsecs()[nSect], pRc->m_pList->m_ppFilevec[nRcs]->m_szName);
            }
        }
        catch(Except)
            rethrow;

        /* Attach our rcfile in the list */
        pRc->m_pList->m_ppFilevec[nRcs] = pRcfile;
        pRcfile = NULL;
    }

    /* Memory cleanups */
    if (sBuf) {
        free(sBuf);
        sBuf = NULL;
    }

    return(RC_THROW(RC_OK));
}

/*******************************************
* procRun(rc_proc_t *)                     *
* Run the processed run-command script     *
* Exec  - Fork and execute each command    *
* Eval  - Print machine evaluatable format *
* Print - Print human readable format      *
*******************************************/
rc_return_t procRun(rc_proc_t *pRc)
{
    if (configGetval(RC_EVL_VAL))       /* Evaluate */
        return(procEval(pRc));
    else if (configGetval(RC_EXC_VAL))  /* Execute */
        return(procExec(pRc));
    else if (configGetval(RC_PRN_VAL))  /* Print  */
        return(procPrint(pRc));
    else if (configGetval(RC_PAR_VAL))  /* Parse */
        return(procParse(pRc));
    else
        return(RC_ERR_INT); /* Run mode was not correctly set */
}

/************************************************
* procEval(rc_proc_t *)                         *
* Evaluate the run-command script               *
************************************************/
rc_return_t procEval(rc_proc_t *pRc)
{
    short  nSecs      = 0;                      /* Section index  */
    short  nTotalsecs = vectorCount(configGetsecs()); /* Sections */
    short  nRcs       = 0;                      /* Rc index       */
    int    nTmp       = 0;                      /* Generic index  */
    size_t nTmpname   = 0;                      /* Temp name size */
    size_t nBytes     = 0;                      /* Size in bytes  */

    char *szTmp     = NULL;           /* Generic temporary string */
    char *szTmpfile = NULL;           /* Path of temporary file   */
    char *szVerbose = NULL;           /* Used when handling verbose mode */

    rc_section_t **ppSectmp   = NULL; /* Used with priority scheduling   */
    rc_script_t   *pFatscript = NULL; /* To build a comprehensive script */

    /* Allocate a block of section pointers to use temporarily */
    ppSectmp = calloc(pRc->m_pList->m_nFiles, sizeof(rc_section_t *));
    pFatscript = scriptNew();
    scriptnAppend(pFatscript, RC_BANG_STR, strlen(RC_BANG_STR)); /* Shebang */
    /* Conditionally output initial notice in verbal mode */
    if (configGetval(RC_VRB_VAL)) {
        szVerbose = malloc((strlen(RC_VST_TEXT) + 2) * sizeof (char));
        sprintf(szVerbose, "%s", RC_VST_TEXT);
        strcat(szVerbose, "\n");
        scriptnAppend(pFatscript, szVerbose, strlen(szVerbose));
        free(szVerbose);
        szVerbose = NULL;
    }
    /* Conditionally print funcs section notice in verbal mode */
    if (configGetval(RC_VRB_VAL)) {
        szVerbose = malloc((strlen(RC_EVF_TEXT) + 2) * sizeof (char));
        sprintf(szVerbose, "%s", RC_EVF_TEXT);
        strcat(szVerbose, "\n");
        scriptnAppend(pFatscript, szVerbose, strlen(szVerbose));
        free(szVerbose);
        szVerbose = NULL;
    }
    scriptAdd(pFatscript, pRc->m_pScriptfunc);
    for (nSecs = 0; nSecs < nTotalsecs; nSecs++) {
        for (nRcs = 0; nRcs < pRc->m_pList->m_nFiles; nRcs++) {
            for (nTmp = 0; nTmp < pRc->m_pList->m_ppFilevec[nRcs]->m_nSecs && \
                strcmp(pRc->m_pList->m_ppFilevec[nRcs]->m_ppSecvec[nTmp]->m_szName, \
                configGetsecs()[nSecs]); nTmp++);
            if (nTmp < pRc->m_pList->m_ppFilevec[nRcs]->m_nSecs)
                ppSectmp[nRcs] = pRc->m_pList->m_ppFilevec[nRcs]->m_ppSecvec[nTmp];
            else
                ppSectmp[nRcs] = NULL;
        }
        qsort((void *)ppSectmp, (size_t)pRc->m_pList->m_nFiles, \
            sizeof(rc_section_t *), priCompare);
        for (nTmp = 0; nTmp < pRc->m_pList->m_nFiles && ppSectmp[nTmp]; nTmp++) {
            if (configGetval(RC_VRB_VAL)) {
                /* Conditionally evaluate config section notice in verbal mode */
                nBytes = (strlen(RC_EVN_TEXT) + strlen(RC_DEF_NCF) + \
                    strlen(sectionGetparent(ppSectmp[nTmp])) + 2) * sizeof (char);
                szVerbose = malloc(nBytes);
                sprintf(szVerbose, RC_EVN_TEXT, RC_DEF_NCF, sectionGetparent(ppSectmp[nTmp]));
                strcat(szVerbose, "\n");
                scriptnAppend(pFatscript, szVerbose, strlen(szVerbose));
                free(szVerbose);
                szVerbose = NULL;
            }
            scriptAdd(pFatscript, pRc->m_pScriptcnf);

            /* Examine our list, and try to take the corresponding */
            /* common section data from it to add to your script   */
            {
                rc_section_t *pComsec = NULL;
                pComsec = rcfileGetsec(listGetrcfile(pRc->m_pList, \
                    ppSectmp[nTmp]->m_szParent), configGetval(RC_CMN_VAL));
                if (pComsec) { /* Do we have a common section to load? */
                    if (configGetval(RC_VRB_VAL)) {
                        szTmp = (char *)sectionGetname(pComsec);
                        nBytes = (strlen(RC_EVN_TEXT) + strlen(szTmp) + \
                            strlen (sectionGetparent(pComsec)) + \
                            strlen(RC_ECHO_STR) + strlen("\"\"") + 1) * \
                            sizeof (char);
                        szVerbose = malloc(nBytes);
                        sprintf(szVerbose, RC_EVN_TEXT, szTmp, sectionGetparent(pComsec));
                        strcat(szVerbose, "\n");
                        scriptnAppend(pFatscript, szVerbose, strlen(szVerbose));
                        free(szVerbose);
                        szVerbose = NULL;
                    }
                    scriptAdd(pFatscript, sectionGetscript(pComsec));
                }
            }

            /* Conditionally print each section notice in verbal mode */
            if (configGetval(RC_VRB_VAL)) {
                szTmp = (char *)sectionGetname(ppSectmp[nTmp]);
                nBytes = (strlen(RC_EVN_TEXT) + strlen(szTmp) + 2) * sizeof (char);
                szVerbose = malloc(nBytes);
                sprintf(szVerbose, RC_EVN_TEXT, szTmp, sectionGetparent(ppSectmp[nTmp]));
                strcat(szVerbose, "\n");
                scriptnAppend(pFatscript, szVerbose, strlen(szVerbose));
                free(szVerbose);
                szVerbose = NULL;
            }
            if ((szTmp = (char *)sectionGetlogin(ppSectmp[nTmp])) != NULL) {
                scriptnAppend(pFatscript, "#su ", strlen("#su "));
                scriptnAppend(pFatscript, szTmp, strlen(szTmp));
            }
            else
                scriptnAppend(pFatscript, "#exit ", strlen("#exit "));
            scriptnAppend(pFatscript, "\n", strlen("\n"));
            scriptAdd(pFatscript, sectionGetscript(ppSectmp[nTmp]));
        }
    }
    free(ppSectmp);
    ppSectmp = NULL;

    szTmpfile = (char *)configGetval(RC_TMP_VAL);
    nTmpname = (strlen(szTmpfile) + strlen(RC_EVL_TMP) + \
                strlen(RC_EVL_SUF) + 1) * sizeof(char);
    if (*(szTmpfile + (strlen(szTmpfile) - 1) * sizeof(char)) != '/')
        nTmpname += sizeof(char);
    szTmpfile = malloc(nTmpname);
    strcpy(szTmpfile, configGetval(RC_TMP_VAL));
    if (*(szTmpfile + (strlen(szTmpfile) - 1) * sizeof(char)) != '/')
        strcat(szTmpfile, "/");
    strcat(szTmpfile, RC_EVL_TMP);
    mktemp(szTmpfile);
    strcat(szTmpfile, RC_EVL_SUF);
    scriptWrite(pFatscript, szTmpfile); /* Write the whole script out */

    /* Conditionally don't remove the temp file (see constants) */
    if (configGetval(RC_DBG_VAL))
        fprintf(stdout, RC_EVL_DBG, szTmpfile);
    else
        fprintf(stdout, RC_EVL_OUT, szTmpfile, szTmpfile);

    /* Cleanup eval processing crap */
    free(szTmpfile);
    szTmpfile = NULL;
    scriptDelete(pFatscript);
    pFatscript = NULL;

    return(RC_THROW(RC_OK));
}

/************************************************
* procExec(rc_proc_t *)                         *
* Execute the run-command script                *
************************************************/
rc_return_t procExec(rc_proc_t *pRc)
{
    short nRcs       =  0;                      /* Rc index       */
    short nSecs      =  0;                      /* Section index  */
    short nTotalsecs =  vectorCount(configGetsecs()); /* Sections */
    rc_section_t **ppSectmp = NULL; /* Used with priority scheduling */

    int   nRunuid    = -1;                 /* The current user id */
    int   nSectuid   = -1;               /* The section's user id */
    int   nTmp       =  0;             /* Generic temporary index */
    int   nStat      =  0;                 /* Status forked child */

    pid_t Pidexec    = -1;            /* Spawning before execv(3) */
    char *pszVec[RC_EXEC_MAXARGS];  /* For passing in to execv(3) */
    char *szTmp     = NULL;           /* Generic temporary string */
    char *szFunc    = NULL;          /* Stores func script text   */
    char *szCnf     = NULL;          /* Stores config script text */
    char *szExec    = NULL;         /* Used only during exec mode */
    char *szVerbose = NULL;    /* Used when handling verbose mode */

    /* This block does nothing more than implement the feature,     */
    /* that allows rc to run unprivileged (as long as no privileged */
    /* code is used in the script sections to be executed           */
    for (nSecs = 0; nSecs < nTotalsecs; nSecs++) {
        for (nTmp = 0; nTmp < pRc->m_pList->m_nFiles; nTmp++) {
            if (pRc->m_pList->m_ppFilevec[nTmp]->m_ppSecvec && \
                pRc->m_pList->m_ppFilevec[nTmp]->m_ppSecvec[nSecs]) {
                nRunuid = getuid();
                nSectuid = pRc->m_pList->m_ppFilevec[nTmp]->m_ppSecvec[nSecs]->m_nUid;
                /* See if root user status is needed, and bail out if so */
                if (nRunuid != 0 && nSectuid != -1 && nRunuid != nSectuid) {
                    fprintf(stderr, RC_RUT_TEXT);
                    return(RC_THROW(RC_ERR_USE));
                }
            }
        }
    }
    /* Allocate a block of section pointers to use temporarily */
    ppSectmp = calloc(pRc->m_pList->m_nFiles, sizeof(rc_section_t *));
    szFunc = (char *)scriptGetdata(pRc->m_pScriptfunc);
    szCnf  = (char *)scriptGetdata(pRc->m_pScriptcnf);
    for (nSecs = 0; nSecs < nTotalsecs; nSecs++) {
        for (nRcs = 0; nRcs < pRc->m_pList->m_nFiles; nRcs++) {
            for (nTmp = 0; nTmp < pRc->m_pList->m_ppFilevec[nRcs]->m_nSecs && \
                strcmp(pRc->m_pList->m_ppFilevec[nRcs]->m_ppSecvec[nTmp]->m_szName, \
                            configGetsecs()[nSecs]); nTmp++);
            if (nTmp < pRc->m_pList->m_ppFilevec[nRcs]->m_nSecs)
                ppSectmp[nRcs] = pRc->m_pList->m_ppFilevec[nRcs]->m_ppSecvec[nTmp];
            else
                ppSectmp[nRcs] = NULL;
        }
        qsort((void *)ppSectmp, (size_t)pRc->m_pList->m_nFiles, sizeof(rc_section_t *), priCompare);
        pszVec[0] = "/bin/sh";  /* Run the bourne shell over the following */
        pszVec[1] = "-c";       /* Append script code of the sections */
        pszVec[3] = NULL;       /* Add a NULL to mark the end of the chain */
        nTmp = 0; /* Count from zero until however many sections we have */
        while (nTmp < pRc->m_pList->m_nFiles && ppSectmp[nTmp]) {
            /* Conditionally print config and other section notices in verbal mode */
            if (configGetval(RC_VRB_VAL)) { /* Verbose mode is active */
                size_t nSizverb = 0;
                size_t nPrescr  = 0;
                size_t nSecverb = 0;
                size_t nSection = 0;

                /* Allocate space just for string to prepare for verbose */
                nSizverb = (strlen(RC_EXN_TEXT) + strlen(RC_DEF_NCF) + \
                    strlen(sectionGetparent(ppSectmp[nTmp])) + strlen(RC_ECHO_STR) + \
                    strlen("\"\"") + 1) * sizeof (char);
                szVerbose = malloc(nSizverb);
                sprintf(szVerbose, RC_EXN_TEXT, RC_DEF_NCF, sectionGetparent(ppSectmp[nTmp]));

                /* Allocate space for entire string to execvp(3) */
                nPrescr = (strlen(RC_VST_TEXT) + strlen(RC_EXF_TEXT) + \
                    strlen(szVerbose) + strlen(szFunc) + strlen(szCnf) + \
                    strlen(RC_BANG_STR) + 1) * sizeof (char);
                szExec = malloc(nSizverb + nPrescr);

                strcpy(szExec, RC_BANG_STR);    /* Start out with the bang string */
                strcat(szExec, RC_ECHO_STR);    /* Continue with the echo string */
                strcat(szExec, "\"");           /* Append a quote next to the echo */
                strcat(szExec, RC_VST_TEXT);    /* Continue with the start text */

                if (strlen(szFunc) > 0) {
                    strcat(szExec, "\n");        /* Stick a newline inbetween */
                    strcat(szExec, RC_EXF_TEXT); /* Continue with the func text */
                }

                strcat(szExec, "\";");          /* Finalize the verbosity notice */
                strcat(szExec, szFunc);         /* Continue with the funcs script code */
                strcat(szExec, RC_ECHO_STR);    /* Continue with the echo string */
                strcat(szExec, "\"");           /* Append a quote next to the echo */
                strcat(szExec, szVerbose);      /* Continue with the config text */
                strcat(szExec, "\";");          /* Finalize the verbosity notice */
                strcat(szExec, szCnf);          /* Then with the config script code  */

                /* Examine our list, and try to take the corresponding */
                /* common section data from it to add to your script   */
                {
                    rc_section_t *pComsec = NULL;
                    pComsec = rcfileGetsec(listGetrcfile(pRc->m_pList, \
                        ppSectmp[nTmp]->m_szParent), configGetval(RC_CMN_VAL));
                    if (pComsec) { /* If we have a common section to load,  */
                        szTmp = (char *)sectionGetname(pComsec);
                        nSecverb = (strlen(RC_EXN_TEXT) + strlen(szTmp) + \
                            strlen (sectionGetparent(pComsec)) + \
                            strlen(RC_ECHO_STR) + strlen("\"\"") + 1) * \
                            sizeof (char);
                        realloc(szVerbose, nSecverb);
                        sprintf(szVerbose, RC_EXN_TEXT, szTmp, sectionGetparent(pComsec));
                        nSection = (strlen(szTmp) + 1) * sizeof (char);
                        realloc(szExec, nSizverb + nPrescr + nSecverb + nSection);
                        strcat(szExec, RC_ECHO_STR);    /* Start out with the echo string */
                        strcat(szExec, "\"");           /* Append a quote next to the echo */
                        strcat(szExec, szVerbose);      /* Continue with the common text */
                        strcat(szExec, "\";");          /* Finalize the verbosity notice */
                        strcat(szExec, sectionGetdata(pComsec)); /* load it */
                    }
                }

                /* Build last set of verbose data for the actual script */
                szTmp = (char *)sectionGetname(ppSectmp[nTmp]);
                nSecverb = (strlen(RC_EXN_TEXT) + strlen(szTmp) * 2 \
                    + strlen(RC_ECHO_STR) + strlen("\"\"") + 1) * sizeof (char);
                realloc(szVerbose, nSecverb);
                sprintf(szVerbose, RC_EXN_TEXT, szTmp, sectionGetparent(ppSectmp[nTmp]));
                nSection = (strlen(szTmp) + strlen(sectionGetdata(ppSectmp[nTmp])) + 1) * sizeof (char);
                realloc(szExec, nSizverb + nPrescr + nSecverb + nSection);

                szTmp = (char *)sectionGetdata(ppSectmp[nTmp]);
                strcat(szExec, RC_ECHO_STR);    /* Start out with the echo string */
                strcat(szExec, "\"");           /* Append a quote next to the echo */
                strcat(szExec, szVerbose);      /* Continue with the verboseity text */
                strcat(szExec, "\";");          /* Finalize the verbosity notice */
                strcat(szExec, szTmp);          /* Then with the new script code */
                pszVec[2] = szExec;             /* Launch the new process image now  */
                free(szVerbose);
                szVerbose = NULL;

                /* Spawn the section shell code */
                switch (Pidexec = fork()) {
                    case -1:    /* Broken */
                        return(RC_THROW(RC_ERR_INT));
                        break;  /* Huh? */
                    case 0:     /* Child, runs script code through bourne shell */
                        nSectuid = sectionGetuid(ppSectmp[nTmp]);
                        if (nSectuid >= 0 && getuid() != nSectuid)
                            if (setuid(nSectuid) != 0)
                                return(RC_THROW(RC_ERR_ROOT));
                        if (execvp(*pszVec, pszVec) == -1)
                            return(RC_THROW(RC_ERR_INT));
                        break;
                    default: /* Parent, blocks until child returns */
                        waitpid(Pidexec, &nStat, WUNTRACED);
                        if ((nStat = WEXITSTATUS(nStat)) != 0)
                            return(nStat);
                        break;
                }
                if (szExec) {
                    free(szExec); /* Cleanup after exec */
                    szExec = NULL;
                }
            }
            else { /* Verbose mode is off */
                szTmp = (char *)sectionGetdata(ppSectmp[nTmp]);
                szExec = malloc((strlen(szFunc) + strlen(szCnf) + \
                    strlen(szTmp) + 1) * sizeof(char));
                strcpy(szExec, RC_BANG_STR);     /* Start out with the shebang string */
                strcat(szExec, szFunc); /* Continue with just the funcs script code   */
                strcat(szExec, szCnf);  /* Continue with just the config script code  */

                /* Examine our list, and try to take the corresponding */
                /* common section data from it to add to your script   */
                {
                    rc_section_t *pComsec = NULL;
                    pComsec = rcfileGetsec(listGetrcfile(pRc->m_pList, \
                        ppSectmp[nTmp]->m_szParent), configGetval(RC_CMN_VAL));
                    if (pComsec)   /* If we have a common section to load,  */
                        strcat(szExec, sectionGetdata(pComsec)); /* load it */
                }

                strcat(szExec, szTmp);  /* And build a section onto the command chain */
                pszVec[2] = szExec;     /* Actually launch the new process image now  */

                /* Spawn the section shell code */
                switch (Pidexec = fork()){
                    case -1:    /* Broken */
                        return(RC_THROW(RC_ERR_INT));
                        break;  /* Huh? */
                    case 0:     /* Child, runs script code through bourne shell */
                        nSectuid = sectionGetuid(ppSectmp[nTmp]);
                        if (nSectuid >= 0 && getuid() != nSectuid)
                            if (setuid(nSectuid) != 0)
                                return(RC_THROW(RC_ERR_ROOT));
                        if (execvp(*pszVec, pszVec) == -1)
                            return(RC_THROW(RC_ERR_INT));
                        break;
                    default: /* Parent, blocks until child returns */
                        waitpid(Pidexec, &nStat, WUNTRACED);
                        if ((nStat = WEXITSTATUS(nStat)) != 0)
                            return(nStat);
                        break;
                }
                free(szExec); /* Cleanup after exec */
                szExec = NULL;
            }
            nTmp++; /* Next rc script */
        }
    }
    free(ppSectmp);
    ppSectmp = NULL;

    return(RC_THROW(RC_OK));
}

/************************************************
* procPrint(rc_proc_t *)                        *
* Print the run-command script                  *
************************************************/
rc_return_t procPrint(rc_proc_t *pRc)
{
    size_t nBytes     = 0;                      /* Size in bytes  */
    int    nTmp       = 0;                      /* Generic index  */
    short  nRcs       = 0;                      /* Rc index       */
    short  nSecs      = 0;                      /* Section index  */
    short  nTotalsecs = vectorCount(configGetsecs()); /* Sections */
    rc_section_t **ppSectmp = NULL; /* Used with priority scheduling */

    char *szVerbose = NULL;    /* Used when handling verbose mode */
    char *szTmp     = NULL;           /* Generic temporary string */

    /* Allocate a block of section pointers to use as a temporary */
    ppSectmp = calloc(pRc->m_pList->m_nFiles, sizeof(rc_section_t *));

    /* Conditionally output initial notice in verbal mode */
    if (configGetval(RC_VRB_VAL))
        fprintf(stderr, "%s\n", RC_VST_TEXT);
    /* Conditionally print funcs section notice in verbal mode */
    if (configGetval(RC_VRB_VAL))
        fprintf(stderr, "%s\n", RC_PNF_TEXT);
    scriptDump(pRc->m_pScriptfunc); /* Dump the funcs script */

    for (nSecs = 0; nSecs < nTotalsecs; nSecs++) {
        for (nRcs = 0; nRcs < pRc->m_pList->m_nFiles; nRcs++) {
            for (nTmp = 0; nTmp < pRc->m_pList->m_ppFilevec[nRcs]->m_nSecs && \
                strcmp(pRc->m_pList->m_ppFilevec[nRcs]->m_ppSecvec[nTmp]->m_szName, \
                            configGetsecs()[nSecs]); nTmp++);
            if (nTmp < pRc->m_pList->m_ppFilevec[nRcs]->m_nSecs)
                ppSectmp[nRcs] = pRc->m_pList->m_ppFilevec[nRcs]->m_ppSecvec[nTmp];
            else
                ppSectmp[nRcs] = NULL;
        }
        qsort((void *)ppSectmp, (size_t)pRc->m_pList->m_nFiles, sizeof(rc_section_t *), priCompare);
        for (nTmp = 0; nTmp < pRc->m_pList->m_nFiles && ppSectmp[nTmp]; nTmp++) {
            if (configGetval(RC_VRB_VAL)) {
                /* Conditionally print config section notice in verbal mode */
                nBytes = (strlen(RC_PRN_TEXT) + strlen(RC_DEF_NCF) + \
                    strlen(sectionGetparent(ppSectmp[nTmp])) + 2) * sizeof (char);
                szVerbose = malloc(nBytes);
                sprintf(szVerbose, RC_PRN_TEXT, RC_DEF_NCF, sectionGetparent(ppSectmp[nTmp]));
                strcat(szVerbose, "\n");
                fprintf(stderr, szVerbose);
                free(szVerbose);
                szVerbose = NULL;
            }
            scriptDump(pRc->m_pScriptcnf);  /* Dump the config script */

            /* Examine our list, and try to take the corresponding */
            /* common section data from it to add to your script   */
            {
                rc_section_t *pComsec = NULL;
                pComsec = rcfileGetsec(listGetrcfile(pRc->m_pList, \
                    ppSectmp[nTmp]->m_szParent), configGetval(RC_CMN_VAL));
                if (pComsec) { /* Do we have a common section to load? */
                    if (configGetval(RC_VRB_VAL)) {
                        szTmp = (char *)sectionGetname(pComsec);
                        nBytes = (strlen(RC_PRN_TEXT) + strlen(szTmp) + \
                            strlen (sectionGetparent(pComsec)) + \
                            strlen(RC_ECHO_STR) + strlen("\"\"") + 1) * \
                            sizeof (char);
                        szVerbose = malloc(nBytes);
                        sprintf(szVerbose, RC_PRN_TEXT, szTmp, sectionGetparent(pComsec));
                        strcat(szVerbose, "\n");
                        fprintf(stderr, "%s", szVerbose);
                        free(szVerbose);
                        szVerbose = NULL;
                    }
                    sectionDump(pComsec);
                }
            }

            if (configGetval(RC_VRB_VAL)) {
                /* Conditionally print each section notice in verbal mode */
                szTmp = (char *)sectionGetname(ppSectmp[nTmp]);
                nBytes = (strlen(RC_PRN_TEXT) + strlen(szTmp) + 2) * sizeof (char);
                szVerbose = malloc(nBytes);
                sprintf(szVerbose, RC_PRN_TEXT, szTmp, sectionGetparent(ppSectmp[nTmp]));
                strcat(szVerbose, "\n");
                fprintf(stderr, "%s", szVerbose);
                free(szVerbose);
                szVerbose = NULL;
            }
            sectionDump(ppSectmp[nTmp]);
        }
    }
    free(ppSectmp);
    ppSectmp = NULL;

    return(RC_THROW(RC_OK));
}

/************************************************
* procParse(rc_proc_t *)                        *
* Parse the run-command script                  *
************************************************/
rc_return_t procParse(rc_proc_t *pRc)
{
    rc_section_t **ppSectmp = NULL; /* Used with priority scheduling */
    int    nTmp       = 0;                         /* Generic index  */
    short  nRcs       = 0;                         /* Rc index       */
    short  nSecs      = 0;                         /* Section index  */
    short  nTotalsecs = vectorCount(configGetsecs()); /* Sections    */

    /* Allocate a block of section pointers to use as a temporary */
    ppSectmp = calloc(pRc->m_pList->m_nFiles, sizeof(rc_section_t *));
    fprintf(stderr, "file %s, section %s\n", pRc->m_pList->m_ppFilevec[nRcs]->m_szName, RC_DEF_NCF);
    for (nSecs = 0; nSecs < nTotalsecs; nSecs++) {
        for (nRcs = 0; nRcs < pRc->m_pList->m_nFiles; nRcs++) {
            for (nTmp = 0; nTmp < pRc->m_pList->m_ppFilevec[nRcs]->m_nSecs && \
                strcmp(pRc->m_pList->m_ppFilevec[nRcs]->m_ppSecvec[nTmp]->m_szName, \
                            configGetsecs()[nSecs]); nTmp++);
            if (nTmp < pRc->m_pList->m_ppFilevec[nRcs]->m_nSecs)
                ppSectmp[nRcs] = pRc->m_pList->m_ppFilevec[nRcs]->m_ppSecvec[nTmp];
            else
                ppSectmp[nRcs] = NULL;
        }
        qsort((void *)ppSectmp, (size_t)pRc->m_pList->m_nFiles, sizeof(rc_section_t *), priCompare);
        for (nTmp = 0; nTmp < pRc->m_pList->m_nFiles && ppSectmp[nTmp]; nTmp++)
            fprintf(stderr, "section %s\n", ppSectmp[nTmp]->m_szName);
    }
    free(ppSectmp);
    ppSectmp = NULL;

    return(RC_THROW(RC_OK));
}

/************************************************
* procDelete(rc_proc_t *)                       *
* Destruct a processor                          *
************************************************/
rc_return_t procDelete(rc_proc_t *pRc)
{
    int nRcs = pRc->m_pList->m_nFiles;

    scriptDelete(pRc->m_pScriptcnf);    /* Destroy the config script */
    pRc->m_pScriptcnf = NULL;
    scriptDelete(pRc->m_pScriptfunc);   /* Destroy the funcs script  */
    pRc->m_pScriptfunc = NULL;

    /* Destroy the rcfile objects */
    while (nRcs-- > 0)
        if (rcfileExists(pRc->m_pList->m_ppFilevec[nRcs])) {
            rcfileDelete(pRc->m_pList->m_ppFilevec[nRcs]);
            pRc->m_pList->m_ppFilevec[nRcs] = NULL;
        }

    free(pRc->m_pList->m_ppFilevec);
    pRc->m_pList->m_ppFilevec = NULL;
    listDelete(pRc->m_pList);           /* Destroy the rcfile list   */
    pRc->m_pList = NULL;
    free(pRc);                          /* Free the processor itself */
    pRc = NULL;

    return(RC_THROW(RC_OK));
}


CVSTrac 2.0.1