OSSP CVS Repository

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

ossp-pkg/rc/rc_script.c 1.13
/*  OSSP rc - Run-command processor
**  Copyright (c) 2002 Ralf S. Engelschall
**  Copyright (c) 2002 Cable & Wireless Deutschland GmbH
**  Copyright (c) 2002 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_script.c: Run-command processor ISO C source file
*/

#include <stdlib.h>
#include <string.h>

#include "rc.h"         /* Public Rc interface        */
#include "rc_pcre.h"    /* For section parsing        */
#include "rc_config.h"  /* For configuration access   */
#include "rc_const.h"   /* For configuration defaults */


/************************************************
* scriptNew(void)                               *
* Construct a script                            *
************************************************/
rc_script_t *scriptNew(void)
{
    rc_script_t *pScript = NULL;

    pScript = (rc_script_t *)malloc(sizeof(rc_script_t));
    *pScript = NULL;

    return(pScript);
}

/****************************************************
* scriptAppend(rc_script_t *, const char *, size_t) *
* Append text to a script                           *
****************************************************/
rc_return_t scriptAppend(rc_script_t *pScript, const char *szInbuf, size_t Size)
{
    int nResize     = 0;
    void *pvRealloc = NULL;

    assert(pScript); /* Script parameter must be valid */

    if (!szInbuf) {
TRACE("Problem with appendScript");
/*        return(RC_THROW(RC_ERR_USE));*/
    }

    /* Short circuit in case of dumb noop call */
    if (Size == 0) {
        return(RC_THROW(RC_OK));
    }

    /* Add 2 to end of nResize to ensure that a \0 precedes any strings */
    nResize = (*pScript != NULL ? strlen(*pScript) : 0) + Size + 2;
    /* Don't trust realloc(3) in this case */
    if ((pvRealloc = calloc(1, (size_t)nResize)) == NULL) {
TRACE("Problem with appendScript");
/*        return(RC_THROW(RC_ERR_MEM));*/
    }

    /* Coerce strings into one Script again */
    if (*pScript) {
        strcpy(pvRealloc, *pScript);
        strncat(pvRealloc, szInbuf, Size);
    }
    else
        strncpy(pvRealloc, szInbuf, Size);

    /* Cleanup and deallocate memory */
    if (*pScript) {
        free(*pScript);
        *pScript = NULL;
    }
    *pScript = pvRealloc;

    return(RC_THROW(RC_OK));
}

