~ubuntu-branches/debian/squeeze/ntp/squeeze-201010051545

« back to all changes in this revision

Viewing changes to libopts/autoopts.c

  • Committer: Bazaar Package Importer
  • Author(s): Kurt Roeckx
  • Date: 2009-01-05 21:10:03 UTC
  • mfrom: (1.2.4 upstream)
  • Revision ID: james.westby@ubuntu.com-20090105211003-mh6zc3um4k1uhsj7
Tags: 1:4.2.4p4+dfsg-8
It did not properly check the return value of EVP_VerifyFinal
which results in an malformed DSA signature being treated as
a good signature rather than as an error.  (CVE-2009-0021)

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
 
 
2
/*
 
3
 *  $Id: autoopts.c,v 4.25 2007/04/15 19:01:18 bkorb Exp $
 
4
 *  Time-stamp:      "2007-04-15 11:10:40 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
static char const zNil[] = "";
 
56
 
 
57
/* = = = START-STATIC-FORWARD = = = */
 
58
/* static forward declarations maintained by :mkfwd */
 
59
static tSuccess
 
60
findOptDesc( tOptions* pOpts, tOptState* pOptState );
 
61
 
 
62
static tSuccess
 
63
nextOption( tOptions* pOpts, tOptState* pOptState );
 
64
 
 
65
static tSuccess
 
66
doPresets( tOptions* pOpts );
 
67
 
 
68
static int
 
69
checkConsistency( tOptions* pOpts );
 
70
/* = = = END-STATIC-FORWARD = = = */
 
71
 
 
72
LOCAL void *
 
73
ao_malloc( size_t sz )
 
74
{
 
75
    void * res = malloc(sz);
 
76
    if (res == NULL) {
 
77
        fprintf( stderr, "malloc of %d bytes failed\n", (int)sz );
 
78
        exit( EXIT_FAILURE );
 
79
    }
 
80
    return res;
 
81
}
 
82
#undef  malloc
 
83
#define malloc(_s) ao_malloc(_s)
 
84
 
 
85
LOCAL void *
 
86
ao_realloc( void *p, size_t sz )
 
87
{
 
88
    void * res = realloc(p, sz);
 
89
    if (res == NULL) {
 
90
        fprintf( stderr, "realloc of %d bytes at 0x%p failed\n", (int)sz, p );
 
91
        exit( EXIT_FAILURE );
 
92
    }
 
93
    return res;
 
94
}
 
95
#undef  realloc
 
96
#define realloc(_p,_s) ao_realloc(_p,_s)
 
97
 
 
98
 
 
99
LOCAL void
 
100
ao_free( void *p )
 
101
{
 
102
    if (p != NULL)
 
103
        free(p);
 
104
}
 
105
#undef  free
 
106
#define free(_p) ao_free(_p)
 
107
 
 
108
 
 
109
LOCAL char *
 
110
ao_strdup( char const *str )
 
111
{
 
112
    char * res = strdup(str);
 
113
    if (res == NULL) {
 
114
        fprintf( stderr, "strdup of %d byte string failed\n", (int)strlen(str) );
 
115
        exit( EXIT_FAILURE );
 
116
    }
 
117
    return res;
 
118
}
 
119
#undef  strdup
 
120
#define strdup(_p) ao_strdup(_p)
 
121
 
 
122
#ifndef HAVE_PATHFIND
 
123
#  include "compat/pathfind.c"
 
124
#endif
 
125
 
 
126
#ifndef HAVE_SNPRINTF
 
127
#  include "compat/snprintf.c"
 
128
#endif
 
129
 
 
130
#ifndef HAVE_STRDUP
 
131
#  include "compat/strdup.c"
 
132
#endif
 
133
 
 
134
#ifndef HAVE_STRCHR
 
135
#  include "compat/strchr.c"
 
136
#endif
 
137
 
 
138
/*
 
139
 *  handleOption
 
140
 *
 
141
 *  This routine handles equivalencing, sets the option state flags and
 
142
 *  invokes the handler procedure, if any.
 
143
 */
 
144
LOCAL tSuccess
 
145
handleOption( tOptions* pOpts, tOptState* pOptState )
 
