~ubuntu-branches/ubuntu/gutsy/ntp/gutsy

« back to all changes in this revision

Viewing changes to libopts/makeshell.c

  • Committer: Bazaar Package Importer
  • Author(s): Steve Kowalik
  • Date: 2007-05-18 22:41:56 UTC
  • mfrom: (1.2.3 upstream)
  • Revision ID: james.westby@ubuntu.com-20070518224156-563ruqxsxvqvoy8h
Tags: 1:4.2.4p0+dfsg-1ubuntu1
* Merge from Debian unstable.
* Remaining Ubuntu changes:
  - Update version in conflicts/replaces to that which was shipped in edgy,
    which was later than that in Debian (due to the ubuntuX).
  - Change default server to ntp.ubuntu.com.
  - Remove stop links from rc0 and rc6
  - Call dh_installinit with --error-handler
  - Set Ubuntu maintainer address.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
 
 
2
/*
 
3
 *  $Id: makeshell.c,v 4.14 2006/10/06 05:29:00 bkorb Exp $
 
4
 * Time-stamp:      "2006-10-05 20:41:23 bkorb"
 
5
 *
 
6
 *  This module will interpret the options set in the tOptions
 
7
 *  structure and create a Bourne shell script capable of parsing them.
 
8
 */
 
9
 
 
10
/*
 
11
 *  Automated Options copyright 1992-2006 Bruce Korb
 
12
 *
 
13
 *  Automated Options is free software.
 
14
 *  You may redistribute it and/or modify it under the terms of the
 
15
 *  GNU General Public License, as published by the Free Software
 
16
 *  Foundation; either version 2, or (at your option) any later version.
 
17
 *
 
18
 *  Automated Options is distributed in the hope that it will be useful,
 
19
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 
20
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
21
 *  GNU General Public License for more details.
 
22
 *
 
23
 *  You should have received a copy of the GNU General Public License
 
24
 *  along with Automated Options.  See the file "COPYING".  If not,
 
25
 *  write to:  The Free Software Foundation, Inc.,
 
26
 *             51 Franklin Street, Fifth Floor,
 
27
 *             Boston, MA  02110-1301, USA.
 
28
 *
 
29
 * As a special exception, Bruce Korb gives permission for additional
 
30
 * uses of the text contained in his release of AutoOpts.
 
31
 *
 
32
 * The exception is that, if you link the AutoOpts library with other
 
33
 * files to produce an executable, this does not by itself cause the
 
34
 * resulting executable to be covered by the GNU General Public License.
 
35
 * Your use of that executable is in no way restricted on account of
 
36
 * linking the AutoOpts library code into it.
 
37
 *
 
38
 * This exception does not however invalidate any other reasons why
 
39
 * the executable file might be covered by the GNU General Public License.
 
40
 *
 
41
 * This exception applies only to the code released by Bruce Korb under
 
42
 * the name AutoOpts.  If you copy code from other sources under the
 
43
 * General Public License into a copy of AutoOpts, as the General Public
 
44
 * License permits, the exception does not apply to the code that you add
 
45
 * in this way.  To avoid misleading anyone as to the status of such
 
46
 * modified files, you must delete this exception notice from them.
 
47
 *
 
48
 * If you write modifications of your own for AutoOpts, it is your choice
 
49
 * whether to permit this exception to apply to your modifications.
 
50
 * If you do not wish that, delete this exception notice.
 
51
 */
 
52
 
 
53
tOptions*  pShellParseOptions = NULL;
 
54
 
 
55
/* * * * * * * * * * * * * * * * * * * * *
 
56
 *
 
57
 *  Setup Format Strings
 
58
 */
 
59
tSCC zStartMarker[] =
 
60
"# # # # # # # # # # -- do not modify this marker --\n#\n"
 
61
"#  DO NOT EDIT THIS SECTION";
 
62
 
 
63
tSCC zPreamble[] =
 
64
"%s OF %s\n#\n"
 
65
"#  From here to the next `-- do not modify this marker --',\n"
 
66
"#  the text has been generated %s\n";
 
67
 
 
68
tSCC zEndPreamble[] =
 
69
"#  From the %s option definitions\n#\n";
 
70
 
 
71
tSCC zMultiDef[] = "\n"
 
72
"if test -z \"${%1$s_%2$s}\"\n"
 
73
"then\n"
 
74
"  %1$s_%2$s_CT=0\n"
 
75
"else\n"
 
76
"  %1$s_%2$s_CT=1\n"
 
77
"  %1$s_%2$s_1=\"${%1$s_%2$s}\"\n"
 
78
"fi\n"
 
79
"export %1$s_%2$s_CT";
 
80
 
 
81
tSCC zSingleDef[] = "\n"
 
82
"%1$s_%2$s=\"${%1$s_%2$s-'%3$s'}\"\n"
 
83
"%1$s_%2$s_set=false\n"
 
84
"export %1$s_%2$s\n";
 
85
 
 
86
tSCC zSingleNoDef[] = "\n"
 
87
"%1$s_%2$s=\"${%1$s_%2$s}\"\n"
 
88
"%1$s_%2$s_set=false\n"
 
89
"export %1$s_%2$s\n";
 
90
 
 
91
/* * * * * * * * * * * * * * * * * * * * *
 
92
 *
 
93
 *  LOOP START
 
94
 *
 
95
 *  The loop may run in either of two modes:
 
96
 *  all options are named options (loop only)
 
97
 *  regular, marked option processing.
 
98
 */
 
99
tSCC zLoopCase[] = "\n"
 
100
"OPT_PROCESS=true\n"
 
101
"OPT_ARG=\"$1\"\n\n"
 
102
"while ${OPT_PROCESS} && [ $# -gt 0 ]\ndo\n"
 
103
"    OPT_ELEMENT=''\n"
 
104
"    OPT_ARG_VAL=''\n\n"
 
105
     /*
 
106
      *  'OPT_ARG' may or may not match the current $1
 
107
      */
 
108
"    case \"${OPT_ARG}\" in\n"
 
109
"    -- )\n"
 
110
"        OPT_PROCESS=false\n"
 
