PageRenderTime 39ms CodeModel.GetById 18ms app.highlight 16ms RepoModel.GetById 1ms app.codeStats 0ms

/contrib/ntp/sntp/libopts/environment.c

https://bitbucket.org/freebsd/freebsd-head/
C | 279 lines | 119 code | 31 blank | 129 comment | 42 complexity | 7df9362aa47840c22e00360d52c475d5 MD5 | raw file
  1
  2/*
  3 *  $Id: environment.c,v 4.13 2007/04/15 19:01:18 bkorb Exp $
  4 * Time-stamp:      "2007-04-15 11:50:35 bkorb"
  5 *
  6 *  This file contains all of the routines that must be linked into
  7 *  an executable to use the generated option processing.  The optional
  8 *  routines are in separately compiled modules so that they will not
  9 *  necessarily be linked in.
 10 */
 11
 12/*
 13 *  Automated Options copyright 1992-2007 Bruce Korb
 14 *
 15 *  Automated Options is free software.
 16 *  You may redistribute it and/or modify it under the terms of the
 17 *  GNU General Public License, as published by the Free Software
 18 *  Foundation; either version 2, or (at your option) any later version.
 19 *
 20 *  Automated Options is distributed in the hope that it will be useful,
 21 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 22 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 23 *  GNU General Public License for more details.
 24 *
 25 *  You should have received a copy of the GNU General Public License
 26 *  along with Automated Options.  See the file "COPYING".  If not,
 27 *  write to:  The Free Software Foundation, Inc.,
 28 *             51 Franklin Street, Fifth Floor,
 29 *             Boston, MA  02110-1301, USA.
 30 *
 31 * As a special exception, Bruce Korb gives permission for additional
 32 * uses of the text contained in his release of AutoOpts.
 33 *
 34 * The exception is that, if you link the AutoOpts library with other
 35 * files to produce an executable, this does not by itself cause the
 36 * resulting executable to be covered by the GNU General Public License.
 37 * Your use of that executable is in no way restricted on account of
 38 * linking the AutoOpts library code into it.
 39 *
 40 * This exception does not however invalidate any other reasons why
 41 * the executable file might be covered by the GNU General Public License.
 42 *
 43 * This exception applies only to the code released by Bruce Korb under
 44 * the name AutoOpts.  If you copy code from other sources under the
 45 * General Public License into a copy of AutoOpts, as the General Public
 46 * License permits, the exception does not apply to the code that you add
 47 * in this way.  To avoid misleading anyone as to the status of such
 48 * modified files, you must delete this exception notice from them.
 49 *
 50 * If you write modifications of your own for AutoOpts, it is your choice
 51 * whether to permit this exception to apply to your modifications.
 52 * If you do not wish that, delete this exception notice.
 53 */
 54
 55/* = = = START-STATIC-FORWARD = = = */
 56/* static forward declarations maintained by :mkfwd */
 57static void
 58checkEnvOpt(tOptState * os, char * env_name,
 59            tOptions* pOpts, teEnvPresetType type);
 60/* = = = END-STATIC-FORWARD = = = */
 61
 62/*
 63 *  doPrognameEnv - check for preset values from the ${PROGNAME}
 64 *  environment variable.  This is accomplished by parsing the text into
 65 *  tokens, temporarily replacing the arg vector and calling
 66 *  doImmediateOpts and/or doRegularOpts.
 67 */
 68LOCAL void
 69doPrognameEnv( tOptions* pOpts, teEnvPresetType type )
 70{
 71    char const*   pczOptStr = getenv( pOpts->pzPROGNAME );
 72    token_list_t* pTL;
 73    int           sv_argc;
 74    tAoUI         sv_flag;
 75    char**        sv_argv;
 76
 77    /*
 78     *  IF there is no such environment variable
 79     *   *or* there is, but we are doing immediate opts and there are
 80     *        no immediate opts to do (--help inside $PROGNAME is silly,
 81     *        but --no-load-defs is not, so that is marked)
 82     *  THEN bail out now.  (
 83     */
 84    if (  (pczOptStr == NULL)
 85       || (  (type == ENV_IMM)
 86          && ((pOpts->fOptSet & OPTPROC_HAS_IMMED) == 0)  )  )
 87        return;
 88
 89    /*
 90     *  Tokenize the string.  If there's nothing of interest, we'll bail
 91     *  here immediately.
 92     */
 93    pTL = ao_string_tokenize( pczOptStr );
 94    if (pTL == NULL)
 95        return;
 96
 97    /*
 98     *  Substitute our $PROGNAME argument list for the real one
 99     */
100    sv_argc = pOpts->origArgCt;
101    sv_argv = pOpts->origArgVect;
102    sv_flag = pOpts->fOptSet;
103
104    /*
105     *  We add a bogus pointer to the start of the list.  The program name
106     *  has already been pulled from "argv", so it won't get dereferenced.
107     *  The option scanning code will skip the "program name" at the start
108     *  of this list of tokens, so we accommodate this way ....
109     */
110    pOpts->origArgVect = (char**)(pTL->tkn_list - 1);
111    pOpts->origArgCt   = pTL->tkn_ct   + 1;
112    pOpts->fOptSet    &= ~OPTPROC_ERRSTOP;
113
114    pOpts->curOptIdx   = 1;
115    pOpts->pzCurOpt    = NULL;
116
117    switch (type) {
118    case ENV_IMM:
119        /*
120         *  We know the OPTPROC_HAS_IMMED bit is set.
121         */
122        (void)doImmediateOpts( pOpts );
123        break;
124
125    case ENV_NON_IMM:
126        (void)doRegularOpts( pOpts );
127        break;
128
129    default:
130        /*
131         *  Only to immediate opts if the OPTPROC_HAS_IMMED bit is set.
132         */
133        if (pOpts->fOptSet & OPTPROC_HAS_IMMED) {
134            (void)doImmediateOpts( pOpts );
135            pOpts->curOptIdx = 1;
136            pOpts->pzCurOpt  = NULL;
137        }
138        (void)doRegularOpts( pOpts );
139        break;
140    }
141
142    /*
143     *  Free up the temporary arg vector and restore the original program args.
144     */
145    free( pTL );
146    pOpts->origArgVect = sv_argv;
147    pOpts->origArgCt   = sv_argc;
148    pOpts->fOptSet     = sv_flag;
149}
150
151static void
152checkEnvOpt(tOptState * os, char * env_name,
153            tOptions* pOpts, teEnvPresetType type)
154{
155    os->pzOptArg = getenv( env_name );
156    if (os->pzOptArg == NULL)
157        return;
158
159    os->flags    = OPTST_PRESET | OPTST_ALLOC_ARG | os->pOD->fOptState;
160    os->optType  = TOPT_UNDEFINED;
161
162    if (  (os->pOD->pz_DisablePfx != NULL)
163       && (streqvcmp( os->pzOptArg, os->pOD->pz_DisablePfx ) == 0)) {
164        os->flags |= OPTST_DISABLED;
165        os->pzOptArg = NULL;
166    }
167
168    switch (type) {
169    case ENV_IMM:
170        /*
171         *  Process only immediate actions
172         */
173        if (DO_IMMEDIATELY(os->flags))
174            break;
175        return;
176
177    case ENV_NON_IMM:
178        /*
179         *  Process only NON immediate actions
180         */
181        if (DO_NORMALLY(os->flags) || DO_SECOND_TIME(os->flags))
182            break;
183        return;
184
185    default: /* process everything */
186        break;
187    }
188
189    /*
190     *  Make sure the option value string is persistent and consistent.
191     *
192     *  The interpretation of the option value depends
193     *  on the type of value argument the option takes
194     */
195    if (os->pzOptArg != NULL) {
196        if (OPTST_GET_ARGTYPE(os->pOD->fOptState) == OPARG_TYPE_NONE) {
197            os->pzOptArg = NULL;
198        } else if (  (os->pOD->fOptState & OPTST_ARG_OPTIONAL)
199                     && (*os->pzOptArg == NUL)) {
200            os->pzOptArg = NULL;
201        } else if (*os->pzOptArg == NUL) {
202            os->pzOptArg = zNil;
203        } else {
204            AGDUPSTR( os->pzOptArg, os->pzOptArg, "option argument" );
205            os->flags |= OPTST_ALLOC_ARG;
206        }
207    }
208
209    handleOption( pOpts, os );
210}
211
212/*
213 *  doEnvPresets - check for preset values from the envrionment
214 *  This routine should process in all, immediate or normal modes....
215 */
216LOCAL void
217doEnvPresets( tOptions* pOpts, teEnvPresetType type )
218{
219    int        ct;
220    tOptState  st;
221    char*      pzFlagName;
222    size_t     spaceLeft;
223    char       zEnvName[ AO_NAME_SIZE ];
224
225    /*
226     *  Finally, see if we are to look at the environment
227     *  variables for initial values.
228     */
229    if ((pOpts->fOptSet & OPTPROC_ENVIRON) == 0)
230        return;
231
232    doPrognameEnv( pOpts, type );
233
234    ct  = pOpts->presetOptCt;
235    st.pOD = pOpts->pOptDesc;
236
237    pzFlagName = zEnvName
238        + snprintf( zEnvName, sizeof( zEnvName ), "%s_", pOpts->pzPROGNAME );
239    spaceLeft = AO_NAME_SIZE - (pzFlagName - zEnvName) - 1;
240
241    for (;ct-- > 0; st.pOD++) {
242        /*
243         *  If presetting is disallowed, then skip this entry
244         */
245        if (  ((st.pOD->fOptState & OPTST_NO_INIT) != 0)
246           || (st.pOD->optEquivIndex != NO_EQUIVALENT)  )
247            continue;
248
249        /*
250         *  IF there is no such environment variable,
251         *  THEN skip this entry, too.
252         */
253        if (strlen( st.pOD->pz_NAME ) >= spaceLeft)
254            continue;
255
256        /*
257         *  Set up the option state
258         */
259        strcpy( pzFlagName, st.pOD->pz_NAME );
260        checkEnvOpt(&st, zEnvName, pOpts, type);
261    }
262
263    /*
264     *  Special handling for ${PROGNAME_LOAD_OPTS}
265     */
266    if (pOpts->specOptIdx.save_opts != 0) {
267        st.pOD = pOpts->pOptDesc + pOpts->specOptIdx.save_opts + 1;
268        strcpy( pzFlagName, st.pOD->pz_NAME );
269        checkEnvOpt(&st, zEnvName, pOpts, type);
270    }
271}
272
273/*
274 * Local Variables:
275 * mode: C
276 * c-file-style: "stroustrup"
277 * indent-tabs-mode: nil
278 * End:
279 * end of autoopts/environment.c */