146
{
 
147
    /*
 
148
     *  Save a copy of the option procedure pointer.
 
149
     *  If this is an equivalence class option, we still want this proc.
 
150
     */
 
151
    tOptDesc* pOD = pOptState->pOD;
 
152
    tOptProc* pOP = pOD->pOptProc;
 
153
    if (pOD->fOptState & OPTST_ALLOC_ARG)
 
154
        AGFREE(pOD->optArg.argString);
 
155
 
 
156
    pOD->optArg.argString = pOptState->pzOptArg;
 
157
 
 
158
    /*
 
159
     *  IF we are presetting options, then we will ignore any un-presettable
 
160
     *  options.  They are the ones either marked as such.
 
161
     */
 
162
    if (  ((pOpts->fOptSet & OPTPROC_PRESETTING) != 0)
 
163
       && ((pOD->fOptState & OPTST_NO_INIT) != 0)
 
164
       )
 
165
        return PROBLEM;
 
166
 
 
167
    /*
 
168
     *  IF this is an equivalence class option,
 
169
     *  THEN
 
170
     *      Save the option value that got us to this option
 
171
     *      entry.  (It may not be pOD->optChar[0], if this is an
 
172
     *      equivalence entry.)
 
173
     *      set the pointer to the equivalence class base
 
174
     */
 
175
    if (pOD->optEquivIndex != NO_EQUIVALENT) {
 
176
        tOptDesc* p = pOpts->pOptDesc + pOD->optEquivIndex;
 
177
 
 
178
        /*
 
179
         * IF the current option state has not been defined (set on the
 
180
         *    command line), THEN we will allow continued resetting of
 
181
         *    the value.  Once "defined", then it must not change.
 
182
         */
 
183
        if ((pOD->fOptState & OPTST_DEFINED) != 0) {
 
184
            /*
 
185
             *  The equivalenced-to option has been found on the command
 
186
             *  line before.  Make sure new occurrences are the same type.
 
187
             *
 
188
             *  IF this option has been previously equivalenced and
 
189
             *     it was not the same equivalenced-to option,
 
190
             *  THEN we have a usage problem.
 
191
             */
 
192
            if (p->optActualIndex != pOD->optIndex) {
 
193
                fprintf( stderr, (char*)zMultiEquiv, p->pz_Name, pOD->pz_Name,
 
194
                         (pOpts->pOptDesc + p->optActualIndex)->pz_Name);
 
195
                return FAILURE;
 
196
            }
 
197
        } else {
 
198
            /*
 
199
             *  Set the equivalenced-to actual option index to no-equivalent
 
200
             *  so that we set all the entries below.  This option may either
 
201
             *  never have been selected before, or else it was selected by
 
202
             *  some sort of "presetting" mechanism.
 
203
             */
 
204
            p->optActualIndex = NO_EQUIVALENT;
 
205
        }
 
206
 
 
207
        if (p->optActualIndex != pOD->optIndex) {
 
208
            /*
 
209
             *  First time through, copy over the state
 
210
             *  and add in the equivalence flag
 
211
             */
 
212
            p->optActualValue = pOD->optValue;
 
213
            p->optActualIndex = pOD->optIndex;
 
214
            pOptState->flags |= OPTST_EQUIVALENCE;
 
215
        }
 
216
 
 
217
        /*
 
218
         *  Copy the most recent option argument.  set membership state
 
219
         *  is kept in ``p->optCookie''.  Do not overwrite.
 
220
         */
 
221
        p->optArg.argString = pOD->optArg.argString;
 
222
        pOD = p;
 
223
 
 
224
    } else {
 
225
        pOD->optActualValue = pOD->optValue;
 
226
        pOD->optActualIndex = pOD->optIndex;
 
227
    }
 
228
 
 
229
    pOD->fOptState &= OPTST_PERSISTENT_MASK;
 
230
    pOD->fOptState |= (pOptState->flags & ~OPTST_PERSISTENT_MASK);
 
231
 
 
232
    /*
 
233
     *  Keep track of count only for DEFINED (command line) options.
 
234
     *  IF we have too many, build up an error message and bail.
 
235
     */
 
236
    if (  (pOD->fOptState & OPTST_DEFINED)
 
237
       && (++pOD->optOccCt > pOD->optMaxCt)  )  {
 
238
 
 
239
        if ((pOpts->fOptSet & OPTPROC_ERRSTOP) != 0) {
 
240
            char const * pzEqv =
 
241
                (pOD->optEquivIndex != NO_EQUIVALENT) ? zEquiv : zNil;
 
242
 
 
243
            fputs( zErrOnly, stderr );
 
244
 
 
245
            if (pOD->optMaxCt > 1)
 
246
                fprintf(stderr, zAtMost, pOD->optMaxCt, pOD->pz_Name, pzEqv);
 
247
            else
 
248
                fprintf(stderr, zOnlyOne, pOD->pz_Name, pzEqv);
 
249
        }
 
250
 
 
251
        return FAILURE;
 
252
    }
 
253
 
 
254
    /*
 
255
     *  If provided a procedure to call, call it
 
256
     */
 
257
    if (pOP != (tpOptProc)NULL)
 
258
        (*pOP)( pOpts, pOD );
 
259
 
 
260
    return SUCCESS;
 
261
}
 
262
 
 
263
 
 
264
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
 
265
 *
 
266
 *  HUNT FOR OPTIONS IN THE ARGUMENT LIST
 
267
 *
 
268
 *  The next four procedures are "private" to nextOption().
 
269
 *  nextOption() uses findOptDesc() to find the next descriptor and it, in
 
270
 *  turn, uses longOptionFind() and shortOptionFind() to actually do the hunt.
 
271
 *
 
272
 *  longOptionFind
 
273
 *
 
274
 *  Find the long option descriptor for the current option
 
275
 */
 
276
LOCAL tSuccess
 
277
longOptionFind( tOptions* pOpts, char* pzOptName, tOptState* pOptState )
 
