xref: /freebsd-src/contrib/ntp/sntp/libopts/env.c (revision a466cc55373fc3cf86837f09da729535b57e69a1)
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