111
"        shift\n"
 
112
"        ;;\n\n";
 
113
 
 
114
tSCC zLoopOnly[] = "\n"
 
115
"OPT_ARG=\"$1\"\n\n"
 
116
"while [ $# -gt 0 ]\ndo\n"
 
117
"    OPT_ELEMENT=''\n"
 
118
"    OPT_ARG_VAL=''\n\n"
 
119
"    OPT_ARG=\"${1}\"\n";
 
120
 
 
121
/* * * * * * * * * * * * * * * *
 
122
 *
 
123
 *  CASE SELECTORS
 
124
 *
 
125
 *  If the loop runs as a regular option loop,
 
126
 *  then we must have selectors for each acceptable option
 
127
 *  type (long option, flag character and non-option)
 
128
 */
 
129
tSCC zLongSelection[] =
 
130
"    --* )\n";
 
131
 
 
132
tSCC zFlagSelection[] =
 
133
"    -* )\n";
 
134
 
 
135
tSCC zEndSelection[] =
 
136
"        ;;\n\n";
 
137
 
 
138
tSCC zNoSelection[] =
 
139
"    * )\n"
 
140
"         OPT_PROCESS=false\n"
 
141
"         ;;\n"
 
142
"    esac\n\n";
 
143
 
 
144
/* * * * * * * * * * * * * * * *
 
145
 *
 
146
 *  LOOP END
 
147
 */
 
148
tSCC zLoopEnd[] =
 
149
"    if [ -n \"${OPT_ARG_VAL}\" ]\n"
 
150
"    then\n"
 
151
"        eval %1$s_${OPT_NAME}${OPT_ELEMENT}=\"'${OPT_ARG_VAL}'\"\n"
 
152
"        export %1$s_${OPT_NAME}${OPT_ELEMENT}\n"
 
153
"    fi\n"
 
154
"done\n\n"
 
155
"unset OPT_PROCESS || :\n"
 
156
"unset OPT_ELEMENT || :\n"
 
157
"unset OPT_ARG || :\n"
 
158
"unset OPT_ARG_NEEDED || :\n"
 
159
"unset OPT_NAME || :\n"
 
160
"unset OPT_CODE || :\n"
 
161
"unset OPT_ARG_VAL || :\n%2$s";
 
162
 
 
163
tSCC zTrailerMarker[] = "\n"
 
164
"# # # # # # # # # #\n#\n"
 
165
"#  END OF AUTOMATED OPTION PROCESSING\n"
 
166
"#\n# # # # # # # # # # -- do not modify this marker --\n";
 
167
 
 
168
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
 
169
 *
 
170
 *  OPTION SELECTION
 
171
 */
 
172
tSCC zOptionCase[] =
 
173
"        case \"${OPT_CODE}\" in\n";
 
174
 
 
175
tSCC zOptionPartName[] =
 
176
"        '%s' | \\\n";
 
177
 
 
178
tSCC zOptionFullName[] =
 
179
"        '%s' )\n";
 
180
 
 
181
tSCC zOptionFlag[] =
 
182
"        '%c' )\n";
 
183
 
 
184
tSCC zOptionEndSelect[] =
 
185
"            ;;\n\n";
 
186
 
 
187
tSCC zOptionUnknown[] =
 
188
"        * )\n"
 
189
"            echo Unknown %s: \"${OPT_CODE}\" >&2\n"
 
190
"            echo \"$%s_USAGE_TEXT\"\n"
 
191
"            exit 1\n"
 
192
"            ;;\n"
 
193
"        esac\n\n";
 
194
 
 
195
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
 
196
 *
 
197
 *  OPTION PROCESSING
 
198
 *
 
199
 *  Formats for emitting the text for handling particular options
 
200
 */
 
201
tSCC zTextExit[] =
 
202
"            echo \"$%s_%s_TEXT\"\n"
 
203
"            exit 0\n";
 
204
 
 
205
tSCC zPagedUsageExit[] =
 
206
"            echo \"$%s_LONGUSAGE_TEXT\" | ${PAGER-more}\n"
 
207
"            exit 0\n";
 
208
 
 
209
tSCC zCmdFmt[] =
 
210
"            %s\n";
 
211
 
 
212
tSCC zCountTest[] =
 
213
"            if [ $%1$s_%2$s_CT -ge %3$d ] ; then\n"
 
214
"                echo Error:  more than %3$d %2$s options >&2\n"
 
215
"                echo \"$%1$s_USAGE_TEXT\"\n"
 
216
"                exit 1 ; fi\n";
 
217
 
 
218
tSCC zMultiArg[] =
 
219
"            %1$s_%2$s_CT=`expr ${%1$s_%2$s_CT} + 1`\n"
 
220
"            OPT_ELEMENT=\"_${%1$s_%2$s_CT}\"\n"
 
221
"            OPT_NAME='%2$s'\n";
 
222
 
 
223
tSCC zSingleArg[] =
 
224
"            if [ -n \"${%1$s_%2$s}\" ] && ${%1$s_%2$s_set} ; then\n"
 
225
"                echo Error:  duplicate %2$s option >&2\n"
 
226
"                echo \"$%1$s_USAGE_TEXT\"\n"
 
227
"                exit 1 ; fi\n"
 
228
"            %1$s_%2$s_set=true\n"
 
229
"            OPT_NAME='%2$s'\n";
 
230
 
 
231
tSCC zNoMultiArg[] =
 
232
"            %1$s_%2$s_CT=0\n"
 
233
"            OPT_ELEMENT=''\n"
 
234
"            %1$s_%2$s='%3$s'\n"
 
235
"            export %1$s_%2$s\n"
 
236
"            OPT_NAME='%2$s'\n";
 
237
 
 
238
tSCC zNoSingleArg[] =
 
239
"            if [ -n \"${%1$s_%2$s}\" ] && ${%1$s_%2$s_set} ; then\n"
 
240
"                echo Error:  duplicate %2$s option >&2\n"
 
241
"                echo \"$%1$s_USAGE_TEXT\"\n"
 
242
"                exit 1 ; fi\n"
 
243
"            %1$s_%2$s_set=true\n"
 