278
{
 
279
    ag_bool    disable  = AG_FALSE;
 
280
    char*      pzEq     = strchr( pzOptName, '=' );
 
281
    tOptDesc*  pOD      = pOpts->pOptDesc;
 
282
    int        idx      = 0;
 
283
    int        idxLim   = pOpts->optCt;
 
284
    int        matchCt  = 0;
 
285
    int        matchIdx = 0;
 
286
    int        nameLen;
 
287
 
 
288
    /*
 
289
     *  IF the value is attached to the name,
 
290
     *  THEN clip it off.
 
291
     *  Either way, figure out how long our name is
 
292
     */
 
293
    if (pzEq != NULL) {
 
294
        nameLen = (int)(pzEq - pzOptName);
 
295
        *pzEq = NUL;
 
296
    } else nameLen = strlen( pzOptName );
 
297
 
 
298
    do  {
 
299
        if (SKIP_OPT(pOD))
 
300
            continue;
 
301
 
 
302
        if (strneqvcmp( pzOptName, pOD->pz_Name, nameLen ) == 0) {
 
303
            /*
 
304
             *  IF we have a complete match
 
305
             *  THEN it takes priority over any already located partial
 
306
             */
 
307
            if (pOD->pz_Name[ nameLen ] == NUL) {
 
308
                matchCt  = 1;
 
309
                matchIdx = idx;
 
310
                break;
 
311
            }
 
312
        }
 
313
 
 
314
        /*
 
315
         *  IF       there is a disable name
 
316
         *     *AND* no argument value has been supplied
 
317
         *              (disabled options may have no argument)
 
318
         *     *AND* the option name matches the disable name
 
319
         *  THEN ...
 
320
         */
 
321
        else if (  (pOD->pz_DisableName != NULL)
 
322
                && (strneqvcmp(pzOptName, pOD->pz_DisableName, nameLen) == 0)
 
323
                )  {
 
324
            disable  = AG_TRUE;
 
325
 
 
326
            /*
 
327
             *  IF we have a complete match
 
328
             *  THEN it takes priority over any already located partial
 
329
             */
 
330
            if (pOD->pz_DisableName[ nameLen ] == NUL) {
 
331
                matchCt  = 1;
 
332
                matchIdx = idx;
 
333
                break;
 
334
            }
 
335
        }
 
336
 
 
337
        else
 
338
            continue;
 
339
 
 
340
        /*
 
341
         *  We found a partial match, either regular or disabling.
 
342
         *  Remember the index for later.
 
343
         */
 
344
        matchIdx = idx;
 
345
 
 
346
        if (++matchCt > 1)
 
347
            break;
 
348
 
 
349
    } while (pOD++, (++idx < idxLim));
 
350
 
 
351
    if (pzEq != NULL)
 
352
        *(pzEq++) = '=';
 
353
 
 
354
    /*
 
355
     *  Make sure we either found an exact match or found only one partial
 
356
     */
 
357
    if (matchCt == 1) {
 
358
        /*
 
359
         *  IF we found a disablement name,
 
360
         *  THEN set the bit in the callers' flag word
 
361
         */
 
362
        if (disable)
 
363
            pOptState->flags |= OPTST_DISABLED;
 
364
 
 
365
        pOptState->pOD      = pOpts->pOptDesc + matchIdx;
 
366
        pOptState->pzOptArg = pzEq;
 
367
        pOptState->optType  = TOPT_LONG;
 
368
        return SUCCESS;
 
369
    }
 
370
 
 
371
    /*
 
372
     *  IF there is no equal sign
 
373
     *     *AND* we are using named arguments
 
374
     *     *AND* there is a default named option,
 
375
     *  THEN return that option.
 
376
     */
 
377
    if (  (pzEq == NULL)
 
378
       && NAMED_OPTS(pOpts)
 
379
       && (pOpts->specOptIdx.default_opt != NO_EQUIVALENT)) {
 
380
        pOptState->pOD = pOpts->pOptDesc + pOpts->specOptIdx.default_opt;
 
381
 
 
382
        pOptState->pzOptArg = pzOptName;
 
383
        pOptState->optType  = TOPT_DEFAULT;
 
384
        return SUCCESS;
 
385
    }
 
386
 
 
387
    /*
 
388
     *  IF we are to stop on errors (the default, actually)
 
389
     *  THEN call the usage procedure.
 
390
     */
 
391
    if ((pOpts->fOptSet & OPTPROC_ERRSTOP) != 0) {
 
392
        fprintf( stderr, zIllOptStr, pOpts->pzProgPath,
 
393
                 (matchCt == 0) ? zIllegal : zAmbiguous, pzOptName );
 
394
        (*pOpts->pUsageProc)( pOpts, EXIT_FAILURE );
 
395
    }
 
396
 
 
397
    return FAILURE;
 
398
}
 
399
 
 
400
 
 
401
/*
 
402
 *  shortOptionFind
 
403
 *
 
404
 *  Find the short option descriptor for the current option
 
405
 */
 
406
LOCAL tSuccess
 
407
shortOptionFind( tOptions* pOpts, uint_t optValue, tOptState* pOptState )
 
408
{
 
409
    tOptDesc*  pRes = pOpts->pOptDesc;
 
410
    int        ct   = pOpts->optCt;
 
411
 
 
412
    /*
 
413
     *  Search the option list
 
414
     */
 
415
    for (;;) {
 
416
        /*
 
417
         *  IF the values match,
 
418
         *  THEN we stop here
 
419
         */
 
420
        if ((! SKIP_OPT(pRes)) && (optValue == pRes->optValue)) {
 
421
            pOptState->pOD     = pRes;
 
422
            pOptState->optType = TOPT_SHORT;
 
423
            return SUCCESS;
 
424
        }
 
425
 
 
426
        /*
 
427
         *  Advance to next option description
 
428
         */
 
429
        pRes++;
 
430
 
 
431
        /*
 
432
         *  IF we have searched everything, ...
 
433
         */
 
434
        if (--ct <= 0)
 
435
            break;
 
436
    }
 
437
 
 
438
    /*
 
439
     *  IF    the character value is a digit
 
440
     *    AND there is a special number option ("-n")
 
441
     *  THEN the result is the "option" itself and the
 
442
     *       option is the specially marked "number" option.
 
443
     */
 
444
    if (  isdigit( optValue )
 
445
       && (pOpts->specOptIdx.number_option != NO_EQUIVALENT) ) {
 
446
        pOptState->pOD = \
 
447
        pRes           = pOpts->pOptDesc + pOpts->specOptIdx.number_option;
 
448
        (pOpts->pzCurOpt)--;
 
449
        pOptState->optType = TOPT_SHORT;
 
450
        return SUCCESS;
 
451
    }
 
452
 
 
453
    /*
 
454
     *  IF we are to stop on errors (the default, actually)
 
455
     *  THEN call the usage procedure.
 
456
     */
 
457
    if ((pOpts->fOptSet & OPTPROC_ERRSTOP) != 0) {
 
458
        fprintf( stderr, zIllOptChr, pOpts->pzProgPath, optValue );
 
459
        (*pOpts->pUsageProc)( pOpts, EXIT_FAILURE );
 
460
    }
 
461
 
 
462
    return FAILURE;
 
463
}
 
