ossp-pkg/rc/rc_list.c
/* 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_list.c: Run-Command Processor ISO C source file
*/
#include <stdlib.h>
#include <string.h>
#include <dirent.h>
#include "rc.h" /* Public interfaces */
#include "rc_const.h" /* String constants */
#include "rc_config.h" /* Configuration interface */
/************************************************
* listNew(void) *
* Construct a new rcfile list *
************************************************/
rc_list_t *listNew(void)
{
rc_list_t *pNew = NULL;
/* Allocate storage for one list object */
pNew = calloc(1, sizeof(rc_list_t));
return(pNew);
}
/**************************************************
* private listPopulate(rc_list_t *, const char *) *
* Read the rcfile identifier and analyse it *
**************************************************/
rc_return_t listPopulate(rc_list_t *pInst, const char *kszName)
{
ex_t Except;
assert(pInst); /* Verify sanity */
assert(!pInst->m_ppFilevec); /* Rcfiles 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 */
/* FIXME mlelstv -- why malloc only a single pointer ? */
/* FIXME mlelstv -- why malloc when non-wildcard case allocs itself ? */
pInst->m_ppFilevec = malloc(sizeof (rc_file_t *));
if (strcmp(kszName, RC_GLOB_WILD)) {
/* FIXME mlelstv -- already using two pointes here */
pInst->m_ppFilevec[0] = rcfileNew(kszName); /* For an object */
pInst->m_ppFilevec[1] = rcfileNew(NULL); /* For the tail */
pInst->m_nFiles = 1; /* We handle just one rc file */
}
else { /* Wildcard rcfile indicates to glob the locs directories */
try {
DIR *pLocdir = NULL;
struct dirent *pDirent = NULL;
char *szLocations = NULL; /* Locations of run command files */
int nCount = 0; /* How many globbed files we find */
int nIter = 0; /* Used to step through found files */
assert(pInst); /* Sanity check */
/* Build the location path name */
if (!configGetval(RC_LOC_VAL)) {
szLocations = NULL;
szLocations = strdup("./"); /* FIXME: Relocate default val */
RC_THROW(RC_ERR_INT); /* Config should have given a locs default */
}
else { /* Only enter block with valid string, strdup can't handle NULL */
if (*(configGetval(RC_LOC_VAL) + strlen(configGetval(RC_LOC_VAL)) - \
sizeof (char)) != '/') {
szLocations = malloc(strlen(configGetval(RC_LOC_VAL)) + \
sizeof (char) + \
sizeof (char));
strcpy(szLocations, configGetval(RC_LOC_VAL));
strcat(szLocations, "/");
}
else
szLocations = strdup(configGetval(RC_LOC_VAL));
}
/* First just learn how many globbed files we have */
if ((pLocdir = opendir(szLocations)) == NULL)
return(RC_THROW(RC_ERR_LOC));
for (pDirent = readdir(pLocdir); pDirent; pDirent = readdir(pLocdir))
if (!strncmp(pDirent->d_name, "rc.", strlen("rc.")))
nCount++;
closedir(pLocdir);
/* Prepare resources before entering rcfile allocation loop */
if (nCount == 0) /* Check out the health of this directory listing */
return(RC_THROW(RC_ERR_LOC));
nIter = 0; /* Used in the next for block, so initialize */
/* FIXME mlelstv -- overwriting m_ppFilevec ?? */
pInst->m_ppFilevec = calloc(nCount + 1, sizeof (rc_file_t *));
if (!pInst->m_ppFilevec) /* Guard against memory overruns */
return(RC_THROW(RC_ERR_MEM));
/* FIXME mlelstv -- scanning directory twice, so being unsure
* about how many files we have
*/
if ((pLocdir = opendir(szLocations)) == NULL)
return(RC_THROW(RC_ERR_LOC));
/* Loop through file index setting rc file names according to dirent */
for (pDirent = readdir(pLocdir); pDirent; pDirent = readdir(pLocdir))
if (!strncmp(pDirent->d_name, "rc.", strlen("rc.")))
pInst->m_ppFilevec[nIter++] = rcfileNew(pDirent->d_name + strlen("rc.") * sizeof (char));
/* Clean up our used resources and prepare to exit */
pInst->m_ppFilevec[nIter] = rcfileNew(NULL); /* Make the tail */
pInst->m_nFiles = nIter; /* Store how many globbed files */
assert(nCount == nIter); /* Be cautious, ensure numbers */
free(szLocations); /* Cleanup our temp */
szLocations = NULL; /* locations string */
closedir(pLocdir);
}
catch(Except)
rethrow;
}
}
return(RC_THROW(RC_OK));
}
/************************************************
* listGetrcfile(rc_list_t *, const char *) *
* Searches the rcfile list and returns the file *
* matching the given name *
************************************************/
rc_file_t *listGetrcfile(rc_list_t *pInst, const char *kszName)
{
int nIter = 0;
assert(pInst && kszName); /* Dummy check */
/* Iterate through list, searching for a rcfile matching the given name */
for (nIter = 0; nIter < pInst->m_nFiles; nIter++) {
if (strcmp(pInst->m_ppFilevec[nIter]->m_szName, kszName) == 0)
/* Name of rcfile in list matched */
return(pInst->m_ppFilevec[nIter]);
}
return(NULL); /* Name did not match any rcfile */
}
/************************************************
* listDelete(rc_list_t *) *
* Destruct a rcfile list *
************************************************/
rc_return_t listDelete(rc_list_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_ppFilevec) {
/* free all rcfiles including extra tail element */
for (nIter = 0; nIter <= pInst->m_nFiles; nIter++) {
if (pInst->m_ppFilevec[nIter]) {
/* FIXME mlelstv -- should be rcfileDelete() */
free(pInst->m_ppFilevec[nIter]); /* Deallocate a rcfile */
pInst->m_ppFilevec[nIter] = NULL;
}
}
free(pInst->m_ppFilevec); /* Deallocate the rcfile vector */
pInst->m_ppFilevec = NULL;
}
free(pInst); /* Deallocate the list itself */
pInst = NULL;
return(RC_THROW(RC_OK));
}