244
"            %1$s_%2$s='%3$s'\n"
 
245
"            export %1$s_%2$s\n"
 
246
"            OPT_NAME='%2$s'\n";
 
247
 
 
248
tSCC zMayArg[]  =
 
249
"            eval %1$s_%2$s${OPT_ELEMENT}=true\n"
 
250
"            export %1$s_%2$s${OPT_ELEMENT}\n"
 
251
"            OPT_ARG_NEEDED=OK\n";
 
252
 
 
253
tSCC zMustArg[] =
 
254
"            OPT_ARG_NEEDED=YES\n";
 
255
 
 
256
tSCC zCantArg[] =
 
257
"            eval %1$s_%2$s${OPT_ELEMENT}=true\n"
 
258
"            export %1$s_%2$s${OPT_ELEMENT}\n"
 
259
"            OPT_ARG_NEEDED=NO\n";
 
260
 
 
261
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
 
262
 *
 
263
 *  LONG OPTION PROCESSING
 
264
 *
 
265
 *  Formats for emitting the text for handling long option types
 
266
 */
 
267
tSCC zLongOptInit[] =
 
268
"        OPT_CODE=`echo \"X${OPT_ARG}\"|sed 's/^X-*//'`\n"
 
269
"        shift\n"
 
270
"        OPT_ARG=\"$1\"\n\n"
 
271
"        case \"${OPT_CODE}\" in *=* )\n"
 
272
"            OPT_ARG_VAL=`echo \"${OPT_CODE}\"|sed 's/^[^=]*=//'`\n"
 
273
"            OPT_CODE=`echo \"${OPT_CODE}\"|sed 's/=.*$//'` ;; esac\n\n";
 
274
 
 
275
tSCC zLongOptArg[] =
 
276
"        case \"${OPT_ARG_NEEDED}\" in\n"
 
277
"        NO )\n"
 
278
"            OPT_ARG_VAL=''\n"
 
279
"            ;;\n\n"
 
280
"        YES )\n"
 
281
"            if [ -z \"${OPT_ARG_VAL}\" ]\n"
 
282
"            then\n"
 
283
"                if [ $# -eq 0 ]\n"
 
284
"                then\n"
 
285
"                    echo No argument provided for ${OPT_NAME} option >&2\n"
 
286
"                    echo \"$%s_USAGE_TEXT\"\n"
 
287
"                    exit 1\n"
 
288
"                fi\n\n"
 
289
"                OPT_ARG_VAL=\"${OPT_ARG}\"\n"
 
290
"                shift\n"
 
291
"                OPT_ARG=\"$1\"\n"
 
292
"            fi\n"
 
293
"            ;;\n\n"
 
294
"        OK )\n"
 
295
"            if [ -z \"${OPT_ARG_VAL}\" ] && [ $# -gt 0 ]\n"
 
296
"            then\n"
 
297
"                case \"${OPT_ARG}\" in -* ) ;; * )\n"
 
298
"                    OPT_ARG_VAL=\"${OPT_ARG}\"\n"
 
299
"                    shift\n"
 
300
"                    OPT_ARG=\"$1\" ;; esac\n"
 
301
"            fi\n"
 
302
"            ;;\n"
 
303
"        esac\n";
 
304
 
 
305
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
 
306
 *
 
307
 *  FLAG OPTION PROCESSING
 
308
 *
 
309
 *  Formats for emitting the text for handling flag option types
 
310
 */
 
311
tSCC zFlagOptInit[] =
 
312
"        OPT_CODE=`echo \"X${OPT_ARG}\" | sed 's/X-\\(.\\).*/\\1/'`\n"
 
313
"        OPT_ARG=` echo \"X${OPT_ARG}\" | sed 's/X-.//'`\n\n";
 
314
 
 
315
tSCC zFlagOptArg[] =
 
316
"        case \"${OPT_ARG_NEEDED}\" in\n"
 
317
"        NO )\n"
 
318
"            if [ -n \"${OPT_ARG}\" ]\n"
 
319
"            then\n"
 
320
"                OPT_ARG=-\"${OPT_ARG}\"\n"
 
321
"            else\n"
 
322
"                shift\n"
 
323
"                OPT_ARG=\"$1\"\n"
 
324
"            fi\n"
 
325
"            ;;\n\n"
 
326
"        YES )\n"
 
327
"            if [ -n \"${OPT_ARG}\" ]\n"
 
328
"            then\n"
 
329
"                OPT_ARG_VAL=\"${OPT_ARG}\"\n\n"
 
330
"            else\n"
 
331
"                if [ $# -eq 0 ]\n"
 
332
"                then\n"
 
333
"                    echo No argument provided for ${OPT_NAME} option >&2\n"
 
334
"                    echo \"$%s_USAGE_TEXT\"\n"
 
335
"                    exit 1\n"
 
336
"                fi\n"
 
337
"                shift\n"
 
338
"                OPT_ARG_VAL=\"$1\"\n"
 
339
"            fi\n\n"
 
340
"            shift\n"
 
341
"            OPT_ARG=\"$1\"\n"
 
342
"            ;;\n\n"
 
343
"        OK )\n"
 
344
"            if [ -n \"${OPT_ARG}\" ]\n"
 
345
"            then\n"
 
346
"                OPT_ARG_VAL=\"${OPT_ARG}\"\n"
 
347
"                shift\n"
 
348
"                OPT_ARG=\"$1\"\n\n"
 
349
"            else\n"
 
350
"                shift\n"
 
351
"                if [ $# -gt 0 ]\n"
 
352
"                then\n"
 
353
"                    case \"$1\" in -* ) ;; * )\n"
 
354
"                        OPT_ARG_VAL=\"$1\"\n"
 
355
"                        shift ;; esac\n"
 
356
"                    OPT_ARG=\"$1\"\n"
 
357
"                fi\n"
 
358
"            fi\n"
 
359
"            ;;\n"
 
360
"        esac\n";
 
361
 
 
362
tSCC* pzShell = NULL;
 
363
static char*  pzLeader  = NULL;
 
364
static char*  pzTrailer = NULL;
 
