/* 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
**
** 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_cliopt.c: Run-Command Processor ISO C source file
*/
#include
#include
#include "rc.h"
#include "rc_const.h"
#include "rc_config.h"
#include "popt.h" /* OSSP popt options library */
static char *m_pszOptuples[RC_NUMOPTS]; /* Option name value tuples */
static char *m_szRcfile = NULL; /* rc file name */
static char **m_pszSecs = NULL; /* Section names */
static popt_context m_Optcon; /* Context for parsing options */
static struct popt_option m_pOptable[] = {
/* Long options are defined as short keys but no arguments */
{RC_USE_NAME, '?', POPT_ARG_NONE, 0, RC_USE_VAL, RC_USE_DESC, NULL},
{RC_DBG_NAME, 'D', POPT_ARG_NONE, 0, RC_DBG_VAL, RC_DBG_DESC, NULL},
{RC_VER_NAME, 'V', POPT_ARG_NONE, 0, RC_VER_VAL, RC_VER_DESC, NULL},
{RC_EVL_NAME, 'e', POPT_ARG_NONE, 0, RC_EVL_VAL, RC_EVL_DESC, NULL},
{RC_HLP_NAME, 'h', POPT_ARG_NONE, 0, RC_HLP_VAL, RC_HLP_DESC, NULL},
{RC_INF_NAME, 'i', POPT_ARG_NONE, 0, RC_INF_VAL, RC_INF_DESC, NULL},
{RC_LBL_NAME, 'l', POPT_ARG_NONE, 0, RC_LBL_VAL, RC_LBL_DESC, NULL},
{RC_PRN_NAME, 'p', POPT_ARG_NONE, 0, RC_PRN_VAL, RC_PRN_DESC, NULL},
{RC_PAR_NAME, 'a', POPT_ARG_NONE, 0, RC_PAR_VAL, RC_PAR_DESC, NULL},
{RC_SIL_NAME, 's', POPT_ARG_NONE, 0, RC_SIL_VAL, RC_SIL_DESC, NULL},
{RC_RAW_NAME, 'r', POPT_ARG_NONE, 0, RC_RAW_VAL, RC_RAW_DESC, NULL},
{RC_VRB_NAME, 'v', POPT_ARG_NONE, 0, RC_VRB_VAL, RC_VRB_DESC, NULL},
{RC_EXC_NAME, 'x', POPT_ARG_NONE, 0, RC_EXC_VAL, RC_EXC_DESC, NULL},
/* Single argument long options with short keys */
{RC_LOC_NAME, 'L', POPT_ARG_STRING, 0, RC_LOC_VAL, RC_LOC_DESC, "regx"},
{RC_CNF_NAME, 'c', POPT_ARG_STRING, 0, RC_CNF_VAL, RC_CNF_DESC, "path"},
{RC_FNC_NAME, 'f', POPT_ARG_STRING, 0, RC_FNC_VAL, RC_FNC_DESC, "path"},
{RC_QRY_NAME, 'q', POPT_ARG_STRING, 0, RC_QRY_VAL, RC_QRY_DESC, "varx"},
{RC_TMP_NAME, 't', POPT_ARG_STRING, 0, RC_TMP_VAL, RC_TMP_DESC, "path"},
/* Single argument long options without short keys */
{RC_OWN_NAME, 0, POPT_ARG_STRING, 0, RC_OWN_VAL, RC_OWN_DESC, "user"},
{RC_GRP_NAME, 0, POPT_ARG_STRING, 0, RC_GRP_VAL, RC_GRP_DESC, "group"},
{RC_MSK_NAME, 0, POPT_ARG_INT, 0, RC_MSK_VAL, RC_MSK_DESC, "umask"},
{RC_ASS_NAME, 0, POPT_ARG_STRING, 0, RC_ASS_VAL, RC_ASS_DESC, "regx"},
{RC_DEF_NAME, 0, POPT_ARG_STRING, 0, RC_DEF_VAL, RC_DEF_DESC, "regx"},
{RC_REF_NAME, 0, POPT_ARG_STRING, 0, RC_REF_VAL, RC_REF_DESC, "regx"},
{RC_PRM_NAME, 0, POPT_ARG_STRING, 0, RC_PRM_VAL, RC_PRM_DESC, "regx"},
{RC_TRM_NAME, 0, POPT_ARG_STRING, 0, RC_TRM_VAL, RC_TRM_DESC, "regx"},
{RC_NCF_NAME, 0, POPT_ARG_STRING, 0, RC_NCF_VAL, RC_NCF_DESC, "name"},
{RC_CMN_NAME, 0, POPT_ARG_STRING, 0, RC_CMN_VAL, RC_CMN_DESC, "name"},
{RC_DFL_NAME, 0, POPT_ARG_STRING, 0, RC_DFL_VAL, RC_DFL_DESC, "name"},
{RC_ERR_NAME, 0, POPT_ARG_STRING, 0, RC_ERR_VAL, RC_ERR_DESC, "name"},
/* Special stuff */
POPT_AUTOHELP
{NULL, 0, 0, NULL, 0}
};
/***************************************
* clioptNew(void) *
* Construct a command line option *
***************************************/
rc_return_t clioptNew(void)
{
/* assert(s_pBintab == NULL); */ /* Error if constructed already */
/* s_pBintab = malloc(sizeof(*s_pBintab));*/ /* Allocate a cliopt instance */
/* if (!s_pBintab)
return(RC_THROW(RC_ERR_MEM));
s_pBintab->pOptlist = malloc(sizeof(*s_pBintab->pOptlist));*/
/*FIXME optNew((rc_opt_t **)&s_pBintab->pOptlist->pvData);FIXME*/
/* s_pBintab->pOptlist->pvData = NULL;
s_pBintab->pOptlist->pvNext = NULL;*/
memset(m_pszOptuples, 0L, sizeof(m_pszOptuples));
return(RC_THROW(RC_OK));
}
/***************************************
* clioptPrintusage() *
* Print usage to command line stderr *
***************************************/
rc_return_t clioptPrintusage(void)
{
popt_printusage(m_Optcon, stderr, 0);
return(RC_THROW(RC_OK));
}
/***************************************
* clioptGetXXX() *
* clioptSetXXX() *
* Command line option accessors *
***************************************/
const char *clioptGetval(rc_opt_t Optname)
{
if (!(Optname < RC_NUMOPTS)) /* Validate option range */
RC_THROW(RC_ERR_USE);
return((const char *)m_pszOptuples[Optname]);
}
const char *clioptGetrcfile(void)
{
if (!m_szRcfile)
RC_THROW(RC_ERR_USE);
return((const char *)m_szRcfile);
}
const char **clioptGetsecs(void)
{
if (!m_pszSecs)
RC_THROW(RC_ERR_USE);
return((const char **)m_pszSecs);
}
rc_return_t clioptSetval(rc_opt_t Optname, const char *kszOptval)
{
if (!(Optname < RC_NUMOPTS)) /* Validate option range */
return(RC_THROW(RC_ERR_USE));
if (!(kszOptval)) /* Validate string value */
return(RC_THROW(RC_ERR_USE));
if (!(m_pszOptuples[Optname] = strdup(kszOptval)))
return(RC_THROW(RC_ERR_MEM));
return(RC_THROW(RC_OK));
}
rc_return_t clioptSetrcfile(const char *kszRc)
{
if (m_szRcfile) /* Warn on overwrites */
RC_THROW(RC_WRN_OWR);
if (kszRc)
m_szRcfile = strdup(kszRc);
else
return(RC_THROW(RC_ERR_USE)); /* Incoming string is NULL? */
return(RC_THROW(RC_OK));
}
rc_return_t clioptSetsecs(const char **pkszSecs)
{
ex_t Except;
assert (pkszSecs); /* IF NULL, its broken */
if (m_pszSecs) /* Warn on overwrites */
RC_THROW(RC_WRN_OWR);
try {
m_pszSecs = vectorCopy(pkszSecs);
}
catch(Except)
rethrow;
return(RC_THROW(RC_OK));
}
/***************************************
* clioptProcess(int) *
* Switch through available options *
* processing the corresponding option *
* and update option table accordingly *
***************************************/
rc_return_t clioptProcess(int cliOption, const char *kszArg)
{
switch (cliOption) {
/* Begin concrete (digital) options */
case RC_USE_VAL:
clioptSetval(cliOption, RC_DEF_ON); break; /* Usage */
case RC_DBG_VAL:
clioptSetval(cliOption, RC_DEF_ON); break; /* Debug */
case RC_VER_VAL:
clioptSetval(cliOption, RC_DEF_ON); break; /* Version */
case RC_EVL_VAL:
clioptSetval(cliOption, RC_DEF_ON); break; /* Eval */
case RC_HLP_VAL:
clioptSetval(cliOption, RC_DEF_ON); break; /* Help */
case RC_INF_VAL:
clioptSetval(cliOption, RC_DEF_ON); break; /* Info */
case RC_LBL_VAL:
clioptSetval(cliOption, RC_DEF_ON); break; /* Label */
case RC_PRN_VAL:
clioptSetval(cliOption, RC_DEF_ON); break; /* Print */
case RC_PAR_VAL:
clioptSetval(cliOption, RC_DEF_ON); break; /* Print */
case RC_SIL_VAL:
clioptSetval(cliOption, RC_DEF_ON); break; /* Silent */
case RC_RAW_VAL:
clioptSetval(cliOption, RC_DEF_ON); break; /* Raw */
case RC_VRB_VAL:
clioptSetval(cliOption, RC_DEF_ON); break; /* Verbose */
case RC_EXC_VAL:
clioptSetval(cliOption, RC_DEF_ON); break; /* Exec */
/* Begin abstract (nondigital) options */
case RC_LOC_VAL:
clioptSetval(cliOption, kszArg); break; /* Locations */
case RC_CNF_VAL:
clioptSetval(cliOption, kszArg); break; /* Conf file */
case RC_FNC_VAL:
clioptSetval(cliOption, kszArg); break; /* Func file */
case RC_QRY_VAL:
clioptSetval(cliOption, kszArg); break; /* Format */
case RC_TMP_VAL:
clioptSetval(cliOption, kszArg); break; /* Temp dir */
case RC_OWN_VAL:
clioptSetval(cliOption, kszArg); break; /* User name */
case RC_GRP_VAL:
clioptSetval(cliOption, kszArg); break; /* Group name */
case RC_MSK_VAL:
clioptSetval(cliOption, kszArg); break; /* Umask */
case RC_ASS_VAL:
clioptSetval(cliOption, kszArg); break; /* Assignregex */
case RC_DEF_VAL:
clioptSetval(cliOption, kszArg); break; /* Labelregex */
case RC_REF_VAL:
clioptSetval(cliOption, kszArg); break; /* Refregex */
case RC_PRM_VAL:
clioptSetval(cliOption, kszArg); break; /* Paramregex */
case RC_TRM_VAL:
clioptSetval(cliOption, kszArg); break; /* Termregex */
case RC_NCF_VAL:
clioptSetval(cliOption, kszArg); break; /* Configname */
case RC_CMN_VAL:
clioptSetval(cliOption, kszArg); break; /* Commonname */
case RC_DFL_VAL:
clioptSetval(cliOption, kszArg); break; /* Defaultname */
case RC_ERR_VAL:
clioptSetval(cliOption, kszArg); break; /* Errorname */
default : break;
}
return(RC_THROW(RC_OK));
}
/***************************************
* clioptParseopts(int, const char **) *
* Parse command line options *
***************************************/
rc_return_t clioptParseopts(int nArgs, const char *szVector[])
{
ex_t Except;
char cliOpt = 0; /* For argument parsing */
m_Optcon = popt_getcontext(NULL, nArgs, szVector, m_pOptable, 0);
popt_setotheroptionhelp(m_Optcon, " ");
if (nArgs < 2) { /* Allow the user to enter just one option, -h z.B. */
fprintf(stderr, RC_LST_TEXT);
popt_printusage(m_Optcon, stderr, 0);
return(RC_THROW(RC_ERR_USE));
}
/* Now do options processing */
while ((cliOpt = popt_getnextopt(m_Optcon)) >= 0) {/* Loop, each time */
try { /* eating a new option */
clioptProcess(cliOpt, popt_getoptarg(m_Optcon));
}
catch(Except) /* Error condition probably deserves attention */
rethrow;
}
if (cliOpt < -1) { /* The option given was not found in the index */
fprintf(stderr, "%s: %s\n",
popt_badoption(m_Optcon, POPT_BADOPTION_NOALIAS),
popt_strerror(cliOpt));
return(RC_THROW(RC_ERR_USE));
}
return(RC_THROW(RC_OK));
}
/******************************************
* clioptParseargs(void) *
* Parse command line rc file and sections *
******************************************/
rc_return_t clioptParseargs(void)
{
ex_t Except;
/* Use popt as a transport to read the user specified rcfile and sections */
try {
clioptSetrcfile(popt_getarg(m_Optcon));
clioptSetsecs(popt_getargs(m_Optcon));
}
catch(Except)
rethrow; /* Our generic response */
return(RC_THROW(RC_OK));
}
/***************************************
* clioptDelete(void) *
* Destruct a command line option *
***************************************/
rc_return_t clioptDelete(void)
{
int i = 0;
/* ex_t Except;
assert(s_pBintab);*/ /* Error if not constructed */
/* try {
clioptRemall();*/ /* Removes ALL list nodes */
/*FIXME optDelete((rc_opt_t **)&s_pBintab->pOptlist->pvData);FIXME*/
/* free(s_pBintab->pOptlist);*/ /* Deallocate option list */
/* free(s_pBintab);*/ /* Deallocate cliopt and */
/* s_pBintab = NULL;*/ /* clear its reference */
/* }
catch(Except)
rethrow;
*/
popt_freecontext(m_Optcon); /* Free the popt context */
for (i = 0; i < RC_NUMOPTS; i++) { /* Free the tuples themselves */
if (m_pszOptuples[i]) {
free(m_pszOptuples[i]);
m_pszOptuples[i] = NULL;
}
}
if (m_szRcfile) /* Free the rc file arg */
free(m_szRcfile);
if (m_pszSecs) /* Free the section name arg */
vectorDel(m_pszSecs);
/* FIXME BEGIN DEBUG */
for (i = 0; i < RC_NUMOPTS; i++)
if (m_pszOptuples[i])
TRACE("Problem! Destructor failed!\n");
/* FIXME END DEBUG */
return(RC_THROW(RC_OK));
}