464
 
 
465
 
 
466
/*
 
467
 *  findOptDesc
 
468
 *
 
469
 *  Find the option descriptor for the current option
 
470
 */
 
471
static tSuccess
 
472
findOptDesc( tOptions* pOpts, tOptState* pOptState )
 
473
{
 
474
    /*
 
475
     *  IF we are continuing a short option list (e.g. -xyz...)
 
476
     *  THEN continue a single flag option.
 
477
     *  OTHERWISE see if there is room to advance and then do so.
 
478
     */
 
479
    if ((pOpts->pzCurOpt != NULL) && (*pOpts->pzCurOpt != NUL))
 
480
        return shortOptionFind( pOpts, (tAoUC)*(pOpts->pzCurOpt), pOptState );
 
481
 
 
482
    if (pOpts->curOptIdx >= pOpts->origArgCt)
 
483
        return PROBLEM; /* NORMAL COMPLETION */
 
484
 
 
485
    pOpts->pzCurOpt = pOpts->origArgVect[ pOpts->curOptIdx ];
 
486
 
 
487
    /*
 
488
     *  IF all arguments must be named options, ...
 
489
     */
 
490
    if (NAMED_OPTS(pOpts)) {
 
491
        char* pz = pOpts->pzCurOpt;
 
492
        pOpts->curOptIdx++;
 
493
 
 
494
        /*
 
495
         *  Skip over any flag/option markers.
 
496
         *  In this mode, they are not required.
 
497
         */
 
498
        while (*pz == '-') pz++;
 
499
 
 
500
        return longOptionFind( pOpts, pz, pOptState );
 
501
    }
 
502
 
 
503
    /*
 
504
     *  Note the kind of flag/option marker
 
505
     */
 
506
    if (*((pOpts->pzCurOpt)++) != '-')
 
507
        return PROBLEM; /* NORMAL COMPLETION - this + rest are operands */
 
508
 
 
509
    /*
 
510
     *  Special hack for a hyphen by itself
 
511
     */
 
512
    if (*(pOpts->pzCurOpt) == NUL)
 
513
        return PROBLEM; /* NORMAL COMPLETION - this + rest are operands */
 
514
 
 
515
    /*
 
516
     *  The current argument is to be processed as an option argument
 
517
     */
 
518
    pOpts->curOptIdx++;
 
519
 
 
520
    /*
 
521
     *  We have an option marker.
 
522
     *  Test the next character for long option indication
 
523
     */
 
524
    if (pOpts->pzCurOpt[0] == '-') {
 
525
        if (*++(pOpts->pzCurOpt) == NUL)
 
526
            /*
 
527
             *  NORMAL COMPLETION - NOT this arg, but rest are operands
 
528
             */
 
529
            return PROBLEM;
 
530
 
 
531
        /*
 
532
         *  We do not allow the hyphen to be used as a flag value.
 
533
         *  Therefore, if long options are not to be accepted, we punt.
 
534
         */
 
535
        if ((pOpts->fOptSet & OPTPROC_LONGOPT) == 0) {
 
536
            fprintf( stderr, zIllOptStr, pOpts->pzProgPath,
 
537
                     zIllegal, pOpts->pzCurOpt-2 );
 
538
            return FAILURE;
 
539
        }
 
540
 
 
541
        return longOptionFind( pOpts, pOpts->pzCurOpt, pOptState );
 
542
    }
 
543
 
 
544
    /*
 
545
     *  If short options are not allowed, then do long
 
546
     *  option processing.  Otherwise the character must be a
 
547
     *  short (i.e. single character) option.
 
548
     */
 
549
    if ((pOpts->fOptSet & OPTPROC_SHORTOPT) != 0)
 
550
        return shortOptionFind( pOpts, (tAoUC)*(pOpts->pzCurOpt), pOptState );
 
551
 
 
552
    return longOptionFind( pOpts, pOpts->pzCurOpt, pOptState );
 
553
}
 
554
 
 
555
 
 
556
/*
 
557
 *  nextOption
 
558
 *
 
559
 *  Find the option descriptor and option argument (if any) for the
 
560
 *  next command line argument.  DO NOT modify the descriptor.  Put
 
561
 *  all the state in the state argument so that the option can be skipped
 
562
 *  without consequence (side effect).
 
563
 */
 
564
static tSuccess
 
565
nextOption( tOptions* pOpts, tOptState* pOptState )
 