365
 
 
366
/* = = = START-STATIC-FORWARD = = = */
 
367
/* static forward declarations maintained by :mkfwd */
 
368
static void
 
369
textToVariable( tOptions* pOpts, teTextTo whichVar, tOptDesc* pOD );
 
370
 
 
371
static void
 
372
emitUsage( tOptions* pOpts );
 
373
 
 
374
static void
 
375
emitSetup( tOptions* pOpts );
 
376
 
 
377
static void
 
378
printOptionAction( tOptions* pOpts, tOptDesc* pOptDesc );
 
379
 
 
380
static void
 
381
printOptionInaction( tOptions* pOpts, tOptDesc* pOptDesc );
 
382
 
 
383
static void
 
384
emitFlag( tOptions* pOpts );
 
385
 
 
386
static void
 
387
emitMatchExpr( tCC* pzMatchName, tOptDesc* pCurOpt, tOptions* pOpts );
 
388
 
 
389
static void
 
390
emitLong( tOptions* pOpts );
 
391
 
 
392
static void
 
393
openOutput( char const* pzFile );
 
394
/* = = = END-STATIC-FORWARD = = = */
 
395
 
 
396
/*=export_func  optionParseShell
 
397
 * private:
 
398
 *
 
399
 * what:  Decipher a boolean value
 
400
 * arg:   + tOptions* + pOpts    + program options descriptor +
 
401
 *
 
402
 * doc:
 
403
 *  Emit a shell script that will parse the command line options.
 
404
=*/
 
405
void
 
406
optionParseShell( tOptions* pOpts )
 
407
{
 
408
    /*
 
409
     *  Check for our SHELL option now.
 
410
     *  IF the output file contains the "#!" magic marker,
 
411
     *  it will override anything we do here.
 
412
     */
 
413
    if (HAVE_OPT( SHELL ))
 
414
        pzShell = OPT_ARG( SHELL );
 
415
 
 
416
    else if (! ENABLED_OPT( SHELL ))
 
417
        pzShell = NULL;
 
418
 
 
419
    else if ((pzShell = getenv( "SHELL" )),
 
420
             pzShell == NULL)
 
421
 
 
422
        pzShell = "/bin/sh";
 
423
 
 
424
    /*
 
425
     *  Check for a specified output file
 
426
     */
 
427
    if (HAVE_OPT( SCRIPT ))
 
428
        openOutput( OPT_ARG( SCRIPT ));
 
429
 
 
430
    emitUsage( pOpts );
 
431
    emitSetup( pOpts );
 
432
 
 
433
    /*
 
434
     *  There are four modes of option processing.
 
435
     */
 
436
    switch (pOpts->fOptSet & (OPTPROC_LONGOPT|OPTPROC_SHORTOPT)) {
 
437
    case OPTPROC_LONGOPT:
 
438
        fputs( zLoopCase,        stdout );
 
439
 
 
440
        fputs( zLongSelection,   stdout );
 
441
        fputs( zLongOptInit,     stdout );
 
442
        emitLong( pOpts );
 
443
        printf( zLongOptArg,     pOpts->pzPROGNAME );
 
444
        fputs( zEndSelection,    stdout );
 
445
 
 
446
        fputs( zNoSelection,     stdout );
 
447
        break;
 
448
 
 
449
    case 0:
 
450
        fputs( zLoopOnly,        stdout );
 
451
        fputs( zLongOptInit,     stdout );
 
452
        emitLong( pOpts );
 
453
        printf( zLongOptArg,     pOpts->pzPROGNAME );
 
454
        break;
 
455
 
 
456
    case OPTPROC_SHORTOPT:
 
457
        fputs( zLoopCase,        stdout );
 
458
 
 
459
        fputs( zFlagSelection,   stdout );
 
460
        fputs( zFlagOptInit,     stdout );
 
461
        emitFlag( pOpts );
 
462
        printf( zFlagOptArg,     pOpts->pzPROGNAME );
 
463
        fputs( zEndSelection,    stdout );
 
464
 
 
465
        fputs( zNoSelection,     stdout );
 
466
        break;
 
467
 
 
468
    case OPTPROC_LONGOPT|OPTPROC_SHORTOPT:
 
469
        fputs( zLoopCase,        stdout );
 
470
 
 
471
        fputs( zLongSelection,   stdout );
 
472
        fputs( zLongOptInit,     stdout );
 
473
        emitLong( pOpts );
 
474
        printf( zLongOptArg,     pOpts->pzPROGNAME );
 
475
        fputs( zEndSelection,    stdout );
 
476
 
 
477
        fputs( zFlagSelection,   stdout );
 
478
        fputs( zFlagOptInit,     stdout );
 
479
        emitFlag( pOpts );
 
480
        printf( zFlagOptArg,     pOpts->pzPROGNAME );
 
481
        fputs( zEndSelection,    stdout );
 
482
 
 
483
        fputs( zNoSelection,     stdout );
 
484
        break;
 
485
    }
 
486
 
 
487
    printf( zLoopEnd, pOpts->pzPROGNAME, zTrailerMarker );
 
488
    if ((pzTrailer != NULL) && (*pzTrailer != '\0'))
 
489
        fputs( pzTrailer, stdout );
 
490
    else if (ENABLED_OPT( SHELL ))
 
491
        printf( "\nenv | egrep %s_\n", pOpts->pzPROGNAME );
 
492
 
 
493
    fflush( stdout );
 
494
    fchmod( STDOUT_FILENO, 0755 );
 
495
    fclose( stdout );
 
496
}
 
497
 
 
498
 
 
499
static void
 
500
textToVariable( tOptions* pOpts, teTextTo whichVar, tOptDesc* pOD )
 
