xref: /netbsd-src/external/bsd/ntp/dist/sntp/libopts/env.c (revision eabc0478de71e4e011a5b4e0392741e01d491794)
1*eabc0478Schristos /*	$NetBSD: env.c,v 1.6 2024/08/18 20:47:24 christos Exp $	*/
28585484eSchristos 
38585484eSchristos 
48585484eSchristos /**
58585484eSchristos  * \file environment.c
68585484eSchristos  *
78585484eSchristos  *  This file contains all of the routines that must be linked into
88585484eSchristos  *  an executable to use the generated option processing.  The optional
98585484eSchristos  *  routines are in separately compiled modules so that they will not
108585484eSchristos  *  necessarily be linked in.
118585484eSchristos  *
128585484eSchristos  * @addtogroup autoopts
138585484eSchristos  * @{
148585484eSchristos  */
158585484eSchristos /*
168585484eSchristos  *  This file is part of AutoOpts, a companion to AutoGen.
178585484eSchristos  *  AutoOpts is free software.
18*eabc0478Schristos  *  AutoOpts is Copyright (C) 1992-2018 by Bruce Korb - all rights reserved
198585484eSchristos  *
208585484eSchristos  *  AutoOpts is available under any one of two licenses.  The license
218585484eSchristos  *  in use must be one of these two and the choice is under the control
228585484eSchristos  *  of the user of the license.
238585484eSchristos  *
248585484eSchristos  *   The GNU Lesser General Public License, version 3 or later
258585484eSchristos  *      See the files "COPYING.lgplv3" and "COPYING.gplv3"
268585484eSchristos  *
278585484eSchristos  *   The Modified Berkeley Software Distribution License
288585484eSchristos  *      See the file "COPYING.mbsd"
298585484eSchristos  *
308585484eSchristos  *  These files have the following sha256 sums:
318585484eSchristos  *
328585484eSchristos  *  8584710e9b04216a394078dc156b781d0b47e1729104d666658aecef8ee32e95  COPYING.gplv3
338585484eSchristos  *  4379e7444a0e2ce2b12dd6f5a52a27a4d02d39d247901d3285c88cf0d37f477b  COPYING.lgplv3
348585484eSchristos  *  13aa749a5b0a454917a944ed8fffc530b784f5ead522b1aacaf4ec8aa55a6239  COPYING.mbsd
358585484eSchristos  */
368585484eSchristos 
378585484eSchristos /*
388585484eSchristos  *  doPrognameEnv - check for preset values from the ${PROGNAME}
398585484eSchristos  *  environment variable.  This is accomplished by parsing the text into
408585484eSchristos  *  tokens, temporarily replacing the arg vector and calling
418585484eSchristos  *  immediate_opts and/or regular_opts.
428585484eSchristos  */
43*eabc0478Schristos static void
448585484eSchristos doPrognameEnv(tOptions * pOpts, teEnvPresetType type)
458585484eSchristos {
468585484eSchristos     char const *        env_opts = getenv(pOpts->pzPROGNAME);
478585484eSchristos     token_list_t *      pTL;
488585484eSchristos     int                 sv_argc;
498585484eSchristos     proc_state_mask_t   sv_flag;
508585484eSchristos     char **             sv_argv;
518585484eSchristos 
528585484eSchristos     /*
538585484eSchristos      *  No such beast?  Then bail now.
548585484eSchristos      */
558585484eSchristos     if (env_opts == NULL)
568585484eSchristos         return;
578585484eSchristos 
588585484eSchristos     /*
598585484eSchristos      *  Tokenize the string.  If there's nothing of interest, we'll bail
608585484eSchristos      *  here immediately.
618585484eSchristos      */
628585484eSchristos     pTL = ao_string_tokenize(env_opts);
638585484eSchristos     if (pTL == NULL)
648585484eSchristos         return;
658585484eSchristos 
668585484eSchristos     /*
678585484eSchristos      *  Substitute our $PROGNAME argument list for the real one
688585484eSchristos      */
698585484eSchristos     sv_argc = (int)pOpts->origArgCt;
708585484eSchristos     sv_argv = pOpts->origArgVect;
718585484eSchristos     sv_flag = pOpts->fOptSet;
728585484eSchristos 
738585484eSchristos     /*
748585484eSchristos      *  We add a bogus pointer to the start of the list.  The program name
758585484eSchristos      *  has already been pulled from "argv", so it won't get dereferenced.
768585484eSchristos      *  The option scanning code will skip the "program name" at the start
778585484eSchristos      *  of this list of tokens, so we accommodate this way ....
788585484eSchristos      */
798585484eSchristos     {
808585484eSchristos         uintptr_t v = (uintptr_t)(pTL->tkn_list);
815d681e99Schristos         pOpts->origArgVect = VOIDP(v - sizeof(char *));
828585484eSchristos     }
838585484eSchristos     pOpts->origArgCt   = (unsigned int)pTL->tkn_ct   + 1;
848585484eSchristos     pOpts->fOptSet    &= ~OPTPROC_ERRSTOP;
858585484eSchristos 
868585484eSchristos     pOpts->curOptIdx   = 1;
878585484eSchristos     pOpts->pzCurOpt    = NULL;
888585484eSchristos 
898585484eSchristos     switch (type) {
908585484eSchristos     case ENV_IMM:
918585484eSchristos         (void)immediate_opts(pOpts);
928585484eSchristos         break;
938585484eSchristos 
948585484eSchristos     case ENV_ALL:
958585484eSchristos         (void)immediate_opts(pOpts);
968585484eSchristos         pOpts->curOptIdx = 1;
978585484eSchristos         pOpts->pzCurOpt  = NULL;
988585484eSchristos         /* FALLTHROUGH */
998585484eSchristos 
1008585484eSchristos     case ENV_NON_IMM:
1018585484eSchristos         (void)regular_opts(pOpts);
1028585484eSchristos     }
1038585484eSchristos 
1048585484eSchristos     /*
1058585484eSchristos      *  Free up the temporary arg vector and restore the original program args.
1068585484eSchristos      */
1078585484eSchristos     free(pTL);
1088585484eSchristos     pOpts->origArgVect = sv_argv;
1098585484eSchristos     pOpts->origArgCt   = (unsigned int)sv_argc;
1108585484eSchristos     pOpts->fOptSet     = sv_flag;
1118585484eSchristos }
1128585484eSchristos 
1138585484eSchristos static void
1148585484eSchristos do_env_opt(tOptState * os, char * env_name,
1158585484eSchristos             tOptions * pOpts, teEnvPresetType type)
1168585484eSchristos {
1178585484eSchristos     os->pzOptArg = getenv(env_name);
1188585484eSchristos     if (os->pzOptArg == NULL)
1198585484eSchristos         return;
1208585484eSchristos 
1218585484eSchristos     os->flags   = OPTST_PRESET | OPTST_ALLOC_ARG | os->pOD->fOptState;
1228585484eSchristos     os->optType = TOPT_UNDEFINED;
1238585484eSchristos 
1248585484eSchristos     if (  (os->pOD->pz_DisablePfx != NULL)
1258585484eSchristos        && (streqvcmp(os->pzOptArg, os->pOD->pz_DisablePfx) == 0)) {
1268585484eSchristos         os->flags |= OPTST_DISABLED;
1278585484eSchristos         os->pzOptArg = NULL;
1288585484eSchristos         handle_opt(pOpts, os);
1298585484eSchristos         return;
1308585484eSchristos     }
1318585484eSchristos 
1328585484eSchristos     switch (type) {
1338585484eSchristos     case ENV_IMM:
1348585484eSchristos         /*
1358585484eSchristos          *  Process only immediate actions
1368585484eSchristos          */
1378585484eSchristos         if (DO_IMMEDIATELY(os->flags))
1388585484eSchristos             break;
1398585484eSchristos         return;
1408585484eSchristos 
1418585484eSchristos     case ENV_NON_IMM:
1428585484eSchristos         /*
1438585484eSchristos          *  Process only NON immediate actions
1448585484eSchristos          */
1458585484eSchristos         if (DO_NORMALLY(os->flags) || DO_SECOND_TIME(os->flags))
1468585484eSchristos             break;
1478585484eSchristos         return;
1488585484eSchristos 
1498585484eSchristos     default: /* process everything */
1508585484eSchristos         break;
1518585484eSchristos     }
1528585484eSchristos 
1538585484eSchristos     /*
1548585484eSchristos      *  Make sure the option value string is persistent and consistent.
1558585484eSchristos      *
1568585484eSchristos      *  The interpretation of the option value depends
1578585484eSchristos      *  on the type of value argument the option takes
1588585484eSchristos      */
1598585484eSchristos     if (OPTST_GET_ARGTYPE(os->pOD->fOptState) == OPARG_TYPE_NONE) {
1608585484eSchristos         /*
1618585484eSchristos          *  Ignore any value.
1628585484eSchristos          */
1638585484eSchristos         os->pzOptArg = NULL;
1648585484eSchristos 
1658585484eSchristos     } else if (os->pzOptArg[0] == NUL) {
1668585484eSchristos         /*
1678585484eSchristos          * If the argument is the empty string and the argument is
1688585484eSchristos          * optional, then treat it as if the option was not specified.
1698585484eSchristos          */
1708585484eSchristos         if ((os->pOD->fOptState & OPTST_ARG_OPTIONAL) == 0)
1718585484eSchristos             return;
1728585484eSchristos         os->pzOptArg = NULL;
1738585484eSchristos 
1748585484eSchristos     } else {
1758585484eSchristos         AGDUPSTR(os->pzOptArg, os->pzOptArg, "option argument");
1768585484eSchristos         os->flags |= OPTST_ALLOC_ARG;
1778585484eSchristos     }
1788585484eSchristos 
1798585484eSchristos     handle_opt(pOpts, os);
1808585484eSchristos }
1818585484eSchristos 
1828585484eSchristos /*
1838585484eSchristos  *  env_presets - check for preset values from the envrionment
1848585484eSchristos  *  This routine should process in all, immediate or normal modes....
1858585484eSchristos  */
186*eabc0478Schristos static void
1878585484eSchristos env_presets(tOptions * pOpts, teEnvPresetType type)
1888585484eSchristos {
1898585484eSchristos     int        ct;
1908585484eSchristos     tOptState  st;
1918585484eSchristos     char *     pzFlagName;
1928585484eSchristos     size_t     spaceLeft;
1938585484eSchristos     char       zEnvName[ AO_NAME_SIZE ];
1948585484eSchristos 
1958585484eSchristos     /*
1968585484eSchristos      *  Finally, see if we are to look at the environment
1978585484eSchristos      *  variables for initial values.
1988585484eSchristos      */
1998585484eSchristos     if ((pOpts->fOptSet & OPTPROC_ENVIRON) == 0)
2008585484eSchristos         return;
2018585484eSchristos 
2028585484eSchristos     doPrognameEnv(pOpts, type);
2038585484eSchristos 
2048585484eSchristos     ct  = pOpts->presetOptCt;
2058585484eSchristos     st.pOD = pOpts->pOptDesc;
2068585484eSchristos 
2078585484eSchristos     pzFlagName = zEnvName
2088585484eSchristos         + snprintf(zEnvName, sizeof(zEnvName), "%s_", pOpts->pzPROGNAME);
2098585484eSchristos     spaceLeft = AO_NAME_SIZE - (unsigned long)(pzFlagName - zEnvName) - 1;
2108585484eSchristos 
2118585484eSchristos     for (;ct-- > 0; st.pOD++) {
2128585484eSchristos         size_t nln;
2138585484eSchristos 
2148585484eSchristos         /*
2158585484eSchristos          *  If presetting is disallowed, then skip this entry
2168585484eSchristos          */
2178585484eSchristos         if (  ((st.pOD->fOptState & OPTST_NO_INIT) != 0)
2188585484eSchristos            || (st.pOD->optEquivIndex != NO_EQUIVALENT)  )
2198585484eSchristos             continue;
2208585484eSchristos 
2218585484eSchristos         /*
2228585484eSchristos          *  IF there is no such environment variable,
2238585484eSchristos          *  THEN skip this entry, too.
2248585484eSchristos          */
2258585484eSchristos         nln = strlen(st.pOD->pz_NAME) + 1;
2268585484eSchristos         if (nln <= spaceLeft) {
2278585484eSchristos             /*
2288585484eSchristos              *  Set up the option state
2298585484eSchristos              */
2308585484eSchristos             memcpy(pzFlagName, st.pOD->pz_NAME, nln);
2318585484eSchristos             do_env_opt(&st, zEnvName, pOpts, type);
2328585484eSchristos         }
2338585484eSchristos     }
2348585484eSchristos 
2358585484eSchristos     /*
2368585484eSchristos      *  Special handling for ${PROGNAME_LOAD_OPTS}
2378585484eSchristos      */
2388585484eSchristos     if (  (pOpts->specOptIdx.save_opts != NO_EQUIVALENT)
2398585484eSchristos        && (pOpts->specOptIdx.save_opts != 0)) {
2408585484eSchristos         size_t nln;
2418585484eSchristos         st.pOD = pOpts->pOptDesc + pOpts->specOptIdx.save_opts + 1;
2428585484eSchristos 
2438585484eSchristos         if (st.pOD->pz_NAME == NULL)
2448585484eSchristos             return;
2458585484eSchristos 
2468585484eSchristos         nln = strlen(st.pOD->pz_NAME) + 1;
2478585484eSchristos 
2488585484eSchristos         if (nln > spaceLeft)
2498585484eSchristos             return;
2508585484eSchristos 
2518585484eSchristos         memcpy(pzFlagName, st.pOD->pz_NAME, nln);
2528585484eSchristos         do_env_opt(&st, zEnvName, pOpts, type);
2538585484eSchristos     }
2548585484eSchristos }
2558585484eSchristos 
2568585484eSchristos /** @}
2578585484eSchristos  *
2588585484eSchristos  * Local Variables:
2598585484eSchristos  * mode: C
2608585484eSchristos  * c-file-style: "stroustrup"
2618585484eSchristos  * indent-tabs-mode: nil
2628585484eSchristos  * End:
2638585484eSchristos  * end of autoopts/environment.c */
264