566
{
 
567
    tSuccess res;
 
568
    enum { ARG_NONE, ARG_MAY, ARG_MUST } arg_type = ARG_NONE;
 
569
    teOptArgType at;
 
570
 
 
571
    res = findOptDesc( pOpts, pOptState );
 
572
    if (! SUCCESSFUL( res ))
 
573
        return res;
 
574
    pOptState->flags |= (pOptState->pOD->fOptState & OPTST_PERSISTENT_MASK);
 
575
    at = OPTST_GET_ARGTYPE(pOptState->flags);
 
576
 
 
577
    /*
 
578
     *  Figure out what to do about option arguments.  An argument may be
 
579
     *  required, not associated with the option, or be optional.  We detect the
 
580
     *  latter by examining for an option marker on the next possible argument.
 
581
     *  Disabled mode option selection also disables option arguments.
 
582
     */
 
583
    if ((pOptState->flags & OPTST_DISABLED) != 0)
 
584
        arg_type = ARG_NONE;
 
585
    else if (at == OPARG_TYPE_NONE)
 
586
        arg_type = ARG_NONE;
 
587
    else if (pOptState->flags & OPTST_ARG_OPTIONAL)
 
588
        arg_type = ARG_MAY;
 
589
    else
 
590
        arg_type = ARG_MUST;
 
591
 
 
592
    switch (arg_type) {
 
593
    case ARG_MUST:
 
594
        /*
 
595
         *  An option argument is required.  Long options can either have
 
596
         *  a separate command line argument, or an argument attached by
 
597
         *  the '=' character.  Figure out which.
 
598
         */
 
599
        switch (pOptState->optType) {
 
600
        case TOPT_SHORT:
 
601
            /*
 
602
             *  See if an arg string follows the flag character
 
603
             */
 
604
            if (*++(pOpts->pzCurOpt) == NUL)
 
605
                pOpts->pzCurOpt = pOpts->origArgVect[ pOpts->curOptIdx++ ];
 
606
            pOptState->pzOptArg = pOpts->pzCurOpt;
 
607
            break;
 
608
 
 
609
        case TOPT_LONG:
 
610
            /*
 
611
             *  See if an arg string has already been assigned (glued on
 
612
             *  with an `=' character)
 
613
             */
 
614
            if (pOptState->pzOptArg == NULL)
 
615
                pOptState->pzOptArg = pOpts->origArgVect[ pOpts->curOptIdx++ ];
 
616
            break;
 
617
 
 
618
        default:
 
619
#ifdef DEBUG
 
620
            fputs( "AutoOpts lib error: option type not selected\n",
 
621
                   stderr );
 
622
            exit( EXIT_FAILURE );
 
623
#endif
 
624
 
 
625
        case TOPT_DEFAULT:
 
626
            /*
 
627
             *  The option was selected by default.  The current token is
 
628
             *  the option argument.
 
629
             */
 
630
            break;
 
631
        }
 
632
 
 
633
        /*
 
634
         *  Make sure we did not overflow the argument list.
 
635
         */
 
636
        if (pOpts->curOptIdx > pOpts->origArgCt) {
 
637
            fprintf( stderr, zMisArg, pOpts->pzProgPath,
 
638
                     pOptState->pOD->pz_Name );
 
639
            return FAILURE;
 
640
        }
 
641
 
 
642
        pOpts->pzCurOpt = NULL;  /* next time advance to next arg */
 
643
        break;
 
644
 
 
645
    case ARG_MAY:
 
646
        /*
 
647
         *  An option argument is optional.
 
648
         */
 
649
        switch (pOptState->optType) {
 
650
        case TOPT_SHORT:
 
651
            if (*++pOpts->pzCurOpt != NUL)
 
652
                pOptState->pzOptArg = pOpts->pzCurOpt;
 
653
            else {
 
654
                char* pzLA = pOpts->origArgVect[ pOpts->curOptIdx ];
 
655
 
 
656
                /*
 
657
                 *  BECAUSE it is optional, we must make sure
 
658
                 *  we did not find another flag and that there
 
659
                 *  is such an argument.
 
660
                 */
 
661
                if ((pzLA == NULL) || (*pzLA == '-'))
 
662
                    pOptState->pzOptArg = NULL;
 
663
                else {
 
664
                    pOpts->curOptIdx++; /* argument found */
 
665
                    pOptState->pzOptArg = pzLA;
 
666
                }
 
667
            }
 
668
            break;
 
669
 
 
670
        case TOPT_LONG:
 
671
            /*
 
672
             *  Look for an argument if we don't already have one (glued on
 
673
             *  with a `=' character) *AND* we are not in named argument mode
 
674
             */
 
675
            if (  (pOptState->pzOptArg == NULL)
 
676
               && (! NAMED_OPTS(pOpts))) {
 
677
                char* pzLA = pOpts->origArgVect[ pOpts->curOptIdx ];
 
678
 
 
679
                /*
 
680
                 *  BECAUSE it is optional, we must make sure
 
681
                 *  we did not find another flag and that there
 
682
                 *  is such an argument.
 
683
                 */
 
684
                if ((pzLA == NULL) || (*pzLA == '-'))
 
685
                    pOptState->pzOptArg = NULL;
 
686
                else {
 
687
                    pOpts->curOptIdx++; /* argument found */
 
688
                    pOptState->pzOptArg = pzLA;
 
689
                }
 
690
            }
 
691
            break;
 
692
 
 
693
        default:
 
694
        case TOPT_DEFAULT:
 
695
            fputs( "AutoOpts lib error: defaulted to option with optional arg\n",
 
696
                   stderr );
 
697
            exit( EX_SOFTWARE );
 
698
        }
 
699
 
 
700
        /*
 
701
         *  After an option with an optional argument, we will
 
702
         *  *always* start with the next option because if there
 
703
         *  were any characters following the option name/flag,
 
704
         *  they would be interpreted as the argument.
 
705
         */
 
706
        pOpts->pzCurOpt = NULL;
 
707
        break;
 
708
 
 
709
    default: /* CANNOT */
 
710
        /*
 
711
         *  No option argument.  Make sure next time around we find
 
712
         *  the correct option flag character for short options
 
713
         */
 
714
        if (pOptState->optType == TOPT_SHORT)
 
715
            (pOpts->pzCurOpt)++;
 
716
 
 
717
        /*
 
718
         *  It is a long option.  Make sure there was no ``=xxx'' argument
 
719
         */
 
720
        else if (pOptState->pzOptArg != NULL) {
 
721
            fprintf( stderr, zNoArg, pOpts->pzProgPath,
 
722
                     pOptState->pOD->pz_Name );
 
723
            return FAILURE;
 
724
        }
 
725
 
 
726
        /*
 
727
         *  It is a long option.  Advance to next command line argument.
 
728
         */
 
729
        else
 
730
            pOpts->pzCurOpt = NULL;
 
731
    }
 
732
 
 
733
    return SUCCESS;
 
734
}
 
