12b15cb3dSCy Schubert
22b15cb3dSCy Schubert /**
32b15cb3dSCy Schubert * \file environment.c
42b15cb3dSCy Schubert *
52b15cb3dSCy Schubert * This file contains all of the routines that must be linked into
62b15cb3dSCy Schubert * an executable to use the generated option processing. The optional
72b15cb3dSCy Schubert * routines are in separately compiled modules so that they will not
82b15cb3dSCy Schubert * necessarily be linked in.
92b15cb3dSCy Schubert *
102b15cb3dSCy Schubert * @addtogroup autoopts
112b15cb3dSCy Schubert * @{
122b15cb3dSCy Schubert */
132b15cb3dSCy Schubert /*
142b15cb3dSCy Schubert * This file is part of AutoOpts, a companion to AutoGen.
152b15cb3dSCy Schubert * AutoOpts is free software.
16*a466cc55SCy Schubert * AutoOpts is Copyright (C) 1992-2018 by Bruce Korb - all rights reserved
172b15cb3dSCy Schubert *
182b15cb3dSCy Schubert * AutoOpts is available under any one of two licenses. The license
192b15cb3dSCy Schubert * in use must be one of these two and the choice is under the control
202b15cb3dSCy Schubert * of the user of the license.
212b15cb3dSCy Schubert *
222b15cb3dSCy Schubert * The GNU Lesser General Public License, version 3 or later
232b15cb3dSCy Schubert * See the files "COPYING.lgplv3" and "COPYING.gplv3"
242b15cb3dSCy Schubert *
252b15cb3dSCy Schubert * The Modified Berkeley Software Distribution License
262b15cb3dSCy Schubert * See the file "COPYING.mbsd"
272b15cb3dSCy Schubert *
282b15cb3dSCy Schubert * These files have the following sha256 sums:
292b15cb3dSCy Schubert *
302b15cb3dSCy Schubert * 8584710e9b04216a394078dc156b781d0b47e1729104d666658aecef8ee32e95 COPYING.gplv3
312b15cb3dSCy Schubert * 4379e7444a0e2ce2b12dd6f5a52a27a4d02d39d247901d3285c88cf0d37f477b COPYING.lgplv3
322b15cb3dSCy Schubert * 13aa749a5b0a454917a944ed8fffc530b784f5ead522b1aacaf4ec8aa55a6239 COPYING.mbsd
332b15cb3dSCy Schubert */
342b15cb3dSCy Schubert
352b15cb3dSCy Schubert /*
362b15cb3dSCy Schubert * doPrognameEnv - check for preset values from the ${PROGNAME}
372b15cb3dSCy Schubert * environment variable. This is accomplished by parsing the text into
382b15cb3dSCy Schubert * tokens, temporarily replacing the arg vector and calling
392b15cb3dSCy Schubert * immediate_opts and/or regular_opts.
402b15cb3dSCy Schubert */
41*a466cc55SCy Schubert static void
doPrognameEnv(tOptions * pOpts,teEnvPresetType type)422b15cb3dSCy Schubert doPrognameEnv(tOptions * pOpts, teEnvPresetType type)
432b15cb3dSCy Schubert {
442b15cb3dSCy Schubert char const * env_opts = getenv(pOpts->pzPROGNAME);
452b15cb3dSCy Schubert token_list_t * pTL;
462b15cb3dSCy Schubert int sv_argc;
472b15cb3dSCy Schubert proc_state_mask_t sv_flag;
482b15cb3dSCy Schubert char ** sv_argv;
492b15cb3dSCy Schubert
502b15cb3dSCy Schubert /*
512b15cb3dSCy Schubert * No such beast? Then bail now.
522b15cb3dSCy Schubert */
532b15cb3dSCy Schubert if (env_opts == NULL)
542b15cb3dSCy Schubert return;
552b15cb3dSCy Schubert
562b15cb3dSCy Schubert /*
572b15cb3dSCy Schubert * Tokenize the string. If there's nothing of interest, we'll bail
582b15cb3dSCy Schubert * here immediately.
592b15cb3dSCy Schubert */
602b15cb3dSCy Schubert pTL = ao_string_tokenize(env_opts);
612b15cb3dSCy Schubert if (pTL == NULL)
622b15cb3dSCy Schubert return;
632b15cb3dSCy Schubert
642b15cb3dSCy Schubert /*
652b15cb3dSCy Schubert * Substitute our $PROGNAME argument list for the real one
662b15cb3dSCy Schubert */
672b15cb3dSCy Schubert sv_argc = (int)pOpts->origArgCt;
682b15cb3dSCy Schubert sv_argv = pOpts->origArgVect;
692b15cb3dSCy Schubert sv_flag = pOpts->fOptSet;
702b15cb3dSCy Schubert
712b15cb3dSCy Schubert /*
722b15cb3dSCy Schubert * We add a bogus pointer to the start of the list. The program name
732b15cb3dSCy Schubert * has already been pulled from "argv", so it won't get dereferenced.
742b15cb3dSCy Schubert * The option scanning code will skip the "program name" at the start
752b15cb3dSCy Schubert * of this list of tokens, so we accommodate this way ....
762b15cb3dSCy Schubert */
772b15cb3dSCy Schubert {
782b15cb3dSCy Schubert uintptr_t v = (uintptr_t)(pTL->tkn_list);
79276da39aSCy Schubert pOpts->origArgVect = VOIDP(v - sizeof(char *));
802b15cb3dSCy Schubert }
812b15cb3dSCy Schubert pOpts->origArgCt = (unsigned int)pTL->tkn_ct + 1;
822b15cb3dSCy Schubert pOpts->fOptSet &= ~OPTPROC_ERRSTOP;
832b15cb3dSCy Schubert
842b15cb3dSCy Schubert pOpts->curOptIdx = 1;
852b15cb3dSCy Schubert pOpts->pzCurOpt = NULL;
862b15cb3dSCy Schubert
872b15cb3dSCy Schubert switch (type) {
882b15cb3dSCy Schubert case ENV_IMM:
892b15cb3dSCy Schubert (void)immediate_opts(pOpts);
902b15cb3dSCy Schubert break;
912b15cb3dSCy Schubert
922b15cb3dSCy Schubert case ENV_ALL:
932b15cb3dSCy Schubert (void)immediate_opts(pOpts);
942b15cb3dSCy Schubert pOpts->curOptIdx = 1;
952b15cb3dSCy Schubert pOpts->pzCurOpt = NULL;
962b15cb3dSCy Schubert /* FALLTHROUGH */
972b15cb3dSCy Schubert
982b15cb3dSCy Schubert case ENV_NON_IMM:
992b15cb3dSCy Schubert (void)regular_opts(pOpts);
1002b15cb3dSCy Schubert }
1012b15cb3dSCy Schubert
1022b15cb3dSCy Schubert /*
1032b15cb3dSCy Schubert * Free up the temporary arg vector and restore the original program args.
1042b15cb3dSCy Schubert */
1052b15cb3dSCy Schubert free(pTL);
1062b15cb3dSCy Schubert pOpts->origArgVect = sv_argv;
1072b15cb3dSCy Schubert pOpts->origArgCt = (unsigned int)sv_argc;
1082b15cb3dSCy Schubert pOpts->fOptSet = sv_flag;
1092b15cb3dSCy Schubert }
1102b15cb3dSCy Schubert
1112b15cb3dSCy Schubert static void
do_env_opt(tOptState * os,char * env_name,tOptions * pOpts,teEnvPresetType type)1122b15cb3dSCy Schubert do_env_opt(tOptState * os, char * env_name,
1132b15cb3dSCy Schubert tOptions * pOpts, teEnvPresetType type)
1142b15cb3dSCy Schubert {
1152b15cb3dSCy Schubert os->pzOptArg = getenv(env_name);
1162b15cb3dSCy Schubert if (os->pzOptArg == NULL)
1172b15cb3dSCy Schubert return;
1182b15cb3dSCy Schubert
1192b15cb3dSCy Schubert os->flags = OPTST_PRESET | OPTST_ALLOC_ARG | os->pOD->fOptState;
1202b15cb3dSCy Schubert os->optType = TOPT_UNDEFINED;
1212b15cb3dSCy Schubert
1222b15cb3dSCy Schubert if ( (os->pOD->pz_DisablePfx != NULL)
1232b15cb3dSCy Schubert && (streqvcmp(os->pzOptArg, os->pOD->pz_DisablePfx) == 0)) {
1242b15cb3dSCy Schubert os->flags |= OPTST_DISABLED;
1252b15cb3dSCy Schubert os->pzOptArg = NULL;
1262b15cb3dSCy Schubert handle_opt(pOpts, os);
1272b15cb3dSCy Schubert return;
1282b15cb3dSCy Schubert }
1292b15cb3dSCy Schubert
1302b15cb3dSCy Schubert switch (type) {
1312b15cb3dSCy Schubert case ENV_IMM:
1322b15cb3dSCy Schubert /*
1332b15cb3dSCy Schubert * Process only immediate actions
1342b15cb3dSCy Schubert */
1352b15cb3dSCy Schubert if (DO_IMMEDIATELY(os->flags))
1362b15cb3dSCy Schubert break;
1372b15cb3dSCy Schubert return;
1382b15cb3dSCy Schubert
1392b15cb3dSCy Schubert case ENV_NON_IMM:
1402b15cb3dSCy Schubert /*
1412b15cb3dSCy Schubert * Process only NON immediate actions
1422b15cb3dSCy Schubert */
1432b15cb3dSCy Schubert if (DO_NORMALLY(os->flags) || DO_SECOND_TIME(os->flags))
1442b15cb3dSCy Schubert break;
1452b15cb3dSCy Schubert return;
1462b15cb3dSCy Schubert
1472b15cb3dSCy Schubert default: /* process everything */
1482b15cb3dSCy Schubert break;
1492b15cb3dSCy Schubert }
1502b15cb3dSCy Schubert
1512b15cb3dSCy Schubert /*
1522b15cb3dSCy Schubert * Make sure the option value string is persistent and consistent.
1532b15cb3dSCy Schubert *
1542b15cb3dSCy Schubert * The interpretation of the option value depends
1552b15cb3dSCy Schubert * on the type of value argument the option takes
1562b15cb3dSCy Schubert */
1572b15cb3dSCy Schubert if (OPTST_GET_ARGTYPE(os->pOD->fOptState) == OPARG_TYPE_NONE) {
1582b15cb3dSCy Schubert /*
1592b15cb3dSCy Schubert * Ignore any value.
1602b15cb3dSCy Schubert */
1612b15cb3dSCy Schubert os->pzOptArg = NULL;
1622b15cb3dSCy Schubert
1632b15cb3dSCy Schubert } else if (os->pzOptArg[0] == NUL) {
1642b15cb3dSCy Schubert /*
1652b15cb3dSCy Schubert * If the argument is the empty string and the argument is
1662b15cb3dSCy Schubert * optional, then treat it as if the option was not specified.
1672b15cb3dSCy Schubert */
1682b15cb3dSCy Schubert if ((os->pOD->fOptState & OPTST_ARG_OPTIONAL) == 0)
1692b15cb3dSCy Schubert return;
1702b15cb3dSCy Schubert os->pzOptArg = NULL;
1712b15cb3dSCy Schubert
1722b15cb3dSCy Schubert } else {
1732b15cb3dSCy Schubert AGDUPSTR(os->pzOptArg, os->pzOptArg, "option argument");
1742b15cb3dSCy Schubert os->flags |= OPTST_ALLOC_ARG;
1752b15cb3dSCy Schubert }
1762b15cb3dSCy Schubert
1772b15cb3dSCy Schubert handle_opt(pOpts, os);
1782b15cb3dSCy Schubert }
1792b15cb3dSCy Schubert
1802b15cb3dSCy Schubert /*
1812b15cb3dSCy Schubert * env_presets - check for preset values from the envrionment
1822b15cb3dSCy Schubert * This routine should process in all, immediate or normal modes....
1832b15cb3dSCy Schubert */
184*a466cc55SCy Schubert static void
env_presets(tOptions * pOpts,teEnvPresetType type)1852b15cb3dSCy Schubert env_presets(tOptions * pOpts, teEnvPresetType type)
1862b15cb3dSCy Schubert {
1872b15cb3dSCy Schubert int ct;
1882b15cb3dSCy Schubert tOptState st;
1892b15cb3dSCy Schubert char * pzFlagName;
1902b15cb3dSCy Schubert size_t spaceLeft;
1912b15cb3dSCy Schubert char zEnvName[ AO_NAME_SIZE ];
1922b15cb3dSCy Schubert
1932b15cb3dSCy Schubert /*
1942b15cb3dSCy Schubert * Finally, see if we are to look at the environment
1952b15cb3dSCy Schubert * variables for initial values.
1962b15cb3dSCy Schubert */
1972b15cb3dSCy Schubert if ((pOpts->fOptSet & OPTPROC_ENVIRON) == 0)
1982b15cb3dSCy Schubert return;
1992b15cb3dSCy Schubert
2002b15cb3dSCy Schubert doPrognameEnv(pOpts, type);
2012b15cb3dSCy Schubert
2022b15cb3dSCy Schubert ct = pOpts->presetOptCt;
2032b15cb3dSCy Schubert st.pOD = pOpts->pOptDesc;
2042b15cb3dSCy Schubert
2052b15cb3dSCy Schubert pzFlagName = zEnvName
2062b15cb3dSCy Schubert + snprintf(zEnvName, sizeof(zEnvName), "%s_", pOpts->pzPROGNAME);
2072b15cb3dSCy Schubert spaceLeft = AO_NAME_SIZE - (unsigned long)(pzFlagName - zEnvName) - 1;
2082b15cb3dSCy Schubert
2092b15cb3dSCy Schubert for (;ct-- > 0; st.pOD++) {
2102b15cb3dSCy Schubert size_t nln;
2112b15cb3dSCy Schubert
2122b15cb3dSCy Schubert /*
2132b15cb3dSCy Schubert * If presetting is disallowed, then skip this entry
2142b15cb3dSCy Schubert */
2152b15cb3dSCy Schubert if ( ((st.pOD->fOptState & OPTST_NO_INIT) != 0)
2162b15cb3dSCy Schubert || (st.pOD->optEquivIndex != NO_EQUIVALENT) )
2172b15cb3dSCy Schubert continue;
2182b15cb3dSCy Schubert
2192b15cb3dSCy Schubert /*
2202b15cb3dSCy Schubert * IF there is no such environment variable,
2212b15cb3dSCy Schubert * THEN skip this entry, too.
2222b15cb3dSCy Schubert */
2232b15cb3dSCy Schubert nln = strlen(st.pOD->pz_NAME) + 1;
2242b15cb3dSCy Schubert if (nln <= spaceLeft) {
2252b15cb3dSCy Schubert /*
2262b15cb3dSCy Schubert * Set up the option state
2272b15cb3dSCy Schubert */
2282b15cb3dSCy Schubert memcpy(pzFlagName, st.pOD->pz_NAME, nln);
2292b15cb3dSCy Schubert do_env_opt(&st, zEnvName, pOpts, type);
2302b15cb3dSCy Schubert }
2312b15cb3dSCy Schubert }
2322b15cb3dSCy Schubert
2332b15cb3dSCy Schubert /*
2342b15cb3dSCy Schubert * Special handling for ${PROGNAME_LOAD_OPTS}
2352b15cb3dSCy Schubert */
2362b15cb3dSCy Schubert if ( (pOpts->specOptIdx.save_opts != NO_EQUIVALENT)
2372b15cb3dSCy Schubert && (pOpts->specOptIdx.save_opts != 0)) {
2382b15cb3dSCy Schubert size_t nln;
2392b15cb3dSCy Schubert st.pOD = pOpts->pOptDesc + pOpts->specOptIdx.save_opts + 1;
2402b15cb3dSCy Schubert
2412b15cb3dSCy Schubert if (st.pOD->pz_NAME == NULL)
2422b15cb3dSCy Schubert return;
2432b15cb3dSCy Schubert
2442b15cb3dSCy Schubert nln = strlen(st.pOD->pz_NAME) + 1;
2452b15cb3dSCy Schubert
2462b15cb3dSCy Schubert if (nln > spaceLeft)
2472b15cb3dSCy Schubert return;
2482b15cb3dSCy Schubert
2492b15cb3dSCy Schubert memcpy(pzFlagName, st.pOD->pz_NAME, nln);
2502b15cb3dSCy Schubert do_env_opt(&st, zEnvName, pOpts, type);
2512b15cb3dSCy Schubert }
2522b15cb3dSCy Schubert }
2532b15cb3dSCy Schubert
2542b15cb3dSCy Schubert /** @}
2552b15cb3dSCy Schubert *
2562b15cb3dSCy Schubert * Local Variables:
2572b15cb3dSCy Schubert * mode: C
2582b15cb3dSCy Schubert * c-file-style: "stroustrup"
2592b15cb3dSCy Schubert * indent-tabs-mode: nil
2602b15cb3dSCy Schubert * End:
2612b15cb3dSCy Schubert * end of autoopts/environment.c */
262