ossp-pkg/rc/rc_proc.c
1.21
/* 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_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 */
/* FIXME: Remove */
#include <sys/stat.h>
#include "rc.h" /* Public interfaces */
#include "rc_config.h" /* Option definitions */
/************************************************
* procNew(void) *
* Construct a processor *
************************************************/
rc_proc_t *procNew(void)
{
int nIter = 0;
rc_proc_t *pNewrc = NULL;
pNewrc = malloc(sizeof(rc_proc_t));
pNewrc->m_pAnal = analNew(); /* Construct a configuration analyser */
analParse(pNewrc->m_pAnal); /* Preprocess the anal configuration */
pNewrc->m_pScriptcom = scriptNew(); /* Construct a run-command script */
/* Logic needed for multiple run-command section combination with priorities */
pNewrc->m_ppScriptvec = malloc(sizeof(rc_script_t *) * pNewrc->m_pAnal->m_nRcs);
for (nIter = 0; nIter < pNewrc->m_pAnal->m_nRcs; nIter++)
pNewrc->m_ppScriptvec[nIter] = scriptNew();
return(pNewrc);
}
/************************************************
* procReadtmp(rc_proc_t *, const char *) *
* Open and store a temp file *
************************************************/
rc_return_t procReadtmp(rc_proc_t *pRc, const char *szTmpname)
{
fprintf(stderr, "%s!!!\n", szTmpname);
return(RC_THROW(RC_OK));
}
/************************************************
* procPopulate(rc_proc_t *) *
* Populate the processor with run commands *
************************************************/
rc_return_t procPopulate(rc_proc_t *pRc)
{
int i = 0;
int nFdrc = 0;
int nFdfunc = 0;
int nRet = 0;
int nIter = 0;
ex_t Except;
char *sBuf = NULL;
rc_section_t *pSec = NULL;
char *szLocex = NULL;
rc_script_t *pTempscript = NULL;
assert(*pRc->m_pAnal->m_szRcs);
sBuf = (char *)calloc(1, RC_READ_BUFSIZE);
/* Open the func file if it exists in the configuration */
if (pRc->m_pAnal->m_szFuncs) {
if ((nFdfunc = open(pRc->m_pAnal->m_szFuncs, O_RDONLY)) == -1) {
RC_THROW(RC_ERR_FNC);
}
}
/* Stick on the starting shell id line */
scriptAppend(pRc->m_pScriptcom, "#! /bin/sh\n", strlen("#! /bin/sh\n"));
/* Read the func file if it was opened successfully */
/* We unfortunately make the assumption that 0 is an invalid filedesc */
if (nFdfunc) {
/* Read data from the func file */
while ((nRet = read(nFdfunc, sBuf, RC_READ_BUFSIZE)) > 0) {
scriptAppend(pRc->m_pScriptcom, sBuf, nRet);
}
scriptAppend(pRc->m_pScriptcom, "\n", sizeof(char));
if (nRet == -1) /* Handle read errors */
RC_THROW(RC_ERR_IO);
}
/* Iteratively read possibly globbed rc files */
for (nIter = 0; nIter < pRc->m_pAnal->m_nRcs; nIter++)
{
assert(*pRc->m_pAnal->m_szRcs); /* If one of these assertions fail, */
assert(pRc->m_pAnal->m_szLocs); /* you've probably seen the ex_ bug */
/* Build the path name */
szLocex = (char *)malloc(strlen(pRc->m_pAnal->m_szLocs) + strlen(pRc->m_pAnal->m_szRcs[nIter]) + 2);
strcpy(szLocex, pRc->m_pAnal->m_szLocs);
strcat(szLocex, pRc->m_pAnal->m_szRcs[nIter]);
/* Open the rc file unconditionally */
if ((nFdrc = open(szLocex, O_RDONLY)) == -1)
RC_THROW(RC_ERR_RCF);
/* Read data from the rc file into a temporary script */
pTempscript = scriptNew();
while ((nRet = read(nFdrc, sBuf, RC_READ_BUFSIZE)) > 0)
scriptAppend(pTempscript, sBuf, nRet);
if (nRet == -1) /* Handle read errors */
RC_THROW(RC_ERR_IO);
try {
/* Append config section if it exists */
pSec = scriptSection(pTempscript, configGetval(RC_NCF_VAL));
if (pSec) { /* Only operate if the section lookup succeeds */
scriptAppend(pRc->m_pScriptcom, sectionGetdata(pSec), strlen(sectionGetdata(pSec)));
scriptAppend(pRc->m_pScriptcom, "\n", sizeof(char));
sectionDelete(pSec); /* Cleanup */
pSec = NULL; /* Cleanup */
}
/* FIXME: Swap nested rcfile/section logic loops for section/rcfile ordering */
for (i = 0; pRc->m_pAnal->m_pszSecs[i]; i++) { /* Iterate over */
/* Extract a section from the temp script, and append it */
pSec = scriptSection(pTempscript, pRc->m_pAnal->m_pszSecs[i]);
if (pSec) { /* Only call if the section lookup succeeds */
scriptAppend(pRc->m_ppScriptvec[nIter], sectionGetdata(pSec),
sectionGetlen(pSec) - 1);
scriptAppend(pRc->m_ppScriptvec[nIter], "\n", sizeof(char));
}
else if (configGetval(RC_DBG_VAL)) /* Only show if debug set */
fprintf(stderr, "#Warning: Missing section '%s' in %s!\n",\
pRc->m_pAnal->m_pszSecs[i],\
pRc->m_pAnal->m_szRcs[nIter]);
if (pSec) /* Cleanup iterative section string */
sectionDelete(pSec);
}
}
catch(Except)
rethrow;
/* Clean up our crap */
scriptDelete(pTempscript); /* Temp script */
pTempscript = NULL;
free(szLocex); /* Temp Location + Rcfile */
szLocex = NULL;
close(nFdrc); /* Close Rc file handle */
}
close(nFdfunc); /* Close Func file handle */
/* Memory cleanups */
if (sBuf) {
free(sBuf);
sBuf = NULL;
}
return(RC_THROW(RC_OK));
}
/************************************************
* procRun(rc_proc_t *) *
* Run the processed run-command script *
************************************************/
rc_return_t procRun(rc_proc_t *pRc)
{
int nIter = 0;
char *pszVec[RC_EXEC_MAXARGS];
/****************************************************/
/* This will execute, evaluate, or print the script */
/* Exec - Fork and execute each command */
/* Eval - Print machine evaluatable format */
/* Print - Print human readable format */
/****************************************************/
if (configGetval(RC_EVL_VAL)) /* Evaluate */
fprintf(stderr, "Error: Evaluate is not implemented yet.\n"); /* FIX */
else if (configGetval(RC_EXC_VAL)) { /* Execute */
pszVec[0] = "/bin/sh";
pszVec[1] = "-c";
pszVec[2] = (char *)scriptTostring(pRc->m_pScriptcom);
pszVec[3] = NULL; /* Add a NULL to mark the end of the chain */
if (execvp(*pszVec, pszVec) == -1) /* launch */
TRACE("Bad, execvp in child returned -1");
}
else if (configGetval(RC_PRN_VAL)) { /* Print */
scriptDump(pRc->m_pScriptcom);
for (nIter = 0; nIter < pRc->m_pAnal->m_nRcs; nIter++) {
if (*pRc->m_ppScriptvec[nIter])
scriptDump(pRc->m_ppScriptvec[nIter]);
}
}
else /* Something is wrong here */
return(RC_THROW(RC_ERR_INT));
return(RC_THROW(RC_OK));
}
/************************************************
* procDelete(rc_proc_t *) *
* Destruct a processor *
************************************************/
rc_return_t procDelete(rc_proc_t *pRc)
{
int nIter = 0;
/* Destroy the script vector */
for (nIter = pRc->m_pAnal->m_nRcs - 1; nIter >= 0 ; nIter--) {
if (pRc->m_ppScriptvec[nIter]) {
scriptDelete(pRc->m_ppScriptvec[nIter]);
pRc->m_ppScriptvec[nIter] = NULL;
}
}
free(pRc->m_ppScriptvec);
pRc->m_ppScriptvec = NULL;
scriptDelete(pRc->m_pScriptcom); /* Destroy the script */
analDelete(pRc->m_pAnal); /* Destroy the analyser */
free(pRc); /* Free the processor itself */
return(RC_THROW(RC_OK));
}