/************************************************
* scriptSection(rc_script_t *, const char *)    *
* Parse a script for a given section            *
************************************************/
rc_section_t *scriptSection(rc_script_t *pScript, const char *kszSecname)
{
    rc_section_t *pSec = NULL;
    char *piLabstart   = NULL;
    int   nLabsize     = NULL;
    char *piSubtemp    = NULL; /* To find priority and userid in substrings */
    char *piBlocend    = NULL; /* Misnomer used to control section looping */
    char *piStart      = NULL;
    char *piEnd        = NULL;
    int nOffset        = 0;
    int nFound         = 0;
    int nVecsize       = 0;
    int nSubstrings    = 0;
    int *pnVec         = NULL;
    const char *kszErr = NULL;
    const int kiRegopt = PCRE_DOTALL | PCRE_MULTILINE;
/*    const int kiRegopt = PCRE_DOTALL | PCRE_MULTILINE | PCRE_UNGREEDY;*/

    pcre *pRegex       = NULL;  /* Perl Compatible Regular Expression */
    pcre_extra *pExtra = NULL;  /* Used for studying an expression    */

    assert(pScript);            /* Check for a valid incoming script  */
    assert(configGetval(RC_DEF_VAL));

    if (!kszSecname)    /* If we get a NULL section label, then throw up */
        RC_THROW(RC_ERR_USE);

    if ((pRegex = pcre_compile(configGetval(RC_DEF_VAL), kiRegopt, &kszErr, &nOffset, NULL)) == NULL) {
        RC_THROW(RC_ERR_SYS);
    }

    pExtra = pcre_study(pRegex, 0, &kszErr); /* Study the FSM */
    if (kszErr) {   /* Variable contains a string reference in case of errors */
        free(pRegex);
        RC_THROW(RC_ERR_SYS);
    }

    if (pcre_fullinfo(pRegex, pExtra, PCRE_INFO_CAPTURECOUNT, &nSubstrings))
        RC_THROW(RC_ERR_SYS);

    /* Use multiples of six, because PCRE needs 2x multiples of three */
    nVecsize = 6 * (nSubstrings > 0 ? nSubstrings : 1);
    nVecsize *= RC_GOOD_MEASURE; /* Add redundancy factor for error margin */
/*    pAwesome += RC_GOOD_VIBRATIONS;*/ /* Add good vibes for super action */

    /***********************************************************************/
    /* Reminder: PCRE writes vectors to help identify substrings.          */
    /*           That means that in the following code we can              */
    /*           execute a compiled PCRE regex (ab)(\s)(.*)$               */
    /*                                                                     */
    /*           piBlocend + pnVec[0] = 'start of whole matched string'    */
    /*           piBlocend + pnVec[1] = 'end of whole matched string'      */
    /*           piBlocend + pnVec[2] = 'start of first substring (ab)'    */
    /*           piBlocend + pnVec[3] = 'end of first substring (ab)'      */
    /*           piBlocend + pnVec[4] = 'start of second substring (\s)'   */
    /*           piBlocend + pnVec[5] = 'end of second substring (\s)'     */
    /*           piBlocend + pnVec[6] = 'start of third substring (.*)'    */
    /*           piBlocend + pnVec[7] = 'end of third substring (.*)'      */
    /***********************************************************************/

    /* Filter the rc file for the section label, do it here the first time */
    pnVec = calloc(nVecsize, sizeof(int));  /* 2/3 vec 1/3 scrapinfo */
    nFound = pcre_exec(pRegex, pExtra, *pScript,\
        strlen(*pScript), 0, 0, pnVec, nVecsize);

    piBlocend = *pScript;   /* Start piBlocend pointing to the script object */
    while (nFound > 1) {    /* Loop as long as we have more sections */
        piLabstart = piBlocend + *(pnVec + 2);
        nLabsize   = *(pnVec + 3) - *(pnVec + 2);

/*fprintf(stderr, "Substring we want ist %s!\n", kszSecname);
fprintf(stderr, "Compared with ist %s!\n", piLabstart);*/
        /* Test the substring. If it matches our label, make a new section */
        if (!strncmp(piLabstart, kszSecname, nLabsize)) {
            /* Handle the section body */
            piStart   = piBlocend + *(pnVec + 6);
            piEnd     = piBlocend + *(pnVec + 7);
            pSec = sectionNew();
            pSec->szData = malloc(piEnd - piStart + sizeof(char));
            strncpy(pSec->szData, piStart, piEnd - piStart);
            *(pSec->szData + (piEnd - piStart)) = NULL; /* Terminate outgoing */

            /* Handle the section priority */
            piStart = piBlocend + *(pnVec + 4);
            piEnd   = piBlocend + *(pnVec + 5);
            /* FIXME: Implement --ParseSectionParam for extra gravy */
            piSubtemp = strnstr(piStart, RC_DEF_PRG, piEnd - piStart);
            if (piSubtemp) { /* Priority pattern found */
/* FIXME: Remove the 1 in the following line! */
                pSec->nPri = strtol(piSubtemp + strlen(RC_DEF_PRG) + 1, (char **)NULL, 10);
            }
            else /* Fallback to default value */
                pSec->nPri = RC_DEF_PRI;

/*fprintf(stderr, "nPri ist %d!\n", pSec->nPri);*/
            /* Handle the section userid   */
            return(pSec);   /* Section found, so return the text */
        }

        /* Looks like we didn't find the section yet, so keep trying */
        piBlocend += *(pnVec + 1);  /* Find end of section block */
        nFound = pcre_exec(pRegex, pExtra, piBlocend,\
            strlen(piBlocend), 0, 0, pnVec, nVecsize);
    }

    /* Under correct conditions, the section subscript was returned in loop */
    if (nFound == 1)                        /* User gave no klammern */
        RC_THROW(RC_ERR_USE);               /* so complain about it */
    else if (nFound < PCRE_ERROR_NOMATCH)   /* Generic problem so */
        RC_THROW(RC_ERR_SYS);               /* return an error */

    return(NULL);                           /* Probably not found */
}

/************************************************
* scriptTostring(rc_script_t *)                 *
* Return the private script data as a string    *
************************************************/
const char *scriptTostring(rc_script_t *pScript)
{
    /* Don't remove this! It encapsulates the script object, */
    /*                    which might not be a simple string */
    if (pScript)
        return(*pScript);
    else
        return(NULL);
}

/************************************************
* scriptDump(rc_script_t *)                     *
* Print a script to standard out                *
************************************************/
rc_return_t scriptDump(rc_script_t *pScript)
{
    /* Don't remove this! It encapsulates the script object, */
    /*                    which might not be a simple string */
    fprintf(stdout, "%s", *pScript);
    return(RC_THROW(RC_OK));
}

/************************************************
* scriptDelete(rc_script_t *)                   *
* Destruct a script                             *
************************************************/
rc_return_t scriptDelete(rc_script_t *pScript)
{
    if (*pScript)
        free(*pScript);
    else {
TRACE("Empty script created, unused, then destroyed");
/*        RC_THROW(RC_WRN_NUL);*/
    }
    free(pScript);

    return(RC_THROW(RC_OK));
}


CVSTrac 2.0.1