/* 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_anal.c: Run-command processor ISO C source file
*/
#include
#include
#include "rc.h" /* Public interfaces */
#include "rc_const.h" /* String constants */
#include "rc_config.h" /* Configuration interface */
#include "rc_anal.h" /* Anal specific headers */
/************************************************
* analNew(void) *
* Construct a new analyser *
************************************************/
rc_anal_t *analNew(void)
{
rc_anal_t *pNew = NULL;
/* Allocate storage for 1 anal object */
pNew = calloc(1, sizeof(rc_anal_t));
return(pNew);
}
/************************************************
* private analRcs(rc_anal_t **, const char *) *
* Read a rc file identifier to analyse *
************************************************/
rc_return_t analRcs(rc_anal_t **ppInst, const char *kszName)
{
ex_t Except;
assert(!(*ppInst)->m_szRcs); /* Rcs should be NULL until we set them */
if (!kszName)
return(RC_THROW(RC_ERR_RCF));
else { /* Only enter block with valid string, strdup can't handle NULL */
(*ppInst)->m_szRcs = malloc(sizeof(char **));
if (strcmp(kszName, RC_GLOB_WILD)) {
(*ppInst)->m_szRcs = malloc(sizeof(*((*ppInst)->m_szRcs)));
*(*ppInst)->m_szRcs = strdup(kszName);
(*ppInst)->m_nRcs = 1; /* We handle just one rc file */
}
else { /* Wildcard rcfile indicates we must glob the locs directories */
try {
analGloblocs(ppInst);
}
catch(Except)
rethrow;
}
}
return(RC_THROW(RC_OK));
}
/************************************************
* private analTmp(rc_anal_t **, const char *) *
* Read a temp file to analyze *
************************************************/
rc_return_t analTmp(rc_anal_t **ppInst, const char *kszName)
{
if (!kszName) {
(*ppInst)->m_szTmp = NULL;
/* RC_THROW(RC_WRN_NUL);*/
}
else { /* Only enter block with valid string, strdup can't handle NULL */
(*ppInst)->m_szTmp = strdup(kszName);
}
return(RC_THROW(RC_OK));
}
/************************************************
* private analFuncs(rc_anal_t **, const char *) *
* Read a functions file to analyse *
************************************************/
rc_return_t analFuncs(rc_anal_t **ppInst, const char *kszName)
{
if (!kszName) {
(*ppInst)->m_szFuncs = NULL;
/* RC_THROW(RC_WRN_NUL);*/
}
else { /* Only enter block with valid string, strdup can't handle NULL */
(*ppInst)->m_szFuncs = strdup(kszName);
}
return(RC_THROW(RC_OK));
}
/************************************************
* private analLocs(rc_anal_t **, const char *) *
* Read a location path expression to analyse *
************************************************/
rc_return_t analLocs(rc_anal_t **ppInst, const char *kszPathexpr)
{
if (!kszPathexpr) {
(*ppInst)->m_szLocs = NULL;
(*ppInst)->m_szLocs = strdup("./"); /* FIXME: Relocate default val */
/* RC_THROW(RC_WRN_NUL);*/ /* FIXME: ex_ Illegal instruction - core dumped */
}
else { /* Only enter block with valid string, strdup can't handle NULL */
if (*(kszPathexpr + strlen(kszPathexpr)) != '/') {
(*ppInst)->m_szLocs = malloc(strlen(kszPathexpr) + 2 * sizeof(char));
strcpy((*ppInst)->m_szLocs, kszPathexpr);
if ((char)*((*ppInst)->m_szLocs + strlen((*ppInst)->m_szLocs) - 1) != '/')
strcat((*ppInst)->m_szLocs, "/");
}
else
(*ppInst)->m_szLocs = strdup(kszPathexpr);
}
return(RC_THROW(RC_OK));
}
/************************************************
* private analSecs(rc_anal_t **, const char **) *
* Read a sections vector to analyse *
************************************************/
rc_return_t analSecs(rc_anal_t **ppInst, const char **pkszVector)
{
ex_t Except;
if (!pkszVector) {
RC_THROW(RC_WRN_NUL);
}
ex_try { /* Sections are a vector, so we must copy accordingly */
(*ppInst)->m_pszSecs = vectorCopy(pkszVector);
(*ppInst)->m_nSecs = vectorCount(pkszVector);
}
ex_catch(Except)
rethrow;
return(RC_THROW(RC_OK));
}
/***************************************************************
* int analFileselect(struct dirent *Direntry) *
* Calculate whether a directory entry belongs to a defined set *
***************************************************************/
int analFileselect(struct dirent *Direntry)
{
if ((Direntry->d_name != NULL) && (strncmp(Direntry->d_name, "rc.", 3) == 0))
return (TRUE);
else if ((strcmp(Direntry->d_name, ".") == 0) || (strcmp(Direntry->d_name, "..") == 0))
return (FALSE);
else /* Catchall returns false for all not met set conditions */
return (FALSE);
}
/************************************************
* analGloblocs(rc_anal_t **ppInst) *
* Glob all files of the location directories *
************************************************/
rc_return_t analGloblocs(rc_anal_t **ppInst)
{
struct dirent ***pppFiles = NULL;
int nCount = 0; /* How many globbed files we find */
int nIter = 0; /* Iterate over the number of globbed files */
assert(*ppInst); /* Verify sanity */
/* Write the globbed filenames to our anal object */
pppFiles = malloc(sizeof(struct dirent));
nCount = scandir((*ppInst)->m_szLocs, pppFiles, analFileselect, alphasort);
/* Check out the health of this directory listing */
if (nCount == -1)
return(RC_THROW(RC_ERR_DIR));
else /* Allocate for the string array to hold directory entry names */
(*ppInst)->m_szRcs = malloc(sizeof((*((*ppInst)->m_szRcs))) * (nCount + 1));
/* Loop through file index setting rc file names according to dirent */
for (nIter = 0; nIter < nCount; ++nIter) {
(*ppInst)->m_szRcs[nIter] = strdup((*pppFiles)[nIter]->d_name +\
strlen("rc.") * sizeof(char));
}
(*ppInst)->m_szRcs[nIter] = NULL; /* Terminate */
(*ppInst)->m_nRcs = nCount; /* Store how many globbed files there are */
/* Cleanup our Dirent object */
if (pppFiles) {
free(pppFiles);
pppFiles = NULL;
}
return(RC_THROW(RC_OK));
}
/************************************************
* analParse(rc_anal_t *) *
* Parse the analyzed configuration data *
************************************************/
rc_return_t analParse(rc_anal_t *pInst)
{
ex_t Except;
assert(pInst); /* Verify sanity */
ex_try { /* Read in data from the main configuration */
analLocs (&pInst, configGetval(RC_LOC_VAL));
analRcs (&pInst, configGetrcfile());
analTmp (&pInst, configGetval(RC_TMP_VAL));
analFuncs(&pInst, configGetval(RC_FNC_VAL));
analSecs (&pInst, configGetsecs());
}
ex_catch(Except)
rethrow;
return(RC_THROW(RC_OK));
}
/************************************************
* analDelete(rc_anal_t *) *
* Destruct an analyser *
************************************************/
rc_return_t analDelete(rc_anal_t *pInst)
{
/* FIXME: It could be that pInst needs to be a double pointer to */
/* be properly used in destruction. Otherwise members are */
/* just copies of the stack parameters passed in. */
int nIter = 0;
assert(pInst); /* Verify sanity */
if (pInst->m_szRcs && pInst->m_szRcs[nIter])
while (pInst->m_szRcs[nIter]) /* Rc file names */
free(pInst->m_szRcs[nIter++]);
if (pInst->m_szRcs) /* Rc file name index */
free(pInst->m_szRcs);
if (pInst->m_szTmp) /* Temp file name */
free(pInst->m_szTmp);
if (pInst->m_szFuncs) /* Function file names */
free(pInst->m_szFuncs);
if (pInst->m_szLocs) /* Location path names */
free(pInst->m_szLocs);
if (pInst->m_pszSecs) /* Section names */
vectorDel(pInst->m_pszSecs);
free(pInst);
return(RC_THROW(RC_OK));
}