735
 
 
736
 
 
737
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
 
738
 *
 
739
 *  DO PRESETS
 
740
 *
 
741
 *  The next several routines do the immediate action pass on the command
 
742
 *  line options, then the environment variables, then the config files in
 
743
 *  reverse order.  Once done with that, the order is reversed and all
 
744
 *  the config files and environment variables are processed again, this
 
745
 *  time only processing the non-immediate action options.  doPresets()
 
746
 *  will then return for optionProcess() to do the final pass on the command
 
747
 *  line arguments.
 
748
 */
 
749
 
 
750
/*
 
751
 *  doImmediateOpts - scan the command line for immediate action options
 
752
 */
 
753
LOCAL tSuccess
 
754
doImmediateOpts( tOptions* pOpts )
 
755
{
 
756
    pOpts->curOptIdx = 1;     /* start by skipping program name */
 
757
    pOpts->pzCurOpt  = NULL;
 
758
 
 
759
    /*
 
760
     *  Examine all the options from the start.  We process any options that
 
761
     *  are marked for immediate processing.
 
762
     */
 
763
    for (;;) {
 
764
        tOptState optState = OPTSTATE_INITIALIZER(PRESET);
 
765
 
 
766
        switch (nextOption( pOpts, &optState )) {
 
767
        case FAILURE: goto optionsDone;
 
768
        case PROBLEM: return SUCCESS; /* no more args */
 
769
        case SUCCESS: break;
 
770
        }
 
771
 
 
772
        /*
 
773
         *  IF this *is* an immediate-attribute option, then do it.
 
774
         */
 
775
        if (! DO_IMMEDIATELY(optState.flags))
 
776
            continue;
 
777
 
 
778
        if (! SUCCESSFUL( handleOption( pOpts, &optState )))
 
779
            break;
 
780
    } optionsDone:;
 
781
 
 
782
    if ((pOpts->fOptSet & OPTPROC_ERRSTOP) != 0)
 
783
        (*pOpts->pUsageProc)( pOpts, EXIT_FAILURE );
 
784
    return FAILURE;
 
785
}
 
786
 
 
787
 
 
788
LOCAL tSuccess
 
789
doRegularOpts( tOptions* pOpts )
 
790
{
 
791
    /*
 
792
     *  Now, process all the options from our current position onward.
 
793
     *  (This allows interspersed options and arguments for the few
 
794
     *  non-standard programs that require it.)
 
795
     */
 
796
    for (;;) {
 
797
        tOptState optState = OPTSTATE_INITIALIZER(DEFINED);
 
798
 
 
799
        switch (nextOption( pOpts, &optState )) {
 
800
        case FAILURE: goto optionsDone;
 
801
        case PROBLEM: return SUCCESS; /* no more args */
 
802
        case SUCCESS: break;
 
803
        }
 
804
 
 
805
        /*
 
806
         *  IF this is not being processed normally (i.e. is immediate action)
 
807
         *  THEN skip it (unless we are supposed to do it a second time).
 
808
         */
 
809
        if (! DO_NORMALLY(optState.flags)) {
 
810
            if (! DO_SECOND_TIME(optState.flags))
 
811
                continue;
 
812
            optState.pOD->optOccCt--; /* don't count last time */
 
813
        }
 
814
 
 
815
        if (! SUCCESSFUL( handleOption( pOpts, &optState )))
 
816
            break;
 
817
    } optionsDone:;
 
818
    if ((pOpts->fOptSet & OPTPROC_ERRSTOP) != 0)
 
819
        (*pOpts->pUsageProc)( pOpts, EXIT_FAILURE );
 
820
    return FAILURE;
 
821
}
 
822
 
 
823
 
 
824
/*
 
825
 *  doPresets - check for preset values from a config file or the envrionment
 
826
 */
 
827
static tSuccess
 
828
doPresets( tOptions* pOpts )
 
829
{
 
830
    tOptDesc * pOD = NULL;
 
831
 
 
832
    if (! SUCCESSFUL( doImmediateOpts( pOpts )))
 
833
        return FAILURE;
 
834
 
 
835
    /*
 
836
     *  IF this option set has a --save-opts option, then it also
 
837
     *  has a --load-opts option.  See if a command line option has disabled
 
838
     *  option presetting.
 
839
     */
 
840
    if (pOpts->specOptIdx.save_opts != 0) {
 
841
        pOD = pOpts->pOptDesc + pOpts->specOptIdx.save_opts + 1;
 
842
        if (DISABLED_OPT(pOD))
 
843
            return SUCCESS;
 
844
    }
 
845
 
 
846
    /*
 
847
     *  Until we return from this procedure, disable non-presettable opts
 
848
     */
 
849
    pOpts->fOptSet |= OPTPROC_PRESETTING;
 
850
    /*
 
851
     *  IF there are no config files,
 
852
     *  THEN do any environment presets and leave.
 
853
     */
 
854
    if (pOpts->papzHomeList == NULL) {
 
855
        doEnvPresets( pOpts, ENV_ALL );
 
856
    }
 
857
    else {
 
858
        doEnvPresets( pOpts, ENV_IMM );
 
859
 
 
860
        /*
 
861
         *  Check to see if environment variables have disabled presetting.
 
862
         */
 
863
        if ((pOD != NULL) && ! DISABLED_OPT(pOD))
 
864
            internalFileLoad( pOpts );
 
865
 
 
866
        /*
 
867
         *  ${PROGRAM_LOAD_OPTS} value of "no" cannot disable other environment
 
868
         *  variable options.  Only the loading of .rc files.
 
869
         */
 
870
        doEnvPresets( pOpts, ENV_NON_IMM );
 
871
    }
 
872
    pOpts->fOptSet &= ~OPTPROC_PRESETTING;
 
873
 
 
874
    return SUCCESS;
 
875
}
 
