/* OSSP rc - Run-command processor
** Copyright (c) 2002 Ralf S. Engelschall
** Copyright (c) 2002 Cable & Wireless Deutschland GmbH
** Copyright (c) 2002 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_script.c: Run-command processor ISO C source file
*/
#include
#include
#include "rc.h" /* Public Rc interface */
#include "rc_pcre.h" /* For section parsing */
#include "rc_config.h" /* For configuration access */
/************************************************
* 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 *, char *, size_t) *
* Append text to a script *
************************************************/
rc_return_t scriptAppend(rc_script_t *pScript, 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 *
************************************************/
char *scriptSection(rc_script_t *pScript, const char *kszSecname)
{
char *szTempout = NULL;
char *piLabstart = NULL;
int nLabsize = NULL;
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);
/* Test the substring. If it matches our label, generate a subscript */
if (!strncmp(piLabstart, kszSecname, nLabsize)) {
piStart = piBlocend + *(pnVec + 6);
piEnd = piBlocend + *(pnVec + 7);
szTempout = malloc(piEnd - piStart + sizeof(char));
strncpy(szTempout, piStart, piEnd - piStart);
*(szTempout + (piEnd - piStart)) = NULL; /* Terminate outgoing */
return(szTempout); /* Section found, so return the text */
}
piBlocend += *(pnVec + 1); /* Find end of section block */
/* Get ready for the next round of matching */
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));
}