501
{
 
502
#   define _TT_(n) tSCC z ## n [] = #n;
 
503
    TEXTTO_TABLE
 
504
#   undef _TT_
 
505
#   define _TT_(n) z ## n ,
 
506
      static char const*  apzTTNames[] = { TEXTTO_TABLE };
 
507
#   undef _TT_
 
508
 
 
509
#if defined(__windows__) && !defined(__CYGWIN__)
 
510
    printf( "%1$s_%2$s_TEXT='no %2$s text'\n",
 
511
            pOpts->pzPROGNAME, apzTTNames[ whichVar ]);
 
512
#else
 
513
    int  nlHoldCt = 0;
 
514
    int  pipeFd[2];
 
515
    FILE* fp;
 
516
 
 
517
    printf( "%s_%s_TEXT='", pOpts->pzPROGNAME, apzTTNames[ whichVar ]);
 
518
    fflush( stdout );
 
519
 
 
520
    if (pipe( pipeFd ) != 0) {
 
521
        fprintf( stderr, zBadPipe, errno, strerror( errno ));
 
522
        exit( EXIT_FAILURE );
 
523
    }
 
524
 
 
525
    switch (fork()) {
 
526
    case -1:
 
527
        fprintf( stderr, zForkFail, errno, strerror(errno), pOpts->pzProgName);
 
528
        exit( EXIT_FAILURE );
 
529
        break;
 
530
 
 
531
    case 0:
 
532
        dup2( pipeFd[1], STDERR_FILENO );
 
533
        dup2( pipeFd[1], STDOUT_FILENO );
 
534
        close( pipeFd[0] );
 
535
 
 
536
        switch (whichVar) {
 
537
        case TT_LONGUSAGE:
 
538
            (*(pOpts->pUsageProc))( pOpts, EXIT_SUCCESS );
 
539
            /* NOTREACHED */
 
540
            exit( EXIT_FAILURE );
 
541
 
 
542
        case TT_USAGE:
 
543
            (*(pOpts->pUsageProc))( pOpts, EXIT_FAILURE );
 
544
            /* NOTREACHED */
 
545
            exit( EXIT_FAILURE );
 
546
 
 
547
        case TT_VERSION:
 
548
            pOD->optArg.argString = "c";
 
549
            optionPrintVersion( pOpts, pOD );
 
550
            /* NOTREACHED */
 
551
 
 
552
        default:
 
553
            exit( EXIT_FAILURE );
 
554
        }
 
555
 
 
556
    default:
 
557
        close( pipeFd[1] );
 
558
        fp = fdopen( pipeFd[0], "r" FOPEN_BINARY_FLAG );
 
559
    }
 
560
 
 
561
    for (;;) {
 
562
        int  ch = fgetc( fp );
 
563
        switch (ch) {
 
564
 
 
565
        case '\n':
 
566
            nlHoldCt++;
 
567
            break;
 
568
 
 
569
        case '\'':
 
570
            while (nlHoldCt > 0) {
 
571
                fputc( '\n', stdout );
 
572
                nlHoldCt--;
 
573
            }
 
574
            fputs( "'\\''", stdout );
 
575
            break;
 
576
 
 
577
        case EOF:
 
578
            goto endCharLoop;
 
579
 
 
580
        default:
 
581
            while (nlHoldCt > 0) {
 
582
                fputc( '\n', stdout );
 
583
                nlHoldCt--;
 
584
            }
 
585
            fputc( ch, stdout );
 
586
            break;
 
587
        }
 
588
    } endCharLoop:;
 
589
 
 
590
    fputs( "'\n\n", stdout );
 
591
    close( pipeFd[0] );
 
592
#endif
 
593
}
 
594
 
 
595
 
 
596
static void
 
597
emitUsage( tOptions* pOpts )
 
598
{
 
599
    char     zTimeBuf[ AO_NAME_SIZE ];
 
600
 
 
601
    /*
 
602
     *  First, switch stdout to the output file name.
 
603
     *  Then, change the program name to the one defined
 
604
     *  by the definitions (rather than the current
 
605
     *  executable name).  Down case the upper cased name.
 
606
     */
 
607
    if (pzLeader != NULL)
 
608
        fputs( pzLeader, stdout );
 
609
 
 
610
    {
 
611
        tSCC    zStdout[] = "stdout";
 
612
        tCC*    pzOutName;
 
613
 
 
614
        {
 
615
            time_t    curTime = time( NULL );
 
616
            struct tm*  pTime = localtime( &curTime );
 
617
            strftime( zTimeBuf, AO_NAME_SIZE, "%A %B %e, %Y at %r %Z", pTime );
 
618
        }
 
619
 
 
620
        if (HAVE_OPT( SCRIPT ))
 
621
             pzOutName = OPT_ARG( SCRIPT );
 
622
        else pzOutName = zStdout;
 
623
 
 
624
        if ((pzLeader == NULL) && (pzShell != NULL))
 
625
            printf( "#! %s\n", pzShell );
 
626
 
 
627
        printf( zPreamble, zStartMarker, pzOutName, zTimeBuf );
 
628
    }
 
629
 
 
630
    /*
 
631
     *  Get a copy of the original program name in lower case
 
632
     */
 
633
    {
 
634
        char* pzPN = zTimeBuf;
 
635
        tCC*  pz   = pOpts->pzPROGNAME;
 
636
        for (;;) {
 
637
            if ((*pzPN++ = tolower( *pz++ )) == '\0')
 
638
                break;
 
639
        }
 
640
    }
 
641
 
 
642
    printf( zEndPreamble, pOpts->pzPROGNAME );
 
643
 
 
644
    pOpts->pzProgPath = pOpts->pzProgName = zTimeBuf;
 
645
    textToVariable( pOpts, TT_LONGUSAGE, NULL );
 
646
    textToVariable( pOpts, TT_USAGE,     NULL );
 
647
 
 
648
    {
 
649
        tOptDesc* pOptDesc = pOpts->pOptDesc;
 
650
        int       optionCt = pOpts->optCt;
 
651
 
 
652
        for (;;) {
 
653
            if (pOptDesc->pOptProc == optionPrintVersion) {
 
654
                textToVariable( pOpts, TT_VERSION, pOptDesc );
 
655
                break;
 
656
            }
 
657
 
 
658
            if (--optionCt <= 0)
 
659
                break;
 
660
            pOptDesc++;
 
661
        }
 
662
    }
 
663
}
 
664
 
 
665
 
 
666
static void
 
667
emitSetup( tOptions* pOpts )
 