876
 
 
877
 
 
878
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
 
879
 *
 
880
 *  VERIFY OPTION CONSISTENCY
 
881
 *
 
882
 *  Make sure that the argument list passes our consistency tests.
 
883
 */
 
884
static int
 
885
checkConsistency( tOptions* pOpts )
 
886
{
 
887
    int        errCt = 0;
 
888
    tOptDesc*  pOD   = pOpts->pOptDesc;
 
889
    int        oCt   = pOpts->presetOptCt;
 
890
 
 
891
    /*
 
892
     *  FOR each of "oCt" options, ...
 
893
     */
 
894
    for (;;) {
 
895
        const int*  pMust = pOD->pOptMust;
 
896
        const int*  pCant = pOD->pOptCant;
 
897
 
 
898
        /*
 
899
         *  IF the current option was provided on the command line
 
900
         *  THEN ensure that any "MUST" requirements are not
 
901
         *       "DEFAULT" (unspecified) *AND* ensure that any
 
902
         *       "CANT" options have not been SET or DEFINED.
 
903
         */
 
904
        if (SELECTED_OPT(pOD)) {
 
905
            if (pMust != NULL) for (;;) {
 
906
                tOptDesc*  p = pOpts->pOptDesc + *(pMust++);
 
907
                if (UNUSED_OPT(p)) {
 
908
                    const tOptDesc* pN = pOpts->pOptDesc + pMust[-1];
 
909
                    errCt++;
 
910
                    fprintf( stderr, zReqFmt, pOD->pz_Name, pN->pz_Name );
 
911
                }
 
912
 
 
913
                if (*pMust == NO_EQUIVALENT)
 
914
                    break;
 
915
            }
 
916
 
 
917
            if (pCant != NULL) for (;;) {
 
918
                tOptDesc*  p = pOpts->pOptDesc + *(pCant++);
 
919
                if (SELECTED_OPT(p)) {
 
920
                    const tOptDesc* pN = pOpts->pOptDesc + pCant[-1];
 
921
                    errCt++;
 
922
                    fprintf( stderr, zCantFmt, pOD->pz_Name, pN->pz_Name );
 
923
                }
 
924
 
 
925
                if (*pCant == NO_EQUIVALENT)
 
926
                    break;
 
927
            }
 
928
        }
 
929
 
 
930
        /*
 
931
         *  IF       this option is not equivalenced to another,
 
932
         *        OR it is equivalenced to itself (is the equiv. root)
 
933
         *  THEN we need to make sure it occurs often enough.
 
934
         */
 
935
        if (  (pOD->optEquivIndex == NO_EQUIVALENT)
 
936
           || (pOD->optEquivIndex == pOD->optIndex) )   do {
 
937
            /*
 
938
             *  IF the occurrence counts have been satisfied,
 
939
             *  THEN there is no problem.
 
940
             */
 
941
            if (pOD->optOccCt >= pOD->optMinCt)
 
942
                break;
 
943
 
 
944
            /*
 
945
             *  IF MUST_SET means SET and PRESET are okay,
 
946
             *  so min occurrence count doesn't count
 
947
             */
 
948
            if (  (pOD->fOptState & OPTST_MUST_SET)
 
949
               && (pOD->fOptState & (OPTST_PRESET | OPTST_SET)) )
 
950
                break;
 
951
 
 
952
            errCt++;
 
953
            if (pOD->optMinCt > 1)
 
954
                 fprintf( stderr, zNotEnough, pOD->pz_Name, pOD->optMinCt );
 
955
            else fprintf( stderr, zNeedOne, pOD->pz_Name );
 
956
        } while (0);
 
957
 
 
958
        if (--oCt <= 0)
 
959
            break;
 
960
        pOD++;
 
961
    }
 
962
 
 
963
    /*
 
964
     *  IF we are stopping on errors, check to see if any remaining
 
965
     *  arguments are required to be there or prohibited from being there.
 
966
     */
 
967
    if ((pOpts->fOptSet & OPTPROC_ERRSTOP) != 0) {
 
968
 
 
969
        /*
 
970
         *  Check for prohibition
 
971
         */
 
972
        if ((pOpts->fOptSet & OPTPROC_NO_ARGS) != 0) {
 
973
            if (pOpts->origArgCt > pOpts->curOptIdx) {
 
974
                fprintf( stderr, zNoArgs, pOpts->pzProgName );
 
975
                ++errCt;
 
976
            }
 
977
        }
 
978
 
 
979
        /*
 
980
         *  ELSE not prohibited, check for being required
 
981
         */
 
982
        else if ((pOpts->fOptSet & OPTPROC_ARGS_REQ) != 0) {
 
983
            if (pOpts->origArgCt <= pOpts->curOptIdx) {
 
984
                fprintf( stderr, zArgsMust, pOpts->pzProgName );
 
985
                ++errCt;
 
986
            }
 
987
        }
 
988
    }
 
989
 
 
990
    return errCt;
 
991
}
 
992
 
 
993
 
 
994
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
 
995
 *
 
996
 *  THESE ROUTINES ARE CALLABLE FROM THE GENERATED OPTION PROCESSING CODE
 
997
 */
 