668
{
 
669
    tOptDesc* pOptDesc = pOpts->pOptDesc;
 
670
    int       optionCt = pOpts->presetOptCt;
 
671
    char const* pzFmt;
 
672
    char const* pzDefault;
 
673
 
 
674
    for (;optionCt > 0; pOptDesc++, --optionCt) {
 
675
        char zVal[16];
 
676
 
 
677
        /*
 
678
         *  Options that are either usage documentation or are compiled out
 
679
         *  are not to be processed.
 
680
         */
 
681
        if (SKIP_OPT(pOptDesc) || (pOptDesc->pz_NAME == NULL))
 
682
            continue;
 
683
 
 
684
        if (pOptDesc->optMaxCt > 1)
 
685
             pzFmt = zMultiDef;
 
686
        else pzFmt = zSingleDef;
 
687
 
 
688
        /*
 
689
         *  IF this is an enumeration/bitmask option, then convert the value
 
690
         *  to a string before printing the default value.
 
691
         */
 
692
        switch (OPTST_GET_ARGTYPE(pOptDesc->fOptState)) {
 
693
        case OPARG_TYPE_ENUMERATION:
 
694
            (*(pOptDesc->pOptProc))( (tOptions*)2UL, pOptDesc );
 
695
            pzDefault = pOptDesc->optArg.argString;
 
696
            break;
 
697
 
 
698
        /*
 
699
         *  Numeric and membership bit options are just printed as a number.
 
700
         */
 
701
        case OPARG_TYPE_NUMERIC:
 
702
            snprintf( zVal, sizeof( zVal ), "%d",
 
703
                      (int)pOptDesc->optArg.argInt );
 
704
            pzDefault = zVal;
 
705
            break;
 
706
 
 
707
        case OPARG_TYPE_MEMBERSHIP:
 
708
            snprintf( zVal, sizeof( zVal ), "%lu",
 
709
                      (unsigned long)pOptDesc->optArg.argIntptr );
 
710
            pzDefault = zVal;
 
711
            break;
 
712
 
 
713
        case OPARG_TYPE_BOOLEAN:
 
714
            pzDefault = (pOptDesc->optArg.argBool) ? "true" : "false";
 
715
            break;
 
716
 
 
717
        default:
 
718
            if (pOptDesc->optArg.argString == NULL) {
 
719
                if (pzFmt == zSingleDef)
 
720
                    pzFmt = zSingleNoDef;
 
721
                pzDefault = NULL;
 
722
            }
 
723
            else
 
724
                pzDefault = pOptDesc->optArg.argString;
 
725
        }
 
726
 
 
727
        printf( pzFmt, pOpts->pzPROGNAME, pOptDesc->pz_NAME, pzDefault );
 
728
    }
 
729
}
 
730
 
 
731
 
 
732
static void
 
733
printOptionAction( tOptions* pOpts, tOptDesc* pOptDesc )
 
734
{
 
735
    if (pOptDesc->pOptProc == optionPrintVersion)
 
736
        printf( zTextExit, pOpts->pzPROGNAME, "VERSION" );
 
737
 
 
738
    else if (pOptDesc->pOptProc == optionPagedUsage)
 
739
        printf( zPagedUsageExit, pOpts->pzPROGNAME );
 
740
 
 
741
    else if (pOptDesc->pOptProc == optionLoadOpt) {
 
742
        printf( zCmdFmt, "echo 'Warning:  Cannot load options files' >&2" );
 
743
        printf( zCmdFmt, "OPT_ARG_NEEDED=YES" );
 
744
 
 
745
    } else if (pOptDesc->pz_NAME == NULL) {
 
746
 
 
747
        if (pOptDesc->pOptProc == NULL) {
 
748
            printf( zCmdFmt, "echo 'Warning:  Cannot save options files' "
 
749
                    ">&2" );
 
750
            printf( zCmdFmt, "OPT_ARG_NEEDED=OK" );
 
751
        } else
 
752
            printf( zTextExit, pOpts->pzPROGNAME, "LONGUSAGE" );
 
753
 
 
754
    } else {
 
755
        if (pOptDesc->optMaxCt == 1)
 
756
            printf( zSingleArg, pOpts->pzPROGNAME, pOptDesc->pz_NAME );
 
757
        else {
 
758
            if ((unsigned)pOptDesc->optMaxCt < NOLIMIT)
 
759
                printf( zCountTest, pOpts->pzPROGNAME,
 
760
                        pOptDesc->pz_NAME, pOptDesc->optMaxCt );
 
761
 
 
762
            printf( zMultiArg, pOpts->pzPROGNAME, pOptDesc->pz_NAME );
 
763
        }
 
764
 
 
765
        /*
 
766
         *  Fix up the args.
 
767
         */
 
768
        if (OPTST_GET_ARGTYPE(pOptDesc->fOptState) == OPARG_TYPE_NONE) {
 
769
            printf( zCantArg, pOpts->pzPROGNAME, pOptDesc->pz_NAME );
 
770
 
 
771
        } else if (pOptDesc->fOptState & OPTST_ARG_OPTIONAL) {
 
772
            printf( zMayArg,  pOpts->pzPROGNAME, pOptDesc->pz_NAME );
 
773
 
 
774
        } else {
 
775
            fputs( zMustArg, stdout );
 
776
        }
 
777
    }
 
778
    fputs( zOptionEndSelect, stdout );
 
779
}
 
780
 
 
781
 
 
782
static void
 
783
printOptionInaction( tOptions* pOpts, tOptDesc* pOptDesc )
 
784
{
 
785
    if (pOptDesc->pOptProc == optionLoadOpt) {
 
786
        printf( zCmdFmt, "echo 'Warning:  Cannot suppress the loading of "
 
787
                "options files' >&2" );
 
788
 
 
789
    } else if (pOptDesc->optMaxCt == 1)
 
790
        printf( zNoSingleArg, pOpts->pzPROGNAME,
 
791
                pOptDesc->pz_NAME, pOptDesc->pz_DisablePfx );
 
792
    else
 
793
        printf( zNoMultiArg, pOpts->pzPROGNAME,
 
794
                pOptDesc->pz_NAME, pOptDesc->pz_DisablePfx );
 
795
 
 
796
    printf( zCmdFmt, "OPT_ARG_NEEDED=NO" );
 
797
    fputs( zOptionEndSelect, stdout );
 
798
}
 
799
 
 
800
 
 
801
static void
 
802
emitFlag( tOptions* pOpts )
 
803
{
 
804
    tOptDesc* pOptDesc = pOpts->pOptDesc;
 
805
    int       optionCt = pOpts->optCt;
 
806
 
 
807
    fputs( zOptionCase, stdout );
 
808
 
 
809
    for (;optionCt > 0; pOptDesc++, --optionCt) {
 
810
 
 
811
        if (SKIP_OPT(pOptDesc))
 
812
            continue;
 
813
 
 
814
        if (isprint( pOptDesc->optValue )) {
 
815
            printf( zOptionFlag, pOptDesc->optValue );
 
816
            printOptionAction( pOpts, pOptDesc );
 
817
        }
 
818
    }
 
819
    printf( zOptionUnknown, "flag", pOpts->pzPROGNAME );
 
820
}
 
821
 
 
822
 
 
823
/*
 
824
 *  Emit the match text for a long option
 
825
 */
 
826
static void
 
827
emitMatchExpr( tCC* pzMatchName, tOptDesc* pCurOpt, tOptions* pOpts )
 
828
{
 
829
    tOptDesc* pOD = pOpts->pOptDesc;
 
830
    int       oCt = pOpts->optCt;
 
831
    int       min = 1;
 
832
    char      zName[ 256 ];
 
833
    char*     pz  = zName;
 
834
 
 
835
    for (;;) {
 
836
        int matchCt = 0;
 
837
 
 
838
        /*
 
839
         *  Omit the current option, Documentation opts and compiled out opts.
 
840
         */
 
841
        if ((pOD == pCurOpt) || SKIP_OPT(pOD)){
 
842
            if (--oCt <= 0)
 
843
                break;
 
844
            pOD++;
 
845
            continue;
 
846
        }
 
847
 
 
848
        /*
 
849
         *  Check each character of the name case insensitively.
 
850
         *  They must not be the same.  They cannot be, because it would
 
851
         *  not compile correctly if they were.
 
852
         */
 
853
        while (  toupper( pOD->pz_Name[matchCt] )
 
854
              == toupper( pzMatchName[matchCt] ))
 
855
            matchCt++;
 
856
 
 
857
        if (matchCt > min)
 
858
            min = matchCt;
 
859
 
 
860
        /*
 
861
         *  Check the disablement name, too.
 
862
         */
 
863
        if (pOD->pz_DisableName != NULL) {
 
864
            matchCt = 0;
 
865
            while (  toupper( pOD->pz_DisableName[matchCt] )
 
866
                  == toupper( pzMatchName[matchCt] ))
 
867
                matchCt++;
 
868
            if (matchCt > min)
 
869
                min = matchCt;
 
870
        }
 
871
        if (--oCt <= 0)
 
872
            break;
 
873
        pOD++;
 
874
    }
 
875
 
 
876
    /*
 
877
     *  IF the 'min' is all or one short of the name length,
 
878
     *  THEN the entire string must be matched.
 
879
     */
 
880
    if (  (pzMatchName[min  ] == NUL)
 
881
       || (pzMatchName[min+1] == NUL) )
 
882
        printf( zOptionFullName, pzMatchName );
 
883
 
 
884
    else {
 
885
        int matchCt = 0;
 
886
        for (; matchCt <= min; matchCt++)
 
887
            *pz++ = pzMatchName[matchCt];
 
888
 
 
889
        for (;;) {
 
890
            *pz = NUL;
 
891
            printf( zOptionPartName, zName );
 
892
            *pz++ = pzMatchName[matchCt++];
 
893
            if (pzMatchName[matchCt] == NUL) {
 
894
                *pz = NUL;
 
895
                printf( zOptionFullName, zName );
 
896
                break;
 
897
            }
 
898
        }
 
899
    }
 
900
}
 
901
 
 
902
 
 
903
/*
 
904
 *  Emit GNU-standard long option handling code
 
905
 */
 
906
static void
 
907
emitLong( tOptions* pOpts )
 
908
{
 
909
    tOptDesc* pOD = pOpts->pOptDesc;
 
910
    int       ct  = pOpts->optCt;
 
911
 
 
912
    fputs( zOptionCase, stdout );
 
913
 
 
914
    /*
 
915
     *  do each option, ...
 
916
     */
 
917
    do  {
 
918
        /*
 
919
         *  Documentation & compiled-out options
 
920
         */
 
921
        if (SKIP_OPT(pOD))
 
922
            continue;
 
923
 
 
924
        emitMatchExpr( pOD->pz_Name, pOD, pOpts );
 
925
        printOptionAction( pOpts, pOD );
 
926
 
 
927
        /*
 
928
         *  Now, do the same thing for the disablement version of the option.
 
929
         */
 
930
        if (pOD->pz_DisableName != NULL) {
 
931
            emitMatchExpr( pOD->pz_DisableName, pOD, pOpts );
 
932
            printOptionInaction( pOpts, pOD );
 
933
        }
 
934
    } while (pOD++, --ct > 0);
 
935
 
 
936
    printf( zOptionUnknown, "option", pOpts->pzPROGNAME );
 
937
}
 
938
 
 
939
 
 
940
static void
 
941
openOutput( char const* pzFile )
 