998
/*=--subblock=arg=arg_type,arg_name,arg_desc =*/
 
999
/*=*
 
1000
 * library:  opts
 
1001
 * header:   your-opts.h
 
1002
 *
 
1003
 * lib_description:
 
1004
 *
 
1005
 *  These are the routines that libopts users may call directly from their
 
1006
 *  code.  There are several other routines that can be called by code
 
1007
 *  generated by the libopts option templates, but they are not to be
 
1008
 *  called from any other user code.  The @file{options.h} header is
 
1009
 *  fairly clear about this, too.
 
1010
=*/
 
1011
 
 
1012
/*=export_func optionProcess
 
1013
 *
 
1014
 * what: this is the main option processing routine
 
1015
 *
 
1016
 * arg:  + tOptions* + pOpts + program options descriptor +
 
1017
 * arg:  + int       + argc  + program arg count  +
 
1018
 * arg:  + char**    + argv  + program arg vector +
 
1019
 *
 
1020
 * ret_type:  int
 
1021
 * ret_desc:  the count of the arguments processed
 
1022
 *
 
1023
 * doc:
 
1024
 *
 
1025
 * This is the main entry point for processing options.  It is intended
 
1026
 * that this procedure be called once at the beginning of the execution of
 
1027
 * a program.  Depending on options selected earlier, it is sometimes
 
1028
 * necessary to stop and restart option processing, or to select completely
 
1029
 * different sets of options.  This can be done easily, but you generally
 
1030
 * do not want to do this.
 
1031
 *
 
1032
 * The number of arguments processed always includes the program name.
 
1033
 * If one of the arguments is "--", then it is counted and the processing
 
1034
 * stops.  If an error was encountered and errors are to be tolerated, then
 
1035
 * the returned value is the index of the argument causing the error.
 
1036
 * A hyphen by itself ("-") will also cause processing to stop and will
 
1037
 * @emph{not} be counted among the processed arguments.  A hyphen by itself
 
1038
 * is treated as an operand.  Encountering an operand stops option
 
1039
 * processing.
 
1040
 *
 
1041
 * err:  Errors will cause diagnostics to be printed.  @code{exit(3)} may
 
1042
 *       or may not be called.  It depends upon whether or not the options
 
1043
 *       were generated with the "allow-errors" attribute, or if the
 
1044
 *       ERRSKIP_OPTERR or ERRSTOP_OPTERR macros were invoked.
 
1045
=*/
 
1046
int
 
1047
optionProcess(
 
1048
    tOptions*  pOpts,
 
1049
    int        argCt,
 
1050
    char**     argVect )
 
1051
{
 
1052
    if (! SUCCESSFUL( validateOptionsStruct( pOpts, argVect[0] )))
 
1053
        exit( EX_SOFTWARE );
 
1054
 
 
1055
    /*
 
1056
     *  Establish the real program name, the program full path,
 
1057
     *  and do all the presetting the first time thru only.
 
1058
     */
 
1059
    if ((pOpts->fOptSet & OPTPROC_INITDONE) == 0) {
 
1060
        pOpts->origArgCt   = argCt;
 
1061
        pOpts->origArgVect = argVect;
 
1062
        pOpts->fOptSet    |= OPTPROC_INITDONE;
 
1063
 
 
1064
        if (! SUCCESSFUL( doPresets( pOpts )))
 
1065
            return 0;
 
1066
 
 
1067
        if ((pOpts->fOptSet & OPTPROC_REORDER) != 0)
 
1068
            optionSort( pOpts );
 
1069
 
 
1070
        pOpts->curOptIdx   = 1;
 
1071
        pOpts->pzCurOpt    = NULL;
 
1072
    }
 
1073
 
 
1074
    /*
 
1075
     *  IF we are (re)starting,
 
1076
     *  THEN reset option location
 
1077
     */
 
1078
    else if (pOpts->curOptIdx <= 0) {
 
1079
        pOpts->curOptIdx = 1;
 
1080
        pOpts->pzCurOpt  = NULL;
 
1081
    }
 
1082
 
 
1083
    if (! SUCCESSFUL( doRegularOpts( pOpts )))
 
1084
        return pOpts->origArgCt;
 
1085
 
 
1086
    /*
 
1087
     *  IF    there were no errors
 
1088
     *    AND we have RC/INI files
 
1089
     *    AND there is a request to save the files
 
1090
     *  THEN do that now before testing for conflicts.
 
1091
     *       (conflicts are ignored in preset options)
 
1092
     */
 
1093
    if (pOpts->specOptIdx.save_opts != 0) {
 
1094
        tOptDesc*  pOD = pOpts->pOptDesc + pOpts->specOptIdx.save_opts;
 
1095
 
 
1096
        if (SELECTED_OPT( pOD )) {
 
1097
            optionSaveFile( pOpts );
 
1098
            exit( EXIT_SUCCESS );
 
1099
        }
 
1100
    }
 
1101
 
 
1102
    /*
 
1103
     *  IF we are checking for errors,
 
1104
     *  THEN look for too few occurrences of required options
 
1105
     */
 
1106
    if ((pOpts->fOptSet & OPTPROC_ERRSTOP) != 0) {
 
1107
        if (checkConsistency( pOpts ) != 0)
 
1108
            (*pOpts->pUsageProc)( pOpts, EXIT_FAILURE );
 
1109
    }
 
1110
 
 
1111
    return pOpts->curOptIdx;
 
1112
}
 
1113
 
 
1114
/*
 
1115
 * Local Variables:
 
1116
 * mode: C
 
1117
 * c-file-style: "stroustrup"
 
1118
 * indent-tabs-mode: nil
 
1119
 * End:
 
1120
 * end of autoopts/autoopts.c */