942
{
 
943
    FILE* fp;
 
944
    char* pzData = NULL;
 
945
    struct stat stbf;
 
946
 
 
947
    do  {
 
948
        char*    pzScan;
 
949
        uint32_t sizeLeft;
 
950
 
 
951
        /*
 
952
         *  IF we cannot stat the file,
 
953
         *  THEN assume we are creating a new file.
 
954
         *       Skip the loading of the old data.
 
955
         */
 
956
        if (stat( pzFile, &stbf ) != 0)
 
957
            break;
 
958
 
 
959
        /*
 
960
         *  The file must be a regular file
 
961
         */
 
962
        if (! S_ISREG( stbf.st_mode )) {
 
963
            fprintf( stderr, zNotFile, pzFile );
 
964
            exit( EXIT_FAILURE );
 
965
        }
 
966
 
 
967
        pzData = (char*)malloc( (unsigned)(stbf.st_size + 1) );
 
968
        fp = fopen( pzFile, "r" FOPEN_BINARY_FLAG );
 
969
 
 
970
        sizeLeft = (unsigned)stbf.st_size;
 
971
        pzScan   = pzData;
 
972
 
 
973
        /*
 
974
         *  Read in all the data as fast as our OS will let us.
 
975
         */
 
976
        for (;;) {
 
977
            int inct = fread( (void*)pzScan, 1, sizeLeft, fp );
 
978
            if (inct == 0)
 
979
                break;
 
980
 
 
981
            pzScan   += inct;
 
982
            sizeLeft -= inct;
 
983
 
 
984
            if (sizeLeft == 0)
 
985
                break;
 
986
        }
 
987
 
 
988
        /*
 
989
         *  NUL-terminate the leader and look for the trailer
 
990
         */
 
991
        *pzScan = '\0';
 
992
        fclose( fp );
 
993
        pzScan  = strstr( pzData, zStartMarker );
 
994
        if (pzScan == NULL) {
 
995
            pzTrailer = pzData;
 
996
            break;
 
997
        }
 
998
 
 
999
        *(pzScan++) = NUL;
 
1000
        pzScan  = strstr( pzScan, zTrailerMarker );
 
1001
        if (pzScan == NULL) {
 
1002
            pzTrailer = pzData;
 
1003
            break;
 
1004
        }
 
1005
 
 
1006
        /*
 
1007
         *  Check to see if the data contains
 
1008
         *  our marker.  If it does, then we will skip over it
 
1009
         */
 
1010
        pzTrailer = pzScan + sizeof( zTrailerMarker ) - 1;
 
1011
        pzLeader  = pzData;
 
1012
    } while (AG_FALSE);
 
1013
 
 
1014
    freopen( pzFile, "w" FOPEN_BINARY_FLAG, stdout );
 
1015
}
 
1016
 
 
1017
 
 
1018
/*=export_func genshelloptUsage
 
1019
 * private:
 
1020
 * what: The usage function for the genshellopt generated program
 
1021
 *
 
1022
 * arg:  + tOptions* + pOpts    + program options descriptor +
 
1023
 * arg:  + int       + exitCode + usage text type to produce +
 
1024
 *
 
1025
 * doc:
 
1026
 *  This function is used to create the usage strings for the option
 
1027
 *  processing shell script code.  Two child processes are spawned
 
1028
 *  each emitting the usage text in either the short (error exit)
 
1029
 *  style or the long style.  The generated program will capture this
 
1030
 *  and create shell script variables containing the two types of text.
 
1031
=*/
 
1032
void
 
1033
genshelloptUsage( tOptions*  pOpts, int exitCode )
 
1034
{
 
1035
#if defined(__windows__) && !defined(__CYGWIN__)
 
1036
    optionUsage( pOpts, exitCode );
 
1037
#else
 
1038
    /*
 
1039
     *  IF not EXIT_SUCCESS,
 
1040
     *  THEN emit the short form of usage.
 
1041
     */
 
1042
    if (exitCode != EXIT_SUCCESS)
 
1043
        optionUsage( pOpts, exitCode );
 
1044
    fflush( stderr );
 
1045
    fflush( stdout );
 
1046
 
 
1047
    option_usage_fp = stdout;
 
1048
 
 
1049
    /*
 
1050
     *  First, print our usage
 
1051
     */
 
1052
    switch (fork()) {
 
1053
    case -1:
 
1054
        optionUsage( pOpts, EXIT_FAILURE );
 
1055
        /*NOTREACHED*/
 
1056
        _exit( EXIT_FAILURE );
 
1057
 
 
1058
    case 0:
 
1059
        pagerState = PAGER_STATE_CHILD;
 
1060
        optionUsage( pOpts, EXIT_SUCCESS );
 
1061
        /*NOTREACHED*/
 
1062
        _exit( EXIT_FAILURE );
 
1063
 
 
1064
    default:
 
1065
    {
 
1066
        int  sts;
 
1067
        wait( &sts );
 
1068
    }
 
1069
    }
 
1070
 
 
1071
    /*
 
1072
     *  Generate the pzProgName, since optionProcess() normally
 
1073
     *  gets it from the command line
 
1074
     */
 
1075
    {
 
1076
        char* pz;
 
1077
        AGDUPSTR( pz, pShellParseOptions->pzPROGNAME, "program name" );
 
1078
        pShellParseOptions->pzProgName = pz;
 
1079
        while (*pz != NUL) {
 
1080
            *pz = tolower( *pz );
 
1081
            pz++;
 
1082
        }
 
1083
    }
 
1084
 
 
1085
    /*
 
1086
     *  Separate the makeshell usage from the client usage
 
1087
     */
 
1088
    fprintf( option_usage_fp, zGenshell, pShellParseOptions->pzProgName );
 
1089
    fflush( option_usage_fp );
 
1090
 
 
1091
    /*
 
1092
     *  Now, print the client usage.
 
1093
     */
 
1094
    switch (fork()) {
 
1095
    case 0:
 
1096
        pagerState = PAGER_STATE_CHILD;
 
1097
        /*FALLTHROUGH*/
 
1098
    case -1:
 
1099
        optionUsage( pShellParseOptions, EXIT_FAILURE );
 
1100
 
 
1101
    default:
 
1102
    {
 
1103
        int  sts;
 
1104
        wait( &sts );
 
1105
    }
 
1106
    }
 
1107
 
 
1108
    exit( EXIT_SUCCESS );
 
1109
#endif
 
1110
}
 
1111
 
 
1112
/*
 
1113
 * Local Variables:
 
1114
 * mode: C
 
1115
 * c-file-style: "stroustrup"
 
1116
 * indent-tabs-mode: nil
 
1117
 * End:
 
1118
 * end of autoopts/makeshell.c */