]> git.ipfire.org Git - thirdparty/ntp.git/commitdiff
Check in libopts and autgen-generated files
authorHarlan Stenn <stenn@ntp.org>
Fri, 30 Jun 2006 05:03:52 +0000 (01:03 -0400)
committerHarlan Stenn <stenn@ntp.org>
Fri, 30 Jun 2006 05:03:52 +0000 (01:03 -0400)
bk: 44a4b0b8iStIeNHMAiP2OSNmEp2Akg

110 files changed:
bootstrap
clockstuff/clktest-opts.c [new file with mode: 0644]
clockstuff/clktest-opts.h [new file with mode: 0644]
libopts/COPYING.lgpl [new file with mode: 0644]
libopts/COPYING.mbsd [new file with mode: 0644]
libopts/MakeDefs.inc [new file with mode: 0644]
libopts/Makefile.am [new file with mode: 0644]
libopts/README [new file with mode: 0644]
libopts/autoopts.c [new file with mode: 0644]
libopts/autoopts.h [new file with mode: 0644]
libopts/autoopts/options.h [new file with mode: 0644]
libopts/autoopts/usage-txt.h [new file with mode: 0644]
libopts/boolean.c [new file with mode: 0644]
libopts/compat/compat.h [new file with mode: 0644]
libopts/compat/pathfind.c [new file with mode: 0644]
libopts/compat/snprintf.c [new file with mode: 0644]
libopts/compat/strdup.c [new file with mode: 0644]
libopts/configfile.c [new file with mode: 0644]
libopts/cook.c [new file with mode: 0644]
libopts/enumeration.c [new file with mode: 0644]
libopts/environment.c [new file with mode: 0644]
libopts/genshell.c [new file with mode: 0644]
libopts/genshell.h [new file with mode: 0644]
libopts/libopts.c [new file with mode: 0644]
libopts/load.c [new file with mode: 0644]
libopts/m4/libopts.m4 [new file with mode: 0644]
libopts/m4/liboptschk.m4 [new file with mode: 0644]
libopts/makeshell.c [new file with mode: 0644]
libopts/nested.c [new file with mode: 0644]
libopts/numeric.c [new file with mode: 0644]
libopts/pgusage.c [new file with mode: 0644]
libopts/proto.h [new file with mode: 0644]
libopts/putshell.c [new file with mode: 0644]
libopts/restore.c [new file with mode: 0644]
libopts/save.c [new file with mode: 0644]
libopts/sort.c [new file with mode: 0644]
libopts/stack.c [new file with mode: 0644]
libopts/streqvcmp.c [new file with mode: 0644]
libopts/text_mmap.c [new file with mode: 0644]
libopts/tokenize.c [new file with mode: 0644]
libopts/usage.c [new file with mode: 0644]
libopts/version.c [new file with mode: 0644]
ntpd/ntpd-opts.c [new file with mode: 0644]
ntpd/ntpd-opts.h [new file with mode: 0644]
ntpd/ntpd-opts.menu [new file with mode: 0644]
ntpd/ntpd-opts.texi [new file with mode: 0644]
ntpd/ntpd.1 [new file with mode: 0644]
ntpd/ntpdsim-opts.c [new file with mode: 0644]
ntpd/ntpdsim-opts.h [new file with mode: 0644]
ntpd/ntpdsim-opts.menu [new file with mode: 0644]
ntpd/ntpdsim-opts.texi [new file with mode: 0644]
ntpd/ntpdsim.1 [new file with mode: 0644]
ntpdc/ntpdc-opts.c [new file with mode: 0644]
ntpdc/ntpdc-opts.h [new file with mode: 0644]
ntpdc/ntpdc-opts.menu [new file with mode: 0644]
ntpdc/ntpdc-opts.texi [new file with mode: 0644]
ntpdc/ntpdc.1 [new file with mode: 0644]
ntpq/ntpq-opts.c [new file with mode: 0644]
ntpq/ntpq-opts.h [new file with mode: 0644]
ntpq/ntpq-opts.menu [new file with mode: 0644]
ntpq/ntpq-opts.texi [new file with mode: 0644]
ntpq/ntpq.1 [new file with mode: 0644]
sntp/libopts/COPYING.lgpl [new file with mode: 0644]
sntp/libopts/COPYING.mbsd [new file with mode: 0644]
sntp/libopts/MakeDefs.inc [new file with mode: 0644]
sntp/libopts/Makefile.am [new file with mode: 0644]
sntp/libopts/README [new file with mode: 0644]
sntp/libopts/autoopts.c [new file with mode: 0644]
sntp/libopts/autoopts.h [new file with mode: 0644]
sntp/libopts/autoopts/options.h [new file with mode: 0644]
sntp/libopts/autoopts/usage-txt.h [new file with mode: 0644]
sntp/libopts/boolean.c [new file with mode: 0644]
sntp/libopts/compat/compat.h [new file with mode: 0644]
sntp/libopts/compat/pathfind.c [new file with mode: 0644]
sntp/libopts/compat/snprintf.c [new file with mode: 0644]
sntp/libopts/compat/strdup.c [new file with mode: 0644]
sntp/libopts/configfile.c [new file with mode: 0644]
sntp/libopts/cook.c [new file with mode: 0644]
sntp/libopts/enumeration.c [new file with mode: 0644]
sntp/libopts/environment.c [new file with mode: 0644]
sntp/libopts/genshell.c [new file with mode: 0644]
sntp/libopts/genshell.h [new file with mode: 0644]
sntp/libopts/libopts.c [new file with mode: 0644]
sntp/libopts/load.c [new file with mode: 0644]
sntp/libopts/m4/libopts.m4 [new file with mode: 0644]
sntp/libopts/m4/liboptschk.m4 [new file with mode: 0644]
sntp/libopts/makeshell.c [new file with mode: 0644]
sntp/libopts/nested.c [new file with mode: 0644]
sntp/libopts/numeric.c [new file with mode: 0644]
sntp/libopts/pgusage.c [new file with mode: 0644]
sntp/libopts/proto.h [new file with mode: 0644]
sntp/libopts/putshell.c [new file with mode: 0644]
sntp/libopts/restore.c [new file with mode: 0644]
sntp/libopts/save.c [new file with mode: 0644]
sntp/libopts/sort.c [new file with mode: 0644]
sntp/libopts/stack.c [new file with mode: 0644]
sntp/libopts/streqvcmp.c [new file with mode: 0644]
sntp/libopts/text_mmap.c [new file with mode: 0644]
sntp/libopts/tokenize.c [new file with mode: 0644]
sntp/libopts/usage.c [new file with mode: 0644]
sntp/libopts/version.c [new file with mode: 0644]
sntp/sntp-opts.c [new file with mode: 0644]
sntp/sntp-opts.h [new file with mode: 0644]
sntp/sntp-opts.menu [new file with mode: 0644]
sntp/sntp-opts.texi [new file with mode: 0644]
util/ntp-keygen-opts.c [new file with mode: 0644]
util/ntp-keygen-opts.h [new file with mode: 0644]
util/ntp-keygen-opts.menu [new file with mode: 0644]
util/ntp-keygen-opts.texi [new file with mode: 0644]
util/ntp-keygen.1 [new file with mode: 0644]

index eea61c10e5c00c386ba690987f32ebcc14a0de3a..48125525ca0fa5b56dd437c24dc5e76f5f73403c 100755 (executable)
--- a/bootstrap
+++ b/bootstrap
@@ -33,18 +33,19 @@ AUTORECONF=${AUTORECONF:-autoreconf}
 
 scripts/genver
 
-# The copy for ntp...
-rm -rf libopts*
-gunzip -c $(autoopts-config --libsrc) | (
-  tar -xvf -
-  mv libopts-*.*.* libopts )
+# 20060629: HMS: Let's try checking in libopts and the autogen-generated files
+## The copy for ntp...
+#rm -rf libopts*
+#gunzip -c $(autoopts-config --libsrc) | (
+#  tar -xvf -
+#  mv libopts-*.*.* libopts )
 
-# The copy for sntp...
-rm -rf sntp/libopts*
-gunzip -c $(autoopts-config --libsrc) | (
-  cd sntp
-  tar -xvf -
-  mv libopts-*.*.* libopts )
+## The copy for sntp...
+#rm -rf sntp/libopts*
+#gunzip -c $(autoopts-config --libsrc) | (
+#  cd sntp
+#  tar -xvf -
+#  mv libopts-*.*.* libopts )
 
 prog_opt_files=$(
     egrep -l '^prog.name' $(
@@ -52,13 +53,13 @@ prog_opt_files=$(
 
 incdir=${PWD}/include
 
-for f in ${prog_opt_files}
-do
-  ( cd $(dirname ${f})
-    echo "Running autogen on $f..."
-    autogen -L${incdir} $(basename ${f})
-  ) || exit 1
-done
+#for f in ${prog_opt_files}
+#do
+#  ( cd $(dirname ${f})
+#    echo "Running autogen on $f..."
+#    autogen -L${incdir} $(basename ${f})
+#  ) || exit 1
+#done
 
 cp bincheck.mf sntp/
 
diff --git a/clockstuff/clktest-opts.c b/clockstuff/clktest-opts.c
new file mode 100644 (file)
index 0000000..0ba5733
--- /dev/null
@@ -0,0 +1,825 @@
+/*   -*- buffer-read-only: t -*- vi: set ro:
+ *  
+ *  DO NOT EDIT THIS FILE   (clktest-opts.c)
+ *  
+ *  It has been AutoGen-ed  Tuesday June 27, 2006 at 10:16:45 PM EDT
+ *  From the definitions    clktest-opts.def
+ *  and the template file   options
+ */
+#include <stdio.h>
+#include <limits.h>
+#define OPTION_CODE_COMPILE 1
+#include "clktest-opts.h"
+
+#ifdef  __cplusplus
+extern "C" {
+#endif
+tSCC zCopyright[] =
+       "clktest copyright (c) 1970-2006 ntp.org, all rights reserved";
+tSCC zCopyrightNotice[] =
+       
+/* extracted from /backroom/ntp-dev-hms/include/copyright.def near line 8 */
+"see html/copyright.html";
+extern tUsageProc optionUsage;
+
+/*
+ *  global included definitions
+ */
+#ifdef STREAM
+char magic[32] = "";
+#endif
+extern int speed;
+extern int ttflags;
+
+#ifndef NULL
+#  define NULL 0
+#endif
+#ifndef EXIT_SUCCESS
+#  define  EXIT_SUCCESS 0
+#endif
+#ifndef EXIT_FAILURE
+#  define  EXIT_FAILURE 1
+#endif
+/*
+ *  Magic2 option description:
+ */
+#ifdef CLKLDISC
+tSCC    zMagic2Text[] =
+        "The 'kill' character (default: '\\r')";
+tSCC    zMagic2_NAME[]             = "MAGIC2";
+tSCC    zMagic2_Name[]             = "magic2";
+#define MAGIC2_FLAGS       (OPTST_DISABLED \
+       | OPTST_SET_ARGTYPE(OPARG_TYPE_NUMERIC))
+
+#else   /* disable Magic2 */
+#define VALUE_OPT_MAGIC2 NO_EQUIVALENT
+#define MAGIC2_FLAGS       (OPTST_OMITTED | OPTST_NO_INIT)
+#define zMagic2Text       NULL
+#define zMagic2_NAME      NULL
+#define zMagic2_Name      NULL
+#endif  /* CLKLDISC */
+
+/*
+ *  Magic1 option description:
+ */
+#ifdef CLKLDISC
+tSCC    zMagic1Text[] =
+        "The 'erase' character (default: '\\r')";
+tSCC    zMagic1_NAME[]             = "MAGIC1";
+tSCC    zMagic1_Name[]             = "magic1";
+#define MAGIC1_FLAGS       (OPTST_DISABLED \
+       | OPTST_SET_ARGTYPE(OPARG_TYPE_NUMERIC))
+
+#else   /* disable Magic1 */
+#define VALUE_OPT_MAGIC1 NO_EQUIVALENT
+#define MAGIC1_FLAGS       (OPTST_OMITTED | OPTST_NO_INIT)
+#define zMagic1Text       NULL
+#define zMagic1_NAME      NULL
+#define zMagic1_Name      NULL
+#endif  /* CLKLDISC */
+
+/*
+ *  Magic1 option description:
+ */
+#ifdef STREAM
+tSCC    zMagic1Text[] =
+        "Magic characters for streams";
+tSCC    zMagic1_NAME[]             = "MAGIC1";
+tSCC    zMagic1_Name[]             = "magic1";
+#define MAGIC1_FLAGS       (OPTST_DISABLED \
+       | OPTST_SET_ARGTYPE(OPARG_TYPE_STRING))
+
+#else   /* disable Magic1 */
+#define VALUE_OPT_MAGIC1 NO_EQUIVALENT
+#define MAGIC1_FLAGS       (OPTST_OMITTED | OPTST_NO_INIT)
+#define zMagic1Text       NULL
+#define zMagic1_NAME      NULL
+#define zMagic1_Name      NULL
+#endif  /* STREAM */
+
+/*
+ *  Speed option description:
+ */
+tSCC    zSpeedText[] =
+        "Set the rate according to the speed";
+tSCC    zSpeed_NAME[]              = "SPEED";
+tSCC    zSpeed_Name[]              = "speed";
+#define SPEED_FLAGS       (OPTST_DISABLED \
+       | OPTST_SET_ARGTYPE(OPARG_TYPE_STRING))
+
+/*
+ *  Debug option description:
+ */
+tSCC    zDebugText[] =
+        "Turn on debugging output";
+tSCC    zDebug_NAME[]              = "DEBUG";
+tSCC    zDebug_Name[]              = "debug";
+#define DEBUG_FLAGS       (OPTST_DISABLED)
+
+/*
+ *  Crmod option description:
+ */
+tSCC    zCrmodText[] =
+        "Turn on CRMOD flag";
+tSCC    zCrmod_NAME[]              = "CRMOD";
+tSCC    zCrmod_Name[]              = "crmod";
+#define CRMOD_FLAGS       (OPTST_DISABLED)
+
+/*
+ *  Command option description with
+ *  "Must also have options" and "Incompatible options":
+ */
+tSCC    zCommandText[] =
+        "";
+tSCC    zCommand_NAME[]            = "COMMAND";
+tSCC    zCommand_Name[]            = "command";
+static const int
+    aCommandMustList[] = {
+    INDEX_OPT_TIMEOUT, NO_EQUIVALENT };
+#define COMMAND_FLAGS       (OPTST_DISABLED \
+       | OPTST_SET_ARGTYPE(OPARG_TYPE_STRING))
+
+/*
+ *  Timeout option description:
+ */
+tSCC    zTimeoutText[] =
+        "Limit wait for command completion";
+tSCC    zTimeout_NAME[]            = "TIMEOUT";
+tSCC    zTimeout_Name[]            = "timeout";
+#define TIMEOUT_FLAGS       (OPTST_DISABLED \
+       | OPTST_SET_ARGTYPE(OPARG_TYPE_NUMERIC))
+
+/*
+ *  Help/More_Help/Version option descriptions:
+ */
+tSCC zHelpText[]       = "Display usage information and exit";
+tSCC zHelp_Name[]      = "help";
+
+tSCC zMore_HelpText[]  = "Extended usage information passed thru pager";
+tSCC zMore_Help_Name[] = "more-help";
+
+tSCC zVersionText[]    = "Output version information and exit";
+tSCC zVersion_Name[]   = "version";
+
+/*
+ *  Save/Load_Opts option description:
+ */
+tSCC zSave_OptsText[]     = "Save the option state to a config file";
+tSCC zSave_Opts_Name[]    = "save-opts";
+
+tSCC zLoad_OptsText[]     = "Load options from a config file";
+tSCC zLoad_Opts_NAME[]    = "LOAD_OPTS";
+
+tSCC zNotLoad_Opts_Name[] = "no-load-opts";
+tSCC zNotLoad_Opts_Pfx[]  = "no";
+#define zLoad_Opts_Name   (zNotLoad_Opts_Name + 3)
+/*
+ *  Declare option callback procedures
+ */
+#ifndef CLKLDISC
+#define doOptMagic2 doUsageOpt
+#endif
+#ifndef CLKLDISC
+#define doOptMagic1 doUsageOpt
+#endif
+#ifndef STREAM
+#define doOptMagic1 doUsageOpt
+#endif
+/* extracted from optmain.tpl near line 586 */
+
+#if defined(TEST_CLKTEST_OPTS)
+/*
+ *  Under test, omit argument processing, or call optionStackArg,
+ *  if multiple copies are allowed.
+ */
+extern tOptProc
+    optionPagedUsage, optionVersionStderr;
+static tOptProc
+    doOptMagic1, doOptMagic2, doOptTimeout, doUsageOpt;
+
+/*
+ *  #define map the "normal" callout procs to the test ones...
+ */
+#define SPEED_OPT_PROC optionStackArg
+#define CRMOD_OPT_PROC optionStackArg
+
+
+#else /* NOT defined TEST_CLKTEST_OPTS */
+/*
+ *  When not under test, there are different procs to use
+ */
+extern tOptProc
+    optionPagedUsage, optionPrintVersion;
+static tOptProc
+    doOptCrmod,   doOptMagic1,  doOptMagic2,  doOptSpeed,   doOptTimeout,
+    doUsageOpt;
+
+/*
+ *  #define map the "normal" callout procs
+ */
+#define SPEED_OPT_PROC doOptSpeed
+#define CRMOD_OPT_PROC doOptCrmod
+
+#define SPEED_OPT_PROC doOptSpeed
+#define CRMOD_OPT_PROC doOptCrmod
+#endif /* defined(TEST_CLKTEST_OPTS) */
+#ifndef CLKLDISC
+#undef  doOptMagic2
+#define doOptMagic2 NULL
+#endif
+#ifndef CLKLDISC
+#undef  doOptMagic1
+#define doOptMagic1 NULL
+#endif
+#ifndef STREAM
+#undef  doOptMagic1
+#define doOptMagic1 NULL
+#endif
+#ifdef TEST_CLKTEST_OPTS
+# define DOVERPROC optionVersionStderr
+#else
+# define DOVERPROC optionPrintVersion
+#endif /* TEST_CLKTEST_OPTS */
+
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ *
+ *  Define the Clktest Option Descriptions.
+ */
+static tOptDesc optDesc[ OPTION_CT ] = {
+  {  /* entry idx, value */ 0, VALUE_OPT_MAGIC2,
+     /* equiv idx, value */ 0, VALUE_OPT_MAGIC2,
+     /* equivalenced to  */ NO_EQUIVALENT,
+     /* min, max, act ct */ 0, 1, 0,
+     /* opt state flags  */ MAGIC2_FLAGS, 0,
+     /* last opt argumnt */ NULL,
+     /* arg list/cookie  */ NULL,
+     /* must/cannot opts */ NULL, NULL,
+     /* option proc      */ doOptMagic2,
+     /* desc, NAME, name */ zMagic2Text, zMagic2_NAME, zMagic2_Name,
+     /* disablement strs */ NULL, NULL },
+
+  {  /* entry idx, value */ 1, VALUE_OPT_MAGIC1,
+     /* equiv idx, value */ 1, VALUE_OPT_MAGIC1,
+     /* equivalenced to  */ NO_EQUIVALENT,
+     /* min, max, act ct */ 0, 1, 0,
+     /* opt state flags  */ MAGIC1_FLAGS, 0,
+     /* last opt argumnt */ NULL,
+     /* arg list/cookie  */ NULL,
+     /* must/cannot opts */ NULL, NULL,
+     /* option proc      */ doOptMagic1,
+     /* desc, NAME, name */ zMagic1Text, zMagic1_NAME, zMagic1_Name,
+     /* disablement strs */ NULL, NULL },
+
+  {  /* entry idx, value */ 2, VALUE_OPT_MAGIC1,
+     /* equiv idx, value */ 2, VALUE_OPT_MAGIC1,
+     /* equivalenced to  */ NO_EQUIVALENT,
+     /* min, max, act ct */ 0, 1, 0,
+     /* opt state flags  */ MAGIC1_FLAGS, 0,
+     /* last opt argumnt */ NULL,
+     /* arg list/cookie  */ NULL,
+     /* must/cannot opts */ NULL, NULL,
+     /* option proc      */ doOptMagic1,
+     /* desc, NAME, name */ zMagic1Text, zMagic1_NAME, zMagic1_Name,
+     /* disablement strs */ NULL, NULL },
+
+  {  /* entry idx, value */ 3, VALUE_OPT_SPEED,
+     /* equiv idx, value */ 3, VALUE_OPT_SPEED,
+     /* equivalenced to  */ NO_EQUIVALENT,
+     /* min, max, act ct */ 0, 1, 0,
+     /* opt state flags  */ SPEED_FLAGS, 0,
+     /* last opt argumnt */ NULL,
+     /* arg list/cookie  */ NULL,
+     /* must/cannot opts */ NULL, NULL,
+     /* option proc      */ SPEED_OPT_PROC,
+     /* desc, NAME, name */ zSpeedText, zSpeed_NAME, zSpeed_Name,
+     /* disablement strs */ NULL, NULL },
+
+  {  /* entry idx, value */ 4, VALUE_OPT_DEBUG,
+     /* equiv idx, value */ 4, VALUE_OPT_DEBUG,
+     /* equivalenced to  */ NO_EQUIVALENT,
+     /* min, max, act ct */ 0, 1, 0,
+     /* opt state flags  */ DEBUG_FLAGS, 0,
+     /* last opt argumnt */ NULL,
+     /* arg list/cookie  */ NULL,
+     /* must/cannot opts */ NULL, NULL,
+     /* option proc      */ NULL,
+     /* desc, NAME, name */ zDebugText, zDebug_NAME, zDebug_Name,
+     /* disablement strs */ NULL, NULL },
+
+  {  /* entry idx, value */ 5, VALUE_OPT_CRMOD,
+     /* equiv idx, value */ 5, VALUE_OPT_CRMOD,
+     /* equivalenced to  */ NO_EQUIVALENT,
+     /* min, max, act ct */ 0, 1, 0,
+     /* opt state flags  */ CRMOD_FLAGS, 0,
+     /* last opt argumnt */ NULL,
+     /* arg list/cookie  */ NULL,
+     /* must/cannot opts */ NULL, NULL,
+     /* option proc      */ CRMOD_OPT_PROC,
+     /* desc, NAME, name */ zCrmodText, zCrmod_NAME, zCrmod_Name,
+     /* disablement strs */ NULL, NULL },
+
+  {  /* entry idx, value */ 6, VALUE_OPT_COMMAND,
+     /* equiv idx, value */ 6, VALUE_OPT_COMMAND,
+     /* equivalenced to  */ NO_EQUIVALENT,
+     /* min, max, act ct */ 0, 1, 0,
+     /* opt state flags  */ COMMAND_FLAGS, 0,
+     /* last opt argumnt */ NULL,
+     /* arg list/cookie  */ NULL,
+     /* must/cannot opts */ aCommandMustList, NULL,
+     /* option proc      */ NULL,
+     /* desc, NAME, name */ zCommandText, zCommand_NAME, zCommand_Name,
+     /* disablement strs */ NULL, NULL },
+
+  {  /* entry idx, value */ 7, VALUE_OPT_TIMEOUT,
+     /* equiv idx, value */ 7, VALUE_OPT_TIMEOUT,
+     /* equivalenced to  */ NO_EQUIVALENT,
+     /* min, max, act ct */ 0, 1, 0,
+     /* opt state flags  */ TIMEOUT_FLAGS, 0,
+     /* last opt argumnt */ NULL,
+     /* arg list/cookie  */ NULL,
+     /* must/cannot opts */ NULL, NULL,
+     /* option proc      */ doOptTimeout,
+     /* desc, NAME, name */ zTimeoutText, zTimeout_NAME, zTimeout_Name,
+     /* disablement strs */ NULL, NULL },
+
+  {  /* entry idx, value */ INDEX_OPT_VERSION, VALUE_OPT_VERSION,
+     /* equiv idx value  */ NO_EQUIVALENT, 0,
+     /* equivalenced to  */ NO_EQUIVALENT,
+     /* min, max, act ct */ 0, 1, 0,
+     /* opt state flags  */ OPTST_SET_ARGTYPE(OPARG_TYPE_STRING)
+                          | OPTST_ARG_OPTIONAL, 0,
+     /* last opt argumnt */ NULL,
+     /* arg list/cookie  */ NULL,
+     /* must/cannot opts */ NULL, NULL,
+     /* option proc      */ DOVERPROC,
+     /* desc, NAME, name */ zVersionText, NULL, zVersion_Name,
+     /* disablement strs */ NULL, NULL },
+
+  {  /* entry idx, value */ INDEX_OPT_HELP, VALUE_OPT_HELP,
+     /* equiv idx value  */ NO_EQUIVALENT, 0,
+     /* equivalenced to  */ NO_EQUIVALENT,
+     /* min, max, act ct */ 0, 1, 0,
+     /* opt state flags  */ OPTST_IMM, 0,
+     /* last opt argumnt */ NULL,
+     /* arg list/cookie  */ NULL,
+     /* must/cannot opts */ NULL, NULL,
+     /* option proc      */ doUsageOpt,
+     /* desc, NAME, name */ zHelpText, NULL, zHelp_Name,
+     /* disablement strs */ NULL, NULL },
+
+  {  /* entry idx, value */ INDEX_OPT_MORE_HELP, VALUE_OPT_MORE_HELP,
+     /* equiv idx value  */ NO_EQUIVALENT, 0,
+     /* equivalenced to  */ NO_EQUIVALENT,
+     /* min, max, act ct */ 0, 1, 0,
+     /* opt state flags  */ OPTST_IMM, 0,
+     /* last opt argumnt */ NULL,
+     /* arg list/cookie  */ NULL,
+     /* must/cannot opts */ NULL,  NULL,
+     /* option proc      */ optionPagedUsage,
+     /* desc, NAME, name */ zMore_HelpText, NULL, zMore_Help_Name,
+     /* disablement strs */ NULL, NULL },
+
+  {  /* entry idx, value */ INDEX_OPT_SAVE_OPTS, VALUE_OPT_SAVE_OPTS,
+     /* equiv idx value  */ NO_EQUIVALENT, 0,
+     /* equivalenced to  */ NO_EQUIVALENT,
+     /* min, max, act ct */ 0, 1, 0,
+     /* opt state flags  */ OPTST_SET_ARGTYPE(OPARG_TYPE_STRING)
+                          | OPTST_ARG_OPTIONAL, 0,
+     /* last opt argumnt */ NULL,
+     /* arg list/cookie  */ NULL,
+     /* must/cannot opts */ NULL,  NULL,
+     /* option proc      */ NULL,
+     /* desc, NAME, name */ zSave_OptsText, NULL, zSave_Opts_Name,
+     /* disablement strs */ NULL, NULL },
+
+  {  /* entry idx, value */ INDEX_OPT_LOAD_OPTS, VALUE_OPT_LOAD_OPTS,
+     /* equiv idx value  */ NO_EQUIVALENT, 0,
+     /* equivalenced to  */ NO_EQUIVALENT,
+     /* min, max, act ct */ 0, NOLIMIT, 0,
+     /* opt state flags  */ OPTST_DISABLE_IMM | \
+                       OPTST_SET_ARGTYPE(OPARG_TYPE_STRING), 0,
+     /* last opt argumnt */ NULL,
+     /* arg list/cookie  */ NULL,
+     /* must/cannot opts */ NULL, NULL,
+     /* option proc      */ optionLoadOpt,
+     /* desc, NAME, name */ zLoad_OptsText, zLoad_Opts_NAME, zLoad_Opts_Name,
+     /* disablement strs */ zNotLoad_Opts_Name, zNotLoad_Opts_Pfx }
+};
+
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ *
+ *  Define the Clktest Option Environment
+ */
+tSCC   zPROGNAME[]   = "CLKTEST";
+tSCC   zUsageTitle[] =
+"clktest - test the clock line discipline - Ver. 4.2.3p12\n\
+USAGE:  %s [ -<flag> [<val>] | --<name>[{=| }<val>] ]... <tty_device>\n";
+tSCC   zRcName[]     = ".ntprc";
+tSCC*  apzHomeList[] = {
+       "$HOME",
+       ".",
+       NULL };
+
+tSCC   zBugsAddr[]    = "http://bugs.ntp.isc.org, bugs@ntp.org";
+#define zExplain NULL
+tSCC    zDetail[]     = "\n\
+Clktest can be used to test the clock line discipline (CLKLDISC,\n\
+it must be available), and to take a look at radio clocks attached\n\
+to a serial port.\n";
+tSCC    zFullVersion[] = CLKTEST_FULL_VERSION;
+/* extracted from optcode near line 321 */
+
+#if defined(ENABLE_NLS)
+# define OPTPROC_BASE OPTPROC_TRANSLATE
+  static tOptionXlateProc translate_option_strings;
+#else
+# define OPTPROC_BASE OPTPROC_NONE
+# define translate_option_strings NULL
+#endif /* ENABLE_NLS */
+
+tOptions clktestOptions = {
+    OPTIONS_STRUCT_VERSION,
+    0, NULL,                    /* original argc + argv    */
+    ( OPTPROC_BASE
+    + OPTPROC_ERRSTOP
+    + OPTPROC_SHORTOPT
+    + OPTPROC_LONGOPT
+    + OPTPROC_NO_REQ_OPT
+    + OPTPROC_ENVIRON
+    + OPTPROC_ARGS_REQ
+    + OPTPROC_HAS_IMMED ),
+    0, NULL,                    /* current option index, current option */
+    NULL,         NULL,         zPROGNAME,
+    zRcName,      zCopyright,   zCopyrightNotice,
+    zFullVersion, apzHomeList,  zUsageTitle,
+    zExplain,     zDetail,      optDesc,
+    zBugsAddr,                  /* address to send bugs to */
+    NULL, NULL,                 /* extensions/saved state  */
+    optionUsage,       /* usage procedure */
+    translate_option_strings,   /* translation procedure */
+    /*
+     *  Indexes to special options
+     */
+    { INDEX_OPT_MORE_HELP,
+      INDEX_OPT_SAVE_OPTS,
+      NO_EQUIVALENT /* index of '-#' option */,
+      NO_EQUIVALENT /* index of default opt */
+    },
+    OPTION_CT, 8 /* user option count */
+};
+
+/*
+ *  Create the static procedure(s) declared above.
+ */
+static void
+doUsageOpt(
+    tOptions*   pOptions,
+    tOptDesc*   pOptDesc )
+{
+    USAGE( EXIT_SUCCESS );
+}
+
+/* * * * * * *
+ *
+ *   For the magic2 option, when CLKLDISC is #define-d.
+ */
+#ifdef CLKLDISC
+static void
+doOptMagic2(
+    tOptions*   pOptions,
+    tOptDesc*   pOptDesc )
+{
+    static const struct {const int rmin, rmax;} rng[ 1 ] = {
+        { 0, 255 } };
+    long val;
+    int ix;
+    const char* pzIndent = "\t\t\t\t  ";
+    extern FILE* option_usage_fp;
+
+    if (pOptDesc == NULL) /* usage is requesting range list
+                             option_usage_fp has already been set */
+        goto emit_ranges;
+
+    val = atoi( pOptDesc->pzLastArg );
+    for (ix = 0; ix < 1; ix++) {
+        if (val < rng[ix].rmin)
+            continue;  /* ranges need not be ordered. */
+        if (val == rng[ix].rmin)
+            goto valid_return;
+        if (rng[ix].rmax == INT_MIN)
+            continue;
+        if (val <= rng[ix].rmax)
+            goto valid_return;
+    }
+
+    option_usage_fp = stderr;
+    fprintf( stderr, _("%s error:  %s option value ``%s''is out of range.\n"),
+             pOptions->pzProgName, pOptDesc->pz_Name, pOptDesc->pzLastArg );
+    pzIndent = "\t";
+
+  emit_ranges:
+    fprintf( option_usage_fp, _("%sit must lie in the range: %d to %d\n"),
+             pzIndent, rng[0].rmin, rng[0].rmax );
+    if (pOptDesc == NULL)
+        return;
+
+    USAGE( EXIT_FAILURE );
+    /* NOTREACHED */
+    return;
+
+  valid_return:
+    pOptDesc->pzLastArg = (char*)val;
+}
+#endif /* defined CLKLDISC */
+
+/* * * * * * *
+ *
+ *   For the magic1 option, when CLKLDISC is #define-d.
+ */
+#ifdef CLKLDISC
+static void
+doOptMagic1(
+    tOptions*   pOptions,
+    tOptDesc*   pOptDesc )
+{
+    static const struct {const int rmin, rmax;} rng[ 1 ] = {
+        { 0, 255 } };
+    long val;
+    int ix;
+    const char* pzIndent = "\t\t\t\t  ";
+    extern FILE* option_usage_fp;
+
+    if (pOptDesc == NULL) /* usage is requesting range list
+                             option_usage_fp has already been set */
+        goto emit_ranges;
+
+    val = atoi( pOptDesc->pzLastArg );
+    for (ix = 0; ix < 1; ix++) {
+        if (val < rng[ix].rmin)
+            continue;  /* ranges need not be ordered. */
+        if (val == rng[ix].rmin)
+            goto valid_return;
+        if (rng[ix].rmax == INT_MIN)
+            continue;
+        if (val <= rng[ix].rmax)
+            goto valid_return;
+    }
+
+    option_usage_fp = stderr;
+    fprintf( stderr, _("%s error:  %s option value ``%s''is out of range.\n"),
+             pOptions->pzProgName, pOptDesc->pz_Name, pOptDesc->pzLastArg );
+    pzIndent = "\t";
+
+  emit_ranges:
+    fprintf( option_usage_fp, _("%sit must lie in the range: %d to %d\n"),
+             pzIndent, rng[0].rmin, rng[0].rmax );
+    if (pOptDesc == NULL)
+        return;
+
+    USAGE( EXIT_FAILURE );
+    /* NOTREACHED */
+    return;
+
+  valid_return:
+    pOptDesc->pzLastArg = (char*)val;
+}
+#endif /* defined CLKLDISC */
+
+#if ! defined(TEST_CLKTEST_OPTS)
+
+/* * * * * * *
+ *
+ *   For the magic1 option, when STREAM is #define-d.
+ */
+#ifdef STREAM
+static void
+doOptMagic1(
+    tOptions*   pOptions,
+    tOptDesc*   pOptDesc )
+{
+    unsigned long tmp;
+
+    if (!atouint(pOptDesc->pzLastArg, &tmp)) {
+        fprintf(stderr, "%s error:  not a number:  ``%s''\n",
+                pOptions->pzProgName, pOptDesc->pzLastArg );
+        USAGE( EXIT_FAILURE );
+    }
+}
+#endif /* defined STREAM */
+
+#endif /* defined(TEST_CLKTEST_OPTS) */
+
+#if ! defined(TEST_CLKTEST_OPTS)
+
+/* * * * * * *
+ *
+ *   For the speed option.
+ */
+static void
+doOptSpeed(
+    tOptions*   pOptions,
+    tOptDesc*   pOptDesc )
+{
+    /*
+     * speed table
+     */
+    static struct speeds {
+            const unsigned int bps;
+            const unsigned int rate;
+    } *spd, speedtab[] = {
+        { 300,          B300 },
+        { 1200,         B1200 },
+        { 2400,         B2400 },
+        { 4800,         B4800 },
+        { 9600,         B9600 },
+        { 19200,        EXTA },
+        { 38400,        EXTB },
+        { 0,            0 }
+    };
+    unsigned long tmp;
+
+    if (!atouint(pOptDesc->pzLastArg, &tmp)) {
+        fprintf(stderr, "%s error:  not a number:  ``%s''\n",
+                pOptions->pzProgName, pOptDesc->pzLastArg );
+        USAGE( EXIT_FAILURE );
+    }
+
+    for (spd = speedtab;;) {
+        if (tmp == spd->bps)
+            break;
+        spd++;
+        if (spd->bps == 0) {
+            fprintf(stderr, "%s: speed %lu is unsupported\n",
+                    pOptions->pzProgName, tmp);
+            USAGE( EXIT_FAILURE );
+        }
+    }
+
+    speed = spd->rate;
+}
+
+#endif /* defined(TEST_CLKTEST_OPTS) */
+
+#if ! defined(TEST_CLKTEST_OPTS)
+
+/* * * * * * *
+ *
+ *   For the crmod option.
+ */
+static void
+doOptCrmod(
+    tOptions*   pOptions,
+    tOptDesc*   pOptDesc )
+{
+    ttflags |= CRMOD;
+}
+
+#endif /* defined(TEST_CLKTEST_OPTS) */
+
+/* * * * * * *
+ *
+ *   For the timeout option.
+ */
+static void
+doOptTimeout(
+    tOptions*   pOptions,
+    tOptDesc*   pOptDesc )
+{
+    static const struct {const int rmin, rmax;} rng[ 1 ] = {
+        { 1, 600 } };
+    long val;
+    int ix;
+    const char* pzIndent = "\t\t\t\t  ";
+    extern FILE* option_usage_fp;
+
+    if (pOptDesc == NULL) /* usage is requesting range list
+                             option_usage_fp has already been set */
+        goto emit_ranges;
+
+    val = atoi( pOptDesc->pzLastArg );
+    for (ix = 0; ix < 1; ix++) {
+        if (val < rng[ix].rmin)
+            continue;  /* ranges need not be ordered. */
+        if (val == rng[ix].rmin)
+            goto valid_return;
+        if (rng[ix].rmax == INT_MIN)
+            continue;
+        if (val <= rng[ix].rmax)
+            goto valid_return;
+    }
+
+    option_usage_fp = stderr;
+    fprintf( stderr, _("%s error:  %s option value ``%s''is out of range.\n"),
+             pOptions->pzProgName, pOptDesc->pz_Name, pOptDesc->pzLastArg );
+    pzIndent = "\t";
+
+  emit_ranges:
+    fprintf( option_usage_fp, _("%sit must lie in the range: %d to %d\n"),
+             pzIndent, rng[0].rmin, rng[0].rmax );
+    if (pOptDesc == NULL)
+        return;
+
+    USAGE( EXIT_FAILURE );
+    /* NOTREACHED */
+    return;
+
+  valid_return:
+    pOptDesc->pzLastArg = (char*)val;
+}
+
+/* extracted from optmain.tpl near line 92 */
+
+#if defined(TEST_CLKTEST_OPTS) /* TEST MAIN PROCEDURE: */
+
+int
+main( int argc, char** argv )
+{
+    int res = EXIT_SUCCESS;
+    (void)optionProcess( &clktestOptions, argc, argv );
+    {
+        void optionPutShell( tOptions* );
+        optionPutShell( &clktestOptions );
+    }
+    return res;
+}
+#endif  /* defined TEST_CLKTEST_OPTS */
+/* extracted from optcode near line 418 */
+
+#if ENABLE_NLS
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+#include <autoopts/usage-txt.h>
+
+static char*
+AO_gettext( const char* pz )
+{
+    char* pzRes;
+    if (pz == NULL)
+        return NULL;
+    pzRes = _(pz);
+    if (pzRes == pz)
+        return pzRes;
+    pzRes = strdup( pzRes );
+    if (pzRes == NULL) {
+        fputs( _("No memory for duping translated strings\n"), stderr );
+        exit( EXIT_FAILURE );
+    }
+    return pzRes;
+}
+
+/*
+ *  This invokes the translation code (e.g. gettext(3)).
+ */
+static void
+translate_option_strings( void )
+{
+    /*
+     *  Guard against re-translation.  It won't work.  The strings will have
+     *  been changed by the first pass through this code.  One shot only.
+     */
+    if (option_usage_text.field_ct == 0)
+        return;
+    /*
+     *  Do the translations.  The first pointer follows the field count field.
+     *  The field count field is the size of a pointer.
+     */
+    {
+        char** ppz = (char**)(void*)&(option_usage_text);
+        int    ix  = option_usage_text.field_ct;
+
+        do {
+            ppz++;
+            *ppz = AO_gettext(*ppz);
+        } while (--ix > 0);
+    }
+    option_usage_text.field_ct = 0;
+
+    {
+        tOptDesc* pOD = clktestOptions.pOptDesc;
+        int       ix  = clktestOptions.optCt;
+
+        for (;;) {
+            pOD->pzText           = AO_gettext(pOD->pzText);
+            pOD->pz_NAME          = AO_gettext(pOD->pz_NAME);
+            pOD->pz_Name          = AO_gettext(pOD->pz_Name);
+            pOD->pz_DisableName   = AO_gettext(pOD->pz_DisableName);
+            pOD->pz_DisablePfx    = AO_gettext(pOD->pz_DisablePfx);
+            if (--ix <= 0)
+                break;
+            pOD++;
+        }
+    }
+    clktestOptions.pzCopyright   = AO_gettext(clktestOptions.pzCopyright);
+    clktestOptions.pzCopyNotice  = AO_gettext(clktestOptions.pzCopyNotice);
+    clktestOptions.pzFullVersion = AO_gettext(clktestOptions.pzFullVersion);
+    clktestOptions.pzUsageTitle  = AO_gettext(clktestOptions.pzUsageTitle);
+    clktestOptions.pzExplain     = AO_gettext(clktestOptions.pzExplain);
+    clktestOptions.pzDetail      = AO_gettext(clktestOptions.pzDetail);
+}
+
+#endif /* ENABLE_NLS */
+
+#ifdef  __cplusplus
+}
+#endif
diff --git a/clockstuff/clktest-opts.h b/clockstuff/clktest-opts.h
new file mode 100644 (file)
index 0000000..47737d8
--- /dev/null
@@ -0,0 +1,192 @@
+/*   -*- buffer-read-only: t -*- vi: set ro:
+ *  
+ *  DO NOT EDIT THIS FILE   (clktest-opts.h)
+ *  
+ *  It has been AutoGen-ed  Tuesday June 27, 2006 at 10:16:45 PM EDT
+ *  From the definitions    clktest-opts.def
+ *  and the template file   options
+ */
+/*
+ *  This file contains the programmatic interface to the Automated
+ *  Options generated for the clktest program.
+ *  These macros are documented in the AutoGen info file in the
+ *  "AutoOpts" chapter.  Please refer to that doc for usage help.
+ */
+#ifndef AUTOOPTS_CLKTEST_OPTS_H_GUARD
+#define AUTOOPTS_CLKTEST_OPTS_H_GUARD
+
+/*
+ * clktest copyright 1970-2006 ntp.org - all rights reserved
+ *
+ * see html/copyright.html
+ */
+#include "config.h"
+#include <autoopts/options.h>
+
+/*
+ *  Ensure that the library used for compiling this generated header is at
+ *  least as new as the version current when the header template was released
+ *  (not counting patch version increments).  Also ensure that the oldest
+ *  tolerable version is at least as old as what was current when the header
+ *  template was released.
+ */
+#define AO_TEMPLATE_VERSION 110592
+#if (AO_TEMPLATE_VERSION < OPTIONS_MINIMUM_VERSION) \
+ || (AO_TEMPLATE_VERSION > OPTIONS_STRUCT_VERSION)
+# error option template version mismatches autoopts/options.h header
+#endif
+
+/*
+ *  Enumeration of each option:
+ */
+typedef enum {
+        INDEX_OPT_MAGIC2           =  0,
+        INDEX_OPT_MAGIC1           =  1,
+        INDEX_OPT_MAGIC1           =  2,
+        INDEX_OPT_SPEED            =  3,
+        INDEX_OPT_DEBUG            =  4,
+        INDEX_OPT_CRMOD            =  5,
+        INDEX_OPT_COMMAND          =  6,
+        INDEX_OPT_TIMEOUT          =  7,
+        INDEX_OPT_VERSION          = 8,
+        INDEX_OPT_HELP             = 9,
+        INDEX_OPT_MORE_HELP        = 10,
+        INDEX_OPT_SAVE_OPTS        = 11,
+        INDEX_OPT_LOAD_OPTS        = 12
+} teOptIndex;
+
+#define OPTION_CT    13
+#define CLKTEST_VERSION       "4.2.3p12"
+#define CLKTEST_FULL_VERSION  "clktest - test the clock line discipline - Ver. 4.2.3p12"
+
+/*
+ *  Interface defines for all options.  Replace "n" with
+ *  the UPPER_CASED option name (as in the teOptIndex
+ *  enumeration above).  e.g. HAVE_OPT( MAGIC2 )
+ */
+#define        DESC(n) clktestOptions.pOptDesc[INDEX_OPT_ ## n]
+#define     HAVE_OPT(n) (! UNUSED_OPT(& DESC(n)))
+#define      OPT_ARG(n) (DESC(n).pzLastArg)
+#define    STATE_OPT(n) (DESC(n).fOptState & OPTST_SET_MASK)
+#define    COUNT_OPT(n) (DESC(n).optOccCt)
+#define    ISSEL_OPT(n) (SELECTED_OPT(&DESC(n)))
+#define ISUNUSED_OPT(n) (UNUSED_OPT(& DESC(n)))
+#define  ENABLED_OPT(n) (! DISABLED_OPT(& DESC(n)))
+#define  STACKCT_OPT(n) (((tArgList*)(DESC(n).optCookie))->useCt)
+#define STACKLST_OPT(n) (((tArgList*)(DESC(n).optCookie))->apzArgs)
+#define    CLEAR_OPT(n) STMTS( \
+                DESC(n).fOptState &= OPTST_PERSISTENT;   \
+                if ( (DESC(n).fOptState & OPTST_INITENABLED) == 0) \
+                    DESC(n).fOptState |= OPTST_DISABLED; \
+                DESC(n).optCookie = NULL )
+
+/*
+ *  Interface defines for specific options.
+ */
+#ifdef CLKLDISC
+#define VALUE_OPT_MAGIC2         'a'
+#define OPT_VALUE_MAGIC2         (*(unsigned long*)(&DESC(MAGIC2).pzLastArg))
+#endif /* CLKLDISC */
+#ifdef CLKLDISC
+#define VALUE_OPT_MAGIC1         'c'
+#define OPT_VALUE_MAGIC1         (*(unsigned long*)(&DESC(MAGIC1).pzLastArg))
+#endif /* CLKLDISC */
+#ifdef STREAM
+#define VALUE_OPT_MAGIC1         'c'
+#endif /* STREAM */
+#define VALUE_OPT_SPEED          'b'
+#define VALUE_OPT_DEBUG          'd'
+#define VALUE_OPT_CRMOD          'f'
+#define VALUE_OPT_COMMAND        's'
+#define VALUE_OPT_TIMEOUT        't'
+#define OPT_VALUE_TIMEOUT        (*(unsigned long*)(&DESC(TIMEOUT).pzLastArg))
+
+#define VALUE_OPT_VERSION       'v'
+#define VALUE_OPT_SAVE_OPTS     '>'
+#define VALUE_OPT_LOAD_OPTS     '<'
+#define VALUE_OPT_HELP          '?'
+#define VALUE_OPT_MORE_HELP     '!'
+#define SET_OPT_SAVE_OPTS(a)   STMTS( \
+        DESC(SAVE_OPTS).fOptState &= OPTST_PERSISTENT; \
+        DESC(SAVE_OPTS).fOptState |= OPTST_SET; \
+        DESC(SAVE_OPTS).pzLastArg  = (const char*)(a) )
+/*
+ *  Interface defines not associated with particular options
+ */
+#define ERRSKIP_OPTERR  STMTS( clktestOptions.fOptSet &= ~OPTPROC_ERRSTOP )
+#define ERRSTOP_OPTERR  STMTS( clktestOptions.fOptSet |= OPTPROC_ERRSTOP )
+#define RESTART_OPT(n)  STMTS( \
+                clktestOptions.curOptIdx = (n); \
+                clktestOptions.pzCurOpt  = NULL )
+#define START_OPT       RESTART_OPT(1)
+#define USAGE(c)        (*clktestOptions.pUsageProc)( &clktestOptions, c )
+/* extracted from opthead near line 289 */
+
+/* * * * * *
+ *
+ *  Declare the clktest option descriptor.
+ */
+#ifdef  __cplusplus
+extern "C" {
+#endif
+
+extern tOptions   clktestOptions;
+
+/* * * * * *
+ *
+ *  Globals exported from the test the clock line discipline option definitions
+ */
+#include <stdio.h>
+#include <ctype.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <signal.h>
+#include <netinet/in.h>
+#include <sys/ioctl.h>
+#include <sys/time.h>
+#include <sys/file.h>
+#include <sgtty.h>
+
+#include "../include/ntp_fp.h"
+#include "../include/ntp.h"
+#include "../include/ntp_unixtime.h"
+
+#ifdef CLKLDISC
+# define DEFMAGIC      '\r'
+#endif
+
+#ifdef CLKLDISC
+# ifdef STREAM
+#  include <stropts.h>
+#  ifdef HAVE_SYS_CLKDEFS_H
+#   include <sys/clkdefs.h>
+#  endif
+#  undef  DEFMAGIC
+#  define DEFMAGIC     "\r"
+# endif
+#endif
+
+#ifndef _
+#  if ENABLE_NLS
+#    include <stdio.h>
+     static inline char* aoGetsText( const char* pz ) {
+         if (pz == NULL) return NULL;
+         return (char*)gettext( pz );
+     }
+#    define _(s)  aoGetsText(s)
+#  else  /* ENABLE_NLS */
+#    define _(s)  s
+#  endif /* ENABLE_NLS */
+#endif
+
+#ifdef  __cplusplus
+}
+#endif
+#endif /* AUTOOPTS_CLKTEST_OPTS_H_GUARD */
+/*
+ * Local Variables:
+ * Mode: C
+ * c-file-style: "stroustrup"
+ * indent-tabs-mode: nil
+ * End:
+ * options.h ends here */
diff --git a/libopts/COPYING.lgpl b/libopts/COPYING.lgpl
new file mode 100644 (file)
index 0000000..52f31fd
--- /dev/null
@@ -0,0 +1,502 @@
+                 GNU LESSER GENERAL PUBLIC LICENSE
+                      Version 2.1, February 1999
+
+ Copyright (C) 1991, 1999 Free Software Foundation, Inc.
+ 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+[This is the first released version of the Lesser GPL.  It also counts
+ as the successor of the GNU Library Public License, version 2, hence
+ the version number 2.1.]
+
+                           Preamble
+
+  The licenses for most software are designed to take away your
+freedom to share and change it.  By contrast, the GNU General Public
+Licenses are intended to guarantee your freedom to share and change
+free software--to make sure the software is free for all its users.
+
+  This license, the Lesser General Public License, applies to some
+specially designated software packages--typically libraries--of the
+Free Software Foundation and other authors who decide to use it.  You
+can use it too, but we suggest you first think carefully about whether
+this license or the ordinary General Public License is the better
+strategy to use in any particular case, based on the explanations below.
+
+  When we speak of free software, we are referring to freedom of use,
+not price.  Our General Public Licenses are designed to make sure that
+you have the freedom to distribute copies of free software (and charge
+for this service if you wish); that you receive source code or can get
+it if you want it; that you can change the software and use pieces of
+it in new free programs; and that you are informed that you can do
+these things.
+
+  To protect your rights, we need to make restrictions that forbid
+distributors to deny you these rights or to ask you to surrender these
+rights.  These restrictions translate to certain responsibilities for
+you if you distribute copies of the library or if you modify it.
+
+  For example, if you distribute copies of the library, whether gratis
+or for a fee, you must give the recipients all the rights that we gave
+you.  You must make sure that they, too, receive or can get the source
+code.  If you link other code with the library, you must provide
+complete object files to the recipients, so that they can relink them
+with the library after making changes to the library and recompiling
+it.  And you must show them these terms so they know their rights.
+
+  We protect your rights with a two-step method: (1) we copyright the
+library, and (2) we offer you this license, which gives you legal
+permission to copy, distribute and/or modify the library.
+
+  To protect each distributor, we want to make it very clear that
+there is no warranty for the free library.  Also, if the library is
+modified by someone else and passed on, the recipients should know
+that what they have is not the original version, so that the original
+author's reputation will not be affected by problems that might be
+introduced by others.
+
+  Finally, software patents pose a constant threat to the existence of
+any free program.  We wish to make sure that a company cannot
+effectively restrict the users of a free program by obtaining a
+restrictive license from a patent holder.  Therefore, we insist that
+any patent license obtained for a version of the library must be
+consistent with the full freedom of use specified in this license.
+
+  Most GNU software, including some libraries, is covered by the
+ordinary GNU General Public License.  This license, the GNU Lesser
+General Public License, applies to certain designated libraries, and
+is quite different from the ordinary General Public License.  We use
+this license for certain libraries in order to permit linking those
+libraries into non-free programs.
+
+  When a program is linked with a library, whether statically or using
+a shared library, the combination of the two is legally speaking a
+combined work, a derivative of the original library.  The ordinary
+General Public License therefore permits such linking only if the
+entire combination fits its criteria of freedom.  The Lesser General
+Public License permits more lax criteria for linking other code with
+the library.
+
+  We call this license the "Lesser" General Public License because it
+does Less to protect the user's freedom than the ordinary General
+Public License.  It also provides other free software developers Less
+of an advantage over competing non-free programs.  These disadvantages
+are the reason we use the ordinary General Public License for many
+libraries.  However, the Lesser license provides advantages in certain
+special circumstances.
+
+  For example, on rare occasions, there may be a special need to
+encourage the widest possible use of a certain library, so that it becomes
+a de-facto standard.  To achieve this, non-free programs must be
+allowed to use the library.  A more frequent case is that a free
+library does the same job as widely used non-free libraries.  In this
+case, there is little to gain by limiting the free library to free
+software only, so we use the Lesser General Public License.
+
+  In other cases, permission to use a particular library in non-free
+programs enables a greater number of people to use a large body of
+free software.  For example, permission to use the GNU C Library in
+non-free programs enables many more people to use the whole GNU
+operating system, as well as its variant, the GNU/Linux operating
+system.
+
+  Although the Lesser General Public License is Less protective of the
+users' freedom, it does ensure that the user of a program that is
+linked with the Library has the freedom and the wherewithal to run
+that program using a modified version of the Library.
+
+  The precise terms and conditions for copying, distribution and
+modification follow.  Pay close attention to the difference between a
+"work based on the library" and a "work that uses the library".  The
+former contains code derived from the library, whereas the latter must
+be combined with the library in order to run.
+
+                 GNU LESSER GENERAL PUBLIC LICENSE
+   TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+  0. This License Agreement applies to any software library or other
+program which contains a notice placed by the copyright holder or
+other authorized party saying it may be distributed under the terms of
+this Lesser General Public License (also called "this License").
+Each licensee is addressed as "you".
+
+  A "library" means a collection of software functions and/or data
+prepared so as to be conveniently linked with application programs
+(which use some of those functions and data) to form executables.
+
+  The "Library", below, refers to any such software library or work
+which has been distributed under these terms.  A "work based on the
+Library" means either the Library or any derivative work under
+copyright law: that is to say, a work containing the Library or a
+portion of it, either verbatim or with modifications and/or translated
+straightforwardly into another language.  (Hereinafter, translation is
+included without limitation in the term "modification".)
+
+  "Source code" for a work means the preferred form of the work for
+making modifications to it.  For a library, complete source code means
+all the source code for all modules it contains, plus any associated
+interface definition files, plus the scripts used to control compilation
+and installation of the library.
+
+  Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope.  The act of
+running a program using the Library is not restricted, and output from
+such a program is covered only if its contents constitute a work based
+on the Library (independent of the use of the Library in a tool for
+writing it).  Whether that is true depends on what the Library does
+and what the program that uses the Library does.
+  
+  1. You may copy and distribute verbatim copies of the Library's
+complete source code as you receive it, in any medium, provided that
+you conspicuously and appropriately publish on each copy an
+appropriate copyright notice and disclaimer of warranty; keep intact
+all the notices that refer to this License and to the absence of any
+warranty; and distribute a copy of this License along with the
+Library.
+
+  You may charge a fee for the physical act of transferring a copy,
+and you may at your option offer warranty protection in exchange for a
+fee.
+
+  2. You may modify your copy or copies of the Library or any portion
+of it, thus forming a work based on the Library, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+    a) The modified work must itself be a software library.
+
+    b) You must cause the files modified to carry prominent notices
+    stating that you changed the files and the date of any change.
+
+    c) You must cause the whole of the work to be licensed at no
+    charge to all third parties under the terms of this License.
+
+    d) If a facility in the modified Library refers to a function or a
+    table of data to be supplied by an application program that uses
+    the facility, other than as an argument passed when the facility
+    is invoked, then you must make a good faith effort to ensure that,
+    in the event an application does not supply such function or
+    table, the facility still operates, and performs whatever part of
+    its purpose remains meaningful.
+
+    (For example, a function in a library to compute square roots has
+    a purpose that is entirely well-defined independent of the
+    application.  Therefore, Subsection 2d requires that any
+    application-supplied function or table used by this function must
+    be optional: if the application does not supply it, the square
+    root function must still compute square roots.)
+
+These requirements apply to the modified work as a whole.  If
+identifiable sections of that work are not derived from the Library,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works.  But when you
+distribute the same sections as part of a whole which is a work based
+on the Library, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote
+it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Library.
+
+In addition, mere aggregation of another work not based on the Library
+with the Library (or with a work based on the Library) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+  3. You may opt to apply the terms of the ordinary GNU General Public
+License instead of this License to a given copy of the Library.  To do
+this, you must alter all the notices that refer to this License, so
+that they refer to the ordinary GNU General Public License, version 2,
+instead of to this License.  (If a newer version than version 2 of the
+ordinary GNU General Public License has appeared, then you can specify
+that version instead if you wish.)  Do not make any other change in
+these notices.
+
+  Once this change is made in a given copy, it is irreversible for
+that copy, so the ordinary GNU General Public License applies to all
+subsequent copies and derivative works made from that copy.
+
+  This option is useful when you wish to copy part of the code of
+the Library into a program that is not a library.
+
+  4. You may copy and distribute the Library (or a portion or
+derivative of it, under Section 2) in object code or executable form
+under the terms of Sections 1 and 2 above provided that you accompany
+it with the complete corresponding machine-readable source code, which
+must be distributed under the terms of Sections 1 and 2 above on a
+medium customarily used for software interchange.
+
+  If distribution of object code is made by offering access to copy
+from a designated place, then offering equivalent access to copy the
+source code from the same place satisfies the requirement to
+distribute the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+  5. A program that contains no derivative of any portion of the
+Library, but is designed to work with the Library by being compiled or
+linked with it, is called a "work that uses the Library".  Such a
+work, in isolation, is not a derivative work of the Library, and
+therefore falls outside the scope of this License.
+
+  However, linking a "work that uses the Library" with the Library
+creates an executable that is a derivative of the Library (because it
+contains portions of the Library), rather than a "work that uses the
+library".  The executable is therefore covered by this License.
+Section 6 states terms for distribution of such executables.
+
+  When a "work that uses the Library" uses material from a header file
+that is part of the Library, the object code for the work may be a
+derivative work of the Library even though the source code is not.
+Whether this is true is especially significant if the work can be
+linked without the Library, or if the work is itself a library.  The
+threshold for this to be true is not precisely defined by law.
+
+  If such an object file uses only numerical parameters, data
+structure layouts and accessors, and small macros and small inline
+functions (ten lines or less in length), then the use of the object
+file is unrestricted, regardless of whether it is legally a derivative
+work.  (Executables containing this object code plus portions of the
+Library will still fall under Section 6.)
+
+  Otherwise, if the work is a derivative of the Library, you may
+distribute the object code for the work under the terms of Section 6.
+Any executables containing that work also fall under Section 6,
+whether or not they are linked directly with the Library itself.
+
+  6. As an exception to the Sections above, you may also combine or
+link a "work that uses the Library" with the Library to produce a
+work containing portions of the Library, and distribute that work
+under terms of your choice, provided that the terms permit
+modification of the work for the customer's own use and reverse
+engineering for debugging such modifications.
+
+  You must give prominent notice with each copy of the work that the
+Library is used in it and that the Library and its use are covered by
+this License.  You must supply a copy of this License.  If the work
+during execution displays copyright notices, you must include the
+copyright notice for the Library among them, as well as a reference
+directing the user to the copy of this License.  Also, you must do one
+of these things:
+
+    a) Accompany the work with the complete corresponding
+    machine-readable source code for the Library including whatever
+    changes were used in the work (which must be distributed under
+    Sections 1 and 2 above); and, if the work is an executable linked
+    with the Library, with the complete machine-readable "work that
+    uses the Library", as object code and/or source code, so that the
+    user can modify the Library and then relink to produce a modified
+    executable containing the modified Library.  (It is understood
+    that the user who changes the contents of definitions files in the
+    Library will not necessarily be able to recompile the application
+    to use the modified definitions.)
+
+    b) Use a suitable shared library mechanism for linking with the
+    Library.  A suitable mechanism is one that (1) uses at run time a
+    copy of the library already present on the user's computer system,
+    rather than copying library functions into the executable, and (2)
+    will operate properly with a modified version of the library, if
+    the user installs one, as long as the modified version is
+    interface-compatible with the version that the work was made with.
+
+    c) Accompany the work with a written offer, valid for at
+    least three years, to give the same user the materials
+    specified in Subsection 6a, above, for a charge no more
+    than the cost of performing this distribution.
+
+    d) If distribution of the work is made by offering access to copy
+    from a designated place, offer equivalent access to copy the above
+    specified materials from the same place.
+
+    e) Verify that the user has already received a copy of these
+    materials or that you have already sent this user a copy.
+
+  For an executable, the required form of the "work that uses the
+Library" must include any data and utility programs needed for
+reproducing the executable from it.  However, as a special exception,
+the materials to be distributed need not include anything that is
+normally distributed (in either source or binary form) with the major
+components (compiler, kernel, and so on) of the operating system on
+which the executable runs, unless that component itself accompanies
+the executable.
+
+  It may happen that this requirement contradicts the license
+restrictions of other proprietary libraries that do not normally
+accompany the operating system.  Such a contradiction means you cannot
+use both them and the Library together in an executable that you
+distribute.
+
+  7. You may place library facilities that are a work based on the
+Library side-by-side in a single library together with other library
+facilities not covered by this License, and distribute such a combined
+library, provided that the separate distribution of the work based on
+the Library and of the other library facilities is otherwise
+permitted, and provided that you do these two things:
+
+    a) Accompany the combined library with a copy of the same work
+    based on the Library, uncombined with any other library
+    facilities.  This must be distributed under the terms of the
+    Sections above.
+
+    b) Give prominent notice with the combined library of the fact
+    that part of it is a work based on the Library, and explaining
+    where to find the accompanying uncombined form of the same work.
+
+  8. You may not copy, modify, sublicense, link with, or distribute
+the Library except as expressly provided under this License.  Any
+attempt otherwise to copy, modify, sublicense, link with, or
+distribute the Library is void, and will automatically terminate your
+rights under this License.  However, parties who have received copies,
+or rights, from you under this License will not have their licenses
+terminated so long as such parties remain in full compliance.
+
+  9. You are not required to accept this License, since you have not
+signed it.  However, nothing else grants you permission to modify or
+distribute the Library or its derivative works.  These actions are
+prohibited by law if you do not accept this License.  Therefore, by
+modifying or distributing the Library (or any work based on the
+Library), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Library or works based on it.
+
+  10. Each time you redistribute the Library (or any work based on the
+Library), the recipient automatically receives a license from the
+original licensor to copy, distribute, link with or modify the Library
+subject to these terms and conditions.  You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties with
+this License.
+
+  11. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License.  If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Library at all.  For example, if a patent
+license would not permit royalty-free redistribution of the Library by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Library.
+
+If any portion of this section is held invalid or unenforceable under any
+particular circumstance, the balance of the section is intended to apply,
+and the section as a whole is intended to apply in other circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system which is
+implemented by public license practices.  Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+  12. If the distribution and/or use of the Library is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Library under this License may add
+an explicit geographical distribution limitation excluding those countries,
+so that distribution is permitted only in or among countries not thus
+excluded.  In such case, this License incorporates the limitation as if
+written in the body of this License.
+
+  13. The Free Software Foundation may publish revised and/or new
+versions of the Lesser General Public License from time to time.
+Such new versions will be similar in spirit to the present version,
+but may differ in detail to address new problems or concerns.
+
+Each version is given a distinguishing version number.  If the Library
+specifies a version number of this License which applies to it and
+"any later version", you have the option of following the terms and
+conditions either of that version or of any later version published by
+the Free Software Foundation.  If the Library does not specify a
+license version number, you may choose any version ever published by
+the Free Software Foundation.
+
+  14. If you wish to incorporate parts of the Library into other free
+programs whose distribution conditions are incompatible with these,
+write to the author to ask for permission.  For software which is
+copyrighted by the Free Software Foundation, write to the Free
+Software Foundation; we sometimes make exceptions for this.  Our
+decision will be guided by the two goals of preserving the free status
+of all derivatives of our free software and of promoting the sharing
+and reuse of software generally.
+
+                           NO WARRANTY
+
+  15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO
+WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW.
+EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR
+OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY
+KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+PURPOSE.  THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE
+LIBRARY IS WITH YOU.  SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME
+THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
+
+  16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN
+WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY
+AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU
+FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR
+CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE
+LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
+RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
+FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
+SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+DAMAGES.
+
+                    END OF TERMS AND CONDITIONS
+
+           How to Apply These Terms to Your New Libraries
+
+  If you develop a new library, and you want it to be of the greatest
+possible use to the public, we recommend making it free software that
+everyone can redistribute and change.  You can do so by permitting
+redistribution under these terms (or, alternatively, under the terms of the
+ordinary General Public License).
+
+  To apply these terms, attach the following notices to the library.  It is
+safest to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least the
+"copyright" line and a pointer to where the full notice is found.
+
+    <one line to give the library's name and a brief idea of what it does.>
+    Copyright (C) <year>  <name of author>
+
+    This library is free software; you can redistribute it and/or
+    modify it under the terms of the GNU Lesser General Public
+    License as published by the Free Software Foundation; either
+    version 2.1 of the License, or (at your option) any later version.
+
+    This library is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+    Lesser General Public License for more details.
+
+    You should have received a copy of the GNU Lesser General Public
+    License along with this library; if not, write to the Free Software
+    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
+
+Also add information on how to contact you by electronic and paper mail.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the library, if
+necessary.  Here is a sample; alter the names:
+
+  Yoyodyne, Inc., hereby disclaims all copyright interest in the
+  library `Frob' (a library for tweaking knobs) written by James Random Hacker.
+
+  <signature of Ty Coon>, 1 April 1990
+  Ty Coon, President of Vice
+
+That's all there is to it!
diff --git a/libopts/COPYING.mbsd b/libopts/COPYING.mbsd
new file mode 100644 (file)
index 0000000..8a70427
--- /dev/null
@@ -0,0 +1,26 @@
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+    1. Redistributions of source code must retain the above copyright
+       notice, this list of conditions and the following disclaimer.
+
+    2. Redistributions in binary form must reproduce the above
+       copyright notice, this list of conditions and the following
+       disclaimer in the documentation and/or other materials provided
+       with the distribution.
+
+    3. The name of the author may not be used to endorse or promote
+       products derived from this software without specific prior
+       written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
+INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
+IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE.
diff --git a/libopts/MakeDefs.inc b/libopts/MakeDefs.inc
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/libopts/Makefile.am b/libopts/Makefile.am
new file mode 100644 (file)
index 0000000..ca0f8a6
--- /dev/null
@@ -0,0 +1,20 @@
+## LIBOPTS Makefile
+MAINTAINERCLEANFILES  = Makefile.in
+lib_LTLIBRARIES       = libopts.la
+libopts_la_SOURCES    = libopts.c
+libopts_la_CPPFLAGS   = -I$(top_srcdir)
+libopts_la_LDFLAGS    = -version-info  27:1:2
+EXTRA_DIST            = \
+    COPYING.lgpl         COPYING.mbsd         MakeDefs.inc  \
+    README               autoopts/options.h   autoopts/usage-txt.h  \
+    autoopts.c           autoopts.h           boolean.c  \
+    compat/compat.h      compat/pathfind.c    compat/snprintf.c  \
+    compat/strdup.c      configfile.c         cook.c  \
+    enumeration.c        environment.c        genshell.c  \
+    genshell.h           load.c               m4/libopts.m4  \
+    m4/liboptschk.m4     makeshell.c          nested.c  \
+    numeric.c            pgusage.c            proto.h  \
+    putshell.c           restore.c            save.c  \
+    sort.c               stack.c              streqvcmp.c  \
+    text_mmap.c          tokenize.c           usage.c  \
+    version.c
diff --git a/libopts/README b/libopts/README
new file mode 100644 (file)
index 0000000..7f426fa
--- /dev/null
@@ -0,0 +1,93 @@
+        THIS TARBALL IS NOT A FULL DISTRIBUTION.
+
+The contents of this tarball is designed to be incorporated into
+software packages that utilize the AutoOpts option automation
+package and are intended to be installed on systems that may not
+have libopts installed.  It is redistributable under the terms
+of either the LGPL (see COPYING.lgpl) or under the terms of
+the advertising clause free BSD license (see COPYING.mbsd).
+
+Usage Instructions for autoconf/automake/libtoolized projects:
+
+1. Install the unrolled tarball into your package source tree,
+   copying ``libopts.m4'' to your autoconf macro directory.
+
+   In your bootstrap (pre-configure) script, you can do this:
+
+      rm -rf libopts libopts-*
+      gunzip -c `autoopts-config libsrc` | tar -xvf -
+      mv -f libopts-*.*.* libopts
+      cp -fp libopts/m4/*.m4 m4/.
+
+   I tend to put my configure auxiliary files in "m4".
+   Whatever directory you choose, if it is not ".", then
+   be sure to tell autoconf about it with:
+
+      AC_CONFIG_AUX_DIR(m4)
+
+   This is one macro where you *MUST* remember to *NOT* quote
+   the argument.  If you do, automake will get lost.
+
+2. Add the following to your ``configure.ac'' file:
+
+      LIBOPTS_CHECK
+
+   or:
+
+      LIBOPTS_CHECK([relative/path/to/libopts])
+
+   This macro will automatically invoke
+
+      AC_CONFIG_FILES( [relative/path/to/libopts/Makefile] )
+
+   The default ``relative/path/to/libopts'' is simply
+   ``libopts''.
+
+3. Add the following to your top level ``Makefile.am'' file:
+
+      if NEED_LIBOPTS
+         SUBDIRS += $(LIBOPTS_DIR)
+      endif
+
+   where ``<...>'' can be whatever other files or directories
+   you may need.  The SUBDIRS must be properly ordered.
+   *PLEASE NOTE* it is crucial that the SUBDIRS be set under the
+   control of an automake conditional.  To work correctly,
+   automake has to know the range of possible values of SUBDIRS.
+   It's a magical name with magical properties.  ``NEED_LIBOPTS''
+   will be correctly set by the ``LIBOPTS_CHECK'' macro, above.
+
+4. Add ``$(LIBOPTS_CFLAGS)'' to relevant compiler flags and
+   ``$(LIBOPTS_LDADD)'' to relevant link options whereever
+   you need them in your build tree.
+
+5. Make sure your object files explicitly depend upon the
+   generated options header file.  e.g.:
+
+     $(prog_OBJECTS) : prog-opts.h
+     prog-opts.h : prog-opts.c
+     prog-opts.c : prog-opts.def
+         autogen prog-opts.def
+
+6. *OPTIONAL* --
+   If you are creating man pages and texi documentation from
+   the program options, you will need these rules somewhere, too:
+
+     man_MANS = prog.1
+     prog.1 : prog-opts.def
+         autogen -Tagman1.tpl -bprog prog-opts.def
+
+     prog-invoke.texi : prog-opts.def
+         autogen -Taginfo.tpl -bprog-invoke prog-opts.def
+
+If your package does not utilize the auto* tools, then you
+will need to hand craft the rules for building the library.
+
+LICENSING:
+
+This material is copyright 1993-2006 by Bruce Korb.
+You are licensed to use this under the terms of either
+the GNU Lesser General Public License (see: COPYING.lgpl), or,
+at your option, the modified Berkeley Software Distribution
+License (see:  COPYING.mbsd).  Both of these files should be
+included with this tarball.
diff --git a/libopts/autoopts.c b/libopts/autoopts.c
new file mode 100644 (file)
index 0000000..6d88967
--- /dev/null
@@ -0,0 +1,1043 @@
+
+/*
+ *  $Id: autoopts.c,v 4.14 2006/03/25 19:24:56 bkorb Exp $
+ *  Time-stamp:      "2005-10-29 13:19:36 bkorb"
+ *
+ *  This file contains all of the routines that must be linked into
+ *  an executable to use the generated option processing.  The optional
+ *  routines are in separately compiled modules so that they will not
+ *  necessarily be linked in.
+ */
+
+/*
+ *  Automated Options copyright 1992-2006 Bruce Korb
+ *
+ *  Automated Options is free software.
+ *  You may redistribute it and/or modify it under the terms of the
+ *  GNU General Public License, as published by the Free Software
+ *  Foundation; either version 2, or (at your option) any later version.
+ *
+ *  Automated Options is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with Automated Options.  See the file "COPYING".  If not,
+ *  write to:  The Free Software Foundation, Inc.,
+ *             51 Franklin Street, Fifth Floor,
+ *             Boston, MA  02110-1301, USA.
+ *
+ * As a special exception, Bruce Korb gives permission for additional
+ * uses of the text contained in his release of AutoOpts.
+ *
+ * The exception is that, if you link the AutoOpts library with other
+ * files to produce an executable, this does not by itself cause the
+ * resulting executable to be covered by the GNU General Public License.
+ * Your use of that executable is in no way restricted on account of
+ * linking the AutoOpts library code into it.
+ *
+ * This exception does not however invalidate any other reasons why
+ * the executable file might be covered by the GNU General Public License.
+ *
+ * This exception applies only to the code released by Bruce Korb under
+ * the name AutoOpts.  If you copy code from other sources under the
+ * General Public License into a copy of AutoOpts, as the General Public
+ * License permits, the exception does not apply to the code that you add
+ * in this way.  To avoid misleading anyone as to the status of such
+ * modified files, you must delete this exception notice from them.
+ *
+ * If you write modifications of your own for AutoOpts, it is your choice
+ * whether to permit this exception to apply to your modifications.
+ * If you do not wish that, delete this exception notice.
+ */
+
+#ifndef HAVE_PATHFIND
+#  include "compat/pathfind.c"
+#endif
+
+#ifndef HAVE_LIBSNPRINTFV
+# ifndef HAVE_SNPRINTF
+#   include "compat/snprintf.c"
+# endif
+
+# ifndef HAVE_STRDUP
+#   include "compat/strdup.c"
+# endif
+#endif
+
+static const char zNil[] = "";
+
+#define SKIP_RC_FILES(po) \
+    DISABLED_OPT(&((po)->pOptDesc[ (po)->specOptIdx.save_opts+1]))
+
+/* = = = START-STATIC-FORWARD = = = */
+/* static forward declarations maintained by :mkfwd */
+static tSuccess
+findOptDesc( tOptions* pOpts, tOptState* pOptState );
+
+static tSuccess
+nextOption( tOptions* pOpts, tOptState* pOptState );
+
+static tSuccess
+doPresets( tOptions* pOpts );
+
+static int
+checkConsistency( tOptions* pOpts );
+/* = = = END-STATIC-FORWARD = = = */
+
+/*
+ *  handleOption
+ *
+ *  This routine handles equivalencing, sets the option state flags and
+ *  invokes the handler procedure, if any.
+ */
+LOCAL tSuccess
+handleOption( tOptions* pOpts, tOptState* pOptState )
+{
+    /*
+     *  Save a copy of the option procedure pointer.
+     *  If this is an equivalence class option, we still want this proc.
+     */
+    tOptDesc* pOD = pOptState->pOD;
+    tOptProc* pOP = pOD->pOptProc;
+
+    pOD->pzLastArg =  pOptState->pzOptArg;
+
+    /*
+     *  IF we are presetting options, then we will ignore any un-presettable
+     *  options.  They are the ones either marked as such.
+     */
+    if (  ((pOpts->fOptSet & OPTPROC_PRESETTING) != 0)
+       && ((pOD->fOptState & OPTST_NO_INIT) != 0)
+       )
+        return PROBLEM;
+
+    /*
+     *  IF this is an equivalence class option,
+     *  THEN
+     *      Save the option value that got us to this option
+     *      entry.  (It may not be pOD->optChar[0], if this is an
+     *      equivalence entry.)
+     *      set the pointer to the equivalence class base
+     */
+    if (pOD->optEquivIndex != NO_EQUIVALENT) {
+        tOptDesc* p = pOpts->pOptDesc + pOD->optEquivIndex;
+
+        /*
+         * IF the current option state has not been defined (set on the
+         *    command line), THEN we will allow continued resetting of
+         *    the value.  Once "defined", then it must not change.
+         */
+        if ((pOD->fOptState & OPTST_DEFINED) != 0) {
+            /*
+             *  The equivalenced-to option has been found on the command
+             *  line before.  Make sure new occurrences are the same type.
+             *
+             *  IF this option has been previously equivalenced and
+             *     it was not the same equivalenced-to option,
+             *  THEN we have a usage problem.
+             */
+            if (p->optActualIndex != pOD->optIndex) {
+                fprintf( stderr, (char*)zMultiEquiv, p->pz_Name, pOD->pz_Name,
+                         (pOpts->pOptDesc + p->optActualIndex)->pz_Name);
+                return FAILURE;
+            }
+        } else {
+            /*
+             *  Set the equivalenced-to actual option index to no-equivalent
+             *  so that we set all the entries below.  This option may either
+             *  never have been selected before, or else it was selected by
+             *  some sort of "presetting" mechanism.
+             */
+            p->optActualIndex = NO_EQUIVALENT;
+        }
+
+        if (p->optActualIndex != pOD->optIndex) {
+            /*
+             *  First time through, copy over the state
+             *  and add in the equivalence flag
+             */
+            p->optActualValue = pOD->optValue;
+            p->optActualIndex = pOD->optIndex;
+            pOptState->flags |= OPTST_EQUIVALENCE;
+        }
+
+        /*
+         *  Copy the most recent option argument.  set membership state
+         *  is kept in ``p->optCookie''.  Do not overwrite.
+         */
+        p->pzLastArg = pOD->pzLastArg;
+        pOD = p;
+
+    } else {
+        pOD->optActualValue = pOD->optValue;
+        pOD->optActualIndex = pOD->optIndex;
+    }
+
+    pOD->fOptState &= OPTST_PERSISTENT;
+    pOD->fOptState |= (pOptState->flags & ~OPTST_PERSISTENT);
+
+    /*
+     *  Keep track of count only for DEFINED (command line) options.
+     *  IF we have too many, build up an error message and bail.
+     */
+    if (  (pOD->fOptState & OPTST_DEFINED)
+       && (++pOD->optOccCt > pOD->optMaxCt)  )  {
+        const char* pzEqv =
+            (pOD->optEquivIndex != NO_EQUIVALENT) ? zEquiv : zNil;
+
+        if ((pOpts->fOptSet & OPTPROC_ERRSTOP) != 0) {
+            const char* pzFmt = (pOD->optMaxCt > 1) ? zAtMost : zOnlyOne;
+            fputs( zErrOnly, stderr );
+            fprintf( stderr, pzFmt, pOD->pz_Name, pzEqv,
+                     pOD->optMaxCt );
+        }
+
+        return FAILURE;
+    }
+
+    /*
+     *  If provided a procedure to call, call it
+     */
+    if (pOP != (tpOptProc)NULL)
+        (*pOP)( pOpts, pOD );
+
+    return SUCCESS;
+}
+
+
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ *
+ *  HUNT FOR OPTIONS IN THE ARGUMENT LIST
+ *
+ *  The next four procedures are "private" to nextOption().
+ *  nextOption() uses findOptDesc() to find the next descriptor and it, in
+ *  turn, uses longOptionFind() and shortOptionFind() to actually do the hunt.
+ *
+ *  longOptionFind
+ *
+ *  Find the long option descriptor for the current option
+ */
+LOCAL tSuccess
+longOptionFind( tOptions* pOpts, char* pzOptName, tOptState* pOptState )
+{
+    ag_bool    disable  = AG_FALSE;
+    char*      pzEq     = strchr( pzOptName, '=' );
+    tOptDesc*  pOD      = pOpts->pOptDesc;
+    int        idx      = 0;
+    int        idxLim   = pOpts->optCt;
+    int        matchCt  = 0;
+    int        matchIdx = 0;
+    int        nameLen;
+
+    /*
+     *  IF the value is attached to the name,
+     *  THEN clip it off.
+     *  Either way, figure out how long our name is
+     */
+    if (pzEq != NULL) {
+        nameLen = (int)(pzEq - pzOptName);
+        *pzEq = NUL;
+    } else nameLen = strlen( pzOptName );
+
+    do  {
+        if (SKIP_OPT(pOD))
+            continue;
+
+        if (strneqvcmp( pzOptName, pOD->pz_Name, nameLen ) == 0) {
+            /*
+             *  IF we have a complete match
+             *  THEN it takes priority over any already located partial
+             */
+            if (pOD->pz_Name[ nameLen ] == NUL) {
+                matchCt  = 1;
+                matchIdx = idx;
+                break;
+            }
+        }
+
+        /*
+         *  IF       there is a disable name
+         *     *AND* no argument value has been supplied
+         *              (disabled options may have no argument)
+         *     *AND* the option name matches the disable name
+         *  THEN ...
+         */
+        else if (  (pOD->pz_DisableName != NULL)
+                && (strneqvcmp(pzOptName, pOD->pz_DisableName, nameLen) == 0)
+                )  {
+            disable  = AG_TRUE;
+
+            /*
+             *  IF we have a complete match
+             *  THEN it takes priority over any already located partial
+             */
+            if (pOD->pz_DisableName[ nameLen ] == NUL) {
+                matchCt  = 1;
+                matchIdx = idx;
+                break;
+            }
+        }
+
+        else
+            continue;
+
+        /*
+         *  We found a partial match, either regular or disabling.
+         *  Remember the index for later.
+         */
+        matchIdx = idx;
+
+        if (++matchCt > 1)
+            break;
+
+    } while (pOD++, (++idx < idxLim));
+
+    if (pzEq != NULL)
+        *(pzEq++) = '=';
+
+    /*
+     *  Make sure we either found an exact match or found only one partial
+     */
+    if (matchCt == 1) {
+        /*
+         *  IF we found a disablement name,
+         *  THEN set the bit in the callers' flag word
+         */
+        if (disable)
+            pOptState->flags |= OPTST_DISABLED;
+
+        pOptState->pOD      = pOpts->pOptDesc + matchIdx;
+        pOptState->pzOptArg = pzEq;
+        pOptState->optType  = TOPT_LONG;
+        return SUCCESS;
+    }
+
+    /*
+     *  IF there is no equal sign
+     *     *AND* we are using named arguments
+     *     *AND* there is a default named option,
+     *  THEN return that option.
+     */
+    if (  (pzEq == NULL)
+       && NAMED_OPTS(pOpts)
+       && (pOpts->specOptIdx.default_opt != NO_EQUIVALENT)) {
+        pOptState->pOD = pOpts->pOptDesc + pOpts->specOptIdx.default_opt;
+
+        pOptState->pzOptArg = pzOptName;
+        pOptState->optType  = TOPT_DEFAULT;
+        return SUCCESS;
+    }
+
+    /*
+     *  IF we are to stop on errors (the default, actually)
+     *  THEN call the usage procedure.
+     */
+    if ((pOpts->fOptSet & OPTPROC_ERRSTOP) != 0) {
+        fprintf( stderr, zIllOptStr, pOpts->pzProgPath,
+                 (matchCt == 0) ? zIllegal : zAmbiguous, pzOptName );
+        (*pOpts->pUsageProc)( pOpts, EXIT_FAILURE );
+    }
+
+    return FAILURE;
+}
+
+
+/*
+ *  shortOptionFind
+ *
+ *  Find the short option descriptor for the current option
+ */
+LOCAL tSuccess
+shortOptionFind( tOptions* pOpts, tAoUC optValue, tOptState* pOptState )
+{
+    tOptDesc*  pRes = pOpts->pOptDesc;
+    int        ct   = pOpts->optCt;
+
+    /*
+     *  Search the option list
+     */
+    for (;;) {
+        /*
+         *  IF the values match,
+         *  THEN we stop here
+         */
+        if ((! SKIP_OPT(pRes)) && (optValue == pRes->optValue)) {
+            pOptState->pOD     = pRes;
+            pOptState->optType = TOPT_SHORT;
+            return SUCCESS;
+        }
+
+        /*
+         *  Advance to next option description
+         */
+        pRes++;
+
+        /*
+         *  IF we have searched everything, ...
+         */
+        if (--ct <= 0)
+            break;
+    }
+
+    /*
+     *  IF    the character value is a digit
+     *    AND there is a special number option ("-n")
+     *  THEN the result is the "option" itself and the
+     *       option is the specially marked "number" option.
+     */
+    if (  isdigit( optValue )
+       && (pOpts->specOptIdx.number_option != NO_EQUIVALENT) ) {
+        pOptState->pOD = \
+        pRes           = pOpts->pOptDesc + pOpts->specOptIdx.number_option;
+        (pOpts->pzCurOpt)--;
+        pOptState->optType = TOPT_SHORT;
+        return SUCCESS;
+    }
+
+    /*
+     *  IF we are to stop on errors (the default, actually)
+     *  THEN call the usage procedure.
+     */
+    if ((pOpts->fOptSet & OPTPROC_ERRSTOP) != 0) {
+        fprintf( stderr, zIllOptChr, pOpts->pzProgPath, optValue );
+        (*pOpts->pUsageProc)( pOpts, EXIT_FAILURE );
+    }
+
+    return FAILURE;
+}
+
+
+/*
+ *  findOptDesc
+ *
+ *  Find the option descriptor for the current option
+ */
+static tSuccess
+findOptDesc( tOptions* pOpts, tOptState* pOptState )
+{
+    /*
+     *  IF we are continuing a short option list (e.g. -xyz...)
+     *  THEN continue a single flag option.
+     *  OTHERWISE see if there is room to advance and then do so.
+     */
+    if ((pOpts->pzCurOpt != NULL) && (*pOpts->pzCurOpt != NUL))
+        return shortOptionFind( pOpts, *pOpts->pzCurOpt, pOptState );
+
+    if (pOpts->curOptIdx >= pOpts->origArgCt)
+        return PROBLEM; /* NORMAL COMPLETION */
+
+    pOpts->pzCurOpt = pOpts->origArgVect[ pOpts->curOptIdx ];
+
+    /*
+     *  IF all arguments must be named options, ...
+     */
+    if (NAMED_OPTS(pOpts)) {
+        char* pz = pOpts->pzCurOpt;
+        pOpts->curOptIdx++;
+
+        /*
+         *  Skip over any flag/option markers.
+         *  In this mode, they are not required.
+         */
+        while (*pz == '-') pz++;
+
+        return longOptionFind( pOpts, pz, pOptState );
+    }
+
+    /*
+     *  Note the kind of flag/option marker
+     */
+    if (*((pOpts->pzCurOpt)++) != '-')
+        return PROBLEM; /* NORMAL COMPLETION - this + rest are operands */
+
+    /*
+     *  Special hack for a hyphen by itself
+     */
+    if (*(pOpts->pzCurOpt) == NUL)
+        return PROBLEM; /* NORMAL COMPLETION - this + rest are operands */
+
+    /*
+     *  The current argument is to be processed as an option argument
+     */
+    pOpts->curOptIdx++;
+
+    /*
+     *  We have an option marker.
+     *  Test the next character for long option indication
+     */
+    if (pOpts->pzCurOpt[0] == '-') {
+        if (*++(pOpts->pzCurOpt) == NUL)
+            /*
+             *  NORMAL COMPLETION - NOT this arg, but rest are operands
+             */
+            return PROBLEM;
+
+        /*
+         *  We do not allow the hyphen to be used as a flag value.
+         *  Therefore, if long options are not to be accepted, we punt.
+         */
+        if ((pOpts->fOptSet & OPTPROC_LONGOPT) == 0) {
+            fprintf( stderr, zIllOptStr, pOpts->pzProgPath,
+                     zIllegal, pOpts->pzCurOpt-2 );
+            return FAILURE;
+        }
+
+        return longOptionFind( pOpts, pOpts->pzCurOpt, pOptState );
+    }
+
+    /*
+     *  If short options are not allowed, then do long
+     *  option processing.  Otherwise the character must be a
+     *  short (i.e. single character) option.
+     */
+    if ((pOpts->fOptSet & OPTPROC_SHORTOPT) != 0)
+        return shortOptionFind( pOpts, *pOpts->pzCurOpt, pOptState );
+
+    return longOptionFind( pOpts, pOpts->pzCurOpt, pOptState );
+}
+
+
+/*
+ *  nextOption
+ *
+ *  Find the option descriptor and option argument (if any) for the
+ *  next command line argument.  DO NOT modify the descriptor.  Put
+ *  all the state in the state argument so that the option can be skipped
+ *  without consequence (side effect).
+ */
+static tSuccess
+nextOption( tOptions* pOpts, tOptState* pOptState )
+{
+    tSuccess res;
+    enum { ARG_NONE, ARG_MAY, ARG_MUST } arg_type = ARG_NONE;
+
+    res = findOptDesc( pOpts, pOptState );
+    if (! SUCCESSFUL( res ))
+        return res;
+    pOptState->flags |= (pOptState->pOD->fOptState & OPTST_PERSISTENT);
+
+    /*
+     *  Figure out what to do about option arguments.  An argument may be
+     *  required, not associated with the option, or be optional.  We detect the
+     *  latter by examining for an option marker on the next possible argument.
+     *  Disabled mode option selection also disables option arguments.
+     */
+    if ((pOptState->flags & OPTST_DISABLED) != 0)
+        arg_type = ARG_NONE;
+    else if (OPTST_GET_ARGTYPE(pOptState->flags) == OPARG_TYPE_NONE)
+        arg_type = ARG_NONE;
+    else if (pOptState->flags & OPTST_ARG_OPTIONAL)
+        arg_type = ARG_MAY;
+    else
+        arg_type = ARG_MUST;
+
+    switch (arg_type) {
+    case ARG_MUST:
+        /*
+         *  An option argument is required.  Long options can either have
+         *  a separate command line argument, or an argument attached by
+         *  the '=' character.  Figure out which.
+         */
+        switch (pOptState->optType) {
+        case TOPT_SHORT:
+            /*
+             *  See if an arg string follows the flag character
+             */
+            if (*++(pOpts->pzCurOpt) == NUL)
+                pOpts->pzCurOpt = pOpts->origArgVect[ pOpts->curOptIdx++ ];
+            pOptState->pzOptArg = pOpts->pzCurOpt;
+            break;
+
+        case TOPT_LONG:
+            /*
+             *  See if an arg string has already been assigned (glued on
+             *  with an `=' character)
+             */
+            if (pOptState->pzOptArg == NULL)
+                pOptState->pzOptArg = pOpts->origArgVect[ pOpts->curOptIdx++ ];
+            break;
+
+        default:
+#ifdef DEBUG
+            fputs( "AutoOpts lib error: option type not selected\n",
+                   stderr );
+            exit( EXIT_FAILURE );
+#endif
+
+        case TOPT_DEFAULT:
+            /*
+             *  The option was selected by default.  The current token is
+             *  the option argument.
+             */
+            break;
+        }
+
+        /*
+         *  Make sure we did not overflow the argument list.
+         */
+        if (pOpts->curOptIdx > pOpts->origArgCt) {
+            fprintf( stderr, zMisArg, pOpts->pzProgPath,
+                     pOptState->pOD->pz_Name );
+            return FAILURE;
+        }
+
+        pOpts->pzCurOpt = NULL;  /* next time advance to next arg */
+        break;
+
+    case ARG_MAY:
+        /*
+         *  An option argument is optional.
+         */
+        switch (pOptState->optType) {
+        case TOPT_SHORT:
+            if (*++pOpts->pzCurOpt != NUL)
+                pOptState->pzOptArg = pOpts->pzCurOpt;
+            else {
+                char* pzLA = pOpts->origArgVect[ pOpts->curOptIdx ];
+
+                /*
+                 *  BECAUSE it is optional, we must make sure
+                 *  we did not find another flag and that there
+                 *  is such an argument.
+                 */
+                if ((pzLA == NULL) || (*pzLA == '-'))
+                    pOptState->pzOptArg = NULL;
+                else {
+                    pOpts->curOptIdx++; /* argument found */
+                    pOptState->pzOptArg = pzLA;
+                }
+            }
+            break;
+
+        case TOPT_LONG:
+            /*
+             *  Look for an argument if we don't already have one (glued on
+             *  with a `=' character) *AND* we are not in named argument mode
+             */
+            if (  (pOptState->pzOptArg == NULL)
+               && (! NAMED_OPTS(pOpts))) {
+                char* pzLA = pOpts->origArgVect[ pOpts->curOptIdx ];
+
+                /*
+                 *  BECAUSE it is optional, we must make sure
+                 *  we did not find another flag and that there
+                 *  is such an argument.
+                 */
+                if ((pzLA == NULL) || (*pzLA == '-'))
+                    pOptState->pzOptArg = NULL;
+                else {
+                    pOpts->curOptIdx++; /* argument found */
+                    pOptState->pzOptArg = pzLA;
+                }
+            }
+            break;
+
+        default:
+        case TOPT_DEFAULT:
+            fputs( "AutoOpts lib error: defaulted to option with optional arg\n",
+                   stderr );
+            exit( EXIT_FAILURE );
+        }
+
+        /*
+         *  After an option with an optional argument, we will
+         *  *always* start with the next option because if there
+         *  were any characters following the option name/flag,
+         *  they would be interpreted as the argument.
+         */
+        pOpts->pzCurOpt = NULL;
+        break;
+
+    default: /* CANNOT */
+        /*
+         *  No option argument.  Make sure next time around we find
+         *  the correct option flag character for short options
+         */
+        if (pOptState->optType == TOPT_SHORT)
+            (pOpts->pzCurOpt)++;
+
+        /*
+         *  It is a long option.  Make sure there was no ``=xxx'' argument
+         */
+        else if (pOptState->pzOptArg != NULL) {
+            fprintf( stderr, zNoArg, pOpts->pzProgPath,
+                     pOptState->pOD->pz_Name );
+            return FAILURE;
+        }
+
+        /*
+         *  It is a long option.  Advance to next command line argument.
+         */
+        else
+            pOpts->pzCurOpt = NULL;
+    }
+
+    return SUCCESS;
+}
+
+
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ *
+ *  DO PRESETS
+ *
+ *  The next several routines do the immediate action pass on the command
+ *  line options, then the environment variables, then the config files in
+ *  reverse order.  Once done with that, the order is reversed and all
+ *  the config files and environment variables are processed again, this
+ *  time only processing the non-immediate action options.  doPresets()
+ *  will then return for optionProcess() to do the final pass on the command
+ *  line arguments.
+ */
+
+/*
+ *  doImmediateOpts - scan the command line for immediate action options
+ */
+LOCAL tSuccess
+doImmediateOpts( tOptions* pOpts )
+{
+    pOpts->curOptIdx = 1;     /* start by skipping program name */
+    pOpts->pzCurOpt  = NULL;
+
+    /*
+     *  Examine all the options from the start.  We process any options that
+     *  are marked for immediate processing.
+     */
+    for (;;) {
+        tOptState optState = OPTSTATE_INITIALIZER(PRESET);
+
+        switch (nextOption( pOpts, &optState )) {
+        case FAILURE: goto optionsDone;
+        case PROBLEM: return SUCCESS; /* no more args */
+        case SUCCESS: break;
+        }
+
+        /*
+         *  IF this *is* an immediate-attribute option, then do it.
+         */
+        if (! DO_IMMEDIATELY(optState.flags))
+            continue;
+
+        if (! SUCCESSFUL( handleOption( pOpts, &optState )))
+            break;
+    } optionsDone:;
+
+    if ((pOpts->fOptSet & OPTPROC_ERRSTOP) != 0)
+        (*pOpts->pUsageProc)( pOpts, EXIT_FAILURE );
+    return FAILURE;
+}
+
+
+LOCAL tSuccess
+doRegularOpts( tOptions* pOpts )
+{
+    /*
+     *  Now, process all the options from our current position onward.
+     *  (This allows interspersed options and arguments for the few
+     *  non-standard programs that require it.)
+     */
+    for (;;) {
+        tOptState optState = OPTSTATE_INITIALIZER(DEFINED);
+
+        switch (nextOption( pOpts, &optState )) {
+        case FAILURE: goto optionsDone;
+        case PROBLEM: return SUCCESS; /* no more args */
+        case SUCCESS: break;
+        }
+
+        /*
+         *  IF this is not being processed normally (i.e. is immediate action)
+         *  THEN skip it (unless we are supposed to do it a second time).
+         */
+        if (! DO_NORMALLY(optState.flags)) {
+            if (! DO_SECOND_TIME(optState.flags))
+                continue;
+            optState.pOD->optOccCt--; /* don't count last time */
+        }
+
+        if (! SUCCESSFUL( handleOption( pOpts, &optState )))
+            break;
+    } optionsDone:;
+    if ((pOpts->fOptSet & OPTPROC_ERRSTOP) != 0)
+        (*pOpts->pUsageProc)( pOpts, EXIT_FAILURE );
+    return FAILURE;
+}
+
+
+/*
+ *  doPresets - check for preset values from a config file or the envrionment
+ */
+static tSuccess
+doPresets( tOptions* pOpts )
+{
+    if (! SUCCESSFUL( doImmediateOpts( pOpts )))
+        return FAILURE;
+
+    /*
+     *  Until we return from this procedure, disable non-presettable opts
+     */
+    pOpts->fOptSet |= OPTPROC_PRESETTING;
+    /*
+     *  IF there are no config files,
+     *  THEN do any environment presets and leave.
+     */
+    if (  (pOpts->papzHomeList == NULL)
+       || SKIP_RC_FILES(pOpts) )  {
+        doEnvPresets( pOpts, ENV_ALL );
+    }
+    else {
+        doEnvPresets( pOpts, ENV_IMM );
+        internalFileLoad( pOpts );
+        doEnvPresets( pOpts, ENV_NON_IMM );
+    }
+    pOpts->fOptSet &= ~OPTPROC_PRESETTING;
+
+    return SUCCESS;
+}
+
+
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ *
+ *  VERIFY OPTION CONSISTENCY
+ *
+ *  Make sure that the argument list passes our consistency tests.
+ */
+static int
+checkConsistency( tOptions* pOpts )
+{
+    int        errCt = 0;
+    tOptDesc*  pOD   = pOpts->pOptDesc;
+    int        oCt   = pOpts->presetOptCt;
+
+    /*
+     *  FOR each of "oCt" options, ...
+     */
+    for (;;) {
+        const int*  pMust = pOD->pOptMust;
+        const int*  pCant = pOD->pOptCant;
+
+        /*
+         *  IF the current option was provided on the command line
+         *  THEN ensure that any "MUST" requirements are not
+         *       "DEFAULT" (unspecified) *AND* ensure that any
+         *       "CANT" options have not been SET or DEFINED.
+         */
+        if (SELECTED_OPT(pOD)) {
+            if (pMust != NULL) for (;;) {
+                tOptDesc*  p = pOpts->pOptDesc + *(pMust++);
+                if (UNUSED_OPT(p)) {
+                    const tOptDesc* pN = pOpts->pOptDesc + pMust[-1];
+                    errCt++;
+                    fprintf( stderr, zReqFmt, pOD->pz_Name, pN->pz_Name );
+                }
+
+                if (*pMust == NO_EQUIVALENT)
+                    break;
+            }
+
+            if (pCant != NULL) for (;;) {
+                tOptDesc*  p = pOpts->pOptDesc + *(pCant++);
+                if (SELECTED_OPT(p)) {
+                    const tOptDesc* pN = pOpts->pOptDesc + pCant[-1];
+                    errCt++;
+                    fprintf( stderr, zCantFmt, pOD->pz_Name, pN->pz_Name );
+                }
+
+                if (*pCant == NO_EQUIVALENT)
+                    break;
+            }
+        }
+
+        /*
+         *  IF       this option is not equivalenced to another,
+         *        OR it is equivalenced to itself (is the equiv. root)
+         *  THEN we need to make sure it occurs often enough.
+         */
+        if (  (pOD->optEquivIndex == NO_EQUIVALENT)
+           || (pOD->optEquivIndex == pOD->optIndex) )   do {
+            /*
+             *  IF the occurrence counts have been satisfied,
+             *  THEN there is no problem.
+             */
+            if (pOD->optOccCt >= pOD->optMinCt)
+                break;
+
+            /*
+             *  IF MUST_SET means SET and PRESET are okay,
+             *  so min occurrence count doesn't count
+             */
+            if (  (pOD->fOptState & OPTST_MUST_SET)
+               && (pOD->fOptState & (OPTST_PRESET | OPTST_SET)) )
+                break;
+
+            errCt++;
+            if (pOD->optMinCt > 1)
+                fprintf( stderr, zNotEnough, pOD->pz_Name, pOD->optMinCt );
+            else fprintf( stderr, zNeedOne, pOD->pz_Name );
+           } while (0);
+
+        if (--oCt <= 0)
+            break;
+        pOD++;
+    }
+
+    /*
+     *  IF we are stopping on errors, check to see if any remaining
+     *  arguments are required to be there or prohibited from being there.
+     */
+    if ((pOpts->fOptSet & OPTPROC_ERRSTOP) != 0) {
+
+        /*
+         *  Check for prohibition
+         */
+        if ((pOpts->fOptSet & OPTPROC_NO_ARGS) != 0) {
+            if (pOpts->origArgCt > pOpts->curOptIdx) {
+                fprintf( stderr, zNoArgs, pOpts->pzProgName );
+                ++errCt;
+            }
+        }
+
+        /*
+         *  ELSE not prohibited, check for being required
+         */
+        else if ((pOpts->fOptSet & OPTPROC_ARGS_REQ) != 0) {
+            if (pOpts->origArgCt <= pOpts->curOptIdx) {
+                fprintf( stderr, zArgsMust, pOpts->pzProgName );
+                ++errCt;
+            }
+        }
+    }
+
+    return errCt;
+}
+
+
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ *
+ *  THESE ROUTINES ARE CALLABLE FROM THE GENERATED OPTION PROCESSING CODE
+ */
+/*=--subblock=arg=arg_type,arg_name,arg_desc =*/
+/*=*
+ * library:  opts
+ * header:   your-opts.h
+ *
+ * lib_description:
+ *
+ *  These are the routines that libopts users may call directly from their
+ *  code.  There are several other routines that can be called by code
+ *  generated by the libopts option templates, but they are not to be
+ *  called from any other user code.  The @file{options.h} header is
+ *  fairly clear about this, too.
+=*/
+
+/*=export_func optionProcess
+ *
+ * what: this is the main option processing routine
+ *
+ * arg:  + tOptions* + pOpts + program options descriptor +
+ * arg:  + int       + argc  + program arg count  +
+ * arg:  + char**    + argv  + program arg vector +
+ *
+ * ret_type:  int
+ * ret_desc:  the count of the arguments processed
+ *
+ * doc:
+ *
+ * This is the main entry point for processing options.  It is intended
+ * that this procedure be called once at the beginning of the execution of
+ * a program.  Depending on options selected earlier, it is sometimes
+ * necessary to stop and restart option processing, or to select completely
+ * different sets of options.  This can be done easily, but you generally
+ * do not want to do this.
+ *
+ * The number of arguments processed always includes the program name.
+ * If one of the arguments is "--", then it is counted and the processing
+ * stops.  If an error was encountered and errors are to be tolerated, then
+ * the returned value is the index of the argument causing the error.
+ * A hyphen by itself ("-") will also cause processing to stop and will
+ * @emph{not} be counted among the processed arguments.  A hyphen by itself
+ * is treated as an operand.  Encountering an operand stops option
+ * processing.
+ *
+ * err:  Errors will cause diagnostics to be printed.  @code{exit(3)} may
+ *       or may not be called.  It depends upon whether or not the options
+ *       were generated with the "allow-errors" attribute, or if the
+ *       ERRSKIP_OPTERR or ERRSTOP_OPTERR macros were invoked.
+=*/
+int
+optionProcess(
+    tOptions*  pOpts,
+    int        argCt,
+    char**     argVect )
+{
+    if (! SUCCESSFUL( validateOptionsStruct( pOpts, argVect[0] )))
+        exit( EXIT_FAILURE );
+
+    /*
+     *  Establish the real program name, the program full path,
+     *  and do all the presetting the first time thru only.
+     */
+    if ((pOpts->fOptSet & OPTPROC_INITDONE) == 0) {
+        pOpts->origArgCt   = argCt;
+        pOpts->origArgVect = argVect;
+        pOpts->fOptSet    |= OPTPROC_INITDONE;
+
+        if (! SUCCESSFUL( doPresets( pOpts )))
+            return 0;
+
+        if ((pOpts->fOptSet & OPTPROC_REORDER) != 0)
+            optionSort( pOpts );
+
+        pOpts->curOptIdx   = 1;
+        pOpts->pzCurOpt    = NULL;
+    }
+
+    /*
+     *  IF we are (re)starting,
+     *  THEN reset option location
+     */
+    else if (pOpts->curOptIdx <= 0) {
+        pOpts->curOptIdx = 1;
+        pOpts->pzCurOpt  = NULL;
+    }
+
+    if (! SUCCESSFUL( doRegularOpts( pOpts )))
+        return pOpts->origArgCt;
+
+    /*
+     *  IF    there were no errors
+     *    AND we have RC/INI files
+     *    AND there is a request to save the files
+     *  THEN do that now before testing for conflicts.
+     *       (conflicts are ignored in preset options)
+     */
+    if (pOpts->specOptIdx.save_opts != 0) {
+        tOptDesc*  pOD = pOpts->pOptDesc + pOpts->specOptIdx.save_opts;
+
+        if (SELECTED_OPT( pOD )) {
+            optionSaveFile( pOpts );
+            exit( EXIT_SUCCESS );
+        }
+    }
+
+    /*
+     *  IF we are checking for errors,
+     *  THEN look for too few occurrences of required options
+     */
+    if ((pOpts->fOptSet & OPTPROC_ERRSTOP) != 0) {
+        if (checkConsistency( pOpts ) != 0)
+            (*pOpts->pUsageProc)( pOpts, EXIT_FAILURE );
+    }
+
+    return pOpts->curOptIdx;
+}
+
+/*
+ * Local Variables:
+ * mode: C
+ * c-file-style: "stroustrup"
+ * tab-width: 4
+ * indent-tabs-mode: nil
+ * End:
+ * end of autoopts/autoopts.c */
diff --git a/libopts/autoopts.h b/libopts/autoopts.h
new file mode 100644 (file)
index 0000000..af01f07
--- /dev/null
@@ -0,0 +1,321 @@
+
+/*
+ *  Time-stamp:      "2005-10-29 15:06:44 bkorb"
+ *
+ *  autoopts.h  $Id: autoopts.h,v 4.17 2006/03/25 19:24:56 bkorb Exp $
+ *  Time-stamp:      "2005-02-14 05:59:50 bkorb"
+ *
+ *  This file defines all the global structures and special values
+ *  used in the automated option processing library.
+ */
+
+/*
+ *  Automated Options copyright 1992-2006 Bruce Korb
+ *
+ *  Automated Options is free software.
+ *  You may redistribute it and/or modify it under the terms of the
+ *  GNU General Public License, as published by the Free Software
+ *  Foundation; either version 2, or (at your option) any later version.
+ *
+ *  Automated Options is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with Automated Options.  See the file "COPYING".  If not,
+ *  write to:  The Free Software Foundation, Inc.,
+ *             51 Franklin Street, Fifth Floor,
+ *             Boston, MA  02110-1301, USA.
+ *
+ * As a special exception, Bruce Korb gives permission for additional
+ * uses of the text contained in his release of AutoOpts.
+ *
+ * The exception is that, if you link the AutoOpts library with other
+ * files to produce an executable, this does not by itself cause the
+ * resulting executable to be covered by the GNU General Public License.
+ * Your use of that executable is in no way restricted on account of
+ * linking the AutoOpts library code into it.
+ *
+ * This exception does not however invalidate any other reasons why
+ * the executable file might be covered by the GNU General Public License.
+ *
+ * This exception applies only to the code released by Bruce Korb under
+ * the name AutoOpts.  If you copy code from other sources under the
+ * General Public License into a copy of AutoOpts, as the General Public
+ * License permits, the exception does not apply to the code that you add
+ * in this way.  To avoid misleading anyone as to the status of such
+ * modified files, you must delete this exception notice from them.
+ *
+ * If you write modifications of your own for AutoOpts, it is your choice
+ * whether to permit this exception to apply to your modifications.
+ * If you do not wish that, delete this exception notice.
+ */
+
+#ifndef AUTOGEN_AUTOOPTS_H
+#define AUTOGEN_AUTOOPTS_H
+
+#include "compat/compat.h"
+
+#define AO_NAME_LIMIT    127
+#define AO_NAME_SIZE     (AO_NAME_LIMIT + 1)
+
+#ifndef MAXPATHLEN
+#  ifdef PATH_MAX
+#    define MAXPATHLEN   PATH_MAX
+#  else
+#    define MAXPATHLEN   4096
+#  endif
+#else
+#  if defined(PATH_MAX) && (PATH_MAX > MAXPATHLEN)
+#     undef  MAXPATHLEN
+#     define MAXPATHLEN  PATH_MAX
+#  endif
+#endif
+
+#undef  EXPORT
+#define EXPORT
+
+/*
+ *  Convert the number to a list usable in a printf call
+ */
+#define NUM_TO_VER(n)       ((n) >> 12), ((n) >> 7) & 0x001F, (n) & 0x007F
+
+#define NAMED_OPTS(po) \
+        (((po)->fOptSet & (OPTPROC_SHORTOPT | OPTPROC_LONGOPT)) == 0)
+
+#define SKIP_OPT(p)  (((p)->fOptState & (OPTST_DOCUMENT|OPTST_OMITTED)) != 0)
+
+typedef int tDirection;
+#define DIRECTION_PRESET  -1
+#define DIRECTION_PROCESS  1
+#define DIRECTION_CALLED   0
+
+#define PROCESSING(d)     ((d)>0)
+#define PRESETTING(d)     ((d)<0)
+
+#define ISNAMECHAR( c )    (isalnum(c) || ((c) == '_') || ((c) == '-'))
+
+/*
+ *  Procedure success codes
+ *
+ *  USAGE:  define procedures to return "tSuccess".  Test their results
+ *          with the SUCCEEDED, FAILED and HADGLITCH macros.
+ */
+#define SUCCESS  ((tSuccess) 0)
+#define FAILURE  ((tSuccess)-1)
+#define PROBLEM  ((tSuccess) 1)
+
+typedef int tSuccess;
+
+#define SUCCEEDED( p )     ((p) == SUCCESS)
+#define SUCCESSFUL( p )    SUCCEEDED( p )
+#define FAILED( p )        ((p) <  SUCCESS)
+#define HADGLITCH( p )     ((p) >  SUCCESS)
+
+/*
+ *  The pager state is used by optionPagedUsage() procedure.
+ *  When it runs, it sets itself up to be called again on exit.
+ *  If, however, a routine needs a child process to do some work
+ *  before it is done, then 'pagerState' must be set to
+ *  'PAGER_STATE_CHILD' so that optionPagedUsage() will not try
+ *  to run the pager program before its time.
+ */
+typedef enum {
+    PAGER_STATE_INITIAL,
+    PAGER_STATE_READY,
+    PAGER_STATE_CHILD
+} tePagerState;
+
+extern tePagerState pagerState;
+
+typedef enum {
+    ENV_ALL,
+    ENV_IMM,
+    ENV_NON_IMM
+} teEnvPresetType;
+
+typedef enum {
+    TOPT_UNDEFINED = 0,
+    TOPT_SHORT,
+    TOPT_LONG,
+    TOPT_DEFAULT
+} teOptType;
+
+typedef struct {
+    tOptDesc*  pOD;
+    tCC*       pzOptArg;
+    tAoUL      flags;
+    teOptType  optType;
+} tOptState;
+#define OPTSTATE_INITIALIZER(st) \
+    { NULL, NULL, OPTST_ ## st, TOPT_UNDEFINED }
+
+#define TEXTTO_TABLE \
+        _TT_( LONGUSAGE ) \
+        _TT_( USAGE ) \
+        _TT_( VERSION )
+#define _TT_(n) \
+        TT_ ## n ,
+
+typedef enum { TEXTTO_TABLE COUNT_TT } teTextTo;
+
+#undef _TT_
+
+typedef struct {
+    tCC*    pzStr;
+    tCC*    pzReq;
+    tCC*    pzNum;
+    tCC*    pzKey;
+    tCC*    pzKeyL;
+    tCC*    pzBool;
+    tCC*    pzNest;
+    tCC*    pzOpt;
+    tCC*    pzNo;
+    tCC*    pzBrk;
+    tCC*    pzNoF;
+    tCC*    pzSpc;
+    tCC*    pzOptFmt;
+} arg_types_t;
+
+#  define AGALOC( c, w )        malloc( c )
+#  define AGREALOC( p, c, w )   realloc( p, c )
+#  define AGFREE( p )           free( p )
+#  define AGDUPSTR( p, s, w )   p = strdup( s )
+#  define TAGMEM( m, t )
+
+#ifdef AUTOGEN_BUILD
+#  include <snprintfv/printf.h>
+#endif /* AUTOGEN_BUILD */
+
+/*
+ *  DO option handling?
+ *
+ *  Options are examined at two times:  at immediate handling time and at
+ *  normal handling time.  If an option is disabled, the timing may be
+ *  different from the handling of the undisabled option.  The OPTST_DIABLED
+ *  bit indicates the state of the currently discovered option.
+ *  So, here's how it works:
+ *
+ *  A) handling at "immediate" time, either 1 or 2:
+ *
+ *  1.  OPTST_DISABLED is not set:
+ *      IMM           must be set
+ *      DISABLE_IMM   don't care
+ *      TWICE         don't care
+ *      DISABLE_TWICE don't care
+ *      0 -and-  1 x x x
+ *
+ *  2.  OPTST_DISABLED is set:
+ *      IMM           don't care
+ *      DISABLE_IMM   must be set
+ *      TWICE         don't care
+ *      DISABLE_TWICE don't care
+ *      1 -and-  x 1 x x
+ */
+#define DO_IMMEDIATELY(_flg) \
+    (  (((_flg) & (OPTST_DISABLED|OPTST_IMM)) == OPTST_IMM) \
+    || (   ((_flg) & (OPTST_DISABLED|OPTST_DISABLE_IMM))    \
+        == (OPTST_DISABLED|OPTST_DISABLE_IMM)  ))
+
+/*  B) handling at "regular" time because it was not immediate
+ *
+ *  1.  OPTST_DISABLED is not set:
+ *      IMM           must *NOT* be set
+ *      DISABLE_IMM   don't care
+ *      TWICE         don't care
+ *      DISABLE_TWICE don't care
+ *      0 -and-  0 x x x
+ *
+ *  2.  OPTST_DISABLED is set:
+ *      IMM           don't care
+ *      DISABLE_IMM   don't care
+ *      TWICE         must be set
+ *      DISABLE_TWICE don't care
+ *      1 -and-  x x 1 x
+ */
+#define DO_NORMALLY(_flg) ( \
+       (((_flg) & (OPTST_DISABLED|OPTST_IMM))            == 0)  \
+    || (((_flg) & (OPTST_DISABLED|OPTST_DISABLE_IMM))    ==     \
+                  OPTST_DISABLED)  )
+
+/*  C)  handling at "regular" time because it is to be handled twice.
+ *      The immediate bit was already tested and found to be set:
+ *
+ *  3.  OPTST_DISABLED is not set:
+ *      IMM           is set (but don't care)
+ *      DISABLE_IMM   don't care
+ *      TWICE         must be set
+ *      DISABLE_TWICE don't care
+ *      0 -and-  ? x 1 x
+ *
+ *  4.  OPTST_DISABLED is set:
+ *      IMM           don't care
+ *      DISABLE_IMM   is set (but don't care)
+ *      TWICE         don't care
+ *      DISABLE_TWICE must be set
+ *      1 -and-  x ? x 1
+ */
+#define DO_SECOND_TIME(_flg) ( \
+       (((_flg) & (OPTST_DISABLED|OPTST_TWICE))          ==     \
+                  OPTST_TWICE)                                  \
+    || (((_flg) & (OPTST_DISABLED|OPTST_DISABLE_TWICE))  ==     \
+                  (OPTST_DISABLED|OPTST_DISABLE_TWICE)  ))
+
+/*
+ *  text_mmap structure.  Only active on platforms with mmap(2).
+ */
+#ifdef HAVE_SYS_MMAN_H
+#  include <sys/mman.h>
+#else
+#  ifndef  PROT_READ
+#   define PROT_READ    0x01
+#  endif
+#  ifndef  PROT_WRITE
+#   define PROT_WRITE   0x02
+#  endif
+#  ifndef  MAP_SHARED
+#   define MAP_SHARED   0x01
+#  endif
+#  ifndef  MAP_PRIVATE
+#   define MAP_PRIVATE  0x02
+#  endif
+#endif
+
+#ifndef MAP_FAILED
+#  define  MAP_FAILED   ((void*)-1)
+#endif
+
+#ifndef  _SC_PAGESIZE
+# ifdef  _SC_PAGE_SIZE
+#  define _SC_PAGESIZE _SC_PAGE_SIZE
+# endif
+#endif
+
+/*
+ *  Define and initialize all the user visible strings.
+ *  We do not do translations.  If translations are to be done, then
+ *  the client will provide a callback for that purpose.
+ */
+#undef DO_TRANSLATIONS
+#include "autoopts/usage-txt.h"
+
+/*
+ *  File pointer for usage output
+ */
+extern FILE* option_usage_fp;
+
+extern tOptProc optionPrintVersion, optionPagedUsage, optionLoadOpt;
+
+#define LOCAL static
+#include "proto.h"
+
+#endif /* AUTOGEN_AUTOOPTS_H */
+/*
+ * Local Variables:
+ * mode: C
+ * c-file-style: "stroustrup"
+ * tab-width: 4
+ * indent-tabs-mode: nil
+ * End:
+ * end of autoopts/autoopts.h */
diff --git a/libopts/autoopts/options.h b/libopts/autoopts/options.h
new file mode 100644 (file)
index 0000000..150af3f
--- /dev/null
@@ -0,0 +1,908 @@
+/*   -*- buffer-read-only: t -*- vi: set ro:
+ *  
+ *  DO NOT EDIT THIS FILE   (options.h)
+ *  
+ *  It has been AutoGen-ed  Sunday April  9, 2006 at 11:49:19 AM PDT
+ *  From the definitions    funcs.def
+ *  and the template file   options_h
+ *
+ *  This file defines all the global structures and special values
+ *  used in the automated option processing library.
+ *
+ *  Automated Options copyright 1992-Y Bruce Korb
+ *
+ *  AutoOpts is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public
+ *  License as published by the Free Software Foundation; either
+ *  version 2.1 of the License, or (at your option) any later version.
+ *  
+ *  AutoOpts is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *  
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with AutoOpts.  If not, write to:
+ *     The Free Software Foundation, Inc.,
+ *     51 Franklin Street, Fifth Floor
+ *     Boston, MA  02110-1301, USA.
+ */
+#ifndef AUTOOPTS_OPTIONS_H_GUARD
+#define AUTOOPTS_OPTIONS_H_GUARD
+#include <sys/types.h>
+
+#if defined(HAVE_STDINT_H)
+# include <stdint.h>
+#elif defined(HAVE_INTTYPES_H)
+# include <inttypes.h>
+#endif /* HAVE_STDINT/INTTYPES_H */
+
+#if defined(HAVE_LIMITS_H)
+# include <limits.h>
+#elif defined(HAVE_SYS_LIMITS_H)
+# include <sys/limits.h>
+#endif /* HAVE_LIMITS/SYS_LIMITS_H */
+
+/*
+ *  PUBLIC DEFINES
+ *
+ *  The following defines may be used in applications that need to test the
+ *  state of an option.  To test against these masks and values, a pointer
+ *  to an option descriptor must be obtained.  There are two ways:
+ *
+ *  1. inside an option processing procedure, it is the second argument,
+ *  conventionally "tOptDesc* pOD".
+ *
+ *  2.  Outside of an option procedure (or to reference a different option
+ *  descriptor), use either "&DESC( opt_name )" or "&pfx_DESC( opt_name )".
+ *
+ *  See the relevant generated header file to determine which and what
+ *  values for "opt_name" are available.
+ */
+
+typedef enum {
+    OPARG_TYPE_NONE             = 0,
+    OPARG_TYPE_STRING           = 1,    /* default type/ vanilla string      */
+    OPARG_TYPE_ENUMERATION      = 2,    /* opt arg is an enum (keyword list) */
+    OPARG_TYPE_BOOLEAN          = 3,    /* opt arg is boolean-valued         */
+    OPARG_TYPE_MEMBERSHIP       = 4,    /* opt arg sets set membership bits  */
+    OPARG_TYPE_NUMERIC          = 5,    /* opt arg has numeric value         */
+    OPARG_TYPE_HIERARCHY        = 6     /* option arg is hierarchical value  */
+} teOptArgType;
+
+typedef struct optionValue {
+    teOptArgType        valType;
+    char*               pzName;
+    union {
+        char            strVal[1];      /* OPARG_TYPE_STRING      */
+        int             enumVal;        /* OPARG_TYPE_ENUMERATION */
+        int             boolVal;        /* OPARG_TYPE_BOOLEAN     */
+        long            setVal;         /* OPARG_TYPE_MEMBERSHIP  */
+        long            longVal;        /* OPARG_TYPE_NUMERIC     */
+        void*           nestVal;        /* OPARG_TYPE_HIERARCHY   */
+    } v;
+} tOptionValue;
+
+#define OPTST_SET_ARGTYPE(n) ((n) << 12)
+#define OPTST_GET_ARGTYPE(f) (((f) & OPTST_ARG_TYPE_MASK) >> 12)
+
+/*
+ *  Bits in the fOptState option descriptor field.
+ */
+#define OPTST_INIT           0x0000000  /* Initial compiled value            */
+#define OPTST_SET            0x0000001  /* Set via the "SET_OPT()" macro     */
+#define OPTST_PRESET         0x0000002  /* Set via an RC/INI file            */
+#define OPTST_DEFINED        0x0000004  /* Set via a command line option     */
+
+#define OPTST_SET_MASK       0x0000007  /* mask of flags that show set state */
+
+#define OPTST_EQUIVALENCE    0x0000010  /* selected by equiv'ed option       */
+#define OPTST_DISABLED       0x0000020  /* option is in disabled state       */
+
+#define OPTST_NO_INIT        0x0000100  /* option cannot be preset           */
+#define OPTST_NUMBER_OPT     0x0000200  /* opt value (flag) is any digit     */
+#define OPTST_STACKED        0x0000400  /* opt uses optionStackArg procedure */
+#define OPTST_INITENABLED    0x0000800  /* option defaults to enabled        */
+#define OPTST_ARG_TYPE_MASK  0x000F000  /* bits used to specify opt arg type */
+#define OPTST_ARG_OPTIONAL   0x0010000  /* the option argument not required  */
+#define OPTST_IMM            0x0020000  /* process option on first pass      */
+#define OPTST_DISABLE_IMM    0x0040000  /* process disablement on first pass */
+#define OPTST_OMITTED        0x0080000  /* compiled out of program           */
+#define OPTST_MUST_SET       0x0100000  /* must be set or pre-set            */
+#define OPTST_DOCUMENT       0x0200000  /* opt is for documentation only     */
+#define OPTST_TWICE          0x0400000  /* process option twice - imm + reg  */
+#define OPTST_DISABLE_TWICE  0x0800000  /* process disabled option twice     */
+
+#define OPTST_PERSISTENT     0xFFFFF00  /* mask of flags that do not change  */
+
+#define SELECTED_OPT( pod )  ( (pod)->fOptState & (OPTST_SET | OPTST_DEFINED))
+#define UNUSED_OPT(   pod )  (((pod)->fOptState & OPTST_SET_MASK) == 0)
+#define DISABLED_OPT( pod )  ( (pod)->fOptState & OPTST_DISABLED)
+#define OPTION_STATE( pod )  ((pod)->fOptState)
+
+/*
+ *  PRIVATE INTERFACES
+ *
+ *  The following values are used in the generated code to communicate
+ *  with the option library procedures.  They are not for public use
+ *  and may be subject to change.
+ */
+
+/*
+ *  Define any special processing flags
+ */
+#define OPTPROC_NONE        0x000000
+#define OPTPROC_LONGOPT     0x000001 /* Process long style options      */
+#define OPTPROC_SHORTOPT    0x000002 /* Process short style "flags"     */
+#define OPTPROC_ERRSTOP     0x000004 /* Stop on argument errors         */
+#define OPTPROC_DISABLEDOPT 0x000008 /* Current option is disabled      */
+#define OPTPROC_NO_REQ_OPT  0x000010 /* no options are required         */
+#define OPTPROC_NUM_OPT     0x000020 /* there is a number option        */
+#define OPTPROC_INITDONE    0x000040 /* have initializations been done? */
+#define OPTPROC_NEGATIONS   0x000080 /* any negation options?           */
+#define OPTPROC_ENVIRON     0x000100 /* check environment?              */
+#define OPTPROC_NO_ARGS     0x000200 /* Disallow remaining arguments    */
+#define OPTPROC_ARGS_REQ    0x000400 /* Require arguments after options */
+#define OPTPROC_REORDER     0x000800 /* reorder arguments after options */
+#define OPTPROC_GNUUSAGE    0x001000 /* emit usage in GNU style         */
+#define OPTPROC_TRANSLATE   0x002000 /* Translate strings in tOptions   */
+#define OPTPROC_HAS_IMMED   0x004000 /* program defines immed options   */
+#define OPTPROC_PRESETTING  0x800000 /* opt processing in preset state  */
+
+#define STMTS(s)  do { s; } while (0)
+
+/*
+ *  The following must be #defined instead of typedef-ed
+ *  because "static const" cannot both be applied to a type,
+ *  tho each individually can...so they all are
+ */
+#define tSCC        static const char
+#define tCC         const char
+#define tAoSC       static char
+#define tAoUC       unsigned char
+#define tAoUI       unsigned int
+#define tAoUL       unsigned long
+#define tAoUS       unsigned short
+
+/*
+ *  It is so disgusting that there must be so many ways
+ *  of specifying TRUE and FALSE.
+ */
+typedef enum { AG_FALSE = 0, AG_TRUE } ag_bool;
+
+/*
+ *  Define a structure that describes each option and
+ *  a pointer to the procedure that handles it.
+ *  The argument is the count of this flag previously seen.
+ */
+typedef struct options  tOptions;
+typedef struct optDesc  tOptDesc;
+typedef struct optNames tOptNames;
+
+/*
+ *  The option procedures do the special processing for each
+ *  option flag that needs it.
+ */
+typedef void (tOptProc)( tOptions*  pOpts, tOptDesc* pOptDesc );
+typedef tOptProc*  tpOptProc;
+
+/*
+ *  The usage procedure will never return.  It calls "exit(2)"
+ *  with the "exitCode" argument passed to it.
+ */
+typedef void (tUsageProc)( tOptions* pOpts, int exitCode );
+typedef tUsageProc* tpUsageProc;
+
+/*
+ *  Special definitions.  "NOLIMIT" is the 'max' value to use when
+ *  a flag may appear multiple times without limit.  "NO_EQUIVALENT"
+ *  is an illegal value for 'optIndex' (option description index).
+ */
+#define NOLIMIT          USHRT_MAX
+#define OPTION_LIMIT     SHRT_MAX
+#define NO_EQUIVALENT    (OPTION_LIMIT+1)
+
+/*
+ *  Special values for optValue.  It must not be generatable from the
+ *  computation "optIndex +96".  Since "optIndex" is limited to 100, ...
+ */
+#define NUMBER_OPTION    '#'
+
+typedef struct argList tArgList;
+#define MIN_ARG_ALLOC_CT   6
+#define INCR_ARG_ALLOC_CT  8
+struct argList {
+    int             useCt;
+    int             allocCt;
+    tCC*            apzArgs[ MIN_ARG_ALLOC_CT ];
+};
+
+/*
+ *  Descriptor structure for each option.
+ *  Only the fields marked "PUBLIC" are for public use.
+ */
+struct optDesc {
+    tAoUS           optIndex;         /* PUBLIC */
+    tAoUS           optValue;         /* PUBLIC */
+    tAoUS           optActualIndex;   /* PUBLIC */
+    tAoUS           optActualValue;   /* PUBLIC */
+
+    tAoUS           optEquivIndex;    /* PUBLIC */
+    tAoUS           optMinCt;
+    tAoUS           optMaxCt;
+    tAoUS           optOccCt;         /* PUBLIC */
+
+    tAoUI           fOptState;        /* PUBLIC */
+    tAoUI           reserved;
+    tCC*            pzLastArg;        /* PUBLIC */
+    void*           optCookie;        /* PUBLIC */
+
+    const int *     pOptMust;
+    const int *     pOptCant;
+    tpOptProc       pOptProc;
+    const char*     pzText;
+
+    const char*     pz_NAME;
+    const char*     pz_Name;
+    const char*     pz_DisableName;
+    const char*     pz_DisablePfx;
+};
+
+/*
+ *  Some options need special processing, so we store their
+ *  indexes in a known place:
+ */
+typedef struct optSpecIndex tOptSpecIndex;
+struct optSpecIndex {
+    tAoUS           more_help;
+    tAoUS           save_opts;
+    tAoUS           number_option;
+    tAoUS           default_opt;
+};
+
+#define  OPTIONS_STRUCT_VERSION  110594
+#define  OPTIONS_VERSION_STRING  "27:1:2"
+#define  OPTIONS_MINIMUM_VERSION 102400
+#define  OPTIONS_MIN_VER_STRING  "25:0:0"
+
+/*
+ *  The procedure generated for translating option text
+ */
+typedef void (tOptionXlateProc)(void);
+
+struct options {
+    const int         structVersion;
+    int               origArgCt;
+    char**            origArgVect;
+    unsigned int      fOptSet;
+    unsigned int      curOptIdx;
+    char*             pzCurOpt;
+
+    const char*       pzProgPath;
+    const char*       pzProgName;
+    const char*       pzPROGNAME;
+    const char*       pzRcName;
+    const char*       pzCopyright;
+    const char*       pzCopyNotice;
+    const char*       pzFullVersion;
+    const char**      papzHomeList;
+    const char*       pzUsageTitle;
+    const char*       pzExplain;
+    const char*       pzDetail;
+    tOptDesc*         pOptDesc;
+    const char*       pzBugAddr;
+
+    void*             pExtensions;
+    void*             pSavedState;
+
+    tpUsageProc       pUsageProc;
+    tOptionXlateProc* pTransProc;
+
+    tOptSpecIndex     specOptIdx;
+    const int         optCt;
+    const int         presetOptCt;
+};
+
+/*
+ *  "token list" structure returned by "string_tokenize()"
+ */
+typedef struct {
+    unsigned long   tkn_ct;
+    unsigned char*  tkn_list[1];
+} token_list_t;
+
+/*
+ *  Hide the interface - it pollutes a POSIX claim, but leave it for
+ *  anyone #include-ing this header
+ */
+#define strneqvcmp      option_strneqvcmp
+#define streqvcmp       option_streqvcmp
+#define streqvmap       option_streqvmap
+#define strequate       option_strequate
+#define strtransform    option_strtransform
+
+/*
+ *  This is an output only structure used by text_mmap and text_munmap.
+ *  Clients must not alter the contents and must provide it to both
+ *  the text_mmap and text_munmap procedures.  BE ADVISED: if you are
+ *  mapping the file with PROT_WRITE the NUL byte at the end MIGHT NOT
+ *  BE WRITABLE.  In any event, that byte is not be written back
+ *  to the source file.  ALSO: if "txt_data" is valid and "txt_errno"
+ *  is not zero, then there *may* not be a terminating NUL.
+ */
+typedef struct {
+    void*       txt_data;      /* text file data   */
+    size_t      txt_size;      /* actual file size */
+    size_t      txt_full_size; /* mmaped mem size  */
+    int         txt_fd;        /* file descriptor  */
+    int         txt_zero_fd;   /* fd for /dev/zero */
+    int         txt_errno;     /* warning code     */
+    int         txt_prot;      /* "prot" flags     */
+    int         txt_flags;     /* mapping type     */
+    int         txt_alloc;     /* if we malloced memory */
+} tmap_info_t;
+
+#define TEXT_MMAP_FAILED_ADDR(a)  ((void*)(a) ==  (void*)MAP_FAILED)
+
+/*
+ *  When loading a line (or block) of text as an option, the value can
+ *  be processed in any of several modes:
+ *
+ *  @table @samp
+ *  @item keep
+ *  Every part of the value between the delimiters is saved.
+ *
+ *  @item uncooked
+ *  Even if the value begins with quote characters, do not do quote processing.
+ *
+ *  @item cooked
+ *  If the value looks like a quoted string, then process it.
+ *  Double quoted strings are processed the way strings are in "C" programs,
+ *  except they are treated as regular characters if the following character
+ *  is not a well-established escape sequence.
+ *  Single quoted strings (quoted with apostrophies) are handled the way
+ *  strings are handled in shell scripts, *except* that backslash escapes
+ *  are honored before backslash escapes and apostrophies.
+ *  @end table
+ */
+typedef enum {
+    OPTION_LOAD_COOKED,
+    OPTION_LOAD_UNCOOKED,
+    OPTION_LOAD_KEEP
+} tOptionLoadMode;
+
+#ifdef  __cplusplus
+extern "C" {
+#define CPLUSPLUS_CLOSER }
+#else
+#define CPLUSPLUS_CLOSER
+#endif
+
+/*
+ *  The following routines may be coded into AutoOpts client code:
+ */
+
+/* From: tokenize.c line 115
+ *
+ * ao_string_tokenize - tokenize an input string
+ *
+ * Arguments:
+ *   string       string to be tokenized
+ *
+ * Returns: token_list_t* - pointer to a structure that lists each token
+ *
+ *  This function will convert one input string into a list of strings.
+ *  The list of strings is derived by separating the input based on
+ *  white space separation.  However, if the input contains either single
+ *  or double quote characters, then the text after that character up to
+ *  a matching quote will become the string in the list.
+ *  
+ *  The returned pointer should be deallocated with @code{free(3C)} when
+ *  are done using the data.  The data are placed in a single block of
+ *  allocated memory.  Do not deallocate individual token/strings.
+ *  
+ *  The structure pointed to will contain at least these two fields:
+ *  @table @samp
+ *  @item tkn_ct
+ *  The number of tokens found in the input string.
+ *  @item tok_list
+ *  An array of @code{tkn_ct + 1} pointers to substring tokens, with
+ *  the last pointer set to NULL.
+ *  @end table
+ *  
+ *  There are two types of quoted strings: single quoted (@code{'}) and
+ *  double quoted (@code{"}).  Singly quoted strings are fairly raw in that
+ *  escape characters (@code{\\}) are simply another character, except when
+ *  preceding the following characters:
+ *  @example
+ *  @code{\\}  double backslashes reduce to one
+ *  @code{'}   incorporates the single quote into the string
+ *  @code{\n}  suppresses both the backslash and newline character
+ *  @end example
+ *  
+ *  Double quote strings are formed according to the rules of string
+ *  constants in ANSI-C programs.
+ */
+extern token_list_t* ao_string_tokenize( const char* );
+
+
+/* From: configfile.c line 113
+ *
+ * configFileLoad - parse a configuration file
+ *
+ * Arguments:
+ *   pzFile       the file to load
+ *
+ * Returns: const tOptionValue* - An allocated, compound value structure
+ *
+ *  This routine will load a named configuration file and parse the
+ *  text as a hierarchically valued option.  The option descriptor
+ *  created from an option definition file is not used via this interface.
+ *  The returned value is "named" with the input file name and is of
+ *  type "@code{OPARG_TYPE_HIERARCHY}".  It may be used in calls to
+ *  @code{optionGetValue()}, @code{optionNextValue()} and
+ *  @code{optionUnloadNested()}.
+ */
+extern const tOptionValue* configFileLoad( const char* );
+
+
+/* From: configfile.c line 869
+ *
+ * optionFileLoad - Load the locatable config files, in order
+ *
+ * Arguments:
+ *   pOpts        program options descriptor
+ *   pzProg       program name
+ *
+ * Returns: int - 0 -> SUCCESS, -1 -> FAILURE
+ *
+ *  This function looks in all the specified directories for a configuration
+ *  file ("rc" file or "ini" file) and processes any found twice.  The first
+ *  time through, they are processed in reverse order (last file first).  At
+ *  that time, only "immediate action" configurables are processed.  For
+ *  example, if the last named file specifies not processing any more
+ *  configuration files, then no more configuration files will be processed.
+ *  Such an option in the @strong{first} named directory will have no effect.
+ *  
+ *  Once the immediate action configurables have been handled, then the
+ *  directories are handled in normal, forward order.  In that way, later
+ *  config files can override the settings of earlier config files.
+ *  
+ *  See the AutoOpts documentation for a thorough discussion of the
+ *  config file format.
+ *  
+ *  Configuration files not found or not decipherable are simply ignored.
+ */
+extern int optionFileLoad( tOptions*, const char* );
+
+
+/* From: configfile.c line 241
+ *
+ * optionFindNextValue - find a hierarcicaly valued option instance
+ *
+ * Arguments:
+ *   pOptDesc     an option with a nested arg type
+ *   pPrevVal     the last entry
+ *   name         name of value to find
+ *   value        the matching value
+ *
+ * Returns: const tOptionValue* - a compound value structure
+ *
+ *  This routine will find the next entry in a nested value option or
+ *  configurable.  It will search through the list and return the next entry
+ *  that matches the criteria.
+ */
+extern const tOptionValue* optionFindNextValue( const tOptDesc*, const tOptionValue*, const char*, const char* );
+
+
+/* From: configfile.c line 166
+ *
+ * optionFindValue - find a hierarcicaly valued option instance
+ *
+ * Arguments:
+ *   pOptDesc     an option with a nested arg type
+ *   name         name of value to find
+ *   value        the matching value
+ *
+ * Returns: const tOptionValue* - a compound value structure
+ *
+ *  This routine will find an entry in a nested value option or configurable.
+ *  It will search through the list and return a matching entry.
+ */
+extern const tOptionValue* optionFindValue( const tOptDesc*, const char*, const char* );
+
+
+/* From: restore.c line 157
+ *
+ * optionFree - free allocated option processing memory
+ *
+ * Arguments:
+ *   pOpts        program options descriptor
+ *
+ *  AutoOpts sometimes allocates memory and puts pointers to it in the
+ *  option state structures.  This routine deallocates all such memory.
+ */
+extern void optionFree( tOptions* );
+
+
+/* From: configfile.c line 310
+ *
+ * optionGetValue - get a specific value from a hierarcical list
+ *
+ * Arguments:
+ *   pOptValue    a hierarchcal value
+ *   valueName    name of value to get
+ *
+ * Returns: const tOptionValue* - a compound value structure
+ *
+ *  This routine will find an entry in a nested value option or configurable.
+ *  If "valueName" is NULL, then the first entry is returned.  Otherwise,
+ *  the first entry with a name that exactly matches the argument will be
+ *  returned.
+ */
+extern const tOptionValue* optionGetValue( const tOptionValue*, const char* );
+
+
+/* From: load.c line 477
+ *
+ * optionLoadLine - process a string for an option name and value
+ *
+ * Arguments:
+ *   pOpts        program options descriptor
+ *   pzLine       NUL-terminated text
+ *
+ *  This is a client program callable routine for setting options from, for
+ *  example, the contents of a file that they read in.  Only one option may
+ *  appear in the text.  It will be treated as a normal (non-preset) option.
+ *  
+ *  When passed a pointer to the option struct and a string, it will find
+ *  the option named by the first token on the string and set the option
+ *  argument to the remainder of the string.  The caller must NUL terminate
+ *  the string.  Any embedded new lines will be included in the option
+ *  argument.  If the input looks like one or more quoted strings, then the
+ *  input will be "cooked".  The "cooking" is identical to the string
+ *  formation used in AutoGen definition files (@pxref{basic expression}),
+ *  except that you may not use backquotes.
+ */
+extern void optionLoadLine( tOptions*, const char* );
+
+
+/* From: configfile.c line 369
+ *
+ * optionNextValue - get the next value from a hierarchical list
+ *
+ * Arguments:
+ *   pOptValue    a hierarchcal list value
+ *   pOldValue    a value from this list
+ *
+ * Returns: const tOptionValue* - a compound value structure
+ *
+ *  This routine will return the next entry after the entry passed in.  At the
+ *  end of the list, NULL will be returned.  If the entry is not found on the
+ *  list, NULL will be returned and "@var{errno}" will be set to EINVAL.
+ *  The "@var{pOldValue}" must have been gotten from a prior call to this
+ *  routine or to "@code{opitonGetValue()}".
+ */
+extern const tOptionValue* optionNextValue( const tOptionValue*, const tOptionValue* );
+
+
+/* From: usage.c line 128
+ *
+ * optionOnlyUsage - Print usage text for just the options
+ *
+ * Arguments:
+ *   pOpts        program options descriptor
+ *   ex_code      exit code for calling exit(3)
+ *
+ *  This routine will print only the usage for each option.
+ *  This function may be used when the emitted usage must incorporate
+ *  information not available to AutoOpts.
+ */
+extern void optionOnlyUsage( tOptions*, int );
+
+
+/* From: autoopts.c line 934
+ *
+ * optionProcess - this is the main option processing routine
+ *
+ * Arguments:
+ *   pOpts        program options descriptor
+ *   argc         program arg count
+ *   argv         program arg vector
+ *
+ * Returns: int - the count of the arguments processed
+ *
+ *  This is the main entry point for processing options.  It is intended
+ *  that this procedure be called once at the beginning of the execution of
+ *  a program.  Depending on options selected earlier, it is sometimes
+ *  necessary to stop and restart option processing, or to select completely
+ *  different sets of options.  This can be done easily, but you generally
+ *  do not want to do this.
+ *  
+ *  The number of arguments processed always includes the program name.
+ *  If one of the arguments is "--", then it is counted and the processing
+ *  stops.  If an error was encountered and errors are to be tolerated, then
+ *  the returned value is the index of the argument causing the error.
+ *  A hyphen by itself ("-") will also cause processing to stop and will
+ *  @emph{not} be counted among the processed arguments.  A hyphen by itself
+ *  is treated as an operand.  Encountering an operand stops option
+ *  processing.
+ */
+extern int optionProcess( tOptions*, int, char** );
+
+
+/* From: restore.c line 121
+ *
+ * optionRestore - restore option state from memory copy
+ *
+ * Arguments:
+ *   pOpts        program options descriptor
+ *
+ *  Copy back the option state from saved memory.
+ *  The allocated memory is left intact, so this routine can be
+ *  called repeatedly without having to call optionSaveState again.
+ *  If you are restoring a state that was saved before the first call
+ *  to optionProcess(3AO), then you may change the contents of the
+ *  argc/argv parameters to optionProcess.
+ */
+extern void optionRestore( tOptions* );
+
+
+/* From: save.c line 325
+ *
+ * optionSaveFile - saves the option state to a file
+ *
+ * Arguments:
+ *   pOpts        program options descriptor
+ *
+ *  This routine will save the state of option processing to a file.  The name
+ *  of that file can be specified with the argument to the @code{--save-opts}
+ *  option, or by appending the @code{rcfile} attribute to the last
+ *  @code{homerc} attribute.  If no @code{rcfile} attribute was specified, it
+ *  will default to @code{.@i{programname}rc}.  If you wish to specify another
+ *  file, you should invoke the @code{SET_OPT_SAVE_OPTS( @i{filename} )} macro.
+ */
+extern void optionSaveFile( tOptions* );
+
+
+/* From: restore.c line 54
+ *
+ * optionSaveState - saves the option state to memory
+ *
+ * Arguments:
+ *   pOpts        program options descriptor
+ *
+ *  This routine will allocate enough memory to save the current
+ *  option processing state.  If this routine has been called before,
+ *  that memory will be reused.  You may only save one copy of the
+ *  option state.  This routine may be called before optionProcess(3AO).
+ *  If you do call it before the first call to optionProcess, then
+ *  you may also change the contents of argc/argv after you call
+ *  optionRestore(3AO)
+ */
+extern void optionSaveState( tOptions* );
+
+
+/* From: nested.c line 527
+ *
+ * optionUnloadNested - Deallocate the memory for a nested value
+ *
+ * Arguments:
+ *   pOptVal      the hierarchical value
+ *
+ *  A nested value needs to be deallocated.  The pointer passed in should
+ *  have been gotten from a call to @code{configFileLoad()} (See
+ *  @pxref{libopts-configFileLoad}).
+ */
+extern void optionUnloadNested( const tOptionValue* );
+
+
+/* From: version.c line 58
+ *
+ * optionVersion - return the compiled AutoOpts version number
+ *
+ * Returns: const char* - the version string in constant memory
+ *
+ *  Returns the full version string compiled into the library.
+ *  The returned string cannot be modified.
+ */
+extern const char* optionVersion( void );
+
+
+/* From: ../compat/pathfind.c line 24
+ *
+ * pathfind - fild a file in a list of directories
+ *
+ * Arguments:
+ *   path         colon separated list of search directories
+ *   file         the name of the file to look for
+ *   mode         the mode bits that must be set to match
+ *
+ * Returns: char* - the path to the located file
+ *
+ * the pathfind function is available only if HAVE_PATHFIND is not defined
+ *
+ *  pathfind looks for a a file with name "FILE" and "MODE" access
+ *  along colon delimited "PATH", and returns the full pathname as a
+ *  string, or NULL if not found.  If "FILE" contains a slash, then
+ *  it is treated as a relative or absolute path and "PATH" is ignored.
+ *  
+ *  @strong{NOTE}: this function is compiled into @file{libopts} only if
+ *  it is not natively supplied.
+ *  
+ *  The "MODE" argument is a string of option letters chosen from the
+ *  list below:
+ *  @example
+ *  Letter    Meaning
+ *  r         readable
+ *  w         writable
+ *  x         executable
+ *  f         normal file       (NOT IMPLEMENTED)
+ *  b         block special     (NOT IMPLEMENTED)
+ *  c         character special (NOT IMPLEMENTED)
+ *  d         directory         (NOT IMPLEMENTED)
+ *  p         FIFO (pipe)       (NOT IMPLEMENTED)
+ *  u         set user ID bit   (NOT IMPLEMENTED)
+ *  g         set group ID bit  (NOT IMPLEMENTED)
+ *  k         sticky bit        (NOT IMPLEMENTED)
+ *  s         size nonzero      (NOT IMPLEMENTED)
+ *  @end example
+ */
+#ifndef HAVE_PATHFIND
+extern char* pathfind( const char*, const char*, const char* );
+#endif /* HAVE_PATHFIND */
+
+
+/* From: streqvcmp.c line 233
+ *
+ * strequate - map a list of characters to the same value
+ *
+ * Arguments:
+ *   ch_list      characters to equivalence
+ *
+ *  Each character in the input string get mapped to the first character
+ *  in the string.
+ *  This function name is mapped to option_strequate so as to not conflict
+ *  with the POSIX name space.
+ */
+extern void strequate( const char* );
+
+
+/* From: streqvcmp.c line 143
+ *
+ * streqvcmp - compare two strings with an equivalence mapping
+ *
+ * Arguments:
+ *   str1         first string
+ *   str2         second string
+ *
+ * Returns: int - the difference between two differing characters
+ *
+ *  Using a character mapping, two strings are compared for "equivalence".
+ *  Each input character is mapped to a comparison character and the
+ *  mapped-to characters are compared for the two NUL terminated input strings.
+ *  This function name is mapped to option_streqvcmp so as to not conflict
+ *  with the POSIX name space.
+ */
+extern int streqvcmp( const char*, const char* );
+
+
+/* From: streqvcmp.c line 180
+ *
+ * streqvmap - Set the character mappings for the streqv functions
+ *
+ * Arguments:
+ *   From         Input character
+ *   To           Mapped-to character
+ *   ct           compare length
+ *
+ *  Set the character mapping.  If the count (@code{ct}) is set to zero, then
+ *  the map is cleared by setting all entries in the map to their index
+ *  value.  Otherwise, the "@code{From}" character is mapped to the "@code{To}"
+ *  character.  If @code{ct} is greater than 1, then @code{From} and @code{To}
+ *  are incremented and the process repeated until @code{ct} entries have been
+ *  set. For example,
+ *  @example
+ *  streqvmap( 'a', 'A', 26 );
+ *  @end example
+ *  @noindent
+ *  will alter the mapping so that all English lower case letters
+ *  will map to upper case.
+ *  
+ *  This function name is mapped to option_streqvmap so as to not conflict
+ *  with the POSIX name space.
+ */
+extern void streqvmap( char, char, int );
+
+
+/* From: streqvcmp.c line 102
+ *
+ * strneqvcmp - compare two strings with an equivalence mapping
+ *
+ * Arguments:
+ *   str1         first string
+ *   str2         second string
+ *   ct           compare length
+ *
+ * Returns: int - the difference between two differing characters
+ *
+ *  Using a character mapping, two strings are compared for "equivalence".
+ *  Each input character is mapped to a comparison character and the
+ *  mapped-to characters are compared for the two NUL terminated input strings.
+ *  The comparison is limited to @code{ct} bytes.
+ *  This function name is mapped to option_strneqvcmp so as to not conflict
+ *  with the POSIX name space.
+ */
+extern int strneqvcmp( const char*, const char*, int );
+
+
+/* From: streqvcmp.c line 259
+ *
+ * strtransform - convert a string into its mapped-to value
+ *
+ * Arguments:
+ *   dest         output string
+ *   src          input string
+ *
+ *  Each character in the input string is mapped and the mapped-to
+ *  character is put into the output.
+ *  This function name is mapped to option_strtransform so as to not conflict
+ *  with the POSIX name space.
+ */
+extern void strtransform( char*, const char* );
+
+/*  AutoOpts PRIVATE FUNCTIONS:  */
+tOptProc optionStackArg, optionUnstackArg, optionBooleanVal, optionNumericVal;
+
+extern char* ao_string_cook( char*, int* );
+
+extern unsigned int ao_string_cook_escape_char( const char*, char*, char );
+
+extern void genshelloptUsage( tOptions*, int );
+
+extern void optionBooleanVal( tOptions*, tOptDesc* );
+
+extern char* optionEnumerationVal( tOptions*, tOptDesc*, const char**, unsigned int );
+
+extern const char* optionKeywordName( tOptDesc*, unsigned int );
+
+extern tOptionValue* optionLoadNested( const char*, const char*, size_t, tOptionLoadMode );
+
+extern void optionLoadOpt( tOptions*, tOptDesc* );
+
+extern ag_bool optionMakePath( char*, int, const char*, const char* );
+
+extern void optionNestedVal( tOptions*, tOptDesc* );
+
+extern void optionNumericVal( tOptions*, tOptDesc* );
+
+extern void optionPagedUsage( tOptions*, tOptDesc* );
+
+extern void optionParseShell( tOptions* );
+
+extern void optionPrintVersion( tOptions*, tOptDesc* );
+
+extern void optionPutShell( tOptions* );
+
+extern void optionSetMembers( tOptions*, tOptDesc*, const char**, unsigned int );
+
+extern void optionStackArg( tOptions*, tOptDesc* );
+
+extern void optionUnstackArg( tOptions*, tOptDesc* );
+
+extern void optionUsage( tOptions*, int );
+
+extern void optionVersionStderr( tOptions*, tOptDesc* );
+
+extern void* text_mmap( const char*, int, int, tmap_info_t* );
+
+extern int text_munmap( tmap_info_t* );
+
+CPLUSPLUS_CLOSER
+#endif /* AUTOOPTS_OPTIONS_H_GUARD */
+/*
+ * Local Variables:
+ * c-file-style: "stroustrup"
+ * indent-tabs-mode: nil
+ * End:
+ * options.h ends here */
diff --git a/libopts/autoopts/usage-txt.h b/libopts/autoopts/usage-txt.h
new file mode 100644 (file)
index 0000000..9953efa
--- /dev/null
@@ -0,0 +1,479 @@
+/*   -*- buffer-read-only: t -*- vi: set ro:
+ *  
+ *  DO NOT EDIT THIS FILE   (usage-txt.h)
+ *  
+ *  It has been AutoGen-ed  Sunday April  9, 2006 at 11:49:19 AM PDT
+ *  From the definitions    usage-txt.def
+ *  and the template file   usage-txt.tpl
+ *
+ *  This file handles all the bookkeeping required for tracking all the little
+ *  tiny strings used by the AutoOpts library.  There are 114
+ *  of them.  This is not versioned because it is entirely internal to the
+ *  library and accessed by client code only in a very well-controlled way:
+ *  they may substitute translated strings using a procedure that steps through
+ *  all the string pointers.
+ *
+ *  AutoOpts is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public
+ *  License as published by the Free Software Foundation; either
+ *  version 2.1 of the License, or (at your option) any later version.
+ *  
+ *  AutoOpts is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *  
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with AutoOpts.  If not, write to:
+ *     The Free Software Foundation, Inc.,
+ *     51 Franklin Street, Fifth Floor
+ *     Boston, MA  02110-1301, USA.
+ */
+#ifndef AUTOOPTS_USAGE_TXT_H_GUARD
+#define AUTOOPTS_USAGE_TXT_H_GUARD
+
+#undef  cch_t
+#define cch_t const char
+
+/*
+ *  One structure to hold all the pointers to all the stringlets.
+ */
+typedef struct {
+  int       field_ct;
+  char*     utpz_GnuBoolArg;
+  char*     utpz_GnuKeyArg;
+  char*     utpz_GnuKeyLArg;
+  char*     utpz_GnuNumArg;
+  char*     utpz_GnuStrArg;
+  cch_t*    apz_str[ 109 ];
+} usage_text_t;
+
+/*
+ *  Declare the global structure with all the pointers to translated
+ *  strings.  This is then used by the usage generation procedure.
+ */
+extern usage_text_t option_usage_text;
+
+#if defined(AUTOOPTS_INTERNAL) /* DEFINE ALL THE STRINGS = = = = = */
+/*
+ *  Provide a mapping from a short name to fields in this structure.
+ */
+#define zAO_Bad               (option_usage_text.apz_str[0])
+#define zAO_Big               (option_usage_text.apz_str[1])
+#define zAO_Err               (option_usage_text.apz_str[2])
+#define zAO_Sml               (option_usage_text.apz_str[3])
+#define zAll                  (option_usage_text.apz_str[4])
+#define zAlt                  (option_usage_text.apz_str[5])
+#define zAmbigKey             (option_usage_text.apz_str[6])
+#define zAmbiguous            (option_usage_text.apz_str[7])
+#define zArgsMust             (option_usage_text.apz_str[8])
+#define zAtMost               (option_usage_text.apz_str[9])
+#define zAuto                 (option_usage_text.apz_str[10])
+#define zBadPipe              (option_usage_text.apz_str[11])
+#define zBadVerArg            (option_usage_text.apz_str[12])
+#define zCantFmt              (option_usage_text.apz_str[13])
+#define zCantSave             (option_usage_text.apz_str[14])
+#define zDefaultOpt           (option_usage_text.apz_str[15])
+#define zDis                  (option_usage_text.apz_str[16])
+#define zEnab                 (option_usage_text.apz_str[17])
+#define zEquiv                (option_usage_text.apz_str[18])
+#define zErrOnly              (option_usage_text.apz_str[19])
+#define zExamineFmt           (option_usage_text.apz_str[20])
+#define zFiveSpaces           (option_usage_text.apz_str[21])
+#define zFlagOkay             (option_usage_text.apz_str[22])
+#define zFmtFmt               (option_usage_text.apz_str[23])
+#define zForkFail             (option_usage_text.apz_str[24])
+#define zFSErrOptLoad         (option_usage_text.apz_str[25])
+#define zFSErrReadFile        (option_usage_text.apz_str[26])
+#define zGenshell             (option_usage_text.apz_str[27])
+#define zGnuBoolArg           (option_usage_text.utpz_GnuBoolArg)
+#define zGnuBreak             (option_usage_text.apz_str[28])
+#define zGnuKeyArg            (option_usage_text.utpz_GnuKeyArg)
+#define zGnuKeyLArg           (option_usage_text.utpz_GnuKeyLArg)
+#define zGnuNestArg           (option_usage_text.apz_str[29])
+#define zGnuNumArg            (option_usage_text.utpz_GnuNumArg)
+#define zGnuOptArg            (option_usage_text.apz_str[30])
+#define zGnuOptFmt            (option_usage_text.apz_str[31])
+#define zGnuStrArg            (option_usage_text.utpz_GnuStrArg)
+#define zHomePath             (option_usage_text.apz_str[32])
+#define zIllOptChr            (option_usage_text.apz_str[33])
+#define zIllOptStr            (option_usage_text.apz_str[34])
+#define zIllegal              (option_usage_text.apz_str[35])
+#define zInvalOptDesc         (option_usage_text.apz_str[36])
+#define zKeyWords             (option_usage_text.apz_str[37])
+#define zLoadCooked           (option_usage_text.apz_str[38])
+#define zLoadKeep             (option_usage_text.apz_str[39])
+#define zLoadType             (option_usage_text.apz_str[40])
+#define zLoadUncooked         (option_usage_text.apz_str[41])
+#define zLtypeInteger         (option_usage_text.apz_str[42])
+#define zLtypeNest            (option_usage_text.apz_str[43])
+#define zLtypeString          (option_usage_text.apz_str[44])
+#define zLtypeBool            (option_usage_text.apz_str[45])
+#define zLtypeKeyword         (option_usage_text.apz_str[46])
+#define zLtypeSetMembership   (option_usage_text.apz_str[47])
+#define zMembers              (option_usage_text.apz_str[48])
+#define zMisArg               (option_usage_text.apz_str[49])
+#define zMultiEquiv           (option_usage_text.apz_str[50])
+#define zMust                 (option_usage_text.apz_str[51])
+#define zNeedOne              (option_usage_text.apz_str[52])
+#define zNoArg                (option_usage_text.apz_str[53])
+#define zNoArgs               (option_usage_text.apz_str[54])
+#define zNoCreat              (option_usage_text.apz_str[55])
+#define zNoFlags              (option_usage_text.apz_str[56])
+#define zNoKey                (option_usage_text.apz_str[57])
+#define zNoLim                (option_usage_text.apz_str[58])
+#define zNoPreset             (option_usage_text.apz_str[59])
+#define zNoRq_NoShrtTtl       (option_usage_text.apz_str[60])
+#define zNoRq_ShrtTtl         (option_usage_text.apz_str[61])
+#define zNoStat               (option_usage_text.apz_str[62])
+#define zNoState              (option_usage_text.apz_str[63])
+#define zNone                 (option_usage_text.apz_str[64])
+#define zNotDef               (option_usage_text.apz_str[65])
+#define zNotEnough            (option_usage_text.apz_str[66])
+#define zNotFile              (option_usage_text.apz_str[67])
+#define zNotNumber            (option_usage_text.apz_str[68])
+#define zNrmOptFmt            (option_usage_text.apz_str[69])
+#define zNumberOpt            (option_usage_text.apz_str[70])
+#define zOneSpace             (option_usage_text.apz_str[71])
+#define zOnlyOne              (option_usage_text.apz_str[72])
+#define zOptsOnly             (option_usage_text.apz_str[73])
+#define zPathFmt              (option_usage_text.apz_str[74])
+#define zPlsSendBugs          (option_usage_text.apz_str[75])
+#define zPreset               (option_usage_text.apz_str[76])
+#define zPresetFile           (option_usage_text.apz_str[77])
+#define zPresetIntro          (option_usage_text.apz_str[78])
+#define zProg                 (option_usage_text.apz_str[79])
+#define zProhib               (option_usage_text.apz_str[80])
+#define zReorder              (option_usage_text.apz_str[81])
+#define zReqFmt               (option_usage_text.apz_str[82])
+#define zReqOptFmt            (option_usage_text.apz_str[83])
+#define zReqThese             (option_usage_text.apz_str[84])
+#define zReq_NoShrtTtl        (option_usage_text.apz_str[85])
+#define zReq_ShrtTtl          (option_usage_text.apz_str[86])
+#define zSepChars             (option_usage_text.apz_str[87])
+#define zSetMembers           (option_usage_text.apz_str[88])
+#define zSetMemberSettings    (option_usage_text.apz_str[89])
+#define zShrtGnuOptFmt        (option_usage_text.apz_str[90])
+#define zSixSpaces            (option_usage_text.apz_str[91])
+#define zStdBoolArg           (option_usage_text.apz_str[92])
+#define zStdBreak             (option_usage_text.apz_str[93])
+#define zStdKeyArg            (option_usage_text.apz_str[94])
+#define zStdKeyLArg           (option_usage_text.apz_str[95])
+#define zStdNestArg           (option_usage_text.apz_str[96])
+#define zStdNoArg             (option_usage_text.apz_str[97])
+#define zStdNumArg            (option_usage_text.apz_str[98])
+#define zStdOptArg            (option_usage_text.apz_str[99])
+#define zStdReqArg            (option_usage_text.apz_str[100])
+#define zStdStrArg            (option_usage_text.apz_str[101])
+#define zTabHyp               (option_usage_text.apz_str[102])
+#define zTabHypAnd            (option_usage_text.apz_str[103])
+#define zTabout               (option_usage_text.apz_str[104])
+#define zThreeSpaces          (option_usage_text.apz_str[105])
+#define zTwoSpaces            (option_usage_text.apz_str[106])
+#define zUpTo                 (option_usage_text.apz_str[107])
+#define zValidKeys            (option_usage_text.apz_str[108])
+
+  /*
+   *  First, set up the strings.  Some of these are writable.  These are all in
+   *  English.  This gets compiled into libopts and is distributed here so that
+   *  xgettext (or equivalents) can extract these strings for translation.
+   */
+
+  static cch_t   eng_zAO_Bad[] =
+       "AutoOpts function called without option descriptor\n";
+  static cch_t   eng_zAO_Big[] =
+       "\tThis exceeds the compiled library version:  ";
+  static cch_t   eng_zAO_Err[] =
+       "Automated Options Processing Error!\n\
+\t%s called AutoOpts function with structure version %d:%d:%d.\n";
+  static cch_t   eng_zAO_Sml[] =
+       "\tThis is less than the minimum library version:  ";
+  static cch_t   eng_zAll[] =
+       "all";
+  static cch_t   eng_zAlt[] =
+       "\t\t\t\t- an alternate for %s\n";
+  static cch_t   eng_zAmbigKey[] =
+       "%s error:  the keyword `%s' is ambiguous\n";
+  static cch_t   eng_zAmbiguous[] =
+       "ambiguous";
+  static cch_t   eng_zArgsMust[] =
+       "%s: Command line arguments required\n";
+  static cch_t   eng_zAtMost[] =
+       "%4$d %1$s%s options allowed\n";
+  static cch_t   eng_zAuto[] =
+       "version and help options:";
+  static cch_t   eng_zBadPipe[] =
+       "Error %d (%s) from the pipe(2) syscall\n";
+  static cch_t   eng_zBadVerArg[] =
+       "ERROR: version option argument '%c' invalid.  Use:\n\
+\t'v' - version only\n\
+\t'c' - version and copyright\n\
+\t'n' - version and copyright notice\n";
+  static cch_t   eng_zCantFmt[] =
+       "ERROR:  %s option conflicts with the %s option\n";
+  static cch_t   eng_zCantSave[] =
+       "%s(optionSaveState): error: cannot allocate %d bytes\n";
+  static cch_t   eng_zDefaultOpt[] =
+       "\t\t\t\t- default option for unnamed options\n";
+  static cch_t   eng_zDis[] =
+       "\t\t\t\t- disabled as --%s\n";
+  static cch_t   eng_zEnab[] =
+       "\t\t\t\t- enabled by default\n";
+  static cch_t   eng_zEquiv[] =
+       "-equivalence";
+  static cch_t   eng_zErrOnly[] =
+       "ERROR:  only ";
+  static cch_t   eng_zExamineFmt[] =
+       " - examining environment variables named %s_*\n";
+  static cch_t   eng_zFiveSpaces[] =
+       "     ";
+  static cch_t   eng_zFlagOkay[] =
+       "Options are specified by doubled hyphens and their name\n\
+or by a single hyphen and the flag character.\n";
+  static cch_t   eng_zFmtFmt[] =
+       "%%-%ds %%s\n";
+  static cch_t   eng_zForkFail[] =
+       "fs error %d (%s) on fork - cannot obtain %s usage\n";
+  static cch_t   eng_zFSErrOptLoad[] =
+       "File error %d (%s) opening %s for loading options\n";
+  static cch_t   eng_zFSErrReadFile[] =
+       "fs error %d (%s) reading file %s\n";
+  static cch_t   eng_zGenshell[] =
+       "\n\
+= = = = = = = =\n\n\
+This incarnation of genshell will produce\n\
+a shell script to parse the options for %s:\n\n";
+  static char    eng_zGnuBoolArg[] =
+       "=T/F";
+  static cch_t   eng_zGnuBreak[] =
+       "\n\
+%s\n\n";
+  static char    eng_zGnuKeyArg[] =
+       "=KWd";
+  static char    eng_zGnuKeyLArg[] =
+       "=Mbr";
+  static cch_t   eng_zGnuNestArg[] =
+       "=Cplx";
+  static char    eng_zGnuNumArg[] =
+       "=num";
+  static cch_t   eng_zGnuOptArg[] =
+       "[=arg]";
+  static cch_t   eng_zGnuOptFmt[] =
+       "--%2$s%1$s";
+  static char    eng_zGnuStrArg[] =
+       "=str";
+  static cch_t   eng_zHomePath[] =
+       " - reading file /... %s's exe directory .../%s \n";
+  static cch_t   eng_zIllOptChr[] =
+       "%s: illegal option -- %c\n";
+  static cch_t   eng_zIllOptStr[] =
+       "%s: %s option -- %s\n";
+  static cch_t   eng_zIllegal[] =
+       "illegal";
+  static cch_t   eng_zInvalOptDesc[] =
+       "AutoOpts ERROR:  invalid option descriptor for %s\n";
+  static cch_t   eng_zKeyWords[] =
+       "words=";
+  static cch_t   eng_zLoadCooked[] =
+       "cooked";
+  static cch_t   eng_zLoadKeep[] =
+       "keep";
+  static cch_t   eng_zLoadType[] =
+       "type=";
+  static cch_t   eng_zLoadUncooked[] =
+       "uncooked";
+  static cch_t   eng_zLtypeInteger[] =
+       "integer";
+  static cch_t   eng_zLtypeNest[] =
+       "nested";
+  static cch_t   eng_zLtypeString[] =
+       "string";
+  static cch_t   eng_zLtypeBool[] =
+       "bool";
+  static cch_t   eng_zLtypeKeyword[] =
+       "keyword";
+  static cch_t   eng_zLtypeSetMembership[] =
+       "set";
+  static cch_t   eng_zMembers[] =
+       "\t\t\t\t- is a set membership option\n";
+  static cch_t   eng_zMisArg[] =
+       "%s: option `%s' requires an argument\n";
+  static cch_t   eng_zMultiEquiv[] =
+       "Equivalenced option '%s' was equivalenced to both\n\
+\t'%s' and '%s'";
+  static cch_t   eng_zMust[] =
+       "\t\t\t\t- must appear between %d and %d times\n";
+  static cch_t   eng_zNeedOne[] =
+       "ERROR:  The %s option is required\n";
+  static cch_t   eng_zNoArg[] =
+       "%s: option `%s' cannot have an argument\n";
+  static cch_t   eng_zNoArgs[] =
+       "%s: Command line arguments not allowed\n";
+  static cch_t   eng_zNoCreat[] =
+       "error %d (%s) creating %s\n";
+  static cch_t   eng_zNoFlags[] =
+       "Options are specified by single or double hyphens and their name.\n";
+  static cch_t   eng_zNoKey[] =
+       "%s error:  `%s' does not match any keywords\n";
+  static cch_t   eng_zNoLim[] =
+       "\t\t\t\t- may appear multiple times\n";
+  static cch_t   eng_zNoPreset[] =
+       "\t\t\t\t- may not be preset\n";
+  static cch_t   eng_zNoRq_NoShrtTtl[] =
+       "   Arg Option-Name    Description\n";
+  static cch_t   eng_zNoRq_ShrtTtl[] =
+       "  Flg Arg Option-Name    Description\n";
+  static cch_t   eng_zNoStat[] =
+       "error %d (%s) stat-ing %s\n";
+  static cch_t   eng_zNoState[] =
+       "%s(optionRestore): error: no saved option state\n";
+  static cch_t   eng_zNone[] =
+       "none";
+  static cch_t   eng_zNotDef[] =
+       "'%s' not defined\n";
+  static cch_t   eng_zNotEnough[] =
+       "ERROR:  The %s option must appear %d times\n";
+  static cch_t   eng_zNotFile[] =
+       "error:  cannot load options from non-regular file %s\n";
+  static cch_t   eng_zNotNumber[] =
+       "%s error:  `%s' is not a recognizable number\n";
+  static cch_t   eng_zNrmOptFmt[] =
+       " %3s %s";
+  static cch_t   eng_zNumberOpt[] =
+       "The '-#<number>' option may omit the hash char\n";
+  static cch_t   eng_zOneSpace[] =
+       " ";
+  static cch_t   eng_zOnlyOne[] =
+       "one %s%s option allowed\n";
+  static cch_t   eng_zOptsOnly[] =
+       "All arguments are named options.\n";
+  static cch_t   eng_zPathFmt[] =
+       " - reading file %s";
+  static cch_t   eng_zPlsSendBugs[] =
+       "\n\
+please send bug reports to:  %s\n";
+  static cch_t   eng_zPreset[] =
+       "\t\t\t\t- may NOT appear - preset only\n";
+  static cch_t   eng_zPresetFile[] =
+       "#  preset/initialization file\n\
+#  %s#\n";
+  static cch_t   eng_zPresetIntro[] =
+       "\n\
+The following option preset mechanisms are supported:\n";
+  static cch_t   eng_zProg[] =
+       "program";
+  static cch_t   eng_zProhib[] =
+       "prohibits these options:\n";
+  static cch_t   eng_zReorder[] =
+       "Operands and options may be intermixed.  They will be reordered.\n";
+  static cch_t   eng_zReqFmt[] =
+       "ERROR:  %s option requires the %s option\n";
+  static cch_t   eng_zReqOptFmt[] =
+       " %3s %-14s %s";
+  static cch_t   eng_zReqThese[] =
+       "requires these options:\n";
+  static cch_t   eng_zReq_NoShrtTtl[] =
+       "   Arg Option-Name   Req?  Description\n";
+  static cch_t   eng_zReq_ShrtTtl[] =
+       "  Flg Arg Option-Name   Req?  Description\n";
+  static cch_t   eng_zSepChars[] =
+       "-_^";
+  static cch_t   eng_zSetMembers[] =
+       "members=";
+  static cch_t   eng_zSetMemberSettings[] =
+       "or you may use a numeric representation.  Preceding these with a '!' will\n\
+clear the bits, specifying 'none' will clear all bits, and 'all' will set them\n\
+all.  Multiple entries may be passed as an option argument list.\n";
+  static cch_t   eng_zShrtGnuOptFmt[] =
+       "%s";
+  static cch_t   eng_zSixSpaces[] =
+       "      ";
+  static cch_t   eng_zStdBoolArg[] =
+       "T/F";
+  static cch_t   eng_zStdBreak[] =
+       "\n\
+%s\n\n\
+%s";
+  static cch_t   eng_zStdKeyArg[] =
+       "KWd";
+  static cch_t   eng_zStdKeyLArg[] =
+       "Mbr";
+  static cch_t   eng_zStdNestArg[] =
+       "Cpx";
+  static cch_t   eng_zStdNoArg[] =
+       "no ";
+  static cch_t   eng_zStdNumArg[] =
+       "Num";
+  static cch_t   eng_zStdOptArg[] =
+       "opt";
+  static cch_t   eng_zStdReqArg[] =
+       "YES";
+  static cch_t   eng_zStdStrArg[] =
+       "Str";
+  static cch_t   eng_zTabHyp[] =
+       "\t\t\t\t- ";
+  static cch_t   eng_zTabHypAnd[] =
+       "\t\t\t\t-- and ";
+  static cch_t   eng_zTabout[] =
+       "\t\t\t\t%s\n";
+  static cch_t   eng_zThreeSpaces[] =
+       "   ";
+  static cch_t   eng_zTwoSpaces[] =
+       "  ";
+  static cch_t   eng_zUpTo[] =
+       "\t\t\t\t- may appear up to %d times\n";
+  static cch_t   eng_zValidKeys[] =
+       "The valid \"%s\" option keywords are:\n";
+
+  /*
+   *  Now, define (and initialize) the structure that contains
+   *  the pointers to all these strings.
+   *  Aren't you glad you don't maintain this by hand?
+   */
+  usage_text_t option_usage_text = {
+    114,
+    eng_zGnuBoolArg, eng_zGnuKeyArg,  eng_zGnuKeyLArg, eng_zGnuNumArg,
+    eng_zGnuStrArg,
+    {
+      eng_zAO_Bad,             eng_zAO_Big,             eng_zAO_Err,
+      eng_zAO_Sml,             eng_zAll,                eng_zAlt,
+      eng_zAmbigKey,           eng_zAmbiguous,          eng_zArgsMust,
+      eng_zAtMost,             eng_zAuto,               eng_zBadPipe,
+      eng_zBadVerArg,          eng_zCantFmt,            eng_zCantSave,
+      eng_zDefaultOpt,         eng_zDis,                eng_zEnab,
+      eng_zEquiv,              eng_zErrOnly,            eng_zExamineFmt,
+      eng_zFiveSpaces,         eng_zFlagOkay,           eng_zFmtFmt,
+      eng_zForkFail,           eng_zFSErrOptLoad,       eng_zFSErrReadFile,
+      eng_zGenshell,           eng_zGnuBreak,           eng_zGnuNestArg,
+      eng_zGnuOptArg,          eng_zGnuOptFmt,          eng_zHomePath,
+      eng_zIllOptChr,          eng_zIllOptStr,          eng_zIllegal,
+      eng_zInvalOptDesc,       eng_zKeyWords,           eng_zLoadCooked,
+      eng_zLoadKeep,           eng_zLoadType,           eng_zLoadUncooked,
+      eng_zLtypeInteger,       eng_zLtypeNest,          eng_zLtypeString,
+      eng_zLtypeBool,          eng_zLtypeKeyword,       eng_zLtypeSetMembership,
+      eng_zMembers,            eng_zMisArg,             eng_zMultiEquiv,
+      eng_zMust,               eng_zNeedOne,            eng_zNoArg,
+      eng_zNoArgs,             eng_zNoCreat,            eng_zNoFlags,
+      eng_zNoKey,              eng_zNoLim,              eng_zNoPreset,
+      eng_zNoRq_NoShrtTtl,     eng_zNoRq_ShrtTtl,       eng_zNoStat,
+      eng_zNoState,            eng_zNone,               eng_zNotDef,
+      eng_zNotEnough,          eng_zNotFile,            eng_zNotNumber,
+      eng_zNrmOptFmt,          eng_zNumberOpt,          eng_zOneSpace,
+      eng_zOnlyOne,            eng_zOptsOnly,           eng_zPathFmt,
+      eng_zPlsSendBugs,        eng_zPreset,             eng_zPresetFile,
+      eng_zPresetIntro,        eng_zProg,               eng_zProhib,
+      eng_zReorder,            eng_zReqFmt,             eng_zReqOptFmt,
+      eng_zReqThese,           eng_zReq_NoShrtTtl,      eng_zReq_ShrtTtl,
+      eng_zSepChars,           eng_zSetMembers,         eng_zSetMemberSettings,
+      eng_zShrtGnuOptFmt,      eng_zSixSpaces,          eng_zStdBoolArg,
+      eng_zStdBreak,           eng_zStdKeyArg,          eng_zStdKeyLArg,
+      eng_zStdNestArg,         eng_zStdNoArg,           eng_zStdNumArg,
+      eng_zStdOptArg,          eng_zStdReqArg,          eng_zStdStrArg,
+      eng_zTabHyp,             eng_zTabHypAnd,          eng_zTabout,
+      eng_zThreeSpaces,        eng_zTwoSpaces,          eng_zUpTo,
+      eng_zValidKeys
+    }
+  };
+
+#endif /* DO_TRANSLATIONS */
+#endif /* AUTOOPTS_USAGE_TXT_H_GUARD */
diff --git a/libopts/boolean.c b/libopts/boolean.c
new file mode 100644 (file)
index 0000000..30ccd0d
--- /dev/null
@@ -0,0 +1,102 @@
+
+/*
+ *  $Id: boolean.c,v 4.5 2006/03/25 19:24:56 bkorb Exp $
+ * Time-stamp:      "2005-02-14 08:24:12 bkorb"
+ *
+ *   Automated Options Paged Usage module.
+ *
+ *  This routine will run run-on options through a pager so the
+ *  user may examine, print or edit them at their leisure.
+ */
+
+/*
+ *  Automated Options copyright 1992-2006 Bruce Korb
+ *
+ *  Automated Options is free software.
+ *  You may redistribute it and/or modify it under the terms of the
+ *  GNU General Public License, as published by the Free Software
+ *  Foundation; either version 2, or (at your option) any later version.
+ *
+ *  Automated Options is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with Automated Options.  See the file "COPYING".  If not,
+ *  write to:  The Free Software Foundation, Inc.,
+ *             51 Franklin Street, Fifth Floor,
+ *             Boston, MA  02110-1301, USA.
+ *
+ * As a special exception, Bruce Korb gives permission for additional
+ * uses of the text contained in his release of AutoOpts.
+ *
+ * The exception is that, if you link the AutoOpts library with other
+ * files to produce an executable, this does not by itself cause the
+ * resulting executable to be covered by the GNU General Public License.
+ * Your use of that executable is in no way restricted on account of
+ * linking the AutoOpts library code into it.
+ *
+ * This exception does not however invalidate any other reasons why
+ * the executable file might be covered by the GNU General Public License.
+ *
+ * This exception applies only to the code released by Bruce Korb under
+ * the name AutoOpts.  If you copy code from other sources under the
+ * General Public License into a copy of AutoOpts, as the General Public
+ * License permits, the exception does not apply to the code that you add
+ * in this way.  To avoid misleading anyone as to the status of such
+ * modified files, you must delete this exception notice from them.
+ *
+ * If you write modifications of your own for AutoOpts, it is your choice
+ * whether to permit this exception to apply to your modifications.
+ * If you do not wish that, delete this exception notice.
+ */
+
+/*=export_func  optionBooleanVal
+ * private:
+ *
+ * what:  Decipher a boolean value
+ * arg:   + tOptions* + pOpts    + program options descriptor +
+ * arg:   + tOptDesc* + pOptDesc + the descriptor for this arg +
+ *
+ * doc:
+ *  Decipher a true or false value for a boolean valued option argument.
+ *  The value is true, unless it starts with 'n' or 'f' or "#f" or
+ *  it is an empty string or it is a number that evaluates to zero.
+=*/
+void
+optionBooleanVal( tOptions* pOpts, tOptDesc* pOD )
+{
+    long  val;
+    char* pz;
+    ag_bool  res = AG_TRUE;
+
+    switch (*(pOD->pzLastArg)) {
+    case '0':
+        val = strtol( pOD->pzLastArg, &pz, 0 );
+        if ((val != 0) || (*pz != NUL))
+            break;
+        /* FALLTHROUGH */
+    case 'N':
+    case 'n':
+    case 'F':
+    case 'f':
+    case NUL:
+        res = AG_FALSE;
+        break;
+    case '#':
+        if (pOD->pzLastArg[1] != 'f')
+            break;
+        res = AG_FALSE;
+    }
+
+    pOD->pzLastArg = (char*)res;
+}
+/*
+ * Local Variables:
+ * mode: C
+ * c-file-style: "stroustrup"
+ * tab-width: 4
+ * indent-tabs-mode: nil
+ * End:
+ * end of autoopts/boolean.c */
diff --git a/libopts/compat/compat.h b/libopts/compat/compat.h
new file mode 100644 (file)
index 0000000..5c9e923
--- /dev/null
@@ -0,0 +1,292 @@
+/*  -*- Mode: C -*-  */
+
+/* --- fake the preprocessor into handlng portability */
+/*
+ *  Time-stamp:      "2005-09-21 20:56:13 bkorb"
+ *
+ * Author:           Gary V Vaughan <gvaughan@oranda.demon.co.uk>
+ * Created:          Mon Jun 30 15:54:46 1997
+ *
+ * $Id: compat.h,v 4.6 2005/10/02 16:34:30 bkorb Exp $
+ */
+#ifndef COMPAT_H
+#define COMPAT_H 1
+
+#ifndef HAVE_CONFIG_H
+#  error "compat.h" requires "config.h"
+#endif
+
+#include <config.h>
+
+#ifndef HAVE_STRSIGNAL
+   char * strsignal( int signo );
+#endif
+
+#define  _GNU_SOURCE    1 /* for strsignal in GNU's libc */
+#define  __USE_GNU      1 /* exact same thing as above   */
+#define  __EXTENSIONS__ 1 /* and another way to call for it */
+
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ *
+ *  SYSTEM HEADERS:
+ */
+#include <sys/types.h>
+#include <sys/mman.h>
+#include <sys/param.h>
+#if HAVE_SYS_PROCSET_H
+#  include <sys/procset.h>
+#endif
+#include <sys/stat.h>
+#include <sys/wait.h>
+
+#if defined( HAVE_POSIX_SYSINFO )
+#  include <sys/systeminfo.h>
+#elif defined( HAVE_UNAME_SYSCALL )
+#  include <sys/utsname.h>
+#endif
+
+#ifdef DAEMON_ENABLED
+#  if HAVE_SYS_STROPTS_H
+#  include <sys/stropts.h>
+#  endif
+
+#  if HAVE_SYS_SOCKET_H
+#  include <sys/socket.h>
+#  endif
+
+#  if ! defined(HAVE_SYS_POLL_H) && ! defined(HAVE_SYS_SELECT_H)
+#    error This system cannot support daemon processing
+#  endif
+
+#  if HAVE_SYS_POLL_H
+#  include <sys/poll.h>
+#  endif
+
+#  if HAVE_SYS_SELECT_H
+#  include <sys/select.h>
+#  endif
+
+#  if HAVE_NETINET_IN_H
+#  include <netinet/in.h>
+#  endif
+
+#  if HAVE_SYS_UN_H
+#  include <sys/un.h>
+#  endif
+#endif
+
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ *
+ *  USER HEADERS:
+ */
+#include <stdio.h>
+#include <assert.h>
+#include <ctype.h>
+
+/*
+ *  Directory opening stuff:
+ */
+# if defined (_POSIX_SOURCE)
+/* Posix does not require that the d_ino field be present, and some
+   systems do not provide it. */
+#    define REAL_DIR_ENTRY(dp) 1
+# else /* !_POSIX_SOURCE */
+#    define REAL_DIR_ENTRY(dp) (dp->d_ino != 0)
+# endif /* !_POSIX_SOURCE */
+
+# if defined (HAVE_DIRENT_H)
+#   include <dirent.h>
+#   define D_NAMLEN(dirent) strlen((dirent)->d_name)
+# else /* !HAVE_DIRENT_H */
+#   define dirent direct
+#   define D_NAMLEN(dirent) (dirent)->d_namlen
+#   if defined (HAVE_SYS_NDIR_H)
+#     include <sys/ndir.h>
+#   endif /* HAVE_SYS_NDIR_H */
+#   if defined (HAVE_SYS_DIR_H)
+#     include <sys/dir.h>
+#   endif /* HAVE_SYS_DIR_H */
+#   if defined (HAVE_NDIR_H)
+#     include <ndir.h>
+#   endif /* HAVE_NDIR_H */
+# endif /* !HAVE_DIRENT_H */
+
+#include <errno.h>
+#ifdef HAVE_FCNTL_H
+# include <fcntl.h>
+#endif
+#ifndef O_NONBLOCK
+# define O_NONBLOCK FNDELAY
+#endif
+
+#if defined(HAVE_LIBGEN) && defined(HAVE_LIBGEN_H)
+#  include <libgen.h>
+#endif
+
+#include <limits.h>
+#include <memory.h>
+#include <setjmp.h>
+#include <signal.h>
+
+#if defined( HAVE_STDINT_H )
+#  include <stdint.h>
+#elif defined( HAVE_INTTYPES_H )
+#  include <inttypes.h>
+#endif
+
+#include <stdlib.h>
+#include <string.h>
+
+#include <time.h>
+#include <utime.h>
+
+#ifdef HAVE_UNISTD_H
+#  include <unistd.h>
+#endif
+
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ *
+ *  FIXUPS and CONVIENCE STUFF:
+ */
+#ifdef __cplusplus
+#   define EXTERN extern "C"
+#else
+#   define EXTERN extern
+#endif
+
+/* some systems #def errno! and others do not declare it!! */
+#ifndef errno
+   extern int errno;
+#endif
+
+/* Some machines forget this! */
+
+# ifndef EXIT_FAILURE
+#   define EXIT_SUCCESS 0
+#   define EXIT_FAILURE 1
+# endif
+
+#ifndef NUL
+#  define NUL '\0'
+#endif
+
+#ifndef NULL
+#  define NULL 0
+#endif
+
+#if !defined (MAXPATHLEN) && defined (HAVE_SYS_PARAM_H)
+#  include <sys/param.h>
+#endif /* !MAXPATHLEN && HAVE_SYS_PARAM_H */
+
+#if !defined (MAXPATHLEN) && defined (PATH_MAX)
+#  define MAXPATHLEN PATH_MAX
+#endif /* !MAXPATHLEN && PATH_MAX */
+
+#if !defined (MAXPATHLEN)
+#  define MAXPATHLEN 4096
+#endif /* MAXPATHLEN */
+
+#ifndef LONG_MAX
+#  define LONG_MAX      ~(1L << (8*sizeof(long) -1))
+#  define INT_MAX       ~(1 << (8*sizeof(int) -1))
+#endif
+
+#ifndef ULONG_MAX
+#  define ULONG_MAX     ~(OUL)
+#  define UINT_MAX      ~(OU)
+#endif
+
+#ifndef SHORT_MAX
+#  define SHORT_MAX     ~(1 << (8*sizeof(short) -1))
+#else
+#  define USHORT_MAX    ~(OUS)
+#endif
+
+#ifndef HAVE_INT8_T
+  typedef signed char       int8_t;
+#endif
+#ifndef HAVE_UINT8_T
+  typedef unsigned char     uint8_t;
+#endif
+#ifndef HAVE_INT16_T
+  typedef signed short      int16_t;
+#endif
+#ifndef HAVE_UINT16_T
+  typedef unsigned short    uint16_t;
+#endif
+
+#ifndef HAVE_INT32_T
+# if SIZEOF_INT == 4
+       typedef signed int      int32_t;
+# elif SIZEOF_LONG == 4
+       typedef signed long     int32_t;
+# endif
+#endif
+
+#ifndef HAVE_UINT32_T
+# if SIZEOF_INT == 4
+       typedef unsigned int    uint32_t;
+# elif SIZEOF_LONG == 4
+       typedef unsigned long   uint32_t;
+# else
+#   error Cannot create a uint32_t type.
+# endif
+#endif
+
+#ifndef HAVE_INTPTR_T
+  typedef signed long   intptr_t;
+#endif
+#ifndef HAVE_UINTPTR_T
+  typedef unsigned long uintptr_t;
+#endif
+
+/* redefine these for BSD style string libraries */
+#ifndef HAVE_STRCHR
+#  define strchr        index
+#  define strrchr       rindex
+#endif
+
+#ifdef USE_FOPEN_BINARY
+#  ifndef FOPEN_BINARY_FLAG
+#    define FOPEN_BINARY_FLAG   "b"
+#  endif
+#  ifndef FOPEN_TEXT_FLAG
+#    define FOPEN_TEXT_FLAG     "t"
+#  endif
+#else
+#  ifndef FOPEN_BINARY_FLAG
+#    define FOPEN_BINARY_FLAG
+#  endif
+#  ifndef FOPEN_TEXT_FLAG
+#    define FOPEN_TEXT_FLAG
+#  endif
+#endif
+
+#ifndef STR
+#  define _STR(s) #s
+#  define STR(s)  _STR(s)
+#endif
+
+/* ##### Pointer sized word ##### */
+
+/* FIXME:  the MAX stuff in here is broken! */
+#if SIZEOF_CHARP > SIZEOF_INT
+   typedef long t_word;
+   #define WORD_MAX  LONG_MAX
+   #define WORD_MIN  LONG_MIN
+#else /* SIZEOF_CHARP <= SIZEOF_INT */
+   typedef int t_word;
+   #define WORD_MAX  INT_MAX
+   #define WORD_MIN  INT_MIN
+#endif
+
+#endif /* COMPAT_H */
+
+/*
+ * Local Variables:
+ * mode: C
+ * c-file-style: "stroustrup"
+ * tab-width: 4
+ * indent-tabs-mode: nil
+ * End:
+ * end of compat/compat.h */
diff --git a/libopts/compat/pathfind.c b/libopts/compat/pathfind.c
new file mode 100644 (file)
index 0000000..4da759f
--- /dev/null
@@ -0,0 +1,330 @@
+/*  -*- Mode: C -*-  */
+
+/* pathfind.c --- find a FILE  MODE along PATH */
+
+/*
+ * Author:           Gary V Vaughan <gvaughan@oranda.demon.co.uk>
+ * Created:          Tue Jun 24 15:07:31 1997
+ * Last Modified:    $Date: 2005/07/27 17:26:32 $
+ *            by: bkorb
+ *
+ * $Id: pathfind.c,v 4.4 2005/07/27 17:26:32 bkorb Exp $
+ */
+
+/* Code: */
+
+#include "compat.h"
+#ifndef HAVE_PATHFIND
+
+static char* make_absolute( const char *string, const char *dot_path );
+static char* canonicalize_pathname( char *path );
+static char* extract_colon_unit( char* dir, const char *string, int *p_index );
+
+
+/*=export_func pathfind
+ *
+ * what: fild a file in a list of directories
+ *
+ * ifndef: HAVE_PATHFIND
+ *
+ * arg:  + const char* + path + colon separated list of search directories +
+ * arg:  + const char* + file + the name of the file to look for +
+ * arg:  + const char* + mode + the mode bits that must be set to match +
+ *
+ * ret_type:  char*
+ * ret_desc:  the path to the located file
+ *
+ * doc:
+ *
+ * pathfind looks for a a file with name "FILE" and "MODE" access
+ * along colon delimited "PATH", and returns the full pathname as a
+ * string, or NULL if not found.  If "FILE" contains a slash, then
+ * it is treated as a relative or absolute path and "PATH" is ignored.
+ *
+ * @strong{NOTE}: this function is compiled into @file{libopts} only if
+ * it is not natively supplied.
+ *
+ * The "MODE" argument is a string of option letters chosen from the
+ * list below:
+ * @example
+ *          Letter    Meaning
+ *          r         readable
+ *          w         writable
+ *          x         executable
+ *          f         normal file       (NOT IMPLEMENTED)
+ *          b         block special     (NOT IMPLEMENTED)
+ *          c         character special (NOT IMPLEMENTED)
+ *          d         directory         (NOT IMPLEMENTED)
+ *          p         FIFO (pipe)       (NOT IMPLEMENTED)
+ *          u         set user ID bit   (NOT IMPLEMENTED)
+ *          g         set group ID bit  (NOT IMPLEMENTED)
+ *          k         sticky bit        (NOT IMPLEMENTED)
+ *          s         size nonzero      (NOT IMPLEMENTED)
+ * @end example
+ *
+ * example:
+ * To find the "ls" command using the "PATH" environment variable:
+ * @example
+ *    #include <stdlib.h>
+ *    char* pz_ls = pathfind( getenv("PATH"), "ls", "rx" );
+ *    <<do whatever with pz_ls>>
+ *    free( pz_ls );
+ * @end example
+ * The path is allocated with @code{malloc(3C)}, so you must @code{free(3C)}
+ * the result.  Also, do not use unimplemented file modes.  :-)
+ *
+ * err:  returns NULL if the file is not found.
+=*/
+char*
+pathfind( const char*  path,
+          const char*  fileName,
+          const char*  mode )
+{
+    int   p_index   = 0;
+    int   mode_bits = 0;
+    char* pathName  = NULL;
+    char  zPath[ MAXPATHLEN + 1 ];
+
+    if (strchr( mode, 'r' )) mode_bits |= R_OK;
+    if (strchr( mode, 'w' )) mode_bits |= W_OK;
+    if (strchr( mode, 'x' )) mode_bits |= X_OK;
+
+    /*
+     *  FOR each non-null entry in the colon-separated path, DO ...
+     */
+    for (;;) {
+        DIR*  dirP;
+        char* colon_unit = extract_colon_unit( zPath, path, &p_index );
+
+        /*
+         *  IF no more entries, THEN quit
+         */
+        if (colon_unit == NULL)
+            break;
+
+        dirP = opendir( colon_unit );
+
+        /*
+         *  IF the directory is inaccessable, THEN next directory
+         */
+        if (dirP == NULL)
+            continue;
+
+        /*
+         *  FOR every entry in the given directory, ...
+         */
+        for (;;) {
+            struct dirent *entP = readdir( dirP );
+
+            if (entP == (struct dirent*)NULL)
+                break;
+
+            /*
+             *  IF the file name matches the one we are looking for, ...
+             */
+            if (strcmp( entP->d_name, fileName ) == 0) {
+                char* pzFullName = make_absolute( fileName, colon_unit);
+
+                /*
+                 *  Make sure we can access it in the way we want
+                 */
+                if (access( pzFullName, mode_bits ) >= 0) {
+                    /*
+                     *  We can, so normalize the name and return it below
+                     */
+                    pathName = canonicalize_pathname( pzFullName );
+                }
+
+                free( (void*)pzFullName );
+                break;
+            }
+        }
+        
+        closedir( dirP );
+
+        if (pathName != NULL)
+            break;
+    }
+
+    return pathName;
+}
+
+/*
+ * Turn STRING  (a pathname) into an  absolute  pathname, assuming  that
+ * DOT_PATH contains the symbolic location of  `.'.  This always returns
+ * a new string, even if STRING was an absolute pathname to begin with.
+ */
+static char*
+make_absolute( const char *string, const char *dot_path )
+{
+    char *result;
+    int result_len;
+  
+    if (!dot_path || *string == '/') {
+        result = strdup( string );
+    } else {
+        if (dot_path && dot_path[0]) {
+            result = malloc( 2 + strlen( dot_path ) + strlen( string ) );
+            strcpy( result, dot_path );
+            result_len = strlen( result );
+            if (result[result_len - 1] != '/') {
+                result[result_len++] = '/';
+                result[result_len] = '\0';
+            }    
+        } else {
+            result = malloc( 3 + strlen( string ) );
+            result[0] = '.'; result[1] = '/'; result[2] = '\0';
+            result_len = 2;
+        }
+
+        strcpy( result + result_len, string );
+    }
+
+    return result;
+}
+
+/*
+ * Canonicalize PATH, and return a  new path.  The new path differs from
+ * PATH in that:
+ *
+ *    Multiple `/'s     are collapsed to a single `/'.
+ *    Leading `./'s     are removed.
+ *    Trailing `/.'s    are removed.
+ *    Trailing `/'s     are removed.
+ *    Non-leading `../'s and trailing `..'s are handled by removing
+ *                    portions of the path.
+ */
+static char*
+canonicalize_pathname( char *path )
+{
+    int i, start;
+    char stub_char, *result;
+
+    /* The result cannot be larger than the input PATH. */
+    result = strdup( path );
+
+    stub_char = (*path == '/') ? '/' : '.';
+
+    /* Walk along RESULT looking for things to compact. */
+    i = 0;
+    while (result[i]) {
+        while (result[i] != '\0' && result[i] != '/')
+            i++;
+
+        start = i++;
+
+        /* If we didn't find any  slashes, then there is nothing left to
+         * do.
+         */
+        if (!result[start])
+            break;
+
+        /* Handle multiple `/'s in a row. */
+        while (result[i] == '/')
+            i++;
+
+#if !defined (apollo)
+        if ((start + 1) != i)
+#else
+        if ((start + 1) != i && (start != 0 || i != 2))
+#endif /* apollo */
+        {
+            strcpy( result + start + 1, result + i );
+            i = start + 1;
+        }
+
+        /* Handle backquoted `/'. */
+        if (start > 0 && result[start - 1] == '\\')
+            continue;
+
+        /* Check for trailing `/', and `.' by itself. */
+        if ((start && !result[i])
+            || (result[i] == '.' && !result[i+1])) {
+            result[--i] = '\0';
+            break;
+        }
+
+        /* Check for `../', `./' or trailing `.' by itself. */
+        if (result[i] == '.') {
+            /* Handle `./'. */
+            if (result[i + 1] == '/') {
+                strcpy( result + i, result + i + 1 );
+                i = (start < 0) ? 0 : start;
+                continue;
+            }
+
+            /* Handle `../' or trailing `..' by itself. */
+            if (result[i + 1] == '.' &&
+                (result[i + 2] == '/' || !result[i + 2])) {
+                while (--start > -1 && result[start] != '/')
+                    ;
+                strcpy( result + start + 1, result + i + 2 );
+                i = (start < 0) ? 0 : start;
+                continue;
+            }
+        }
+    }
+
+    if (!*result) {
+        *result = stub_char;
+        result[1] = '\0';
+    }
+
+    return result;
+}
+
+/*
+ * Given a  string containing units of information separated  by colons,
+ * return the next one  pointed to by (P_INDEX), or NULL if there are no
+ * more.  Advance (P_INDEX) to the character after the colon.
+ */
+static char*
+extract_colon_unit( char* pzDir, const char *string, int *p_index )
+{
+    char*  pzDest = pzDir;
+    int    ix     = *p_index;
+
+    if (string == NULL)
+        return NULL;
+
+    if ((unsigned)ix >= strlen( string ))
+        return NULL;
+
+    {
+        const char* pzSrc = string + ix;
+
+        while (*pzSrc == ':')  pzSrc++;
+
+        for (;;) {
+            char ch = (*(pzDest++) = *(pzSrc++));
+            switch (ch) {
+            case ':':
+                pzDest[-1] = NUL;
+            case NUL:
+                goto copy_done;
+            }
+
+            if ((pzDest - pzDir) >= MAXPATHLEN)
+                break;
+        } copy_done:;
+
+        ix = pzSrc - string;
+    }
+
+    if (*pzDir == NUL)
+        return NULL;
+
+    *p_index = ix;
+    return pzDir;
+}
+
+#endif /* HAVE_PATHFIND */
+
+/*
+ * Local Variables:
+ * mode: C
+ * c-file-style: "stroustrup"
+ * tab-width: 4
+ * indent-tabs-mode: nil
+ * End:
+ * end of compat/pathfind.c */
diff --git a/libopts/compat/snprintf.c b/libopts/compat/snprintf.c
new file mode 100644 (file)
index 0000000..0215578
--- /dev/null
@@ -0,0 +1,36 @@
+
+#ifndef HAVE_VPRINTF
+#include "choke-me: no vprintf and no snprintf"
+#endif
+
+static int
+snprintf(char *str, size_t n, const char *fmt, ...)
+{
+    va_list ap;
+    int rval;
+
+#ifdef VSPRINTF_CHARSTAR
+    char *rp;
+    va_start(ap, fmt);
+    rp = vsprintf(str, fmt, ap);
+    va_end(ap);
+    rval = strlen(rp);
+
+#else
+    va_start(ap, fmt);
+    rval = vsprintf(str, fmt, ap);
+    va_end(ap);
+#endif
+
+    return rval;
+}
+
+static int
+vsnprintf( char *str, size_t n, const char *fmt, va_list ap )
+{
+#ifdef VSPRINTF_CHARSTAR
+    return (strlen(vsprintf(str, fmt, ap)));
+#else
+    return (vsprintf(str, fmt, ap));
+#endif
+}
diff --git a/libopts/compat/strdup.c b/libopts/compat/strdup.c
new file mode 100644 (file)
index 0000000..34dbcc5
--- /dev/null
@@ -0,0 +1,19 @@
+/*
+ * Platforms without strdup ?!?!?!
+ */
+
+static char *
+strdup( const char *s )
+{
+    char *cp;
+
+    if (s == NULL)
+       return NULL;
+
+    cp = (char *) AGALOC((unsigned) (strlen(s)+1), "strdup");
+
+    if (cp != NULL)
+       (void) strcpy(cp, s);
+
+    return cp;
+}
diff --git a/libopts/configfile.c b/libopts/configfile.c
new file mode 100644 (file)
index 0000000..4a2155a
--- /dev/null
@@ -0,0 +1,1277 @@
+/*
+ *  $Id: configfile.c,v 4.12 2006/03/25 19:24:56 bkorb Exp $
+ *  Time-stamp:      "2005-10-16 15:16:32 bkorb"
+ *
+ *  configuration/rc/ini file handling.
+ */
+
+/*
+ *  Automated Options copyright 1992-2006 Bruce Korb
+ *
+ *  Automated Options is free software.
+ *  You may redistribute it and/or modify it under the terms of the
+ *  GNU General Public License, as published by the Free Software
+ *  Foundation; either version 2, or (at your option) any later version.
+ *
+ *  Automated Options is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with Automated Options.  See the file "COPYING".  If not,
+ *  write to:  The Free Software Foundation, Inc.,
+ *             51 Franklin Street, Fifth Floor,
+ *             Boston, MA  02110-1301, USA.
+ *
+ * As a special exception, Bruce Korb gives permission for additional
+ * uses of the text contained in his release of AutoOpts.
+ *
+ * The exception is that, if you link the AutoOpts library with other
+ * files to produce an executable, this does not by itself cause the
+ * resulting executable to be covered by the GNU General Public License.
+ * Your use of that executable is in no way restricted on account of
+ * linking the AutoOpts library code into it.
+ *
+ * This exception does not however invalidate any other reasons why
+ * the executable file might be covered by the GNU General Public License.
+ *
+ * This exception applies only to the code released by Bruce Korb under
+ * the name AutoOpts.  If you copy code from other sources under the
+ * General Public License into a copy of AutoOpts, as the General Public
+ * License permits, the exception does not apply to the code that you add
+ * in this way.  To avoid misleading anyone as to the status of such
+ * modified files, you must delete this exception notice from them.
+ *
+ * If you write modifications of your own for AutoOpts, it is your choice
+ * whether to permit this exception to apply to your modifications.
+ * If you do not wish that, delete this exception notice.
+ */
+
+/* = = = START-STATIC-FORWARD = = = */
+/* static forward declarations maintained by :mkfwd */
+static void
+filePreset(
+    tOptions*     pOpts,
+    const char*   pzFileName,
+    int           direction );
+
+static char*
+handleComment( char* pzText );
+
+static char*
+handleConfig(
+    tOptions*     pOpts,
+    tOptState*    pOS,
+    char*         pzText,
+    int           direction );
+
+static char*
+handleDirective(
+    tOptions*     pOpts,
+    char*         pzText );
+
+static char*
+handleProgramSection(
+    tOptions*     pOpts,
+    char*         pzText );
+
+static char*
+handleStructure(
+    tOptions*     pOpts,
+    tOptState*    pOS,
+    char*         pzText,
+    int           direction );
+
+static char*
+parseKeyWordType(
+    tOptions*     pOpts,
+    char*         pzText,
+    tOptionValue* pType );
+
+static char*
+parseLoadMode(
+    char*               pzText,
+    tOptionLoadMode*    pMode );
+
+static char*
+parseSetMemType(
+    tOptions*     pOpts,
+    char*         pzText,
+    tOptionValue* pType );
+
+static char*
+parseValueType(
+    char*         pzText,
+    tOptionValue* pType );
+
+static char*
+skipUnknown( char* pzText );
+/* = = = END-STATIC-FORWARD = = = */
+
+
+/*=export_func  configFileLoad
+ *
+ * what:  parse a configuration file
+ * arg:   + const char*     + pzFile + the file to load +
+ *
+ * ret_type:  const tOptionValue*
+ * ret_desc:  An allocated, compound value structure
+ *
+ * doc:
+ *  This routine will load a named configuration file and parse the
+ *  text as a hierarchically valued option.  The option descriptor
+ *  created from an option definition file is not used via this interface.
+ *  The returned value is "named" with the input file name and is of
+ *  type "@code{OPARG_TYPE_HIERARCHY}".  It may be used in calls to
+ *  @code{optionGetValue()}, @code{optionNextValue()} and
+ *  @code{optionUnloadNested()}.
+ *
+ * err:
+ *  If the file cannot be loaded or processed, @code{NULL} is returned and
+ *  @var{errno} is set.  It may be set by a call to either @code{open(2)}
+ *  @code{mmap(2)} or other file system calls, or it may be:
+ *  @itemize @bullet
+ *  @item
+ *  @code{ENOENT} - the file was empty.
+ *  @item
+ *  @code{EINVAL} - the file contents are invalid -- not properly formed.
+ *  @item
+ *  @code{ENOMEM} - not enough memory to allocate the needed structures.
+ *  @end itemize
+=*/
+const tOptionValue*
+configFileLoad( const char* pzFile )
+{
+    tmap_info_t   cfgfile;
+    tOptionValue* pRes = NULL;
+    char* pzText =
+        text_mmap( pzFile, PROT_READ, MAP_PRIVATE, &cfgfile );
+
+    if (TEXT_MMAP_FAILED_ADDR(pzText))
+        return NULL; /* errno is set */
+
+    pRes = optionLoadNested(pzText, pzFile, strlen(pzFile), OPTION_LOAD_COOKED);
+
+    if (pRes == NULL) {
+        int err = errno;
+        text_munmap( &cfgfile );
+        errno = err;
+    } else
+        text_munmap( &cfgfile );
+    return pRes;
+}
+
+
+/*=export_func  optionFindValue
+ *
+ * what:  find a hierarcicaly valued option instance
+ * arg:   + const tOptDesc* + pOptDesc + an option with a nested arg type +
+ * arg:   + const char*     + name     + name of value to find +
+ * arg:   + const char*     + value    + the matching value    +
+ *
+ * ret_type:  const tOptionValue*
+ * ret_desc:  a compound value structure
+ *
+ * doc:
+ *  This routine will find an entry in a nested value option or configurable.
+ *  It will search through the list and return a matching entry.
+ *
+ * err:
+ *  The returned result is NULL and errno is set:
+ *  @itemize @bullet
+ *  @item
+ *  @code{EINVAL} - the @code{pOptValue} does not point to a valid
+ *  hierarchical option value.
+ *  @item
+ *  @code{ENOENT} - no entry matched the given name.
+ *  @end itemize
+=*/
+const tOptionValue*
+optionFindValue( const tOptDesc* pOptDesc,
+                 const char* pzName, const char* pzVal )
+{
+    const tOptionValue* pRes = NULL;
+
+    if (  (pOptDesc == NULL)
+       || (OPTST_GET_ARGTYPE(pOptDesc->fOptState) != OPARG_TYPE_HIERARCHY))  {
+        errno = EINVAL;
+    }
+
+    else if (pOptDesc->optCookie == NULL) {
+        errno = ENOENT;
+    }
+
+    else do {
+        tArgList* pAL = pOptDesc->optCookie;
+        int ct = pAL->useCt;
+        const tOptionValue** ppOV =
+            (const tOptionValue**)(void*)&(pAL->apzArgs);
+
+        if (ct == 0) {
+            errno = ENOENT;
+            break;
+        }
+
+        if (pzName == NULL) {
+            pRes = *ppOV;
+            break;
+        }
+
+        while (--ct >= 0) {
+            const tOptionValue* pOV = *(ppOV++);
+            const tOptionValue* pRV = optionGetValue( pOV, pzName );
+
+            if (pRV == NULL)
+                continue;
+
+            if (pzVal == NULL) {
+                pRes = pOV;
+                break;
+            }
+        }
+        if (pRes == NULL)
+            errno = ENOENT;
+    } while (0);
+
+    return pRes;
+}
+
+
+/*=export_func  optionFindNextValue
+ *
+ * what:  find a hierarcicaly valued option instance
+ * arg:   + const tOptDesc* + pOptDesc + an option with a nested arg type +
+ * arg:   + const tOptionValue* + pPrevVal + the last entry +
+ * arg:   + const char*     + name     + name of value to find +
+ * arg:   + const char*     + value    + the matching value    +
+ *
+ * ret_type:  const tOptionValue*
+ * ret_desc:  a compound value structure
+ *
+ * doc:
+ *  This routine will find the next entry in a nested value option or
+ *  configurable.  It will search through the list and return the next entry
+ *  that matches the criteria.
+ *
+ * err:
+ *  The returned result is NULL and errno is set:
+ *  @itemize @bullet
+ *  @item
+ *  @code{EINVAL} - the @code{pOptValue} does not point to a valid
+ *  hierarchical option value.
+ *  @item
+ *  @code{ENOENT} - no entry matched the given name.
+ *  @end itemize
+=*/
+const tOptionValue*
+optionFindNextValue( const tOptDesc* pOptDesc, const tOptionValue* pPrevVal,
+                 const char* pzName, const char* pzVal )
+{
+    int foundOldVal = 0;
+    tOptionValue* pRes = NULL;
+
+    if (  (pOptDesc == NULL)
+       || (OPTST_GET_ARGTYPE(pOptDesc->fOptState) != OPARG_TYPE_HIERARCHY))  {
+        errno = EINVAL;
+    }
+
+    else if (pOptDesc->optCookie == NULL) {
+        errno = ENOENT;
+    }
+
+    else do {
+        tArgList* pAL = pOptDesc->optCookie;
+        int ct = pAL->useCt;
+        tOptionValue** ppOV = (tOptionValue**)(void*)&(pAL->apzArgs);
+
+        if (ct == 0) {
+            errno = ENOENT;
+            break;
+        }
+
+        while (--ct >= 0) {
+            tOptionValue* pOV = *(ppOV++);
+            if (foundOldVal) {
+                pRes = pOV;
+                break;
+            }
+            if (pOV == pPrevVal)
+                foundOldVal = 1;
+        }
+        if (pRes == NULL)
+            errno = ENOENT;
+    } while (0);
+
+    return pRes;
+}
+
+
+/*=export_func  optionGetValue
+ *
+ * what:  get a specific value from a hierarcical list
+ * arg:   + const tOptionValue* + pOptValue + a hierarchcal value +
+ * arg:   + const char*   + valueName + name of value to get +
+ *
+ * ret_type:  const tOptionValue*
+ * ret_desc:  a compound value structure
+ *
+ * doc:
+ *  This routine will find an entry in a nested value option or configurable.
+ *  If "valueName" is NULL, then the first entry is returned.  Otherwise,
+ *  the first entry with a name that exactly matches the argument will be
+ *  returned.
+ *
+ * err:
+ *  The returned result is NULL and errno is set:
+ *  @itemize @bullet
+ *  @item
+ *  @code{EINVAL} - the @code{pOptValue} does not point to a valid
+ *  hierarchical option value.
+ *  @item
+ *  @code{ENOENT} - no entry matched the given name.
+ *  @end itemize
+=*/
+const tOptionValue*
+optionGetValue( const tOptionValue* pOld, const char* pzValName )
+{
+    tArgList*     pAL;
+    tOptionValue* pRes = NULL;
+
+    if ((pOld == NULL) || (pOld->valType != OPARG_TYPE_HIERARCHY)) {
+        errno = EINVAL;
+        return NULL;
+    }
+    pAL = pOld->v.nestVal;
+
+    if (pAL->useCt > 0) {
+        int ct = pAL->useCt;
+        tOptionValue** papOV = (tOptionValue**)(pAL->apzArgs);
+
+        if (pzValName == NULL) {
+            pRes = *papOV;
+        }
+
+        else do {
+            tOptionValue* pOV = *(papOV++);
+            if (strcmp( pOV->pzName, pzValName ) == 0) {
+                pRes = pOV;
+                break;
+            }
+        } while (--ct > 0);
+    }
+    if (pRes == NULL)
+        errno = ENOENT;
+    return pRes;
+}
+
+
+/*=export_func  optionNextValue
+ *
+ * what:  get the next value from a hierarchical list
+ * arg:   + const tOptionValue* + pOptValue + a hierarchcal list value +
+ * arg:   + const tOptionValue* + pOldValue + a value from this list   +
+ *
+ * ret_type:  const tOptionValue*
+ * ret_desc:  a compound value structure
+ *
+ * doc:
+ *  This routine will return the next entry after the entry passed in.  At the
+ *  end of the list, NULL will be returned.  If the entry is not found on the
+ *  list, NULL will be returned and "@var{errno}" will be set to EINVAL.
+ *  The "@var{pOldValue}" must have been gotten from a prior call to this
+ *  routine or to "@code{opitonGetValue()}".
+ *
+ * err:
+ *  The returned result is NULL and errno is set:
+ *  @itemize @bullet
+ *  @item
+ *  @code{EINVAL} - the @code{pOptValue} does not point to a valid
+ *  hierarchical option value or @code{pOldValue} does not point to a
+ *  member of that option value.
+ *  @item
+ *  @code{ENOENT} - the supplied @code{pOldValue} pointed to the last entry.
+ *  @end itemize
+=*/
+const tOptionValue*
+optionNextValue( const tOptionValue* pOVList, const tOptionValue* pOldOV )
+{
+    tArgList*     pAL;
+    tOptionValue* pRes = NULL;
+    int           err  = EINVAL;
+
+    if ((pOVList == NULL) || (pOVList->valType != OPARG_TYPE_HIERARCHY)) {
+        errno = EINVAL;
+        return NULL;
+    }
+    pAL = pOVList->v.nestVal;
+    {
+        int   ct   = pAL->useCt;
+        tOptionValue** papNV = (tOptionValue**)(pAL->apzArgs);
+
+        while (ct-- > 0) {
+            tOptionValue* pNV = *(papNV++);
+            if (pNV == pOldOV) {
+                if (ct == 0) {
+                    err = ENOENT;
+
+                } else {
+                    err  = 0;
+                    pRes = *papNV;
+                }
+                break;
+            }
+        }
+    }
+    if (err != 0)
+        errno = err;
+    return pRes;
+}
+
+
+/*  filePreset
+ *
+ *  Load a file containing presetting information (a configuration file).
+ */
+static void
+filePreset(
+    tOptions*     pOpts,
+    const char*   pzFileName,
+    int           direction )
+{
+    tmap_info_t   cfgfile;
+    char*         pzFileText =
+        text_mmap( pzFileName, PROT_READ|PROT_WRITE, MAP_PRIVATE, &cfgfile );
+    tOptState     st = OPTSTATE_INITIALIZER(PRESET);
+
+    if (TEXT_MMAP_FAILED_ADDR(pzFileText))
+        return;
+
+    if (direction == DIRECTION_CALLED) {
+        st.flags  = OPTST_DEFINED;
+        direction = DIRECTION_PROCESS;
+    }
+
+    /*
+     *  IF this is called via "optionProcess", then we are presetting.
+     *  This is the default and the PRESETTING bit will be set.
+     *  If this is called via "optionFileLoad", then the bit is not set
+     *  and we consider stuff set herein to be "set" by the client program.
+     */
+    if ((pOpts->fOptSet & OPTPROC_PRESETTING) == 0)
+        st.flags = OPTST_SET;
+
+    do  {
+        while (isspace( *pzFileText ))  pzFileText++;
+
+        if (isalpha( *pzFileText )) {
+            pzFileText = handleConfig( pOpts, &st, pzFileText, direction );
+
+        } else switch (*pzFileText) {
+        case '<':
+            if (isalpha( pzFileText[1] ))
+                pzFileText = handleStructure(pOpts, &st, pzFileText, direction);
+
+            else switch (pzFileText[1]) {
+            case '?':
+                pzFileText = handleDirective( pOpts, pzFileText );
+                break;
+
+            case '!':
+                pzFileText = handleComment( pzFileText );
+                break;
+
+            case '/':
+                pzFileText = strchr( pzFileText+2, '>' );
+                if (pzFileText++ != NULL)
+                    break;
+
+            default:
+                goto all_done;
+            }
+            break;
+
+        case '[':
+            pzFileText = handleProgramSection( pOpts, pzFileText );
+            break;
+
+        case '#':
+            pzFileText = strchr( pzFileText+1, '\n' );
+            break;
+
+        default:
+            goto all_done; /* invalid format */
+        }
+    } while (pzFileText != NULL);
+
+ all_done:
+    text_munmap( &cfgfile );
+}
+
+
+/*  handleComment
+ *
+ *  "pzText" points to a "<!" sequence.
+ *  Theoretically, we should ensure that it begins with "<!--",
+ *  but actually I don't care that much.  It ends with "-->".
+ */
+static char*
+handleComment( char* pzText )
+{
+    char* pz = strstr( pzText, "-->" );
+    if (pz != NULL)
+        pz += 3;
+    return pz;
+}
+
+
+/*  handleConfig
+ *
+ *  "pzText" points to the start of some value name.
+ *  The end of the entry is the end of the line that is not preceded by
+ *  a backslash escape character.  The string value is always processed
+ *  in "cooked" mode.
+ */
+static char*
+handleConfig(
+    tOptions*     pOpts,
+    tOptState*    pOS,
+    char*         pzText,
+    int           direction )
+{
+    char* pzName = pzText++;
+    char* pzEnd  = strchr( pzText, '\n' );
+
+    while (ISNAMECHAR( *pzText ))  pzText++;
+    while (isspace( *pzText )) pzText++;
+    if (pzText > pzEnd) {
+    name_only:
+        *pzEnd++ = NUL;
+        loadOptionLine( pOpts, pOS, pzName, direction, OPTION_LOAD_UNCOOKED );
+        return pzEnd;
+    }
+
+    /*
+     *  Either the first character after the name is a ':' or '=',
+     *  or else we must have skipped over white space.  Anything else
+     *  is an invalid format and we give up parsing the text.
+     */
+    if ((*pzText == '=') || (*pzText == ':')) {
+        while (isspace( *++pzText ))   ;
+        if (pzText > pzEnd)
+            goto name_only;
+    } else if (! isspace(pzText[-1]))
+        return NULL;
+
+    /*
+     *  IF the value is continued, remove the backslash escape and push "pzEnd"
+     *  on to a newline *not* preceded by a backslash.
+     */
+    if (pzEnd[-1] == '\\') {
+        char* pcD = pzEnd-1;
+        char* pcS = pzEnd;
+
+        for (;;) {
+            char ch = *(pcS++);
+            switch (ch) {
+            case NUL:
+                pcS = NULL;
+
+            case '\n':
+                *pcD = NUL;
+                pzEnd = pcS;
+                goto copy_done;
+
+            case '\\':
+                if (*pcS == '\n') {
+                    ch = *(pcS++);
+                }
+                /* FALLTHROUGH */
+            default:
+                *(pcD++) = ch;
+            }
+        } copy_done:;
+
+    } else {
+        /*
+         *  The newline was not preceded by a backslash.  NUL it out
+         */
+        *(pzEnd++) = NUL;
+    }
+
+    /*
+     *  "pzName" points to what looks like text for one option/configurable.
+     *  It is NUL terminated.  Process it.
+     */
+    loadOptionLine( pOpts, pOS, pzName, direction, OPTION_LOAD_UNCOOKED );
+
+    return pzEnd;
+}
+
+
+/*  handleDirective
+ *
+ *  "pzText" points to a "<?" sequence.
+ *  For the moment, we only handle "<?program" directives.
+ */
+static char*
+handleDirective(
+    tOptions*     pOpts,
+    char*         pzText )
+{
+    char   ztitle[32] = "<?";
+    size_t title_len = strlen( zProg );
+    size_t name_len;
+
+    if (  (strncmp( pzText+2, zProg, title_len ) != 0)
+       || (! isspace( pzText[title_len+2] )) )  {
+        pzText = strchr( pzText+2, '>' );
+        if (pzText != NULL)
+            pzText++;
+        return pzText;
+    }
+
+    name_len = strlen( pOpts->pzProgName );
+    strcpy( ztitle+2, zProg );
+    title_len += 2;
+
+    do  {
+        pzText += title_len;
+
+        if (isspace(*pzText)) {
+            while (isspace(*pzText))  pzText++;
+            if (  (strneqvcmp( pzText, pOpts->pzProgName, name_len ) == 0)
+               && (pzText[name_len] == '>'))  {
+                pzText += name_len + 1;
+                break;
+            }
+        }
+
+        pzText = strstr( pzText, ztitle );
+    } while (pzText != NULL);
+
+    return pzText;
+}
+
+
+/*  handleProgramSection
+ *
+ *  "pzText" points to a '[' character.
+ *  The "traditional" [PROG_NAME] segmentation of the config file.
+ *  Do not ever mix with the "<?program prog-name>" variation.
+ */
+static char*
+handleProgramSection(
+    tOptions*     pOpts,
+    char*         pzText )
+{
+    size_t len = strlen( pOpts->pzPROGNAME );
+    if (   (strncmp( pzText+1, pOpts->pzPROGNAME, len ) == 0)
+        && (pzText[len+1] == ']'))
+        return strchr( pzText + len + 2, '\n' );
+
+    if (len > 16)
+        return NULL;
+
+    {
+        char z[24];
+        sprintf( z, "[%s]", pOpts->pzPROGNAME );
+        pzText = strstr( pzText, z );
+    }
+
+    if (pzText != NULL)
+        pzText = strchr( pzText, '\n' );
+    return pzText;
+}
+
+
+/*  handleStructure
+ *
+ *  "pzText" points to a '<' character, followed by an alpha.
+ *  The end of the entry is either the "/>" following the name, or else a
+ *  "</name>" string.
+ */
+static char*
+handleStructure(
+    tOptions*     pOpts,
+    tOptState*    pOS,
+    char*         pzText,
+    int           direction )
+{
+    tOptionLoadMode mode = OPTION_LOAD_UNCOOKED;
+    tOptionValue     valu;
+
+    char* pzName = ++pzText;
+    char* pcNulPoint;
+
+    while (ISNAMECHAR( *pzText ))  pzText++;
+    pcNulPoint = pzText;
+    valu.valType = OPARG_TYPE_STRING;
+
+    switch (*pzText) {
+    case ' ':
+    case '\t':
+        pzText = parseAttributes( pOpts, pzText, &mode, &valu );
+        if (*pzText == '>')
+            break;
+        if (*pzText != '/')
+            return NULL;
+
+    case '/':
+        if (pzText[1] != '>')
+            return NULL;
+        *pzText = NUL;
+        pzText += 2;
+        loadOptionLine( pOpts, pOS, pzName, direction, OPTION_LOAD_KEEP );
+        return pzText;
+
+    case '>':
+        break;
+
+    default:
+        pzText = strchr( pzText, '>');
+        if (pzText != NULL)
+            pzText++;
+        return pzText;
+    }
+
+    /*
+     *  If we are here, we have a value.  Separate the name from the
+     *  value for a moment.
+     */
+    *pcNulPoint = NUL;
+
+    /*
+     *  Find the end of the option text and NUL terminate it
+     */
+    {
+        char   z[64], *pz = z;
+        size_t len = strlen(pzName) + 4;
+        if (len > sizeof(z))
+            pz = AGALOC(len, "scan name");
+
+        sprintf( pz, "</%s>", pzName );
+        *pzText = ' ';
+        pzText = strstr( pzText, pz );
+        if (pz != z) free(pz);
+
+        if (pzText == NULL)
+            return pzText;
+
+        *pzText = NUL;
+
+        pzText += len-1;
+    }
+
+    /*
+     *  Rejoin the name and value for parsing by "loadOptionLine()".
+     */
+    *(pcNulPoint++) = ' ';
+
+    /*
+     *  "pzName" points to what looks like text for one option/configurable.
+     *  It is NUL terminated.  Process it.
+     */
+    loadOptionLine( pOpts, pOS, pzName, direction, mode );
+
+    return pzText;
+}
+
+
+/*  internalFileLoad
+ *
+ *  Load a configuration file.  This may be invoked either from
+ *  scanning the "homerc" list, or from a specific file request.
+ *  (see "optionFileLoad()", the implementation for --load-opts)
+ */
+LOCAL void
+internalFileLoad( tOptions* pOpts )
+{
+    int     idx;
+    int     inc = DIRECTION_PRESET;
+    char    zFileName[ MAXPATHLEN+1 ];
+
+    if (pOpts->papzHomeList == NULL)
+        return;
+
+    /*
+     *  Find the last RC entry (highest priority entry)
+     */
+    for (idx = 0; pOpts->papzHomeList[ idx+1 ] != NULL; ++idx)  ;
+
+    /*
+     *  For every path in the home list, ...  *TWICE* We start at the last
+     *  (highest priority) entry, work our way down to the lowest priority,
+     *  handling the immediate options.
+     *  Then we go back up, doing the normal options.
+     */
+    for (;;) {
+        struct stat StatBuf;
+        cch_t*  pzPath;
+
+        /*
+         *  IF we've reached the bottom end, change direction
+         */
+        if (idx < 0) {
+            inc = DIRECTION_PROCESS;
+            idx = 0;
+        }
+
+        pzPath = pOpts->papzHomeList[ idx ];
+
+        /*
+         *  IF we've reached the top end, bail out
+         */
+        if (pzPath == NULL)
+            break;
+
+        idx += inc;
+
+        if (! optionMakePath( zFileName, sizeof( zFileName ),
+                              pzPath, pOpts->pzProgPath ))
+            continue;
+
+        /*
+         *  IF the file name we constructed is a directory,
+         *  THEN append the Resource Configuration file name
+         *  ELSE we must have the complete file name
+         */
+        if (stat( zFileName, &StatBuf ) != 0)
+            continue; /* bogus name - skip the home list entry */
+
+        if (S_ISDIR( StatBuf.st_mode )) {
+            size_t len = strlen( zFileName );
+            char* pz;
+
+            if (len + 1 + strlen( pOpts->pzRcName ) >= sizeof( zFileName ))
+                continue;
+
+            pz = zFileName + len;
+            if (pz[-1] != '/')
+                *(pz++) = '/';
+            strcpy( pz, pOpts->pzRcName );
+        }
+
+        filePreset( pOpts, zFileName, inc );
+
+        /*
+         *  IF we are now to skip config files AND we are presetting,
+         *  THEN change direction.  We must go the other way.
+         */
+        if (SKIP_RC_FILES(pOpts) && PRESETTING(inc)) {
+            idx -= inc;  /* go back and reprocess current file */
+            inc =  DIRECTION_PROCESS;
+        }
+    } /* For every path in the home list, ... */
+}
+
+
+/*=export_func optionFileLoad
+ *
+ * what: Load the locatable config files, in order
+ *
+ * arg:  + tOptions*   + pOpts  + program options descriptor +
+ * arg:  + const char* + pzProg + program name +
+ *
+ * ret_type:  int
+ * ret_desc:  0 -> SUCCESS, -1 -> FAILURE
+ *
+ * doc:
+ *
+ * This function looks in all the specified directories for a configuration
+ * file ("rc" file or "ini" file) and processes any found twice.  The first
+ * time through, they are processed in reverse order (last file first).  At
+ * that time, only "immediate action" configurables are processed.  For
+ * example, if the last named file specifies not processing any more
+ * configuration files, then no more configuration files will be processed.
+ * Such an option in the @strong{first} named directory will have no effect.
+ *
+ * Once the immediate action configurables have been handled, then the
+ * directories are handled in normal, forward order.  In that way, later
+ * config files can override the settings of earlier config files.
+ *
+ * See the AutoOpts documentation for a thorough discussion of the
+ * config file format.
+ *
+ * Configuration files not found or not decipherable are simply ignored.
+ *
+ * err:  Returns the value, "-1" if the program options descriptor
+ *       is out of date or indecipherable.  Otherwise, the value "0" will
+ *       always be returned.
+=*/
+int
+optionFileLoad( tOptions* pOpts, const char* pzProgram )
+{
+    if (! SUCCESSFUL( validateOptionsStruct( pOpts, pzProgram )))
+        return -1;
+
+    pOpts->pzProgName = pzProgram;
+    internalFileLoad( pOpts );
+    return 0;
+}
+
+
+/*=export_func  optionLoadOpt
+ * private:
+ *
+ * what:  Load an option rc/ini file
+ * arg:   + tOptions* + pOpts    + program options descriptor +
+ * arg:   + tOptDesc* + pOptDesc + the descriptor for this arg +
+ *
+ * doc:
+ *  Processes the options found in the file named with pOptDesc->pzLastArg.
+=*/
+void
+optionLoadOpt( tOptions* pOpts, tOptDesc* pOptDesc )
+{
+    /*
+     *  IF the option is not being disabled,
+     *  THEN load the file.  There must be a file.
+     *  (If it is being disabled, then the disablement processing
+     *  already took place.  It must be done to suppress preloading
+     *  of ini/rc files.)
+     */
+    if (! DISABLED_OPT( pOptDesc )) {
+        struct stat sb;
+        if (stat( pOptDesc->pzLastArg, &sb ) != 0) {
+            if ((pOpts->fOptSet & OPTPROC_ERRSTOP) == 0)
+                return;
+
+            fprintf( stderr, zFSErrOptLoad, errno, strerror( errno ),
+                     pOptDesc->pzLastArg );
+            (*pOpts->pUsageProc)( pOpts, EXIT_FAILURE );
+            /* NOT REACHED */
+        }
+
+        if (! S_ISREG( sb.st_mode )) {
+            if ((pOpts->fOptSet & OPTPROC_ERRSTOP) == 0)
+                return;
+
+            fprintf( stderr, zNotFile, pOptDesc->pzLastArg );
+            (*pOpts->pUsageProc)( pOpts, EXIT_FAILURE );
+            /* NOT REACHED */
+        }
+
+        filePreset(pOpts, pOptDesc->pzLastArg, DIRECTION_CALLED);
+    }
+}
+
+
+/*  parseAttributes
+ *
+ *  Parse the various attributes of an XML-styled config file entry
+ */
+LOCAL char*
+parseAttributes(
+    tOptions*           pOpts,
+    char*               pzText,
+    tOptionLoadMode*    pMode,
+    tOptionValue*       pType )
+{
+    size_t lenLoadType = strlen( zLoadType );
+    size_t lenKeyWords = strlen( zKeyWords );
+    size_t lenSetMem   = strlen( zSetMembers );
+
+    do  {
+        switch (*pzText) {
+        case '/': pType->valType = OPARG_TYPE_NONE;
+        case '>': return pzText;
+
+        default:
+        case NUL: return NULL;
+
+        case ' ':
+        case '\t':
+        case '\n':
+        case '\f':
+        case '\r':
+        case '\v':
+            break;
+        }
+
+        while (isspace( *++pzText ))   ;
+
+        if (strncmp( pzText, zLoadType, lenLoadType ) == 0) {
+            pzText = parseValueType( pzText+lenLoadType, pType );
+            continue;
+        }
+
+        if (strncmp( pzText, zKeyWords, lenKeyWords ) == 0) {
+            pzText = parseKeyWordType( pOpts, pzText+lenKeyWords, pType );
+            continue;
+        }
+
+        if (strncmp( pzText, zSetMembers, lenSetMem ) == 0) {
+            pzText = parseSetMemType( pOpts, pzText+lenSetMem, pType );
+            continue;
+        }
+
+        pzText = parseLoadMode( pzText, pMode );
+    } while (pzText != NULL);
+
+    return pzText;
+}
+
+
+/*  parseKeyWordType
+ *
+ *  "pzText" points to the character after "words=".
+ *  What should follow is a name of a keyword (enumeration) list.
+ */
+static char*
+parseKeyWordType(
+    tOptions*     pOpts,
+    char*         pzText,
+    tOptionValue* pType )
+{
+    return skipUnknown( pzText );
+}
+
+
+/*  parseLoadMode
+ *
+ *  "pzText" points to some name character.  We check for "cooked" or
+ *  "uncooked" or "keep".  This function should handle any attribute
+ *  that does not have an associated value.
+ */
+static char*
+parseLoadMode(
+    char*               pzText,
+    tOptionLoadMode*    pMode )
+{
+    {
+        size_t len = strlen(zLoadCooked);
+        if (strncmp( pzText, zLoadCooked, len ) == 0) {
+            if (  (pzText[len] == '>')
+               || (pzText[len] == '/')
+               || isspace(pzText[len])) {
+                *pMode = OPTION_LOAD_COOKED;
+                return pzText + len;
+            }
+            goto unknown;
+        }
+    }
+
+    {
+        size_t len = strlen(zLoadUncooked);
+        if (strncmp( pzText, zLoadUncooked, len ) == 0) {
+            if (  (pzText[len] == '>')
+               || (pzText[len] == '/')
+               || isspace(pzText[len])) {
+                *pMode = OPTION_LOAD_UNCOOKED;
+                return pzText + len;
+            }
+            goto unknown;
+        }
+    }
+
+    {
+        size_t len = strlen(zLoadKeep);
+        if (strncmp( pzText, zLoadKeep, len ) == 0) {
+            if (  (pzText[len] == '>')
+               || (pzText[len] == '/')
+               || isspace(pzText[len])) {
+                *pMode = OPTION_LOAD_KEEP;
+                return pzText + len;
+            }
+            goto unknown;
+        }
+    }
+
+  unknown:
+    return skipUnknown( pzText );
+}
+
+
+/*  parseSetMemType
+ *
+ *  "pzText" points to the character after "members="
+ *  What should follow is a name of a "set membership".
+ *  A collection of bit flags.
+ */
+static char*
+parseSetMemType(
+    tOptions*     pOpts,
+    char*         pzText,
+    tOptionValue* pType )
+{
+    return skipUnknown( pzText );
+}
+
+
+/*  parseValueType
+ *
+ *  "pzText" points to the character after "type="
+ */
+static char*
+parseValueType(
+    char*         pzText,
+    tOptionValue* pType )
+{
+    {
+        size_t len = strlen(zLtypeString);
+        if (strncmp( pzText, zLtypeString, len ) == 0) {
+            if ((pzText[len] == '>') || isspace(pzText[len])) {
+                pType->valType = OPARG_TYPE_STRING;
+                return pzText + len;
+            }
+            goto unknown;
+        }
+    }
+
+    {
+        size_t len = strlen(zLtypeInteger);
+        if (strncmp( pzText, zLtypeInteger, len ) == 0) {
+            if ((pzText[len] == '>') || isspace(pzText[len])) {
+                pType->valType = OPARG_TYPE_NUMERIC;
+                return pzText + len;
+            }
+            goto unknown;
+        }
+    }
+
+    {
+        size_t len = strlen(zLtypeBool);
+        if (strncmp( pzText, zLtypeBool, len ) == 0) {
+            if ((pzText[len] == '>') || isspace(pzText[len])) {
+                pType->valType = OPARG_TYPE_BOOLEAN;
+                return pzText + len;
+            }
+            goto unknown;
+        }
+    }
+
+    {
+        size_t len = strlen(zLtypeKeyword);
+        if (strncmp( pzText, zLtypeKeyword, len ) == 0) {
+            if ((pzText[len] == '>') || isspace(pzText[len])) {
+                pType->valType = OPARG_TYPE_ENUMERATION;
+                return pzText + len;
+            }
+            goto unknown;
+        }
+    }
+
+    {
+        size_t len = strlen(zLtypeSetMembership);
+        if (strncmp( pzText, zLtypeSetMembership, len ) == 0) {
+            if ((pzText[len] == '>') || isspace(pzText[len])) {
+                pType->valType = OPARG_TYPE_MEMBERSHIP;
+                return pzText + len;
+            }
+            goto unknown;
+        }
+    }
+
+    {
+        size_t len = strlen(zLtypeNest);
+        if (strncmp( pzText, zLtypeNest, len ) == 0) {
+            if ((pzText[len] == '>') || isspace(pzText[len])) {
+                pType->valType = OPARG_TYPE_HIERARCHY;
+                return pzText + len;
+            }
+            goto unknown;
+        }
+    }
+
+  unknown:
+    pType->valType = OPARG_TYPE_NONE;
+    return skipUnknown( pzText );
+}
+
+
+/*  skipUnknown
+ *
+ *  Skip over some unknown attribute
+ */
+static char*
+skipUnknown( char* pzText )
+{
+    for (;; pzText++) {
+        if (isspace( *pzText ))  return pzText;
+        switch (*pzText) {
+        case NUL: return NULL;
+        case '/':
+        case '>': return pzText;
+        }
+    }
+}
+
+
+/*  validateOptionsStruct
+ *
+ *  Make sure the option descriptor is there and that we understand it.
+ *  This should be called from any user entry point where one needs to
+ *  worry about validity.  (Some entry points are free to assume that
+ *  the call is not the first to the library and, thus, that this has
+ *  already been called.)
+ */
+LOCAL tSuccess
+validateOptionsStruct( tOptions* pOpts, const char* pzProgram )
+{
+    if (pOpts == NULL) {
+        fputs( zAO_Bad, stderr );
+        exit( EXIT_FAILURE );
+    }
+
+    /*
+     *  IF the client has enabled translation and the translation procedure
+     *  is available, then go do it.
+     */
+    if (  ((pOpts->fOptSet & OPTPROC_TRANSLATE) != 0)
+       && (pOpts->pTransProc != 0) ) {
+        (*pOpts->pTransProc)();
+        pOpts->fOptSet &= ~OPTPROC_TRANSLATE;
+    }
+
+    /*
+     *  IF the struct version is not the current, and also
+     *     either too large (?!) or too small,
+     *  THEN emit error message and fail-exit
+     */
+    if (  ( pOpts->structVersion  != OPTIONS_STRUCT_VERSION  )
+       && (  (pOpts->structVersion > OPTIONS_STRUCT_VERSION  )
+          || (pOpts->structVersion < OPTIONS_MINIMUM_VERSION )
+       )  )  {
+
+        fprintf( stderr, zAO_Err, pOpts->origArgVect[0],
+                 NUM_TO_VER( pOpts->structVersion ));
+        if (pOpts->structVersion > OPTIONS_STRUCT_VERSION )
+            fputs( zAO_Big, stderr );
+        else
+            fputs( zAO_Sml, stderr );
+
+        return FAILURE;
+    }
+
+    /*
+     *  If the program name hasn't been set, then set the name and the path
+     *  and the set of equivalent characters.
+     */
+    if (pOpts->pzProgName == NULL) {
+        const char* pz = strrchr( pzProgram, '/' );
+
+        if (pz == NULL)
+             pOpts->pzProgName = pzProgram;
+        else pOpts->pzProgName = pz+1;
+
+        pOpts->pzProgPath = pzProgram;
+
+        /*
+         *  when comparing long names, these are equivalent
+         */
+        strequate( zSepChars );
+    }
+
+    return SUCCESS;
+}
+
+
+/**
+ * Local Variables:
+ * mode: C
+ * c-file-style: "stroustrup"
+ * tab-width: 4
+ * indent-tabs-mode: nil
+ * End:
+ * end of autoopts/configfile.c */
diff --git a/libopts/cook.c b/libopts/cook.c
new file mode 100644 (file)
index 0000000..763f697
--- /dev/null
@@ -0,0 +1,355 @@
+
+/*
+ *  $Id: cook.c,v 4.3 2006/03/25 19:24:56 bkorb Exp $
+ *  Time-stamp:      "2005-05-20 13:58:56 bkorb"
+ *
+ *  This file contains the routines that deal with processing quoted strings
+ *  into an internal format.
+ */
+
+/*
+ *  Automated Options copyright 1992-2006 Bruce Korb
+ *
+ *  Automated Options is free software.
+ *  You may redistribute it and/or modify it under the terms of the
+ *  GNU General Public License, as published by the Free Software
+ *  Foundation; either version 2, or (at your option) any later version.
+ *
+ *  Automated Options is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with Automated Options.  See the file "COPYING".  If not,
+ *  write to:  The Free Software Foundation, Inc.,
+ *             51 Franklin Street, Fifth Floor,
+ *             Boston, MA  02110-1301, USA.
+ *
+ * As a special exception, Bruce Korb gives permission for additional
+ * uses of the text contained in his release of AutoOpts.
+ *
+ * The exception is that, if you link the AutoOpts library with other
+ * files to produce an executable, this does not by itself cause the
+ * resulting executable to be covered by the GNU General Public License.
+ * Your use of that executable is in no way restricted on account of
+ * linking the AutoOpts library code into it.
+ *
+ * This exception does not however invalidate any other reasons why
+ * the executable file might be covered by the GNU General Public License.
+ *
+ * This exception applies only to the code released by Bruce Korb under
+ * the name AutoOpts.  If you copy code from other sources under the
+ * General Public License into a copy of AutoOpts, as the General Public
+ * License permits, the exception does not apply to the code that you add
+ * in this way.  To avoid misleading anyone as to the status of such
+ * modified files, you must delete this exception notice from them.
+ *
+ * If you write modifications of your own for AutoOpts, it is your choice
+ * whether to permit this exception to apply to your modifications.
+ * If you do not wish that, delete this exception notice.
+ */
+
+/* = = = START-STATIC-FORWARD = = = */
+/* static forward declarations maintained by :mkfwd */
+/* = = = END-STATIC-FORWARD = = = */
+
+/*=export_func  ao_string_cook_escape_char
+ * private:
+ *
+ * what:  escape-process a string fragment
+ * arg:   + const char* + pzScan  + points to character after the escape +
+ * arg:   + char*       + pRes    + Where to put the result byte +
+ * arg:   + char        + nl_ch   + replacement char if scanned char is \n +
+ *
+ * ret-type: unsigned int
+ * ret-desc: The number of bytes consumed processing the escaped character.
+ *
+ * doc:
+ *
+ *  This function converts "t" into "\t" and all your other favorite
+ *  escapes, including numeric ones:  hex and ocatal, too.
+ *  The returned result tells the caller how far to advance the
+ *  scan pointer (passed in).  The default is to just pass through the
+ *  escaped character and advance the scan by one.
+ *
+ *  Some applications need to keep an escaped newline, others need to
+ *  suppress it.  This is accomplished by supplying a '\n' replacement
+ *  character that is different from \n, if need be.  For example, use
+ *  0x7F and never emit a 0x7F.
+ *
+ * err:  @code{NULL} is returned if the string(s) is/are mal-formed.
+=*/
+unsigned int
+ao_string_cook_escape_char( const char* pzIn, char* pRes, char nl )
+{
+    unsigned int  res = 1;
+
+    switch (*pRes = *pzIn++) {
+    case NUL:         /* NUL - end of input string */
+        return 0;
+    case '\r':
+        if (*pzIn != '\n')
+            return 1;
+        res++;
+        /* FALLTHROUGH */
+    case '\n':        /* NL  - emit newline        */
+        *pRes = nl;
+        return res;
+
+    case 'a': *pRes = '\a'; break;
+    case 'b': *pRes = '\b'; break;
+    case 'f': *pRes = '\f'; break;
+    case 'n': *pRes = '\n'; break;
+    case 'r': *pRes = '\r'; break;
+    case 't': *pRes = '\t'; break;
+    case 'v': *pRes = '\v'; break;
+
+    case 'x':         /* HEX Escape       */
+        if (isxdigit( *pzIn ))  {
+            unsigned int  val;
+            unsigned char ch = *pzIn++;
+
+            if ((ch >= 'A') && (ch <= 'F'))
+                val = 10 + (ch - 'A');
+            else if ((ch >= 'a') && (ch <= 'f'))
+                val = 10 + (ch - 'a');
+            else val = ch - '0';
+
+            ch = *pzIn;
+
+            if (! isxdigit( ch )) {
+                *pRes = val;
+                res   = 2;
+                break;
+            }
+            val <<= 4;
+            if ((ch >= 'A') && (ch <= 'F'))
+                val += 10 + (ch - 'A');
+            else if ((ch >= 'a') && (ch <= 'f'))
+                val += 10 + (ch - 'a');
+            else val += ch - '0';
+
+            res = 3;
+            *pRes = val;
+        }
+        break;
+
+    default:
+        /*
+         *  IF the character copied was an octal digit,
+         *  THEN set the output character to an octal value
+         */
+        if (isdigit( *pRes ) && (*pRes < '8'))  {
+            unsigned int  val = *pRes - '0';
+            unsigned char ch  = *pzIn++;
+
+            /*
+             *  IF the second character is *not* an octal digit,
+             *  THEN save the value and bail
+             */
+            if ((ch < '0') || (ch > '7')) {
+                *pRes = val;
+                break;
+            }
+
+            val = (val<<3) + (ch - '0');
+            ch  = *pzIn;
+            res = 2;
+
+            /*
+             *  IF the THIRD character is *not* an octal digit,
+             *  THEN save the value and bail
+             */
+            if ((ch < '0') || (ch > '7')) {
+                *pRes = val;
+                break;
+            }
+
+            /*
+             *  IF the new value would not be too large,
+             *  THEN add on the third and last character value
+             */
+            if ((val<<3) < 0xFF) {
+                val = (val<<3) + (ch - '0');
+                res = 3;
+            }
+
+            *pRes = val;
+            break;
+        }
+    }
+
+    return res;
+}
+
+
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ *
+ *  A quoted string has been found.
+ *  Find the end of it and compress any escape sequences.
+ */
+/*=export_func  ao_string_cook
+ * private:
+ *
+ * what:  concatenate and escape-process strings
+ * arg:   + char* + pzScan     + The *MODIFIABLE* input buffer +
+ * arg:   + int*  + pLineCt    + The (possibly NULL) pointer to a line count +
+ *
+ * ret-type: char*
+ * ret-desc: The address of the text following the processed strings.
+ *           The return value is NULL if the strings are ill-formed.
+ *
+ * doc:
+ *
+ *  A series of one or more quoted strings are concatenated together.
+ *  If they are quoted with double quotes (@code{"}), then backslash
+ *  escapes are processed per the C programming language.  If they are
+ *  single quote strings, then the backslashes are honored only when they
+ *  precede another backslash or a single quote character.
+ *
+ * err:  @code{NULL} is returned if the string(s) is/are mal-formed.
+=*/
+char*
+ao_string_cook( char* pzScan, int* pLineCt )
+{
+    int   l = 0;
+    char  q = *pzScan;
+
+    /*
+     *  It is a quoted string.  Process the escape sequence characters
+     *  (in the set "abfnrtv") and make sure we find a closing quote.
+     */
+    char* pzD = pzScan++;
+    char* pzS = pzScan;
+
+    if (pLineCt == NULL)
+        pLineCt = &l;
+
+    for (;;) {
+        /*
+         *  IF the next character is the quote character, THEN we may end the
+         *  string.  We end it unless the next non-blank character *after* the
+         *  string happens to also be a quote.  If it is, then we will change
+         *  our quote character to the new quote character and continue
+         *  condensing text.
+         */
+        while (*pzS == q) {
+            *pzD = NUL; /* This is probably the end of the line */
+            pzS++;
+
+        scan_for_quote:
+            while (isspace(*pzS))
+                if (*(pzS++) == '\n')
+                    (*pLineCt)++;
+
+            /*
+             *  IF the next character is a quote character,
+             *  THEN we will concatenate the strings.
+             */
+            switch (*pzS) {
+            case '"':
+            case '\'':
+                break;
+
+            case '/':
+                /*
+                 *  Allow for a comment embedded in the concatenated string.
+                 */
+                switch (pzS[1]) {
+                default:  return NULL;
+                case '/':
+                    /*
+                     *  Skip to end of line
+                     */
+                    pzS = strchr( pzS, '\n' );
+                    if (pzS == NULL)
+                        return NULL;
+                    (*pLineCt)++;
+                    break;
+
+                case '*':
+                {
+                    char* p = strstr( pzS+2, "*/" );
+                    /*
+                     *  Skip to terminating star slash
+                     */
+                    if (p == NULL)
+                        return NULL;
+                    while (pzS < p) {
+                        if (*(pzS++) == '\n')
+                            (*pLineCt)++;
+                    }
+
+                    pzS = p + 2;
+                }
+                }
+                goto scan_for_quote;
+
+            default:
+                /*
+                 *  The next non-whitespace character is not a quote.
+                 *  The series of quoted strings has come to an end.
+                 */
+                return pzS;
+            }
+
+            q = *(pzS++);  /* assign new quote character and advance scan */
+        }
+
+        /*
+         *  We are inside a quoted string.  Copy text.
+         */
+        switch (*(pzD++) = *(pzS++)) {
+        case NUL:
+            return NULL;
+
+        case '\n':
+            (*pLineCt)++;
+            break;
+
+        case '\\':
+            /*
+             *  IF we are escaping a new line,
+             *  THEN drop both the escape and the newline from
+             *       the result string.
+             */
+            if (*pzS == '\n') {
+                pzS++;
+                pzD--;
+                (*pLineCt)++;
+            }
+
+            /*
+             *  ELSE IF the quote character is '"' or '`',
+             *  THEN we do the full escape character processing
+             */
+            else if (q != '\'') {
+                int ct = ao_string_cook_escape_char( pzS, pzD-1, '\n' );
+                if (ct == 0)
+                    return NULL;
+
+                pzS += ct;
+            }     /* if (q != '\'')                  */
+
+            /*
+             *  OTHERWISE, we only process "\\", "\'" and "\#" sequences.
+             *  The latter only to easily hide preprocessing directives.
+             */
+            else switch (*pzS) {
+            case '\\':
+            case '\'':
+            case '#':
+                pzD[-1] = *pzS++;
+            }
+        }     /* switch (*(pzD++) = *(pzS++))    */
+    }         /* for (;;)                        */
+}
+/*
+ * Local Variables:
+ * mode: C
+ * c-file-style: "stroustrup"
+ * tab-width: 4
+ * indent-tabs-mode: nil
+ * End:
+ * end of autoopts/cook.c */
diff --git a/libopts/enumeration.c b/libopts/enumeration.c
new file mode 100644 (file)
index 0000000..86f7cc0
--- /dev/null
@@ -0,0 +1,485 @@
+
+/*
+ *  $Id: enumeration.c,v 4.9 2006/03/25 19:24:56 bkorb Exp $
+ * Time-stamp:      "2005-12-09 06:37:15 bkorb"
+ *
+ *   Automated Options Paged Usage module.
+ *
+ *  This routine will run run-on options through a pager so the
+ *  user may examine, print or edit them at their leisure.
+ */
+
+/*
+ *  Automated Options copyright 1992-2006 Bruce Korb
+ *
+ *  Automated Options is free software.
+ *  You may redistribute it and/or modify it under the terms of the
+ *  GNU General Public License, as published by the Free Software
+ *  Foundation; either version 2, or (at your option) any later version.
+ *
+ *  Automated Options is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with Automated Options.  See the file "COPYING".  If not,
+ *  write to:  The Free Software Foundation, Inc.,
+ *             51 Franklin Street, Fifth Floor,
+ *             Boston, MA  02110-1301, USA.
+ *
+ * As a special exception, Bruce Korb gives permission for additional
+ * uses of the text contained in his release of AutoOpts.
+ *
+ * The exception is that, if you link the AutoOpts library with other
+ * files to produce an executable, this does not by itself cause the
+ * resulting executable to be covered by the GNU General Public License.
+ * Your use of that executable is in no way restricted on account of
+ * linking the AutoOpts library code into it.
+ *
+ * This exception does not however invalidate any other reasons why
+ * the executable file might be covered by the GNU General Public License.
+ *
+ * This exception applies only to the code released by Bruce Korb under
+ * the name AutoOpts.  If you copy code from other sources under the
+ * General Public License into a copy of AutoOpts, as the General Public
+ * License permits, the exception does not apply to the code that you add
+ * in this way.  To avoid misleading anyone as to the status of such
+ * modified files, you must delete this exception notice from them.
+ *
+ * If you write modifications of your own for AutoOpts, it is your choice
+ * whether to permit this exception to apply to your modifications.
+ * If you do not wish that, delete this exception notice.
+ */
+
+tSCC*  pz_enum_err_fmt;
+
+/* = = = START-STATIC-FORWARD = = = */
+/* static forward declarations maintained by :mkfwd */
+static void
+enumError(
+    tOptions* pOpts,
+    tOptDesc* pOD,
+    tCC**     paz_names,
+    int       name_ct );
+
+static uintptr_t
+findName(
+    tCC*          pzName,
+    tOptions*     pOpts,
+    tOptDesc*     pOD,
+    tCC**         paz_names,
+    unsigned int  name_ct );
+/* = = = END-STATIC-FORWARD = = = */
+
+static void
+enumError(
+    tOptions* pOpts,
+    tOptDesc* pOD,
+    tCC**     paz_names,
+    int       name_ct )
+{
+    size_t max_len = 0;
+    size_t ttl_len = 0;
+
+    if (pOpts != NULL)
+        fprintf( option_usage_fp, pz_enum_err_fmt,
+                 pOpts->pzProgName, pOD->pzLastArg );
+
+    fprintf( option_usage_fp, zValidKeys, pOD->pz_Name );
+
+    if (**paz_names == 0x7F) {
+        paz_names++;
+        name_ct--;
+    }
+
+    /*
+     *  Figure out the maximum length of any name, plus the total length
+     *  of all the names.
+     */
+    {
+        tCC** paz = paz_names;
+        int   ct  = name_ct;
+
+        do  {
+            size_t len = strlen( *(paz++) ) + 1;
+            if (len > max_len)
+                max_len = len;
+            ttl_len += len;
+        } while (--ct > 0);
+    }
+
+    /*
+     *  IF any one entry is about 1/2 line or longer, print one per line
+     */
+    if (max_len > 35) {
+        do  {
+            fprintf( option_usage_fp, "  %s\n", *(paz_names++) );
+        } while (--name_ct > 0);
+    }
+
+    /*
+     *  ELSE IF they all fit on one line, then do so.
+     */
+    else if (ttl_len < 76) {
+        fputc( ' ', option_usage_fp );
+        do  {
+            fputc( ' ', option_usage_fp );
+            fputs( *(paz_names++), option_usage_fp );
+        } while (--name_ct > 0);
+        fputc( '\n', option_usage_fp );
+    }
+
+    /*
+     *  Otherwise, columnize the output
+     */
+    else {
+        int   ent_no = 0;
+        char  zFmt[16];  /* format for all-but-last entries on a line */
+
+        sprintf( zFmt, "%%-%ds", max_len );
+        max_len = 78 / max_len; /* max_len is now max entries on a line */
+        fputs( "  ", option_usage_fp );
+
+        /*
+         *  Loop through all but the last entry
+         */
+        while (--name_ct > 0) {
+            if (++ent_no == max_len) {
+                /*
+                 *  Last entry on a line.  Start next line, too.
+                 */
+                fprintf( option_usage_fp, "%s\n  ", *(paz_names++) );
+                ent_no = 0;
+            }
+
+            else
+                fprintf( option_usage_fp, zFmt, *(paz_names++) );
+        }
+        fprintf( option_usage_fp, "%s\n", *paz_names );
+    }
+
+    /*
+     *  IF we do not have a pOpts pointer, then this output is being requested
+     *  by the usage procedure.  Let's not re-invoke it recursively.
+     */
+    if (pOpts != NULL)
+        (*(pOpts->pUsageProc))( pOpts, EXIT_FAILURE );
+    if (OPTST_GET_ARGTYPE(pOD->fOptState) == OPARG_TYPE_MEMBERSHIP)
+        fputs( zSetMemberSettings, option_usage_fp );
+}
+
+
+static uintptr_t
+findName(
+    tCC*          pzName,
+    tOptions*     pOpts,
+    tOptDesc*     pOD,
+    tCC**         paz_names,
+    unsigned int  name_ct )
+{
+    uintptr_t     res = name_ct;
+    size_t        len = strlen( (char*)pzName );
+    uintptr_t     idx;
+    /*
+     *  Look for an exact match, but remember any partial matches.
+     *  Multiple partial matches means we have an ambiguous match.
+     */
+    for (idx = 0; idx < name_ct; idx++) {
+        if (strncmp( (char*)paz_names[idx], (char*)pzName, len ) == 0) {
+            if (paz_names[idx][len] == NUL)
+                return idx;  /* full match */
+
+            if (res != name_ct) {
+                pz_enum_err_fmt = zAmbigKey;
+                option_usage_fp = stderr;
+                enumError( pOpts, pOD, paz_names, name_ct );
+            }
+            res = idx; /* save partial match */
+        }
+    }
+
+    /*
+     *  no partial match -> error
+     */
+    if (res == name_ct) {
+        pz_enum_err_fmt = zNoKey;
+        option_usage_fp = stderr;
+        enumError( pOpts, pOD, paz_names, name_ct );
+    }
+
+    /*
+     *  Return the matching index as a char* pointer.
+     *  The result gets stashed in a char* pointer, so it will have to fit.
+     */
+    return res;
+}
+
+
+/*=export_func  optionKeywordName
+ * what:  Convert between enumeration values and strings
+ * private:
+ *
+ * arg:   tOptDesc*,     pOD,       enumeration option description
+ * arg:   unsigned int,  enum_val,  the enumeration value to map
+ *
+ * ret_type:  const char*
+ * ret_desc:  the enumeration name from const memory
+ *
+ * doc:   This converts an enumeration value into the matching string.
+=*/
+const char*
+optionKeywordName(
+    tOptDesc*     pOD,
+    unsigned int  enum_val )
+{
+    tOptDesc od;
+
+    od.pzLastArg = (const char*)(uintptr_t)enum_val;
+    (*(pOD->pOptProc))( (void*)(2UL), &od );
+    return od.pzLastArg;
+}
+
+
+/*=export_func  optionEnumerationVal
+ * what:  Convert from a string to an enumeration value
+ * private:
+ *
+ * arg:   tOptions*,     pOpts,     the program options descriptor
+ * arg:   tOptDesc*,     pOD,       enumeration option description
+ * arg:   const char**,  paz_names, list of enumeration names
+ * arg:   unsigned int,  name_ct,   number of names in list
+ *
+ * ret_type:  char*
+ * ret_desc:  the enumeration value cast as a char*
+ *
+ * doc:   This converts the pzLastArg string from the option description
+ *        into the index corresponding to an entry in the name list.
+ *        This will match the generated enumeration value.
+ *        Full matches are always accepted.  Partial matches are accepted
+ *        if there is only one partial match.
+=*/
+char*
+optionEnumerationVal(
+    tOptions*     pOpts,
+    tOptDesc*     pOD,
+    tCC**         paz_names,
+    unsigned int  name_ct )
+{
+    /*
+     *  IF the program option descriptor pointer is invalid,
+     *  then it is some sort of special request.
+     */
+    switch ((uintptr_t)pOpts) {
+    case 0UL:
+        /*
+         *  print the list of enumeration names.
+         */
+        enumError( pOpts, pOD, paz_names, name_ct );
+        return (char*)0UL;
+
+    case 1UL:
+    {
+        unsigned int ix = (uintptr_t)(pOD->pzLastArg);
+        /*
+         *  print the name string.
+         */
+        if (ix >= name_ct)
+            printf( "INVALID-%d", ix );
+        else
+            fputs( paz_names[ ix ], stdout );
+        return (char*)0UL;
+    }
+    case 2UL:
+    {
+        tSCC zInval[] = "*INVALID*";
+        unsigned int ix = (uintptr_t)(pOD->pzLastArg);
+        /*
+         *  Replace the enumeration value with the name string.
+         */
+        if (ix >= name_ct)
+            return (char*)zInval;
+
+        return (char*)paz_names[ ix ];
+    }
+    default:
+        break;
+    }
+
+    return (char*)findName( pOD->pzLastArg, pOpts, pOD, paz_names, name_ct );
+}
+
+
+/*=export_func  optionSetMembers
+ * what:  Convert between bit flag values and strings
+ * private:
+ *
+ * arg:   tOptions*,     pOpts,     the program options descriptor
+ * arg:   tOptDesc*,     pOD,       enumeration option description
+ * arg:   const char**,  paz_names, list of enumeration names
+ * arg:   unsigned int,  name_ct,   number of names in list
+ *
+ * doc:   This converts the pzLastArg string from the option description
+ *        into the index corresponding to an entry in the name list.
+ *        This will match the generated enumeration value.
+ *        Full matches are always accepted.  Partial matches are accepted
+ *        if there is only one partial match.
+=*/
+void
+optionSetMembers(
+    tOptions*     pOpts,
+    tOptDesc*     pOD,
+    tCC**         paz_names,
+    unsigned int  name_ct )
+{
+    /*
+     *  IF the program option descriptor pointer is invalid,
+     *  then it is some sort of special request.
+     */
+    switch ((uintptr_t)pOpts) {
+    case 0UL:
+        /*
+         *  print the list of enumeration names.
+         */
+        enumError( pOpts, pOD, paz_names, name_ct );
+        return;
+
+    case 1UL:
+    {
+        /*
+         *  print the name string.
+         */
+        uintptr_t bits = (uintptr_t)pOD->optCookie;
+        uintptr_t res  = 0;
+        size_t    len  = 0;
+
+        while (bits != 0) {
+            if (bits & 1) {
+                if (len++ > 0) fputs( " | ", stdout );
+                fputs( paz_names[ res ], stdout );
+            }
+            if (++res >= name_ct) break;
+            bits >>= 1;
+        }
+        return;
+    }
+
+    case 2UL:
+    {
+        char*     pz;
+        uintptr_t bits = (uintptr_t)pOD->optCookie;
+        uintptr_t res  = 0;
+        size_t    len  = 0;
+
+        /*
+         *  Replace the enumeration value with the name string.
+         *  First, determine the needed length, then allocate and fill in.
+         */
+        while (bits != 0) {
+            if (bits & 1)
+                len += strlen( paz_names[ res ]) + 8;
+            if (++res >= name_ct) break;
+            bits >>= 1;
+        }
+
+        pOD->pzLastArg = pz = malloc( len );
+        /*
+         *  Start by clearing all the bits.  We want to turn off any defaults
+         *  because we will be restoring to current state, not adding to
+         *  the default set of bits.
+         */
+        strcpy( pz, "none" );
+        pz += 4;
+        bits = (uintptr_t)pOD->optCookie;
+        res = 0;
+        while (bits != 0) {
+            if (bits & 1) {
+                strcpy( pz, " + " );
+                strcpy( pz+3, paz_names[ res ]);
+                pz += strlen( paz_names[ res ]) + 3;
+            }
+            if (++res >= name_ct) break;
+            bits >>= 1;
+        }
+        return;
+    }
+
+    default:
+        break;
+    }
+
+    {
+        tCC*      pzArg = pOD->pzLastArg;
+        uintptr_t res;
+        if ((pzArg == NULL) || (*pzArg == NUL)) {
+            pOD->optCookie = (void*)0;
+            return;
+        }
+
+        res = (uintptr_t)pOD->optCookie;
+        for (;;) {
+            tSCC zSpn[] = " ,|+\t\r\f\n";
+            int  iv, len;
+
+            pzArg += strspn( pzArg, zSpn );
+            iv = (*pzArg == '!');
+            if (iv)
+                pzArg += strspn( pzArg+1, zSpn ) + 1;
+
+            len = strcspn( pzArg, zSpn );
+            if (len == 0)
+                break;
+
+            if ((len == 3) && (strncmp( pzArg, zAll, 3 ) == 0)) {
+                if (iv)
+                     res = 0;
+                else res = ~0;
+            }
+            else if ((len == 4) && (strncmp( pzArg, zNone, 4 ) == 0)) {
+                if (! iv)
+                    res = 0;
+            }
+            else do {
+                char* pz;
+                uintptr_t bit = strtoul( pzArg, &pz, 0 );
+
+                if (pz != pzArg + len) {
+                    char z[ AO_NAME_SIZE ];
+                    tCC* p;
+                    if (*pz != NUL) {
+                        if (len >= AO_NAME_LIMIT)
+                            break;
+                        strncpy( z, pzArg, len );
+                        z[len] = NUL;
+                        p = z;
+                    } else {
+                        p = pzArg;
+                    }
+
+                    bit = 1UL << findName(p, pOpts, pOD, paz_names, name_ct);
+                }
+                if (iv)
+                     res &= ~bit;
+                else res |= bit;
+            } while (0);
+
+            if (pzArg[len] == NUL)
+                break;
+            pzArg += len + 1;
+        }
+        if (name_ct < (8 * sizeof( uintptr_t ))) {
+            res &= (1UL << name_ct) - 1UL;
+        }
+
+        pOD->optCookie = (void*)res;
+    }
+}
+
+/*
+ * Local Variables:
+ * mode: C
+ * c-file-style: "stroustrup"
+ * tab-width: 4
+ * indent-tabs-mode: nil
+ * End:
+ * end of autoopts/enumeration.c */
diff --git a/libopts/environment.c b/libopts/environment.c
new file mode 100644 (file)
index 0000000..285b229
--- /dev/null
@@ -0,0 +1,261 @@
+
+/*
+ *  $Id: environment.c,v 4.8 2006/03/25 19:24:56 bkorb Exp $
+ * Time-stamp:      "2005-10-29 13:23:59 bkorb"
+ *
+ *  This file contains all of the routines that must be linked into
+ *  an executable to use the generated option processing.  The optional
+ *  routines are in separately compiled modules so that they will not
+ *  necessarily be linked in.
+ */
+
+/*
+ *  Automated Options copyright 1992-2006 Bruce Korb
+ *
+ *  Automated Options is free software.
+ *  You may redistribute it and/or modify it under the terms of the
+ *  GNU General Public License, as published by the Free Software
+ *  Foundation; either version 2, or (at your option) any later version.
+ *
+ *  Automated Options is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with Automated Options.  See the file "COPYING".  If not,
+ *  write to:  The Free Software Foundation, Inc.,
+ *             51 Franklin Street, Fifth Floor,
+ *             Boston, MA  02110-1301, USA.
+ *
+ * As a special exception, Bruce Korb gives permission for additional
+ * uses of the text contained in his release of AutoOpts.
+ *
+ * The exception is that, if you link the AutoOpts library with other
+ * files to produce an executable, this does not by itself cause the
+ * resulting executable to be covered by the GNU General Public License.
+ * Your use of that executable is in no way restricted on account of
+ * linking the AutoOpts library code into it.
+ *
+ * This exception does not however invalidate any other reasons why
+ * the executable file might be covered by the GNU General Public License.
+ *
+ * This exception applies only to the code released by Bruce Korb under
+ * the name AutoOpts.  If you copy code from other sources under the
+ * General Public License into a copy of AutoOpts, as the General Public
+ * License permits, the exception does not apply to the code that you add
+ * in this way.  To avoid misleading anyone as to the status of such
+ * modified files, you must delete this exception notice from them.
+ *
+ * If you write modifications of your own for AutoOpts, it is your choice
+ * whether to permit this exception to apply to your modifications.
+ * If you do not wish that, delete this exception notice.
+ */
+
+/* = = = START-STATIC-FORWARD = = = */
+/* static forward declarations maintained by :mkfwd */
+/* = = = END-STATIC-FORWARD = = = */
+
+/*
+ *  doPrognameEnv - check for preset values from the ${PROGNAME}
+ *  environment variable.  This is accomplished by parsing the text into
+ *  tokens, temporarily replacing the arg vector and calling
+ *  doImmediateOpts and/or doRegularOpts.
+ */
+LOCAL void
+doPrognameEnv( tOptions* pOpts, teEnvPresetType type )
+{
+    const char*   pczOptStr = getenv( pOpts->pzPROGNAME );
+    token_list_t* pTL;
+    int           sv_argc;
+    tAoUI         sv_flag;
+    char**        sv_argv;
+
+    /*
+     *  IF there is no such environment variable
+     *   *or* there is, but we are doing immediate opts and there are
+     *        no immediate opts to do (--help inside $PROGNAME is silly,
+     *        but --no-load-defs is not, so that is marked)
+     *  THEN bail out now.  (
+     */
+    if (  (pczOptStr == NULL)
+       || (  (type == ENV_IMM)
+          && ((pOpts->fOptSet & OPTPROC_HAS_IMMED) == 0)  )  )
+        return;
+
+    /*
+     *  Tokenize the string.  If there's nothing of interest, we'll bail
+     *  here immediately.
+     */
+    pTL = ao_string_tokenize( pczOptStr );
+    if (pTL == NULL)
+        return;
+
+    /*
+     *  Substitute our $PROGNAME argument list for the real one
+     */
+    sv_argc = pOpts->origArgCt;
+    sv_argv = pOpts->origArgVect;
+    sv_flag = pOpts->fOptSet;
+
+    /*
+     *  We add a bogus pointer to the start of the list.  The program name
+     *  has already been pulled from "argv", so it won't get dereferenced.
+     *  The option scanning code will skip the "program name" at the start
+     *  of this list of tokens, so we accommodate this way ....
+     */
+    pOpts->origArgVect = (char**)(pTL->tkn_list - 1);
+    pOpts->origArgCt   = pTL->tkn_ct   + 1;
+    pOpts->fOptSet    &= ~OPTPROC_ERRSTOP;
+
+    pOpts->curOptIdx   = 1;
+    pOpts->pzCurOpt    = NULL;
+
+    switch (type) {
+    case ENV_IMM:
+        /*
+         *  We know the OPTPROC_HAS_IMMED bit is set.
+         */
+        (void)doImmediateOpts( pOpts );
+        break;
+
+    case ENV_NON_IMM:
+        (void)doRegularOpts( pOpts );
+        break;
+
+    default:
+        /*
+         *  Only to immediate opts if the OPTPROC_HAS_IMMED bit is set.
+         */
+        if (pOpts->fOptSet & OPTPROC_HAS_IMMED) {
+            (void)doImmediateOpts( pOpts );
+            pOpts->curOptIdx = 1;
+            pOpts->pzCurOpt  = NULL;
+        }
+        (void)doRegularOpts( pOpts );
+        break;
+    }
+
+    /*
+     *  Free up the temporary arg vector and restore the original program args.
+     */
+    free( pTL );
+    pOpts->origArgVect = sv_argv;
+    pOpts->origArgCt   = sv_argc;
+    pOpts->fOptSet     = sv_flag;
+}
+
+
+/*
+ *  doEnvPresets - check for preset values from the envrionment
+ *  This routine should process in all, immediate or normal modes....
+ */
+LOCAL void
+doEnvPresets( tOptions* pOpts, teEnvPresetType type )
+{
+    int        ct;
+    tOptState  st;
+    char*      pzFlagName;
+    size_t     spaceLeft;
+    char       zEnvName[ AO_NAME_SIZE ];
+
+    /*
+     *  Finally, see if we are to look at the environment
+     *  variables for initial values.
+     */
+    if ((pOpts->fOptSet & OPTPROC_ENVIRON) == 0)
+        return;
+
+    doPrognameEnv( pOpts, type );
+
+    ct  = pOpts->presetOptCt;
+    st.pOD = pOpts->pOptDesc;
+
+    pzFlagName = zEnvName
+        + snprintf( zEnvName, sizeof( zEnvName ), "%s_", pOpts->pzPROGNAME );
+    spaceLeft = AO_NAME_SIZE - (pzFlagName - zEnvName) - 1;
+
+    for (;ct-- > 0; st.pOD++) {
+        /*
+         *  If presetting is disallowed, then skip this entry
+         */
+        if (  ((st.pOD->fOptState & OPTST_NO_INIT) != 0)
+           || (st.pOD->optEquivIndex != NO_EQUIVALENT)  )
+            continue;
+
+        /*
+         *  IF there is no such environment variable,
+         *  THEN skip this entry, too.
+         */
+        if (strlen( st.pOD->pz_NAME ) >= spaceLeft)
+            continue;
+
+        /*
+         *  Set up the option state
+         */
+        strcpy( pzFlagName, st.pOD->pz_NAME );
+        st.pzOptArg = getenv( zEnvName );
+        if (st.pzOptArg == NULL)
+            continue;
+        st.flags    = OPTST_PRESET | st.pOD->fOptState;
+        st.optType  = TOPT_UNDEFINED;
+
+        if (  (st.pOD->pz_DisablePfx != NULL)
+           && (streqvcmp( st.pzOptArg, st.pOD->pz_DisablePfx ) == 0)) {
+            st.flags |= OPTST_DISABLED;
+            st.pzOptArg = NULL;
+        }
+
+        switch (type) {
+        case ENV_IMM:
+            /*
+             *  Process only immediate actions
+             */
+            if (DO_IMMEDIATELY(st.flags))
+                break;
+            continue;
+
+        case ENV_NON_IMM:
+            /*
+             *  Process only NON immediate actions
+             */
+            if (DO_NORMALLY(st.flags) || DO_SECOND_TIME(st.flags))
+                break;
+            continue;
+
+        default: /* process everything */
+            break;
+        }
+
+        /*
+         *  Make sure the option value string is persistent and consistent.
+         *  This may be a memory leak, but we cannot do anything about it.
+         *
+         *  The interpretation of the option value depends
+         *  on the type of value argument the option takes
+         */
+        if (st.pzOptArg != NULL) {
+            if (OPTST_GET_ARGTYPE(st.pOD->fOptState) == OPARG_TYPE_NONE) {
+                st.pzOptArg = NULL;
+            } else if (  (st.pOD->fOptState & OPTST_ARG_OPTIONAL)
+                      && (*st.pzOptArg == NUL)) {
+                    st.pzOptArg = NULL;
+            } else if (*st.pzOptArg == NUL) {
+                st.pzOptArg = zNil;
+            } else {
+                AGDUPSTR( st.pzOptArg, st.pzOptArg, "option argument" );
+            }
+        }
+
+        handleOption( pOpts, &st );
+    }
+}
+
+/*
+ * Local Variables:
+ * mode: C
+ * c-file-style: "stroustrup"
+ * tab-width: 4
+ * indent-tabs-mode: nil
+ * End:
+ * end of autoopts/environment.c */
diff --git a/libopts/genshell.c b/libopts/genshell.c
new file mode 100644 (file)
index 0000000..5b321cf
--- /dev/null
@@ -0,0 +1,301 @@
+/*   -*- buffer-read-only: t -*- vi: set ro:
+ *  
+ *  DO NOT EDIT THIS FILE   (genshell.c)
+ *  
+ *  It has been AutoGen-ed  Sunday April  9, 2006 at 11:49:19 AM PDT
+ *  From the definitions    genshell.def
+ *  and the template file   options
+ */
+
+#define OPTION_CODE_COMPILE 1
+#include "genshell.h"
+
+#ifdef  __cplusplus
+extern "C" {
+#endif
+tSCC zCopyright[] =
+       "genshellopt copyright (c) 1999-2006 Bruce Korb, all rights reserved";
+tSCC zCopyrightNotice[] =
+       "genshellopt is free software; you can redistribute it and/or\n\
+modify it under the terms of the GNU Lesser General Public\n\
+License as published by the Free Software Foundation; either\n\
+version 2.1 of the License, or (at your option) any later version.\n\n\
+genshellopt is distributed in the hope that it will be useful,\n\
+but WITHOUT ANY WARRANTY; without even the implied warranty of\n\
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n\
+Lesser General Public License for more details.\n\n\
+You should have received a copy of the GNU Lesser General Public\n\
+License along with genshellopt.  If not, write to:\n\
+\tThe Free Software Foundation, Inc.,\n\
+\t51 Franklin Street, Fifth Floor\n\
+\tBoston, MA  02110-1301, USA.";
+extern tUsageProc genshelloptUsage;
+
+#ifndef NULL
+#  define NULL 0
+#endif
+#ifndef EXIT_SUCCESS
+#  define  EXIT_SUCCESS 0
+#endif
+#ifndef EXIT_FAILURE
+#  define  EXIT_FAILURE 1
+#endif
+/*
+ *  Script option description:
+ */
+tSCC    zScriptText[] =
+        "Output Script File";
+tSCC    zScript_NAME[]             = "SCRIPT";
+tSCC    zScript_Name[]             = "script";
+#define SCRIPT_FLAGS       (OPTST_DISABLED \
+       | OPTST_SET_ARGTYPE(OPARG_TYPE_STRING))
+
+/*
+ *  Shell option description:
+ */
+tSCC    zShellText[] =
+        "Shell name (follows \"#!\" magic)";
+tSCC    zShell_NAME[]              = "SHELL";
+tSCC    zNotShell_Name[]           = "no-shell";
+tSCC    zNotShell_Pfx[]            = "no";
+#define zShell_Name                  (zNotShell_Name + 3)
+#define SHELL_FLAGS       (OPTST_INITENABLED \
+       | OPTST_SET_ARGTYPE(OPARG_TYPE_STRING))
+
+/*
+ *  Help/More_Help/Version option descriptions:
+ */
+tSCC zHelpText[]       = "Display usage information and exit";
+tSCC zHelp_Name[]      = "help";
+
+tSCC zMore_HelpText[]  = "Extended usage information passed thru pager";
+tSCC zMore_Help_Name[] = "more-help";
+
+tSCC zVersionText[]    = "Output version information and exit";
+tSCC zVersion_Name[]   = "version";
+/*
+ *  Declare option callback procedures
+ */
+extern tOptProc
+    optionPagedUsage, optionPrintVersion;
+static tOptProc
+    doUsageOpt;
+
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ *
+ *  Define the Genshellopt Option Descriptions.
+ */
+static tOptDesc optDesc[ OPTION_CT ] = {
+  {  /* entry idx, value */ 0, VALUE_OPT_SCRIPT,
+     /* equiv idx, value */ 0, VALUE_OPT_SCRIPT,
+     /* equivalenced to  */ NO_EQUIVALENT,
+     /* min, max, act ct */ 0, 1, 0,
+     /* opt state flags  */ SCRIPT_FLAGS, 0,
+     /* last opt argumnt */ NULL,
+     /* arg list/cookie  */ NULL,
+     /* must/cannot opts */ NULL, NULL,
+     /* option proc      */ NULL,
+     /* desc, NAME, name */ zScriptText, zScript_NAME, zScript_Name,
+     /* disablement strs */ NULL, NULL },
+
+  {  /* entry idx, value */ 1, VALUE_OPT_SHELL,
+     /* equiv idx, value */ 1, VALUE_OPT_SHELL,
+     /* equivalenced to  */ NO_EQUIVALENT,
+     /* min, max, act ct */ 0, 1, 0,
+     /* opt state flags  */ SHELL_FLAGS, 0,
+     /* last opt argumnt */ NULL,
+     /* arg list/cookie  */ NULL,
+     /* must/cannot opts */ NULL, NULL,
+     /* option proc      */ NULL,
+     /* desc, NAME, name */ zShellText, zShell_NAME, zShell_Name,
+     /* disablement strs */ zNotShell_Name, zNotShell_Pfx },
+
+  {  /* entry idx, value */ INDEX_OPT_VERSION, VALUE_OPT_VERSION,
+     /* equiv idx value  */ NO_EQUIVALENT, 0,
+     /* equivalenced to  */ NO_EQUIVALENT,
+     /* min, max, act ct */ 0, 1, 0,
+     /* opt state flags  */ OPTST_SET_ARGTYPE(OPARG_TYPE_STRING)
+                          | OPTST_ARG_OPTIONAL, 0,
+     /* last opt argumnt */ NULL,
+     /* arg list/cookie  */ NULL,
+     /* must/cannot opts */ NULL, NULL,
+     /* option proc      */ optionPrintVersion,
+     /* desc, NAME, name */ zVersionText, NULL, zVersion_Name,
+     /* disablement strs */ NULL, NULL },
+
+  {  /* entry idx, value */ INDEX_OPT_HELP, VALUE_OPT_HELP,
+     /* equiv idx value  */ NO_EQUIVALENT, 0,
+     /* equivalenced to  */ NO_EQUIVALENT,
+     /* min, max, act ct */ 0, 1, 0,
+     /* opt state flags  */ OPTST_IMM, 0,
+     /* last opt argumnt */ NULL,
+     /* arg list/cookie  */ NULL,
+     /* must/cannot opts */ NULL, NULL,
+     /* option proc      */ doUsageOpt,
+     /* desc, NAME, name */ zHelpText, NULL, zHelp_Name,
+     /* disablement strs */ NULL, NULL },
+
+  {  /* entry idx, value */ INDEX_OPT_MORE_HELP, VALUE_OPT_MORE_HELP,
+     /* equiv idx value  */ NO_EQUIVALENT, 0,
+     /* equivalenced to  */ NO_EQUIVALENT,
+     /* min, max, act ct */ 0, 1, 0,
+     /* opt state flags  */ OPTST_IMM, 0,
+     /* last opt argumnt */ NULL,
+     /* arg list/cookie  */ NULL,
+     /* must/cannot opts */ NULL,  NULL,
+     /* option proc      */ optionPagedUsage,
+     /* desc, NAME, name */ zMore_HelpText, NULL, zMore_Help_Name,
+     /* disablement strs */ NULL, NULL }
+};
+
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ *
+ *  Define the Genshellopt Option Environment
+ */
+tSCC   zPROGNAME[]   = "GENSHELLOPT";
+tSCC   zUsageTitle[] =
+"genshellopt - Generate Shell Option Processing Script - Ver. 1\n\
+USAGE:  %s [ -<flag> [<val>] | --<name>[{=| }<val>] ]...\n";
+#define zRcName     NULL
+#define apzHomeList NULL
+
+tSCC   zBugsAddr[]    = "autogen-users@lists.sf.net";
+tSCC   zExplain[]     = "\n\
+Note that `shell' is only useful if the output file does not already\n\
+exist.  If it does, then the shell name and optional first argument\n\
+will be extracted from the script file.\n";
+tSCC    zDetail[]     = "\n\
+If the script file already exists and contains Automated Option Processing\n\
+text, the second line of the file through the ending tag will be replaced\n\
+by the newly generated text.  The first `#!' line will be regenerated.\n";
+tSCC    zFullVersion[] = GENSHELLOPT_FULL_VERSION;
+/* extracted from optcode near line 321 */
+
+#if defined(ENABLE_NLS)
+# define OPTPROC_BASE OPTPROC_TRANSLATE
+  static tOptionXlateProc translate_option_strings;
+#else
+# define OPTPROC_BASE OPTPROC_NONE
+# define translate_option_strings NULL
+#endif /* ENABLE_NLS */
+
+tOptions genshelloptOptions = {
+    OPTIONS_STRUCT_VERSION,
+    0, NULL,                    /* original argc + argv    */
+    ( OPTPROC_BASE
+    + OPTPROC_ERRSTOP
+    + OPTPROC_SHORTOPT
+    + OPTPROC_LONGOPT
+    + OPTPROC_NO_REQ_OPT
+    + OPTPROC_NEGATIONS
+    + OPTPROC_NO_ARGS ),
+    0, NULL,                    /* current option index, current option */
+    NULL,         NULL,         zPROGNAME,
+    zRcName,      zCopyright,   zCopyrightNotice,
+    zFullVersion, apzHomeList,  zUsageTitle,
+    zExplain,     zDetail,      optDesc,
+    zBugsAddr,                  /* address to send bugs to */
+    NULL, NULL,                 /* extensions/saved state  */
+    genshelloptUsage,       /* usage procedure */
+    translate_option_strings,   /* translation procedure */
+    /*
+     *  Indexes to special options
+     */
+    { INDEX_OPT_MORE_HELP,
+       0 /* no option state saving */,
+      NO_EQUIVALENT /* index of '-#' option */,
+      NO_EQUIVALENT /* index of default opt */
+    },
+    OPTION_CT, 2 /* user option count */
+};
+
+/*
+ *  Create the static procedure(s) declared above.
+ */
+static void
+doUsageOpt(
+    tOptions*   pOptions,
+    tOptDesc*   pOptDesc )
+{
+    USAGE( EXIT_SUCCESS );
+}
+/* extracted from optcode near line 418 */
+
+#if ENABLE_NLS
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+#include <autoopts/usage-txt.h>
+
+static char*
+AO_gettext( const char* pz )
+{
+    char* pzRes;
+    if (pz == NULL)
+        return NULL;
+    pzRes = _(pz);
+    if (pzRes == pz)
+        return pzRes;
+    pzRes = strdup( pzRes );
+    if (pzRes == NULL) {
+        fputs( _("No memory for duping translated strings\n"), stderr );
+        exit( EXIT_FAILURE );
+    }
+    return pzRes;
+}
+
+/*
+ *  This invokes the translation code (e.g. gettext(3)).
+ */
+static void
+translate_option_strings( void )
+{
+    /*
+     *  Guard against re-translation.  It won't work.  The strings will have
+     *  been changed by the first pass through this code.  One shot only.
+     */
+    if (option_usage_text.field_ct == 0)
+        return;
+    /*
+     *  Do the translations.  The first pointer follows the field count field.
+     *  The field count field is the size of a pointer.
+     */
+    {
+        char** ppz = (char**)(void*)&(option_usage_text);
+        int    ix  = option_usage_text.field_ct;
+
+        do {
+            ppz++;
+            *ppz = AO_gettext(*ppz);
+        } while (--ix > 0);
+    }
+    option_usage_text.field_ct = 0;
+
+    {
+        tOptDesc* pOD = genshelloptOptions.pOptDesc;
+        int       ix  = genshelloptOptions.optCt;
+
+        for (;;) {
+            pOD->pzText           = AO_gettext(pOD->pzText);
+            pOD->pz_NAME          = AO_gettext(pOD->pz_NAME);
+            pOD->pz_Name          = AO_gettext(pOD->pz_Name);
+            pOD->pz_DisableName   = AO_gettext(pOD->pz_DisableName);
+            pOD->pz_DisablePfx    = AO_gettext(pOD->pz_DisablePfx);
+            if (--ix <= 0)
+                break;
+            pOD++;
+        }
+    }
+    genshelloptOptions.pzCopyright   = AO_gettext(genshelloptOptions.pzCopyright);
+    genshelloptOptions.pzCopyNotice  = AO_gettext(genshelloptOptions.pzCopyNotice);
+    genshelloptOptions.pzFullVersion = AO_gettext(genshelloptOptions.pzFullVersion);
+    genshelloptOptions.pzUsageTitle  = AO_gettext(genshelloptOptions.pzUsageTitle);
+    genshelloptOptions.pzExplain     = AO_gettext(genshelloptOptions.pzExplain);
+    genshelloptOptions.pzDetail      = AO_gettext(genshelloptOptions.pzDetail);
+}
+
+#endif /* ENABLE_NLS */
+
+#ifdef  __cplusplus
+}
+#endif
diff --git a/libopts/genshell.h b/libopts/genshell.h
new file mode 100644 (file)
index 0000000..621fbc4
--- /dev/null
@@ -0,0 +1,142 @@
+/*   -*- buffer-read-only: t -*- vi: set ro:
+ *  
+ *  DO NOT EDIT THIS FILE   (genshell.h)
+ *  
+ *  It has been AutoGen-ed  Sunday April  9, 2006 at 11:49:19 AM PDT
+ *  From the definitions    genshell.def
+ *  and the template file   options
+ */
+/*
+ *  This file contains the programmatic interface to the Automated
+ *  Options generated for the genshellopt program.
+ *  These macros are documented in the AutoGen info file in the
+ *  "AutoOpts" chapter.  Please refer to that doc for usage help.
+ */
+#ifndef AUTOOPTS_GENSHELL_H_GUARD
+#define AUTOOPTS_GENSHELL_H_GUARD
+
+/*
+ * genshellopt copyright 1999-2006 Bruce Korb - all rights reserved
+ *
+ * genshellopt is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ * 
+ * genshellopt is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ * 
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with genshellopt.  If not, write to:
+ *     The Free Software Foundation, Inc.,
+ *     51 Franklin Street, Fifth Floor
+ *     Boston, MA  02110-1301, USA.
+ */
+#include <autoopts/options.h>
+
+/*
+ *  Ensure that the library used for compiling this generated header is at
+ *  least as new as the version current when the header template was released
+ *  (not counting patch version increments).  Also ensure that the oldest
+ *  tolerable version is at least as old as what was current when the header
+ *  template was released.
+ */
+#define AO_TEMPLATE_VERSION 110592
+#if (AO_TEMPLATE_VERSION < OPTIONS_MINIMUM_VERSION) \
+ || (AO_TEMPLATE_VERSION > OPTIONS_STRUCT_VERSION)
+# error option template version mismatches autoopts/options.h header
+#endif
+
+/*
+ *  Enumeration of each option:
+ */
+typedef enum {
+        INDEX_OPT_SCRIPT           =  0,
+        INDEX_OPT_SHELL            =  1,
+        INDEX_OPT_VERSION          = 2,
+        INDEX_OPT_HELP             = 3,
+        INDEX_OPT_MORE_HELP        = 4
+} teOptIndex;
+
+#define OPTION_CT    5
+#define GENSHELLOPT_VERSION       "1"
+#define GENSHELLOPT_FULL_VERSION  "genshellopt - Generate Shell Option Processing Script - Ver. 1"
+
+/*
+ *  Interface defines for all options.  Replace "n" with
+ *  the UPPER_CASED option name (as in the teOptIndex
+ *  enumeration above).  e.g. HAVE_OPT( SCRIPT )
+ */
+#define        DESC(n) genshelloptOptions.pOptDesc[INDEX_OPT_ ## n]
+#define     HAVE_OPT(n) (! UNUSED_OPT(& DESC(n)))
+#define      OPT_ARG(n) (DESC(n).pzLastArg)
+#define    STATE_OPT(n) (DESC(n).fOptState & OPTST_SET_MASK)
+#define    COUNT_OPT(n) (DESC(n).optOccCt)
+#define    ISSEL_OPT(n) (SELECTED_OPT(&DESC(n)))
+#define ISUNUSED_OPT(n) (UNUSED_OPT(& DESC(n)))
+#define  ENABLED_OPT(n) (! DISABLED_OPT(& DESC(n)))
+#define  STACKCT_OPT(n) (((tArgList*)(DESC(n).optCookie))->useCt)
+#define STACKLST_OPT(n) (((tArgList*)(DESC(n).optCookie))->apzArgs)
+#define    CLEAR_OPT(n) STMTS( \
+                DESC(n).fOptState &= OPTST_PERSISTENT;   \
+                if ( (DESC(n).fOptState & OPTST_INITENABLED) == 0) \
+                    DESC(n).fOptState |= OPTST_DISABLED; \
+                DESC(n).optCookie = NULL )
+
+/*
+ *  Interface defines for specific options.
+ */
+#define VALUE_OPT_SCRIPT         'o'
+#define VALUE_OPT_SHELL          's'
+
+#define VALUE_OPT_VERSION       'v'
+#define VALUE_OPT_HELP          '?'
+#define VALUE_OPT_MORE_HELP     '!'
+/*
+ *  Interface defines not associated with particular options
+ */
+#define ERRSKIP_OPTERR  STMTS( genshelloptOptions.fOptSet &= ~OPTPROC_ERRSTOP )
+#define ERRSTOP_OPTERR  STMTS( genshelloptOptions.fOptSet |= OPTPROC_ERRSTOP )
+#define RESTART_OPT(n)  STMTS( \
+                genshelloptOptions.curOptIdx = (n); \
+                genshelloptOptions.pzCurOpt  = NULL )
+#define START_OPT       RESTART_OPT(1)
+#define USAGE(c)        (*genshelloptOptions.pUsageProc)( &genshelloptOptions, c )
+/* extracted from opthead near line 289 */
+
+/* * * * * *
+ *
+ *  Declare the genshellopt option descriptor.
+ */
+#ifdef  __cplusplus
+extern "C" {
+#endif
+
+extern tOptions   genshelloptOptions;
+
+#ifndef _
+#  if ENABLE_NLS
+#    include <stdio.h>
+     static inline char* aoGetsText( const char* pz ) {
+         if (pz == NULL) return NULL;
+         return (char*)gettext( pz );
+     }
+#    define _(s)  aoGetsText(s)
+#  else  /* ENABLE_NLS */
+#    define _(s)  s
+#  endif /* ENABLE_NLS */
+#endif
+
+#ifdef  __cplusplus
+}
+#endif
+#endif /* AUTOOPTS_GENSHELL_H_GUARD */
+/*
+ * Local Variables:
+ * Mode: C
+ * c-file-style: "stroustrup"
+ * indent-tabs-mode: nil
+ * End:
+ * options.h ends here */
diff --git a/libopts/libopts.c b/libopts/libopts.c
new file mode 100644 (file)
index 0000000..960a492
--- /dev/null
@@ -0,0 +1,30 @@
+#define AUTOOPTS_INTERNAL
+#include "compat/compat.h"
+#define HAVE_LIBSNPRINTFV
+#include "autoopts/options.h"
+#include "autoopts/usage-txt.h"
+#include "genshell.h"
+#include "autoopts.h"
+#include "proto.h"
+#include "autoopts.c"
+#include "boolean.c"
+#include "configfile.c"
+#include "cook.c"
+#include "enumeration.c"
+#include "environment.c"
+#include "genshell.c"
+#include "load.c"
+#include "makeshell.c"
+#include "nested.c"
+#include "numeric.c"
+#include "pgusage.c"
+#include "putshell.c"
+#include "restore.c"
+#include "save.c"
+#include "sort.c"
+#include "stack.c"
+#include "streqvcmp.c"
+#include "text_mmap.c"
+#include "tokenize.c"
+#include "usage.c"
+#include "version.c"
diff --git a/libopts/load.c b/libopts/load.c
new file mode 100644 (file)
index 0000000..e5a2b8f
--- /dev/null
@@ -0,0 +1,520 @@
+
+/*
+ *  $Id: load.c,v 4.18 2006/03/25 19:24:56 bkorb Exp $
+ *  Time-stamp:      "2005-10-29 14:45:36 bkorb"
+ *
+ *  This file contains the routines that deal with processing text strings
+ *  for options, either from a NUL-terminated string passed in or from an
+ *  rc/ini file.
+ */
+
+/*
+ *  Automated Options copyright 1992-2006 Bruce Korb
+ *
+ *  Automated Options is free software.
+ *  You may redistribute it and/or modify it under the terms of the
+ *  GNU General Public License, as published by the Free Software
+ *  Foundation; either version 2, or (at your option) any later version.
+ *
+ *  Automated Options is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with Automated Options.  See the file "COPYING".  If not,
+ *  write to:  The Free Software Foundation, Inc.,
+ *             51 Franklin Street, Fifth Floor,
+ *             Boston, MA  02110-1301, USA.
+ *
+ * As a special exception, Bruce Korb gives permission for additional
+ * uses of the text contained in his release of AutoOpts.
+ *
+ * The exception is that, if you link the AutoOpts library with other
+ * files to produce an executable, this does not by itself cause the
+ * resulting executable to be covered by the GNU General Public License.
+ * Your use of that executable is in no way restricted on account of
+ * linking the AutoOpts library code into it.
+ *
+ * This exception does not however invalidate any other reasons why
+ * the executable file might be covered by the GNU General Public License.
+ *
+ * This exception applies only to the code released by Bruce Korb under
+ * the name AutoOpts.  If you copy code from other sources under the
+ * General Public License into a copy of AutoOpts, as the General Public
+ * License permits, the exception does not apply to the code that you add
+ * in this way.  To avoid misleading anyone as to the status of such
+ * modified files, you must delete this exception notice from them.
+ *
+ * If you write modifications of your own for AutoOpts, it is your choice
+ * whether to permit this exception to apply to your modifications.
+ * If you do not wish that, delete this exception notice.
+ */
+
+/* = = = START-STATIC-FORWARD = = = */
+/* static forward declarations maintained by :mkfwd */
+static ag_bool
+insertProgramPath(
+    char*   pzBuf,
+    int     bufSize,
+    tCC*    pzName,
+    tCC*    pzProgPath );
+
+static ag_bool
+insertEnvVal(
+    char*   pzBuf,
+    int     bufSize,
+    tCC*    pzName,
+    tCC*    pzProgPath );
+
+static char*
+assembleArgValue( char* pzTxt, tOptionLoadMode mode );
+/* = = = END-STATIC-FORWARD = = = */
+
+/*=export_func  optionMakePath
+ * private:
+ *
+ * what:  translate and construct a path
+ * arg:   + char*       + pzBuf      + The result buffer +
+ * arg:   + int         + bufSize    + The size of this buffer +
+ * arg:   + const char* + pzName     + The input name +
+ * arg:   + const char* + pzProgPath + The full path of the current program +
+ *
+ * ret-type: ag_bool
+ * ret-desc: AG_TRUE if the name was handled, otherwise AG_FALSE.
+ *           If the name does not start with ``$'', then it is handled
+ *           simply by copying the input name to the output buffer and
+ *           resolving the name with either @code{canonicalize_file_name(3GLIBC)}
+ *           or @code{realpath(3C)}.
+ *
+ * doc:
+ *
+ *  This routine will copy the @code{pzName} input name into the @code{pzBuf}
+ *  output buffer, carefully not exceeding @code{bufSize} bytes.  If the
+ *  first character of the input name is a @code{'$'} character, then there
+ *  is special handling:
+ *  @*
+ *  @code{$$} is replaced with the directory name of the @code{pzProgPath},
+ *  searching @code{$PATH} if necessary.
+ *  @*
+ *  @code{$NAME} is replaced by the contents of the @code{NAME} environment
+ *  variable.
+ *
+ *  Please note: both @code{$$} and @code{$NAME} must be at the start of the
+ *     @code{pzName} string and must either be the entire string or be followed
+ *     by the @code{'/'} character.
+ *
+ * err:  @code{AG_FALSE} is returned if:
+ *       @*
+ *       @bullet{} The input name exceeds @code{bufSize} bytes.
+ *       @*
+ *       @bullet{} @code{$$} or @code{$NAME} is not the full string and
+ *                 the next character is not '/'.
+ *       @*
+ *       @bullet{} @code{NAME} is not a known environment variable
+ *       @*
+ *       @bullet{} @code{canonicalize_file_name} or @code{realpath} return
+ *                 errors (cannot resolve the resulting path).
+=*/
+ag_bool
+optionMakePath(
+    char*   pzBuf,
+    int     bufSize,
+    tCC*    pzName,
+    tCC*    pzProgPath )
+{
+    ag_bool res = AG_TRUE;
+
+    if (bufSize <= strlen( pzName ))
+        return AG_FALSE;
+
+    /*
+     *  IF not an environment variable, just copy the data
+     */
+    if (*pzName != '$') {
+        tCC*  pzS = pzName;
+        char* pzD = pzBuf;
+        int   ct  = bufSize;
+
+        for (;;) {
+            if ( (*(pzD++) = *(pzS++)) == NUL)
+                break;
+            if (--ct <= 0)
+                return AG_FALSE;
+        }
+    }
+
+    /*
+     *  IF the name starts with "$$", then it must be "$$" or
+     *  it must start with "$$/".  In either event, replace the "$$"
+     *  with the path to the executable and append a "/" character.
+     */
+    else if (pzName[1] == '$')
+        res = insertProgramPath( pzBuf, bufSize, pzName, pzProgPath );
+    else
+        res = insertEnvVal( pzBuf, bufSize, pzName, pzProgPath );
+
+    if (! res)
+        return AG_FALSE;
+
+#if defined(HAVE_CANONICALIZE_FILE_NAME)
+    {
+        char* pz = canonicalize_file_name(pzBuf);
+        if (pz == NULL)
+            return AG_FALSE;
+        if (strlen(pz) < bufSize)
+            strcpy(pzBuf, pz);
+        free(pz);
+    }
+
+#elif defined(HAVE_REALPATH)
+    {
+        char z[ PATH_MAX+1 ];
+
+        if (realpath( pzBuf, z ) == NULL)
+            return AG_FALSE;
+
+        if (strlen(z) < bufSize)
+            strcpy( pzBuf, z );
+    }
+#endif
+
+    return AG_TRUE;
+}
+
+
+static ag_bool
+insertProgramPath(
+    char*   pzBuf,
+    int     bufSize,
+    tCC*    pzName,
+    tCC*    pzProgPath )
+{
+    tCC*    pzPath;
+    tCC*    pz;
+    int     skip = 2;
+
+    switch (pzName[2]) {
+    case '/':
+        skip = 3;
+    case NUL:
+        break;
+    default:
+        return AG_FALSE;
+    }
+
+    /*
+     *  See if the path is included in the program name.
+     *  If it is, we're done.  Otherwise, we have to hunt
+     *  for the program using "pathfind".
+     */
+    if (strchr( pzProgPath, '/' ) != NULL)
+        pzPath = pzProgPath;
+    else {
+        pzPath = pathfind( getenv( "PATH" ), (char*)pzProgPath, "rx" );
+
+        if (pzPath == NULL)
+            return AG_FALSE;
+    }
+
+    pz = strrchr( pzPath, '/' );
+
+    /*
+     *  IF we cannot find a directory name separator,
+     *  THEN we do not have a path name to our executable file.
+     */
+    if (pz == NULL)
+        return AG_FALSE;
+
+    pzName += skip;
+
+    /*
+     *  Concatenate the file name to the end of the executable path.
+     *  The result may be either a file or a directory.
+     */
+    if ((pz - pzPath)+1 + strlen(pzName) >= bufSize)
+        return AG_FALSE;
+
+    memcpy( pzBuf, pzPath, (pz - pzPath)+1 );
+    strcpy( pzBuf + (pz - pzPath) + 1, pzName );
+
+    /*
+     *  If the "pzPath" path was gotten from "pathfind()", then it was
+     *  allocated and we need to deallocate it.
+     */
+    if (pzPath != pzProgPath)
+        free( (void*)pzPath );
+    return AG_TRUE;
+}
+
+
+static ag_bool
+insertEnvVal(
+    char*   pzBuf,
+    int     bufSize,
+    tCC*    pzName,
+    tCC*    pzProgPath )
+{
+    char* pzDir = pzBuf;
+
+    for (;;) {
+        char ch = *++pzName;
+        if (! ISNAMECHAR( ch ))
+            break;
+        *(pzDir++) = ch;
+    }
+
+    if (pzDir == pzBuf)
+        return AG_FALSE;
+
+    *pzDir = NUL;
+
+    pzDir = getenv( pzBuf );
+
+    /*
+     *  Environment value not found -- skip the home list entry
+     */
+    if (pzDir == NULL)
+        return AG_FALSE;
+
+    if (strlen( pzDir ) + 1 + strlen( pzName ) >= bufSize)
+        return AG_FALSE;
+
+    sprintf( pzBuf, "%s%s", pzDir, pzName );
+    return AG_TRUE;
+}
+
+
+LOCAL void
+mungeString( char* pzTxt, tOptionLoadMode mode )
+{
+    char* pzE;
+
+    if (mode == OPTION_LOAD_KEEP)
+        return;
+
+    if (isspace( *pzTxt )) {
+        char* pzS = pzTxt;
+        char* pzD = pzTxt;
+        while (isspace( *++pzS ))  ;
+        while ((*(pzD++) = *(pzS++)) != NUL)   ;
+        pzE = pzD-1;
+    } else
+        pzE = pzTxt + strlen( pzTxt );
+
+    while ((pzE > pzTxt) && isspace( pzE[-1] ))  pzE--;
+    *pzE = NUL;
+
+    if (mode == OPTION_LOAD_UNCOOKED)
+        return;
+
+    switch (*pzTxt) {
+    default: return;
+    case '"':
+    case '\'': break;
+    }
+
+    switch (pzE[-1]) {
+    default: return;
+    case '"':
+    case '\'': break;
+    }
+
+    (void)ao_string_cook( pzTxt, NULL );
+}
+
+
+static char*
+assembleArgValue( char* pzTxt, tOptionLoadMode mode )
+{
+    tSCC zBrk[] = " \t:=";
+    char* pzEnd = strpbrk( pzTxt, zBrk );
+    int   space_break;
+
+    /*
+     *  Not having an argument to a configurable name is okay.
+     */
+    if (pzEnd == NULL)
+        return pzTxt + strlen(pzTxt);
+
+    /*
+     *  If we are keeping all whitespace, then the value starts with the
+     *  character that follows the end of the configurable name, regardless
+     *  of which character caused it.
+     */
+    if (mode == OPTION_LOAD_KEEP) {
+        *(pzEnd++) = NUL;
+        return pzEnd;
+    }
+
+    /*
+     *  If the name ended on a white space character, remember that
+     *  because we'll have to skip over an immediately following ':' or '='
+     *  (and the white space following *that*).
+     */
+    space_break = isspace(*pzEnd);
+    *(pzEnd++) = NUL;
+    while (isspace(*pzEnd))  pzEnd++;
+    if (space_break && ((*pzEnd == ':') || (*pzEnd == '=')))
+        pzEnd++;
+
+    mungeString( pzEnd, mode );
+    return pzEnd;
+}
+
+
+/*
+ *  Load an option from a block of text.  The text must start with the
+ *  configurable/option name and be followed by its associated value.
+ *  That value may be processed in any of several ways.  See "tOptionLoadMode"
+ *  in autoopts.h.
+ */
+LOCAL void
+loadOptionLine(
+    tOptions*   pOpts,
+    tOptState*  pOS,
+    char*       pzLine,
+    tDirection  direction,
+    tOptionLoadMode   load_mode )
+{
+    while (isspace( *pzLine ))  pzLine++;
+
+    {
+        char* pzArg = assembleArgValue( pzLine, load_mode );
+
+        if (! SUCCESSFUL( longOptionFind( pOpts, pzLine, pOS )))
+            return;
+        if (pOS->flags & OPTST_NO_INIT)
+            return;
+        pOS->pzOptArg = pzArg;
+    }
+
+    switch (pOS->flags & (OPTST_IMM|OPTST_DISABLE_IMM)) {
+    case 0:
+        /*
+         *  The selected option has no immediate action.
+         *  THEREFORE, if the direction is PRESETTING
+         *  THEN we skip this option.
+         */
+        if (PRESETTING(direction))
+            return;
+        break;
+
+    case OPTST_IMM:
+        if (PRESETTING(direction)) {
+            /*
+             *  We are in the presetting direction with an option we handle
+             *  immediately for enablement, but normally for disablement.
+             *  Therefore, skip if disabled.
+             */
+            if ((pOS->flags & OPTST_DISABLED) == 0)
+                return;
+        } else {
+            /*
+             *  We are in the processing direction with an option we handle
+             *  immediately for enablement, but normally for disablement.
+             *  Therefore, skip if NOT disabled.
+             */
+            if ((pOS->flags & OPTST_DISABLED) != 0)
+                return;
+        }
+        break;
+
+    case OPTST_DISABLE_IMM:
+        if (PRESETTING(direction)) {
+            /*
+             *  We are in the presetting direction with an option we handle
+             *  immediately for disablement, but normally for disablement.
+             *  Therefore, skip if NOT disabled.
+             */
+            if ((pOS->flags & OPTST_DISABLED) != 0)
+                return;
+        } else {
+            /*
+             *  We are in the processing direction with an option we handle
+             *  immediately for disablement, but normally for disablement.
+             *  Therefore, skip if disabled.
+             */
+            if ((pOS->flags & OPTST_DISABLED) == 0)
+                return;
+        }
+        break;
+
+    case OPTST_IMM|OPTST_DISABLE_IMM:
+        /*
+         *  The selected option is always for immediate action.
+         *  THEREFORE, if the direction is PROCESSING
+         *  THEN we skip this option.
+         */
+        if (PROCESSING(direction))
+            return;
+        break;
+    }
+
+    /*
+     *  Fix up the args.
+     */
+    if (OPTST_GET_ARGTYPE(pOS->pOD->fOptState) == OPARG_TYPE_NONE) {
+        if (*pOS->pzOptArg != NUL)
+            return;
+        pOS->pzOptArg = NULL;
+
+    } else if (pOS->pOD->fOptState & OPTST_ARG_OPTIONAL) {
+        if (*pOS->pzOptArg == NUL)
+             pOS->pzOptArg = NULL;
+        else AGDUPSTR( pOS->pzOptArg, pOS->pzOptArg, "option argument" );
+
+    } else {
+        if (*pOS->pzOptArg == NUL)
+             pOS->pzOptArg = zNil;
+        else AGDUPSTR( pOS->pzOptArg, pOS->pzOptArg, "option argument" );
+    }
+
+    handleOption( pOpts, pOS );
+}
+
+
+/*=export_func  optionLoadLine
+ *
+ * what:  process a string for an option name and value
+ *
+ * arg:   tOptions*,   pOpts,  program options descriptor
+ * arg:   const char*, pzLine, NUL-terminated text
+ *
+ * doc:
+ *
+ *  This is a client program callable routine for setting options from, for
+ *  example, the contents of a file that they read in.  Only one option may
+ *  appear in the text.  It will be treated as a normal (non-preset) option.
+ *
+ *  When passed a pointer to the option struct and a string, it will find
+ *  the option named by the first token on the string and set the option
+ *  argument to the remainder of the string.  The caller must NUL terminate
+ *  the string.  Any embedded new lines will be included in the option
+ *  argument.  If the input looks like one or more quoted strings, then the
+ *  input will be "cooked".  The "cooking" is identical to the string
+ *  formation used in AutoGen definition files (@pxref{basic expression}),
+ *  except that you may not use backquotes.
+ *
+ * err:   Invalid options are silently ignored.  Invalid option arguments
+ *        will cause a warning to print, but the function should return.
+=*/
+void
+optionLoadLine(
+    tOptions*  pOpts,
+    tCC*       pzLine )
+{
+    tOptState st = OPTSTATE_INITIALIZER(SET);
+    char* pz;
+    AGDUPSTR( pz, pzLine, "user option line" );
+    loadOptionLine( pOpts, &st, pz, DIRECTION_PROCESS, OPTION_LOAD_COOKED );
+    AGFREE( pz );
+}
+/*
+ * Local Variables:
+ * mode: C
+ * c-file-style: "stroustrup"
+ * tab-width: 4
+ * indent-tabs-mode: nil
+ * End:
+ * end of autoopts/load.c */
diff --git a/libopts/m4/libopts.m4 b/libopts/m4/libopts.m4
new file mode 100644 (file)
index 0000000..085c776
--- /dev/null
@@ -0,0 +1,487 @@
+dnl  -*- buffer-read-only: t -*- vi: set ro:
+dnl 
+dnl DO NOT EDIT THIS FILE   (libopts.m4)
+dnl 
+dnl It has been AutoGen-ed  Sunday April  9, 2006 at 11:49:18 AM PDT
+dnl From the definitions    libopts.def
+dnl and the template file   conftest.tpl
+dnl
+dnl do always before generated macros:
+dnl
+AC_DEFUN([INVOKE_LIBOPTS_MACROS_FIRST],[
+[if test X${INVOKE_LIBOPTS_MACROS_FIRST_done} != Xyes ; then]
+  # =================
+  # AC_HEADER_STDC
+  # =================
+  AC_HEADER_STDC
+  # =================
+  # AC_HEADER_DIRENT
+  # =================
+  AC_HEADER_DIRENT
+  
+  # =================
+  # AC_CHECK_HEADERS
+  # =================
+  AC_CHECK_HEADERS(dlfcn.h errno.h fcntl.h libgen.h memory.h netinet/in.h \
+    setjmp.h sys/mman.h sys/param.h sys/poll.h sys/procset.h sys/select.h \
+    sys/socket.h sys/stropts.h sys/time.h sys/un.h sys/wait.h unistd.h)
+  
+  # --------------------------------------------
+  # Verify certain entries from AC_CHECK_HEADERS
+  # --------------------------------------------
+  [for f in sys_types sys_mman sys_param sys_stat sys_wait \
+           string errno stdlib memory setjmp
+  do eval as_ac_var=\${ac_cv_header_${f}_h+set}
+     test "${as_ac_var}" = set] || \
+       AC_MSG_ERROR([You must have ${f}.h on your system])
+  done
+  
+  # ================================================
+  # AC_CHECK_HEADERS: stdarg.h is present define HAVE_STDARG_H, otherwise
+  # if varargs.h is present define HAVE_VARARGS_H.
+  # ================================================
+  AC_CHECK_HEADERS(stdarg.h varargs.h, break)
+  [if test `eval echo '${'$as_ac_Header'}'` != yes; then]
+    AC_MSG_ERROR([You must have stdarg.h or varargs.h on your system])
+  fi
+  
+  # ================================================
+  # Similarly for the string.h and strings.h headers
+  # ================================================
+  AC_CHECK_HEADERS(string.h strings.h, break)
+  [if test `eval echo '${'$as_ac_Header'}'` != yes; then]
+    AC_MSG_ERROR([You must have string.h or strings.h on your system])
+  fi
+  
+  # =====================
+  # ...and limits headers
+  # =====================
+  AC_CHECK_HEADERS(limits.h sys/limits.h values.h, break)
+  [if test `eval echo '${'$as_ac_Header'}'` != yes; then]
+    AC_MSG_ERROR([You must have one of limits.h, sys/limits.h or values.h])
+  fi
+  
+  # ========================
+  # ...and int types headers
+  # ========================
+  AC_CHECK_HEADERS(stdint.h inttypes.h, break)
+  AC_CHECK_TYPES([int8_t, uint8_t, int16_t, uint16_t, int32_t, uint32_t,
+     intptr_t])
+  
+  # ====================
+  # uintptr type & sizes
+  # ====================
+  AC_CHECK_TYPES([uintptr_t], ,
+         [AC_DEFINE([uintptr_t], unsigned long,
+                    [Alternate uintptr_t for systems without it.])])
+  AC_CHECK_SIZEOF(char*, 4)
+  AC_CHECK_SIZEOF(int,   4)
+  AC_CHECK_SIZEOF(long,  4)
+  AC_CHECK_SIZEOF(short, 2)
+  
+  # ----------------------------------------------------------------------
+  # AC_CHECK_LIB for SVR4 libgen, and use it if it defines pathfind.
+  # ----------------------------------------------------------------------
+  AC_CHECK_LIB(gen, pathfind)
+  AC_FUNC_VPRINTF
+  AC_CHECK_FUNCS([mmap canonicalize_file_name snprintf strdup])
+[  INVOKE_LIBOPTS_MACROS_FIRST_done=yes
+fi]])
+
+dnl
+dnl @synopsis  INVOKE_LIBOPTS_MACROS
+dnl
+dnl  This macro will invoke the AutoConf macros specified in libopts.def
+dnl  that have not been disabled with "omit-invocation".
+dnl
+AC_DEFUN([LIBOPTS_WITH_REGEX_HEADER],[
+  AC_ARG_WITH([regex-header],
+    AC_HELP_STRING([--with-regex-header], [a reg expr header is specified]),
+    [libopts_cv_with_regex_header=${with_regex_header}],
+    AC_CACHE_CHECK([whether a reg expr header is specified], libopts_cv_with_regex_header,
+      libopts_cv_with_regex_header=no)
+  ) # end of AC_ARG_WITH
+
+  if test "X${libopts_cv_with_regex_header}" != Xno
+  then
+    AC_DEFINE_UNQUOTED([REGEX_HEADER],[<${libopts_cv_with_regex_header}>])
+  else
+    AC_DEFINE([REGEX_HEADER],[<regex.h>],[name of regex header file])
+  fi
+  
+]) # end of AC_DEFUN of LIBOPTS_WITH_REGEX_HEADER
+
+
+AC_DEFUN([LIBOPTS_WITHLIB_REGEX],[
+  AC_ARG_WITH([libregex],
+    AC_HELP_STRING([--with-libregex], [libregex installation prefix]),
+    [libopts_cv_with_libregex_root=${with_libregex}],
+    AC_CACHE_CHECK([whether with-libregex was specified], libopts_cv_with_libregex_root,
+      libopts_cv_with_libregex_root=no)
+  ) # end of AC_ARG_WITH libregex
+
+  if test "${with_libguile+set}" = set && \
+     test "${withval}" = no
+  then ## disabled by request
+    libopts_cv_with_libregex_root=no
+    libopts_cv_with_libregex_cflags=no
+    libopts_cv_with_libregex_libs=no
+  else
+
+  AC_ARG_WITH([libregex-cflags],
+    AC_HELP_STRING([--with-libregex-cflags], [libregex compile flags]),
+    [libopts_cv_with_libregex_cflags=${with_regex_cflags}],
+    AC_CACHE_CHECK([whether with-libregex-cflags was specified], libopts_cv_with_libregex_cflags,
+      libopts_cv_with_libregex_cflags=no)
+  ) # end of AC_ARG_WITH libregex-cflags
+
+  AC_ARG_WITH([libregex-libs],
+    AC_HELP_STRING([--with-libregex-libs], [libregex link command arguments]),
+    [libopts_cv_with_libregex_libs=${with_regex_libs}],
+    AC_CACHE_CHECK([whether with-libregex-libs was specified], libopts_cv_with_libregex_libs,
+      libopts_cv_with_libregex_libs=no)
+  ) # end of AC_ARG_WITH libregex-libs
+
+  case "X${libopts_cv_with_libregex_cflags}" in
+  Xyes|Xno|X )
+    case "X${libopts_cv_with_libregex_root}" in
+    Xyes|Xno|X ) libopts_cv_with_libregex_cflags=no ;;
+    * )        libopts_cv_with_libregex_cflags=-I${libopts_cv_with_libregex_root}/include ;;
+    esac
+  esac
+  case "X${libopts_cv_with_libregex_libs}" in
+  Xyes|Xno|X )
+    case "X${libopts_cv_with_libregex_root}" in
+    Xyes|Xno|X ) libopts_cv_with_libregex_libs=no ;;
+    * )        libopts_cv_with_libregex_libs="-L${libopts_cv_with_libregex_root}/lib -lregex";;
+    esac
+  esac
+  libopts_save_CPPFLAGS="${CPPFLAGS}"
+  libopts_save_LIBS="${LIBS}"
+  fi ## disabled by request
+
+  case "X${libopts_cv_with_libregex_cflags}" in
+  Xyes|Xno|X )
+    libopts_cv_with_libregex_cflags="" ;;
+  * ) CPPFLAGS="${CPPFLAGS} ${libopts_cv_with_libregex_cflags}" ;;
+  esac
+  case "X${libopts_cv_with_libregex_libs}" in
+  Xyes|Xno|X )
+    libopts_cv_with_libregex_libs="" ;;
+  * )
+    LIBS="${LIBS} ${libopts_cv_with_libregex_libs}" ;;
+  esac
+  LIBREGEX_CFLAGS=""
+  LIBREGEX_LIBS=""
+  AC_MSG_CHECKING([whether libregex functions properly])
+  AC_CACHE_VAL([libopts_cv_with_libregex],[
+  AC_TRY_RUN([@%:@include <stdio.h>
+@%:@include <stdlib.h>
+@%:@include <sys/types.h>
+@%:@include REGEX_HEADER
+static regex_t re;
+void comp_re( const char* pzPat ) {
+  int res = regcomp( &re, pzPat, REG_EXTENDED|REG_ICASE|REG_NEWLINE );
+  if (res == 0) return;
+  exit( res ); }
+int main() {
+  regmatch_t m@<:@2@:>@;
+  comp_re( "^.*\@S|@"   );
+  comp_re( "()|no.*" );
+  comp_re( "."       );
+  if (regexec( &re, "X", 2, m, 0 ) != 0)  return 1;
+  if ((m@<:@0@:>@.rm_so != 0) || (m@<:@0@:>@.rm_eo != 1)) {
+    fputs( "error: regex -->.<-- did not match\n", stderr );
+    return 1;
+  }
+  return 0; }],
+    [libopts_cv_with_libregex=yes], [libopts_cv_with_libregex=no],
+    [libopts_cv_with_libregex=no]) # end of AC_TRY_RUN 
+  ]) # end of AC_CACHE_VAL for libopts_cv_with_libregex
+  AC_MSG_RESULT([${libopts_cv_with_libregex}])
+
+  if test "X${libopts_cv_with_libregex}" = Xno
+  then
+    CPPFLAGS="${libopts_save_CPPFLAGS}"
+    LIBS="${libopts_save_LIBS}"
+               cat >&2 <<'_EOF_'
+I cannot detect POSIX compliant regcomp/regexec routines.
+These are required for AutoGen to work correctly.  If you have
+such a library present on your system, you must specify it by
+setting the LIBS environment variable, e.g., "LIBS='-lregex'".
+If you do not have such a library on your system, then you should
+download and install, for example, the one from:
+    ftp://ftp.gnu.org/gnu/rx/
+_EOF_
+AC_MSG_ERROR([Cannot find working POSIX regex library])
+  fi
+  
+]) # end of AC_DEFUN of LIBOPTS_WITHLIB_REGEX
+
+
+AC_DEFUN([LIBOPTS_RUN_PATHFIND],[
+  AC_MSG_CHECKING([whether pathfind(3) works])
+  AC_CACHE_VAL([libopts_cv_run_pathfind],[
+  AC_TRY_RUN([@%:@include <string.h>
+@%:@include <stdlib.h>
+int main (int argc, char** argv) {
+   char* pz = pathfind( getenv( "PATH" ), "sh", "x" );
+   return (pz == 0) ? 1 : 0;
+}],
+    [libopts_cv_run_pathfind=yes],[libopts_cv_run_pathfind=no],[libopts_cv_run_pathfind=no]
+  ) # end of TRY_RUN
+  ]) # end of AC_CACHE_VAL for libopts_cv_run_pathfind
+  AC_MSG_RESULT([${libopts_cv_run_pathfind}])
+
+  if test "X${libopts_cv_run_pathfind}" != Xno
+  then
+    AC_DEFINE([HAVE_PATHFIND],[1],
+        [Define this if pathfind(3) works])
+  fi
+  
+]) # end of AC_DEFUN of LIBOPTS_RUN_PATHFIND
+
+
+AC_DEFUN([LIBOPTS_TEST_DEV_ZERO],[
+  AC_MSG_CHECKING([whether /dev/zero is readable device])
+  AC_CACHE_VAL([libopts_cv_test_dev_zero],[
+    libopts_cv_test_dev_zero=`exec 2> /dev/null
+dzero=\`ls -l /dev/zero | egrep ^c......r\`
+test -z "${dzero}" && exit 1
+echo ${dzero}`
+    if test $? -ne 0
+    then libopts_cv_test_dev_zero=no
+    elif test -z "$libopts_cv_test_dev_zero"
+    then libopts_cv_test_dev_zero=no
+    fi
+  ]) # end of CACHE_VAL of libopts_cv_test_dev_zero
+  AC_MSG_RESULT([${libopts_cv_test_dev_zero}])
+
+  if test "X${libopts_cv_test_dev_zero}" != Xno
+  then
+    AC_DEFINE([HAVE_DEV_ZERO],[1],
+        [Define this if /dev/zero is readable device])
+  fi
+  
+]) # end of AC_DEFUN of LIBOPTS_TEST_DEV_ZERO
+
+
+AC_DEFUN([LIBOPTS_RUN_REALPATH],[
+  AC_MSG_CHECKING([whether we have a functional realpath(3C)])
+  AC_CACHE_VAL([libopts_cv_run_realpath],[
+  AC_TRY_RUN([@%:@include <limits.h>
+@%:@include <stdlib.h>
+int main (int argc, char** argv) {
+@%:@ifndef PATH_MAX
+choke me!!
+@%:@else
+   char zPath@<:@PATH_MAX+1@:>@;
+@%:@endif
+   char *pz = realpath(argv@<:@0@:>@, zPath);
+   return (pz == zPath) ? 0 : 1;
+}],
+    [libopts_cv_run_realpath=yes],[libopts_cv_run_realpath=no],[libopts_cv_run_realpath=no]
+  ) # end of TRY_RUN
+  ]) # end of AC_CACHE_VAL for libopts_cv_run_realpath
+  AC_MSG_RESULT([${libopts_cv_run_realpath}])
+
+  if test "X${libopts_cv_run_realpath}" != Xno
+  then
+    AC_DEFINE([HAVE_REALPATH],[1],
+        [Define this if we have a functional realpath(3C)])
+  fi
+  
+]) # end of AC_DEFUN of LIBOPTS_RUN_REALPATH
+
+
+AC_DEFUN([LIBOPTS_RUN_STRFTIME],[
+  AC_MSG_CHECKING([whether strftime() works])
+  AC_CACHE_VAL([libopts_cv_run_strftime],[
+  AC_TRY_RUN([@%:@include <time.h>
+@%:@include <string.h>
+char t_buf@<:@ 64 @:>@;
+int main() {
+  static const char z@<:@@:>@ = "Thursday Aug 28 240";
+  struct tm tm;
+  tm.tm_sec   = 36;  /* seconds after the minute @<:@0, 61@:>@  */
+  tm.tm_min   = 44;  /* minutes after the hour @<:@0, 59@:>@ */
+  tm.tm_hour  = 12;  /* hour since midnight @<:@0, 23@:>@ */
+  tm.tm_mday  = 28;  /* day of the month @<:@1, 31@:>@ */
+  tm.tm_mon   =  7;  /* months since January @<:@0, 11@:>@ */
+  tm.tm_year  = 86;  /* years since 1900 */
+  tm.tm_wday  =  4;  /* days since Sunday @<:@0, 6@:>@ */
+  tm.tm_yday  = 239; /* days since January 1 @<:@0, 365@:>@ */
+  tm.tm_isdst =  1;  /* flag for daylight savings time */
+  strftime( t_buf, sizeof( t_buf ), "%A %b %d %j", &tm );
+  return (strcmp( t_buf, z ) != 0); }],
+    [libopts_cv_run_strftime=yes],[libopts_cv_run_strftime=no],[libopts_cv_run_strftime=no]
+  ) # end of TRY_RUN
+  ]) # end of AC_CACHE_VAL for libopts_cv_run_strftime
+  AC_MSG_RESULT([${libopts_cv_run_strftime}])
+
+  if test "X${libopts_cv_run_strftime}" != Xno
+  then
+    AC_DEFINE([HAVE_STRFTIME],[1],
+        [Define this if strftime() works])
+  fi
+  
+]) # end of AC_DEFUN of LIBOPTS_RUN_STRFTIME
+
+
+AC_DEFUN([LIBOPTS_RUN_FOPEN_BINARY],[
+  AC_MSG_CHECKING([whether fopen accepts "b" mode])
+  AC_CACHE_VAL([libopts_cv_run_fopen_binary],[
+  AC_TRY_RUN([@%:@include <stdio.h>
+int main (int argc, char** argv) {
+FILE* fp = fopen("conftest.@S|@ac_ext", "rb");
+return (fp == NULL) ? 1 : fclose(fp); }],
+    [libopts_cv_run_fopen_binary=yes],[libopts_cv_run_fopen_binary=no],[libopts_cv_run_fopen_binary=no]
+  ) # end of TRY_RUN
+  ]) # end of AC_CACHE_VAL for libopts_cv_run_fopen_binary
+  AC_MSG_RESULT([${libopts_cv_run_fopen_binary}])
+
+  if test "X${libopts_cv_run_fopen_binary}" != Xno
+  then
+    AC_DEFINE([FOPEN_BINARY_FLAG],"b",
+       [fopen(3) accepts a 'b' in the mode flag])
+  else
+    AC_DEFINE([FOPEN_BINARY_FLAG],"",
+       [fopen(3) accepts a 'b' in the mode flag])
+  fi
+  
+]) # end of AC_DEFUN of LIBOPTS_RUN_FOPEN_BINARY
+
+
+AC_DEFUN([LIBOPTS_RUN_FOPEN_TEXT],[
+  AC_MSG_CHECKING([whether fopen accepts "t" mode])
+  AC_CACHE_VAL([libopts_cv_run_fopen_text],[
+  AC_TRY_RUN([@%:@include <stdio.h>
+int main (int argc, char** argv) {
+FILE* fp = fopen("conftest.@S|@ac_ext", "rt");
+return (fp == NULL) ? 1 : fclose(fp); }],
+    [libopts_cv_run_fopen_text=yes],[libopts_cv_run_fopen_text=no],[libopts_cv_run_fopen_text=no]
+  ) # end of TRY_RUN
+  ]) # end of AC_CACHE_VAL for libopts_cv_run_fopen_text
+  AC_MSG_RESULT([${libopts_cv_run_fopen_text}])
+
+  if test "X${libopts_cv_run_fopen_text}" != Xno
+  then
+    AC_DEFINE([FOPEN_TEXT_FLAG],"t",
+       [fopen(3) accepts a 't' in the mode flag])
+  else
+    AC_DEFINE([FOPEN_TEXT_FLAG],"",
+       [fopen(3) accepts a 't' in the mode flag])
+  fi
+  
+]) # end of AC_DEFUN of LIBOPTS_RUN_FOPEN_TEXT
+
+
+AC_DEFUN([INVOKE_LIBOPTS_MACROS],[
+  INVOKE_LIBOPTS_MACROS_FIRST
+  # Check to see if a reg expr header is specified.
+  LIBOPTS_WITH_REGEX_HEADER
+
+  # Check to see if a working libregex can be found.
+  LIBOPTS_WITHLIB_REGEX
+
+  # Check to see if pathfind(3) works.
+  LIBOPTS_RUN_PATHFIND
+
+  # Check to see if /dev/zero is readable device.
+  LIBOPTS_TEST_DEV_ZERO
+
+  # Check to see if we have a functional realpath(3C).
+  LIBOPTS_RUN_REALPATH
+
+  # Check to see if strftime() works.
+  LIBOPTS_RUN_STRFTIME
+
+  # Check to see if fopen accepts "b" mode.
+  LIBOPTS_RUN_FOPEN_BINARY
+
+  # Check to see if fopen accepts "t" mode.
+  LIBOPTS_RUN_FOPEN_TEXT
+
+]) # end AC_DEFUN of INVOKE_LIBOPTS_MACROS
+
+dnl @synopsis  LIBOPTS_CHECK
+dnl
+dnl If autoopts-config works, add the linking information to LIBS.
+dnl Otherwise, add ``libopts-${ao_rev}'' to SUBDIRS and run all
+dnl the config tests that the library needs.  Invoke the
+dnl "INVOKE_LIBOPTS_MACROS" macro iff we are building libopts.
+dnl
+dnl Default to system libopts
+dnl
+AC_DEFUN([LIBOPTS_CHECK],[
+  [NEED_LIBOPTS_DIR='']
+  m4_pushdef([AO_Libopts_Dir],
+           [ifelse($1, , [libopts], [$1])])
+  AC_SUBST(LIBOPTS_DIR, AO_Libopts_Dir)
+  AC_ARG_ENABLE([local-libopts],
+    AC_HELP_STRING([--enable-local-libopts],
+       [Force using the supplied libopts tearoff code]),[
+    if test x$enableval = xyes ; then
+       AC_MSG_NOTICE([Using supplied libopts tearoff])
+       LIBOPTS_LDADD='$(top_builddir)/AO_Libopts_Dir/libopts.la'
+       LIBOPTS_CFLAGS='-I$(top_srcdir)/AO_Libopts_Dir'
+       NEED_LIBOPTS_DIR=true
+    fi])
+
+  [if test -z "${NEED_LIBOPTS_DIR}" ; then]
+     AC_MSG_CHECKING([whether autoopts-config can be found])
+     AC_ARG_WITH([autoopts-config],
+        AC_HELP_STRING([--with-autoopts-config],
+             [specify the config-info script]),
+        [lo_cv_with_autoopts_config=${with_autoopts_config}],
+        AC_CACHE_CHECK([whether autoopts-config is specified],
+             [lo_cv_with_autoopts_config],
+             [if autoopts-config --help 2>/dev/null 1>&2
+        then lo_cv_with_autoopts_config=autoopts-config
+        elif libopts-config --help 2>/dev/null 1>&2
+        then lo_cv_with_autoopts_config=libopts-config
+        else lo_cv_with_autoopts_config=no ; fi])
+     ) # end of AC_ARG_WITH
+
+     AC_CACHE_VAL([lo_cv_test_autoopts],[
+        if test -z "${lo_cv_with_autoopts_config}" \
+                -o X"${lo_cv_with_autoopts_config}" = Xno
+        then
+           if autoopts-config --help 2>/dev/null 1>&2
+           then lo_cv_with_autoopts_config=autoopts-config
+           elif libopts-config --help 2>/dev/null 1>&2
+           then lo_cv_with_autoopts_config=libopts-config
+           else lo_cv_with_autoopts_config=false ; fi
+        fi
+        lo_cv_test_autoopts=`
+            ${lo_cv_with_autoopts_config} --libs` 2> /dev/null
+        if test $? -ne 0 -o -z "${lo_cv_test_autoopts}"
+        then lo_cv_test_autoopts=no ; fi
+     ]) # end of CACHE_VAL
+     AC_MSG_RESULT([${lo_cv_test_autoopts}])
+
+     [if test "X${lo_cv_test_autoopts}" != Xno
+     then
+        LIBOPTS_LDADD="${lo_cv_test_autoopts}"
+        LIBOPTS_CFLAGS="`${lo_cv_with_autoopts_config} --cflags`"
+     else
+        LIBOPTS_LDADD='$(top_builddir)/]AO_Libopts_Dir[/libopts.la'
+        LIBOPTS_CFLAGS='-I$(top_srcdir)/]AO_Libopts_Dir['
+        NEED_LIBOPTS_DIR=true
+     fi
+  fi # end of if test -z "${NEED_LIBOPTS_DIR}"]
+
+  AM_CONDITIONAL([NEED_LIBOPTS], [test -n "${NEED_LIBOPTS_DIR}"])
+  AC_SUBST(LIBOPTS_LDADD)
+  AC_SUBST(LIBOPTS_CFLAGS)
+  AC_SUBST(LIBOPTS_DIR, AO_Libopts_Dir)
+  AC_CONFIG_FILES(AO_Libopts_Dir/Makefile)
+  m4_popdef([AO_Libopts_Dir])
+
+  [if test -n "${NEED_LIBOPTS_DIR}" ; then]
+    INVOKE_LIBOPTS_MACROS
+  else
+    INVOKE_LIBOPTS_MACROS_FIRST
+  [fi
+# end of AC_DEFUN of LIBOPTS_CHECK]
+])
diff --git a/libopts/m4/liboptschk.m4 b/libopts/m4/liboptschk.m4
new file mode 100644 (file)
index 0000000..26f9c24
--- /dev/null
@@ -0,0 +1,39 @@
+# liboptschk.m4 serial 1 (autogen - 5.7.3)
+dnl Copyright (C) 2005 Free Software Foundation, Inc.
+dnl This file is free software; the Free Software Foundation
+dnl gives unlimited permission to copy and/or distribute it,
+dnl with or without modifications, as long as this notice is preserved.
+dnl
+dnl This file can can be used in projects which are not available under
+dnl the GNU General Public License or the GNU Library General Public
+dnl License but which still want to provide support for the GNU gettext
+dnl functionality.
+dnl Please note that the actual code of the GNU gettext library is covered
+dnl by the GNU Library General Public License, and the rest of the GNU
+dnl gettext package package is covered by the GNU General Public License.
+dnl They are *not* in the public domain.
+
+dnl Authors:
+dnl   Ulrich Drepper <drepper@cygnus.com>, 1995-2000.
+dnl   Bruno Haible <haible@clisp.cons.org>, 2000-2003.
+
+AC_PREREQ(2.50)
+
+AC_DEFUN([ag_FIND_LIBOPTS],
+    [if test "X${ac_cv_header_autoopts_options_h}" == Xno
+    then
+      :
+    else
+      f=`autoopts-config cflags` 2>/dev/null
+      test X"${f}" = X && f=`libopts-config cflags` 2>/dev/null
+      if test X"${f}" = X
+      then
+        :
+      else
+        AC_DEFINE([HAVE_LIBOPTS],[1],[define if we can find libopts])
+        CFLAGS="${CFLAGS} ${f}"
+        f=`autoopts-config ldflags` 2>/dev/null
+        test X"${f}" = X && f=`libopts-config ldflags` 2>/dev/null
+        LIBS="${LIBS} ${f}"
+      fi
+    fi])
diff --git a/libopts/makeshell.c b/libopts/makeshell.c
new file mode 100644 (file)
index 0000000..32bcaa3
--- /dev/null
@@ -0,0 +1,1100 @@
+
+/*
+ *  $Id: makeshell.c,v 4.8 2006/03/25 19:24:56 bkorb Exp $
+ * Time-stamp:      "2005-10-29 13:23:33 bkorb"
+ *
+ *  This module will interpret the options set in the tOptions
+ *  structure and create a Bourne shell script capable of parsing them.
+ */
+
+/*
+ *  Automated Options copyright 1992-2006 Bruce Korb
+ *
+ *  Automated Options is free software.
+ *  You may redistribute it and/or modify it under the terms of the
+ *  GNU General Public License, as published by the Free Software
+ *  Foundation; either version 2, or (at your option) any later version.
+ *
+ *  Automated Options is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with Automated Options.  See the file "COPYING".  If not,
+ *  write to:  The Free Software Foundation, Inc.,
+ *             51 Franklin Street, Fifth Floor,
+ *             Boston, MA  02110-1301, USA.
+ *
+ * As a special exception, Bruce Korb gives permission for additional
+ * uses of the text contained in his release of AutoOpts.
+ *
+ * The exception is that, if you link the AutoOpts library with other
+ * files to produce an executable, this does not by itself cause the
+ * resulting executable to be covered by the GNU General Public License.
+ * Your use of that executable is in no way restricted on account of
+ * linking the AutoOpts library code into it.
+ *
+ * This exception does not however invalidate any other reasons why
+ * the executable file might be covered by the GNU General Public License.
+ *
+ * This exception applies only to the code released by Bruce Korb under
+ * the name AutoOpts.  If you copy code from other sources under the
+ * General Public License into a copy of AutoOpts, as the General Public
+ * License permits, the exception does not apply to the code that you add
+ * in this way.  To avoid misleading anyone as to the status of such
+ * modified files, you must delete this exception notice from them.
+ *
+ * If you write modifications of your own for AutoOpts, it is your choice
+ * whether to permit this exception to apply to your modifications.
+ * If you do not wish that, delete this exception notice.
+ */
+
+tOptions*  pShellParseOptions = NULL;
+
+/* * * * * * * * * * * * * * * * * * * * *
+ *
+ *  Setup Format Strings
+ */
+tSCC zStartMarker[] =
+"# # # # # # # # # # -- do not modify this marker --\n#\n"
+"#  DO NOT EDIT THIS SECTION";
+
+tSCC zPreamble[] =
+"%s OF %s\n#\n"
+"#  From here to the next `-- do not modify this marker --',\n"
+"#  the text has been generated %s\n";
+
+tSCC zEndPreamble[] =
+"#  From the %s option definitions\n#\n";
+
+tSCC zMultiDef[] = "\n"
+"if test -z \"${%1$s_%2$s}\"\n"
+"then\n"
+"  %1$s_%2$s_CT=0\n"
+"else\n"
+"  %1$s_%2$s_CT=1\n"
+"  %1$s_%2$s_1=\"${%1$s_%2$s}\"\n"
+"fi\n"
+"export %1$s_%2$s_CT";
+
+tSCC zSingleDef[] = "\n"
+"%1$s_%2$s=\"${%1$s_%2$s-'%3$s'}\"\n"
+"%1$s_%2$s_set=false\n"
+"export %1$s_%2$s\n";
+
+tSCC zSingleNoDef[] = "\n"
+"%1$s_%2$s=\"${%1$s_%2$s}\"\n"
+"%1$s_%2$s_set=false\n"
+"export %1$s_%2$s\n";
+
+/* * * * * * * * * * * * * * * * * * * * *
+ *
+ *  LOOP START
+ *
+ *  The loop may run in either of two modes:
+ *  all options are named options (loop only)
+ *  regular, marked option processing.
+ */
+tSCC zLoopCase[] = "\n"
+"OPT_PROCESS=true\n"
+"OPT_ARG=\"$1\"\n\n"
+"while ${OPT_PROCESS} && [ $# -gt 0 ]\ndo\n"
+"    OPT_ELEMENT=''\n"
+"    OPT_ARG_VAL=''\n\n"
+     /*
+      *  'OPT_ARG' may or may not match the current $1
+      */
+"    case \"${OPT_ARG}\" in\n"
+"    -- )\n"
+"        OPT_PROCESS=false\n"
+"        shift\n"
+"        ;;\n\n";
+
+tSCC zLoopOnly[] = "\n"
+"OPT_ARG=\"$1\"\n\n"
+"while [ $# -gt 0 ]\ndo\n"
+"    OPT_ELEMENT=''\n"
+"    OPT_ARG_VAL=''\n\n"
+"    OPT_ARG=\"${1}\"\n";
+
+/* * * * * * * * * * * * * * * *
+ *
+ *  CASE SELECTORS
+ *
+ *  If the loop runs as a regular option loop,
+ *  then we must have selectors for each acceptable option
+ *  type (long option, flag character and non-option)
+ */
+tSCC zLongSelection[] =
+"    --* )\n";
+
+tSCC zFlagSelection[] =
+"    -* )\n";
+
+tSCC zEndSelection[] =
+"        ;;\n\n";
+
+tSCC zNoSelection[] =
+"    * )\n"
+"         OPT_PROCESS=false\n"
+"         ;;\n"
+"    esac\n\n";
+
+/* * * * * * * * * * * * * * * *
+ *
+ *  LOOP END
+ */
+tSCC zLoopEnd[] =
+"    if [ -n \"${OPT_ARG_VAL}\" ]\n"
+"    then\n"
+"        eval %1$s_${OPT_NAME}${OPT_ELEMENT}=\"'${OPT_ARG_VAL}'\"\n"
+"        export %1$s_${OPT_NAME}${OPT_ELEMENT}\n"
+"    fi\n"
+"done\n\n"
+"unset OPT_PROCESS || :\n"
+"unset OPT_ELEMENT || :\n"
+"unset OPT_ARG || :\n"
+"unset OPT_ARG_NEEDED || :\n"
+"unset OPT_NAME || :\n"
+"unset OPT_CODE || :\n"
+"unset OPT_ARG_VAL || :\n%2$s";
+
+tSCC zTrailerMarker[] = "\n"
+"# # # # # # # # # #\n#\n"
+"#  END OF AUTOMATED OPTION PROCESSING\n"
+"#\n# # # # # # # # # # -- do not modify this marker --\n";
+
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ *
+ *  OPTION SELECTION
+ */
+tSCC zOptionCase[] =
+"        case \"${OPT_CODE}\" in\n";
+
+tSCC zOptionPartName[] =
+"        '%s' | \\\n";
+
+tSCC zOptionFullName[] =
+"        '%s' )\n";
+
+tSCC zOptionFlag[] =
+"        '%c' )\n";
+
+tSCC zOptionEndSelect[] =
+"            ;;\n\n";
+
+tSCC zOptionUnknown[] =
+"        * )\n"
+"            echo Unknown %s: \"${OPT_CODE}\" >&2\n"
+"            echo \"$%s_USAGE_TEXT\"\n"
+"            exit 1\n"
+"            ;;\n"
+"        esac\n\n";
+
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ *
+ *  OPTION PROCESSING
+ *
+ *  Formats for emitting the text for handling particular options
+ */
+tSCC zTextExit[] =
+"            echo \"$%s_%s_TEXT\"\n"
+"            exit 0\n";
+
+tSCC zPagedUsageExit[] =
+"            echo \"$%s_LONGUSAGE_TEXT\" | ${PAGER-more}\n"
+"            exit 0\n";
+
+tSCC zCmdFmt[] =
+"            %s\n";
+
+tSCC zCountTest[] =
+"            if [ $%1$s_%2$s_CT -ge %3$d ] ; then\n"
+"                echo Error:  more than %3$d %2$s options >&2\n"
+"                echo \"$%1$s_USAGE_TEXT\"\n"
+"                exit 1 ; fi\n";
+
+tSCC zMultiArg[] =
+"            %1$s_%2$s_CT=`expr ${%1$s_%2$s_CT} + 1`\n"
+"            OPT_ELEMENT=\"_${%1$s_%2$s_CT}\"\n"
+"            OPT_NAME='%2$s'\n";
+
+tSCC zSingleArg[] =
+"            if [ -n \"${%1$s_%2$s}\" ] && ${%1$s_%2$s_set} ; then\n"
+"                echo Error:  duplicate %2$s option >&2\n"
+"                echo \"$%1$s_USAGE_TEXT\"\n"
+"                exit 1 ; fi\n"
+"            %1$s_%2$s_set=true\n"
+"            OPT_NAME='%2$s'\n";
+
+tSCC zNoMultiArg[] =
+"            %1$s_%2$s_CT=0\n"
+"            OPT_ELEMENT=''\n"
+"            %1$s_%2$s='%3$s'\n"
+"            export %1$s_%2$s\n"
+"            OPT_NAME='%2$s'\n";
+
+tSCC zNoSingleArg[] =
+"            if [ -n \"${%1$s_%2$s}\" ] && ${%1$s_%2$s_set} ; then\n"
+"                echo Error:  duplicate %2$s option >&2\n"
+"                echo \"$%1$s_USAGE_TEXT\"\n"
+"                exit 1 ; fi\n"
+"            %1$s_%2$s_set=true\n"
+"            %1$s_%2$s='%3$s'\n"
+"            export %1$s_%2$s\n"
+"            OPT_NAME='%2$s'\n";
+
+tSCC zMayArg[]  =
+"            eval %1$s_%2$s${OPT_ELEMENT}=true\n"
+"            export %1$s_%2$s${OPT_ELEMENT}\n"
+"            OPT_ARG_NEEDED=OK\n";
+
+tSCC zMustArg[] =
+"            OPT_ARG_NEEDED=YES\n";
+
+tSCC zCantArg[] =
+"            eval %1$s_%2$s${OPT_ELEMENT}=true\n"
+"            export %1$s_%2$s${OPT_ELEMENT}\n"
+"            OPT_ARG_NEEDED=NO\n";
+
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ *
+ *  LONG OPTION PROCESSING
+ *
+ *  Formats for emitting the text for handling long option types
+ */
+tSCC zLongOptInit[] =
+"        OPT_CODE=`echo \"X${OPT_ARG}\"|sed 's/^X-*//'`\n"
+"        shift\n"
+"        OPT_ARG=\"$1\"\n\n"
+"        case \"${OPT_CODE}\" in *=* )\n"
+"            OPT_ARG_VAL=`echo \"${OPT_CODE}\"|sed 's/^[^=]*=//'`\n"
+"            OPT_CODE=`echo \"${OPT_CODE}\"|sed 's/=.*$//'` ;; esac\n\n";
+
+tSCC zLongOptArg[] =
+"        case \"${OPT_ARG_NEEDED}\" in\n"
+"        NO )\n"
+"            OPT_ARG_VAL=''\n"
+"            ;;\n\n"
+"        YES )\n"
+"            if [ -z \"${OPT_ARG_VAL}\" ]\n"
+"            then\n"
+"                if [ $# -eq 0 ]\n"
+"                then\n"
+"                    echo No argument provided for ${OPT_NAME} option >&2\n"
+"                    echo \"$%s_USAGE_TEXT\"\n"
+"                    exit 1\n"
+"                fi\n\n"
+"                OPT_ARG_VAL=\"${OPT_ARG}\"\n"
+"                shift\n"
+"                OPT_ARG=\"$1\"\n"
+"            fi\n"
+"            ;;\n\n"
+"        OK )\n"
+"            if [ -z \"${OPT_ARG_VAL}\" ] && [ $# -gt 0 ]\n"
+"            then\n"
+"                case \"${OPT_ARG}\" in -* ) ;; * )\n"
+"                    OPT_ARG_VAL=\"${OPT_ARG}\"\n"
+"                    shift\n"
+"                    OPT_ARG=\"$1\" ;; esac\n"
+"            fi\n"
+"            ;;\n"
+"        esac\n";
+
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ *
+ *  FLAG OPTION PROCESSING
+ *
+ *  Formats for emitting the text for handling flag option types
+ */
+tSCC zFlagOptInit[] =
+"        OPT_CODE=`echo \"X${OPT_ARG}\" | sed 's/X-\\(.\\).*/\\1/'`\n"
+"        OPT_ARG=` echo \"X${OPT_ARG}\" | sed 's/X-.//'`\n\n";
+
+tSCC zFlagOptArg[] =
+"        case \"${OPT_ARG_NEEDED}\" in\n"
+"        NO )\n"
+"            if [ -n \"${OPT_ARG}\" ]\n"
+"            then\n"
+"                OPT_ARG=-\"${OPT_ARG}\"\n"
+"            else\n"
+"                shift\n"
+"                OPT_ARG=\"$1\"\n"
+"            fi\n"
+"            ;;\n\n"
+"        YES )\n"
+"            if [ -n \"${OPT_ARG}\" ]\n"
+"            then\n"
+"                OPT_ARG_VAL=\"${OPT_ARG}\"\n\n"
+"            else\n"
+"                if [ $# -eq 0 ]\n"
+"                then\n"
+"                    echo No argument provided for ${OPT_NAME} option >&2\n"
+"                    echo \"$%s_USAGE_TEXT\"\n"
+"                    exit 1\n"
+"                fi\n"
+"                shift\n"
+"                OPT_ARG_VAL=\"$1\"\n"
+"            fi\n\n"
+"            shift\n"
+"            OPT_ARG=\"$1\"\n"
+"            ;;\n\n"
+"        OK )\n"
+"            if [ -n \"${OPT_ARG}\" ]\n"
+"            then\n"
+"                OPT_ARG_VAL=\"${OPT_ARG}\"\n"
+"                shift\n"
+"                OPT_ARG=\"$1\"\n\n"
+"            else\n"
+"                shift\n"
+"                if [ $# -gt 0 ]\n"
+"                then\n"
+"                    case \"$1\" in -* ) ;; * )\n"
+"                        OPT_ARG_VAL=\"$1\"\n"
+"                        shift ;; esac\n"
+"                    OPT_ARG=\"$1\"\n"
+"                fi\n"
+"            fi\n"
+"            ;;\n"
+"        esac\n";
+
+tSCC* pzShell = NULL;
+static char*  pzLeader  = NULL;
+static char*  pzTrailer = NULL;
+
+/* = = = START-STATIC-FORWARD = = = */
+/* static forward declarations maintained by :mkfwd */
+static void
+textToVariable( tOptions* pOpts, teTextTo whichVar, tOptDesc* pOD );
+
+static void
+emitUsage( tOptions* pOpts );
+
+static void
+emitSetup( tOptions* pOpts );
+
+static void
+printOptionAction( tOptions* pOpts, tOptDesc* pOptDesc );
+
+static void
+printOptionInaction( tOptions* pOpts, tOptDesc* pOptDesc );
+
+static void
+emitFlag( tOptions* pOpts );
+
+static void
+emitMatchExpr( tCC* pzMatchName, tOptDesc* pCurOpt, tOptions* pOpts );
+
+static void
+emitLong( tOptions* pOpts );
+
+static void
+openOutput( const char* pzFile );
+/* = = = END-STATIC-FORWARD = = = */
+
+/*=export_func  optionParseShell
+ * private:
+ *
+ * what:  Decipher a boolean value
+ * arg:   + tOptions* + pOpts    + program options descriptor +
+ *
+ * doc:
+ *  Emit a shell script that will parse the command line options.
+=*/
+void
+optionParseShell( tOptions* pOpts )
+{
+    /*
+     *  Check for our SHELL option now.
+     *  IF the output file contains the "#!" magic marker,
+     *  it will override anything we do here.
+     */
+    if (HAVE_OPT( SHELL ))
+        pzShell = OPT_ARG( SHELL );
+
+    else if (! ENABLED_OPT( SHELL ))
+        pzShell = NULL;
+
+    else if ((pzShell = getenv( "SHELL" )),
+             pzShell == NULL)
+
+        pzShell = "/bin/sh";
+
+    /*
+     *  Check for a specified output file
+     */
+    if (HAVE_OPT( SCRIPT ))
+        openOutput( OPT_ARG( SCRIPT ));
+
+    emitUsage( pOpts );
+    emitSetup( pOpts );
+
+    /*
+     *  There are four modes of option processing.
+     */
+    switch (pOpts->fOptSet & (OPTPROC_LONGOPT|OPTPROC_SHORTOPT)) {
+    case OPTPROC_LONGOPT:
+        fputs( zLoopCase,        stdout );
+
+        fputs( zLongSelection,   stdout );
+        fputs( zLongOptInit,     stdout );
+        emitLong( pOpts );
+        printf( zLongOptArg,     pOpts->pzPROGNAME );
+        fputs( zEndSelection,    stdout );
+
+        fputs( zNoSelection,     stdout );
+        break;
+
+    case 0:
+        fputs( zLoopOnly,        stdout );
+        fputs( zLongOptInit,     stdout );
+        emitLong( pOpts );
+        printf( zLongOptArg,     pOpts->pzPROGNAME );
+        break;
+
+    case OPTPROC_SHORTOPT:
+        fputs( zLoopCase,        stdout );
+
+        fputs( zFlagSelection,   stdout );
+        fputs( zFlagOptInit,     stdout );
+        emitFlag( pOpts );
+        printf( zFlagOptArg,     pOpts->pzPROGNAME );
+        fputs( zEndSelection,    stdout );
+
+        fputs( zNoSelection,     stdout );
+        break;
+
+    case OPTPROC_LONGOPT|OPTPROC_SHORTOPT:
+        fputs( zLoopCase,        stdout );
+
+        fputs( zLongSelection,   stdout );
+        fputs( zLongOptInit,     stdout );
+        emitLong( pOpts );
+        printf( zLongOptArg,     pOpts->pzPROGNAME );
+        fputs( zEndSelection,    stdout );
+
+        fputs( zFlagSelection,   stdout );
+        fputs( zFlagOptInit,     stdout );
+        emitFlag( pOpts );
+        printf( zFlagOptArg,     pOpts->pzPROGNAME );
+        fputs( zEndSelection,    stdout );
+
+        fputs( zNoSelection,     stdout );
+        break;
+    }
+
+    printf( zLoopEnd, pOpts->pzPROGNAME, zTrailerMarker );
+    if ((pzTrailer != NULL) && (*pzTrailer != '\0'))
+        fputs( pzTrailer, stdout );
+    else if (ENABLED_OPT( SHELL ))
+        printf( "\nenv | egrep %s_\n", pOpts->pzPROGNAME );
+
+    fflush( stdout );
+    fchmod( STDOUT_FILENO, 0755 );
+    fclose( stdout );
+}
+
+
+static void
+textToVariable( tOptions* pOpts, teTextTo whichVar, tOptDesc* pOD )
+{
+    int  nlHoldCt = 0;
+    int  pipeFd[2];
+    FILE* fp;
+
+#   define _TT_(n) tSCC z ## n [] = #n;
+    TEXTTO_TABLE
+#   undef _TT_
+#   define _TT_(n) z ## n ,
+      static const char*  apzTTNames[] = { TEXTTO_TABLE };
+#   undef _TT_
+
+    printf( "%s_%s_TEXT='", pOpts->pzPROGNAME, apzTTNames[ whichVar ]);
+    fflush( stdout );
+
+    if (pipe( pipeFd ) != 0) {
+        fprintf( stderr, zBadPipe, errno, strerror( errno ));
+        exit( EXIT_FAILURE );
+    }
+
+    switch (fork()) {
+    case -1:
+        fprintf( stderr, zForkFail, errno, strerror(errno), pOpts->pzProgName);
+        exit( EXIT_FAILURE );
+        break;
+
+    case 0:
+        dup2( pipeFd[1], STDERR_FILENO );
+        dup2( pipeFd[1], STDOUT_FILENO );
+        close( pipeFd[0] );
+
+        switch (whichVar) {
+        case TT_LONGUSAGE:
+            (*(pOpts->pUsageProc))( pOpts, EXIT_SUCCESS );
+            /* NOTREACHED */
+            exit( EXIT_FAILURE );
+
+        case TT_USAGE:
+            (*(pOpts->pUsageProc))( pOpts, EXIT_FAILURE );
+            /* NOTREACHED */
+            exit( EXIT_FAILURE );
+
+        case TT_VERSION:
+            pOD->pzLastArg = "c";
+            optionPrintVersion( pOpts, pOD );
+            /* NOTREACHED */
+
+        default:
+            exit( EXIT_FAILURE );
+        }
+
+    default:
+        close( pipeFd[1] );
+        fp = fdopen( pipeFd[0], "r" FOPEN_BINARY_FLAG );
+    }
+
+    for (;;) {
+        int  ch = fgetc( fp );
+        switch (ch) {
+
+        case '\n':
+            nlHoldCt++;
+            break;
+
+        case '\'':
+            while (nlHoldCt > 0) {
+                fputc( '\n', stdout );
+                nlHoldCt--;
+            }
+            fputs( "'\\''", stdout );
+            break;
+
+        case EOF:
+            goto endCharLoop;
+
+        default:
+            while (nlHoldCt > 0) {
+                fputc( '\n', stdout );
+                nlHoldCt--;
+            }
+            fputc( ch, stdout );
+            break;
+        }
+    } endCharLoop:;
+
+    fputs( "'\n\n", stdout );
+    close( pipeFd[0] );
+}
+
+
+static void
+emitUsage( tOptions* pOpts )
+{
+    char     zTimeBuf[ AO_NAME_SIZE ];
+
+    /*
+     *  First, switch stdout to the output file name.
+     *  Then, change the program name to the one defined
+     *  by the definitions (rather than the current
+     *  executable name).  Down case the upper cased name.
+     */
+    if (pzLeader != NULL)
+        fputs( pzLeader, stdout );
+
+    {
+        tSCC    zStdout[] = "stdout";
+        tCC*    pzOutName;
+
+        {
+            time_t    curTime = time( NULL );
+            struct tm*  pTime = localtime( &curTime );
+            strftime( zTimeBuf, AO_NAME_SIZE, "%A %B %e, %Y at %r %Z", pTime );
+        }
+
+        if (HAVE_OPT( SCRIPT ))
+             pzOutName = OPT_ARG( SCRIPT );
+        else pzOutName = zStdout;
+
+        if ((pzLeader == NULL) && (pzShell != NULL))
+            printf( "#! %s\n", pzShell );
+
+        printf( zPreamble, zStartMarker, pzOutName, zTimeBuf );
+    }
+
+    /*
+     *  Get a copy of the original program name in lower case
+     */
+    {
+        char* pzPN = zTimeBuf;
+        tCC*  pz   = pOpts->pzPROGNAME;
+        for (;;) {
+            if ((*pzPN++ = tolower( *pz++ )) == '\0')
+                break;
+        }
+    }
+
+    printf( zEndPreamble, pOpts->pzPROGNAME );
+
+    pOpts->pzProgPath = pOpts->pzProgName = zTimeBuf;
+    textToVariable( pOpts, TT_LONGUSAGE, NULL );
+    textToVariable( pOpts, TT_USAGE,     NULL );
+
+    {
+        tOptDesc* pOptDesc = pOpts->pOptDesc;
+        int       optionCt = pOpts->optCt;
+
+        for (;;) {
+            if (pOptDesc->pOptProc == optionPrintVersion) {
+                textToVariable( pOpts, TT_VERSION, pOptDesc );
+                break;
+            }
+
+            if (--optionCt <= 0)
+                break;
+            pOptDesc++;
+        }
+    }
+}
+
+
+static void
+emitSetup( tOptions* pOpts )
+{
+    tOptDesc* pOptDesc = pOpts->pOptDesc;
+    int       optionCt = pOpts->presetOptCt;
+    const char* pzFmt;
+    const char* pzDefault;
+
+    for (;optionCt > 0; pOptDesc++, --optionCt) {
+        char zVal[16];
+
+        /*
+         *  Options that are either usage documentation or are compiled out
+         *  are not to be processed.
+         */
+        if (SKIP_OPT(pOptDesc) || (pOptDesc->pz_NAME == NULL))
+            continue;
+
+        if (pOptDesc->optMaxCt > 1)
+             pzFmt = zMultiDef;
+        else pzFmt = zSingleDef;
+
+        /*
+         *  IF this is an enumeration/bitmask option, then convert the value
+         *  to a string before printing the default value.
+         */
+        switch (OPTST_GET_ARGTYPE(pOptDesc->fOptState)) {
+        case OPARG_TYPE_ENUMERATION:
+            (*(pOptDesc->pOptProc))( (tOptions*)2UL, pOptDesc );
+            pzDefault = pOptDesc->pzLastArg;
+            break;
+
+        /*
+         *  Numeric and membership bit options are just printed as a number.
+         */
+        case OPARG_TYPE_NUMERIC:
+        case OPARG_TYPE_MEMBERSHIP:
+            snprintf( zVal, sizeof( zVal ), "%ld", (tAoUL)pOptDesc->pzLastArg );
+            pzDefault = zVal;
+            break;
+
+        default:
+            if (pOptDesc->pzLastArg == NULL) {
+                if (pzFmt == zSingleDef)
+                    pzFmt = zSingleNoDef;
+                pzDefault = NULL;
+            }
+            else
+                pzDefault = pOptDesc->pzLastArg;
+        }
+
+        printf( pzFmt, pOpts->pzPROGNAME, pOptDesc->pz_NAME, pzDefault );
+    }
+}
+
+
+static void
+printOptionAction( tOptions* pOpts, tOptDesc* pOptDesc )
+{
+    if (pOptDesc->pOptProc == optionPrintVersion)
+        printf( zTextExit, pOpts->pzPROGNAME, "VERSION" );
+
+    else if (pOptDesc->pOptProc == optionPagedUsage)
+        printf( zPagedUsageExit, pOpts->pzPROGNAME );
+
+    else if (pOptDesc->pOptProc == optionLoadOpt) {
+        printf( zCmdFmt, "echo 'Warning:  Cannot load options files' >&2" );
+        printf( zCmdFmt, "OPT_ARG_NEEDED=YES" );
+
+    } else if (pOptDesc->pz_NAME == NULL) {
+
+        if (pOptDesc->pOptProc == NULL) {
+            printf( zCmdFmt, "echo 'Warning:  Cannot save options files' "
+                    ">&2" );
+            printf( zCmdFmt, "OPT_ARG_NEEDED=OK" );
+        } else
+            printf( zTextExit, pOpts->pzPROGNAME, "LONGUSAGE" );
+
+    } else {
+        if (pOptDesc->optMaxCt == 1)
+            printf( zSingleArg, pOpts->pzPROGNAME, pOptDesc->pz_NAME );
+        else {
+            if ((unsigned)pOptDesc->optMaxCt < NOLIMIT)
+                printf( zCountTest, pOpts->pzPROGNAME,
+                        pOptDesc->pz_NAME, pOptDesc->optMaxCt );
+
+            printf( zMultiArg, pOpts->pzPROGNAME, pOptDesc->pz_NAME );
+        }
+
+        /*
+         *  Fix up the args.
+         */
+        if (OPTST_GET_ARGTYPE(pOptDesc->fOptState) == OPARG_TYPE_NONE) {
+            printf( zCantArg, pOpts->pzPROGNAME, pOptDesc->pz_NAME );
+
+        } else if (pOptDesc->fOptState & OPTST_ARG_OPTIONAL) {
+            printf( zMayArg,  pOpts->pzPROGNAME, pOptDesc->pz_NAME );
+
+        } else {
+            fputs( zMustArg, stdout );
+        }
+    }
+    fputs( zOptionEndSelect, stdout );
+}
+
+
+static void
+printOptionInaction( tOptions* pOpts, tOptDesc* pOptDesc )
+{
+    if (pOptDesc->pOptProc == optionLoadOpt) {
+        printf( zCmdFmt, "echo 'Warning:  Cannot suppress the loading of "
+                "options files' >&2" );
+
+    } else if (pOptDesc->optMaxCt == 1)
+        printf( zNoSingleArg, pOpts->pzPROGNAME,
+                pOptDesc->pz_NAME, pOptDesc->pz_DisablePfx );
+    else
+        printf( zNoMultiArg, pOpts->pzPROGNAME,
+                pOptDesc->pz_NAME, pOptDesc->pz_DisablePfx );
+
+    printf( zCmdFmt, "OPT_ARG_NEEDED=NO" );
+    fputs( zOptionEndSelect, stdout );
+}
+
+
+static void
+emitFlag( tOptions* pOpts )
+{
+    tOptDesc* pOptDesc = pOpts->pOptDesc;
+    int       optionCt = pOpts->optCt;
+
+    fputs( zOptionCase, stdout );
+
+    for (;optionCt > 0; pOptDesc++, --optionCt) {
+
+        if (SKIP_OPT(pOptDesc))
+            continue;
+
+        if (isprint( pOptDesc->optValue )) {
+            printf( zOptionFlag, pOptDesc->optValue );
+            printOptionAction( pOpts, pOptDesc );
+        }
+    }
+    printf( zOptionUnknown, "flag", pOpts->pzPROGNAME );
+}
+
+
+/*
+ *  Emit the match text for a long option
+ */
+static void
+emitMatchExpr( tCC* pzMatchName, tOptDesc* pCurOpt, tOptions* pOpts )
+{
+    tOptDesc* pOD = pOpts->pOptDesc;
+    int       oCt = pOpts->optCt;
+    int       min = 1;
+    char      zName[ 256 ];
+    char*     pz  = zName;
+
+    for (;;) {
+        int matchCt = 0;
+
+        /*
+         *  Omit the current option, Documentation opts and compiled out opts.
+         */
+        if ((pOD == pCurOpt) || SKIP_OPT(pOD)){
+            if (--oCt <= 0)
+                break;
+            pOD++;
+            continue;
+        }
+
+        /*
+         *  Check each character of the name case insensitively.
+         *  They must not be the same.  They cannot be, because it would
+         *  not compile correctly if they were.
+         */
+        while (  toupper( pOD->pz_Name[matchCt] )
+              == toupper( pzMatchName[matchCt] ))
+            matchCt++;
+
+        if (matchCt > min)
+            min = matchCt;
+
+        /*
+         *  Check the disablement name, too.
+         */
+        if (pOD->pz_DisableName != NULL) {
+            matchCt = 0;
+            while (  toupper( pOD->pz_DisableName[matchCt] )
+                  == toupper( pzMatchName[matchCt] ))
+                matchCt++;
+            if (matchCt > min)
+                min = matchCt;
+        }
+        if (--oCt <= 0)
+            break;
+        pOD++;
+    }
+
+    /*
+     *  IF the 'min' is all or one short of the name length,
+     *  THEN the entire string must be matched.
+     */
+    if (  (pzMatchName[min  ] == NUL)
+       || (pzMatchName[min+1] == NUL) )
+        printf( zOptionFullName, pzMatchName );
+
+    else {
+        int matchCt = 0;
+        for (; matchCt <= min; matchCt++)
+            *pz++ = pzMatchName[matchCt];
+
+        for (;;) {
+            *pz = NUL;
+            printf( zOptionPartName, zName );
+            *pz++ = pzMatchName[matchCt++];
+            if (pzMatchName[matchCt] == NUL) {
+                *pz = NUL;
+                printf( zOptionFullName, zName );
+                break;
+            }
+        }
+    }
+}
+
+
+/*
+ *  Emit GNU-standard long option handling code
+ */
+static void
+emitLong( tOptions* pOpts )
+{
+    tOptDesc* pOD = pOpts->pOptDesc;
+    int       ct  = pOpts->optCt;
+
+    fputs( zOptionCase, stdout );
+
+    /*
+     *  do each option, ...
+     */
+    do  {
+        /*
+         *  Documentation & compiled-out options
+         */
+        if (SKIP_OPT(pOD))
+            continue;
+
+        emitMatchExpr( pOD->pz_Name, pOD, pOpts );
+        printOptionAction( pOpts, pOD );
+
+        /*
+         *  Now, do the same thing for the disablement version of the option.
+         */
+        if (pOD->pz_DisableName != NULL) {
+            emitMatchExpr( pOD->pz_DisableName, pOD, pOpts );
+            printOptionInaction( pOpts, pOD );
+        }
+    } while (pOD++, --ct > 0);
+
+    printf( zOptionUnknown, "option", pOpts->pzPROGNAME );
+}
+
+
+static void
+openOutput( const char* pzFile )
+{
+    FILE* fp;
+    char* pzData = NULL;
+    struct stat stbf;
+
+    do  {
+        char*  pzScan;
+        int    sizeLeft;
+
+        /*
+         *  IF we cannot stat the file,
+         *  THEN assume we are creating a new file.
+         *       Skip the loading of the old data.
+         */
+        if (stat( pzFile, &stbf ) != 0)
+            break;
+
+        /*
+         *  The file must be a regular file
+         */
+        if (! S_ISREG( stbf.st_mode )) {
+            fprintf( stderr, zNotFile, pzFile );
+            exit( EXIT_FAILURE );
+        }
+
+        pzData = (char*)malloc( stbf.st_size + 1 );
+        fp = fopen( pzFile, "r" FOPEN_BINARY_FLAG );
+
+        sizeLeft = stbf.st_size;
+        pzScan   = pzData;
+
+        /*
+         *  Read in all the data as fast as our OS will let us.
+         */
+        for (;;) {
+            int inct = fread( (void*)pzScan, 1, sizeLeft, fp );
+            if (inct == 0)
+                break;
+
+            pzScan   += inct;
+            sizeLeft -= inct;
+
+            if (sizeLeft == 0)
+                break;
+        }
+
+        /*
+         *  NUL-terminate the leader and look for the trailer
+         */
+        *pzScan = '\0';
+        fclose( fp );
+        pzScan  = strstr( pzData, zStartMarker );
+        if (pzScan == NULL) {
+            pzTrailer = pzData;
+            break;
+        }
+
+        *(pzScan++) = NUL;
+        pzScan  = strstr( pzScan, zTrailerMarker );
+        if (pzScan == NULL) {
+            pzTrailer = pzData;
+            break;
+        }
+
+        /*
+         *  Check to see if the data contains
+         *  our marker.  If it does, then we will skip over it
+         */
+        pzTrailer = pzScan + sizeof( zTrailerMarker ) - 1;
+        pzLeader  = pzData;
+    } while (AG_FALSE);
+
+    freopen( pzFile, "w" FOPEN_BINARY_FLAG, stdout );
+}
+
+
+/*=export_func genshelloptUsage
+ * private:
+ * what: The usage function for the genshellopt generated program
+ *
+ * arg:  + tOptions* + pOpts    + program options descriptor +
+ * arg:  + int       + exitCode + usage text type to produce +
+ *
+ * doc:
+ *  This function is used to create the usage strings for the option
+ *  processing shell script code.  Two child processes are spawned
+ *  each emitting the usage text in either the short (error exit)
+ *  style or the long style.  The generated program will capture this
+ *  and create shell script variables containing the two types of text.
+=*/
+void
+genshelloptUsage( tOptions*  pOpts, int exitCode )
+{
+    /*
+     *  IF not EXIT_SUCCESS,
+     *  THEN emit the short form of usage.
+     */
+    if (exitCode != EXIT_SUCCESS)
+        optionUsage( pOpts, exitCode );
+    fflush( stderr );
+    fflush( stdout );
+
+    option_usage_fp = stdout;
+
+    /*
+     *  First, print our usage
+     */
+    switch (fork()) {
+    case -1:
+        optionUsage( pOpts, EXIT_FAILURE );
+        /*NOTREACHED*/
+        _exit( EXIT_FAILURE );
+
+    case 0:
+        pagerState = PAGER_STATE_CHILD;
+        optionUsage( pOpts, EXIT_SUCCESS );
+        /*NOTREACHED*/
+        _exit( EXIT_FAILURE );
+
+    default:
+    {
+        int  stat;
+        wait( &stat );
+    }
+    }
+
+    /*
+     *  Generate the pzProgName, since optionProcess() normally
+     *  gets it from the command line
+     */
+    {
+        char* pz;
+        AGDUPSTR( pz, pShellParseOptions->pzPROGNAME, "program name" );
+        pShellParseOptions->pzProgName = pz;
+        while (*pz != NUL) {
+            *pz = tolower( *pz );
+            pz++;
+        }
+    }
+
+    /*
+     *  Separate the makeshell usage from the client usage
+     */
+    fprintf( option_usage_fp, zGenshell, pShellParseOptions->pzProgName );
+    fflush( option_usage_fp );
+
+    /*
+     *  Now, print the client usage.
+     */
+    switch (fork()) {
+    case 0:
+        pagerState = PAGER_STATE_CHILD;
+        /*FALLTHROUGH*/
+    case -1:
+        optionUsage( pShellParseOptions, EXIT_FAILURE );
+
+    default:
+    {
+        int  stat;
+        wait( &stat );
+    }
+    }
+
+    exit( EXIT_SUCCESS );
+}
+
+/*
+ * Local Variables:
+ * mode: C
+ * c-file-style: "stroustrup"
+ * tab-width: 4
+ * indent-tabs-mode: nil
+ * End:
+ * end of autoopts/makeshell.c */
diff --git a/libopts/nested.c b/libopts/nested.c
new file mode 100644 (file)
index 0000000..ef32f28
--- /dev/null
@@ -0,0 +1,705 @@
+
+/*
+ *  $Id: nested.c,v 4.4 2006/03/25 19:24:56 bkorb Exp $
+ *  Time-stamp:      "2005-07-27 10:10:28 bkorb"
+ *
+ *   Automated Options Nested Values module.
+ */
+
+/*
+ *  Automated Options copyright 1992-2006 Bruce Korb
+ *
+ *  Automated Options is free software.
+ *  You may redistribute it and/or modify it under the terms of the
+ *  GNU General Public License, as published by the Free Software
+ *  Foundation; either version 2, or (at your option) any later version.
+ *
+ *  Automated Options is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with Automated Options.  See the file "COPYING".  If not,
+ *  write to:  The Free Software Foundation, Inc.,
+ *             51 Franklin Street, Fifth Floor,
+ *             Boston, MA  02110-1301, USA.
+ *
+ * As a special exception, Bruce Korb gives permission for additional
+ * uses of the text contained in his release of AutoOpts.
+ *
+ * The exception is that, if you link the AutoOpts library with other
+ * files to produce an executable, this does not by itself cause the
+ * resulting executable to be covered by the GNU General Public License.
+ * Your use of that executable is in no way restricted on account of
+ * linking the AutoOpts library code into it.
+ *
+ * This exception does not however invalidate any other reasons why
+ * the executable file might be covered by the GNU General Public License.
+ *
+ * This exception applies only to the code released by Bruce Korb under
+ * the name AutoOpts.  If you copy code from other sources under the
+ * General Public License into a copy of AutoOpts, as the General Public
+ * License permits, the exception does not apply to the code that you add
+ * in this way.  To avoid misleading anyone as to the status of such
+ * modified files, you must delete this exception notice from them.
+ *
+ * If you write modifications of your own for AutoOpts, it is your choice
+ * whether to permit this exception to apply to your modifications.
+ * If you do not wish that, delete this exception notice.
+ */
+/* = = = START-STATIC-FORWARD = = = */
+/* static forward declarations maintained by :mkfwd */
+static void
+removeBackslashes( char* pzSrc );
+
+static const char*
+scanQuotedString( const char* pzTxt );
+
+static tOptionValue*
+addStringValue( void** pp, const char* pzName, size_t nameLen,
+                const char* pzValue, size_t dataLen );
+
+static tOptionValue*
+addBoolValue( void** pp, const char* pzName, size_t nameLen,
+                const char* pzValue, size_t dataLen );
+
+static tOptionValue*
+addNumberValue( void** pp, const char* pzName, size_t nameLen,
+                const char* pzValue, size_t dataLen );
+
+static tOptionValue*
+addNestedValue( void** pp, const char* pzName, size_t nameLen,
+                char* pzValue, size_t dataLen, tOptionLoadMode mode );
+
+static const char*
+scanNameEntry( const char* pzName, tOptionValue* pRes, tOptionLoadMode mode );
+
+static const char*
+scanXmlEntry( const char* pzName, tOptionValue* pRes, tOptionLoadMode mode );
+
+static void
+unloadNestedArglist( tArgList* pAL );
+
+static void
+sortNestedList( tArgList* pAL );
+/* = = = END-STATIC-FORWARD = = = */
+
+/*  removeBackslashes
+ *
+ *  This function assumes that all newline characters were preceeded by
+ *  backslashes that need removal.
+ */
+static void
+removeBackslashes( char* pzSrc )
+{
+    char* pzD = strchr(pzSrc, '\n');
+
+    if (pzD == NULL)
+        return;
+    *--pzD = '\n';
+
+    for (;;) {
+        char ch = ((*pzD++) = *(pzSrc++));
+        switch (ch) {
+        case '\n': *--pzD = ch; break;
+        case NUL:  return;
+        default:
+            ;
+        }
+    }
+}
+
+
+/*  scanQuotedString
+ *
+ *  Find the end of a quoted string, skipping escaped quote characters.
+ */
+static const char*
+scanQuotedString( const char* pzTxt )
+{
+    char q = *(pzTxt++); /* remember the type of quote */
+
+    for (;;) {
+        char ch = *(pzTxt++);
+        if (ch == NUL)
+            return pzTxt-1;
+
+        if (ch == q)
+            return pzTxt;
+
+        if (ch == '\\') {
+            ch = *(pzTxt++);
+            /*
+             *  IF the next character is NUL, drop the backslash, too.
+             */
+            if (ch == NUL)
+                return pzTxt - 2;
+
+            /*
+             *  IF the quote character or the escape character were escaped,
+             *  then skip both, as long as the string does not end.
+             */
+            if ((ch == q) || (ch == '\\')) {
+                if (*(pzTxt++) == NUL)
+                    return pzTxt-1;
+            }
+        }
+    }
+}
+
+
+/*  addStringValue
+ *
+ *  Associate a name with either a string or no value.
+ */
+static tOptionValue*
+addStringValue( void** pp, const char* pzName, size_t nameLen,
+                const char* pzValue, size_t dataLen )
+{
+    tOptionValue* pNV;
+    size_t sz = nameLen + dataLen + sizeof(*pNV);
+
+    pNV = AGALOC( sz, "option name/str value pair" );
+    if (pNV == NULL)
+        return NULL;
+
+    if (pzValue == NULL) {
+        pNV->valType = OPARG_TYPE_NONE;
+        pNV->pzName = pNV->v.strVal;
+
+    } else {
+        pNV->valType = OPARG_TYPE_STRING;
+        if (dataLen > 0)
+            memcpy( pNV->v.strVal, pzValue, dataLen );
+        pNV->v.strVal[dataLen] = NUL;
+        pNV->pzName = pNV->v.strVal + dataLen + 1;
+    }
+
+    memcpy( pNV->pzName, pzName, nameLen );
+    pNV->pzName[ nameLen ] = NUL;
+    addArgListEntry( pp, pNV );
+    return pNV;
+}
+
+
+/*  addBoolValue
+ *
+ *  Associate a name with either a string or no value.
+ */
+static tOptionValue*
+addBoolValue( void** pp, const char* pzName, size_t nameLen,
+                const char* pzValue, size_t dataLen )
+{
+    tOptionValue* pNV;
+    size_t sz = nameLen + sizeof(*pNV) + 1;
+
+    pNV = AGALOC( sz, "option name/bool value pair" );
+    if (pNV == NULL)
+        return NULL;
+    while (isspace( *pzValue ) && (dataLen > 0)) {
+        dataLen--; pzValue++;
+    }
+    if (dataLen == 0)
+        pNV->v.boolVal = 0;
+    else if (isdigit( *pzValue ))
+        pNV->v.boolVal = atoi( pzValue );
+    else switch (*pzValue) {
+    case 'f':
+    case 'F':
+    case 'n':
+    case 'N':
+        pNV->v.boolVal = 0; break;
+    default:
+        pNV->v.boolVal = 1;
+    }
+
+    pNV->valType = OPARG_TYPE_BOOLEAN;
+    pNV->pzName = (char*)(pNV + 1);
+    memcpy( pNV->pzName, pzName, nameLen );
+    pNV->pzName[ nameLen ] = NUL;
+    addArgListEntry( pp, pNV );
+    return pNV;
+}
+
+
+/*  addNumberValue
+ *
+ *  Associate a name with either a string or no value.
+ */
+static tOptionValue*
+addNumberValue( void** pp, const char* pzName, size_t nameLen,
+                const char* pzValue, size_t dataLen )
+{
+    tOptionValue* pNV;
+    size_t sz = nameLen + sizeof(*pNV) + 1;
+
+    pNV = AGALOC( sz, "option name/bool value pair" );
+    if (pNV == NULL)
+        return NULL;
+    while (isspace( *pzValue ) && (dataLen > 0)) {
+        dataLen--; pzValue++;
+    }
+    if (dataLen == 0)
+        pNV->v.boolVal = 0;
+    else
+        pNV->v.boolVal = atoi( pzValue );
+
+    pNV->valType = OPARG_TYPE_NUMERIC;
+    pNV->pzName = (char*)(pNV + 1);
+    memcpy( pNV->pzName, pzName, nameLen );
+    pNV->pzName[ nameLen ] = NUL;
+    addArgListEntry( pp, pNV );
+    return pNV;
+}
+
+
+/*  addNestedValue
+ *
+ *  Associate a name with either a string or no value.
+ */
+static tOptionValue*
+addNestedValue( void** pp, const char* pzName, size_t nameLen,
+                char* pzValue, size_t dataLen, tOptionLoadMode mode )
+{
+    tOptionValue* pNV;
+
+    if (dataLen == 0) {
+        size_t sz = nameLen + sizeof(*pNV) + 1;
+        pNV = AGALOC( sz, "empty nested value pair" );
+        if (pNV == NULL)
+            return NULL;
+        pNV->v.nestVal = NULL;
+        pNV->valType = OPARG_TYPE_HIERARCHY;
+        pNV->pzName = (char*)(pNV + 1);
+        memcpy( pNV->pzName, pzName, nameLen );
+        pNV->pzName[ nameLen ] = NUL;
+
+    } else {
+        pNV = optionLoadNested( pzValue, pzName, nameLen, mode );
+    }
+
+    if (pNV != NULL)
+        addArgListEntry( pp, pNV );
+
+    return pNV;
+}
+
+
+/*  scanNameEntry
+ *
+ *  We have an entry that starts with a name.  Find the end of it, cook it
+ *  (if called for) and create the name/value association.
+ */
+static const char*
+scanNameEntry( const char* pzName, tOptionValue* pRes, tOptionLoadMode mode )
+{
+    tOptionValue* pNV;
+    const char* pzScan = pzName+1;
+    const char* pzVal;
+    size_t nameLen = 1;
+    size_t dataLen = 0;
+
+    while (ISNAMECHAR( *pzScan ))  { pzScan++; nameLen++; }
+
+    while (isspace( *pzScan )) {
+        char ch = *(pzScan++);
+        if ((ch == '\n') || (ch == ',')) {
+            addStringValue( &(pRes->v.nestVal), pzName, nameLen, NULL, 0 );
+            return pzScan - 1;
+        }
+    }
+
+    switch (*pzScan) {
+    case '=':
+    case ':':
+        while (isspace( *++pzScan ))  ;
+        switch (*pzScan) {
+        case ',':  goto comma_char;
+        case '"':
+        case '\'': goto quote_char;
+        case NUL:  addStringValue( &(pRes->v.nestVal), pzName, nameLen, NULL, 0);
+                   goto leave_scan_name;
+        default:   goto default_char;
+        }
+
+    case ',':
+    comma_char:
+        pzScan++;
+        /* FALLTHROUGH */
+
+    case NUL:
+        addStringValue( &(pRes->v.nestVal), pzName, nameLen, NULL, 0 );
+        break;
+
+    case '"':
+    case '\'':
+    quote_char:
+        pzVal = pzScan;
+        pzScan = scanQuotedString( pzScan );
+        dataLen = pzScan - pzVal;
+        pNV = addStringValue( &(pRes->v.nestVal), pzName, nameLen,
+                              pzVal, dataLen );
+        if ((pNV != NULL) && (mode == OPTION_LOAD_COOKED))
+            ao_string_cook( pNV->v.strVal, NULL );
+        break;
+
+    default:
+    default_char:
+        /*
+         *  We have found some strange text value.  It ends with a newline
+         *  or a comma.
+         */
+        pzVal = pzScan;
+        for (;;) {
+            char ch = *(pzScan++);
+            switch (ch) {
+            case '\n':
+                if ((pzScan > pzVal + 2) && (pzScan[-2] == '\\'))
+                    continue;
+                /* FALLTHROUGH */
+
+            case ',':
+                dataLen = (pzScan - pzVal) - 1;
+                pNV = addStringValue( &(pRes->v.nestVal), pzName, nameLen,
+                                      pzVal, dataLen );
+                if (pNV != NULL)
+                    removeBackslashes( pNV->v.strVal );
+                goto leave_scan_name;
+            }
+        }
+        break;
+    } leave_scan_name:;
+
+    return pzScan;
+}
+
+
+/*  scanXmlEntry
+ *
+ *  We've found a '<' character.  We ignore this if it is a comment or a
+ *  directive.  If it is something else, then whatever it is we are looking
+ *  at is bogus.  Returning NULL stops processing.
+ */
+static const char*
+scanXmlEntry( const char* pzName, tOptionValue* pRes, tOptionLoadMode mode )
+{
+    size_t nameLen = 1, valLen = 0;
+    const char*   pzScan = ++pzName;
+    const char*   pzVal;
+    tOptionValue  valu;
+    tOptionValue* pNewVal;
+
+    if (! isalpha(*pzName)) {
+        switch (*pzName) {
+        default:
+            pzName = NULL;
+            break;
+
+        case '!':
+            pzName = strstr( pzName, "-->" );
+            if (pzName != NULL)
+                pzName += 3;
+            break;
+
+        case '?':
+            pzName = strchr( pzName, '>' );
+            if (pzName != NULL)
+                pzName++;
+            break;
+        }
+        return pzName;
+    }
+
+    while (isalpha( *++pzScan ))  nameLen++;
+    if (nameLen > 64)
+        return NULL;
+    valu.valType = OPARG_TYPE_STRING;
+
+    switch (*pzScan) {
+    case ' ':
+    case '\t':
+        pzScan = parseAttributes( NULL, (char*)pzScan, &mode, &valu );
+        if (*pzScan == '>') {
+            pzScan++;
+            break;
+        }
+
+        if (*pzScan != '/')
+            return NULL;
+        /* FALLTHROUGH */
+
+    case '/':
+        if (*++pzScan != '>')
+            return NULL;
+        addStringValue( &(pRes->v.nestVal), pzName, nameLen, NULL, 0 );
+        return pzScan+2;
+
+    default:  return NULL;
+    case '>': break;
+    }
+
+    pzVal = pzScan;
+
+    {
+        char z[68];
+        char* pzD = z;
+        int  ct = nameLen;
+        const char* pzS = pzName;
+
+        *(pzD++) = '<';
+        *(pzD++) = '/';
+
+        do  {
+            *(pzD++) = *(pzS++);
+        } while (--ct > 0);
+        *(pzD++) = '>';
+        *pzD = NUL;
+
+        pzScan = strstr( pzScan, z );
+        if (pzScan == NULL)
+            return NULL;
+        valLen = (pzScan - pzVal);
+        pzScan += nameLen + 3;
+        while (isspace( *pzScan ))  pzScan++;
+    }
+
+    switch (valu.valType) {
+    case OPARG_TYPE_NONE:
+        addStringValue( &(pRes->v.nestVal), pzName, nameLen, NULL, 0 );
+        break;
+
+    case OPARG_TYPE_STRING:
+        pNewVal =
+            addStringValue( &(pRes->v.nestVal), pzName, nameLen, pzVal, valLen );
+        if (mode == OPTION_LOAD_KEEP)
+            break;
+        mungeString( pNewVal->v.strVal, mode );
+        break;
+
+    case OPARG_TYPE_BOOLEAN:
+        addBoolValue(   &(pRes->v.nestVal), pzName, nameLen, pzVal, valLen );
+        break;
+
+    case OPARG_TYPE_NUMERIC:
+        addNumberValue( &(pRes->v.nestVal), pzName, nameLen, pzVal, valLen );
+        break;
+
+    case OPARG_TYPE_HIERARCHY:
+    {
+        char* pz = AGALOC( valLen+1, "hierarchical scan" );
+        if (pz == NULL)
+            break;
+        memcpy( pz, pzVal, valLen );
+        pz[valLen] = NUL;
+        addNestedValue( &(pRes->v.nestVal), pzName, nameLen, pz, valLen, mode );
+        free(pz);
+        break;
+    }
+
+    case OPARG_TYPE_ENUMERATION:
+    case OPARG_TYPE_MEMBERSHIP:
+    default:
+        break;
+    }
+
+    return pzScan;
+}
+
+
+static void
+unloadNestedArglist( tArgList* pAL )
+{
+    int ct = pAL->useCt;
+    tOptionValue** ppNV = (tOptionValue**)(pAL->apzArgs);
+
+    while (ct-- > 0) {
+        tOptionValue* pNV = *(ppNV++);
+        if (pNV->valType == OPARG_TYPE_HIERARCHY)
+            unloadNestedArglist( pNV->v.nestVal );
+        free( pNV );
+    }
+
+    free( (void*)pAL );
+}
+
+
+/*=export_func  optionUnloadNested
+ *
+ * what:  Deallocate the memory for a nested value
+ * arg:   + const tOptionValue* + pOptVal + the hierarchical value +
+ *
+ * doc:
+ *  A nested value needs to be deallocated.  The pointer passed in should
+ *  have been gotten from a call to @code{configFileLoad()} (See
+ *  @pxref{libopts-configFileLoad}).
+=*/
+void
+optionUnloadNested( const tOptionValue* pOV )
+{
+    if (pOV == NULL) return;
+    if (pOV->valType != OPARG_TYPE_HIERARCHY) {
+        errno = EINVAL;
+        return;
+    }
+
+    unloadNestedArglist( pOV->v.nestVal );
+
+    free( (void*)pOV );
+}
+
+
+/*  sortNestedList
+ *
+ *  This is a _stable_ sort.  The entries are sorted alphabetically,
+ *  but within entries of the same name the ordering is unchanged.
+ *  Typically, we also hope the input is sorted.
+ */
+static void
+sortNestedList( tArgList* pAL )
+{
+    int ix;
+    int lm = pAL->useCt;
+
+    /*
+     *  This loop iterates "useCt" - 1 times.
+     */
+    for (ix = 0; ++ix < lm;) {
+        int iy = ix-1;
+        tOptionValue* pNewNV = (tOptionValue*)pAL->apzArgs[ix];
+        tOptionValue* pOldNV = (tOptionValue*)pAL->apzArgs[iy];
+
+        /*
+         *  For as long as the new entry precedes the "old" entry,
+         *  move the old pointer.  Stop before trying to extract the
+         *  "-1" entry.
+         */
+        while (strcmp( pOldNV->pzName, pNewNV->pzName ) > 0) {
+            pAL->apzArgs[iy+1] = (void*)pOldNV;
+            pOldNV = (tOptionValue*)pAL->apzArgs[--iy];
+            if (iy < 0)
+                break;
+        }
+
+        /*
+         *  Always store the pointer.  Sometimes it is redundant,
+         *  but the redundancy is cheaper than a test and branch sequence.
+         */
+        pAL->apzArgs[iy+1] = (void*)pNewNV;
+    }
+}
+
+
+/*=export_func  optionLoadNested
+ * private:
+ *
+ * what:  parse a hierarchical option argument
+ * arg:   + const char*     + pzTxt   + the text to scan +
+ * arg:   + const char*     + pzName  + the name for the text +
+ * arg:   + size_t          + nameLen + the length of "name"  +
+ * arg:   + tOptionLoadMode + mode    + the value formation mode    +
+ *
+ * ret_type:  tOptionValue*
+ * ret_desc:  An allocated, compound value structure
+ *
+ * doc:
+ *  A block of text represents a series of values.  It may be an
+ *  entire configuration file, or it may be an argument to an
+ *  option that takes a hierarchical value.
+=*/
+tOptionValue*
+optionLoadNested( const char* pzTxt, const char* pzName, size_t nameLen,
+                  tOptionLoadMode mode )
+{
+    tOptionValue* pRes;
+    tArgList*     pAL;
+
+    /*
+     *  Make sure we have some data and we have space to put what we find.
+     */
+    if (pzTxt == NULL) {
+        errno = EINVAL;
+        return NULL;
+    }
+    while (isspace( *pzTxt ))  pzTxt++;
+    if (*pzTxt == NUL) {
+        errno = ENOENT;
+        return NULL;
+    }
+    pRes = AGALOC( sizeof(*pRes) + nameLen + 1, "nested args" );
+    if (pRes == NULL) {
+        errno = ENOMEM;
+        return NULL;
+    }
+    pRes->valType   = OPARG_TYPE_HIERARCHY;
+    pRes->pzName    = (char*)(pRes + 1);
+    memcpy( pRes->pzName, pzName, nameLen );
+    pRes->pzName[ nameLen ] = NUL;
+
+    pAL = AGALOC( sizeof(*pAL), "nested arg list" );
+    if (pAL == NULL) {
+        free( pRes );
+        return NULL;
+    }
+    pRes->v.nestVal = pAL;
+    pAL->useCt   = 0;
+    pAL->allocCt = MIN_ARG_ALLOC_CT;
+
+    /*
+     *  Scan until we hit a NUL.
+     */
+    do  {
+        while (isspace( *pzTxt ))  pzTxt++;
+        if (isalpha( *pzTxt )) {
+            pzTxt = scanNameEntry( pzTxt, pRes, mode );
+        }
+        else switch (*pzTxt) {
+        case NUL: goto scan_done;
+        case '<': pzTxt = scanXmlEntry( pzTxt, pRes, mode );
+                  if (*pzTxt == ',') pzTxt++; break;
+        case '#': pzTxt = strchr( pzTxt, '\n' );             break;
+        default:  goto woops;
+        }
+    } while (pzTxt != NULL); scan_done:;
+
+    pAL = pRes->v.nestVal;
+    if (pAL->useCt != 0) {
+        sortNestedList( pAL );
+        return pRes;
+    }
+
+ woops:
+    free( pRes->v.nestVal );
+    free( pRes );
+    return NULL;
+}
+
+
+/*=export_func  optionNestedVal
+ * private:
+ *
+ * what:  parse a hierarchical option argument
+ * arg:   + tOptions* + pOpts    + program options descriptor +
+ * arg:   + tOptDesc* + pOptDesc + the descriptor for this arg +
+ *
+ * doc:
+ *  Nested value was found on the command line
+=*/
+void
+optionNestedVal( tOptions* pOpts, tOptDesc* pOD )
+{
+    tOptionValue* pOV =
+        optionLoadNested(pOD->pzLastArg, pOD->pz_Name, strlen( pOD->pz_Name ),
+                         OPTION_LOAD_UNCOOKED);
+
+    if (pOV != NULL)
+        addArgListEntry( &(pOD->optCookie), (void*)pOV );
+}
+/*
+ * Local Variables:
+ * mode: C
+ * c-file-style: "stroustrup"
+ * tab-width: 4
+ * indent-tabs-mode: nil
+ * End:
+ * end of autoopts/nested.c */
diff --git a/libopts/numeric.c b/libopts/numeric.c
new file mode 100644 (file)
index 0000000..54be7c1
--- /dev/null
@@ -0,0 +1,89 @@
+
+/*
+ *  $Id: numeric.c,v 4.6 2006/03/25 19:24:56 bkorb Exp $
+ *  Time-stamp:      "2005-02-14 08:22:56 bkorb"
+ */
+
+/*
+ *  Automated Options copyright 1992-2006 Bruce Korb
+ *
+ *  Automated Options is free software.
+ *  You may redistribute it and/or modify it under the terms of the
+ *  GNU General Public License, as published by the Free Software
+ *  Foundation; either version 2, or (at your option) any later version.
+ *
+ *  Automated Options is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with Automated Options.  See the file "COPYING".  If not,
+ *  write to:  The Free Software Foundation, Inc.,
+ *             51 Franklin Street, Fifth Floor,
+ *             Boston, MA  02110-1301, USA.
+ *
+ * As a special exception, Bruce Korb gives permission for additional
+ * uses of the text contained in his release of AutoOpts.
+ *
+ * The exception is that, if you link the AutoOpts library with other
+ * files to produce an executable, this does not by itself cause the
+ * resulting executable to be covered by the GNU General Public License.
+ * Your use of that executable is in no way restricted on account of
+ * linking the AutoOpts library code into it.
+ *
+ * This exception does not however invalidate any other reasons why
+ * the executable file might be covered by the GNU General Public License.
+ *
+ * This exception applies only to the code released by Bruce Korb under
+ * the name AutoOpts.  If you copy code from other sources under the
+ * General Public License into a copy of AutoOpts, as the General Public
+ * License permits, the exception does not apply to the code that you add
+ * in this way.  To avoid misleading anyone as to the status of such
+ * modified files, you must delete this exception notice from them.
+ *
+ * If you write modifications of your own for AutoOpts, it is your choice
+ * whether to permit this exception to apply to your modifications.
+ * If you do not wish that, delete this exception notice.
+ */
+
+/*=export_func  optionNumericVal
+ * private:
+ *
+ * what:  Decipher a boolean value
+ * arg:   + tOptions* + pOpts    + program options descriptor +
+ * arg:   + tOptDesc* + pOptDesc + the descriptor for this arg +
+ *
+ * doc:
+ *  Decipher a numeric value.
+=*/
+void
+optionNumericVal( tOptions* pOpts, tOptDesc* pOD )
+{
+    char* pz;
+    long  val;
+
+    /*
+     *  Numeric options may have a range associated with it.
+     *  If it does, the usage procedure requests that it be
+     *  emitted by passing a NULL pOD pointer.
+     */
+    if ((pOD == NULL) || (pOD->pzLastArg == NULL))
+        return;
+
+    val = strtol( pOD->pzLastArg, &pz, 0 );
+    if (*pz != NUL) {
+        fprintf( stderr, zNotNumber, pOpts->pzProgName, pOD->pzLastArg );
+        (*(pOpts->pUsageProc))(pOpts, EXIT_FAILURE);
+    }
+
+    pOD->pzLastArg = (char*)val;
+}
+/*
+ * Local Variables:
+ * mode: C
+ * c-file-style: "stroustrup"
+ * tab-width: 4
+ * indent-tabs-mode: nil
+ * End:
+ * end of autoopts/numeric.c */
diff --git a/libopts/pgusage.c b/libopts/pgusage.c
new file mode 100644 (file)
index 0000000..9842a72
--- /dev/null
@@ -0,0 +1,154 @@
+
+/*
+ *  $Id: pgusage.c,v 4.7 2006/03/25 19:24:56 bkorb Exp $
+ * Time-stamp:      "2005-10-29 13:23:12 bkorb"
+ *
+ *   Automated Options Paged Usage module.
+ *
+ *  This routine will run run-on options through a pager so the
+ *  user may examine, print or edit them at their leisure.
+ */
+
+/*
+ *  Automated Options copyright 1992-2006 Bruce Korb
+ *
+ *  Automated Options is free software.
+ *  You may redistribute it and/or modify it under the terms of the
+ *  GNU General Public License, as published by the Free Software
+ *  Foundation; either version 2, or (at your option) any later version.
+ *
+ *  Automated Options is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with Automated Options.  See the file "COPYING".  If not,
+ *  write to:  The Free Software Foundation, Inc.,
+ *             51 Franklin Street, Fifth Floor,
+ *             Boston, MA  02110-1301, USA.
+ *
+ * As a special exception, Bruce Korb gives permission for additional
+ * uses of the text contained in his release of AutoOpts.
+ *
+ * The exception is that, if you link the AutoOpts library with other
+ * files to produce an executable, this does not by itself cause the
+ * resulting executable to be covered by the GNU General Public License.
+ * Your use of that executable is in no way restricted on account of
+ * linking the AutoOpts library code into it.
+ *
+ * This exception does not however invalidate any other reasons why
+ * the executable file might be covered by the GNU General Public License.
+ *
+ * This exception applies only to the code released by Bruce Korb under
+ * the name AutoOpts.  If you copy code from other sources under the
+ * General Public License into a copy of AutoOpts, as the General Public
+ * License permits, the exception does not apply to the code that you add
+ * in this way.  To avoid misleading anyone as to the status of such
+ * modified files, you must delete this exception notice from them.
+ *
+ * If you write modifications of your own for AutoOpts, it is your choice
+ * whether to permit this exception to apply to your modifications.
+ * If you do not wish that, delete this exception notice.
+ */
+
+tePagerState pagerState = PAGER_STATE_INITIAL;
+
+/*=export_func  optionPagedUsage
+ * private:
+ *
+ * what:  Decipher a boolean value
+ * arg:   + tOptions* + pOpts    + program options descriptor +
+ * arg:   + tOptDesc* + pOptDesc + the descriptor for this arg +
+ *
+ * doc:
+ *  Run the usage output through a pager.
+ *  This is very handy if it is very long.
+=*/
+void
+optionPagedUsage( tOptions* pOptions, tOptDesc* pOD )
+{
+    static pid_t     my_pid;
+    char zPageUsage[ 1024 ];
+
+    /*
+     *  IF we are being called after the usage proc is done
+     *     (and thus has called "exit(2)")
+     *  THEN invoke the pager to page through the usage file we created.
+     */
+    switch (pagerState) {
+    case PAGER_STATE_INITIAL:
+    {
+        my_pid  = getpid();
+#ifdef HAVE_SNPRINTF
+        snprintf(zPageUsage, sizeof(zPageUsage), "/tmp/use.%lu", (tAoUL)my_pid);
+#else
+        sprintf( zPageUsage, "/tmp/use.%lu", (tAoUL)my_pid );
+#endif
+        unlink( zPageUsage );
+
+        /*
+         *  Set usage output to this temporary file
+         */
+        option_usage_fp = fopen( zPageUsage, "w" FOPEN_BINARY_FLAG );
+        if (option_usage_fp == NULL)
+            _exit( EXIT_FAILURE );
+
+        pagerState = PAGER_STATE_READY;
+
+        /*
+         *  Set up so this routine gets called during the exit logic
+         */
+        atexit( (void(*)(void))optionPagedUsage );
+
+        /*
+         *  The usage procedure will now put the usage information into
+         *  the temporary file we created above.
+         */
+        (*pOptions->pUsageProc)( pOptions, EXIT_SUCCESS );
+
+        /*NOTREACHED*/
+        _exit( EXIT_FAILURE );
+    }
+
+    case PAGER_STATE_READY:
+    {
+        tSCC zPage[]  = "%1$s /tmp/use.%2$lu ; rm -f /tmp/use.%2$lu";
+        char* pzPager = getenv( "PAGER" );
+
+        /*
+         *  Use the "more(1)" program if "PAGER" has not been defined
+         */
+        if (pzPager == NULL)
+            pzPager = "more";
+
+        /*
+         *  Page the file and remove it when done.
+         */
+#ifdef HAVE_SNPRINTF
+        snprintf(zPageUsage, sizeof(zPageUsage), zPage, pzPager, (tAoUL)my_pid);
+#else
+        sprintf( zPageUsage, zPage, pzPager, (tAoUL)my_pid );
+#endif
+        fclose( stderr );
+        dup2( STDOUT_FILENO, STDERR_FILENO );
+
+        system( zPageUsage );
+    }
+
+    case PAGER_STATE_CHILD:
+        /*
+         *  This is a child process used in creating shell script usage.
+         */
+        break;
+    }
+}
+
+/*
+ * Local Variables:
+ * mode: C
+ * c-file-style: "stroustrup"
+ * tab-width: 4
+ * indent-tabs-mode: nil
+ * End:
+ * end of autoopts/pgusage.c */
diff --git a/libopts/proto.h b/libopts/proto.h
new file mode 100644 (file)
index 0000000..f150501
--- /dev/null
@@ -0,0 +1,88 @@
+/* -*- buffer-read-only: t -*- vi: set ro:
+ *
+ * Prototypes for autoopts
+ * Generated Sun Apr  9 11:50:00 PDT 2006
+ */
+#ifndef AUTOOPTS_PROTO_H_GUARD
+#define AUTOOPTS_PROTO_H_GUARD 1
+#ifndef LOCAL
+#  define LOCAL extern
+#  define REDEF_LOCAL 1
+#else
+#  undef  REDEF_LOCAL
+#endif
+/*
+ *  Extracted from autoopts.c
+ */
+LOCAL tSuccess
+handleOption( tOptions* pOpts, tOptState* pOptState );
+
+LOCAL tSuccess
+longOptionFind( tOptions* pOpts, char* pzOptName, tOptState* pOptState );
+
+LOCAL tSuccess
+shortOptionFind( tOptions* pOpts, tAoUC optValue, tOptState* pOptState );
+
+LOCAL tSuccess
+doImmediateOpts( tOptions* pOpts );
+
+LOCAL tSuccess
+doRegularOpts( tOptions* pOpts );
+
+/*
+ *  Extracted from configfile.c
+ */
+LOCAL void
+internalFileLoad( tOptions* pOpts );
+
+LOCAL char*
+parseAttributes(
+    tOptions*           pOpts,
+    char*               pzText,
+    tOptionLoadMode*    pMode,
+    tOptionValue*       pType );
+
+LOCAL tSuccess
+validateOptionsStruct( tOptions* pOpts, const char* pzProgram );
+
+/*
+ *  Extracted from environment.c
+ */
+LOCAL void
+doPrognameEnv( tOptions* pOpts, teEnvPresetType type );
+
+LOCAL void
+doEnvPresets( tOptions* pOpts, teEnvPresetType type );
+
+/*
+ *  Extracted from load.c
+ */
+LOCAL void
+mungeString( char* pzTxt, tOptionLoadMode mode );
+
+LOCAL void
+loadOptionLine(
+    tOptions*   pOpts,
+    tOptState*  pOS,
+    char*       pzLine,
+    tDirection  direction,
+    tOptionLoadMode   load_mode );
+
+/*
+ *  Extracted from sort.c
+ */
+LOCAL void
+optionSort( tOptions* pOpts );
+
+/*
+ *  Extracted from stack.c
+ */
+LOCAL void
+addArgListEntry( void** ppAL, void* entry );
+
+#ifdef REDEF_LOCAL
+#  undef LOCAL
+#  define LOCAL
+#endif
+
+#endif /* AUTOOPTS_PROTO_H_GUARD */
diff --git a/libopts/putshell.c b/libopts/putshell.c
new file mode 100644 (file)
index 0000000..feed57b
--- /dev/null
@@ -0,0 +1,333 @@
+
+/*
+ *  $Id: putshell.c,v 4.9 2006/03/25 19:24:56 bkorb Exp $
+ * Time-stamp:      "2005-12-13 10:28:47 bkorb"
+ *
+ *  This module will interpret the options set in the tOptions
+ *  structure and print them to standard out in a fashion that
+ *  will allow them to be interpreted by the Bourne or Korn shells.
+ */
+
+/*
+ *  Automated Options copyright 1992-2006 Bruce Korb
+ *
+ *  Automated Options is free software.
+ *  You may redistribute it and/or modify it under the terms of the
+ *  GNU General Public License, as published by the Free Software
+ *  Foundation; either version 2, or (at your option) any later version.
+ *
+ *  Automated Options is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with Automated Options.  See the file "COPYING".  If not,
+ *  write to:  The Free Software Foundation, Inc.,
+ *             51 Franklin Street, Fifth Floor,
+ *             Boston, MA  02110-1301, USA.
+ *
+ * As a special exception, Bruce Korb gives permission for additional
+ * uses of the text contained in his release of AutoOpts.
+ *
+ * The exception is that, if you link the AutoOpts library with other
+ * files to produce an executable, this does not by itself cause the
+ * resulting executable to be covered by the GNU General Public License.
+ * Your use of that executable is in no way restricted on account of
+ * linking the AutoOpts library code into it.
+ *
+ * This exception does not however invalidate any other reasons why
+ * the executable file might be covered by the GNU General Public License.
+ *
+ * This exception applies only to the code released by Bruce Korb under
+ * the name AutoOpts.  If you copy code from other sources under the
+ * General Public License into a copy of AutoOpts, as the General Public
+ * License permits, the exception does not apply to the code that you add
+ * in this way.  To avoid misleading anyone as to the status of such
+ * modified files, you must delete this exception notice from them.
+ *
+ * If you write modifications of your own for AutoOpts, it is your choice
+ * whether to permit this exception to apply to your modifications.
+ * If you do not wish that, delete this exception notice.
+ */
+
+/* = = = START-STATIC-FORWARD = = = */
+/* static forward declarations maintained by :mkfwd */
+static void
+putQuotedStr( tCC* pzStr );
+/* = = = END-STATIC-FORWARD = = = */
+
+/*
+ *  Make sure embedded single quotes come out okay.  The initial quote has
+ *  been emitted and the closing quote will be upon return.
+ */
+static void
+putQuotedStr( tCC* pzStr )
+{
+    /*
+     *  Handle empty strings to make the rest of the logic simpler.
+     */
+    if ((pzStr == NULL) || (*pzStr == NUL)) {
+        fputs( "''", stdout );
+        return;
+    }
+
+    /*
+     *  Emit any single quotes/apostrophes at the start of the string and
+     *  bail if that is all we need to do.
+     */
+    while (*pzStr == '\'') {
+        fputs( "\\'", stdout );
+        pzStr++;
+    }
+    if (*pzStr == NUL)
+        return;
+
+    /*
+     *  Start the single quote string
+     */
+    fputc( '\'', stdout );
+    for (;;) {
+        tCC* pz = strchr( pzStr, '\'' );
+        if (pz == NULL)
+            break;
+
+        /*
+         *  Emit the string up to the single quote (apostrophe) we just found.
+         */
+        fwrite( pzStr, (pz - pzStr), 1, stdout );
+        fputc( '\'', stdout );
+        pzStr = pz;
+
+        /*
+         *  Emit an escaped apostrophe for every one we find.
+         *  If that ends the string, do not re-open the single quotes.
+         */
+        while (*++pzStr == '\'')   fputs( "\\'", stdout );
+        if (*pzStr == NUL)
+            return;
+
+        fputc( '\'', stdout );
+    }
+
+    /*
+     *  If we broke out of the loop, we must still emit the remaining text
+     *  and then close the single quote string.
+     */
+    fputs( pzStr, stdout );
+    fputc( '\'', stdout );
+}
+
+
+/*=export_func  optionPutShell
+ * what:  write a portable shell script to parse options
+ * private:
+ * arg:   tOptions*, pOpts, the program options descriptor
+ * doc:   This routine will emit portable shell script text for parsing
+ *        the options described in the option definitions.
+=*/
+void
+optionPutShell( tOptions* pOpts )
+{
+    int  optIx = 0;
+    tSCC zOptCtFmt[]  = "OPTION_CT=%d\nexport OPTION_CT\n";
+    tSCC zOptNumFmt[] = "%1$s_%2$s=%3$d # 0x%3$X\nexport %1$s_%2$s\n";
+    tSCC zOptDisabl[] = "%1$s_%2$s=%3$s\nexport %1$s_%2$s\n";
+    tSCC zOptValFmt[] = "%s_%s=";
+    tSCC zOptEnd[]    = "\nexport %s_%s\n";
+    tSCC zFullOptFmt[]= "%1$s_%2$s='%3$s'\nexport %1$s_%2$s\n";
+    tSCC zEquivMode[] = "%1$s_%2$s_MODE='%3$s'\nexport %1$s_%2$s_MODE\n";
+
+    printf( zOptCtFmt, pOpts->curOptIdx-1 );
+
+    do  {
+        tOptDesc* pOD = pOpts->pOptDesc + optIx;
+
+        if (SKIP_OPT(pOD))
+            continue;
+
+        /*
+         *  Equivalence classes are hard to deal with.  Where the
+         *  option data wind up kind of squishes around.  For the purposes
+         *  of emitting shell state, they are not recommended, but we'll
+         *  do something.  I guess we'll emit the equivalenced-to option
+         *  at the point in time when the base option is found.
+         */
+        if (pOD->optEquivIndex != NO_EQUIVALENT)
+            continue; /* equivalence to a different option */
+
+        /*
+         *  Equivalenced to a different option.  Process the current option
+         *  as the equivalenced-to option.  Keep the persistent state bits,
+         *  but copy over the set-state bits.
+         */
+        if (pOD->optActualIndex != optIx) {
+            tOptDesc* p = pOpts->pOptDesc + pOD->optActualIndex;
+            p->pzLastArg = pOD->pzLastArg;
+            p->fOptState &= OPTST_PERSISTENT;
+            p->fOptState |= pOD->fOptState & ~OPTST_PERSISTENT;
+            printf( zEquivMode, pOpts->pzPROGNAME, pOD->pz_NAME, p->pz_NAME );
+            pOD = p;
+        }
+
+        /*
+         *  If the argument type is a set membership bitmask, then we always
+         *  emit the thing.  We do this because it will always have some sort
+         *  of bitmask value and we need to emit the bit values.
+         */
+        if (OPTST_GET_ARGTYPE(pOD->fOptState) == OPARG_TYPE_MEMBERSHIP) {
+            char* pz;
+            uintptr_t val = 1;
+            printf( zOptNumFmt, pOpts->pzPROGNAME, pOD->pz_NAME,
+                    (uintptr_t)(pOD->optCookie) );
+            pOD->optCookie = (void*)(uintptr_t)~0UL;
+            (*(pOD->pOptProc))( (tOptions*)2UL, pOD );
+
+            /*
+             *  We are building the typeset list.  The list returned starts with
+             *  'none + ' for use by option saving stuff.  We must ignore that.
+             */
+            pz = (char*)pOD->pzLastArg + 7;
+            while (*pz != NUL) {
+                printf( "typeset -x -i %s_", pOD->pz_NAME );
+                pz += strspn( pz, " +\t\n\f" );
+                for (;;) {
+                    char ch = *(pz++);
+                         if (islower( ch ))  fputc( toupper( ch ), stdout );
+                    else if (isalnum( ch ))  fputc( ch, stdout );
+                    else if (isspace( ch )
+                          || (ch == '+'))    goto name_done;
+                    else if (ch == NUL)      { pz--; goto name_done; }
+                    else fputc( '_', stdout );
+                } name_done:;
+                printf( "=%1$ld # 0x%1$lX\n", val );
+                val <<= 1;
+            }
+            free( (void*)(pOD->pzLastArg) );
+            continue;
+        }
+
+        /*
+         *  IF the option was either specified or it wakes up enabled,
+         *  then we will emit information.  Otherwise, skip it.
+         *  The idea is that if someone defines an option to initialize
+         *  enabled, we should tell our shell script that it is enabled.
+         */
+        if (UNUSED_OPT( pOD ) && DISABLED_OPT( pOD ))
+            continue;
+
+        /*
+         *  Handle stacked arguments
+         */
+        if (  (pOD->fOptState & OPTST_STACKED)
+           && (pOD->optCookie != NULL) )  {
+            tSCC zOptCookieCt[] = "%1$s_%2$s_CT=%3$d\nexport %1$s_%2$s_CT\n";
+
+            tArgList*    pAL = (tArgList*)pOD->optCookie;
+            tCC**        ppz = pAL->apzArgs;
+            int          ct  = pAL->useCt;
+
+            printf( zOptCookieCt, pOpts->pzPROGNAME, pOD->pz_NAME, ct );
+
+            while (--ct >= 0) {
+                tSCC zOptNumArg[] = "%s_%s_%d=";
+                tSCC zOptEnd[]    = "\nexport %s_%s_%d\n";
+
+                printf( zOptNumArg, pOpts->pzPROGNAME, pOD->pz_NAME,
+                        pAL->useCt - ct );
+                putQuotedStr( *(ppz++) );
+                printf( zOptEnd, pOpts->pzPROGNAME, pOD->pz_NAME,
+                        pAL->useCt - ct );
+            }
+        }
+
+        /*
+         *  If the argument has been disabled,
+         *  Then set its value to the disablement string
+         */
+        else if ((pOD->fOptState & OPTST_DISABLED) != 0)
+            printf( zOptDisabl, pOpts->pzPROGNAME, pOD->pz_NAME,
+                    (pOD->pz_DisablePfx != NULL)
+                    ? pOD->pz_DisablePfx : "false" );
+
+        /*
+         *  If the argument type is numeric, the last arg pointer
+         *  is really the VALUE of the string that was pointed to.
+         */
+        else if (OPTST_GET_ARGTYPE(pOD->fOptState) == OPARG_TYPE_NUMERIC)
+            printf( zOptNumFmt, pOpts->pzPROGNAME, pOD->pz_NAME,
+                    (uintptr_t)(pOD->pzLastArg) );
+
+        /*
+         *  If the argument type is an enumeration, then it is much
+         *  like a text value, except we call the callback function
+         *  to emit the value corresponding to the "pzLastArg" number.
+         */
+        else if (OPTST_GET_ARGTYPE(pOD->fOptState) == OPARG_TYPE_ENUMERATION) {
+            printf( zOptValFmt, pOpts->pzPROGNAME, pOD->pz_NAME );
+            fputc( '\'', stdout );
+            (*(pOD->pOptProc))( (tOptions*)1UL, pOD );
+            fputc( '\'', stdout );
+            printf( zOptEnd, pOpts->pzPROGNAME, pOD->pz_NAME );
+        }
+
+        /*
+         *  If the argument type is numeric, the last arg pointer
+         *  is really the VALUE of the string that was pointed to.
+         */
+        else if (OPTST_GET_ARGTYPE(pOD->fOptState) == OPARG_TYPE_BOOLEAN)
+            printf( zFullOptFmt, pOpts->pzPROGNAME, pOD->pz_NAME,
+                    ((uintptr_t)(pOD->pzLastArg) == 0) ? "false" : "true" );
+
+        /*
+         *  IF the option has an empty value,
+         *  THEN we set the argument to the occurrence count.
+         */
+        else if (  (pOD->pzLastArg == NULL)
+                || (pOD->pzLastArg[0] == NUL) )
+
+            printf( zOptNumFmt, pOpts->pzPROGNAME, pOD->pz_NAME,
+                    (int)pOD->optOccCt );
+
+        /*
+         *  This option has a text value
+         */
+        else {
+            printf( zOptValFmt, pOpts->pzPROGNAME, pOD->pz_NAME );
+            putQuotedStr( pOD->pzLastArg );
+            printf( zOptEnd, pOpts->pzPROGNAME, pOD->pz_NAME );
+        }
+    } while (++optIx < pOpts->presetOptCt );
+
+    if (  ((pOpts->fOptSet & OPTPROC_REORDER) != 0)
+       && (pOpts->curOptIdx < pOpts->origArgCt)) {
+        fputs( "set --", stdout );
+        for (optIx = pOpts->curOptIdx; optIx < pOpts->origArgCt; optIx++) {
+            char* pzArg = pOpts->origArgVect[ optIx ];
+            if (strchr( pzArg, '\'' ) == NULL)
+                printf( " '%s'", pzArg );
+            else {
+                fputs( " '", stdout );
+                for (;;) {
+                    char ch = *(pzArg++);
+                    switch (ch) {
+                    case '\'':  fputs( "'\\''", stdout ); break;
+                    case NUL:   goto arg_done;
+                    default:    fputc( ch, stdout ); break;
+                    }
+                } arg_done:;
+                fputc( '\'', stdout );
+            }
+        }
+        fputs( "\nOPTION_CT=0\n", stdout );
+    }
+}
+
+/*
+ * Local Variables:
+ * mode: C
+ * c-file-style: "stroustrup"
+ * tab-width: 4
+ * indent-tabs-mode: nil
+ * End:
+ * end of autoopts/putshell.c */
diff --git a/libopts/restore.c b/libopts/restore.c
new file mode 100644 (file)
index 0000000..959e0f9
--- /dev/null
@@ -0,0 +1,207 @@
+
+/*
+ *  restore.c  $Id: restore.c,v 4.6 2006/03/25 19:24:56 bkorb Exp $
+ * Time-stamp:      "2005-02-23 15:10:20 bkorb"
+ *
+ *  This module's routines will save the current option state to memory
+ *  and restore it.  If saved prior to the initial optionProcess call,
+ *  then the initial state will be restored.
+ */
+
+/*
+ *  Automated Options copyright 1992-2006 Bruce Korb
+ *
+ *  Automated Options is free software.
+ *  You may redistribute it and/or modify it under the terms of the
+ *  GNU General Public License, as published by the Free Software
+ *  Foundation; either version 2, or (at your option) any later version.
+ *
+ *  Automated Options is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with Automated Options.  See the file "COPYING".  If not,
+ *  write to:  The Free Software Foundation, Inc.,
+ *             51 Franklin Street, Fifth Floor,
+ *             Boston, MA  02110-1301, USA.
+ *
+ * As a special exception, Bruce Korb gives permission for additional
+ * uses of the text contained in his release of AutoOpts.
+ *
+ * The exception is that, if you link the AutoOpts library with other
+ * files to produce an executable, this does not by itself cause the
+ * resulting executable to be covered by the GNU General Public License.
+ * Your use of that executable is in no way restricted on account of
+ * linking the AutoOpts library code into it.
+ *
+ * This exception does not however invalidate any other reasons why
+ * the executable file might be covered by the GNU General Public License.
+ *
+ * This exception applies only to the code released by Bruce Korb under
+ * the name AutoOpts.  If you copy code from other sources under the
+ * General Public License into a copy of AutoOpts, as the General Public
+ * License permits, the exception does not apply to the code that you add
+ * in this way.  To avoid misleading anyone as to the status of such
+ * modified files, you must delete this exception notice from them.
+ *
+ * If you write modifications of your own for AutoOpts, it is your choice
+ * whether to permit this exception to apply to your modifications.
+ * If you do not wish that, delete this exception notice.
+ */
+
+/*=export_func optionSaveState
+ *
+ * what:  saves the option state to memory
+ * arg:   tOptions*, pOpts, program options descriptor
+ *
+ * doc:   This routine will allocate enough memory to save the current
+ *        option processing state.  If this routine has been called before,
+ *        that memory will be reused.  You may only save one copy of the
+ *        option state.  This routine may be called before optionProcess(3AO).
+ *        If you do call it before the first call to optionProcess, then
+ *        you may also change the contents of argc/argv after you call
+ *        optionRestore(3AO)
+ *
+ * err:   If it fails to allocate the memory,
+ *        it will print a message to stderr and exit.
+ *        Otherwise, it will always succeed.
+=*/
+void
+optionSaveState( tOptions* pOpts )
+{
+    if (pOpts->pSavedState == NULL) {
+        size_t sz = sizeof( *pOpts ) + (pOpts->optCt * sizeof( tOptDesc ));
+        pOpts->pSavedState = AGALOC( sz, "saved option state" );
+        if (pOpts->pSavedState == NULL) {
+            tCC* pzName = pOpts->pzProgName;
+            if (pzName == NULL) {
+                pzName = pOpts->pzPROGNAME;
+                if (pzName == NULL)
+                    pzName = zNil;
+            }
+            fprintf( stderr, zCantSave, pzName, sz );
+            exit( EXIT_FAILURE );
+        }
+    }
+
+    {
+        tOptions* p   = pOpts->pSavedState;
+        tOptDesc* pOD = pOpts->pOptDesc;
+        int       ct  = pOpts->optCt;
+
+        memcpy( p, pOpts, sizeof( *p ));
+        memcpy( p + 1, pOpts->pOptDesc, p->optCt * sizeof( tOptDesc ));
+
+        /*
+         *  Make sure that allocated stuff is only referenced in the
+         *  archived copy of the data.
+         */
+        for (; ct-- > 0; pOD++)  {
+            switch (OPTST_GET_ARGTYPE(pOD->fOptState)) {
+            case OPARG_TYPE_STRING:
+                if (pOD->fOptState & OPTST_STACKED) {
+                    tOptDesc* q = p->pOptDesc + (pOD - pOpts->pOptDesc);
+                    q->optCookie = NULL;
+                }
+                break;
+
+            case OPARG_TYPE_HIERARCHY:
+            {
+                tOptDesc* q = p->pOptDesc + (pOD - pOpts->pOptDesc);
+                q->optCookie = NULL;
+            }
+            }
+        }
+    }
+}
+
+
+/*=export_func optionRestore
+ *
+ * what:  restore option state from memory copy
+ * arg:   tOptions*, pOpts, program options descriptor
+ *
+ * doc:  Copy back the option state from saved memory.
+ *       The allocated memory is left intact, so this routine can be
+ *       called repeatedly without having to call optionSaveState again.
+ *       If you are restoring a state that was saved before the first call
+ *       to optionProcess(3AO), then you may change the contents of the
+ *       argc/argv parameters to optionProcess.
+ *
+ * err:  If you have not called @code{optionSaveState} before, a diagnostic is
+ *       printed to @code{stderr} and exit is called.
+=*/
+void
+optionRestore( tOptions* pOpts )
+{
+    tOptions* p = (tOptions*)pOpts->pSavedState;
+
+    if (p == NULL) {
+        tCC* pzName = pOpts->pzProgName;
+        if (pzName == NULL) {
+            pzName = pOpts->pzPROGNAME;
+            if (pzName == NULL)
+                pzName = zNil;
+        }
+        fprintf( stderr, zNoState, pzName );
+        exit( EXIT_FAILURE );
+    }
+    memcpy( pOpts, p, sizeof( *p ));
+    memcpy( pOpts->pOptDesc, p+1, p->optCt * sizeof( tOptDesc ));
+}
+
+/* = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = */
+
+/*=export_func optionFree
+ *
+ * what:  free allocated option processing memory
+ * arg:   tOptions*, pOpts, program options descriptor
+ *
+ * doc:   AutoOpts sometimes allocates memory and puts pointers to it in the
+ *        option state structures.  This routine deallocates all such memory.
+ *
+ * err:   As long as memory has not been corrupted,
+ *        this routine is always successful.
+=*/
+void
+optionFree( tOptions* pOpts )
+{
+    if (pOpts->pSavedState != NULL) {
+        AGFREE( pOpts->pSavedState );
+        pOpts->pSavedState = NULL;
+    }
+    {
+        tOptDesc* p = pOpts->pOptDesc;
+        int ct = pOpts->optCt;
+        do  {
+            switch (OPTST_GET_ARGTYPE(p->fOptState)) {
+            case OPARG_TYPE_STRING:
+                if (  (p->fOptState & OPTST_STACKED)
+                   && (p->optCookie != NULL)) {
+                    AGFREE( p->optCookie );
+                    p->fOptState &= OPTST_PERSISTENT;
+                    if ((p->fOptState & OPTST_INITENABLED) == 0)
+                        p->fOptState |= OPTST_DISABLED;
+                }
+                break;
+
+            case OPARG_TYPE_HIERARCHY:
+                if (p->optCookie != NULL)
+                    optionUnloadNested(p->optCookie);
+                break;
+            }
+
+            p->optCookie = NULL;
+        } while (p++, --ct > 0);
+    }
+}
+/*
+ * Local Variables:
+ * mode: C
+ * c-file-style: "stroustrup"
+ * tab-width: 4
+ * indent-tabs-mode: nil
+ * End:
+ * end of autoopts/restore.c */
diff --git a/libopts/save.c b/libopts/save.c
new file mode 100644 (file)
index 0000000..51fa212
--- /dev/null
@@ -0,0 +1,499 @@
+
+/*
+ *  save.c  $Id: save.c,v 4.12 2006/03/25 19:24:56 bkorb Exp $
+ * Time-stamp:      "2005-02-20 13:49:46 bkorb"
+ *
+ *  This module's routines will take the currently set options and
+ *  store them into an ".rc" file for re-interpretation the next
+ *  time the invoking program is run.
+ */
+
+/*
+ *  Automated Options copyright 1992-2006 Bruce Korb
+ *
+ *  Automated Options is free software.
+ *  You may redistribute it and/or modify it under the terms of the
+ *  GNU General Public License, as published by the Free Software
+ *  Foundation; either version 2, or (at your option) any later version.
+ *
+ *  Automated Options is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with Automated Options.  See the file "COPYING".  If not,
+ *  write to:  The Free Software Foundation, Inc.,
+ *             51 Franklin Street, Fifth Floor,
+ *             Boston, MA  02110-1301, USA.
+ *
+ * As a special exception, Bruce Korb gives permission for additional
+ * uses of the text contained in his release of AutoOpts.
+ *
+ * The exception is that, if you link the AutoOpts library with other
+ * files to produce an executable, this does not by itself cause the
+ * resulting executable to be covered by the GNU General Public License.
+ * Your use of that executable is in no way restricted on account of
+ * linking the AutoOpts library code into it.
+ *
+ * This exception does not however invalidate any other reasons why
+ * the executable file might be covered by the GNU General Public License.
+ *
+ * This exception applies only to the code released by Bruce Korb under
+ * the name AutoOpts.  If you copy code from other sources under the
+ * General Public License into a copy of AutoOpts, as the General Public
+ * License permits, the exception does not apply to the code that you add
+ * in this way.  To avoid misleading anyone as to the status of such
+ * modified files, you must delete this exception notice from them.
+ *
+ * If you write modifications of your own for AutoOpts, it is your choice
+ * whether to permit this exception to apply to your modifications.
+ * If you do not wish that, delete this exception notice.
+ */
+
+tSCC  zWarn[] = "%s WARNING:  cannot save options - ";
+
+/* = = = START-STATIC-FORWARD = = = */
+/* static forward declarations maintained by :mkfwd */
+static tCC*
+findDirName( tOptions* pOpts, int* p_free );
+
+static tCC*
+findFileName( tOptions* pOpts, int* p_free_name );
+
+static void
+printEntry(
+    FILE*      fp,
+    tOptDesc*  p,
+    tCC*       pzLA );
+/* = = = END-STATIC-FORWARD = = = */
+
+static tCC*
+findDirName( tOptions* pOpts, int* p_free )
+{
+    tCC*  pzDir;
+
+    if (pOpts->specOptIdx.save_opts == 0)
+        return NULL;
+
+    pzDir = pOpts->pOptDesc[ pOpts->specOptIdx.save_opts ].pzLastArg;
+    if ((pzDir != NULL) && (*pzDir != NUL))
+        return pzDir;
+
+    /*
+     *  This function only works if there is a directory where
+     *  we can stash the RC (INI) file.
+     */
+    {
+        tCC* const* papz = pOpts->papzHomeList;
+        if (papz == NULL)
+            return NULL;
+
+        while (papz[1] != NULL) papz++;
+        pzDir = *papz;
+    }
+
+    /*
+     *  IF it does not require deciphering an env value, then just copy it
+     */
+    if (*pzDir != '$')
+        return pzDir;
+
+    {
+        tCC*  pzEndDir = strchr( ++pzDir, '/' );
+        char* pzFileName;
+        char* pzEnv;
+
+        if (pzEndDir != NULL) {
+            char z[ AO_NAME_SIZE ];
+            if ((pzEndDir - pzDir) > AO_NAME_LIMIT )
+                return NULL;
+            strncpy( z, pzDir, (pzEndDir - pzDir) );
+            z[ (pzEndDir - pzDir) ] = NUL;
+            pzEnv = getenv( z );
+        } else {
+
+            /*
+             *  Make sure we can get the env value (after stripping off
+             *  any trailing directory or file names)
+             */
+            pzEnv = getenv( pzDir );
+        }
+
+        if (pzEnv == NULL) {
+            fprintf( stderr, zWarn, pOpts->pzProgName );
+            fprintf( stderr, zNotDef, pzDir );
+            return NULL;
+        }
+
+        if (pzEndDir == NULL)
+            return pzEnv;
+
+        {
+            size_t sz = strlen( pzEnv ) + strlen( pzEndDir ) + 2;
+            pzFileName = (char*)AGALOC( sz, "dir name" );
+        }
+
+        if (pzFileName == NULL)
+            return NULL;
+
+        *p_free = 1;
+        /*
+         *  Glue together the full name into the allocated memory.
+         *  FIXME: We lose track of this memory.
+         */
+        sprintf( pzFileName, "%s/%s", pzEnv, pzEndDir );
+        return pzFileName;
+    }
+}
+
+
+static tCC*
+findFileName( tOptions* pOpts, int* p_free_name )
+{
+    tCC*   pzDir;
+    struct stat stBuf;
+    int    free_dir_name = 0;
+
+    pzDir = findDirName( pOpts, &free_dir_name );
+    if (pzDir == NULL)
+        return NULL;
+
+    /*
+     *  See if we can find the specified directory.  We use a once-only loop
+     *  structure so we can bail out early.
+     */
+    if (stat( pzDir, &stBuf ) != 0) do {
+
+        /*
+         *  IF we could not, check to see if we got a full
+         *  path to a file name that has not been created yet.
+         */
+        if (errno == ENOENT) {
+            char z[MAXPATHLEN];
+
+            /*
+             *  Strip off the last component, stat the remaining string and
+             *  that string must name a directory
+             */
+            char* pzDirCh = strrchr( pzDir, '/' );
+            if (pzDirCh == NULL) {
+                stBuf.st_mode = S_IFREG;
+                continue;  /* bail out of error condition */
+            }
+
+            strncpy( z, pzDir, pzDirCh - pzDir );
+            z[ pzDirCh - pzDir ] = NUL;
+
+            if (  (stat( z, &stBuf ) == 0)
+               && S_ISDIR( stBuf.st_mode )) {
+
+                /*
+                 *  We found the directory.  Restore the file name and
+                 *  mark the full name as a regular file
+                 */
+                stBuf.st_mode = S_IFREG;
+                continue;  /* bail out of error condition */
+            }
+        }
+
+        /*
+         *  We got a bogus name.
+         */
+        fprintf( stderr, zWarn, pOpts->pzProgName );
+        fprintf( stderr, zNoStat, errno, strerror( errno ), pzDir );
+        if (free_dir_name)
+            AGFREE( (void*)pzDir );
+        return NULL;
+    } while (0);
+
+    /*
+     *  IF what we found was a directory,
+     *  THEN tack on the config file name
+     */
+    if (S_ISDIR( stBuf.st_mode )) {
+        size_t sz = strlen( pzDir ) + strlen( pOpts->pzRcName ) + 2;
+
+        {
+            char*  pzPath = (char*)AGALOC( sz, "file name" );
+#ifdef HAVE_SNPRINTF
+            snprintf( pzPath, sz, "%s/%s", pzDir, pOpts->pzRcName );
+#else
+            sprintf( pzPath, "%s/%s", pzDir, pOpts->pzRcName );
+#endif
+            if (free_dir_name)
+                AGFREE( (void*)pzDir );
+            pzDir = pzPath;
+            free_dir_name = 1;
+        }
+
+        /*
+         *  IF we cannot stat the object for any reason other than
+         *     it does not exist, then we bail out
+         */
+        if (stat( pzDir, &stBuf ) != 0) {
+            if (errno != ENOENT) {
+                fprintf( stderr, zWarn, pOpts->pzProgName );
+                fprintf( stderr, zNoStat, errno, strerror( errno ),
+                         pzDir );
+                AGFREE( (void*)pzDir );
+                return NULL;
+            }
+
+            /*
+             *  It does not exist yet, but it will be a regular file
+             */
+            stBuf.st_mode = S_IFREG;
+        }
+    }
+
+    /*
+     *  Make sure that whatever we ultimately found, that it either is
+     *  or will soon be a file.
+     */
+    if (! S_ISREG( stBuf.st_mode )) {
+        fprintf( stderr, zWarn, pOpts->pzProgName );
+        fprintf( stderr, zNotFile, pzDir );
+        if (free_dir_name)
+            AGFREE( (void*)pzDir );
+        return NULL;
+    }
+
+    /*
+     *  Get rid of the old file
+     */
+    unlink( pzDir );
+    *p_free_name = free_dir_name;
+    return pzDir;
+}
+
+
+static void
+printEntry(
+    FILE*      fp,
+    tOptDesc*  p,
+    tCC*       pzLA )
+{
+    /*
+     *  There is an argument.  Pad the name so values line up
+     */
+    fprintf( fp, "%-18s",
+             (DISABLED_OPT( p )) ? p->pz_DisableName : p->pz_Name );
+
+    /*
+     *  IF the option is numeric only,
+     *  THEN the char pointer is really the number
+     */
+    if (OPTST_GET_ARGTYPE(p->fOptState) == OPARG_TYPE_NUMERIC)
+        fprintf( fp, "  %d\n", (t_word)pzLA );
+
+    /*
+     *  OTHERWISE, FOR each line of the value text, ...
+     */
+    else if (pzLA == NULL)
+        fputc( '\n', fp );
+
+    else {
+        fputc( ' ', fp ); fputc( ' ', fp );
+        for (;;) {
+            tCC* pzNl = strchr( pzLA, '\n' );
+
+            /*
+             *  IF this is the last line
+             *  THEN bail and print it
+             */
+            if (pzNl == NULL)
+                break;
+
+            /*
+             *  Print the continuation and the text from the current line
+             */
+            fwrite( pzLA, pzNl - pzLA, 1, fp );
+            pzLA = pzNl+1; /* advance the Last Arg pointer */
+            fputs( "\\\n", fp );
+        }
+
+        /*
+         *  Terminate the entry
+         */
+        fputs( pzLA, fp );
+        fputc( '\n', fp );
+    }
+}
+
+
+/*=export_func  optionSaveFile
+ *
+ * what:  saves the option state to a file
+ *
+ * arg:   tOptions*,   pOpts,  program options descriptor
+ *
+ * doc:
+ *
+ * This routine will save the state of option processing to a file.  The name
+ * of that file can be specified with the argument to the @code{--save-opts}
+ * option, or by appending the @code{rcfile} attribute to the last
+ * @code{homerc} attribute.  If no @code{rcfile} attribute was specified, it
+ * will default to @code{.@i{programname}rc}.  If you wish to specify another
+ * file, you should invoke the @code{SET_OPT_SAVE_OPTS( @i{filename} )} macro.
+ *
+ * err:
+ *
+ * If no @code{homerc} file was specified, this routine will silently return
+ * and do nothing.  If the output file cannot be created or updated, a message
+ * will be printed to @code{stderr} and the routine will return.
+=*/
+void
+optionSaveFile( tOptions* pOpts )
+{
+    tOptDesc* pOD;
+    int       ct;
+    FILE*     fp;
+
+    {
+        int   free_name = 0;
+        tCC*  pzFName = findFileName( pOpts, &free_name );
+        if (pzFName == NULL)
+            return;
+
+        fp = fopen( pzFName, "w" FOPEN_BINARY_FLAG );
+        if (fp == NULL) {
+            fprintf( stderr, zWarn, pOpts->pzProgName );
+            fprintf( stderr, zNoCreat, errno, strerror( errno ), pzFName );
+            if (free_name)
+                AGFREE((void*) pzFName );
+            return;
+        }
+
+        if (free_name)
+            AGFREE( (void*)pzFName );
+    }
+
+    {
+        const char*  pz = pOpts->pzUsageTitle;
+        fputs( "#  ", fp );
+        do { fputc( *pz, fp ); } while (*(pz++) != '\n');
+    }
+
+    {
+        time_t  timeVal = time( NULL );
+        char*   pzTime  = ctime( &timeVal );
+
+        fprintf( fp, zPresetFile, pzTime );
+#ifdef HAVE_ALLOCATED_CTIME
+        /*
+         *  The return values for ctime(), localtime(), and gmtime()
+         *  normally point to static data that is overwritten by each call.
+         *  The test to detect allocated ctime, so we leak the memory.
+         */
+        AGFREE( (void*)pzTime );
+#endif
+    }
+
+    /*
+     *  FOR each of the defined options, ...
+     */
+    ct  = pOpts->presetOptCt;
+    pOD = pOpts->pOptDesc;
+    do  {
+        int arg_state;
+        tOptDesc*  p;
+
+        /*
+         *  IF    the option has not been defined
+         *     OR it does not take an initialization value
+         *     OR it is equivalenced to another option
+         *  THEN continue (ignore it)
+         */
+        if (UNUSED_OPT( pOD ))
+            continue;
+
+        if ((pOD->fOptState & (OPTST_NO_INIT|OPTST_DOCUMENT|OPTST_OMITTED))
+            != 0)
+            continue;
+
+        if (  (pOD->optEquivIndex != NO_EQUIVALENT)
+              && (pOD->optEquivIndex != pOD->optIndex))
+            continue;
+
+        /*
+         *  Set a temporary pointer to the real option description
+         *  (i.e. account for equivalencing)
+         */
+        p = ((pOD->fOptState & OPTST_EQUIVALENCE) != 0)
+            ? (pOpts->pOptDesc + pOD->optActualIndex) : pOD;
+
+        /*
+         *  IF    no arguments are allowed
+         *  THEN just print the name and continue
+         */
+        if (OPTST_GET_ARGTYPE(pOD->fOptState) == OPARG_TYPE_NONE) {
+            fprintf( fp, "%s\n",
+                     (DISABLED_OPT( p )) ? p->pz_DisableName : p->pz_Name );
+            continue;
+        }
+
+        arg_state = OPTST_GET_ARGTYPE(p->fOptState);
+        switch (arg_state) {
+        case 0:
+        case OPARG_TYPE_NUMERIC:
+            printEntry( fp, p, p->pzLastArg );
+            break;
+
+        case OPARG_TYPE_STRING:
+            if (p->fOptState & OPTST_STACKED) {
+                tArgList*  pAL = (tArgList*)p->optCookie;
+                int        uct = pAL->useCt;
+                tCC**      ppz = pAL->apzArgs;
+
+                /*
+                 *  Disallow multiple copies of disabled options.
+                 */
+                if (uct > 1)
+                    p->fOptState &= ~OPTST_DISABLED;
+
+                while (uct-- > 0)
+                    printEntry( fp, p, *(ppz++) );
+            } else {
+                printEntry( fp, p, p->pzLastArg );
+            }
+            break;
+
+        case OPARG_TYPE_ENUMERATION:
+        case OPARG_TYPE_MEMBERSHIP:
+        {
+            tCC* val = p->pzLastArg;
+            /*
+             *  This is a magic incantation that will convert the
+             *  bit flag values back into a string suitable for printing.
+             */
+            (*(p->pOptProc))( (tOptions*)2UL, p );
+            printEntry( fp, p, p->pzLastArg );
+            if ((p->pzLastArg != NULL) && (arg_state != OPARG_TYPE_ENUMERATION))
+                /*
+                 *  bit flag and enumeration strings get allocated
+                 */
+                AGFREE( (void*)p->pzLastArg );
+            p->pzLastArg = val;
+            break;
+        }
+
+        case OPARG_TYPE_BOOLEAN:
+            printEntry( fp, p, (p->pzLastArg != 0) ? "true" : "false" );
+            break;
+
+        default:
+            break; /* cannot handle - skip it */
+        }
+    } while ( (pOD++), (--ct > 0));
+
+    fclose( fp );
+}
+/*
+ * Local Variables:
+ * mode: C
+ * c-file-style: "stroustrup"
+ * tab-width: 4
+ * indent-tabs-mode: nil
+ * End:
+ * end of autoopts/save.c */
diff --git a/libopts/sort.c b/libopts/sort.c
new file mode 100644 (file)
index 0000000..e7f29ed
--- /dev/null
@@ -0,0 +1,369 @@
+
+/*
+ *  sort.c  $Id: sort.c,v 4.7 2006/03/25 19:24:56 bkorb Exp $
+ * Time-stamp:      "2005-02-20 17:18:41 bkorb"
+ *
+ *  This module implements argument sorting.
+ */
+
+/*
+ *  Automated Options copyright 1992-2006 Bruce Korb
+ *
+ *  Automated Options is free software.
+ *  You may redistribute it and/or modify it under the terms of the
+ *  GNU General Public License, as published by the Free Software
+ *  Foundation; either version 2, or (at your option) any later version.
+ *
+ *  Automated Options is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with Automated Options.  See the file "COPYING".  If not,
+ *  write to:  The Free Software Foundation, Inc.,
+ *             51 Franklin Street, Fifth Floor,
+ *             Boston, MA  02110-1301, USA.
+ *
+ * As a special exception, Bruce Korb gives permission for additional
+ * uses of the text contained in his release of AutoOpts.
+ *
+ * The exception is that, if you link the AutoOpts library with other
+ * files to produce an executable, this does not by itself cause the
+ * resulting executable to be covered by the GNU General Public License.
+ * Your use of that executable is in no way restricted on account of
+ * linking the AutoOpts library code into it.
+ *
+ * This exception does not however invalidate any other reasons why
+ * the executable file might be covered by the GNU General Public License.
+ *
+ * This exception applies only to the code released by Bruce Korb under
+ * the name AutoOpts.  If you copy code from other sources under the
+ * General Public License into a copy of AutoOpts, as the General Public
+ * License permits, the exception does not apply to the code that you add
+ * in this way.  To avoid misleading anyone as to the status of such
+ * modified files, you must delete this exception notice from them.
+ *
+ * If you write modifications of your own for AutoOpts, it is your choice
+ * whether to permit this exception to apply to your modifications.
+ * If you do not wish that, delete this exception notice.
+ */
+
+/* = = = START-STATIC-FORWARD = = = */
+/* static forward declarations maintained by :mkfwd */
+static tSuccess
+mustHandleArg( tOptions* pOpts, char* pzArg, tOptState* pOS,
+               char** ppzOpts, int* pOptsIdx );
+
+static tSuccess
+mayHandleArg( tOptions* pOpts, char* pzArg, tOptState* pOS,
+              char** ppzOpts, int* pOptsIdx );
+
+static tSuccess
+checkShortOpts( tOptions* pOpts, char* pzArg, tOptState* pOS,
+                char** ppzOpts, int* pOptsIdx );
+/* = = = END-STATIC-FORWARD = = = */
+
+/*
+ *  "mustHandleArg" and "mayHandleArg" are really similar.  The biggest
+ *  difference is that "may" will consume the next argument only if it
+ *  does not start with a hyphen and "must" will consume it, hyphen or not.
+ */
+static tSuccess
+mustHandleArg( tOptions* pOpts, char* pzArg, tOptState* pOS,
+               char** ppzOpts, int* pOptsIdx )
+{
+    /*
+     *  An option argument is required.  Long options can either have
+     *  a separate command line argument, or an argument attached by
+     *  the '=' character.  Figure out which.
+     */
+    switch (pOS->optType) {
+    case TOPT_SHORT:
+        /*
+         *  See if an arg string follows the flag character.  If not,
+         *  the next arg must be the option argument.
+         */
+        if (*pzArg != NUL)
+            return SUCCESS;
+        break;
+
+    case TOPT_LONG:
+        /*
+         *  See if an arg string has already been assigned (glued on
+         *  with an `=' character).  If not, the next is the opt arg.
+         */
+        if (pOS->pzOptArg != NULL)
+            return SUCCESS;
+        break;
+
+    default:
+        return FAILURE;
+    }
+    if (pOpts->curOptIdx >= pOpts->origArgCt)
+        return FAILURE;
+
+    ppzOpts[ (*pOptsIdx)++ ] = pOpts->origArgVect[ (pOpts->curOptIdx)++ ];
+    return SUCCESS;
+}
+
+static tSuccess
+mayHandleArg( tOptions* pOpts, char* pzArg, tOptState* pOS,
+              char** ppzOpts, int* pOptsIdx )
+{
+    /*
+     *  An option argument is optional.
+     */
+    switch (pOS->optType) {
+    case TOPT_SHORT:
+        /*
+         *  IF nothing is glued on after the current flag character,
+         *  THEN see if there is another argument.  If so and if it
+         *  does *NOT* start with a hyphen, then it is the option arg.
+         */
+        if (*pzArg != NUL)
+            return SUCCESS;
+        break;
+
+    case TOPT_LONG:
+        /*
+         *  Look for an argument if we don't already have one (glued on
+         *  with a `=' character)
+         */
+        if (pOS->pzOptArg != NULL)
+            return SUCCESS;
+        break;
+
+    default:
+        return FAILURE;
+    }
+    if (pOpts->curOptIdx >= pOpts->origArgCt)
+        return PROBLEM;
+
+    pzArg = pOpts->origArgVect[ pOpts->curOptIdx ];
+    if (*pzArg != '-')
+        ppzOpts[ (*pOptsIdx)++ ] = pOpts->origArgVect[ (pOpts->curOptIdx)++ ];
+    return SUCCESS;
+}
+
+/*
+ *  Process a string of short options glued together.  If the last one
+ *  does or may take an argument, the do the argument processing and leave.
+ */
+static tSuccess
+checkShortOpts( tOptions* pOpts, char* pzArg, tOptState* pOS,
+                char** ppzOpts, int* pOptsIdx )
+{
+    while (*pzArg != NUL) {
+        if (FAILED( shortOptionFind( pOpts, *pzArg, pOS )))
+            return FAILURE;
+
+        /*
+         *  See if we can have an arg.
+         */
+        if (OPTST_GET_ARGTYPE(pOS->pOD->fOptState) == OPARG_TYPE_NONE) {
+            pzArg++;
+
+        } else if (pOS->pOD->fOptState & OPTST_ARG_OPTIONAL) {
+            /*
+             *  Take an argument if it is not attached and it does not
+             *  start with a hyphen.
+             */
+            if (pzArg[1] != NUL)
+                return SUCCESS;
+
+            pzArg = pOpts->origArgVect[ pOpts->curOptIdx ];
+            if (*pzArg != '-')
+                ppzOpts[ (*pOptsIdx)++ ] =
+                    pOpts->origArgVect[ (pOpts->curOptIdx)++ ];
+            return SUCCESS;
+
+        } else {
+            /*
+             *  IF we need another argument, be sure it is there and
+             *  take it.
+             */
+            if (pzArg[1] == NUL) {
+                if (pOpts->curOptIdx >= pOpts->origArgCt)
+                    return FAILURE;
+                ppzOpts[ (*pOptsIdx)++ ] =
+                    pOpts->origArgVect[ (pOpts->curOptIdx)++ ];
+            }
+            return SUCCESS;
+        }
+    }
+    return SUCCESS;
+}
+
+/*
+ *  If the program wants sorted options (separated operands and options),
+ *  then this routine will to the trick.
+ */
+LOCAL void
+optionSort( tOptions* pOpts )
+{
+    char** ppzOpts;
+    char** ppzOpds;
+    int    optsIdx = 0;
+    int    opdsIdx = 0;
+
+    tOptState os = OPTSTATE_INITIALIZER(DEFINED);
+
+    /*
+     *  Disable for POSIX conformance
+     */
+    if (getenv( "POSIXLY_CORRECT" ) != NULL) {
+        errno = 0;
+        return;
+    }
+
+    errno = ENOENT;
+
+    /*
+     *  If all arguments are named, we can't sort 'em.  There are no operands.
+     */
+    if (NAMED_OPTS(pOpts))
+        return;
+
+    /*
+     *  Make sure we can allocate two full-sized arg vectors.
+     */
+    ppzOpts = malloc( pOpts->origArgCt * sizeof( char* ));
+    if (ppzOpts == NULL)
+        goto exit_no_mem;
+
+    ppzOpds = malloc( pOpts->origArgCt * sizeof( char* ));
+    if (ppzOpds == NULL) {
+        free( ppzOpts );
+        goto exit_no_mem;
+    }
+
+    pOpts->curOptIdx = 1;
+    pOpts->pzCurOpt  = NULL;
+
+    /*
+     *  Now, process all the options from our current position onward.
+     *  (This allows interspersed options and arguments for the few
+     *  non-standard programs that require it.)
+     */
+    for (;;) {
+        char* pzArg;
+        tSuccess res;
+
+        /*
+         *  If we're out of arguments, we're done.  Join the option and
+         *  operand lists into the original argument vector.
+         */
+        if (pOpts->curOptIdx >= pOpts->origArgCt) {
+            errno = 0;
+            goto joinLists;
+        }
+
+        pzArg = pOpts->origArgVect[ pOpts->curOptIdx ];
+        if (*pzArg != '-') {
+            ppzOpds[ opdsIdx++ ] = pOpts->origArgVect[ (pOpts->curOptIdx)++ ];
+            continue;
+        }
+
+        switch (pzArg[1]) {
+        case NUL:
+            /*
+             *  A regular option.  Put it on the operand list.
+             */
+            ppzOpds[ opdsIdx++ ] = pOpts->origArgVect[ (pOpts->curOptIdx)++ ];
+            continue;
+
+        case '-':
+            /*
+             *  Two consecutive hypens.  Put them on the options list and then
+             *  _always_ force the remainder of the arguments to be operands.
+             */
+            if (pzArg[2] == NUL) {
+                ppzOpts[ optsIdx++ ] =
+                    pOpts->origArgVect[ (pOpts->curOptIdx)++ ];
+                goto restOperands;
+            }
+            res = longOptionFind( pOpts, pzArg+2, &os );
+            break;
+
+        default:
+            /*
+             *  If short options are not allowed, then do long
+             *  option processing.  Otherwise the character must be a
+             *  short (i.e. single character) option.
+             */
+            if ((pOpts->fOptSet & OPTPROC_SHORTOPT) == 0) {
+                res = longOptionFind( pOpts, pzArg+1, &os );
+            } else {
+                res = shortOptionFind( pOpts, pzArg[1], &os );
+            }
+            break;
+        }
+        if (FAILED( res )) {
+            errno = EIO;
+            goto freeTemps;
+        }
+
+        /*
+         *  We've found an option.  Add the argument to the option list.
+         *  Next, we have to see if we need to pull another argument to be
+         *  used as the option argument.
+         */
+        ppzOpts[ optsIdx++ ] = pOpts->origArgVect[ (pOpts->curOptIdx)++ ];
+
+        if (OPTST_GET_ARGTYPE(os.pOD->fOptState) == OPARG_TYPE_NONE) {
+            /*
+             *  No option argument.  If we have a short option here,
+             *  then scan for short options until we get to the end
+             *  of the argument string.
+             */
+            if (  (os.optType == TOPT_SHORT)
+               && FAILED( checkShortOpts( pOpts, pzArg+2, &os,
+                                          ppzOpts, &optsIdx )) )  {
+                errno = EIO;
+                goto freeTemps;
+            }
+
+        } else if (os.pOD->fOptState & OPTST_ARG_OPTIONAL) {
+            switch (mayHandleArg( pOpts, pzArg+2, &os, ppzOpts, &optsIdx )) {
+            case FAILURE: errno = EIO; goto freeTemps;
+            case PROBLEM: errno = 0;   goto joinLists;
+            }
+
+        } else {
+            switch (mustHandleArg( pOpts, pzArg+2, &os, ppzOpts, &optsIdx )) {
+            case PROBLEM:
+            case FAILURE: errno = EIO; goto freeTemps;
+            }
+        }
+    } /* for (;;) */
+
+ restOperands:
+    while (pOpts->curOptIdx < pOpts->origArgCt)
+        ppzOpds[ opdsIdx++ ] = pOpts->origArgVect[ (pOpts->curOptIdx)++ ];
+
+ joinLists:
+    if (optsIdx > 0)
+        memcpy( pOpts->origArgVect + 1, ppzOpts, optsIdx * sizeof( char* ));
+    if (opdsIdx > 0)
+        memcpy( pOpts->origArgVect + 1 + optsIdx,
+                ppzOpds, opdsIdx * sizeof( char* ));
+
+ freeTemps:
+    free( ppzOpts );
+    free( ppzOpds );
+    return;
+
+ exit_no_mem:
+    errno = ENOMEM;
+    return;
+}
+
+/*
+ * Local Variables:
+ * mode: C
+ * c-file-style: "stroustrup"
+ * tab-width: 4
+ * indent-tabs-mode: nil
+ * End:
+ * end of autoopts/sort.c */
diff --git a/libopts/stack.c b/libopts/stack.c
new file mode 100644 (file)
index 0000000..bbea334
--- /dev/null
@@ -0,0 +1,224 @@
+
+/*
+ *  stack.c
+ *  $Id: stack.c,v 4.6 2006/03/25 19:24:56 bkorb Exp $
+ *  Time-stamp:      "2005-02-20 16:33:20 bkorb"
+ *
+ *  This is a special option processing routine that will save the
+ *  argument to an option in a FIFO queue.
+ */
+
+/*
+ *  Automated Options copyright 1992-2006 Bruce Korb
+ *
+ *  Automated Options is free software.
+ *  You may redistribute it and/or modify it under the terms of the
+ *  GNU General Public License, as published by the Free Software
+ *  Foundation; either version 2, or (at your option) any later version.
+ *
+ *  Automated Options is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with Automated Options.  See the file "COPYING".  If not,
+ *  write to:  The Free Software Foundation, Inc.,
+ *             51 Franklin Street, Fifth Floor,
+ *             Boston, MA  02110-1301, USA.
+ *
+ * As a special exception, Bruce Korb gives permission for additional
+ * uses of the text contained in his release of AutoOpts.
+ *
+ * The exception is that, if you link the AutoOpts library with other
+ * files to produce an executable, this does not by itself cause the
+ * resulting executable to be covered by the GNU General Public License.
+ * Your use of that executable is in no way restricted on account of
+ * linking the AutoOpts library code into it.
+ *
+ * This exception does not however invalidate any other reasons why
+ * the executable file might be covered by the GNU General Public License.
+ *
+ * This exception applies only to the code released by Bruce Korb under
+ * the name AutoOpts.  If you copy code from other sources under the
+ * General Public License into a copy of AutoOpts, as the General Public
+ * License permits, the exception does not apply to the code that you add
+ * in this way.  To avoid misleading anyone as to the status of such
+ * modified files, you must delete this exception notice from them.
+ *
+ * If you write modifications of your own for AutoOpts, it is your choice
+ * whether to permit this exception to apply to your modifications.
+ * If you do not wish that, delete this exception notice.
+ */
+
+#include REGEX_HEADER
+
+/*=export_func  optionUnstackArg
+ * private:
+ *
+ * what:  Remove option args from a stack
+ * arg:   + tOptions* + pOpts    + program options descriptor +
+ * arg:   + tOptDesc* + pOptDesc + the descriptor for this arg +
+ *
+ * doc:
+ *  Invoked for options that are equivalenced to stacked options.
+=*/
+void
+optionUnstackArg(
+    tOptions*  pOpts,
+    tOptDesc*  pOptDesc )
+{
+    int       res;
+
+    tArgList* pAL = (tArgList*)pOptDesc->optCookie;
+    /*
+     *  IF we don't have any stacked options,
+     *  THEN indicate that we don't have any of these options
+     */
+    if (pAL == NULL) {
+        pOptDesc->fOptState &= OPTST_PERSISTENT;
+        if ( (pOptDesc->fOptState & OPTST_INITENABLED) == 0)
+            pOptDesc->fOptState |= OPTST_DISABLED;
+        return;
+    }
+
+    {
+        regex_t   re;
+        int       i, ct, dIdx;
+
+        if (regcomp( &re, pOptDesc->pzLastArg, REG_NOSUB ) != 0)
+            return;
+
+        /*
+         *  search the list for the entry(s) to remove.  Entries that
+         *  are removed are *not* copied into the result.  The source
+         *  index is incremented every time.  The destination only when
+         *  we are keeping a define.
+         */
+        for (i = 0, dIdx = 0, ct = pAL->useCt; --ct >= 0; i++) {
+            tCC*      pzSrc = pAL->apzArgs[ i ];
+            char*     pzEq  = strchr( pzSrc, '=' );
+
+            if (pzEq != NULL)
+                *pzEq = NUL;
+
+            res = regexec( &re, pzSrc, (size_t)0, NULL, 0 );
+            switch (res) {
+            case 0:
+                /*
+                 *  Remove this entry by reducing the in-use count
+                 *  and *not* putting the string pointer back into
+                 *  the list.
+                 */
+                pAL->useCt--;
+                break;
+
+            default:
+            case REG_NOMATCH:
+                if (pzEq != NULL)
+                    *pzEq = '=';
+
+                /*
+                 *  IF we have dropped an entry
+                 *  THEN we have to move the current one.
+                 */
+                if (dIdx != i)
+                    pAL->apzArgs[ dIdx ] = pzSrc;
+                dIdx++;
+            }
+        }
+
+        regfree( &re );
+    }
+
+    /*
+     *  IF we have unstacked everything,
+     *  THEN indicate that we don't have any of these options
+     */
+    if (pAL->useCt == 0) {
+        pOptDesc->fOptState &= OPTST_PERSISTENT;
+        if ( (pOptDesc->fOptState & OPTST_INITENABLED) == 0)
+            pOptDesc->fOptState |= OPTST_DISABLED;
+        free( (void*)pAL );
+        pOptDesc->optCookie = NULL;
+    }
+}
+
+
+/*
+ *  Put an entry into an argument list.  The first argument points to
+ *  a pointer to the argument list structure.  It gets passed around
+ *  as an opaque address.
+ */
+LOCAL void
+addArgListEntry( void** ppAL, void* entry )
+{
+    tArgList* pAL = *(void**)ppAL;
+
+    /*
+     *  IF we have never allocated one of these,
+     *  THEN allocate one now
+     */
+    if (pAL == NULL) {
+        pAL = (tArgList*)AGALOC( sizeof( *pAL ), "new option arg stack" );
+        if (pAL == NULL)
+            return;
+        pAL->useCt   = 0;
+        pAL->allocCt = MIN_ARG_ALLOC_CT;
+        *ppAL = (void*)pAL;
+    }
+
+    /*
+     *  ELSE if we are out of room
+     *  THEN make it bigger
+     */
+    else if (pAL->useCt >= pAL->allocCt) {
+        size_t sz = sizeof( *pAL );
+        pAL->allocCt += INCR_ARG_ALLOC_CT;
+
+        /*
+         *  The base structure contains space for MIN_ARG_ALLOC_CT
+         *  pointers.  We subtract it off to find our augment size.
+         */
+        sz += sizeof(char*) * (pAL->allocCt - MIN_ARG_ALLOC_CT);
+        pAL = (tArgList*)AGREALOC( (void*)pAL, sz, "expanded opt arg stack" );
+        if (pAL == NULL)
+            return;
+        *ppAL = (void*)pAL;
+    }
+
+    /*
+     *  Insert the new argument into the list
+     */
+    pAL->apzArgs[ (pAL->useCt)++ ] = entry;
+}
+
+
+/*=export_func  optionStackArg
+ * private:
+ *
+ * what:  put option args on a stack
+ * arg:   + tOptions* + pOpts    + program options descriptor +
+ * arg:   + tOptDesc* + pOptDesc + the descriptor for this arg +
+ *
+ * doc:
+ *  Keep an entry-ordered list of option arguments.
+=*/
+void
+optionStackArg(
+    tOptions*  pOpts,
+    tOptDesc*  pOD )
+{
+    if (pOD->pzLastArg == NULL)
+        return;
+
+    addArgListEntry( &(pOD->optCookie), (void*)pOD->pzLastArg );
+}
+/*
+ * Local Variables:
+ * mode: C
+ * c-file-style: "stroustrup"
+ * tab-width: 4
+ * indent-tabs-mode: nil
+ * End:
+ * end of autoopts/stack.c */
diff --git a/libopts/streqvcmp.c b/libopts/streqvcmp.c
new file mode 100644 (file)
index 0000000..135e235
--- /dev/null
@@ -0,0 +1,292 @@
+
+/*
+ *  $Id: streqvcmp.c,v 4.7 2006/03/25 19:24:56 bkorb Exp $
+ * Time-stamp:      "2005-10-29 14:05:07 bkorb"
+ *
+ *  String Equivalence Comparison
+ *
+ *  These routines allow any character to be mapped to any other
+ *  character before comparison.  In processing long option names,
+ *  the characters "-", "_" and "^" all need to be equivalent
+ *  (because they are treated so by different development environments).
+ */
+
+/*
+ *  Automated Options copyright 1992-2006 Bruce Korb
+ *
+ *  Automated Options is free software.
+ *  You may redistribute it and/or modify it under the terms of the
+ *  GNU General Public License, as published by the Free Software
+ *  Foundation; either version 2, or (at your option) any later version.
+ *
+ *  Automated Options is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with Automated Options.  See the file "COPYING".  If not,
+ *  write to:  The Free Software Foundation, Inc.,
+ *             51 Franklin Street, Fifth Floor,
+ *             Boston, MA  02110-1301, USA.
+ *
+ * As a special exception, Bruce Korb gives permission for additional
+ * uses of the text contained in his release of AutoOpts.
+ *
+ * The exception is that, if you link the AutoOpts library with other
+ * files to produce an executable, this does not by itself cause the
+ * resulting executable to be covered by the GNU General Public License.
+ * Your use of that executable is in no way restricted on account of
+ * linking the AutoOpts library code into it.
+ *
+ * This exception does not however invalidate any other reasons why
+ * the executable file might be covered by the GNU General Public License.
+ *
+ * This exception applies only to the code released by Bruce Korb under
+ * the name AutoOpts.  If you copy code from other sources under the
+ * General Public License into a copy of AutoOpts, as the General Public
+ * License permits, the exception does not apply to the code that you add
+ * in this way.  To avoid misleading anyone as to the status of such
+ * modified files, you must delete this exception notice from them.
+ *
+ * If you write modifications of your own for AutoOpts, it is your choice
+ * whether to permit this exception to apply to your modifications.
+ * If you do not wish that, delete this exception notice.
+ */
+
+/*
+ * This array is designed for mapping upper and lower case letter
+ * together for a case independent comparison.  The mappings are
+ * based upon ascii character sequences.
+ */
+static unsigned char charmap[] = {
+    0x00, 0x01, 0x02, 0x03,  0x04, 0x05, 0x06, '\a',
+    '\b', '\t', '\n', '\v',  '\f', '\r', 0x0E, 0x0F,
+    0x10, 0x11, 0x12, 0x13,  0x14, 0x15, 0x16, 0x17,
+    0x18, 0x19, 0x1A, 0x1B,  0x1C, 0x1D, 0x1E, 0x1F,
+
+    ' ',  '!',  '"',  '#',   '$',  '%',  '&',  '\'',
+    '(',  ')',  '*',  '+',   ',',  '-',  '.',  '/',
+    '0',  '1',  '2',  '3',   '4',  '5',  '6',  '7',
+    '8',  '9',  ':',  ';',   '<',  '=',  '>',  '?',
+
+    '@',  'a',  'b',  'c',   'd',  'e',  'f',  'g',
+    'h',  'i',  'j',  'k',   'l',  'm',  'n',  'o',
+    'p',  'q',  'r',  's',   't',  'u',  'v',  'w',
+    'x',  'y',  'z',  '[',   '\\', ']',  '^',  '_',
+    '`',  'a',  'b',  'c',   'd',  'e',  'f',  'g',
+    'h',  'i',  'j',  'k',   'l',  'm',  'n',  'o',
+    'p',  'q',  'r',  's',   't',  'u',  'v',  'w',
+    'x',  'y',  'z',  '{',   '|',  '}',  '~',  0x7f,
+
+    0x80, 0x81, 0x82, 0x83,  0x84, 0x85, 0x86, 0x87,
+    0x88, 0x89, 0x8A, 0x8B,  0x8C, 0x8D, 0x8E, 0x8F,
+    0x90, 0x91, 0x92, 0x93,  0x94, 0x95, 0x96, 0x97,
+    0x98, 0x99, 0x9A, 0x9B,  0x9C, 0x9D, 0x9E, 0x9F,
+    0xA0, 0xA1, 0xA2, 0xA3,  0xA4, 0xA5, 0xA6, 0xA7,
+    0xA8, 0xA9, 0xAA, 0xAB,  0xAC, 0xAD, 0xAE, 0xAF,
+    0xB0, 0xB1, 0xB2, 0xB3,  0xB4, 0xB5, 0xB6, 0xB7,
+    0xB8, 0xB9, 0xBA, 0xBB,  0xBC, 0xBD, 0xBE, 0xBF,
+
+    0xC0, 0xC1, 0xC2, 0xC3,  0xC4, 0xC5, 0xC6, 0xC7,
+    0xC8, 0xC9, 0xCA, 0xCB,  0xCC, 0xCD, 0xCE, 0xCF,
+    0xD0, 0xD1, 0xD2, 0xD3,  0xD4, 0xD5, 0xD6, 0xD7,
+    0xD8, 0xD9, 0xDA, 0xDB,  0xDC, 0xDD, 0xDE, 0xDF,
+    0xE0, 0xE1, 0xE2, 0xE3,  0xE4, 0xE5, 0xE6, 0xE7,
+    0xE8, 0xE9, 0xEA, 0xEB,  0xEC, 0xED, 0xEE, 0xEF,
+    0xF0, 0xF1, 0xF2, 0xF3,  0xF4, 0xF5, 0xF6, 0xF7,
+    0xF8, 0xF9, 0xFA, 0xFB,  0xFC, 0xFD, 0xFE, 0xFF,
+};
+
+
+/*=export_func strneqvcmp
+ *
+ * what: compare two strings with an equivalence mapping
+ *
+ * arg:  + const char* + str1 + first string +
+ * arg:  + const char* + str2 + second string +
+ * arg:  + int         + ct   + compare length +
+ *
+ * ret_type:  int
+ * ret_desc:  the difference between two differing characters
+ *
+ * doc:
+ *
+ * Using a character mapping, two strings are compared for "equivalence".
+ * Each input character is mapped to a comparison character and the
+ * mapped-to characters are compared for the two NUL terminated input strings.
+ * The comparison is limited to @code{ct} bytes.
+ * This function name is mapped to option_strneqvcmp so as to not conflict
+ * with the POSIX name space.
+ *
+ * err:  none checked.  Caller responsible for seg faults.
+=*/
+int
+strneqvcmp( tCC* s1, tCC* s2, int ct )
+{
+    for (; ct > 0; --ct) {
+        unsigned char u1 = (unsigned char) *s1++;
+        unsigned char u2 = (unsigned char) *s2++;
+        int dif = charmap[ u1 ] - charmap[ u2 ];
+
+        if (dif != 0)
+            return dif;
+
+        if (u1 == NUL)
+            return 0;
+    }
+
+    return 0;
+}
+
+
+/*=export_func streqvcmp
+ *
+ * what: compare two strings with an equivalence mapping
+ *
+ * arg:  + const char* + str1 + first string +
+ * arg:  + const char* + str2 + second string +
+ *
+ * ret_type:  int
+ * ret_desc:  the difference between two differing characters
+ *
+ * doc:
+ *
+ * Using a character mapping, two strings are compared for "equivalence".
+ * Each input character is mapped to a comparison character and the
+ * mapped-to characters are compared for the two NUL terminated input strings.
+ * This function name is mapped to option_streqvcmp so as to not conflict
+ * with the POSIX name space.
+ *
+ * err:  none checked.  Caller responsible for seg faults.
+=*/
+int
+streqvcmp( tCC* s1, tCC* s2 )
+{
+    for (;;) {
+        unsigned char u1 = (unsigned char) *s1++;
+        unsigned char u2 = (unsigned char) *s2++;
+        int dif = charmap[ u1 ] - charmap[ u2 ];
+
+        if (dif != 0)
+            return dif;
+
+        if (u1 == NUL)
+            return 0;
+    }
+}
+
+
+/*=export_func streqvmap
+ *
+ * what: Set the character mappings for the streqv functions
+ *
+ * arg:  + char + From + Input character +
+ * arg:  + char + To   + Mapped-to character +
+ * arg:  + int  + ct   + compare length +
+ *
+ * doc:
+ *
+ * Set the character mapping.  If the count (@code{ct}) is set to zero, then
+ * the map is cleared by setting all entries in the map to their index
+ * value.  Otherwise, the "@code{From}" character is mapped to the "@code{To}"
+ * character.  If @code{ct} is greater than 1, then @code{From} and @code{To}
+ * are incremented and the process repeated until @code{ct} entries have been
+ * set. For example,
+ * @example
+ *    streqvmap( 'a', 'A', 26 );
+ * @end example
+ * @noindent
+ * will alter the mapping so that all English lower case letters
+ * will map to upper case.
+ *
+ * This function name is mapped to option_streqvmap so as to not conflict
+ * with the POSIX name space.
+ *
+ * err:  none.
+=*/
+void
+streqvmap( char From, char To, int ct )
+{
+    if (ct == 0) {
+        ct = sizeof( charmap ) - 1;
+        do  {
+            charmap[ ct ] = ct;
+        } while (--ct >= 0);
+    }
+
+    else {
+        int  chTo   = (int)To   & 0xFF;
+        int  chFrom = (int)From & 0xFF;
+
+        do  {
+            charmap[ chFrom ] = (unsigned)chTo;
+            chFrom++;
+            chTo++;
+            if ((chFrom >= sizeof( charmap )) || (chTo >= sizeof( charmap )))
+                break;
+        } while (--ct > 0);
+    }
+}
+
+
+/*=export_func strequate
+ *
+ * what: map a list of characters to the same value
+ *
+ * arg:  + const char* + ch_list + characters to equivalence +
+ *
+ * doc:
+ *
+ * Each character in the input string get mapped to the first character
+ * in the string.
+ * This function name is mapped to option_strequate so as to not conflict
+ * with the POSIX name space.
+ *
+ * err:  none.
+=*/
+void
+strequate( const char* s )
+{
+    if ((s != NULL) && (*s != NUL)) {
+        unsigned char equiv = (unsigned)*s;
+        while (*s != NUL)
+            charmap[ (unsigned)*(s++) ] = equiv;
+    }
+}
+
+
+/*=export_func strtransform
+ *
+ * what: convert a string into its mapped-to value
+ *
+ * arg:  + char*       + dest + output string +
+ * arg:  + const char* + src  + input string +
+ *
+ * doc:
+ *
+ * Each character in the input string is mapped and the mapped-to
+ * character is put into the output.
+ * This function name is mapped to option_strtransform so as to not conflict
+ * with the POSIX name space.
+ *
+ * err:  none.
+=*/
+void
+strtransform( d, s )
+    char*       d;
+    const char* s;
+{
+    do  {
+        *(d++) = (char)charmap[ (unsigned)*s ];
+    } while (*(s++) != NUL);
+}
+
+/*
+ * Local Variables:
+ * mode: C
+ * c-file-style: "stroustrup"
+ * tab-width: 4
+ * indent-tabs-mode: nil
+ * End:
+ * end of autoopts/streqvcmp.c */
diff --git a/libopts/text_mmap.c b/libopts/text_mmap.c
new file mode 100644 (file)
index 0000000..825cd90
--- /dev/null
@@ -0,0 +1,367 @@
+/*
+ * $Id: text_mmap.c,v 4.11 2006/02/01 17:18:00 bkorb Exp $
+ *
+ * Time-stamp:      "2006-02-01 08:45:37 bkorb"
+ */
+
+#ifndef MAP_ANONYMOUS 
+#  ifdef   MAP_ANON 
+#  define  MAP_ANONYMOUS   MAP_ANON 
+#  endif 
+#endif 
+
+/*
+ *  Some weird systems require that a specifically invalid FD number
+ *  get passed in as an argument value.  Which value is that?  Well,
+ *  as everybody knows, if open(2) fails, it returns -1, so that must
+ *  be the value.  :)
+ */
+#define AO_INVALID_FD  -1
+
+#define FILE_WRITABLE(_prt,_flg) \
+       ((_prt & PROT_WRITE) && (_flg & (MAP_SHARED|MAP_PRIVATE) == MAP_SHARED))
+#define MAP_FAILED_PTR ((void*)MAP_FAILED)
+
+/*=export_func  text_mmap
+ * private:
+ *
+ * what:  map a text file with terminating NUL
+ *
+ * arg:   const char*,  pzFile,  name of the file to map
+ * arg:   int,          prot,    mmap protections (see mmap(2))
+ * arg:   int,          flags,   mmap flags (see mmap(2))
+ * arg:   tmap_info_t*, mapinfo, returned info about the mapping
+ *
+ * ret-type:   void*
+ * ret-desc:   The mmaped data address
+ *
+ * doc:
+ *
+ * This routine will mmap a file into memory ensuring that there is at least
+ * one @file{NUL} character following the file data.  It will return the
+ * address where the file contents have been mapped into memory.  If there is a
+ * problem, then it will return @code{MAP_FAILED} and set @file{errno}
+ * appropriately.
+ *
+ * The named file does not exist, @code{stat(2)} will set @file{errno} as it
+ * will.  If the file is not a regular file, @file{errno} will be
+ * @code{EINVAL}.  At that point, @code{open(2)} is attempted with the access
+ * bits set appropriately for the requested @code{mmap(2)} protections and flag
+ * bits.  On failure, @file{errno} will be set according to the documentation
+ * for @code{open(2)}.  If @code{mmap(2)} fails, @file{errno} will be set as
+ * that routine sets it.  If @code{text_mmap} works to this point, a valid
+ * address will be returned, but there may still be ``issues''.
+ *
+ * If the file size is not an even multiple of the system page size, then
+ * @code{text_map} will return at this point and @file{errno} will be zero.
+ * Otherwise, an anonymous map is attempted.  If not available, then an attempt
+ * is made to @code{mmap(2)} @file{/dev/zero}.  If any of these fail, the
+ * address of the file's data is returned, bug @code{no} @file{NUL} characters
+ * are mapped after the end of the data.
+ *
+ * see: mmap(2), open(2), stat(2)
+ *
+ * err: Any error code issued by mmap(2), open(2), stat(2) is possible.
+ *      Additionally, if the specified file is not a regular file, then
+ *      errno will be set to @code{EINVAL}.
+ *
+ * example:
+ * #include <mylib.h>
+ * tmap_info_t mi;
+ * int no_nul;
+ * void* data = text_mmap( "file", PROT_WRITE, MAP_PRIVATE, &mi );
+ * if (data == MAP_FAILED) return;
+ * no_nul = (mi.txt_size == mi.txt_full_size);
+ * << use the data >>
+ * text_munmap( &mi );
+=*/
+void*
+text_mmap( const char* pzFile, int prot, int flags, tmap_info_t* pMI )
+{
+    memset( pMI, 0, sizeof(*pMI) );
+#ifdef HAVE_MMAP
+    pMI->txt_zero_fd = -1;
+#endif
+    pMI->txt_fd = -1;
+
+    /*
+     *  Make sure we can stat the regular file.  Save the file size.
+     */
+    {
+        struct stat sb;
+        if (stat( pzFile, &sb ) != 0) {
+            pMI->txt_errno = errno;
+            return MAP_FAILED_PTR;
+        }
+
+        if (! S_ISREG( sb.st_mode )) {
+            pMI->txt_errno = errno = EINVAL;
+            return MAP_FAILED_PTR;
+        }
+
+        pMI->txt_size = sb.st_size;
+    }
+
+    /*
+     *  Map mmap flags and protections into open flags and do the open.
+     */
+    {
+        int o_flag;
+        /*
+         *  See if we will be updating the file.  If we can alter the memory
+         *  and if we share the data and we are *not* copy-on-writing the data,
+         *  then our updates will show in the file, so we must open with
+         *  write access.
+         */
+        if (FILE_WRITABLE(prot,flags))
+            o_flag = O_RDWR;
+        else
+            o_flag = O_RDONLY;
+
+        /*
+         *  If you're not sharing the file and you are writing to it,
+         *  then don't let anyone else have access to the file.
+         */
+        if (((flags & MAP_SHARED) == 0) && (prot & PROT_WRITE))
+            o_flag |= O_EXCL;
+
+        pMI->txt_fd = open( pzFile, o_flag );
+    }
+
+    if (pMI->txt_fd == AO_INVALID_FD) {
+        pMI->txt_errno = errno;
+        return MAP_FAILED_PTR;
+    }
+
+#ifdef HAVE_MMAP /* * * * * WITH MMAP * * * * * */
+    /*
+     *  do the mmap.  If we fail, then preserve errno, close the file and
+     *  return the failure.
+     */
+    pMI->txt_data = mmap( NULL, pMI->txt_size+1, prot, flags, pMI->txt_fd, 0 );
+    if (pMI->txt_data == MAP_FAILED_PTR) {
+        pMI->txt_errno = errno;
+        goto fail_return;
+    }
+
+    /*
+     *  Most likely, everything will turn out fine now.  The only difficult
+     *  part at this point is coping with files with sizes that are a multiple
+     *  of the page size.  Handling that is what this whole thing is about.
+     */
+    pMI->txt_zero_fd = -1;
+    pMI->txt_errno   = 0;
+
+    {
+        void* pNuls;
+#ifdef _SC_PAGESIZE
+        size_t pgsz = sysconf(_SC_PAGESIZE);
+#else
+        size_t pgsz = getpagesize();
+#endif
+        /*
+         *  Compute the pagesize rounded mapped memory size.
+         *  IF this is not the same as the file size, then there are NUL's
+         *  at the end of the file mapping and all is okay.
+         */
+        pMI->txt_full_size = (pMI->txt_size + (pgsz - 1)) & ~(pgsz - 1);
+        if (pMI->txt_size != pMI->txt_full_size)
+            return pMI->txt_data;
+
+        /*
+         *  Still here?  We have to remap the trailing inaccessible page
+         *  either anonymously or to /dev/zero.
+         */
+        pMI->txt_full_size += pgsz;
+#if defined(MAP_ANONYMOUS)
+        pNuls = mmap(
+                (void*)(((char*)pMI->txt_data) + pMI->txt_size),
+                pgsz, PROT_READ|PROT_WRITE,
+                MAP_ANONYMOUS|MAP_FIXED|MAP_PRIVATE, AO_INVALID_FD, 0 );
+
+        if (pNuls != MAP_FAILED_PTR)
+            return pMI->txt_data;
+
+        pMI->txt_errno = errno;
+#endif
+
+#if defined(HAVE_DEV_ZERO)
+        pMI->txt_zero_fd = open( "/dev/zero", O_RDONLY );
+
+        if (pMI->txt_zero_fd == AO_INVALID_FD) {
+            pMI->txt_errno = errno;
+
+        } else {
+            pNuls = mmap(
+                    (void*)(((char*)pMI->txt_data) + pMI->txt_size), pgsz,
+                    PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED,
+                    pMI->txt_zero_fd, 0 );
+
+            if (pNuls != MAP_FAILED_PTR)
+                return pMI->txt_data;
+
+            pMI->txt_errno = errno;
+            close( pMI->txt_zero_fd );
+            pMI->txt_zero_fd = -1;
+        }
+#endif
+
+        pMI->txt_full_size = pMI->txt_size;
+    }
+
+    {
+        void* p = AGALOC( pMI->txt_size+1, "file text" );
+        if (pMI->txt_data == NULL) {
+            pMI->txt_errno = ENOMEM;
+            goto fail_return;
+        }
+        memcpy( p, pMI->txt_data, pMI->txt_size );
+        ((char*)p)[pMI->txt_size] = NUL;
+        munmap(pMI->txt_data, pMI->txt_size );
+        pMI->txt_data = p;
+    }
+    pMI->txt_alloc = 1;
+    return pMI->txt_data;
+
+#else /* * * * * * no HAVE_MMAP * * * * * */
+
+    pMI->txt_data = AGALOC( pMI->txt_size+1, "file text" );
+    if (pMI->txt_data == NULL) {
+        pMI->txt_errno = ENOMEM;
+        goto fail_return;
+    }
+
+    {
+        size_t sz = pMI->txt_size;
+        char*  pz = pMI->txt_data;
+
+        while (sz > 0) {
+            ssize_t rdct = read( pMI->txt_fd, pz, sz );
+            if (rdct <= 0) {
+                pMI->txt_errno = errno;
+                fprintf( stderr, zFSErrReadFile,
+                         errno, strerror( errno ), pzFile );
+                free( pMI->txt_data );
+                goto fail_return;
+            }
+
+            pz += rdct;
+            sz -= rdct;
+        }
+
+        *pz = NUL;
+    }
+
+    /*
+     *  We never need a dummy page mapped in
+     */
+    pMI->txt_zero_fd = -1;
+    pMI->txt_errno   = 0;
+
+    return pMI->txt_data;
+
+#endif /* * * * * * no HAVE_MMAP * * * * * */
+
+ fail_return:
+    if (pMI->txt_fd >= 0) {
+        close( pMI->txt_fd );
+        pMI->txt_fd = -1;
+    }
+    errno = pMI->txt_errno;
+    pMI->txt_data = MAP_FAILED_PTR;
+    return pMI->txt_data;
+}
+
+
+/*=export_func  text_munmap
+ * private:
+ *
+ * what:  unmap the data mapped in by text_mmap
+ *
+ * arg:   tmap_info_t*, mapinfo, info about the mapping
+ *
+ * ret-type:   int
+ * ret-desc:   -1 or 0.  @file{errno} will have the error code.
+ *
+ * doc:
+ *
+ * This routine will unmap the data mapped in with @code{text_mmap} and close
+ * the associated file descriptors opened by that function.
+ *
+ * see: munmap(2), close(2)
+ *
+ * err: Any error code issued by munmap(2) or close(2) is possible.
+=*/
+int
+text_munmap( tmap_info_t* pMI )
+{
+#ifdef HAVE_MMAP
+    int res = 0;
+    if (pMI->txt_alloc) {
+        /*
+         *  IF the user has write permission and the text is not mapped private,
+         *  then write back any changes.  Hopefully, nobody else has modified
+         *  the file in the mean time.
+         */
+        if (   ((pMI->txt_prot & PROT_WRITE) != 0)
+            && ((pMI->txt_flags & MAP_PRIVATE) == 0))  {
+
+            if (lseek( pMI->txt_fd, 0, SEEK_SET) != 0)
+                goto error_return;
+
+            res = (write( pMI->txt_fd, pMI->txt_data, pMI->txt_size ) < 0)
+                ? errno : 0;
+        }
+
+        AGFREE( pMI->txt_data );
+        errno = res;
+    } else {
+        res = munmap( pMI->txt_data, pMI->txt_full_size );
+    }
+    if (res != 0)
+        goto error_return;
+
+    res = close( pMI->txt_fd );
+    if (res != 0)
+        goto error_return;
+
+    pMI->txt_fd = -1;
+    errno = 0;
+    if (pMI->txt_zero_fd != -1) {
+        res = close( pMI->txt_zero_fd );
+        pMI->txt_zero_fd = -1;
+    }
+
+ error_return:
+    pMI->txt_errno = errno;
+    return res;
+#else  /* HAVE_MMAP */
+
+    errno = 0;
+    /*
+     *  IF the memory is writable *AND* it is not private (copy-on-write)
+     *     *AND* the memory is "sharable" (seen by other processes)
+     *  THEN rewrite the data.
+     */
+    if (   FILE_WRITABLE(pMI->txt_prot, pMI->txt_flags)
+        && (lseek( pMI->txt_fd, 0, SEEK_SET ) >= 0) ) {
+        write( pMI->txt_fd, pMI->txt_data, pMI->txt_size );
+    }
+
+    close( pMI->txt_fd );
+    pMI->txt_fd = -1;
+    pMI->txt_errno = errno;
+    free( pMI->txt_data );
+
+    return pMI->txt_errno;
+#endif /* HAVE_MMAP */
+}
+
+/*
+ * Local Variables:
+ * mode: C
+ * c-file-style: "stroustrup"
+ * tab-width: 4
+ * indent-tabs-mode: nil
+ * End:
+ * end of autoopts/text_mmap.c */
diff --git a/libopts/tokenize.c b/libopts/tokenize.c
new file mode 100644 (file)
index 0000000..074473c
--- /dev/null
@@ -0,0 +1,322 @@
+/*
+ *  This file defines the string_tokenize interface
+ * Time-stamp:      "2005-04-25 18:47:21 bkorb"
+ *
+ *  string_tokenize copyright 2005 Bruce Korb
+ *
+ *  string_tokenize is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public
+ *  License as published by the Free Software Foundation; either
+ *  version 2.1 of the License, or (at your option) any later version.
+ *
+ *  string_tokenize is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with string_tokenize; if not, write to:
+ *             The Free Software Foundation, Inc.,
+ *             51 Franklin Street, Fifth Floor,
+ *             Boston, MA  02110-1301, USA.
+ */
+#include <ctype.h>
+#include <errno.h>
+#include <stdlib.h>
+
+#define cc_t   const unsigned char
+#define ch_t   unsigned char
+
+/* = = = START-STATIC-FORWARD = = = */
+/* static forward declarations maintained by :mkfwd */
+static void
+copy_cooked( ch_t** ppDest, cc_t** ppSrc );
+
+static void
+copy_raw( ch_t** ppDest, cc_t** ppSrc );
+/* = = = END-STATIC-FORWARD = = = */
+
+static void
+copy_cooked( ch_t** ppDest, cc_t** ppSrc )
+{
+    ch_t* pDest = (ch_t*)*ppDest;
+    const ch_t* pSrc  = (const ch_t*)(*ppSrc + 1);
+
+    for (;;) {
+        ch_t ch = *(pSrc++);
+        switch (ch) {
+        case NUL:   *ppSrc = NULL; return;
+        case '"':   goto done;
+        case '\\':
+            pSrc += ao_string_cook_escape_char( (char*)pSrc, (char*)&ch, 0x7F );
+            if (ch == 0x7F)
+                break;
+            /* FALLTHROUGH */
+
+        default:
+            *(pDest++) = ch;
+        }
+    }
+
+ done:
+    *ppDest = (ch_t*)pDest; /* next spot for storing character */
+    *ppSrc  = (ch_t*)pSrc;  /* char following closing quote    */
+}
+
+
+static void
+copy_raw( ch_t** ppDest, cc_t** ppSrc )
+{
+    ch_t* pDest = *ppDest;
+    cc_t* pSrc  = *ppSrc + 1;
+
+    for (;;) {
+        ch_t ch = *(pSrc++);
+        switch (ch) {
+        case NUL:   *ppSrc = NULL; return;
+        case '\'':  goto done;
+        case '\\':
+            /*
+             *  *Four* escapes are handled:  newline removal, escape char
+             *  quoting and apostrophe quoting
+             */
+            switch (*pSrc) {
+            case NUL:   *ppSrc = NULL; return;
+            case '\r':
+                if (*(++pSrc) == '\n')
+                    ++pSrc;
+                continue;
+
+            case '\n':
+                ++pSrc;
+                continue;
+
+            case '\'':
+                ch = '\'';
+                /* FALLTHROUGH */
+
+            case '\\':
+                ++pSrc;
+                break;
+            }
+            /* FALLTHROUGH */
+
+        default:
+            *(pDest++) = ch;
+        }
+    }
+
+ done:
+    *ppDest = pDest; /* next spot for storing character */
+    *ppSrc  = pSrc;  /* char following closing quote    */
+}
+
+
+/*=export_func ao_string_tokenize
+ *
+ * what: tokenize an input string
+ *
+ * arg:  + const char* + string + string to be tokenized +
+ *
+ * ret_type:  token_list_t*
+ * ret_desc:  pointer to a structure that lists each token
+ *
+ * doc:
+ *
+ * This function will convert one input string into a list of strings.
+ * The list of strings is derived by separating the input based on
+ * white space separation.  However, if the input contains either single
+ * or double quote characters, then the text after that character up to
+ * a matching quote will become the string in the list.
+ *
+ *  The returned pointer should be deallocated with @code{free(3C)} when
+ *  are done using the data.  The data are placed in a single block of
+ *  allocated memory.  Do not deallocate individual token/strings.
+ *
+ *  The structure pointed to will contain at least these two fields:
+ *  @table @samp
+ *  @item tkn_ct
+ *  The number of tokens found in the input string.
+ *  @item tok_list
+ *  An array of @code{tkn_ct + 1} pointers to substring tokens, with
+ *  the last pointer set to NULL.
+ *  @end table
+ *
+ * There are two types of quoted strings: single quoted (@code{'}) and
+ * double quoted (@code{"}).  Singly quoted strings are fairly raw in that
+ * escape characters (@code{\\}) are simply another character, except when
+ * preceding the following characters:
+ * @example
+ * @code{\\}  double backslashes reduce to one
+ * @code{'}   incorporates the single quote into the string
+ * @code{\n}  suppresses both the backslash and newline character
+ * @end example
+ *
+ * Double quote strings are formed according to the rules of string
+ * constants in ANSI-C programs.
+ *
+ * example:
+ * @example
+ *    #include <stdlib.h>
+ *    int ix;
+ *    token_list_t* ptl = ao_string_tokenize( some_string )
+ *    for (ix = 0; ix < ptl->tkn_ct; ix++)
+ *       do_something_with_tkn( ptl->tkn_list[ix] );
+ *    free( ptl );
+ * @end example
+ * Note that everything is freed with the one call to @code{free(3C)}.
+ *
+ * err:
+ *  NULL is returned and @code{errno} will be set to indicate the problem:
+ *  @itemize @bullet
+ *  @item
+ *  @code{EINVAL} - There was an unterminated quoted string.
+ *  @item
+ *  @code{ENOENT} - The input string was empty.
+ *  @item
+ *  @code{ENOMEM} - There is not enough memory.
+ *  @end itemize
+=*/
+token_list_t*
+ao_string_tokenize( const char* str )
+{
+    int max_token_ct = 1; /* allow for trailing NUL on string */
+    token_list_t* res;
+
+    if (str == NULL)  goto bogus_str;
+
+    /*
+     *  Trim leading white space.  Use "ENOENT" and a NULL return to indicate
+     *  an empty string was passed.
+     */
+    while (isspace( *str ))  str++;
+    if (*str == NUL) {
+    bogus_str:
+        errno = ENOENT;
+        return NULL;
+    }
+
+    /*
+     *  Take an approximate count of tokens.  If no quoted strings are used,
+     *  it will be accurate.  If quoted strings are used, it will be a little
+     *  high and we'll squander the space for a few extra pointers.
+     */
+    {
+        cc_t* pz = (cc_t*)str;
+
+        do {
+            max_token_ct++;
+            while (! isspace( *++pz ))
+                if (*pz == NUL) goto found_nul;
+            while (isspace( *pz ))  pz++;
+        } while (*pz != NUL);
+
+    found_nul:
+        ;
+    }
+
+    res = malloc( sizeof(*res) + strlen(str) + (max_token_ct * sizeof(ch_t*)) );
+    if (res == NULL) {
+        errno = ENOMEM;
+        return res;
+    }
+
+    /*
+     *  Now copy each token into the output buffer.
+     */
+    {
+        ch_t* pzDest = (ch_t*)(res->tkn_list + (max_token_ct + 1));
+        res->tkn_ct  = 0;
+
+        do  {
+            res->tkn_list[ res->tkn_ct++ ] = pzDest;
+            for (;;) {
+                char ch = *str;
+                if (isspace( ch )) {
+                found_white_space:
+                    while (isspace( *++str ))  ;
+                    break;
+                }
+
+                switch (ch) {
+                case '"':
+                    copy_cooked( &pzDest, (cc_t**)&str );
+                    if (str == NULL) {
+                        free(res);
+                        errno = EINVAL;
+                        return NULL;
+                    }
+                    if (isspace( *str ))
+                        goto found_white_space;
+                    break;
+
+                case '\'':
+                    copy_raw( &pzDest, (cc_t**)&str );
+                    if (str == NULL) {
+                        free(res);
+                        errno = EINVAL;
+                        return NULL;
+                    }
+                    if (isspace( *str ))
+                        goto found_white_space;
+                    break;
+
+                case NUL:
+                    goto copy_done;
+
+                default:
+                    str++;
+                    *(pzDest++) = ch;
+                }
+            } copy_done:;
+
+            /*
+             * NUL terminate the last token and see if we have any more tokens.
+             */
+            *(pzDest++) = NUL;
+        } while (*str != NUL);
+
+        res->tkn_list[ res->tkn_ct ] = NULL;
+    }
+
+    return res;
+}
+
+#ifdef TEST
+#include <stdio.h>
+#include <string.h>
+
+int
+main( int argc, char** argv )
+{
+    if (argc == 1) {
+        printf("USAGE:  %s arg [ ... ]\n", *argv);
+        return 1;
+    }
+    while (--argc > 0) {
+        char* arg = *(++argv);
+        token_list_t* p = ao_string_tokenize( arg );
+        if (p == NULL) {
+            printf( "Parsing string ``%s'' failed:\n\terrno %d (%s)\n",
+                    arg, errno, strerror( errno ));
+        } else {
+            int ix = 0;
+            printf( "Parsed string ``%s''\ninto %d tokens:\n", arg, p->tkn_ct );
+            do {
+                printf( " %3d:  ``%s''\n", ix+1, p->tkn_list[ix] );
+            } while (++ix < p->tkn_ct);
+            free(p);
+        }
+    }
+    return 0;
+}
+#endif
+
+/*
+ * Local Variables:
+ * mode: C
+ * c-file-style: "stroustrup"
+ * tab-width: 4
+ * indent-tabs-mode: nil
+ * End:
+ * end of autoopts/tokenize.c */
diff --git a/libopts/usage.c b/libopts/usage.c
new file mode 100644 (file)
index 0000000..5d36ab9
--- /dev/null
@@ -0,0 +1,732 @@
+
+/*
+ *  usage.c  $Id: usage.c,v 4.11 2006/03/25 19:24:57 bkorb Exp $
+ * Time-stamp:      "2006-02-04 13:35:26 bkorb"
+ *
+ *  This module implements the default usage procedure for
+ *  Automated Options.  It may be overridden, of course.
+ *
+ *  Sort options:
+    --start=END-[S]TATIC-FORWARD --patt='^/\*($|[^:])' \
+    --out=xx.c key='^[a-zA-Z0-9_]+\(' --trail='^/\*:' \
+    --spac=2 --input=usage.c
+ */
+
+/*
+ *  Automated Options copyright 1992-2006 Bruce Korb
+ *
+ *  Automated Options is free software.
+ *  You may redistribute it and/or modify it under the terms of the
+ *  GNU General Public License, as published by the Free Software
+ *  Foundation; either version 2, or (at your option) any later version.
+ *
+ *  Automated Options is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with Automated Options.  See the file "COPYING".  If not,
+ *  write to:  The Free Software Foundation, Inc.,
+ *             51 Franklin Street, Fifth Floor,
+ *             Boston, MA  02110-1301, USA.
+ *
+ * As a special exception, Bruce Korb gives permission for additional
+ * uses of the text contained in his release of AutoOpts.
+ *
+ * The exception is that, if you link the AutoOpts library with other
+ * files to produce an executable, this does not by itself cause the
+ * resulting executable to be covered by the GNU General Public License.
+ * Your use of that executable is in no way restricted on account of
+ * linking the AutoOpts library code into it.
+ *
+ * This exception does not however invalidate any other reasons why
+ * the executable file might be covered by the GNU General Public License.
+ *
+ * This exception applies only to the code released by Bruce Korb under
+ * the name AutoOpts.  If you copy code from other sources under the
+ * General Public License into a copy of AutoOpts, as the General Public
+ * License permits, the exception does not apply to the code that you add
+ * in this way.  To avoid misleading anyone as to the status of such
+ * modified files, you must delete this exception notice from them.
+ *
+ * If you write modifications of your own for AutoOpts, it is your choice
+ * whether to permit this exception to apply to your modifications.
+ * If you do not wish that, delete this exception notice.
+ */
+
+#define OPTPROC_L_N_S  (OPTPROC_LONGOPT | OPTPROC_SHORTOPT)
+
+static arg_types_t argTypes;
+
+FILE* option_usage_fp = NULL;
+static char    zOptFmtLine[ 16 ];
+static ag_bool displayEnum;
+
+/* = = = START-STATIC-FORWARD = = = */
+/* static forward declarations maintained by :mkfwd */
+static ag_bool
+checkGNUUsage( tOptions* pOpts );
+
+static void
+printExtendedUsage(
+    tOptions*     pOptions,
+    tOptDesc*     pOD,
+    arg_types_t*  pAT );
+
+static void
+printInitList(
+    tCC**    papz,
+    ag_bool* pInitIntro,
+    tCC*     pzRc,
+    tCC*     pzPN );
+
+static void
+printOneUsage(
+    tOptions*     pOptions,
+    tOptDesc*     pOD,
+    arg_types_t*  pAT );
+
+static void
+printOptionUsage(
+    tOptions* pOpts,
+    int       ex_code,
+    tCC*      pOptTitle );
+
+static void
+printProgramDetails( tOptions* pOptions );
+
+static int
+setGnuOptFmts( tOptions* pOpts, tCC** ppT );
+
+static int
+setStdOptFmts( tOptions* pOpts, tCC** ppT );
+/* = = = END-STATIC-FORWARD = = = */
+
+
+/*
+ *  Figure out if we should try to format usage text sort-of like
+ *  the way many GNU programs do.
+ */
+static ag_bool
+checkGNUUsage( tOptions* pOpts )
+{
+    char* pz = getenv( "AUTOOPTS_USAGE" );
+    if (pz == NULL)
+        ;
+
+    else if (streqvcmp( pz, "gnu" ) == 0)
+        pOpts->fOptSet |= OPTPROC_GNUUSAGE;
+
+    else if (streqvcmp( pz, "autoopts" ) == 0)
+        pOpts->fOptSet &= ~OPTPROC_GNUUSAGE;
+
+    return (pOpts->fOptSet & OPTPROC_GNUUSAGE) ? AG_TRUE : AG_FALSE;
+}
+
+
+/*=export_func  optionOnlyUsage
+ *
+ * what:  Print usage text for just the options
+ * arg:   + tOptions*   + pOpts    + program options descriptor +
+ * arg:   + int         + ex_code  + exit code for calling exit(3) +
+ *
+ * doc:
+ *  This routine will print only the usage for each option.
+ *  This function may be used when the emitted usage must incorporate
+ *  information not available to AutoOpts.
+=*/
+void
+optionOnlyUsage(
+    tOptions* pOpts,
+    int       ex_code )
+{
+    tCC* pOptTitle;
+
+    /*
+     *  Determine which header and which option formatting strings to use
+     */
+    if (checkGNUUsage(pOpts)) {
+        (void)setGnuOptFmts( pOpts, &pOptTitle );
+    }
+    else {
+        (void)setStdOptFmts( pOpts, &pOptTitle );
+    }
+
+    printOptionUsage( pOpts, ex_code, pOptTitle );
+}
+
+
+/*=export_func  optionUsage
+ * private:
+ *
+ * what:  Print usage text
+ * arg:   + tOptions* + pOptions + program options descriptor +
+ * arg:   + int       + exitCode + exit code for calling exit(3) +
+ *
+ * doc:
+ *  This routine will print usage in both GNU-standard and AutoOpts-expanded
+ *  formats.  The descriptor specifies the default, but AUTOOPTS_USAGE will
+ *  over-ride this, providing the value of it is set to either "gnu" or
+ *  "autoopts".  This routine will @strong{not} return.
+=*/
+void
+optionUsage(
+    tOptions* pOptions,
+    int       exitCode )
+{
+    displayEnum = AG_FALSE;
+
+    /*
+     *  Paged usage will preset option_usage_fp to an output file.
+     *  If it hasn't already been set, then set it to standard output
+     *  on successful exit (help was requested), otherwise error out.
+     */
+    if (option_usage_fp == NULL)
+        option_usage_fp = (exitCode != EXIT_SUCCESS) ? stderr : stdout;
+
+    fprintf( option_usage_fp, pOptions->pzUsageTitle, pOptions->pzProgName );
+
+    {
+        tCC* pOptTitle;
+
+        /*
+         *  Determine which header and which option formatting strings to use
+         */
+        if (checkGNUUsage(pOptions)) {
+            int flen = setGnuOptFmts( pOptions, &pOptTitle );
+            sprintf( zOptFmtLine, zFmtFmt, flen );
+            fputc( '\n', option_usage_fp );
+        }
+        else {
+            int flen = setStdOptFmts( pOptions, &pOptTitle );
+            sprintf( zOptFmtLine, zFmtFmt, flen );
+
+            /*
+             *  When we exit with EXIT_SUCCESS and the first option is a doc
+             *  option, we do *NOT* want to emit the column headers.
+             *  Otherwise, we do.
+             */
+            if (  (exitCode != EXIT_SUCCESS)
+               || ((pOptions->pOptDesc->fOptState & OPTST_DOCUMENT) == 0) )
+
+                fputs( pOptTitle, option_usage_fp );
+        }
+
+        printOptionUsage( pOptions, exitCode, pOptTitle );
+    }
+
+    /*
+     *  Describe the mechanics of denoting the options
+     */
+    switch (pOptions->fOptSet & OPTPROC_L_N_S) {
+    case OPTPROC_L_N_S:     fputs( zFlagOkay, option_usage_fp ); break;
+    case OPTPROC_SHORTOPT:  break;
+    case OPTPROC_LONGOPT:   fputs( zNoFlags,  option_usage_fp ); break;
+    case 0:                 fputs( zOptsOnly, option_usage_fp ); break;
+    }
+
+    if ((pOptions->fOptSet & OPTPROC_NUM_OPT) != 0) {
+        fputs( zNumberOpt, option_usage_fp );
+    }
+
+    if ((pOptions->fOptSet & OPTPROC_REORDER) != 0) {
+        fputs( zReorder, option_usage_fp );
+    }
+
+    if (pOptions->pzExplain != NULL)
+        fputs( pOptions->pzExplain, option_usage_fp );
+
+    /*
+     *  IF the user is asking for help (thus exiting with SUCCESS),
+     *  THEN see what additional information we can provide.
+     */
+    if (exitCode == EXIT_SUCCESS)
+        printProgramDetails( pOptions );
+
+    if (pOptions->pzBugAddr != NULL)
+        fprintf( option_usage_fp, zPlsSendBugs, pOptions->pzBugAddr );
+    fflush( option_usage_fp );
+
+    exit( exitCode );
+}
+
+
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ *
+ *   PER OPTION TYPE USAGE INFORMATION
+ */
+static void
+printExtendedUsage(
+    tOptions*     pOptions,
+    tOptDesc*     pOD,
+    arg_types_t*  pAT )
+{
+    /*
+     *  IF there are option conflicts or dependencies,
+     *  THEN print them here.
+     */
+    if (  (pOD->pOptMust != NULL)
+       || (pOD->pOptCant != NULL) ) {
+
+        fputs( zTabHyp, option_usage_fp );
+
+        /*
+         *  DEPENDENCIES:
+         */
+        if (pOD->pOptMust != NULL) {
+            const int* pOptNo = pOD->pOptMust;
+
+            fputs( zReqThese, option_usage_fp );
+            for (;;) {
+                fprintf( option_usage_fp, zTabout, pOptions->pOptDesc[
+                             *pOptNo ].pz_Name );
+                if (*++pOptNo == NO_EQUIVALENT)
+                    break;
+            }
+
+            if (pOD->pOptCant != NULL)
+                fputs( zTabHypAnd, option_usage_fp );
+        }
+
+        /*
+         *  CONFLICTS:
+         */
+        if (pOD->pOptCant != NULL) {
+            const int* pOptNo = pOD->pOptCant;
+
+            fputs( zProhib, option_usage_fp );
+            for (;;) {
+                fprintf( option_usage_fp, zTabout, pOptions->pOptDesc[
+                             *pOptNo ].pz_Name );
+                if (*++pOptNo == NO_EQUIVALENT)
+                    break;
+            }
+        }
+    }
+
+    /*
+     *  IF there is a disablement string
+     *  THEN print the disablement info
+     */
+    if (pOD->pz_DisableName != NULL )
+        fprintf( option_usage_fp, zDis, pOD->pz_DisableName );
+
+    /*
+     *  IF the numeric option has a special callback,
+     *  THEN call it, requesting the range or other special info
+     */
+    if (  (OPTST_GET_ARGTYPE(pOD->fOptState) == OPARG_TYPE_NUMERIC)
+       && (pOD->pOptProc != NULL)
+       && (pOD->pOptProc != optionNumericVal) ) {
+        (*(pOD->pOptProc))( pOptions, NULL );
+    }
+
+    /*
+     *  IF the option defaults to being enabled,
+     *  THEN print that out
+     */
+    if (pOD->fOptState & OPTST_INITENABLED)
+        fputs( zEnab, option_usage_fp );
+
+    /*
+     *  IF  the option is in an equivalence class
+     *        AND not the designated lead
+     *  THEN print equivalence and leave it at that.
+     */
+    if (  (pOD->optEquivIndex != NO_EQUIVALENT)
+       && (pOD->optEquivIndex != pOD->optActualIndex )  )  {
+        fprintf( option_usage_fp, zAlt,
+                 pOptions->pOptDesc[ pOD->optEquivIndex ].pz_Name );
+        return;
+    }
+
+    /*
+     *  IF this particular option can NOT be preset
+     *    AND some form of presetting IS allowed,
+     *  THEN advise that this option may not be preset.
+     */
+    if (  ((pOD->fOptState & OPTST_NO_INIT) != 0)
+       && (  (pOptions->papzHomeList != NULL)
+          || (pOptions->pzPROGNAME != NULL)
+       )  )
+
+        fputs( zNoPreset, option_usage_fp );
+
+    /*
+     *  Print the appearance requirements.
+     */
+    if (OPTST_GET_ARGTYPE(pOD->fOptState) == OPARG_TYPE_MEMBERSHIP)
+        fputs( zMembers, option_usage_fp );
+
+    else switch (pOD->optMinCt) {
+    case 1:
+    case 0:
+        switch (pOD->optMaxCt) {
+        case 0:       fputs( zPreset, option_usage_fp ); break;
+        case NOLIMIT: fputs( zNoLim, option_usage_fp );  break;
+        case 1:       break;
+            /*
+             * IF the max is more than one but limited, print "UP TO" message
+             */
+        default:      fprintf( option_usage_fp, zUpTo, pOD->optMaxCt );  break;
+        }
+        break;
+
+    default:
+        /*
+         *  More than one is required.  Print the range.
+         */
+        fprintf( option_usage_fp, zMust, pOD->optMinCt, pOD->optMaxCt );
+    }
+
+    if (  NAMED_OPTS( pOptions )
+       && (pOptions->specOptIdx.default_opt == pOD->optIndex))
+        fputs( zDefaultOpt, option_usage_fp );
+}
+
+
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ *
+ *   Figure out where all the initialization files might live.
+ *   This requires translating some environment variables and
+ *   testing to see if a name is a directory or a file.  It's
+ *   squishy, but important to tell users how to find these files.
+ */
+static void
+printInitList(
+    tCC**    papz,
+    ag_bool* pInitIntro,
+    tCC*     pzRc,
+    tCC*     pzPN )
+{
+    char zPath[ MAXPATHLEN+1 ];
+
+    if (papz == NULL)
+        return;
+
+    fputs( zPresetIntro, option_usage_fp );
+    *pInitIntro = AG_FALSE;
+
+    for (;;) {
+        const char* pzPath = *(papz++);
+
+        if (pzPath == NULL)
+            break;
+
+        if (optionMakePath( zPath, sizeof( zPath ), pzPath, pzPN ))
+            pzPath = zPath;
+
+        /*
+         *  Print the name of the "homerc" file.  If the "rcfile" name is
+         *  not empty, we may or may not print that, too...
+         */
+        fprintf( option_usage_fp, zPathFmt, pzPath );
+        if (*pzRc != NUL) {
+            struct stat sb;
+
+            /*
+             *  IF the "homerc" file is a directory,
+             *  then append the "rcfile" name.
+             */
+            if (  (stat( pzPath, &sb ) == 0)
+              &&  S_ISDIR( sb.st_mode ) ) {
+                fputc( '/', option_usage_fp );
+                fputs( pzRc, option_usage_fp );
+            }
+        }
+
+        fputc( '\n', option_usage_fp );
+    }
+}
+
+
+/*
+ *  Print the usage information for a single option.
+ */
+static void
+printOneUsage(
+    tOptions*     pOptions,
+    tOptDesc*     pOD,
+    arg_types_t*  pAT )
+{
+    /*
+     *  Flag prefix: IF no flags at all, then omit it.  If not printable
+     *  (not allowed for this option), then blank, else print it.
+     *  Follow it with a comma if we are doing GNU usage and long
+     *  opts are to be printed too.
+     */
+    if ((pOptions->fOptSet & OPTPROC_SHORTOPT) == 0)
+        fputs( pAT->pzSpc, option_usage_fp );
+    else if (! isgraph( pOD->optValue)) {
+        if (  (pOptions->fOptSet & (OPTPROC_GNUUSAGE|OPTPROC_LONGOPT))
+           == (OPTPROC_GNUUSAGE|OPTPROC_LONGOPT))
+            fputc( ' ', option_usage_fp );
+        fputs( pAT->pzNoF, option_usage_fp );
+    } else {
+        fprintf( option_usage_fp, "   -%c", pOD->optValue );
+        if (  (pOptions->fOptSet & (OPTPROC_GNUUSAGE|OPTPROC_LONGOPT))
+           == (OPTPROC_GNUUSAGE|OPTPROC_LONGOPT))
+            fputs( ", ", option_usage_fp );
+    }
+
+    {
+        char  z[ 80 ];
+        tCC*  pzArgType;
+        /*
+         *  Determine the argument type string first on its usage, then,
+         *  when the option argument is required, base the type string on the
+         *  argument type.
+         */
+        if (OPTST_GET_ARGTYPE(pOD->fOptState) == OPARG_TYPE_NONE) {
+            pzArgType = pAT->pzNo;
+
+        } else if (pOD->fOptState & OPTST_ARG_OPTIONAL) {
+            pzArgType = pAT->pzOpt;
+
+        } else switch (OPTST_GET_ARGTYPE(pOD->fOptState)) {
+        case OPARG_TYPE_ENUMERATION: pzArgType = pAT->pzKey;  break;
+        case OPARG_TYPE_MEMBERSHIP:  pzArgType = pAT->pzKeyL; break;
+        case OPARG_TYPE_BOOLEAN:     pzArgType = pAT->pzBool; break;
+        case OPARG_TYPE_NUMERIC:     pzArgType = pAT->pzNum;  break;
+        case OPARG_TYPE_HIERARCHY:   pzArgType = pAT->pzNest; break;
+        case OPARG_TYPE_STRING:      pzArgType = pAT->pzStr;  break;
+        default:                     goto bogus_desc;         break;
+        }
+
+        snprintf( z, sizeof(z), pAT->pzOptFmt, pzArgType, pOD->pz_Name,
+                  (pOD->optMinCt != 0) ? pAT->pzReq : pAT->pzOpt );
+
+        fprintf( option_usage_fp, zOptFmtLine, z, pOD->pzText );
+
+        switch (OPTST_GET_ARGTYPE(pOD->fOptState)) {
+        case OPARG_TYPE_ENUMERATION:
+        case OPARG_TYPE_MEMBERSHIP:
+            displayEnum = (pOD->pOptProc != NULL) ? AG_TRUE : displayEnum;
+        }
+    }
+    return;
+
+ bogus_desc:
+    fprintf( stderr, zInvalOptDesc, pOD->pz_Name );
+    exit( EXIT_FAILURE );
+}
+
+
+/*
+ *  Print out the usage information for just the options.
+ */
+static void
+printOptionUsage(
+    tOptions* pOpts,
+    int       ex_code,
+    tCC*      pOptTitle )
+{
+    int        ct     = pOpts->optCt;
+    int        optNo  = 0;
+    tOptDesc*  pOD    = pOpts->pOptDesc;
+    int        docCt  = 0;
+
+    do  {
+        if ((pOD->fOptState & OPTST_OMITTED) != 0)
+            continue;
+
+        if ((pOD->fOptState & OPTST_DOCUMENT) != 0) {
+            if (ex_code == EXIT_SUCCESS) {
+                fprintf(option_usage_fp, argTypes.pzBrk, pOD->pzText,
+                        pOptTitle);
+                docCt++;
+            }
+
+            continue;
+        }
+
+        /*
+         *  IF       this is the first auto-opt maintained option
+         *    *AND*  we are doing a full help
+         *    *AND*  there are documentation options
+         *    *AND*  the last one was not a doc option,
+         *  THEN document that the remaining options are not user opts
+         */
+        if (  (pOpts->presetOptCt == optNo)
+              && (ex_code == EXIT_SUCCESS)
+              && (docCt > 0)
+              && ((pOD[-1].fOptState & OPTST_DOCUMENT) == 0) )
+            fprintf( option_usage_fp, argTypes.pzBrk, zAuto, pOptTitle );
+
+        printOneUsage( pOpts, pOD, &argTypes );
+
+        /*
+         *  IF we were invoked because of the --help option,
+         *  THEN print all the extra info
+         */
+        if (ex_code == EXIT_SUCCESS)
+            printExtendedUsage( pOpts, pOD, &argTypes );
+
+    }  while (pOD++, optNo++, (--ct > 0));
+
+    fputc( '\n', option_usage_fp );
+}
+
+
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ *
+ *   PROGRAM DETAILS
+ */
+static void
+printProgramDetails( tOptions* pOptions )
+{
+    ag_bool  initIntro = AG_TRUE;
+
+    /*
+     *  Display all the places we look for config files
+     */
+    printInitList( pOptions->papzHomeList, &initIntro,
+                   pOptions->pzRcName, pOptions->pzProgPath );
+
+    /*
+     *  Let the user know about environment variable settings
+     */
+    if ((pOptions->fOptSet & OPTPROC_ENVIRON) != 0) {
+        if (initIntro)
+            fputs( zPresetIntro, option_usage_fp );
+
+        fprintf( option_usage_fp, zExamineFmt, pOptions->pzPROGNAME );
+    }
+
+    /*
+     *  IF we found an enumeration,
+     *  THEN hunt for it again.  Call the handler proc with a NULL
+     *       option struct pointer.  That tells it to display the keywords.
+     */
+    if (displayEnum) {
+        int        ct     = pOptions->optCt;
+        int        optNo  = 0;
+        tOptDesc*  pOD    = pOptions->pOptDesc;
+
+        fputc( '\n', option_usage_fp );
+        fflush( option_usage_fp );
+        do  {
+            switch (OPTST_GET_ARGTYPE(pOD->fOptState)) {
+            case OPARG_TYPE_ENUMERATION:
+            case OPARG_TYPE_MEMBERSHIP:
+                (*(pOD->pOptProc))( NULL, pOD );
+            }
+        }  while (pOD++, optNo++, (--ct > 0));
+    }
+
+    /*
+     *  If there is a detail string, now is the time for that.
+     */
+    if (pOptions->pzDetail != NULL)
+        fputs( pOptions->pzDetail, option_usage_fp );
+}
+
+
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ *
+ *   OPTION LINE FORMATTING SETUP
+ *
+ *  The "OptFmt" formats receive three arguments:
+ *  1.  the type of the option's argument
+ *  2.  the long name of the option
+ *  3.  "YES" or "no ", depending on whether or not the option must appear
+ *      on the command line.
+ *  These formats are used immediately after the option flag (if used) has
+ *  been printed.
+ *
+ *  Set up the formatting for GNU-style output
+ */
+static int
+setGnuOptFmts( tOptions* pOpts, tCC** ppT )
+{
+    int  flen = 22;
+    *ppT = zNoRq_ShrtTtl;
+
+    argTypes.pzStr  = zGnuStrArg;
+    argTypes.pzReq  = zOneSpace;
+    argTypes.pzNum  = zGnuNumArg;
+    argTypes.pzKey  = zGnuKeyArg;
+    argTypes.pzKeyL = zGnuKeyLArg;
+    argTypes.pzBool = zGnuBoolArg;
+    argTypes.pzNest = zGnuNestArg;
+    argTypes.pzOpt  = zGnuOptArg;
+    argTypes.pzNo   = zOneSpace;
+    argTypes.pzBrk  = zGnuBreak;
+    argTypes.pzNoF  = zSixSpaces;
+    argTypes.pzSpc  = zThreeSpaces;
+
+    switch (pOpts->fOptSet & OPTPROC_L_N_S) {
+    case OPTPROC_L_N_S:    argTypes.pzOptFmt = zGnuOptFmt;     break;
+    case OPTPROC_LONGOPT:  argTypes.pzOptFmt = zGnuOptFmt;     break;
+    case 0:                argTypes.pzOptFmt = zGnuOptFmt + 2; break;
+    case OPTPROC_SHORTOPT:
+        argTypes.pzOptFmt = zShrtGnuOptFmt;
+        zGnuStrArg[0] = zGnuNumArg[0] = zGnuKeyArg[0] = zGnuBoolArg[0] = ' ';
+        argTypes.pzOpt = " [arg]";
+        flen = 8;
+        break;
+    }
+
+    return flen;
+}
+
+
+/*
+ *  Standard (AutoOpts normal) option line formatting
+ */
+static int
+setStdOptFmts( tOptions* pOpts, tCC** ppT )
+{
+    int  flen = 0;
+
+    argTypes.pzStr  = zStdStrArg;
+    argTypes.pzReq  = zStdReqArg;
+    argTypes.pzNum  = zStdNumArg;
+    argTypes.pzKey  = zStdKeyArg;
+    argTypes.pzKeyL = zStdKeyLArg;
+    argTypes.pzBool = zStdBoolArg;
+    argTypes.pzNest = zStdNestArg;
+    argTypes.pzOpt  = zStdOptArg;
+    argTypes.pzNo   = zStdNoArg;
+    argTypes.pzBrk  = zStdBreak;
+    argTypes.pzNoF  = zFiveSpaces;
+    argTypes.pzSpc  = zTwoSpaces;
+
+    switch (pOpts->fOptSet & (OPTPROC_NO_REQ_OPT | OPTPROC_SHORTOPT)) {
+    case (OPTPROC_NO_REQ_OPT | OPTPROC_SHORTOPT):
+        *ppT = zNoRq_ShrtTtl;
+        argTypes.pzOptFmt = zNrmOptFmt;
+        flen = 19;
+        break;
+
+    case OPTPROC_NO_REQ_OPT:
+        *ppT = zNoRq_NoShrtTtl;
+        argTypes.pzOptFmt = zNrmOptFmt;
+        flen = 19;
+        break;
+
+    case OPTPROC_SHORTOPT:
+        *ppT = zReq_ShrtTtl;
+        argTypes.pzOptFmt = zReqOptFmt;
+        flen = 24;
+        break;
+
+    case 0:
+        *ppT = zReq_NoShrtTtl;
+        argTypes.pzOptFmt = zReqOptFmt;
+        flen = 24;
+    }
+
+    return flen;
+}
+
+
+/*:
+ * Local Variables:
+ * mode: C
+ * c-file-style: "stroustrup"
+ * tab-width: 4
+ * indent-tabs-mode: nil
+ * End:
+ * end of autoopts/usage.c */
diff --git a/libopts/version.c b/libopts/version.c
new file mode 100644 (file)
index 0000000..ede9173
--- /dev/null
@@ -0,0 +1,181 @@
+
+/*  $Id: version.c,v 4.7 2006/03/25 19:24:57 bkorb Exp $
+ * Time-stamp:      "2005-12-13 10:29:09 bkorb"
+ *
+ *  This module implements the default usage procedure for
+ *  Automated Options.  It may be overridden, of course.
+ */
+
+static const char zAOV[] =
+    "Automated Options version %s, copyright (c) 1999-2006 Bruce Korb\n";
+
+/*  Automated Options is free software.
+ *  You may redistribute it and/or modify it under the terms of the
+ *  GNU General Public License, as published by the Free Software
+ *  Foundation; either version 2, or (at your option) any later version.
+ *
+ *  Automated Options is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with Automated Options.  See the file "COPYING".  If not,
+ *  write to:  The Free Software Foundation, Inc.,
+ *             51 Franklin Street, Fifth Floor,
+ *             Boston, MA  02110-1301, USA.
+ *
+ * As a special exception, Bruce Korb gives permission for additional
+ * uses of the text contained in his release of AutoOpts.
+ *
+ * The exception is that, if you link the AutoOpts library with other
+ * files to produce an executable, this does not by itself cause the
+ * resulting executable to be covered by the GNU General Public License.
+ * Your use of that executable is in no way restricted on account of
+ * linking the AutoOpts library code into it.
+ *
+ * This exception does not however invalidate any other reasons why
+ * the executable file might be covered by the GNU General Public License.
+ *
+ * This exception applies only to the code released by Bruce Korb under
+ * the name AutoOpts.  If you copy code from other sources under the
+ * General Public License into a copy of AutoOpts, as the General Public
+ * License permits, the exception does not apply to the code that you add
+ * in this way.  To avoid misleading anyone as to the status of such
+ * modified files, you must delete this exception notice from them.
+ *
+ * If you write modifications of your own for AutoOpts, it is your choice
+ * whether to permit this exception to apply to your modifications.
+ * If you do not wish that, delete this exception notice.
+ */
+
+/* = = = START-STATIC-FORWARD = = = */
+/* static forward declarations maintained by :mkfwd */
+static void
+printVersion( tOptions* pOpts, tOptDesc* pOD, FILE* fp );
+/* = = = END-STATIC-FORWARD = = = */
+
+/*=export_func  optionVersion
+ *
+ * what:     return the compiled AutoOpts version number
+ * ret_type: const char*
+ * ret_desc: the version string in constant memory
+ * doc:
+ *  Returns the full version string compiled into the library.
+ *  The returned string cannot be modified.
+=*/
+const char*
+optionVersion( void )
+{
+    static const char zVersion[] =
+        STR( AO_CURRENT.AO_REVISION );
+
+    return zVersion;
+}
+
+
+static void
+printVersion( tOptions* pOpts, tOptDesc* pOD, FILE* fp )
+{
+    char swCh;
+
+    if (pOD->pzLastArg == NULL)
+         swCh = 'v';
+    else swCh = pOD->pzLastArg[0];
+
+    if (pOpts->pzFullVersion != NULL) {
+        fputs( pOpts->pzFullVersion, fp );
+        fputc( '\n', fp );
+
+    } else {
+        const char *pz = pOpts->pzUsageTitle;
+        do { fputc( *pz, fp ); } while (*(pz++) != '\n');
+    }
+
+    switch (swCh) {
+    case NUL:
+    case 'v':
+    case 'V':
+        break;
+
+    case 'c':
+    case 'C':
+        if (pOpts->pzCopyright != NULL) {
+            fputs( pOpts->pzCopyright, fp );
+            fputc( '\n', fp );
+        }
+        fprintf( fp, zAOV, optionVersion() );
+        if (pOpts->pzBugAddr != NULL)
+            fprintf( fp, zPlsSendBugs, pOpts->pzBugAddr );
+        break;
+
+    case 'n':
+    case 'N':
+        if (pOpts->pzCopyright != NULL) {
+            fputs( pOpts->pzCopyright, fp );
+            fputc( '\n', fp );
+            fputc( '\n', fp );
+        }
+
+        if (pOpts->pzCopyNotice != NULL) {
+            fputs( pOpts->pzCopyNotice, fp );
+            fputc( '\n', fp );
+        }
+
+        fprintf( fp, zAOV, optionVersion() );
+        if (pOpts->pzBugAddr != NULL)
+            fprintf( fp, zPlsSendBugs, pOpts->pzBugAddr );
+        break;
+
+    default:
+        fprintf( stderr, zBadVerArg, swCh );
+        exit( EXIT_FAILURE );
+    }
+
+    exit( EXIT_SUCCESS );
+}
+
+/*=export_func  optionPrintVersion
+ * private:
+ *
+ * what:  Print the program version
+ * arg:   + tOptions* + pOpts    + program options descriptor +
+ * arg:   + tOptDesc* + pOptDesc + the descriptor for this arg +
+ *
+ * doc:
+ *  This routine will print the version to stdout.
+=*/
+void
+optionPrintVersion( pOpts, pOD )
+    tOptions*  pOpts;
+    tOptDesc*  pOD;
+{
+    printVersion( pOpts, pOD, stdout );
+}
+
+/*=export_func  optionVersionStderr
+ * private:
+ *
+ * what:  Print the program version to stderr
+ * arg:   + tOptions* + pOpts    + program options descriptor +
+ * arg:   + tOptDesc* + pOptDesc + the descriptor for this arg +
+ *
+ * doc:
+ *  This routine will print the version to stderr.
+=*/
+void
+optionVersionStderr( pOpts, pOD )
+    tOptions*  pOpts;
+    tOptDesc*  pOD;
+{
+    printVersion( pOpts, pOD, stderr );
+}
+
+/*
+ * Local Variables:
+ * mode: C
+ * c-file-style: "stroustrup"
+ * tab-width: 4
+ * indent-tabs-mode: nil
+ * End:
+ * end of autoopts/version.c */
diff --git a/ntpd/ntpd-opts.c b/ntpd/ntpd-opts.c
new file mode 100644 (file)
index 0000000..98df11c
--- /dev/null
@@ -0,0 +1,975 @@
+/*   -*- buffer-read-only: t -*- vi: set ro:
+ *  
+ *  DO NOT EDIT THIS FILE   (ntpd-opts.c)
+ *  
+ *  It has been AutoGen-ed  Tuesday June 27, 2006 at 10:16:47 PM EDT
+ *  From the definitions    ntpd-opts.def
+ *  and the template file   options
+ */
+
+#define OPTION_CODE_COMPILE 1
+#include "ntpd-opts.h"
+
+#ifdef  __cplusplus
+extern "C" {
+#endif
+tSCC zCopyright[] =
+       "ntpd copyright (c) 1970-2006 ntp.org, all rights reserved";
+tSCC zCopyrightNotice[] =
+       
+/* extracted from /backroom/ntp-dev-hms/include/copyright.def near line 8 */
+"see html/copyright.html";
+extern tUsageProc optionUsage;
+
+/*
+ *  global included definitions
+ */
+#ifdef __windows
+  extern int atoi(const char*);
+#else
+# include <stdlib.h>
+#endif
+
+#ifndef NULL
+#  define NULL 0
+#endif
+#ifndef EXIT_SUCCESS
+#  define  EXIT_SUCCESS 0
+#endif
+#ifndef EXIT_FAILURE
+#  define  EXIT_FAILURE 1
+#endif
+/*
+ *  Ipv4 option description:
+ */
+tSCC    zIpv4Text[] =
+        "Force IPv4 DNS name resolution";
+tSCC    zIpv4_NAME[]               = "IPV4";
+tSCC    zIpv4_Name[]               = "ipv4";
+#define IPV4_FLAGS       (OPTST_DISABLED)
+
+/*
+ *  Ipv6 option description:
+ */
+tSCC    zIpv6Text[] =
+        "Force IPv6 DNS name resolution";
+tSCC    zIpv6_NAME[]               = "IPV6";
+tSCC    zIpv6_Name[]               = "ipv6";
+#define IPV6_FLAGS       (OPTST_DISABLED)
+
+/*
+ *  Authreq option description with
+ *  "Must also have options" and "Incompatible options":
+ */
+tSCC    zAuthreqText[] =
+        "Require crypto authentication";
+tSCC    zAuthreq_NAME[]            = "AUTHREQ";
+tSCC    zAuthreq_Name[]            = "authreq";
+static const int
+    aAuthreqCantList[] = {
+    INDEX_OPT_AUTHNOREQ, NO_EQUIVALENT };
+#define AUTHREQ_FLAGS       (OPTST_DISABLED)
+
+/*
+ *  Authnoreq option description with
+ *  "Must also have options" and "Incompatible options":
+ */
+tSCC    zAuthnoreqText[] =
+        "Do not require crypto authentication";
+tSCC    zAuthnoreq_NAME[]          = "AUTHNOREQ";
+tSCC    zAuthnoreq_Name[]          = "authnoreq";
+static const int
+    aAuthnoreqCantList[] = {
+    INDEX_OPT_AUTHREQ, NO_EQUIVALENT };
+#define AUTHNOREQ_FLAGS       (OPTST_DISABLED)
+
+/*
+ *  Bcastsync option description:
+ */
+tSCC    zBcastsyncText[] =
+        "Allow us to sync to broadcast servers";
+tSCC    zBcastsync_NAME[]          = "BCASTSYNC";
+tSCC    zBcastsync_Name[]          = "bcastsync";
+#define BCASTSYNC_FLAGS       (OPTST_DISABLED)
+
+/*
+ *  Configfile option description:
+ */
+tSCC    zConfigfileText[] =
+        "configuration file name";
+tSCC    zConfigfile_NAME[]         = "CONFIGFILE";
+tSCC    zConfigfile_Name[]         = "configfile";
+#define CONFIGFILE_FLAGS       (OPTST_DISABLED \
+       | OPTST_SET_ARGTYPE(OPARG_TYPE_STRING))
+
+/*
+ *  Debug_Level option description:
+ */
+tSCC    zDebug_LevelText[] =
+        "Increase output debug message level";
+tSCC    zDebug_Level_NAME[]        = "DEBUG_LEVEL";
+tSCC    zDebug_Level_Name[]        = "debug-level";
+#define DEBUG_LEVEL_FLAGS       (OPTST_DISABLED)
+
+/*
+ *  Set_Debug_Level option description:
+ */
+tSCC    zSet_Debug_LevelText[] =
+        "Set the output debug message level";
+tSCC    zSet_Debug_Level_NAME[]    = "SET_DEBUG_LEVEL";
+tSCC    zSet_Debug_Level_Name[]    = "set-debug-level";
+#define SET_DEBUG_LEVEL_FLAGS       (OPTST_DISABLED \
+       | OPTST_SET_ARGTYPE(OPARG_TYPE_STRING))
+
+/*
+ *  Driftfile option description:
+ */
+tSCC    zDriftfileText[] =
+        "frequency drift file name";
+tSCC    zDriftfile_NAME[]          = "DRIFTFILE";
+tSCC    zDriftfile_Name[]          = "driftfile";
+#define DRIFTFILE_FLAGS       (OPTST_DISABLED \
+       | OPTST_SET_ARGTYPE(OPARG_TYPE_STRING))
+
+/*
+ *  Panicgate option description:
+ */
+tSCC    zPanicgateText[] =
+        "Allow the first adjustment to be Big";
+tSCC    zPanicgate_NAME[]          = "PANICGATE";
+tSCC    zPanicgate_Name[]          = "panicgate";
+#define PANICGATE_FLAGS       (OPTST_DISABLED)
+
+/*
+ *  Jaildir option description:
+ */
+tSCC    zJaildirText[] =
+        "Jail directory";
+tSCC    zJaildir_NAME[]            = "JAILDIR";
+tSCC    zJaildir_Name[]            = "jaildir";
+#define JAILDIR_FLAGS       (OPTST_DISABLED \
+       | OPTST_SET_ARGTYPE(OPARG_TYPE_STRING))
+
+/*
+ *  Interface option description:
+ */
+tSCC    zInterfaceText[] =
+        "Listen on interface";
+tSCC    zInterface_NAME[]          = "INTERFACE";
+tSCC    zInterface_Name[]          = "interface";
+#define INTERFACE_FLAGS       (OPTST_DISABLED | OPTST_STACKED \
+       | OPTST_SET_ARGTYPE(OPARG_TYPE_STRING))
+
+/*
+ *  Keyfile option description:
+ */
+tSCC    zKeyfileText[] =
+        "path to symmetric keys";
+tSCC    zKeyfile_NAME[]            = "KEYFILE";
+tSCC    zKeyfile_Name[]            = "keyfile";
+#define KEYFILE_FLAGS       (OPTST_DISABLED \
+       | OPTST_SET_ARGTYPE(OPARG_TYPE_STRING))
+
+/*
+ *  Logfile option description:
+ */
+tSCC    zLogfileText[] =
+        "path to the log file";
+tSCC    zLogfile_NAME[]            = "LOGFILE";
+tSCC    zLogfile_Name[]            = "logfile";
+#define LOGFILE_FLAGS       (OPTST_DISABLED \
+       | OPTST_SET_ARGTYPE(OPARG_TYPE_STRING))
+
+/*
+ *  Novirtualips option description:
+ */
+tSCC    zNovirtualipsText[] =
+        "Do not listen to virtual IPs";
+tSCC    zNovirtualips_NAME[]       = "NOVIRTUALIPS";
+tSCC    zNovirtualips_Name[]       = "novirtualips";
+#define NOVIRTUALIPS_FLAGS       (OPTST_DISABLED)
+
+/*
+ *  Nofork option description:
+ */
+tSCC    zNoforkText[] =
+        "Do not fork";
+tSCC    zNofork_NAME[]             = "NOFORK";
+tSCC    zNofork_Name[]             = "nofork";
+#define NOFORK_FLAGS       (OPTST_DISABLED)
+
+/*
+ *  Nice option description:
+ */
+tSCC    zNiceText[] =
+        "Run at high priority";
+tSCC    zNice_NAME[]               = "NICE";
+tSCC    zNice_Name[]               = "nice";
+#define NICE_FLAGS       (OPTST_DISABLED)
+
+/*
+ *  Pidfile option description:
+ */
+tSCC    zPidfileText[] =
+        "path to the PID file";
+tSCC    zPidfile_NAME[]            = "PIDFILE";
+tSCC    zPidfile_Name[]            = "pidfile";
+#define PIDFILE_FLAGS       (OPTST_DISABLED \
+       | OPTST_SET_ARGTYPE(OPARG_TYPE_STRING))
+
+/*
+ *  Priority option description:
+ */
+tSCC    zPriorityText[] =
+        "Process priority";
+tSCC    zPriority_NAME[]           = "PRIORITY";
+tSCC    zPriority_Name[]           = "priority";
+#define PRIORITY_FLAGS       (OPTST_DISABLED \
+       | OPTST_SET_ARGTYPE(OPARG_TYPE_NUMERIC))
+
+/*
+ *  Quit option description:
+ */
+tSCC    zQuitText[] =
+        "Set the time and quit";
+tSCC    zQuit_NAME[]               = "QUIT";
+tSCC    zQuit_Name[]               = "quit";
+#define QUIT_FLAGS       (OPTST_DISABLED)
+
+/*
+ *  Propagationdelay option description:
+ */
+tSCC    zPropagationdelayText[] =
+        "Broadcast/propagation delay";
+tSCC    zPropagationdelay_NAME[]   = "PROPAGATIONDELAY";
+tSCC    zPropagationdelay_Name[]   = "propagationdelay";
+#define PROPAGATIONDELAY_FLAGS       (OPTST_DISABLED \
+       | OPTST_SET_ARGTYPE(OPARG_TYPE_STRING))
+
+/*
+ *  Updateinterval option description:
+ */
+tSCC    zUpdateintervalText[] =
+        "interval in seconds between scans for new or dropped interfaces";
+tSCC    zUpdateinterval_NAME[]     = "UPDATEINTERVAL";
+tSCC    zUpdateinterval_Name[]     = "updateinterval";
+#define UPDATEINTERVAL_FLAGS       (OPTST_DISABLED \
+       | OPTST_SET_ARGTYPE(OPARG_TYPE_NUMERIC))
+
+/*
+ *  Statsdir option description:
+ */
+tSCC    zStatsdirText[] =
+        "Statistics file location";
+tSCC    zStatsdir_NAME[]           = "STATSDIR";
+tSCC    zStatsdir_Name[]           = "statsdir";
+#define STATSDIR_FLAGS       (OPTST_DISABLED \
+       | OPTST_SET_ARGTYPE(OPARG_TYPE_STRING))
+
+/*
+ *  Trustedkey option description:
+ */
+tSCC    zTrustedkeyText[] =
+        "Trusted key number";
+tSCC    zTrustedkey_NAME[]         = "TRUSTEDKEY";
+tSCC    zTrustedkey_Name[]         = "trustedkey";
+#define TRUSTEDKEY_FLAGS       (OPTST_DISABLED | OPTST_STACKED \
+       | OPTST_SET_ARGTYPE(OPARG_TYPE_STRING))
+
+/*
+ *  User option description:
+ */
+tSCC    zUserText[] =
+        "Run as userid (or userid:groupid)";
+tSCC    zUser_NAME[]               = "USER";
+tSCC    zUser_Name[]               = "user";
+#define USER_FLAGS       (OPTST_DISABLED \
+       | OPTST_SET_ARGTYPE(OPARG_TYPE_STRING))
+
+/*
+ *  Var option description:
+ */
+tSCC    zVarText[] =
+        "make ARG an ntp variable (RW)";
+tSCC    zVar_NAME[]                = "VAR";
+tSCC    zVar_Name[]                = "var";
+#define VAR_FLAGS       (OPTST_DISABLED | OPTST_STACKED \
+       | OPTST_SET_ARGTYPE(OPARG_TYPE_STRING))
+
+/*
+ *  Dvar option description:
+ */
+tSCC    zDvarText[] =
+        "make ARG an ntp variable (RW|DEF)";
+tSCC    zDvar_NAME[]               = "DVAR";
+tSCC    zDvar_Name[]               = "dvar";
+#define DVAR_FLAGS       (OPTST_DISABLED | OPTST_STACKED \
+       | OPTST_SET_ARGTYPE(OPARG_TYPE_STRING))
+
+/*
+ *  Slew option description:
+ */
+tSCC    zSlewText[] =
+        "Slew up to 600 seconds";
+tSCC    zSlew_NAME[]               = "SLEW";
+tSCC    zSlew_Name[]               = "slew";
+#define SLEW_FLAGS       (OPTST_DISABLED \
+       | OPTST_SET_ARGTYPE(OPARG_TYPE_STRING))
+
+/*
+ *  Help/More_Help/Version option descriptions:
+ */
+tSCC zHelpText[]       = "Display usage information and exit";
+tSCC zHelp_Name[]      = "help";
+
+tSCC zMore_HelpText[]  = "Extended usage information passed thru pager";
+tSCC zMore_Help_Name[] = "more-help";
+
+tSCC zVersionText[]    = "Output version information and exit";
+tSCC zVersion_Name[]   = "version";
+
+/*
+ *  Save/Load_Opts option description:
+ */
+tSCC zSave_OptsText[]     = "Save the option state to a config file";
+tSCC zSave_Opts_Name[]    = "save-opts";
+
+tSCC zLoad_OptsText[]     = "Load options from a config file";
+tSCC zLoad_Opts_NAME[]    = "LOAD_OPTS";
+
+tSCC zNotLoad_Opts_Name[] = "no-load-opts";
+tSCC zNotLoad_Opts_Pfx[]  = "no";
+#define zLoad_Opts_Name   (zNotLoad_Opts_Name + 3)
+/*
+ *  Declare option callback procedures
+ */
+/* extracted from optmain.tpl near line 586 */
+
+#if defined(TEST_NTPD_OPTS)
+/*
+ *  Under test, omit argument processing, or call optionStackArg,
+ *  if multiple copies are allowed.
+ */
+extern tOptProc
+    optionNumericVal,    optionPagedUsage,    optionStackArg,
+    optionVersionStderr;
+static tOptProc
+    doUsageOpt;
+
+/*
+ *  #define map the "normal" callout procs to the test ones...
+ */
+#define SET_DEBUG_LEVEL_OPT_PROC optionStackArg
+
+
+#else /* NOT defined TEST_NTPD_OPTS */
+/*
+ *  When not under test, there are different procs to use
+ */
+extern tOptProc
+    optionNumericVal, optionPagedUsage, optionPrintVersion, optionStackArg;
+static tOptProc
+    doOptSet_Debug_Level, doUsageOpt;
+
+/*
+ *  #define map the "normal" callout procs
+ */
+#define SET_DEBUG_LEVEL_OPT_PROC doOptSet_Debug_Level
+
+#define SET_DEBUG_LEVEL_OPT_PROC doOptSet_Debug_Level
+#endif /* defined(TEST_NTPD_OPTS) */
+#ifdef TEST_NTPD_OPTS
+# define DOVERPROC optionVersionStderr
+#else
+# define DOVERPROC optionPrintVersion
+#endif /* TEST_NTPD_OPTS */
+
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ *
+ *  Define the Ntpd Option Descriptions.
+ */
+static tOptDesc optDesc[ OPTION_CT ] = {
+  {  /* entry idx, value */ 0, VALUE_OPT_IPV4,
+     /* equiv idx, value */ NO_EQUIVALENT, 0,
+     /* equivalenced to  */ NO_EQUIVALENT,
+     /* min, max, act ct */ 0, 1, 0,
+     /* opt state flags  */ IPV4_FLAGS, 0,
+     /* last opt argumnt */ NULL,
+     /* arg list/cookie  */ NULL,
+     /* must/cannot opts */ NULL, NULL,
+     /* option proc      */ NULL,
+     /* desc, NAME, name */ zIpv4Text, zIpv4_NAME, zIpv4_Name,
+     /* disablement strs */ NULL, NULL },
+
+  {  /* entry idx, value */ 1, VALUE_OPT_IPV6,
+     /* equiv idx, value */ NOLIMIT, NOLIMIT,
+     /* equivalenced to  */ INDEX_OPT_IPV4,
+     /* min, max, act ct */ 0, 1, 0,
+     /* opt state flags  */ IPV6_FLAGS, 0,
+     /* last opt argumnt */ NULL,
+     /* arg list/cookie  */ NULL,
+     /* must/cannot opts */ NULL, NULL,
+     /* option proc      */ NULL,
+     /* desc, NAME, name */ zIpv6Text, zIpv6_NAME, zIpv6_Name,
+     /* disablement strs */ NULL, NULL },
+
+  {  /* entry idx, value */ 2, VALUE_OPT_AUTHREQ,
+     /* equiv idx, value */ 2, VALUE_OPT_AUTHREQ,
+     /* equivalenced to  */ NO_EQUIVALENT,
+     /* min, max, act ct */ 0, 1, 0,
+     /* opt state flags  */ AUTHREQ_FLAGS, 0,
+     /* last opt argumnt */ NULL,
+     /* arg list/cookie  */ NULL,
+     /* must/cannot opts */ NULL, aAuthreqCantList,
+     /* option proc      */ NULL,
+     /* desc, NAME, name */ zAuthreqText, zAuthreq_NAME, zAuthreq_Name,
+     /* disablement strs */ NULL, NULL },
+
+  {  /* entry idx, value */ 3, VALUE_OPT_AUTHNOREQ,
+     /* equiv idx, value */ 3, VALUE_OPT_AUTHNOREQ,
+     /* equivalenced to  */ NO_EQUIVALENT,
+     /* min, max, act ct */ 0, 1, 0,
+     /* opt state flags  */ AUTHNOREQ_FLAGS, 0,
+     /* last opt argumnt */ NULL,
+     /* arg list/cookie  */ NULL,
+     /* must/cannot opts */ NULL, aAuthnoreqCantList,
+     /* option proc      */ NULL,
+     /* desc, NAME, name */ zAuthnoreqText, zAuthnoreq_NAME, zAuthnoreq_Name,
+     /* disablement strs */ NULL, NULL },
+
+  {  /* entry idx, value */ 4, VALUE_OPT_BCASTSYNC,
+     /* equiv idx, value */ 4, VALUE_OPT_BCASTSYNC,
+     /* equivalenced to  */ NO_EQUIVALENT,
+     /* min, max, act ct */ 0, 1, 0,
+     /* opt state flags  */ BCASTSYNC_FLAGS, 0,
+     /* last opt argumnt */ NULL,
+     /* arg list/cookie  */ NULL,
+     /* must/cannot opts */ NULL, NULL,
+     /* option proc      */ NULL,
+     /* desc, NAME, name */ zBcastsyncText, zBcastsync_NAME, zBcastsync_Name,
+     /* disablement strs */ NULL, NULL },
+
+  {  /* entry idx, value */ 5, VALUE_OPT_CONFIGFILE,
+     /* equiv idx, value */ 5, VALUE_OPT_CONFIGFILE,
+     /* equivalenced to  */ NO_EQUIVALENT,
+     /* min, max, act ct */ 0, 1, 0,
+     /* opt state flags  */ CONFIGFILE_FLAGS, 0,
+     /* last opt argumnt */ NULL,
+     /* arg list/cookie  */ NULL,
+     /* must/cannot opts */ NULL, NULL,
+     /* option proc      */ NULL,
+     /* desc, NAME, name */ zConfigfileText, zConfigfile_NAME, zConfigfile_Name,
+     /* disablement strs */ NULL, NULL },
+
+  {  /* entry idx, value */ 6, VALUE_OPT_DEBUG_LEVEL,
+     /* equiv idx, value */ 6, VALUE_OPT_DEBUG_LEVEL,
+     /* equivalenced to  */ NO_EQUIVALENT,
+     /* min, max, act ct */ 0, NOLIMIT, 0,
+     /* opt state flags  */ DEBUG_LEVEL_FLAGS, 0,
+     /* last opt argumnt */ NULL,
+     /* arg list/cookie  */ NULL,
+     /* must/cannot opts */ NULL, NULL,
+     /* option proc      */ NULL,
+     /* desc, NAME, name */ zDebug_LevelText, zDebug_Level_NAME, zDebug_Level_Name,
+     /* disablement strs */ NULL, NULL },
+
+  {  /* entry idx, value */ 7, VALUE_OPT_SET_DEBUG_LEVEL,
+     /* equiv idx, value */ 7, VALUE_OPT_SET_DEBUG_LEVEL,
+     /* equivalenced to  */ NO_EQUIVALENT,
+     /* min, max, act ct */ 0, NOLIMIT, 0,
+     /* opt state flags  */ SET_DEBUG_LEVEL_FLAGS, 0,
+     /* last opt argumnt */ NULL,
+     /* arg list/cookie  */ NULL,
+     /* must/cannot opts */ NULL, NULL,
+     /* option proc      */ SET_DEBUG_LEVEL_OPT_PROC,
+     /* desc, NAME, name */ zSet_Debug_LevelText, zSet_Debug_Level_NAME, zSet_Debug_Level_Name,
+     /* disablement strs */ NULL, NULL },
+
+  {  /* entry idx, value */ 8, VALUE_OPT_DRIFTFILE,
+     /* equiv idx, value */ 8, VALUE_OPT_DRIFTFILE,
+     /* equivalenced to  */ NO_EQUIVALENT,
+     /* min, max, act ct */ 0, 1, 0,
+     /* opt state flags  */ DRIFTFILE_FLAGS, 0,
+     /* last opt argumnt */ NULL,
+     /* arg list/cookie  */ NULL,
+     /* must/cannot opts */ NULL, NULL,
+     /* option proc      */ NULL,
+     /* desc, NAME, name */ zDriftfileText, zDriftfile_NAME, zDriftfile_Name,
+     /* disablement strs */ NULL, NULL },
+
+  {  /* entry idx, value */ 9, VALUE_OPT_PANICGATE,
+     /* equiv idx, value */ 9, VALUE_OPT_PANICGATE,
+     /* equivalenced to  */ NO_EQUIVALENT,
+     /* min, max, act ct */ 0, 1, 0,
+     /* opt state flags  */ PANICGATE_FLAGS, 0,
+     /* last opt argumnt */ NULL,
+     /* arg list/cookie  */ NULL,
+     /* must/cannot opts */ NULL, NULL,
+     /* option proc      */ NULL,
+     /* desc, NAME, name */ zPanicgateText, zPanicgate_NAME, zPanicgate_Name,
+     /* disablement strs */ NULL, NULL },
+
+  {  /* entry idx, value */ 10, VALUE_OPT_JAILDIR,
+     /* equiv idx, value */ 10, VALUE_OPT_JAILDIR,
+     /* equivalenced to  */ NO_EQUIVALENT,
+     /* min, max, act ct */ 0, 1, 0,
+     /* opt state flags  */ JAILDIR_FLAGS, 0,
+     /* last opt argumnt */ NULL,
+     /* arg list/cookie  */ NULL,
+     /* must/cannot opts */ NULL, NULL,
+     /* option proc      */ NULL,
+     /* desc, NAME, name */ zJaildirText, zJaildir_NAME, zJaildir_Name,
+     /* disablement strs */ NULL, NULL },
+
+  {  /* entry idx, value */ 11, VALUE_OPT_INTERFACE,
+     /* equiv idx, value */ 11, VALUE_OPT_INTERFACE,
+     /* equivalenced to  */ NO_EQUIVALENT,
+     /* min, max, act ct */ 0, NOLIMIT, 0,
+     /* opt state flags  */ INTERFACE_FLAGS, 0,
+     /* last opt argumnt */ NULL,
+     /* arg list/cookie  */ NULL,
+     /* must/cannot opts */ NULL, NULL,
+     /* option proc      */ optionStackArg,
+     /* desc, NAME, name */ zInterfaceText, zInterface_NAME, zInterface_Name,
+     /* disablement strs */ NULL, NULL },
+
+  {  /* entry idx, value */ 12, VALUE_OPT_KEYFILE,
+     /* equiv idx, value */ 12, VALUE_OPT_KEYFILE,
+     /* equivalenced to  */ NO_EQUIVALENT,
+     /* min, max, act ct */ 0, 1, 0,
+     /* opt state flags  */ KEYFILE_FLAGS, 0,
+     /* last opt argumnt */ NULL,
+     /* arg list/cookie  */ NULL,
+     /* must/cannot opts */ NULL, NULL,
+     /* option proc      */ NULL,
+     /* desc, NAME, name */ zKeyfileText, zKeyfile_NAME, zKeyfile_Name,
+     /* disablement strs */ NULL, NULL },
+
+  {  /* entry idx, value */ 13, VALUE_OPT_LOGFILE,
+     /* equiv idx, value */ 13, VALUE_OPT_LOGFILE,
+     /* equivalenced to  */ NO_EQUIVALENT,
+     /* min, max, act ct */ 0, 1, 0,
+     /* opt state flags  */ LOGFILE_FLAGS, 0,
+     /* last opt argumnt */ NULL,
+     /* arg list/cookie  */ NULL,
+     /* must/cannot opts */ NULL, NULL,
+     /* option proc      */ NULL,
+     /* desc, NAME, name */ zLogfileText, zLogfile_NAME, zLogfile_Name,
+     /* disablement strs */ NULL, NULL },
+
+  {  /* entry idx, value */ 14, VALUE_OPT_NOVIRTUALIPS,
+     /* equiv idx, value */ 14, VALUE_OPT_NOVIRTUALIPS,
+     /* equivalenced to  */ NO_EQUIVALENT,
+     /* min, max, act ct */ 0, 1, 0,
+     /* opt state flags  */ NOVIRTUALIPS_FLAGS, 0,
+     /* last opt argumnt */ NULL,
+     /* arg list/cookie  */ NULL,
+     /* must/cannot opts */ NULL, NULL,
+     /* option proc      */ NULL,
+     /* desc, NAME, name */ zNovirtualipsText, zNovirtualips_NAME, zNovirtualips_Name,
+     /* disablement strs */ NULL, NULL },
+
+  {  /* entry idx, value */ 15, VALUE_OPT_NOFORK,
+     /* equiv idx, value */ 15, VALUE_OPT_NOFORK,
+     /* equivalenced to  */ NO_EQUIVALENT,
+     /* min, max, act ct */ 0, 1, 0,
+     /* opt state flags  */ NOFORK_FLAGS, 0,
+     /* last opt argumnt */ NULL,
+     /* arg list/cookie  */ NULL,
+     /* must/cannot opts */ NULL, NULL,
+     /* option proc      */ NULL,
+     /* desc, NAME, name */ zNoforkText, zNofork_NAME, zNofork_Name,
+     /* disablement strs */ NULL, NULL },
+
+  {  /* entry idx, value */ 16, VALUE_OPT_NICE,
+     /* equiv idx, value */ 16, VALUE_OPT_NICE,
+     /* equivalenced to  */ NO_EQUIVALENT,
+     /* min, max, act ct */ 0, 1, 0,
+     /* opt state flags  */ NICE_FLAGS, 0,
+     /* last opt argumnt */ NULL,
+     /* arg list/cookie  */ NULL,
+     /* must/cannot opts */ NULL, NULL,
+     /* option proc      */ NULL,
+     /* desc, NAME, name */ zNiceText, zNice_NAME, zNice_Name,
+     /* disablement strs */ NULL, NULL },
+
+  {  /* entry idx, value */ 17, VALUE_OPT_PIDFILE,
+     /* equiv idx, value */ 17, VALUE_OPT_PIDFILE,
+     /* equivalenced to  */ NO_EQUIVALENT,
+     /* min, max, act ct */ 0, 1, 0,
+     /* opt state flags  */ PIDFILE_FLAGS, 0,
+     /* last opt argumnt */ NULL,
+     /* arg list/cookie  */ NULL,
+     /* must/cannot opts */ NULL, NULL,
+     /* option proc      */ NULL,
+     /* desc, NAME, name */ zPidfileText, zPidfile_NAME, zPidfile_Name,
+     /* disablement strs */ NULL, NULL },
+
+  {  /* entry idx, value */ 18, VALUE_OPT_PRIORITY,
+     /* equiv idx, value */ 18, VALUE_OPT_PRIORITY,
+     /* equivalenced to  */ NO_EQUIVALENT,
+     /* min, max, act ct */ 0, 1, 0,
+     /* opt state flags  */ PRIORITY_FLAGS, 0,
+     /* last opt argumnt */ NULL,
+     /* arg list/cookie  */ NULL,
+     /* must/cannot opts */ NULL, NULL,
+     /* option proc      */ optionNumericVal,
+     /* desc, NAME, name */ zPriorityText, zPriority_NAME, zPriority_Name,
+     /* disablement strs */ NULL, NULL },
+
+  {  /* entry idx, value */ 19, VALUE_OPT_QUIT,
+     /* equiv idx, value */ 19, VALUE_OPT_QUIT,
+     /* equivalenced to  */ NO_EQUIVALENT,
+     /* min, max, act ct */ 0, 1, 0,
+     /* opt state flags  */ QUIT_FLAGS, 0,
+     /* last opt argumnt */ NULL,
+     /* arg list/cookie  */ NULL,
+     /* must/cannot opts */ NULL, NULL,
+     /* option proc      */ NULL,
+     /* desc, NAME, name */ zQuitText, zQuit_NAME, zQuit_Name,
+     /* disablement strs */ NULL, NULL },
+
+  {  /* entry idx, value */ 20, VALUE_OPT_PROPAGATIONDELAY,
+     /* equiv idx, value */ 20, VALUE_OPT_PROPAGATIONDELAY,
+     /* equivalenced to  */ NO_EQUIVALENT,
+     /* min, max, act ct */ 0, 1, 0,
+     /* opt state flags  */ PROPAGATIONDELAY_FLAGS, 0,
+     /* last opt argumnt */ NULL,
+     /* arg list/cookie  */ NULL,
+     /* must/cannot opts */ NULL, NULL,
+     /* option proc      */ NULL,
+     /* desc, NAME, name */ zPropagationdelayText, zPropagationdelay_NAME, zPropagationdelay_Name,
+     /* disablement strs */ NULL, NULL },
+
+  {  /* entry idx, value */ 21, VALUE_OPT_UPDATEINTERVAL,
+     /* equiv idx, value */ 21, VALUE_OPT_UPDATEINTERVAL,
+     /* equivalenced to  */ NO_EQUIVALENT,
+     /* min, max, act ct */ 0, 1, 0,
+     /* opt state flags  */ UPDATEINTERVAL_FLAGS, 0,
+     /* last opt argumnt */ NULL,
+     /* arg list/cookie  */ NULL,
+     /* must/cannot opts */ NULL, NULL,
+     /* option proc      */ optionNumericVal,
+     /* desc, NAME, name */ zUpdateintervalText, zUpdateinterval_NAME, zUpdateinterval_Name,
+     /* disablement strs */ NULL, NULL },
+
+  {  /* entry idx, value */ 22, VALUE_OPT_STATSDIR,
+     /* equiv idx, value */ 22, VALUE_OPT_STATSDIR,
+     /* equivalenced to  */ NO_EQUIVALENT,
+     /* min, max, act ct */ 0, 1, 0,
+     /* opt state flags  */ STATSDIR_FLAGS, 0,
+     /* last opt argumnt */ NULL,
+     /* arg list/cookie  */ NULL,
+     /* must/cannot opts */ NULL, NULL,
+     /* option proc      */ NULL,
+     /* desc, NAME, name */ zStatsdirText, zStatsdir_NAME, zStatsdir_Name,
+     /* disablement strs */ NULL, NULL },
+
+  {  /* entry idx, value */ 23, VALUE_OPT_TRUSTEDKEY,
+     /* equiv idx, value */ 23, VALUE_OPT_TRUSTEDKEY,
+     /* equivalenced to  */ NO_EQUIVALENT,
+     /* min, max, act ct */ 0, NOLIMIT, 0,
+     /* opt state flags  */ TRUSTEDKEY_FLAGS, 0,
+     /* last opt argumnt */ NULL,
+     /* arg list/cookie  */ NULL,
+     /* must/cannot opts */ NULL, NULL,
+     /* option proc      */ optionStackArg,
+     /* desc, NAME, name */ zTrustedkeyText, zTrustedkey_NAME, zTrustedkey_Name,
+     /* disablement strs */ NULL, NULL },
+
+  {  /* entry idx, value */ 24, VALUE_OPT_USER,
+     /* equiv idx, value */ 24, VALUE_OPT_USER,
+     /* equivalenced to  */ NO_EQUIVALENT,
+     /* min, max, act ct */ 0, 1, 0,
+     /* opt state flags  */ USER_FLAGS, 0,
+     /* last opt argumnt */ NULL,
+     /* arg list/cookie  */ NULL,
+     /* must/cannot opts */ NULL, NULL,
+     /* option proc      */ NULL,
+     /* desc, NAME, name */ zUserText, zUser_NAME, zUser_Name,
+     /* disablement strs */ NULL, NULL },
+
+  {  /* entry idx, value */ 25, VALUE_OPT_VAR,
+     /* equiv idx, value */ 25, VALUE_OPT_VAR,
+     /* equivalenced to  */ NO_EQUIVALENT,
+     /* min, max, act ct */ 0, NOLIMIT, 0,
+     /* opt state flags  */ VAR_FLAGS, 0,
+     /* last opt argumnt */ NULL,
+     /* arg list/cookie  */ NULL,
+     /* must/cannot opts */ NULL, NULL,
+     /* option proc      */ optionStackArg,
+     /* desc, NAME, name */ zVarText, zVar_NAME, zVar_Name,
+     /* disablement strs */ NULL, NULL },
+
+  {  /* entry idx, value */ 26, VALUE_OPT_DVAR,
+     /* equiv idx, value */ 26, VALUE_OPT_DVAR,
+     /* equivalenced to  */ NO_EQUIVALENT,
+     /* min, max, act ct */ 0, NOLIMIT, 0,
+     /* opt state flags  */ DVAR_FLAGS, 0,
+     /* last opt argumnt */ NULL,
+     /* arg list/cookie  */ NULL,
+     /* must/cannot opts */ NULL, NULL,
+     /* option proc      */ optionStackArg,
+     /* desc, NAME, name */ zDvarText, zDvar_NAME, zDvar_Name,
+     /* disablement strs */ NULL, NULL },
+
+  {  /* entry idx, value */ 27, VALUE_OPT_SLEW,
+     /* equiv idx, value */ 27, VALUE_OPT_SLEW,
+     /* equivalenced to  */ NO_EQUIVALENT,
+     /* min, max, act ct */ 0, 1, 0,
+     /* opt state flags  */ SLEW_FLAGS, 0,
+     /* last opt argumnt */ NULL,
+     /* arg list/cookie  */ NULL,
+     /* must/cannot opts */ NULL, NULL,
+     /* option proc      */ NULL,
+     /* desc, NAME, name */ zSlewText, zSlew_NAME, zSlew_Name,
+     /* disablement strs */ NULL, NULL },
+
+  {  /* entry idx, value */ INDEX_OPT_VERSION, VALUE_OPT_VERSION,
+     /* equiv idx value  */ NO_EQUIVALENT, 0,
+     /* equivalenced to  */ NO_EQUIVALENT,
+     /* min, max, act ct */ 0, 1, 0,
+     /* opt state flags  */ OPTST_SET_ARGTYPE(OPARG_TYPE_STRING)
+                          | OPTST_ARG_OPTIONAL, 0,
+     /* last opt argumnt */ NULL,
+     /* arg list/cookie  */ NULL,
+     /* must/cannot opts */ NULL, NULL,
+     /* option proc      */ DOVERPROC,
+     /* desc, NAME, name */ zVersionText, NULL, zVersion_Name,
+     /* disablement strs */ NULL, NULL },
+
+  {  /* entry idx, value */ INDEX_OPT_HELP, VALUE_OPT_HELP,
+     /* equiv idx value  */ NO_EQUIVALENT, 0,
+     /* equivalenced to  */ NO_EQUIVALENT,
+     /* min, max, act ct */ 0, 1, 0,
+     /* opt state flags  */ OPTST_IMM, 0,
+     /* last opt argumnt */ NULL,
+     /* arg list/cookie  */ NULL,
+     /* must/cannot opts */ NULL, NULL,
+     /* option proc      */ doUsageOpt,
+     /* desc, NAME, name */ zHelpText, NULL, zHelp_Name,
+     /* disablement strs */ NULL, NULL },
+
+  {  /* entry idx, value */ INDEX_OPT_MORE_HELP, VALUE_OPT_MORE_HELP,
+     /* equiv idx value  */ NO_EQUIVALENT, 0,
+     /* equivalenced to  */ NO_EQUIVALENT,
+     /* min, max, act ct */ 0, 1, 0,
+     /* opt state flags  */ OPTST_IMM, 0,
+     /* last opt argumnt */ NULL,
+     /* arg list/cookie  */ NULL,
+     /* must/cannot opts */ NULL,  NULL,
+     /* option proc      */ optionPagedUsage,
+     /* desc, NAME, name */ zMore_HelpText, NULL, zMore_Help_Name,
+     /* disablement strs */ NULL, NULL },
+
+  {  /* entry idx, value */ INDEX_OPT_SAVE_OPTS, VALUE_OPT_SAVE_OPTS,
+     /* equiv idx value  */ NO_EQUIVALENT, 0,
+     /* equivalenced to  */ NO_EQUIVALENT,
+     /* min, max, act ct */ 0, 1, 0,
+     /* opt state flags  */ OPTST_SET_ARGTYPE(OPARG_TYPE_STRING)
+                          | OPTST_ARG_OPTIONAL, 0,
+     /* last opt argumnt */ NULL,
+     /* arg list/cookie  */ NULL,
+     /* must/cannot opts */ NULL,  NULL,
+     /* option proc      */ NULL,
+     /* desc, NAME, name */ zSave_OptsText, NULL, zSave_Opts_Name,
+     /* disablement strs */ NULL, NULL },
+
+  {  /* entry idx, value */ INDEX_OPT_LOAD_OPTS, VALUE_OPT_LOAD_OPTS,
+     /* equiv idx value  */ NO_EQUIVALENT, 0,
+     /* equivalenced to  */ NO_EQUIVALENT,
+     /* min, max, act ct */ 0, NOLIMIT, 0,
+     /* opt state flags  */ OPTST_DISABLE_IMM | \
+                       OPTST_SET_ARGTYPE(OPARG_TYPE_STRING), 0,
+     /* last opt argumnt */ NULL,
+     /* arg list/cookie  */ NULL,
+     /* must/cannot opts */ NULL, NULL,
+     /* option proc      */ optionLoadOpt,
+     /* desc, NAME, name */ zLoad_OptsText, zLoad_Opts_NAME, zLoad_Opts_Name,
+     /* disablement strs */ zNotLoad_Opts_Name, zNotLoad_Opts_Pfx }
+};
+
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ *
+ *  Define the Ntpd Option Environment
+ */
+tSCC   zPROGNAME[]   = "NTPD";
+tSCC   zUsageTitle[] =
+"ntpd - NTP daemon program - Ver. 4.2.3p12\n\
+USAGE:  %s [ -<flag> [<val>] | --<name>[{=| }<val>] ]...\n";
+tSCC   zRcName[]     = ".ntprc";
+tSCC*  apzHomeList[] = {
+       "$HOME",
+       ".",
+       "$HOME",
+       ".",
+       NULL };
+
+tSCC   zBugsAddr[]    = "http://bugs.ntp.isc.org, bugs@ntp.org";
+#define zExplain NULL
+tSCC    zDetail[]     = "\n\n";
+tSCC    zFullVersion[] = NTPD_FULL_VERSION;
+/* extracted from optcode near line 321 */
+
+#if defined(ENABLE_NLS)
+# define OPTPROC_BASE OPTPROC_TRANSLATE
+  static tOptionXlateProc translate_option_strings;
+#else
+# define OPTPROC_BASE OPTPROC_NONE
+# define translate_option_strings NULL
+#endif /* ENABLE_NLS */
+
+tOptions ntpdOptions = {
+    OPTIONS_STRUCT_VERSION,
+    0, NULL,                    /* original argc + argv    */
+    ( OPTPROC_BASE
+    + OPTPROC_ERRSTOP
+    + OPTPROC_SHORTOPT
+    + OPTPROC_LONGOPT
+    + OPTPROC_NO_REQ_OPT
+    + OPTPROC_ENVIRON
+    + OPTPROC_NO_ARGS
+    + OPTPROC_HAS_IMMED ),
+    0, NULL,                    /* current option index, current option */
+    NULL,         NULL,         zPROGNAME,
+    zRcName,      zCopyright,   zCopyrightNotice,
+    zFullVersion, apzHomeList,  zUsageTitle,
+    zExplain,     zDetail,      optDesc,
+    zBugsAddr,                  /* address to send bugs to */
+    NULL, NULL,                 /* extensions/saved state  */
+    optionUsage,       /* usage procedure */
+    translate_option_strings,   /* translation procedure */
+    /*
+     *  Indexes to special options
+     */
+    { INDEX_OPT_MORE_HELP,
+      INDEX_OPT_SAVE_OPTS,
+      NO_EQUIVALENT /* index of '-#' option */,
+      NO_EQUIVALENT /* index of default opt */
+    },
+    OPTION_CT, 28 /* user option count */
+};
+
+/*
+ *  Create the static procedure(s) declared above.
+ */
+static void
+doUsageOpt(
+    tOptions*   pOptions,
+    tOptDesc*   pOptDesc )
+{
+    USAGE( EXIT_SUCCESS );
+}
+
+#if ! defined(TEST_NTPD_OPTS)
+
+/* * * * * * *
+ *
+ *   For the set-debug-level option.
+ */
+static void
+doOptSet_Debug_Level(
+    tOptions*   pOptions,
+    tOptDesc*   pOptDesc )
+{
+DESC(DEBUG_LEVEL).optOccCt = atoi( pOptDesc->pzLastArg );
+}
+
+#endif /* defined(TEST_NTPD_OPTS) */
+
+/* extracted from optmain.tpl near line 92 */
+
+#if defined(TEST_NTPD_OPTS) /* TEST MAIN PROCEDURE: */
+
+int
+main( int argc, char** argv )
+{
+    int res = EXIT_SUCCESS;
+    (void)optionProcess( &ntpdOptions, argc, argv );
+    {
+        void optionPutShell( tOptions* );
+        optionPutShell( &ntpdOptions );
+    }
+    return res;
+}
+#endif  /* defined TEST_NTPD_OPTS */
+/* extracted from optcode near line 418 */
+
+#if ENABLE_NLS
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+#include <autoopts/usage-txt.h>
+
+static char*
+AO_gettext( const char* pz )
+{
+    char* pzRes;
+    if (pz == NULL)
+        return NULL;
+    pzRes = _(pz);
+    if (pzRes == pz)
+        return pzRes;
+    pzRes = strdup( pzRes );
+    if (pzRes == NULL) {
+        fputs( _("No memory for duping translated strings\n"), stderr );
+        exit( EXIT_FAILURE );
+    }
+    return pzRes;
+}
+
+/*
+ *  This invokes the translation code (e.g. gettext(3)).
+ */
+static void
+translate_option_strings( void )
+{
+    /*
+     *  Guard against re-translation.  It won't work.  The strings will have
+     *  been changed by the first pass through this code.  One shot only.
+     */
+    if (option_usage_text.field_ct == 0)
+        return;
+    /*
+     *  Do the translations.  The first pointer follows the field count field.
+     *  The field count field is the size of a pointer.
+     */
+    {
+        char** ppz = (char**)(void*)&(option_usage_text);
+        int    ix  = option_usage_text.field_ct;
+
+        do {
+            ppz++;
+            *ppz = AO_gettext(*ppz);
+        } while (--ix > 0);
+    }
+    option_usage_text.field_ct = 0;
+
+    {
+        tOptDesc* pOD = ntpdOptions.pOptDesc;
+        int       ix  = ntpdOptions.optCt;
+
+        for (;;) {
+            pOD->pzText           = AO_gettext(pOD->pzText);
+            pOD->pz_NAME          = AO_gettext(pOD->pz_NAME);
+            pOD->pz_Name          = AO_gettext(pOD->pz_Name);
+            pOD->pz_DisableName   = AO_gettext(pOD->pz_DisableName);
+            pOD->pz_DisablePfx    = AO_gettext(pOD->pz_DisablePfx);
+            if (--ix <= 0)
+                break;
+            pOD++;
+        }
+    }
+    ntpdOptions.pzCopyright   = AO_gettext(ntpdOptions.pzCopyright);
+    ntpdOptions.pzCopyNotice  = AO_gettext(ntpdOptions.pzCopyNotice);
+    ntpdOptions.pzFullVersion = AO_gettext(ntpdOptions.pzFullVersion);
+    ntpdOptions.pzUsageTitle  = AO_gettext(ntpdOptions.pzUsageTitle);
+    ntpdOptions.pzExplain     = AO_gettext(ntpdOptions.pzExplain);
+    ntpdOptions.pzDetail      = AO_gettext(ntpdOptions.pzDetail);
+}
+
+#endif /* ENABLE_NLS */
+
+#ifdef  __cplusplus
+}
+#endif
diff --git a/ntpd/ntpd-opts.h b/ntpd/ntpd-opts.h
new file mode 100644 (file)
index 0000000..b415e3d
--- /dev/null
@@ -0,0 +1,193 @@
+/*   -*- buffer-read-only: t -*- vi: set ro:
+ *  
+ *  DO NOT EDIT THIS FILE   (ntpd-opts.h)
+ *  
+ *  It has been AutoGen-ed  Tuesday June 27, 2006 at 10:16:46 PM EDT
+ *  From the definitions    ntpd-opts.def
+ *  and the template file   options
+ */
+/*
+ *  This file contains the programmatic interface to the Automated
+ *  Options generated for the ntpd program.
+ *  These macros are documented in the AutoGen info file in the
+ *  "AutoOpts" chapter.  Please refer to that doc for usage help.
+ */
+#ifndef AUTOOPTS_NTPD_OPTS_H_GUARD
+#define AUTOOPTS_NTPD_OPTS_H_GUARD
+
+/*
+ * ntpd copyright 1970-2006 ntp.org - all rights reserved
+ *
+ * see html/copyright.html
+ */
+#include "config.h"
+#include <autoopts/options.h>
+
+/*
+ *  Ensure that the library used for compiling this generated header is at
+ *  least as new as the version current when the header template was released
+ *  (not counting patch version increments).  Also ensure that the oldest
+ *  tolerable version is at least as old as what was current when the header
+ *  template was released.
+ */
+#define AO_TEMPLATE_VERSION 110592
+#if (AO_TEMPLATE_VERSION < OPTIONS_MINIMUM_VERSION) \
+ || (AO_TEMPLATE_VERSION > OPTIONS_STRUCT_VERSION)
+# error option template version mismatches autoopts/options.h header
+#endif
+
+/*
+ *  Enumeration of each option:
+ */
+typedef enum {
+        INDEX_OPT_IPV4             =  0,
+        INDEX_OPT_IPV6             =  1,
+        INDEX_OPT_AUTHREQ          =  2,
+        INDEX_OPT_AUTHNOREQ        =  3,
+        INDEX_OPT_BCASTSYNC        =  4,
+        INDEX_OPT_CONFIGFILE       =  5,
+        INDEX_OPT_DEBUG_LEVEL      =  6,
+        INDEX_OPT_SET_DEBUG_LEVEL  =  7,
+        INDEX_OPT_DRIFTFILE        =  8,
+        INDEX_OPT_PANICGATE        =  9,
+        INDEX_OPT_JAILDIR          = 10,
+        INDEX_OPT_INTERFACE        = 11,
+        INDEX_OPT_KEYFILE          = 12,
+        INDEX_OPT_LOGFILE          = 13,
+        INDEX_OPT_NOVIRTUALIPS     = 14,
+        INDEX_OPT_NOFORK           = 15,
+        INDEX_OPT_NICE             = 16,
+        INDEX_OPT_PIDFILE          = 17,
+        INDEX_OPT_PRIORITY         = 18,
+        INDEX_OPT_QUIT             = 19,
+        INDEX_OPT_PROPAGATIONDELAY = 20,
+        INDEX_OPT_UPDATEINTERVAL   = 21,
+        INDEX_OPT_STATSDIR         = 22,
+        INDEX_OPT_TRUSTEDKEY       = 23,
+        INDEX_OPT_USER             = 24,
+        INDEX_OPT_VAR              = 25,
+        INDEX_OPT_DVAR             = 26,
+        INDEX_OPT_SLEW             = 27,
+        INDEX_OPT_VERSION          = 28,
+        INDEX_OPT_HELP             = 29,
+        INDEX_OPT_MORE_HELP        = 30,
+        INDEX_OPT_SAVE_OPTS        = 31,
+        INDEX_OPT_LOAD_OPTS        = 32
+} teOptIndex;
+
+#define OPTION_CT    33
+#define NTPD_VERSION       "4.2.3p12"
+#define NTPD_FULL_VERSION  "ntpd - NTP daemon program - Ver. 4.2.3p12"
+
+/*
+ *  Interface defines for all options.  Replace "n" with
+ *  the UPPER_CASED option name (as in the teOptIndex
+ *  enumeration above).  e.g. HAVE_OPT( IPV4 )
+ */
+#define        DESC(n) ntpdOptions.pOptDesc[INDEX_OPT_ ## n]
+#define     HAVE_OPT(n) (! UNUSED_OPT(& DESC(n)))
+#define      OPT_ARG(n) (DESC(n).pzLastArg)
+#define    STATE_OPT(n) (DESC(n).fOptState & OPTST_SET_MASK)
+#define    COUNT_OPT(n) (DESC(n).optOccCt)
+#define    ISSEL_OPT(n) (SELECTED_OPT(&DESC(n)))
+#define ISUNUSED_OPT(n) (UNUSED_OPT(& DESC(n)))
+#define  ENABLED_OPT(n) (! DISABLED_OPT(& DESC(n)))
+#define  STACKCT_OPT(n) (((tArgList*)(DESC(n).optCookie))->useCt)
+#define STACKLST_OPT(n) (((tArgList*)(DESC(n).optCookie))->apzArgs)
+#define    CLEAR_OPT(n) STMTS( \
+                DESC(n).fOptState &= OPTST_PERSISTENT;   \
+                if ( (DESC(n).fOptState & OPTST_INITENABLED) == 0) \
+                    DESC(n).fOptState |= OPTST_DISABLED; \
+                DESC(n).optCookie = NULL )
+
+/*
+ *  Interface defines for specific options.
+ */
+#define VALUE_OPT_IPV4           '4'
+#define WHICH_OPT_IPV4           (DESC(IPV4).optActualValue)
+#define WHICH_IDX_IPV4           (DESC(IPV4).optActualIndex)
+#define VALUE_OPT_IPV6           '6'
+#define VALUE_OPT_AUTHREQ        'a'
+#define VALUE_OPT_AUTHNOREQ      'A'
+#define VALUE_OPT_BCASTSYNC      'b'
+#define VALUE_OPT_CONFIGFILE     'c'
+#define VALUE_OPT_DEBUG_LEVEL    'd'
+#define VALUE_OPT_SET_DEBUG_LEVEL 'D'
+#define VALUE_OPT_DRIFTFILE      'f'
+#define VALUE_OPT_PANICGATE      'g'
+#define VALUE_OPT_JAILDIR        'i'
+#define VALUE_OPT_INTERFACE      'I'
+#define VALUE_OPT_KEYFILE        'k'
+#define VALUE_OPT_LOGFILE        'l'
+#define VALUE_OPT_NOVIRTUALIPS   'L'
+#define VALUE_OPT_NOFORK         'n'
+#define VALUE_OPT_NICE           'N'
+#define VALUE_OPT_PIDFILE        'p'
+#define VALUE_OPT_PRIORITY       'P'
+#define OPT_VALUE_PRIORITY       (*(unsigned long*)(&DESC(PRIORITY).pzLastArg))
+#define VALUE_OPT_QUIT           'q'
+#define VALUE_OPT_PROPAGATIONDELAY 'r'
+#define VALUE_OPT_UPDATEINTERVAL 'U'
+#define OPT_VALUE_UPDATEINTERVAL (*(unsigned long*)(&DESC(UPDATEINTERVAL).pzLastArg))
+#define VALUE_OPT_STATSDIR       's'
+#define VALUE_OPT_TRUSTEDKEY     't'
+#define VALUE_OPT_USER           'u'
+#define VALUE_OPT_VAR            'v'
+#define VALUE_OPT_DVAR           'V'
+#define VALUE_OPT_SLEW           'x'
+
+#define VALUE_OPT_VERSION       'v'
+#define VALUE_OPT_SAVE_OPTS     '>'
+#define VALUE_OPT_LOAD_OPTS     '<'
+#define VALUE_OPT_HELP          '?'
+#define VALUE_OPT_MORE_HELP     '!'
+#define SET_OPT_SAVE_OPTS(a)   STMTS( \
+        DESC(SAVE_OPTS).fOptState &= OPTST_PERSISTENT; \
+        DESC(SAVE_OPTS).fOptState |= OPTST_SET; \
+        DESC(SAVE_OPTS).pzLastArg  = (const char*)(a) )
+/*
+ *  Interface defines not associated with particular options
+ */
+#define ERRSKIP_OPTERR  STMTS( ntpdOptions.fOptSet &= ~OPTPROC_ERRSTOP )
+#define ERRSTOP_OPTERR  STMTS( ntpdOptions.fOptSet |= OPTPROC_ERRSTOP )
+#define RESTART_OPT(n)  STMTS( \
+                ntpdOptions.curOptIdx = (n); \
+                ntpdOptions.pzCurOpt  = NULL )
+#define START_OPT       RESTART_OPT(1)
+#define USAGE(c)        (*ntpdOptions.pUsageProc)( &ntpdOptions, c )
+/* extracted from opthead near line 289 */
+
+/* * * * * *
+ *
+ *  Declare the ntpd option descriptor.
+ */
+#ifdef  __cplusplus
+extern "C" {
+#endif
+
+extern tOptions   ntpdOptions;
+
+#ifndef _
+#  if ENABLE_NLS
+#    include <stdio.h>
+     static inline char* aoGetsText( const char* pz ) {
+         if (pz == NULL) return NULL;
+         return (char*)gettext( pz );
+     }
+#    define _(s)  aoGetsText(s)
+#  else  /* ENABLE_NLS */
+#    define _(s)  s
+#  endif /* ENABLE_NLS */
+#endif
+
+#ifdef  __cplusplus
+}
+#endif
+#endif /* AUTOOPTS_NTPD_OPTS_H_GUARD */
+/*
+ * Local Variables:
+ * Mode: C
+ * c-file-style: "stroustrup"
+ * indent-tabs-mode: nil
+ * End:
+ * options.h ends here */
diff --git a/ntpd/ntpd-opts.menu b/ntpd/ntpd-opts.menu
new file mode 100644 (file)
index 0000000..3425d82
--- /dev/null
@@ -0,0 +1 @@
+* ntpd Invocation::                Invoking ntpd
diff --git a/ntpd/ntpd-opts.texi b/ntpd/ntpd-opts.texi
new file mode 100644 (file)
index 0000000..6587ce1
--- /dev/null
@@ -0,0 +1,481 @@
+@node ntpd Invocation
+@section Invoking ntpd
+@pindex ntpd
+@cindex NTP daemon program
+@ignore
+#  -*- buffer-read-only: t -*- vi: set ro:
+# 
+# DO NOT EDIT THIS FILE   (ntpd-opts.texi)
+# 
+# It has been AutoGen-ed  Tuesday June 27, 2006 at 10:36:08 PM EDT
+# From the definitions    ntpd-opts.def
+# and the template file   aginfo.tpl
+@end ignore
+This program has no explanation.
+
+
+
+This section was generated by @strong{AutoGen},
+the aginfo template and the option descriptions for the @command{ntpd} program.  It documents the ntpd usage text and option meanings.
+
+This software is released under a specialized copyright license.
+
+@menu
+* ntpd usage::                  ntpd usage help (-?)
+* ntpd authnoreq::              authnoreq option (-A)
+* ntpd authreq::                authreq option (-a)
+* ntpd bcastsync::              bcastsync option (-b)
+* ntpd configfile::             configfile option (-c)
+* ntpd debug-level::            debug-level option (-d)
+* ntpd driftfile::              driftfile option (-f)
+* ntpd dvar::                   dvar option (-V)
+* ntpd interface::              interface option (-I)
+* ntpd ipv4::                   ipv4 option (-4)
+* ntpd ipv6::                   ipv6 option (-6)
+* ntpd jaildir::                jaildir option (-i)
+* ntpd keyfile::                keyfile option (-k)
+* ntpd logfile::                logfile option (-l)
+* ntpd nice::                   nice option (-N)
+* ntpd nofork::                 nofork option (-n)
+* ntpd novirtualips::           novirtualips option (-L)
+* ntpd panicgate::              panicgate option (-g)
+* ntpd pidfile::                pidfile option (-p)
+* ntpd priority::               priority option (-P)
+* ntpd propagationdelay::       propagationdelay option (-r)
+* ntpd quit::                   quit option (-q)
+* ntpd set-debug-level::        set-debug-level option (-D)
+* ntpd slew::                   slew option (-x)
+* ntpd statsdir::               statsdir option (-s)
+* ntpd trustedkey::             trustedkey option (-t)
+* ntpd updateinterval::         updateinterval option (-U)
+* ntpd user::                   user option (-u)
+* ntpd var::                    var option (-v)
+@end menu
+
+@node ntpd usage
+@subsection ntpd usage help (-?)
+@cindex ntpd usage
+
+This is the automatically generated usage text for ntpd:
+
+@exampleindent 0
+@example
+ntpd - NTP daemon program - Ver. 4.2.3p10
+USAGE:  ntpd [ -<flag> [<val>] | --<name>[@{=| @}<val>] ]...
+  Flg Arg Option-Name    Description
+   -4 no  ipv4           Force IPv4 DNS name resolution
+   -6 no  ipv6           Force IPv6 DNS name resolution
+                                - an alternate for ipv4
+   -a no  authreq        Require crypto authentication
+                                - prohibits these options:
+                                authnoreq
+   -A no  authnoreq      Do not require crypto authentication
+                                - prohibits these options:
+                                authreq
+   -b no  bcastsync      Allow us to sync to broadcast servers
+   -c Str configfile     configuration file name
+   -d no  debug-level    Increase output debug message level
+                                - may appear multiple times
+   -D Str set-debug-level Set the output debug message level
+                                - may appear multiple times
+   -f Str driftfile      frequency drift file name
+   -g no  panicgate      Allow the first adjustment to be Big
+   -i Str jaildir        Jail directory
+   -I Str interface      Listen on interface
+                                - may appear multiple times
+   -k Str keyfile        path to symmetric keys
+   -l Str logfile        path to the log file
+   -L no  novirtualips   Do not listen to virtual IPs
+   -n no  nofork         Do not fork
+   -N no  nice           Run at high priority
+   -p Str pidfile        path to the PID file
+   -P Num priority       Process priority
+   -q no  quit           Set the time and quit
+   -r Str propagationdelay Broadcast/propagation delay
+   -U Num updateinterval interval in seconds between scans for new or dropped interfaces
+   -s Str statsdir       Statistics file location
+   -t Str trustedkey     Trusted key number
+                                - may appear multiple times
+   -u Str user           Run as userid (or userid:groupid)
+   -v Str var            make ARG an ntp variable (RW)
+                                - may appear multiple times
+   -V Str dvar           make ARG an ntp variable (RW|DEF)
+                                - may appear multiple times
+   -x Str slew           Slew up to 600 seconds
+   -v opt version        Output version information and exit
+   -? no  help           Display usage information and exit
+   -! no  more-help      Extended usage information passed thru pager
+   -> opt save-opts      Save the option state to a config file
+   -< Str load-opts      Load options from a config file
+                                - disabled as --no-load-opts
+                                - may appear multiple times
+
+Options are specified by doubled hyphens and their name
+or by a single hyphen and the flag character.
+
+The following option preset mechanisms are supported:
+ - reading file /users/stenn/.ntprc
+ - reading file /deacon/backroom/ntp-dev-hms/ntpd/.ntprc
+ - reading file /users/stenn/.ntprc
+ - reading file /deacon/backroom/ntp-dev-hms/ntpd/.ntprc
+ - examining environment variables named NTPD_*
+
+
+
+please send bug reports to:  http://bugs.ntp.isc.org, bugs@@ntp.org
+@end example
+@exampleindent 4
+
+@node ntpd ipv4
+@subsection ipv4 option (-4)
+@cindex ntpd-ipv4
+
+This is the ``force ipv4 dns name resolution'' option.
+
+This option has some usage constraints.  It:
+@itemize @bullet
+@item
+is a member of the ipv4 class of options.
+@end itemize
+
+Force DNS resolution of following host names on the command line
+to the IPv4 namespace.
+
+@node ntpd ipv6
+@subsection ipv6 option (-6)
+@cindex ntpd-ipv6
+
+This is the ``force ipv6 dns name resolution'' option.
+
+This option has some usage constraints.  It:
+@itemize @bullet
+@item
+is a member of the ipv4 class of options.
+@end itemize
+
+Force DNS resolution of following host names on the command line
+to the IPv6 namespace.
+
+@node ntpd authreq
+@subsection authreq option (-a)
+@cindex ntpd-authreq
+
+This is the ``require crypto authentication'' option.
+
+This option has some usage constraints.  It:
+@itemize @bullet
+@item
+must not appear in combination with any of the following options:
+authnoreq.
+@end itemize
+
+Require cryptographic authentication for broadcast client,
+multicast client and symmetric passive associations.
+This is the default.
+
+@node ntpd authnoreq
+@subsection authnoreq option (-A)
+@cindex ntpd-authnoreq
+
+This is the ``do not require crypto authentication'' option.
+
+This option has some usage constraints.  It:
+@itemize @bullet
+@item
+must not appear in combination with any of the following options:
+authreq.
+@end itemize
+
+Do not require cryptographic authentication for broadcast client,
+multicast client and symmetric passive associations.
+This is almost never a good idea.
+
+@node ntpd bcastsync
+@subsection bcastsync option (-b)
+@cindex ntpd-bcastsync
+
+This is the ``allow us to sync to broadcast servers'' option.
+
+
+@node ntpd configfile
+@subsection configfile option (-c)
+@cindex ntpd-configfile
+
+This is the ``configuration file name'' option.
+The name and path of the configuration file,
+/etc/ntp.conf
+by default.
+
+@node ntpd debug-level
+@subsection debug-level option (-d)
+@cindex ntpd-debug-level
+
+This is the ``increase output debug message level'' option.
+
+This option has some usage constraints.  It:
+@itemize @bullet
+@item
+may appear an unlimited number of times.
+@end itemize
+
+Increase the debugging message output level.
+
+@node ntpd set-debug-level
+@subsection set-debug-level option (-D)
+@cindex ntpd-set-debug-level
+
+This is the ``set the output debug message level'' option.
+
+This option has some usage constraints.  It:
+@itemize @bullet
+@item
+may appear an unlimited number of times.
+@end itemize
+
+Set the output debugging level.  Can be supplied multiple times,
+but each overrides the previous value(s).
+
+@node ntpd driftfile
+@subsection driftfile option (-f)
+@cindex ntpd-driftfile
+
+This is the ``frequency drift file name'' option.
+The name and path of the frequency file,
+/etc/ntp.drift
+by default.
+This is the same operation as the
+driftfile driftfile
+configuration specification in the 
+/etc/ntp.conf
+file.
+
+@node ntpd panicgate
+@subsection panicgate option (-g)
+@cindex ntpd-panicgate
+
+This is the ``allow the first adjustment to be big'' option.
+Normally,
+ntpd
+exits with a message to the system log if the offset exceeds the panic threshold, which is 1000 s by default. This option allows the time to be set to any value without restriction; however, this can happen only once. If the threshold is exceeded after that,
+ntpd
+will exit with a message to the system log. This option can be used with the
+-q
+and
+-x
+options.
+See the
+tinker
+configuration file directive for other options.
+
+@node ntpd jaildir
+@subsection jaildir option (-i)
+@cindex ntpd-jaildir
+
+This is the ``jail directory'' option.
+Chroot the server to the directory
+jaildir
+.
+This option also implies that the server attempts to drop root privileges at startup (otherwise, chroot gives very little additional security), and it is only available if the OS supports to run the server without full root privileges.
+You may need to also specify a
+-u
+option.
+
+@node ntpd interface
+@subsection interface option (-I)
+@cindex ntpd-interface
+
+This is the ``listen on interface'' option.
+
+This option has some usage constraints.  It:
+@itemize @bullet
+@item
+may appear an unlimited number of times.
+@end itemize
+
+
+
+@node ntpd keyfile
+@subsection keyfile option (-k)
+@cindex ntpd-keyfile
+
+This is the ``path to symmetric keys'' option.
+Specify the name and path of the symmetric key file.
+/etc/ntp.keys
+is the default.
+This is the same operation as the
+keys keyfile
+configuration file directive.
+
+@node ntpd logfile
+@subsection logfile option (-l)
+@cindex ntpd-logfile
+
+This is the ``path to the log file'' option.
+Specify the name and path of the log file.
+The default is the system log file.
+This is the same operation as the
+logfile logfile
+configuration file directive.
+
+@node ntpd novirtualips
+@subsection novirtualips option (-L)
+@cindex ntpd-novirtualips
+
+This is the ``do not listen to virtual ips'' option.
+Do not listen to virtual IPs. The default is to listen.
+
+@node ntpd nofork
+@subsection nofork option (-n)
+@cindex ntpd-nofork
+
+This is the ``do not fork'' option.
+
+
+@node ntpd nice
+@subsection nice option (-N)
+@cindex ntpd-nice
+
+This is the ``run at high priority'' option.
+To the extent permitted by the operating system, run
+ntpd
+at the highest priority.
+
+@node ntpd pidfile
+@subsection pidfile option (-p)
+@cindex ntpd-pidfile
+
+This is the ``path to the pid file'' option.
+Specify the name and path of the file used to record
+ntpd's
+process ID.
+This is the same operation as the
+pidfile pidfile
+configuration file directive.
+
+@node ntpd priority
+@subsection priority option (-P)
+@cindex ntpd-priority
+
+This is the ``process priority'' option.
+To the extent permitted by the operating system, run
+ntpd
+at the specified
+sched_setscheduler(SCHED_FIFO)
+priority.
+
+@node ntpd quit
+@subsection quit option (-q)
+@cindex ntpd-quit
+
+This is the ``set the time and quit'' option.
+ntpd
+will exit just after the first time the clock is set. This behavior mimics that of the
+ntpdate
+program, which is to be retired.
+The
+-g
+and
+-x
+options can be used with this option.
+Note: The kernel time discipline is disabled with this option.
+
+@node ntpd propagationdelay
+@subsection propagationdelay option (-r)
+@cindex ntpd-propagationdelay
+
+This is the ``broadcast/propagation delay'' option.
+Specify the default propagation delay from the broadcast/multicast server to this client. This is necessary only if the delay cannot be computed automatically by the protocol.
+
+@node ntpd updateinterval
+@subsection updateinterval option (-U)
+@cindex ntpd-updateinterval
+
+This is the ``interval in seconds between scans for new or dropped interfaces'' option.
+Give the time in seconds between two scans for new or dropped interfaces.
+For systems with routing socket support the scans will be performed shortly after the interface change
+has been detected by the system.
+Use 0 to disable scanning. 60 seconds is the minimum time between scans.
+
+@node ntpd statsdir
+@subsection statsdir option (-s)
+@cindex ntpd-statsdir
+
+This is the ``statistics file location'' option.
+Specify the directory path for files created by the statistics facility.
+This is the same operation as the
+statsdir statsdir
+configuration file directive.
+
+@node ntpd trustedkey
+@subsection trustedkey option (-t)
+@cindex ntpd-trustedkey
+
+This is the ``trusted key number'' option.
+
+This option has some usage constraints.  It:
+@itemize @bullet
+@item
+may appear an unlimited number of times.
+@end itemize
+
+Add a key number to the trusted key list.
+
+@node ntpd user
+@subsection user option (-u)
+@cindex ntpd-user
+
+This is the ``run as userid (or userid:groupid)'' option.
+Specify a user, and optionally a group, to switch to.
+This option is only available if the OS supports to run the server without full root privileges.
+Currently, this option is supported under NetBSD (configure with
+--enable-clockctl
+) and Linux (configure with
+--enable-linuxcaps
+).
+
+@node ntpd var
+@subsection var option (-v)
+@cindex ntpd-var
+
+This is the ``make arg an ntp variable (rw)'' option.
+
+This option has some usage constraints.  It:
+@itemize @bullet
+@item
+may appear an unlimited number of times.
+@end itemize
+
+
+
+@node ntpd dvar
+@subsection dvar option (-V)
+@cindex ntpd-dvar
+
+This is the ``make arg an ntp variable (rw|def)'' option.
+
+This option has some usage constraints.  It:
+@itemize @bullet
+@item
+may appear an unlimited number of times.
+@end itemize
+
+
+
+@node ntpd slew
+@subsection slew option (-x)
+@cindex ntpd-slew
+
+This is the ``slew up to 600 seconds'' option.
+Normally, the time is slewed if the offset is less than the step threshold, which is 128 ms by default, and stepped if above the threshold.
+This option sets the threshold to 600 s, which is well within the accuracy window to set the clock manually.
+Note: Since the slew rate of typical Unix kernels is limited to 0.5 ms/s, each second of adjustment requires an amortization interval of 2000 s.
+Thus, an adjustment as much as 600 s will take almost 14 days to complete.
+This option can be used with the
+-g
+and
+-q
+options.
+See the
+tinker
+configuration file directive for other options.
+Note: The kernel time discipline is disabled with this option.
diff --git a/ntpd/ntpd.1 b/ntpd/ntpd.1
new file mode 100644 (file)
index 0000000..be3826a
--- /dev/null
@@ -0,0 +1,307 @@
+.TH NTPD 1 2006-06-27 "" "Programmer's Manual"
+.\"  DO NOT EDIT THIS FILE   (ntpd.1)
+.\"  
+.\"  It has been AutoGen-ed  Tuesday June 27, 2006 at 10:36:08 PM EDT
+.\"  From the definitions    ntpd-opts.def
+.\"  and the template file   agman1.tpl
+.\"
+.SH NAME
+ntpd \- NTP daemon program
+.SH SYNOPSIS
+.B ntpd
+.\" Mixture of short (flag) options and long options
+.RB [ -\fIflag\fP " [\fIvalue\fP]]... [" --\fIopt-name\fP " [[=| ]\fIvalue\fP]]..."
+.PP
+All arguments must be options.
+.SH "DESCRIPTION"
+This manual page documents, briefly, the \fBntpd\fP command.
+
+.SH OPTIONS
+.TP
+.BR -4 ", " --ipv4
+Force IPv4 DNS name resolution.
+This option is a member of the ipv4 class of options.
+.sp
+Force DNS resolution of following host names on the command line
+to the IPv4 namespace.
+.TP
+.BR -6 ", " --ipv6
+Force IPv6 DNS name resolution.
+This option is a member of the ipv4 class of options.
+.sp
+Force DNS resolution of following host names on the command line
+to the IPv6 namespace.
+.TP
+.BR -a ", " --authreq
+Require crypto authentication.
+This option must not appear in combination with any of the following options:
+authnoreq.
+.sp
+Require cryptographic authentication for broadcast client,
+multicast client and symmetric passive associations.
+This is the default.
+.TP
+.BR -A ", " --authnoreq
+Do not require crypto authentication.
+This option must not appear in combination with any of the following options:
+authreq.
+.sp
+Do not require cryptographic authentication for broadcast client,
+multicast client and symmetric passive associations.
+This is almost never a good idea.
+.TP
+.BR -b ", " --bcastsync
+Allow us to sync to broadcast servers.
+.sp
+
+.TP
+.BR -c " \fIstring\fP, " --configfile "=" \fIstring\fP
+configuration file name.
+.sp
+The name and path of the configuration file,
+/etc/ntp.conf
+by default.
+.TP
+.BR -d ", " --debug-level
+Increase output debug message level.
+This option may appear an unlimited number of times.
+.sp
+Increase the debugging message output level.
+.TP
+.BR -D " \fIstring\fP, " --set-debug-level "=" \fIstring\fP
+Set the output debug message level.
+This option may appear an unlimited number of times.
+.sp
+Set the output debugging level.  Can be supplied multiple times,
+but each overrides the previous value(s).
+.TP
+.BR -f " \fIstring\fP, " --driftfile "=" \fIstring\fP
+frequency drift file name.
+.sp
+The name and path of the frequency file,
+/etc/ntp.drift
+by default.
+This is the same operation as the
+driftfile driftfile
+configuration specification in the 
+/etc/ntp.conf
+file.
+.TP
+.BR -g ", " --panicgate
+Allow the first adjustment to be Big.
+.sp
+Normally,
+ntpd
+exits with a message to the system log if the offset exceeds the panic threshold, which is 1000 s by default. This option allows the time to be set to any value without restriction; however, this can happen only once. If the threshold is exceeded after that,
+ntpd
+will exit with a message to the system log. This option can be used with the
+-q
+and
+-x
+options.
+See the
+tinker
+configuration file directive for other options.
+.TP
+.BR -i " \fIstring\fP, " --jaildir "=" \fIstring\fP
+Jail directory.
+.sp
+Chroot the server to the directory
+jaildir
+.
+This option also implies that the server attempts to drop root privileges at startup (otherwise, chroot gives very little additional security), and it is only available if the OS supports to run the server without full root privileges.
+You may need to also specify a
+-u
+option.
+.TP
+.BR -I " \fIiface\fP, " --interface "=" \fIiface\fP
+Listen on interface.
+This option may appear an unlimited number of times.
+.sp
+
+.TP
+.BR -k " \fIstring\fP, " --keyfile "=" \fIstring\fP
+path to symmetric keys.
+.sp
+Specify the name and path of the symmetric key file.
+/etc/ntp.keys
+is the default.
+This is the same operation as the
+keys keyfile
+configuration file directive.
+.TP
+.BR -l " \fIstring\fP, " --logfile "=" \fIstring\fP
+path to the log file.
+.sp
+Specify the name and path of the log file.
+The default is the system log file.
+This is the same operation as the
+logfile logfile
+configuration file directive.
+.TP
+.BR -L ", " --novirtualips
+Do not listen to virtual IPs.
+.sp
+Do not listen to virtual IPs. The default is to listen.
+.TP
+.BR -n ", " --nofork
+Do not fork.
+.sp
+
+.TP
+.BR -N ", " --nice
+Run at high priority.
+.sp
+To the extent permitted by the operating system, run
+ntpd
+at the highest priority.
+.TP
+.BR -p " \fIstring\fP, " --pidfile "=" \fIstring\fP
+path to the PID file.
+.sp
+Specify the name and path of the file used to record
+ntpd's
+process ID.
+This is the same operation as the
+pidfile pidfile
+configuration file directive.
+.TP
+.BR -P " \fInumber\fP, " --priority "=" \fInumber\fP
+Process priority.
+This option takes an integer number as its argument.
+.sp
+To the extent permitted by the operating system, run
+ntpd
+at the specified
+sched_setscheduler(SCHED_FIFO)
+priority.
+.TP
+.BR -q ", " --quit
+Set the time and quit.
+.sp
+ntpd
+will exit just after the first time the clock is set. This behavior mimics that of the
+ntpdate
+program, which is to be retired.
+The
+-g
+and
+-x
+options can be used with this option.
+Note: The kernel time discipline is disabled with this option.
+.TP
+.BR -r " \fIstring\fP, " --propagationdelay "=" \fIstring\fP
+Broadcast/propagation delay.
+.sp
+Specify the default propagation delay from the broadcast/multicast server to this client. This is necessary only if the delay cannot be computed automatically by the protocol.
+.TP
+.BR -U " \fInumber\fP, " --updateinterval "=" \fInumber\fP
+interval in seconds between scans for new or dropped interfaces.
+This option takes an integer number as its argument.
+.sp
+Give the time in seconds between two scans for new or dropped interfaces.
+For systems with routing socket support the scans will be performed shortly after the interface change
+has been detected by the system.
+Use 0 to disable scanning. 60 seconds is the minimum time between scans.
+.TP
+.BR -s " \fIstring\fP, " --statsdir "=" \fIstring\fP
+Statistics file location.
+.sp
+Specify the directory path for files created by the statistics facility.
+This is the same operation as the
+statsdir statsdir
+configuration file directive.
+.TP
+.BR -t " \fItkey\fP, " --trustedkey "=" \fItkey\fP
+Trusted key number.
+This option may appear an unlimited number of times.
+.sp
+Add a key number to the trusted key list.
+.TP
+.BR -u " \fIstring\fP, " --user "=" \fIstring\fP
+Run as userid (or userid:groupid).
+.sp
+Specify a user, and optionally a group, to switch to.
+This option is only available if the OS supports to run the server without full root privileges.
+Currently, this option is supported under NetBSD (configure with
+--enable-clockctl
+) and Linux (configure with
+--enable-linuxcaps
+).
+.TP
+.BR -v " \fInvar\fP, " --var "=" \fInvar\fP
+make ARG an ntp variable (RW).
+This option may appear an unlimited number of times.
+.sp
+
+.TP
+.BR -V " \fIndvar\fP, " --dvar "=" \fIndvar\fP
+make ARG an ntp variable (RW|DEF).
+This option may appear an unlimited number of times.
+.sp
+
+.TP
+.BR -x " \fIstring\fP, " --slew "=" \fIstring\fP
+Slew up to 600 seconds.
+.sp
+Normally, the time is slewed if the offset is less than the step threshold, which is 128 ms by default, and stepped if above the threshold.
+This option sets the threshold to 600 s, which is well within the accuracy window to set the clock manually.
+Note: Since the slew rate of typical Unix kernels is limited to 0.5 ms/s, each second of adjustment requires an amortization interval of 2000 s.
+Thus, an adjustment as much as 600 s will take almost 14 days to complete.
+This option can be used with the
+-g
+and
+-q
+options.
+See the
+tinker
+configuration file directive for other options.
+Note: The kernel time discipline is disabled with this option.
+.TP
+.BR \-? , " \--help"
+Display usage information and exit.
+.TP
+.BR \-! , " \--more-help"
+Extended usage information passed thru pager.
+.TP
+.BR \-> " [\fIrcfile\fP]," " \--save-opts" "[=\fIrcfile\fP]"
+Save the option state to \fIrcfile\fP.  The default is the \fIlast\fP
+configuration file listed in the \fBOPTION PRESETS\fP section, below.
+.TP
+.BR \-< " \fIrcfile\fP," " \--load-opts" "=\fIrcfile\fP," " --no-load-opts"
+Load options from \fIrcfile\fP.
+The \fIno-load-opts\fP form will disable the loading
+of earlier RC/INI files.  \fI--no-load-opts\fP is handled early,
+out of order.
+.TP
+.BR \-v " [{\fIv|c|n\fP}]," " \--version" "[=\fI{v|c|n}\fP]"
+Output version of program and exit.  The default mode is `v', a simple
+version.  The `c' mode will print copyright information and `n' will
+print the full copyright notice.
+.SH OPTION PRESETS
+Any option that is not marked as \fInot presettable\fP may be preset
+by loading values from configuration ("RC" or ".INI") file(s) and values from
+environment variables named:
+.nf
+  \fBNTPD_<option-name>\fP or \fBNTPD\fP
+.fi
+.aj
+The environmental presets take precedence (are processed later than)
+the configuration files.
+The \fIhomerc\fP files are "\fI$HOME\fP", "\fI.\fP", "\fI$HOME\fP", and "\fI.\fP".
+If any of these are directories, then the file \fI.ntprc\fP
+is searched for within those directories.
+.SH AUTHOR
+ntp.org
+.br
+Please send bug reports to:  http://bugs.ntp.isc.org, bugs@ntp.org
+
+.PP
+.nf
+.na
+see html/copyright.html
+.fi
+.ad
+.PP
+This manual page was \fIAutoGen\fP-erated from the \fBntpd\fP
+option definitions.
diff --git a/ntpd/ntpdsim-opts.c b/ntpd/ntpdsim-opts.c
new file mode 100644 (file)
index 0000000..b6f220e
--- /dev/null
@@ -0,0 +1,1173 @@
+/*   -*- buffer-read-only: t -*- vi: set ro:
+ *  
+ *  DO NOT EDIT THIS FILE   (ntpdsim-opts.c)
+ *  
+ *  It has been AutoGen-ed  Tuesday June 27, 2006 at 10:16:49 PM EDT
+ *  From the definitions    ntpdsim-opts.def
+ *  and the template file   options
+ */
+
+#define OPTION_CODE_COMPILE 1
+#include "ntpdsim-opts.h"
+
+#ifdef  __cplusplus
+extern "C" {
+#endif
+tSCC zCopyright[] =
+       "ntpdsim copyright (c) 1970-2006 ntp.org, all rights reserved";
+tSCC zCopyrightNotice[] =
+       
+/* extracted from /backroom/ntp-dev-hms/include/copyright.def near line 8 */
+"see html/copyright.html";
+extern tUsageProc optionUsage;
+
+/*
+ *  global included definitions
+ */
+#ifdef __windows
+  extern int atoi(const char*);
+#else
+# include <stdlib.h>
+#endif
+
+#ifndef NULL
+#  define NULL 0
+#endif
+#ifndef EXIT_SUCCESS
+#  define  EXIT_SUCCESS 0
+#endif
+#ifndef EXIT_FAILURE
+#  define  EXIT_FAILURE 1
+#endif
+/*
+ *  Ipv4 option description:
+ */
+tSCC    zIpv4Text[] =
+        "Force IPv4 DNS name resolution";
+tSCC    zIpv4_NAME[]               = "IPV4";
+tSCC    zIpv4_Name[]               = "ipv4";
+#define IPV4_FLAGS       (OPTST_DISABLED)
+
+/*
+ *  Ipv6 option description:
+ */
+tSCC    zIpv6Text[] =
+        "Force IPv6 DNS name resolution";
+tSCC    zIpv6_NAME[]               = "IPV6";
+tSCC    zIpv6_Name[]               = "ipv6";
+#define IPV6_FLAGS       (OPTST_DISABLED)
+
+/*
+ *  Authreq option description with
+ *  "Must also have options" and "Incompatible options":
+ */
+tSCC    zAuthreqText[] =
+        "Require crypto authentication";
+tSCC    zAuthreq_NAME[]            = "AUTHREQ";
+tSCC    zAuthreq_Name[]            = "authreq";
+static const int
+    aAuthreqCantList[] = {
+    INDEX_OPT_AUTHNOREQ, NO_EQUIVALENT };
+#define AUTHREQ_FLAGS       (OPTST_DISABLED)
+
+/*
+ *  Authnoreq option description with
+ *  "Must also have options" and "Incompatible options":
+ */
+tSCC    zAuthnoreqText[] =
+        "Do not require crypto authentication";
+tSCC    zAuthnoreq_NAME[]          = "AUTHNOREQ";
+tSCC    zAuthnoreq_Name[]          = "authnoreq";
+static const int
+    aAuthnoreqCantList[] = {
+    INDEX_OPT_AUTHREQ, NO_EQUIVALENT };
+#define AUTHNOREQ_FLAGS       (OPTST_DISABLED)
+
+/*
+ *  Bcastsync option description:
+ */
+tSCC    zBcastsyncText[] =
+        "Allow us to sync to broadcast servers";
+tSCC    zBcastsync_NAME[]          = "BCASTSYNC";
+tSCC    zBcastsync_Name[]          = "bcastsync";
+#define BCASTSYNC_FLAGS       (OPTST_DISABLED)
+
+/*
+ *  Simbroadcastdelay option description:
+ */
+tSCC    zSimbroadcastdelayText[] =
+        "Simulator broadcast delay";
+tSCC    zSimbroadcastdelay_NAME[]  = "SIMBROADCASTDELAY";
+tSCC    zSimbroadcastdelay_Name[]  = "simbroadcastdelay";
+#define SIMBROADCASTDELAY_FLAGS       (OPTST_DISABLED \
+       | OPTST_SET_ARGTYPE(OPARG_TYPE_STRING))
+
+/*
+ *  Configfile option description:
+ */
+tSCC    zConfigfileText[] =
+        "configuration file name";
+tSCC    zConfigfile_NAME[]         = "CONFIGFILE";
+tSCC    zConfigfile_Name[]         = "configfile";
+#define CONFIGFILE_FLAGS       (OPTST_DISABLED \
+       | OPTST_SET_ARGTYPE(OPARG_TYPE_STRING))
+
+/*
+ *  Phasenoise option description:
+ */
+tSCC    zPhasenoiseText[] =
+        "Phase noise level";
+tSCC    zPhasenoise_NAME[]         = "PHASENOISE";
+tSCC    zPhasenoise_Name[]         = "phasenoise";
+#define PHASENOISE_FLAGS       (OPTST_DISABLED \
+       | OPTST_SET_ARGTYPE(OPARG_TYPE_STRING))
+
+/*
+ *  Debug_Level option description:
+ */
+tSCC    zDebug_LevelText[] =
+        "Increase output debug message level";
+tSCC    zDebug_Level_NAME[]        = "DEBUG_LEVEL";
+tSCC    zDebug_Level_Name[]        = "debug-level";
+#define DEBUG_LEVEL_FLAGS       (OPTST_DISABLED)
+
+/*
+ *  Set_Debug_Level option description:
+ */
+tSCC    zSet_Debug_LevelText[] =
+        "Set the output debug message level";
+tSCC    zSet_Debug_Level_NAME[]    = "SET_DEBUG_LEVEL";
+tSCC    zSet_Debug_Level_Name[]    = "set-debug-level";
+#define SET_DEBUG_LEVEL_FLAGS       (OPTST_DISABLED \
+       | OPTST_SET_ARGTYPE(OPARG_TYPE_STRING))
+
+/*
+ *  Driftfile option description:
+ */
+tSCC    zDriftfileText[] =
+        "frequency drift file name";
+tSCC    zDriftfile_NAME[]          = "DRIFTFILE";
+tSCC    zDriftfile_Name[]          = "driftfile";
+#define DRIFTFILE_FLAGS       (OPTST_DISABLED \
+       | OPTST_SET_ARGTYPE(OPARG_TYPE_STRING))
+
+/*
+ *  Panicgate option description:
+ */
+tSCC    zPanicgateText[] =
+        "Allow the first adjustment to be Big";
+tSCC    zPanicgate_NAME[]          = "PANICGATE";
+tSCC    zPanicgate_Name[]          = "panicgate";
+#define PANICGATE_FLAGS       (OPTST_DISABLED)
+
+/*
+ *  Simslew option description:
+ */
+tSCC    zSimslewText[] =
+        "Simuator slew";
+tSCC    zSimslew_NAME[]            = "SIMSLEW";
+tSCC    zSimslew_Name[]            = "simslew";
+#define SIMSLEW_FLAGS       (OPTST_DISABLED \
+       | OPTST_SET_ARGTYPE(OPARG_TYPE_STRING))
+
+/*
+ *  Jaildir option description:
+ */
+tSCC    zJaildirText[] =
+        "Jail directory";
+tSCC    zJaildir_NAME[]            = "JAILDIR";
+tSCC    zJaildir_Name[]            = "jaildir";
+#define JAILDIR_FLAGS       (OPTST_DISABLED \
+       | OPTST_SET_ARGTYPE(OPARG_TYPE_STRING))
+
+/*
+ *  Interface option description:
+ */
+tSCC    zInterfaceText[] =
+        "Listen on interface";
+tSCC    zInterface_NAME[]          = "INTERFACE";
+tSCC    zInterface_Name[]          = "interface";
+#define INTERFACE_FLAGS       (OPTST_DISABLED | OPTST_STACKED \
+       | OPTST_SET_ARGTYPE(OPARG_TYPE_STRING))
+
+/*
+ *  Keyfile option description:
+ */
+tSCC    zKeyfileText[] =
+        "path to symmetric keys";
+tSCC    zKeyfile_NAME[]            = "KEYFILE";
+tSCC    zKeyfile_Name[]            = "keyfile";
+#define KEYFILE_FLAGS       (OPTST_DISABLED \
+       | OPTST_SET_ARGTYPE(OPARG_TYPE_STRING))
+
+/*
+ *  Logfile option description:
+ */
+tSCC    zLogfileText[] =
+        "path to the log file";
+tSCC    zLogfile_NAME[]            = "LOGFILE";
+tSCC    zLogfile_Name[]            = "logfile";
+#define LOGFILE_FLAGS       (OPTST_DISABLED \
+       | OPTST_SET_ARGTYPE(OPARG_TYPE_STRING))
+
+/*
+ *  Novirtualips option description:
+ */
+tSCC    zNovirtualipsText[] =
+        "Do not listen to virtual IPs";
+tSCC    zNovirtualips_NAME[]       = "NOVIRTUALIPS";
+tSCC    zNovirtualips_Name[]       = "novirtualips";
+#define NOVIRTUALIPS_FLAGS       (OPTST_DISABLED)
+
+/*
+ *  Nofork option description:
+ */
+tSCC    zNoforkText[] =
+        "Do not fork";
+tSCC    zNofork_NAME[]             = "NOFORK";
+tSCC    zNofork_Name[]             = "nofork";
+#define NOFORK_FLAGS       (OPTST_DISABLED)
+
+/*
+ *  Nice option description:
+ */
+tSCC    zNiceText[] =
+        "Run at high priority";
+tSCC    zNice_NAME[]               = "NICE";
+tSCC    zNice_Name[]               = "nice";
+#define NICE_FLAGS       (OPTST_DISABLED)
+
+/*
+ *  Servertime option description:
+ */
+tSCC    zServertimeText[] =
+        "Server time";
+tSCC    zServertime_NAME[]         = "SERVERTIME";
+tSCC    zServertime_Name[]         = "servertime";
+#define SERVERTIME_FLAGS       (OPTST_DISABLED \
+       | OPTST_SET_ARGTYPE(OPARG_TYPE_STRING))
+
+/*
+ *  Pidfile option description:
+ */
+tSCC    zPidfileText[] =
+        "path to the PID file";
+tSCC    zPidfile_NAME[]            = "PIDFILE";
+tSCC    zPidfile_Name[]            = "pidfile";
+#define PIDFILE_FLAGS       (OPTST_DISABLED \
+       | OPTST_SET_ARGTYPE(OPARG_TYPE_STRING))
+
+/*
+ *  Priority option description:
+ */
+tSCC    zPriorityText[] =
+        "Process priority";
+tSCC    zPriority_NAME[]           = "PRIORITY";
+tSCC    zPriority_Name[]           = "priority";
+#define PRIORITY_FLAGS       (OPTST_DISABLED \
+       | OPTST_SET_ARGTYPE(OPARG_TYPE_NUMERIC))
+
+/*
+ *  Quit option description:
+ */
+tSCC    zQuitText[] =
+        "Set the time and quit";
+tSCC    zQuit_NAME[]               = "QUIT";
+tSCC    zQuit_Name[]               = "quit";
+#define QUIT_FLAGS       (OPTST_DISABLED)
+
+/*
+ *  Propagationdelay option description:
+ */
+tSCC    zPropagationdelayText[] =
+        "Broadcast/propagation delay";
+tSCC    zPropagationdelay_NAME[]   = "PROPAGATIONDELAY";
+tSCC    zPropagationdelay_Name[]   = "propagationdelay";
+#define PROPAGATIONDELAY_FLAGS       (OPTST_DISABLED \
+       | OPTST_SET_ARGTYPE(OPARG_TYPE_STRING))
+
+/*
+ *  Updateinterval option description:
+ */
+tSCC    zUpdateintervalText[] =
+        "interval in seconds between scans for new or dropped interfaces";
+tSCC    zUpdateinterval_NAME[]     = "UPDATEINTERVAL";
+tSCC    zUpdateinterval_Name[]     = "updateinterval";
+#define UPDATEINTERVAL_FLAGS       (OPTST_DISABLED \
+       | OPTST_SET_ARGTYPE(OPARG_TYPE_NUMERIC))
+
+/*
+ *  Statsdir option description:
+ */
+tSCC    zStatsdirText[] =
+        "Statistics file location";
+tSCC    zStatsdir_NAME[]           = "STATSDIR";
+tSCC    zStatsdir_Name[]           = "statsdir";
+#define STATSDIR_FLAGS       (OPTST_DISABLED \
+       | OPTST_SET_ARGTYPE(OPARG_TYPE_STRING))
+
+/*
+ *  Endsimtime option description:
+ */
+tSCC    zEndsimtimeText[] =
+        "Simulation end time";
+tSCC    zEndsimtime_NAME[]         = "ENDSIMTIME";
+tSCC    zEndsimtime_Name[]         = "endsimtime";
+#define ENDSIMTIME_FLAGS       (OPTST_DISABLED \
+       | OPTST_SET_ARGTYPE(OPARG_TYPE_STRING))
+
+/*
+ *  Trustedkey option description:
+ */
+tSCC    zTrustedkeyText[] =
+        "Trusted key number";
+tSCC    zTrustedkey_NAME[]         = "TRUSTEDKEY";
+tSCC    zTrustedkey_Name[]         = "trustedkey";
+#define TRUSTEDKEY_FLAGS       (OPTST_DISABLED | OPTST_STACKED \
+       | OPTST_SET_ARGTYPE(OPARG_TYPE_STRING))
+
+/*
+ *  Freqerr option description:
+ */
+tSCC    zFreqerrText[] =
+        "Simulation frequency error";
+tSCC    zFreqerr_NAME[]            = "FREQERR";
+tSCC    zFreqerr_Name[]            = "freqerr";
+#define FREQERR_FLAGS       (OPTST_DISABLED \
+       | OPTST_SET_ARGTYPE(OPARG_TYPE_STRING))
+
+/*
+ *  Walknoise option description:
+ */
+tSCC    zWalknoiseText[] =
+        "Simulation random walk noise";
+tSCC    zWalknoise_NAME[]          = "WALKNOISE";
+tSCC    zWalknoise_Name[]          = "walknoise";
+#define WALKNOISE_FLAGS       (OPTST_DISABLED \
+       | OPTST_SET_ARGTYPE(OPARG_TYPE_STRING))
+
+/*
+ *  User option description:
+ */
+tSCC    zUserText[] =
+        "Run as userid (or userid:groupid)";
+tSCC    zUser_NAME[]               = "USER";
+tSCC    zUser_Name[]               = "user";
+#define USER_FLAGS       (OPTST_DISABLED \
+       | OPTST_SET_ARGTYPE(OPARG_TYPE_STRING))
+
+/*
+ *  Var option description:
+ */
+tSCC    zVarText[] =
+        "make ARG an ntp variable (RW)";
+tSCC    zVar_NAME[]                = "VAR";
+tSCC    zVar_Name[]                = "var";
+#define VAR_FLAGS       (OPTST_DISABLED | OPTST_STACKED \
+       | OPTST_SET_ARGTYPE(OPARG_TYPE_STRING))
+
+/*
+ *  Dvar option description:
+ */
+tSCC    zDvarText[] =
+        "make ARG an ntp variable (RW|DEF)";
+tSCC    zDvar_NAME[]               = "DVAR";
+tSCC    zDvar_Name[]               = "dvar";
+#define DVAR_FLAGS       (OPTST_DISABLED | OPTST_STACKED \
+       | OPTST_SET_ARGTYPE(OPARG_TYPE_STRING))
+
+/*
+ *  Slew option description:
+ */
+tSCC    zSlewText[] =
+        "Slew up to 600 seconds";
+tSCC    zSlew_NAME[]               = "SLEW";
+tSCC    zSlew_Name[]               = "slew";
+#define SLEW_FLAGS       (OPTST_DISABLED \
+       | OPTST_SET_ARGTYPE(OPARG_TYPE_STRING))
+
+/*
+ *  Ndelay option description:
+ */
+tSCC    zNdelayText[] =
+        "Simulation network delay";
+tSCC    zNdelay_NAME[]             = "NDELAY";
+tSCC    zNdelay_Name[]             = "ndelay";
+#define NDELAY_FLAGS       (OPTST_DISABLED \
+       | OPTST_SET_ARGTYPE(OPARG_TYPE_STRING))
+
+/*
+ *  Pdelay option description:
+ */
+tSCC    zPdelayText[] =
+        "Simulation processing delay";
+tSCC    zPdelay_NAME[]             = "PDELAY";
+tSCC    zPdelay_Name[]             = "pdelay";
+#define PDELAY_FLAGS       (OPTST_DISABLED \
+       | OPTST_SET_ARGTYPE(OPARG_TYPE_STRING))
+
+/*
+ *  Help/More_Help/Version option descriptions:
+ */
+tSCC zHelpText[]       = "Display usage information and exit";
+tSCC zHelp_Name[]      = "help";
+
+tSCC zMore_HelpText[]  = "Extended usage information passed thru pager";
+tSCC zMore_Help_Name[] = "more-help";
+
+tSCC zVersionText[]    = "Output version information and exit";
+tSCC zVersion_Name[]   = "version";
+
+/*
+ *  Save/Load_Opts option description:
+ */
+tSCC zSave_OptsText[]     = "Save the option state to a config file";
+tSCC zSave_Opts_Name[]    = "save-opts";
+
+tSCC zLoad_OptsText[]     = "Load options from a config file";
+tSCC zLoad_Opts_NAME[]    = "LOAD_OPTS";
+
+tSCC zNotLoad_Opts_Name[] = "no-load-opts";
+tSCC zNotLoad_Opts_Pfx[]  = "no";
+#define zLoad_Opts_Name   (zNotLoad_Opts_Name + 3)
+/*
+ *  Declare option callback procedures
+ */
+/* extracted from optmain.tpl near line 586 */
+
+#if defined(TEST_NTPDSIM_OPTS)
+/*
+ *  Under test, omit argument processing, or call optionStackArg,
+ *  if multiple copies are allowed.
+ */
+extern tOptProc
+    optionNumericVal,    optionPagedUsage,    optionStackArg,
+    optionVersionStderr;
+static tOptProc
+    doUsageOpt;
+
+/*
+ *  #define map the "normal" callout procs to the test ones...
+ */
+#define SET_DEBUG_LEVEL_OPT_PROC optionStackArg
+
+
+#else /* NOT defined TEST_NTPDSIM_OPTS */
+/*
+ *  When not under test, there are different procs to use
+ */
+extern tOptProc
+    optionNumericVal, optionPagedUsage, optionPrintVersion, optionStackArg;
+static tOptProc
+    doOptSet_Debug_Level, doUsageOpt;
+
+/*
+ *  #define map the "normal" callout procs
+ */
+#define SET_DEBUG_LEVEL_OPT_PROC doOptSet_Debug_Level
+
+#define SET_DEBUG_LEVEL_OPT_PROC doOptSet_Debug_Level
+#endif /* defined(TEST_NTPDSIM_OPTS) */
+#ifdef TEST_NTPDSIM_OPTS
+# define DOVERPROC optionVersionStderr
+#else
+# define DOVERPROC optionPrintVersion
+#endif /* TEST_NTPDSIM_OPTS */
+
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ *
+ *  Define the Ntpdsim Option Descriptions.
+ */
+static tOptDesc optDesc[ OPTION_CT ] = {
+  {  /* entry idx, value */ 0, VALUE_OPT_IPV4,
+     /* equiv idx, value */ NO_EQUIVALENT, 0,
+     /* equivalenced to  */ NO_EQUIVALENT,
+     /* min, max, act ct */ 0, 1, 0,
+     /* opt state flags  */ IPV4_FLAGS, 0,
+     /* last opt argumnt */ NULL,
+     /* arg list/cookie  */ NULL,
+     /* must/cannot opts */ NULL, NULL,
+     /* option proc      */ NULL,
+     /* desc, NAME, name */ zIpv4Text, zIpv4_NAME, zIpv4_Name,
+     /* disablement strs */ NULL, NULL },
+
+  {  /* entry idx, value */ 1, VALUE_OPT_IPV6,
+     /* equiv idx, value */ NOLIMIT, NOLIMIT,
+     /* equivalenced to  */ INDEX_OPT_IPV4,
+     /* min, max, act ct */ 0, 1, 0,
+     /* opt state flags  */ IPV6_FLAGS, 0,
+     /* last opt argumnt */ NULL,
+     /* arg list/cookie  */ NULL,
+     /* must/cannot opts */ NULL, NULL,
+     /* option proc      */ NULL,
+     /* desc, NAME, name */ zIpv6Text, zIpv6_NAME, zIpv6_Name,
+     /* disablement strs */ NULL, NULL },
+
+  {  /* entry idx, value */ 2, VALUE_OPT_AUTHREQ,
+     /* equiv idx, value */ 2, VALUE_OPT_AUTHREQ,
+     /* equivalenced to  */ NO_EQUIVALENT,
+     /* min, max, act ct */ 0, 1, 0,
+     /* opt state flags  */ AUTHREQ_FLAGS, 0,
+     /* last opt argumnt */ NULL,
+     /* arg list/cookie  */ NULL,
+     /* must/cannot opts */ NULL, aAuthreqCantList,
+     /* option proc      */ NULL,
+     /* desc, NAME, name */ zAuthreqText, zAuthreq_NAME, zAuthreq_Name,
+     /* disablement strs */ NULL, NULL },
+
+  {  /* entry idx, value */ 3, VALUE_OPT_AUTHNOREQ,
+     /* equiv idx, value */ 3, VALUE_OPT_AUTHNOREQ,
+     /* equivalenced to  */ NO_EQUIVALENT,
+     /* min, max, act ct */ 0, 1, 0,
+     /* opt state flags  */ AUTHNOREQ_FLAGS, 0,
+     /* last opt argumnt */ NULL,
+     /* arg list/cookie  */ NULL,
+     /* must/cannot opts */ NULL, aAuthnoreqCantList,
+     /* option proc      */ NULL,
+     /* desc, NAME, name */ zAuthnoreqText, zAuthnoreq_NAME, zAuthnoreq_Name,
+     /* disablement strs */ NULL, NULL },
+
+  {  /* entry idx, value */ 4, VALUE_OPT_BCASTSYNC,
+     /* equiv idx, value */ 4, VALUE_OPT_BCASTSYNC,
+     /* equivalenced to  */ NO_EQUIVALENT,
+     /* min, max, act ct */ 0, 1, 0,
+     /* opt state flags  */ BCASTSYNC_FLAGS, 0,
+     /* last opt argumnt */ NULL,
+     /* arg list/cookie  */ NULL,
+     /* must/cannot opts */ NULL, NULL,
+     /* option proc      */ NULL,
+     /* desc, NAME, name */ zBcastsyncText, zBcastsync_NAME, zBcastsync_Name,
+     /* disablement strs */ NULL, NULL },
+
+  {  /* entry idx, value */ 5, VALUE_OPT_SIMBROADCASTDELAY,
+     /* equiv idx, value */ 5, VALUE_OPT_SIMBROADCASTDELAY,
+     /* equivalenced to  */ NO_EQUIVALENT,
+     /* min, max, act ct */ 0, 1, 0,
+     /* opt state flags  */ SIMBROADCASTDELAY_FLAGS, 0,
+     /* last opt argumnt */ NULL,
+     /* arg list/cookie  */ NULL,
+     /* must/cannot opts */ NULL, NULL,
+     /* option proc      */ NULL,
+     /* desc, NAME, name */ zSimbroadcastdelayText, zSimbroadcastdelay_NAME, zSimbroadcastdelay_Name,
+     /* disablement strs */ NULL, NULL },
+
+  {  /* entry idx, value */ 6, VALUE_OPT_CONFIGFILE,
+     /* equiv idx, value */ 6, VALUE_OPT_CONFIGFILE,
+     /* equivalenced to  */ NO_EQUIVALENT,
+     /* min, max, act ct */ 0, 1, 0,
+     /* opt state flags  */ CONFIGFILE_FLAGS, 0,
+     /* last opt argumnt */ NULL,
+     /* arg list/cookie  */ NULL,
+     /* must/cannot opts */ NULL, NULL,
+     /* option proc      */ NULL,
+     /* desc, NAME, name */ zConfigfileText, zConfigfile_NAME, zConfigfile_Name,
+     /* disablement strs */ NULL, NULL },
+
+  {  /* entry idx, value */ 7, VALUE_OPT_PHASENOISE,
+     /* equiv idx, value */ 7, VALUE_OPT_PHASENOISE,
+     /* equivalenced to  */ NO_EQUIVALENT,
+     /* min, max, act ct */ 0, 1, 0,
+     /* opt state flags  */ PHASENOISE_FLAGS, 0,
+     /* last opt argumnt */ NULL,
+     /* arg list/cookie  */ NULL,
+     /* must/cannot opts */ NULL, NULL,
+     /* option proc      */ NULL,
+     /* desc, NAME, name */ zPhasenoiseText, zPhasenoise_NAME, zPhasenoise_Name,
+     /* disablement strs */ NULL, NULL },
+
+  {  /* entry idx, value */ 8, VALUE_OPT_DEBUG_LEVEL,
+     /* equiv idx, value */ 8, VALUE_OPT_DEBUG_LEVEL,
+     /* equivalenced to  */ NO_EQUIVALENT,
+     /* min, max, act ct */ 0, NOLIMIT, 0,
+     /* opt state flags  */ DEBUG_LEVEL_FLAGS, 0,
+     /* last opt argumnt */ NULL,
+     /* arg list/cookie  */ NULL,
+     /* must/cannot opts */ NULL, NULL,
+     /* option proc      */ NULL,
+     /* desc, NAME, name */ zDebug_LevelText, zDebug_Level_NAME, zDebug_Level_Name,
+     /* disablement strs */ NULL, NULL },
+
+  {  /* entry idx, value */ 9, VALUE_OPT_SET_DEBUG_LEVEL,
+     /* equiv idx, value */ 9, VALUE_OPT_SET_DEBUG_LEVEL,
+     /* equivalenced to  */ NO_EQUIVALENT,
+     /* min, max, act ct */ 0, NOLIMIT, 0,
+     /* opt state flags  */ SET_DEBUG_LEVEL_FLAGS, 0,
+     /* last opt argumnt */ NULL,
+     /* arg list/cookie  */ NULL,
+     /* must/cannot opts */ NULL, NULL,
+     /* option proc      */ SET_DEBUG_LEVEL_OPT_PROC,
+     /* desc, NAME, name */ zSet_Debug_LevelText, zSet_Debug_Level_NAME, zSet_Debug_Level_Name,
+     /* disablement strs */ NULL, NULL },
+
+  {  /* entry idx, value */ 10, VALUE_OPT_DRIFTFILE,
+     /* equiv idx, value */ 10, VALUE_OPT_DRIFTFILE,
+     /* equivalenced to  */ NO_EQUIVALENT,
+     /* min, max, act ct */ 0, 1, 0,
+     /* opt state flags  */ DRIFTFILE_FLAGS, 0,
+     /* last opt argumnt */ NULL,
+     /* arg list/cookie  */ NULL,
+     /* must/cannot opts */ NULL, NULL,
+     /* option proc      */ NULL,
+     /* desc, NAME, name */ zDriftfileText, zDriftfile_NAME, zDriftfile_Name,
+     /* disablement strs */ NULL, NULL },
+
+  {  /* entry idx, value */ 11, VALUE_OPT_PANICGATE,
+     /* equiv idx, value */ 11, VALUE_OPT_PANICGATE,
+     /* equivalenced to  */ NO_EQUIVALENT,
+     /* min, max, act ct */ 0, 1, 0,
+     /* opt state flags  */ PANICGATE_FLAGS, 0,
+     /* last opt argumnt */ NULL,
+     /* arg list/cookie  */ NULL,
+     /* must/cannot opts */ NULL, NULL,
+     /* option proc      */ NULL,
+     /* desc, NAME, name */ zPanicgateText, zPanicgate_NAME, zPanicgate_Name,
+     /* disablement strs */ NULL, NULL },
+
+  {  /* entry idx, value */ 12, VALUE_OPT_SIMSLEW,
+     /* equiv idx, value */ 12, VALUE_OPT_SIMSLEW,
+     /* equivalenced to  */ NO_EQUIVALENT,
+     /* min, max, act ct */ 0, 1, 0,
+     /* opt state flags  */ SIMSLEW_FLAGS, 0,
+     /* last opt argumnt */ NULL,
+     /* arg list/cookie  */ NULL,
+     /* must/cannot opts */ NULL, NULL,
+     /* option proc      */ NULL,
+     /* desc, NAME, name */ zSimslewText, zSimslew_NAME, zSimslew_Name,
+     /* disablement strs */ NULL, NULL },
+
+  {  /* entry idx, value */ 13, VALUE_OPT_JAILDIR,
+     /* equiv idx, value */ 13, VALUE_OPT_JAILDIR,
+     /* equivalenced to  */ NO_EQUIVALENT,
+     /* min, max, act ct */ 0, 1, 0,
+     /* opt state flags  */ JAILDIR_FLAGS, 0,
+     /* last opt argumnt */ NULL,
+     /* arg list/cookie  */ NULL,
+     /* must/cannot opts */ NULL, NULL,
+     /* option proc      */ NULL,
+     /* desc, NAME, name */ zJaildirText, zJaildir_NAME, zJaildir_Name,
+     /* disablement strs */ NULL, NULL },
+
+  {  /* entry idx, value */ 14, VALUE_OPT_INTERFACE,
+     /* equiv idx, value */ 14, VALUE_OPT_INTERFACE,
+     /* equivalenced to  */ NO_EQUIVALENT,
+     /* min, max, act ct */ 0, NOLIMIT, 0,
+     /* opt state flags  */ INTERFACE_FLAGS, 0,
+     /* last opt argumnt */ NULL,
+     /* arg list/cookie  */ NULL,
+     /* must/cannot opts */ NULL, NULL,
+     /* option proc      */ optionStackArg,
+     /* desc, NAME, name */ zInterfaceText, zInterface_NAME, zInterface_Name,
+     /* disablement strs */ NULL, NULL },
+
+  {  /* entry idx, value */ 15, VALUE_OPT_KEYFILE,
+     /* equiv idx, value */ 15, VALUE_OPT_KEYFILE,
+     /* equivalenced to  */ NO_EQUIVALENT,
+     /* min, max, act ct */ 0, 1, 0,
+     /* opt state flags  */ KEYFILE_FLAGS, 0,
+     /* last opt argumnt */ NULL,
+     /* arg list/cookie  */ NULL,
+     /* must/cannot opts */ NULL, NULL,
+     /* option proc      */ NULL,
+     /* desc, NAME, name */ zKeyfileText, zKeyfile_NAME, zKeyfile_Name,
+     /* disablement strs */ NULL, NULL },
+
+  {  /* entry idx, value */ 16, VALUE_OPT_LOGFILE,
+     /* equiv idx, value */ 16, VALUE_OPT_LOGFILE,
+     /* equivalenced to  */ NO_EQUIVALENT,
+     /* min, max, act ct */ 0, 1, 0,
+     /* opt state flags  */ LOGFILE_FLAGS, 0,
+     /* last opt argumnt */ NULL,
+     /* arg list/cookie  */ NULL,
+     /* must/cannot opts */ NULL, NULL,
+     /* option proc      */ NULL,
+     /* desc, NAME, name */ zLogfileText, zLogfile_NAME, zLogfile_Name,
+     /* disablement strs */ NULL, NULL },
+
+  {  /* entry idx, value */ 17, VALUE_OPT_NOVIRTUALIPS,
+     /* equiv idx, value */ 17, VALUE_OPT_NOVIRTUALIPS,
+     /* equivalenced to  */ NO_EQUIVALENT,
+     /* min, max, act ct */ 0, 1, 0,
+     /* opt state flags  */ NOVIRTUALIPS_FLAGS, 0,
+     /* last opt argumnt */ NULL,
+     /* arg list/cookie  */ NULL,
+     /* must/cannot opts */ NULL, NULL,
+     /* option proc      */ NULL,
+     /* desc, NAME, name */ zNovirtualipsText, zNovirtualips_NAME, zNovirtualips_Name,
+     /* disablement strs */ NULL, NULL },
+
+  {  /* entry idx, value */ 18, VALUE_OPT_NOFORK,
+     /* equiv idx, value */ 18, VALUE_OPT_NOFORK,
+     /* equivalenced to  */ NO_EQUIVALENT,
+     /* min, max, act ct */ 0, 1, 0,
+     /* opt state flags  */ NOFORK_FLAGS, 0,
+     /* last opt argumnt */ NULL,
+     /* arg list/cookie  */ NULL,
+     /* must/cannot opts */ NULL, NULL,
+     /* option proc      */ NULL,
+     /* desc, NAME, name */ zNoforkText, zNofork_NAME, zNofork_Name,
+     /* disablement strs */ NULL, NULL },
+
+  {  /* entry idx, value */ 19, VALUE_OPT_NICE,
+     /* equiv idx, value */ 19, VALUE_OPT_NICE,
+     /* equivalenced to  */ NO_EQUIVALENT,
+     /* min, max, act ct */ 0, 1, 0,
+     /* opt state flags  */ NICE_FLAGS, 0,
+     /* last opt argumnt */ NULL,
+     /* arg list/cookie  */ NULL,
+     /* must/cannot opts */ NULL, NULL,
+     /* option proc      */ NULL,
+     /* desc, NAME, name */ zNiceText, zNice_NAME, zNice_Name,
+     /* disablement strs */ NULL, NULL },
+
+  {  /* entry idx, value */ 20, VALUE_OPT_SERVERTIME,
+     /* equiv idx, value */ 20, VALUE_OPT_SERVERTIME,
+     /* equivalenced to  */ NO_EQUIVALENT,
+     /* min, max, act ct */ 0, 1, 0,
+     /* opt state flags  */ SERVERTIME_FLAGS, 0,
+     /* last opt argumnt */ NULL,
+     /* arg list/cookie  */ NULL,
+     /* must/cannot opts */ NULL, NULL,
+     /* option proc      */ NULL,
+     /* desc, NAME, name */ zServertimeText, zServertime_NAME, zServertime_Name,
+     /* disablement strs */ NULL, NULL },
+
+  {  /* entry idx, value */ 21, VALUE_OPT_PIDFILE,
+     /* equiv idx, value */ 21, VALUE_OPT_PIDFILE,
+     /* equivalenced to  */ NO_EQUIVALENT,
+     /* min, max, act ct */ 0, 1, 0,
+     /* opt state flags  */ PIDFILE_FLAGS, 0,
+     /* last opt argumnt */ NULL,
+     /* arg list/cookie  */ NULL,
+     /* must/cannot opts */ NULL, NULL,
+     /* option proc      */ NULL,
+     /* desc, NAME, name */ zPidfileText, zPidfile_NAME, zPidfile_Name,
+     /* disablement strs */ NULL, NULL },
+
+  {  /* entry idx, value */ 22, VALUE_OPT_PRIORITY,
+     /* equiv idx, value */ 22, VALUE_OPT_PRIORITY,
+     /* equivalenced to  */ NO_EQUIVALENT,
+     /* min, max, act ct */ 0, 1, 0,
+     /* opt state flags  */ PRIORITY_FLAGS, 0,
+     /* last opt argumnt */ NULL,
+     /* arg list/cookie  */ NULL,
+     /* must/cannot opts */ NULL, NULL,
+     /* option proc      */ optionNumericVal,
+     /* desc, NAME, name */ zPriorityText, zPriority_NAME, zPriority_Name,
+     /* disablement strs */ NULL, NULL },
+
+  {  /* entry idx, value */ 23, VALUE_OPT_QUIT,
+     /* equiv idx, value */ 23, VALUE_OPT_QUIT,
+     /* equivalenced to  */ NO_EQUIVALENT,
+     /* min, max, act ct */ 0, 1, 0,
+     /* opt state flags  */ QUIT_FLAGS, 0,
+     /* last opt argumnt */ NULL,
+     /* arg list/cookie  */ NULL,
+     /* must/cannot opts */ NULL, NULL,
+     /* option proc      */ NULL,
+     /* desc, NAME, name */ zQuitText, zQuit_NAME, zQuit_Name,
+     /* disablement strs */ NULL, NULL },
+
+  {  /* entry idx, value */ 24, VALUE_OPT_PROPAGATIONDELAY,
+     /* equiv idx, value */ 24, VALUE_OPT_PROPAGATIONDELAY,
+     /* equivalenced to  */ NO_EQUIVALENT,
+     /* min, max, act ct */ 0, 1, 0,
+     /* opt state flags  */ PROPAGATIONDELAY_FLAGS, 0,
+     /* last opt argumnt */ NULL,
+     /* arg list/cookie  */ NULL,
+     /* must/cannot opts */ NULL, NULL,
+     /* option proc      */ NULL,
+     /* desc, NAME, name */ zPropagationdelayText, zPropagationdelay_NAME, zPropagationdelay_Name,
+     /* disablement strs */ NULL, NULL },
+
+  {  /* entry idx, value */ 25, VALUE_OPT_UPDATEINTERVAL,
+     /* equiv idx, value */ 25, VALUE_OPT_UPDATEINTERVAL,
+     /* equivalenced to  */ NO_EQUIVALENT,
+     /* min, max, act ct */ 0, 1, 0,
+     /* opt state flags  */ UPDATEINTERVAL_FLAGS, 0,
+     /* last opt argumnt */ NULL,
+     /* arg list/cookie  */ NULL,
+     /* must/cannot opts */ NULL, NULL,
+     /* option proc      */ optionNumericVal,
+     /* desc, NAME, name */ zUpdateintervalText, zUpdateinterval_NAME, zUpdateinterval_Name,
+     /* disablement strs */ NULL, NULL },
+
+  {  /* entry idx, value */ 26, VALUE_OPT_STATSDIR,
+     /* equiv idx, value */ 26, VALUE_OPT_STATSDIR,
+     /* equivalenced to  */ NO_EQUIVALENT,
+     /* min, max, act ct */ 0, 1, 0,
+     /* opt state flags  */ STATSDIR_FLAGS, 0,
+     /* last opt argumnt */ NULL,
+     /* arg list/cookie  */ NULL,
+     /* must/cannot opts */ NULL, NULL,
+     /* option proc      */ NULL,
+     /* desc, NAME, name */ zStatsdirText, zStatsdir_NAME, zStatsdir_Name,
+     /* disablement strs */ NULL, NULL },
+
+  {  /* entry idx, value */ 27, VALUE_OPT_ENDSIMTIME,
+     /* equiv idx, value */ 27, VALUE_OPT_ENDSIMTIME,
+     /* equivalenced to  */ NO_EQUIVALENT,
+     /* min, max, act ct */ 0, 1, 0,
+     /* opt state flags  */ ENDSIMTIME_FLAGS, 0,
+     /* last opt argumnt */ NULL,
+     /* arg list/cookie  */ NULL,
+     /* must/cannot opts */ NULL, NULL,
+     /* option proc      */ NULL,
+     /* desc, NAME, name */ zEndsimtimeText, zEndsimtime_NAME, zEndsimtime_Name,
+     /* disablement strs */ NULL, NULL },
+
+  {  /* entry idx, value */ 28, VALUE_OPT_TRUSTEDKEY,
+     /* equiv idx, value */ 28, VALUE_OPT_TRUSTEDKEY,
+     /* equivalenced to  */ NO_EQUIVALENT,
+     /* min, max, act ct */ 0, NOLIMIT, 0,
+     /* opt state flags  */ TRUSTEDKEY_FLAGS, 0,
+     /* last opt argumnt */ NULL,
+     /* arg list/cookie  */ NULL,
+     /* must/cannot opts */ NULL, NULL,
+     /* option proc      */ optionStackArg,
+     /* desc, NAME, name */ zTrustedkeyText, zTrustedkey_NAME, zTrustedkey_Name,
+     /* disablement strs */ NULL, NULL },
+
+  {  /* entry idx, value */ 29, VALUE_OPT_FREQERR,
+     /* equiv idx, value */ 29, VALUE_OPT_FREQERR,
+     /* equivalenced to  */ NO_EQUIVALENT,
+     /* min, max, act ct */ 0, 1, 0,
+     /* opt state flags  */ FREQERR_FLAGS, 0,
+     /* last opt argumnt */ NULL,
+     /* arg list/cookie  */ NULL,
+     /* must/cannot opts */ NULL, NULL,
+     /* option proc      */ NULL,
+     /* desc, NAME, name */ zFreqerrText, zFreqerr_NAME, zFreqerr_Name,
+     /* disablement strs */ NULL, NULL },
+
+  {  /* entry idx, value */ 30, VALUE_OPT_WALKNOISE,
+     /* equiv idx, value */ 30, VALUE_OPT_WALKNOISE,
+     /* equivalenced to  */ NO_EQUIVALENT,
+     /* min, max, act ct */ 0, 1, 0,
+     /* opt state flags  */ WALKNOISE_FLAGS, 0,
+     /* last opt argumnt */ NULL,
+     /* arg list/cookie  */ NULL,
+     /* must/cannot opts */ NULL, NULL,
+     /* option proc      */ NULL,
+     /* desc, NAME, name */ zWalknoiseText, zWalknoise_NAME, zWalknoise_Name,
+     /* disablement strs */ NULL, NULL },
+
+  {  /* entry idx, value */ 31, VALUE_OPT_USER,
+     /* equiv idx, value */ 31, VALUE_OPT_USER,
+     /* equivalenced to  */ NO_EQUIVALENT,
+     /* min, max, act ct */ 0, 1, 0,
+     /* opt state flags  */ USER_FLAGS, 0,
+     /* last opt argumnt */ NULL,
+     /* arg list/cookie  */ NULL,
+     /* must/cannot opts */ NULL, NULL,
+     /* option proc      */ NULL,
+     /* desc, NAME, name */ zUserText, zUser_NAME, zUser_Name,
+     /* disablement strs */ NULL, NULL },
+
+  {  /* entry idx, value */ 32, VALUE_OPT_VAR,
+     /* equiv idx, value */ 32, VALUE_OPT_VAR,
+     /* equivalenced to  */ NO_EQUIVALENT,
+     /* min, max, act ct */ 0, NOLIMIT, 0,
+     /* opt state flags  */ VAR_FLAGS, 0,
+     /* last opt argumnt */ NULL,
+     /* arg list/cookie  */ NULL,
+     /* must/cannot opts */ NULL, NULL,
+     /* option proc      */ optionStackArg,
+     /* desc, NAME, name */ zVarText, zVar_NAME, zVar_Name,
+     /* disablement strs */ NULL, NULL },
+
+  {  /* entry idx, value */ 33, VALUE_OPT_DVAR,
+     /* equiv idx, value */ 33, VALUE_OPT_DVAR,
+     /* equivalenced to  */ NO_EQUIVALENT,
+     /* min, max, act ct */ 0, NOLIMIT, 0,
+     /* opt state flags  */ DVAR_FLAGS, 0,
+     /* last opt argumnt */ NULL,
+     /* arg list/cookie  */ NULL,
+     /* must/cannot opts */ NULL, NULL,
+     /* option proc      */ optionStackArg,
+     /* desc, NAME, name */ zDvarText, zDvar_NAME, zDvar_Name,
+     /* disablement strs */ NULL, NULL },
+
+  {  /* entry idx, value */ 34, VALUE_OPT_SLEW,
+     /* equiv idx, value */ 34, VALUE_OPT_SLEW,
+     /* equivalenced to  */ NO_EQUIVALENT,
+     /* min, max, act ct */ 0, 1, 0,
+     /* opt state flags  */ SLEW_FLAGS, 0,
+     /* last opt argumnt */ NULL,
+     /* arg list/cookie  */ NULL,
+     /* must/cannot opts */ NULL, NULL,
+     /* option proc      */ NULL,
+     /* desc, NAME, name */ zSlewText, zSlew_NAME, zSlew_Name,
+     /* disablement strs */ NULL, NULL },
+
+  {  /* entry idx, value */ 35, VALUE_OPT_NDELAY,
+     /* equiv idx, value */ 35, VALUE_OPT_NDELAY,
+     /* equivalenced to  */ NO_EQUIVALENT,
+     /* min, max, act ct */ 0, 1, 0,
+     /* opt state flags  */ NDELAY_FLAGS, 0,
+     /* last opt argumnt */ NULL,
+     /* arg list/cookie  */ NULL,
+     /* must/cannot opts */ NULL, NULL,
+     /* option proc      */ NULL,
+     /* desc, NAME, name */ zNdelayText, zNdelay_NAME, zNdelay_Name,
+     /* disablement strs */ NULL, NULL },
+
+  {  /* entry idx, value */ 36, VALUE_OPT_PDELAY,
+     /* equiv idx, value */ 36, VALUE_OPT_PDELAY,
+     /* equivalenced to  */ NO_EQUIVALENT,
+     /* min, max, act ct */ 0, 1, 0,
+     /* opt state flags  */ PDELAY_FLAGS, 0,
+     /* last opt argumnt */ NULL,
+     /* arg list/cookie  */ NULL,
+     /* must/cannot opts */ NULL, NULL,
+     /* option proc      */ NULL,
+     /* desc, NAME, name */ zPdelayText, zPdelay_NAME, zPdelay_Name,
+     /* disablement strs */ NULL, NULL },
+
+  {  /* entry idx, value */ INDEX_OPT_VERSION, VALUE_OPT_VERSION,
+     /* equiv idx value  */ NO_EQUIVALENT, 0,
+     /* equivalenced to  */ NO_EQUIVALENT,
+     /* min, max, act ct */ 0, 1, 0,
+     /* opt state flags  */ OPTST_SET_ARGTYPE(OPARG_TYPE_STRING)
+                          | OPTST_ARG_OPTIONAL, 0,
+     /* last opt argumnt */ NULL,
+     /* arg list/cookie  */ NULL,
+     /* must/cannot opts */ NULL, NULL,
+     /* option proc      */ DOVERPROC,
+     /* desc, NAME, name */ zVersionText, NULL, zVersion_Name,
+     /* disablement strs */ NULL, NULL },
+
+  {  /* entry idx, value */ INDEX_OPT_HELP, VALUE_OPT_HELP,
+     /* equiv idx value  */ NO_EQUIVALENT, 0,
+     /* equivalenced to  */ NO_EQUIVALENT,
+     /* min, max, act ct */ 0, 1, 0,
+     /* opt state flags  */ OPTST_IMM, 0,
+     /* last opt argumnt */ NULL,
+     /* arg list/cookie  */ NULL,
+     /* must/cannot opts */ NULL, NULL,
+     /* option proc      */ doUsageOpt,
+     /* desc, NAME, name */ zHelpText, NULL, zHelp_Name,
+     /* disablement strs */ NULL, NULL },
+
+  {  /* entry idx, value */ INDEX_OPT_MORE_HELP, VALUE_OPT_MORE_HELP,
+     /* equiv idx value  */ NO_EQUIVALENT, 0,
+     /* equivalenced to  */ NO_EQUIVALENT,
+     /* min, max, act ct */ 0, 1, 0,
+     /* opt state flags  */ OPTST_IMM, 0,
+     /* last opt argumnt */ NULL,
+     /* arg list/cookie  */ NULL,
+     /* must/cannot opts */ NULL,  NULL,
+     /* option proc      */ optionPagedUsage,
+     /* desc, NAME, name */ zMore_HelpText, NULL, zMore_Help_Name,
+     /* disablement strs */ NULL, NULL },
+
+  {  /* entry idx, value */ INDEX_OPT_SAVE_OPTS, VALUE_OPT_SAVE_OPTS,
+     /* equiv idx value  */ NO_EQUIVALENT, 0,
+     /* equivalenced to  */ NO_EQUIVALENT,
+     /* min, max, act ct */ 0, 1, 0,
+     /* opt state flags  */ OPTST_SET_ARGTYPE(OPARG_TYPE_STRING)
+                          | OPTST_ARG_OPTIONAL, 0,
+     /* last opt argumnt */ NULL,
+     /* arg list/cookie  */ NULL,
+     /* must/cannot opts */ NULL,  NULL,
+     /* option proc      */ NULL,
+     /* desc, NAME, name */ zSave_OptsText, NULL, zSave_Opts_Name,
+     /* disablement strs */ NULL, NULL },
+
+  {  /* entry idx, value */ INDEX_OPT_LOAD_OPTS, VALUE_OPT_LOAD_OPTS,
+     /* equiv idx value  */ NO_EQUIVALENT, 0,
+     /* equivalenced to  */ NO_EQUIVALENT,
+     /* min, max, act ct */ 0, NOLIMIT, 0,
+     /* opt state flags  */ OPTST_DISABLE_IMM | \
+                       OPTST_SET_ARGTYPE(OPARG_TYPE_STRING), 0,
+     /* last opt argumnt */ NULL,
+     /* arg list/cookie  */ NULL,
+     /* must/cannot opts */ NULL, NULL,
+     /* option proc      */ optionLoadOpt,
+     /* desc, NAME, name */ zLoad_OptsText, zLoad_Opts_NAME, zLoad_Opts_Name,
+     /* disablement strs */ zNotLoad_Opts_Name, zNotLoad_Opts_Pfx }
+};
+
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ *
+ *  Define the Ntpdsim Option Environment
+ */
+tSCC   zPROGNAME[]   = "NTPDSIM";
+tSCC   zUsageTitle[] =
+"ntpdsim - NTP daemon simulation program - Ver. 4.2.3p12\n\
+USAGE:  %s [ -<flag> [<val>] | --<name>[{=| }<val>] ]...\n";
+tSCC   zRcName[]     = ".ntprc";
+tSCC*  apzHomeList[] = {
+       "$HOME",
+       ".",
+       "$HOME",
+       ".",
+       NULL };
+
+tSCC   zBugsAddr[]    = "http://bugs.ntp.isc.org, bugs@ntp.org";
+#define zExplain NULL
+tSCC    zDetail[]     = "\n\n";
+tSCC    zFullVersion[] = NTPDSIM_FULL_VERSION;
+/* extracted from optcode near line 321 */
+
+#if defined(ENABLE_NLS)
+# define OPTPROC_BASE OPTPROC_TRANSLATE
+  static tOptionXlateProc translate_option_strings;
+#else
+# define OPTPROC_BASE OPTPROC_NONE
+# define translate_option_strings NULL
+#endif /* ENABLE_NLS */
+
+tOptions ntpdsimOptions = {
+    OPTIONS_STRUCT_VERSION,
+    0, NULL,                    /* original argc + argv    */
+    ( OPTPROC_BASE
+    + OPTPROC_ERRSTOP
+    + OPTPROC_SHORTOPT
+    + OPTPROC_LONGOPT
+    + OPTPROC_NO_REQ_OPT
+    + OPTPROC_ENVIRON
+    + OPTPROC_NO_ARGS
+    + OPTPROC_HAS_IMMED ),
+    0, NULL,                    /* current option index, current option */
+    NULL,         NULL,         zPROGNAME,
+    zRcName,      zCopyright,   zCopyrightNotice,
+    zFullVersion, apzHomeList,  zUsageTitle,
+    zExplain,     zDetail,      optDesc,
+    zBugsAddr,                  /* address to send bugs to */
+    NULL, NULL,                 /* extensions/saved state  */
+    optionUsage,       /* usage procedure */
+    translate_option_strings,   /* translation procedure */
+    /*
+     *  Indexes to special options
+     */
+    { INDEX_OPT_MORE_HELP,
+      INDEX_OPT_SAVE_OPTS,
+      NO_EQUIVALENT /* index of '-#' option */,
+      NO_EQUIVALENT /* index of default opt */
+    },
+    OPTION_CT, 37 /* user option count */
+};
+
+/*
+ *  Create the static procedure(s) declared above.
+ */
+static void
+doUsageOpt(
+    tOptions*   pOptions,
+    tOptDesc*   pOptDesc )
+{
+    USAGE( EXIT_SUCCESS );
+}
+
+#if ! defined(TEST_NTPDSIM_OPTS)
+
+/* * * * * * *
+ *
+ *   For the set-debug-level option.
+ */
+static void
+doOptSet_Debug_Level(
+    tOptions*   pOptions,
+    tOptDesc*   pOptDesc )
+{
+DESC(DEBUG_LEVEL).optOccCt = atoi( pOptDesc->pzLastArg );
+}
+
+#endif /* defined(TEST_NTPDSIM_OPTS) */
+
+/* extracted from optmain.tpl near line 92 */
+
+#if defined(TEST_NTPDSIM_OPTS) /* TEST MAIN PROCEDURE: */
+
+int
+main( int argc, char** argv )
+{
+    int res = EXIT_SUCCESS;
+    (void)optionProcess( &ntpdsimOptions, argc, argv );
+    {
+        void optionPutShell( tOptions* );
+        optionPutShell( &ntpdsimOptions );
+    }
+    return res;
+}
+#endif  /* defined TEST_NTPDSIM_OPTS */
+/* extracted from optcode near line 418 */
+
+#if ENABLE_NLS
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+#include <autoopts/usage-txt.h>
+
+static char*
+AO_gettext( const char* pz )
+{
+    char* pzRes;
+    if (pz == NULL)
+        return NULL;
+    pzRes = _(pz);
+    if (pzRes == pz)
+        return pzRes;
+    pzRes = strdup( pzRes );
+    if (pzRes == NULL) {
+        fputs( _("No memory for duping translated strings\n"), stderr );
+        exit( EXIT_FAILURE );
+    }
+    return pzRes;
+}
+
+/*
+ *  This invokes the translation code (e.g. gettext(3)).
+ */
+static void
+translate_option_strings( void )
+{
+    /*
+     *  Guard against re-translation.  It won't work.  The strings will have
+     *  been changed by the first pass through this code.  One shot only.
+     */
+    if (option_usage_text.field_ct == 0)
+        return;
+    /*
+     *  Do the translations.  The first pointer follows the field count field.
+     *  The field count field is the size of a pointer.
+     */
+    {
+        char** ppz = (char**)(void*)&(option_usage_text);
+        int    ix  = option_usage_text.field_ct;
+
+        do {
+            ppz++;
+            *ppz = AO_gettext(*ppz);
+        } while (--ix > 0);
+    }
+    option_usage_text.field_ct = 0;
+
+    {
+        tOptDesc* pOD = ntpdsimOptions.pOptDesc;
+        int       ix  = ntpdsimOptions.optCt;
+
+        for (;;) {
+            pOD->pzText           = AO_gettext(pOD->pzText);
+            pOD->pz_NAME          = AO_gettext(pOD->pz_NAME);
+            pOD->pz_Name          = AO_gettext(pOD->pz_Name);
+            pOD->pz_DisableName   = AO_gettext(pOD->pz_DisableName);
+            pOD->pz_DisablePfx    = AO_gettext(pOD->pz_DisablePfx);
+            if (--ix <= 0)
+                break;
+            pOD++;
+        }
+    }
+    ntpdsimOptions.pzCopyright   = AO_gettext(ntpdsimOptions.pzCopyright);
+    ntpdsimOptions.pzCopyNotice  = AO_gettext(ntpdsimOptions.pzCopyNotice);
+    ntpdsimOptions.pzFullVersion = AO_gettext(ntpdsimOptions.pzFullVersion);
+    ntpdsimOptions.pzUsageTitle  = AO_gettext(ntpdsimOptions.pzUsageTitle);
+    ntpdsimOptions.pzExplain     = AO_gettext(ntpdsimOptions.pzExplain);
+    ntpdsimOptions.pzDetail      = AO_gettext(ntpdsimOptions.pzDetail);
+}
+
+#endif /* ENABLE_NLS */
+
+#ifdef  __cplusplus
+}
+#endif
diff --git a/ntpd/ntpdsim-opts.h b/ntpd/ntpdsim-opts.h
new file mode 100644 (file)
index 0000000..e179f5b
--- /dev/null
@@ -0,0 +1,211 @@
+/*   -*- buffer-read-only: t -*- vi: set ro:
+ *  
+ *  DO NOT EDIT THIS FILE   (ntpdsim-opts.h)
+ *  
+ *  It has been AutoGen-ed  Tuesday June 27, 2006 at 10:16:48 PM EDT
+ *  From the definitions    ntpdsim-opts.def
+ *  and the template file   options
+ */
+/*
+ *  This file contains the programmatic interface to the Automated
+ *  Options generated for the ntpdsim program.
+ *  These macros are documented in the AutoGen info file in the
+ *  "AutoOpts" chapter.  Please refer to that doc for usage help.
+ */
+#ifndef AUTOOPTS_NTPDSIM_OPTS_H_GUARD
+#define AUTOOPTS_NTPDSIM_OPTS_H_GUARD
+
+/*
+ * ntpdsim copyright 1970-2006 ntp.org - all rights reserved
+ *
+ * see html/copyright.html
+ */
+#include "config.h"
+#include <autoopts/options.h>
+
+/*
+ *  Ensure that the library used for compiling this generated header is at
+ *  least as new as the version current when the header template was released
+ *  (not counting patch version increments).  Also ensure that the oldest
+ *  tolerable version is at least as old as what was current when the header
+ *  template was released.
+ */
+#define AO_TEMPLATE_VERSION 110592
+#if (AO_TEMPLATE_VERSION < OPTIONS_MINIMUM_VERSION) \
+ || (AO_TEMPLATE_VERSION > OPTIONS_STRUCT_VERSION)
+# error option template version mismatches autoopts/options.h header
+#endif
+
+/*
+ *  Enumeration of each option:
+ */
+typedef enum {
+        INDEX_OPT_IPV4             =  0,
+        INDEX_OPT_IPV6             =  1,
+        INDEX_OPT_AUTHREQ          =  2,
+        INDEX_OPT_AUTHNOREQ        =  3,
+        INDEX_OPT_BCASTSYNC        =  4,
+        INDEX_OPT_SIMBROADCASTDELAY =  5,
+        INDEX_OPT_CONFIGFILE       =  6,
+        INDEX_OPT_PHASENOISE       =  7,
+        INDEX_OPT_DEBUG_LEVEL      =  8,
+        INDEX_OPT_SET_DEBUG_LEVEL  =  9,
+        INDEX_OPT_DRIFTFILE        = 10,
+        INDEX_OPT_PANICGATE        = 11,
+        INDEX_OPT_SIMSLEW          = 12,
+        INDEX_OPT_JAILDIR          = 13,
+        INDEX_OPT_INTERFACE        = 14,
+        INDEX_OPT_KEYFILE          = 15,
+        INDEX_OPT_LOGFILE          = 16,
+        INDEX_OPT_NOVIRTUALIPS     = 17,
+        INDEX_OPT_NOFORK           = 18,
+        INDEX_OPT_NICE             = 19,
+        INDEX_OPT_SERVERTIME       = 20,
+        INDEX_OPT_PIDFILE          = 21,
+        INDEX_OPT_PRIORITY         = 22,
+        INDEX_OPT_QUIT             = 23,
+        INDEX_OPT_PROPAGATIONDELAY = 24,
+        INDEX_OPT_UPDATEINTERVAL   = 25,
+        INDEX_OPT_STATSDIR         = 26,
+        INDEX_OPT_ENDSIMTIME       = 27,
+        INDEX_OPT_TRUSTEDKEY       = 28,
+        INDEX_OPT_FREQERR          = 29,
+        INDEX_OPT_WALKNOISE        = 30,
+        INDEX_OPT_USER             = 31,
+        INDEX_OPT_VAR              = 32,
+        INDEX_OPT_DVAR             = 33,
+        INDEX_OPT_SLEW             = 34,
+        INDEX_OPT_NDELAY           = 35,
+        INDEX_OPT_PDELAY           = 36,
+        INDEX_OPT_VERSION          = 37,
+        INDEX_OPT_HELP             = 38,
+        INDEX_OPT_MORE_HELP        = 39,
+        INDEX_OPT_SAVE_OPTS        = 40,
+        INDEX_OPT_LOAD_OPTS        = 41
+} teOptIndex;
+
+#define OPTION_CT    42
+#define NTPDSIM_VERSION       "4.2.3p12"
+#define NTPDSIM_FULL_VERSION  "ntpdsim - NTP daemon simulation program - Ver. 4.2.3p12"
+
+/*
+ *  Interface defines for all options.  Replace "n" with
+ *  the UPPER_CASED option name (as in the teOptIndex
+ *  enumeration above).  e.g. HAVE_OPT( IPV4 )
+ */
+#define        DESC(n) ntpdsimOptions.pOptDesc[INDEX_OPT_ ## n]
+#define     HAVE_OPT(n) (! UNUSED_OPT(& DESC(n)))
+#define      OPT_ARG(n) (DESC(n).pzLastArg)
+#define    STATE_OPT(n) (DESC(n).fOptState & OPTST_SET_MASK)
+#define    COUNT_OPT(n) (DESC(n).optOccCt)
+#define    ISSEL_OPT(n) (SELECTED_OPT(&DESC(n)))
+#define ISUNUSED_OPT(n) (UNUSED_OPT(& DESC(n)))
+#define  ENABLED_OPT(n) (! DISABLED_OPT(& DESC(n)))
+#define  STACKCT_OPT(n) (((tArgList*)(DESC(n).optCookie))->useCt)
+#define STACKLST_OPT(n) (((tArgList*)(DESC(n).optCookie))->apzArgs)
+#define    CLEAR_OPT(n) STMTS( \
+                DESC(n).fOptState &= OPTST_PERSISTENT;   \
+                if ( (DESC(n).fOptState & OPTST_INITENABLED) == 0) \
+                    DESC(n).fOptState |= OPTST_DISABLED; \
+                DESC(n).optCookie = NULL )
+
+/*
+ *  Interface defines for specific options.
+ */
+#define VALUE_OPT_IPV4           '4'
+#define WHICH_OPT_IPV4           (DESC(IPV4).optActualValue)
+#define WHICH_IDX_IPV4           (DESC(IPV4).optActualIndex)
+#define VALUE_OPT_IPV6           '6'
+#define VALUE_OPT_AUTHREQ        'a'
+#define VALUE_OPT_AUTHNOREQ      'A'
+#define VALUE_OPT_BCASTSYNC      'b'
+#define VALUE_OPT_SIMBROADCASTDELAY 'B'
+#define VALUE_OPT_CONFIGFILE     'c'
+#define VALUE_OPT_PHASENOISE     'C'
+#define VALUE_OPT_DEBUG_LEVEL    'd'
+#define VALUE_OPT_SET_DEBUG_LEVEL 'D'
+#define VALUE_OPT_DRIFTFILE      'f'
+#define VALUE_OPT_PANICGATE      'g'
+#define VALUE_OPT_SIMSLEW        'H'
+#define VALUE_OPT_JAILDIR        'i'
+#define VALUE_OPT_INTERFACE      'I'
+#define VALUE_OPT_KEYFILE        'k'
+#define VALUE_OPT_LOGFILE        'l'
+#define VALUE_OPT_NOVIRTUALIPS   'L'
+#define VALUE_OPT_NOFORK         'n'
+#define VALUE_OPT_NICE           'N'
+#define VALUE_OPT_SERVERTIME     'O'
+#define VALUE_OPT_PIDFILE        'p'
+#define VALUE_OPT_PRIORITY       'P'
+#define OPT_VALUE_PRIORITY       (*(unsigned long*)(&DESC(PRIORITY).pzLastArg))
+#define VALUE_OPT_QUIT           'q'
+#define VALUE_OPT_PROPAGATIONDELAY 'r'
+#define VALUE_OPT_UPDATEINTERVAL 'U'
+#define OPT_VALUE_UPDATEINTERVAL (*(unsigned long*)(&DESC(UPDATEINTERVAL).pzLastArg))
+#define VALUE_OPT_STATSDIR       's'
+#define VALUE_OPT_ENDSIMTIME     'S'
+#define VALUE_OPT_TRUSTEDKEY     't'
+#define VALUE_OPT_FREQERR        'T'
+#define VALUE_OPT_WALKNOISE      'W'
+#define VALUE_OPT_USER           'u'
+#define VALUE_OPT_VAR            'v'
+#define VALUE_OPT_DVAR           'V'
+#define VALUE_OPT_SLEW           'x'
+#define VALUE_OPT_NDELAY         'Y'
+#define VALUE_OPT_PDELAY         'Z'
+
+#define VALUE_OPT_VERSION       'v'
+#define VALUE_OPT_SAVE_OPTS     '>'
+#define VALUE_OPT_LOAD_OPTS     '<'
+#define VALUE_OPT_HELP          '?'
+#define VALUE_OPT_MORE_HELP     '!'
+#define SET_OPT_SAVE_OPTS(a)   STMTS( \
+        DESC(SAVE_OPTS).fOptState &= OPTST_PERSISTENT; \
+        DESC(SAVE_OPTS).fOptState |= OPTST_SET; \
+        DESC(SAVE_OPTS).pzLastArg  = (const char*)(a) )
+/*
+ *  Interface defines not associated with particular options
+ */
+#define ERRSKIP_OPTERR  STMTS( ntpdsimOptions.fOptSet &= ~OPTPROC_ERRSTOP )
+#define ERRSTOP_OPTERR  STMTS( ntpdsimOptions.fOptSet |= OPTPROC_ERRSTOP )
+#define RESTART_OPT(n)  STMTS( \
+                ntpdsimOptions.curOptIdx = (n); \
+                ntpdsimOptions.pzCurOpt  = NULL )
+#define START_OPT       RESTART_OPT(1)
+#define USAGE(c)        (*ntpdsimOptions.pUsageProc)( &ntpdsimOptions, c )
+/* extracted from opthead near line 289 */
+
+/* * * * * *
+ *
+ *  Declare the ntpdsim option descriptor.
+ */
+#ifdef  __cplusplus
+extern "C" {
+#endif
+
+extern tOptions   ntpdsimOptions;
+
+#ifndef _
+#  if ENABLE_NLS
+#    include <stdio.h>
+     static inline char* aoGetsText( const char* pz ) {
+         if (pz == NULL) return NULL;
+         return (char*)gettext( pz );
+     }
+#    define _(s)  aoGetsText(s)
+#  else  /* ENABLE_NLS */
+#    define _(s)  s
+#  endif /* ENABLE_NLS */
+#endif
+
+#ifdef  __cplusplus
+}
+#endif
+#endif /* AUTOOPTS_NTPDSIM_OPTS_H_GUARD */
+/*
+ * Local Variables:
+ * Mode: C
+ * c-file-style: "stroustrup"
+ * indent-tabs-mode: nil
+ * End:
+ * options.h ends here */
diff --git a/ntpd/ntpdsim-opts.menu b/ntpd/ntpdsim-opts.menu
new file mode 100644 (file)
index 0000000..c787458
--- /dev/null
@@ -0,0 +1 @@
+* ntpdsim Invocation::             Invoking ntpdsim
diff --git a/ntpd/ntpdsim-opts.texi b/ntpd/ntpdsim-opts.texi
new file mode 100644 (file)
index 0000000..27de556
--- /dev/null
@@ -0,0 +1,562 @@
+@node ntpdsim Invocation
+@section Invoking ntpdsim
+@pindex ntpdsim
+@cindex NTP daemon simulation program
+@ignore
+#  -*- buffer-read-only: t -*- vi: set ro:
+# 
+# DO NOT EDIT THIS FILE   (ntpdsim-opts.texi)
+# 
+# It has been AutoGen-ed  Tuesday June 27, 2006 at 10:36:09 PM EDT
+# From the definitions    ntpdsim-opts.def
+# and the template file   aginfo.tpl
+@end ignore
+This program has no explanation.
+
+
+
+This section was generated by @strong{AutoGen},
+the aginfo template and the option descriptions for the @command{ntpdsim} program.  It documents the ntpdsim usage text and option meanings.
+
+This software is released under a specialized copyright license.
+
+@menu
+* ntpdsim usage::                  ntpdsim usage help (-?)
+* ntpdsim authnoreq::              authnoreq option (-A)
+* ntpdsim authreq::                authreq option (-a)
+* ntpdsim bcastsync::              bcastsync option (-b)
+* ntpdsim configfile::             configfile option (-c)
+* ntpdsim debug-level::            debug-level option (-d)
+* ntpdsim driftfile::              driftfile option (-f)
+* ntpdsim dvar::                   dvar option (-V)
+* ntpdsim endsimtime::             endsimtime option (-S)
+* ntpdsim freqerr::                freqerr option (-T)
+* ntpdsim interface::              interface option (-I)
+* ntpdsim ipv4::                   ipv4 option (-4)
+* ntpdsim ipv6::                   ipv6 option (-6)
+* ntpdsim jaildir::                jaildir option (-i)
+* ntpdsim keyfile::                keyfile option (-k)
+* ntpdsim logfile::                logfile option (-l)
+* ntpdsim ndelay::                 ndelay option (-Y)
+* ntpdsim nice::                   nice option (-N)
+* ntpdsim nofork::                 nofork option (-n)
+* ntpdsim novirtualips::           novirtualips option (-L)
+* ntpdsim panicgate::              panicgate option (-g)
+* ntpdsim pdelay::                 pdelay option (-Z)
+* ntpdsim phasenoise::             phasenoise option (-C)
+* ntpdsim pidfile::                pidfile option (-p)
+* ntpdsim priority::               priority option (-P)
+* ntpdsim propagationdelay::       propagationdelay option (-r)
+* ntpdsim quit::                   quit option (-q)
+* ntpdsim servertime::             servertime option (-O)
+* ntpdsim set-debug-level::        set-debug-level option (-D)
+* ntpdsim simbroadcastdelay::      simbroadcastdelay option (-B)
+* ntpdsim simslew::                simslew option (-H)
+* ntpdsim slew::                   slew option (-x)
+* ntpdsim statsdir::               statsdir option (-s)
+* ntpdsim trustedkey::             trustedkey option (-t)
+* ntpdsim updateinterval::         updateinterval option (-U)
+* ntpdsim user::                   user option (-u)
+* ntpdsim var::                    var option (-v)
+* ntpdsim walknoise::              walknoise option (-W)
+@end menu
+
+@node ntpdsim usage
+@subsection ntpdsim usage help (-?)
+@cindex ntpdsim usage
+
+This is the automatically generated usage text for ntpdsim:
+
+@exampleindent 0
+@example
+ntpdsim - NTP daemon simulation program - Ver. 4.2.3p10
+USAGE:  ntpdsim [ -<flag> [<val>] | --<name>[@{=| @}<val>] ]...
+  Flg Arg Option-Name    Description
+   -4 no  ipv4           Force IPv4 DNS name resolution
+   -6 no  ipv6           Force IPv6 DNS name resolution
+                                - an alternate for ipv4
+   -a no  authreq        Require crypto authentication
+                                - prohibits these options:
+                                authnoreq
+   -A no  authnoreq      Do not require crypto authentication
+                                - prohibits these options:
+                                authreq
+   -b no  bcastsync      Allow us to sync to broadcast servers
+   -B Str simbroadcastdelay Simulator broadcast delay
+   -c Str configfile     configuration file name
+   -C Str phasenoise     Phase noise level
+   -d no  debug-level    Increase output debug message level
+                                - may appear multiple times
+   -D Str set-debug-level Set the output debug message level
+                                - may appear multiple times
+   -f Str driftfile      frequency drift file name
+   -g no  panicgate      Allow the first adjustment to be Big
+   -H Str simslew        Simuator slew
+   -i Str jaildir        Jail directory
+   -I Str interface      Listen on interface
+                                - may appear multiple times
+   -k Str keyfile        path to symmetric keys
+   -l Str logfile        path to the log file
+   -L no  novirtualips   Do not listen to virtual IPs
+   -n no  nofork         Do not fork
+   -N no  nice           Run at high priority
+   -O Str servertime     Server time
+   -p Str pidfile        path to the PID file
+   -P Num priority       Process priority
+   -q no  quit           Set the time and quit
+   -r Str propagationdelay Broadcast/propagation delay
+   -U Num updateinterval interval in seconds between scans for new or dropped interfaces
+   -s Str statsdir       Statistics file location
+   -S Str endsimtime     Simulation end time
+   -t Str trustedkey     Trusted key number
+                                - may appear multiple times
+   -T Str freqerr        Simulation frequency error
+   -W Str walknoise      Simulation random walk noise
+   -u Str user           Run as userid (or userid:groupid)
+   -v Str var            make ARG an ntp variable (RW)
+                                - may appear multiple times
+   -V Str dvar           make ARG an ntp variable (RW|DEF)
+                                - may appear multiple times
+   -x Str slew           Slew up to 600 seconds
+   -Y Str ndelay         Simulation network delay
+   -Z Str pdelay         Simulation processing delay
+   -v opt version        Output version information and exit
+   -? no  help           Display usage information and exit
+   -! no  more-help      Extended usage information passed thru pager
+   -> opt save-opts      Save the option state to a config file
+   -< Str load-opts      Load options from a config file
+                                - disabled as --no-load-opts
+                                - may appear multiple times
+
+Options are specified by doubled hyphens and their name
+or by a single hyphen and the flag character.
+
+The following option preset mechanisms are supported:
+ - reading file /users/stenn/.ntprc
+ - reading file /deacon/backroom/ntp-dev-hms/ntpd/.ntprc
+ - reading file /users/stenn/.ntprc
+ - reading file /deacon/backroom/ntp-dev-hms/ntpd/.ntprc
+ - examining environment variables named NTPDSIM_*
+
+
+
+please send bug reports to:  http://bugs.ntp.isc.org, bugs@@ntp.org
+@end example
+@exampleindent 4
+
+@node ntpdsim ipv4
+@subsection ipv4 option (-4)
+@cindex ntpdsim-ipv4
+
+This is the ``force ipv4 dns name resolution'' option.
+
+This option has some usage constraints.  It:
+@itemize @bullet
+@item
+is a member of the ipv4 class of options.
+@end itemize
+
+Force DNS resolution of following host names on the command line
+to the IPv4 namespace.
+
+@node ntpdsim ipv6
+@subsection ipv6 option (-6)
+@cindex ntpdsim-ipv6
+
+This is the ``force ipv6 dns name resolution'' option.
+
+This option has some usage constraints.  It:
+@itemize @bullet
+@item
+is a member of the ipv4 class of options.
+@end itemize
+
+Force DNS resolution of following host names on the command line
+to the IPv6 namespace.
+
+@node ntpdsim authreq
+@subsection authreq option (-a)
+@cindex ntpdsim-authreq
+
+This is the ``require crypto authentication'' option.
+
+This option has some usage constraints.  It:
+@itemize @bullet
+@item
+must not appear in combination with any of the following options:
+authnoreq.
+@end itemize
+
+Require cryptographic authentication for broadcast client,
+multicast client and symmetric passive associations.
+This is the default.
+
+@node ntpdsim authnoreq
+@subsection authnoreq option (-A)
+@cindex ntpdsim-authnoreq
+
+This is the ``do not require crypto authentication'' option.
+
+This option has some usage constraints.  It:
+@itemize @bullet
+@item
+must not appear in combination with any of the following options:
+authreq.
+@end itemize
+
+Do not require cryptographic authentication for broadcast client,
+multicast client and symmetric passive associations.
+This is almost never a good idea.
+
+@node ntpdsim bcastsync
+@subsection bcastsync option (-b)
+@cindex ntpdsim-bcastsync
+
+This is the ``allow us to sync to broadcast servers'' option.
+
+
+@node ntpdsim simbroadcastdelay
+@subsection simbroadcastdelay option (-B)
+@cindex ntpdsim-simbroadcastdelay
+
+This is the ``simulator broadcast delay'' option.
+
+
+@node ntpdsim configfile
+@subsection configfile option (-c)
+@cindex ntpdsim-configfile
+
+This is the ``configuration file name'' option.
+The name and path of the configuration file,
+/etc/ntp.conf
+by default.
+
+@node ntpdsim phasenoise
+@subsection phasenoise option (-C)
+@cindex ntpdsim-phasenoise
+
+This is the ``phase noise level'' option.
+
+
+@node ntpdsim debug-level
+@subsection debug-level option (-d)
+@cindex ntpdsim-debug-level
+
+This is the ``increase output debug message level'' option.
+
+This option has some usage constraints.  It:
+@itemize @bullet
+@item
+may appear an unlimited number of times.
+@end itemize
+
+Increase the debugging message output level.
+
+@node ntpdsim set-debug-level
+@subsection set-debug-level option (-D)
+@cindex ntpdsim-set-debug-level
+
+This is the ``set the output debug message level'' option.
+
+This option has some usage constraints.  It:
+@itemize @bullet
+@item
+may appear an unlimited number of times.
+@end itemize
+
+Set the output debugging level.  Can be supplied multiple times,
+but each overrides the previous value(s).
+
+@node ntpdsim driftfile
+@subsection driftfile option (-f)
+@cindex ntpdsim-driftfile
+
+This is the ``frequency drift file name'' option.
+The name and path of the frequency file,
+/etc/ntp.drift
+by default.
+This is the same operation as the
+driftfile driftfile
+configuration specification in the 
+/etc/ntp.conf
+file.
+
+@node ntpdsim panicgate
+@subsection panicgate option (-g)
+@cindex ntpdsim-panicgate
+
+This is the ``allow the first adjustment to be big'' option.
+Normally,
+ntpd
+exits with a message to the system log if the offset exceeds the panic threshold, which is 1000 s by default. This option allows the time to be set to any value without restriction; however, this can happen only once. If the threshold is exceeded after that,
+ntpd
+will exit with a message to the system log. This option can be used with the
+-q
+and
+-x
+options.
+See the
+tinker
+configuration file directive for other options.
+
+@node ntpdsim simslew
+@subsection simslew option (-H)
+@cindex ntpdsim-simslew
+
+This is the ``simuator slew'' option.
+
+
+@node ntpdsim jaildir
+@subsection jaildir option (-i)
+@cindex ntpdsim-jaildir
+
+This is the ``jail directory'' option.
+Chroot the server to the directory
+jaildir
+.
+This option also implies that the server attempts to drop root privileges at startup (otherwise, chroot gives very little additional security), and it is only available if the OS supports to run the server without full root privileges.
+You may need to also specify a
+-u
+option.
+
+@node ntpdsim interface
+@subsection interface option (-I)
+@cindex ntpdsim-interface
+
+This is the ``listen on interface'' option.
+
+This option has some usage constraints.  It:
+@itemize @bullet
+@item
+may appear an unlimited number of times.
+@end itemize
+
+
+
+@node ntpdsim keyfile
+@subsection keyfile option (-k)
+@cindex ntpdsim-keyfile
+
+This is the ``path to symmetric keys'' option.
+Specify the name and path of the symmetric key file.
+/etc/ntp.keys
+is the default.
+This is the same operation as the
+keys keyfile
+configuration file directive.
+
+@node ntpdsim logfile
+@subsection logfile option (-l)
+@cindex ntpdsim-logfile
+
+This is the ``path to the log file'' option.
+Specify the name and path of the log file.
+The default is the system log file.
+This is the same operation as the
+logfile logfile
+configuration file directive.
+
+@node ntpdsim novirtualips
+@subsection novirtualips option (-L)
+@cindex ntpdsim-novirtualips
+
+This is the ``do not listen to virtual ips'' option.
+Do not listen to virtual IPs. The default is to listen.
+
+@node ntpdsim nofork
+@subsection nofork option (-n)
+@cindex ntpdsim-nofork
+
+This is the ``do not fork'' option.
+
+
+@node ntpdsim nice
+@subsection nice option (-N)
+@cindex ntpdsim-nice
+
+This is the ``run at high priority'' option.
+To the extent permitted by the operating system, run
+ntpd
+at the highest priority.
+
+@node ntpdsim servertime
+@subsection servertime option (-O)
+@cindex ntpdsim-servertime
+
+This is the ``server time'' option.
+
+
+@node ntpdsim pidfile
+@subsection pidfile option (-p)
+@cindex ntpdsim-pidfile
+
+This is the ``path to the pid file'' option.
+Specify the name and path of the file used to record
+ntpd's
+process ID.
+This is the same operation as the
+pidfile pidfile
+configuration file directive.
+
+@node ntpdsim priority
+@subsection priority option (-P)
+@cindex ntpdsim-priority
+
+This is the ``process priority'' option.
+To the extent permitted by the operating system, run
+ntpd
+at the specified
+sched_setscheduler(SCHED_FIFO)
+priority.
+
+@node ntpdsim quit
+@subsection quit option (-q)
+@cindex ntpdsim-quit
+
+This is the ``set the time and quit'' option.
+ntpd
+will exit just after the first time the clock is set. This behavior mimics that of the
+ntpdate
+program, which is to be retired.
+The
+-g
+and
+-x
+options can be used with this option.
+Note: The kernel time discipline is disabled with this option.
+
+@node ntpdsim propagationdelay
+@subsection propagationdelay option (-r)
+@cindex ntpdsim-propagationdelay
+
+This is the ``broadcast/propagation delay'' option.
+Specify the default propagation delay from the broadcast/multicast server to this client. This is necessary only if the delay cannot be computed automatically by the protocol.
+
+@node ntpdsim updateinterval
+@subsection updateinterval option (-U)
+@cindex ntpdsim-updateinterval
+
+This is the ``interval in seconds between scans for new or dropped interfaces'' option.
+Give the time in seconds between two scans for new or dropped interfaces.
+For systems with routing socket support the scans will be performed shortly after the interface change
+has been detected by the system.
+Use 0 to disable scanning. 60 seconds is the minimum time between scans.
+
+@node ntpdsim statsdir
+@subsection statsdir option (-s)
+@cindex ntpdsim-statsdir
+
+This is the ``statistics file location'' option.
+Specify the directory path for files created by the statistics facility.
+This is the same operation as the
+statsdir statsdir
+configuration file directive.
+
+@node ntpdsim endsimtime
+@subsection endsimtime option (-S)
+@cindex ntpdsim-endsimtime
+
+This is the ``simulation end time'' option.
+
+
+@node ntpdsim trustedkey
+@subsection trustedkey option (-t)
+@cindex ntpdsim-trustedkey
+
+This is the ``trusted key number'' option.
+
+This option has some usage constraints.  It:
+@itemize @bullet
+@item
+may appear an unlimited number of times.
+@end itemize
+
+Add a key number to the trusted key list.
+
+@node ntpdsim freqerr
+@subsection freqerr option (-T)
+@cindex ntpdsim-freqerr
+
+This is the ``simulation frequency error'' option.
+
+
+@node ntpdsim walknoise
+@subsection walknoise option (-W)
+@cindex ntpdsim-walknoise
+
+This is the ``simulation random walk noise'' option.
+
+
+@node ntpdsim user
+@subsection user option (-u)
+@cindex ntpdsim-user
+
+This is the ``run as userid (or userid:groupid)'' option.
+Specify a user, and optionally a group, to switch to.
+This option is only available if the OS supports to run the server without full root privileges.
+Currently, this option is supported under NetBSD (configure with
+--enable-clockctl
+) and Linux (configure with
+--enable-linuxcaps
+).
+
+@node ntpdsim var
+@subsection var option (-v)
+@cindex ntpdsim-var
+
+This is the ``make arg an ntp variable (rw)'' option.
+
+This option has some usage constraints.  It:
+@itemize @bullet
+@item
+may appear an unlimited number of times.
+@end itemize
+
+
+
+@node ntpdsim dvar
+@subsection dvar option (-V)
+@cindex ntpdsim-dvar
+
+This is the ``make arg an ntp variable (rw|def)'' option.
+
+This option has some usage constraints.  It:
+@itemize @bullet
+@item
+may appear an unlimited number of times.
+@end itemize
+
+
+
+@node ntpdsim slew
+@subsection slew option (-x)
+@cindex ntpdsim-slew
+
+This is the ``slew up to 600 seconds'' option.
+Normally, the time is slewed if the offset is less than the step threshold, which is 128 ms by default, and stepped if above the threshold.
+This option sets the threshold to 600 s, which is well within the accuracy window to set the clock manually.
+Note: Since the slew rate of typical Unix kernels is limited to 0.5 ms/s, each second of adjustment requires an amortization interval of 2000 s.
+Thus, an adjustment as much as 600 s will take almost 14 days to complete.
+This option can be used with the
+-g
+and
+-q
+options.
+See the
+tinker
+configuration file directive for other options.
+Note: The kernel time discipline is disabled with this option.
+
+@node ntpdsim ndelay
+@subsection ndelay option (-Y)
+@cindex ntpdsim-ndelay
+
+This is the ``simulation network delay'' option.
+
+
+@node ntpdsim pdelay
+@subsection pdelay option (-Z)
+@cindex ntpdsim-pdelay
+
+This is the ``simulation processing delay'' option.
+
diff --git a/ntpd/ntpdsim.1 b/ntpd/ntpdsim.1
new file mode 100644 (file)
index 0000000..1f629d1
--- /dev/null
@@ -0,0 +1,352 @@
+.TH NTPDSIM 1 2006-06-27 "" "Programmer's Manual"
+.\"  DO NOT EDIT THIS FILE   (ntpdsim.1)
+.\"  
+.\"  It has been AutoGen-ed  Tuesday June 27, 2006 at 10:36:08 PM EDT
+.\"  From the definitions    ntpdsim-opts.def
+.\"  and the template file   agman1.tpl
+.\"
+.SH NAME
+ntpdsim \- NTP daemon simulation program
+.SH SYNOPSIS
+.B ntpdsim
+.\" Mixture of short (flag) options and long options
+.RB [ -\fIflag\fP " [\fIvalue\fP]]... [" --\fIopt-name\fP " [[=| ]\fIvalue\fP]]..."
+.PP
+All arguments must be options.
+.SH "DESCRIPTION"
+This manual page documents, briefly, the \fBntpdsim\fP command.
+
+.SH OPTIONS
+.TP
+.BR -4 ", " --ipv4
+Force IPv4 DNS name resolution.
+This option is a member of the ipv4 class of options.
+.sp
+Force DNS resolution of following host names on the command line
+to the IPv4 namespace.
+.TP
+.BR -6 ", " --ipv6
+Force IPv6 DNS name resolution.
+This option is a member of the ipv4 class of options.
+.sp
+Force DNS resolution of following host names on the command line
+to the IPv6 namespace.
+.TP
+.BR -a ", " --authreq
+Require crypto authentication.
+This option must not appear in combination with any of the following options:
+authnoreq.
+.sp
+Require cryptographic authentication for broadcast client,
+multicast client and symmetric passive associations.
+This is the default.
+.TP
+.BR -A ", " --authnoreq
+Do not require crypto authentication.
+This option must not appear in combination with any of the following options:
+authreq.
+.sp
+Do not require cryptographic authentication for broadcast client,
+multicast client and symmetric passive associations.
+This is almost never a good idea.
+.TP
+.BR -b ", " --bcastsync
+Allow us to sync to broadcast servers.
+.sp
+
+.TP
+.BR -B " \fIstring\fP, " --simbroadcastdelay "=" \fIstring\fP
+Simulator broadcast delay.
+.sp
+
+.TP
+.BR -c " \fIstring\fP, " --configfile "=" \fIstring\fP
+configuration file name.
+.sp
+The name and path of the configuration file,
+/etc/ntp.conf
+by default.
+.TP
+.BR -C " \fIstring\fP, " --phasenoise "=" \fIstring\fP
+Phase noise level.
+.sp
+
+.TP
+.BR -d ", " --debug-level
+Increase output debug message level.
+This option may appear an unlimited number of times.
+.sp
+Increase the debugging message output level.
+.TP
+.BR -D " \fIstring\fP, " --set-debug-level "=" \fIstring\fP
+Set the output debug message level.
+This option may appear an unlimited number of times.
+.sp
+Set the output debugging level.  Can be supplied multiple times,
+but each overrides the previous value(s).
+.TP
+.BR -f " \fIstring\fP, " --driftfile "=" \fIstring\fP
+frequency drift file name.
+.sp
+The name and path of the frequency file,
+/etc/ntp.drift
+by default.
+This is the same operation as the
+driftfile driftfile
+configuration specification in the 
+/etc/ntp.conf
+file.
+.TP
+.BR -g ", " --panicgate
+Allow the first adjustment to be Big.
+.sp
+Normally,
+ntpd
+exits with a message to the system log if the offset exceeds the panic threshold, which is 1000 s by default. This option allows the time to be set to any value without restriction; however, this can happen only once. If the threshold is exceeded after that,
+ntpd
+will exit with a message to the system log. This option can be used with the
+-q
+and
+-x
+options.
+See the
+tinker
+configuration file directive for other options.
+.TP
+.BR -H " \fIstring\fP, " --simslew "=" \fIstring\fP
+Simuator slew.
+.sp
+
+.TP
+.BR -i " \fIstring\fP, " --jaildir "=" \fIstring\fP
+Jail directory.
+.sp
+Chroot the server to the directory
+jaildir
+.
+This option also implies that the server attempts to drop root privileges at startup (otherwise, chroot gives very little additional security), and it is only available if the OS supports to run the server without full root privileges.
+You may need to also specify a
+-u
+option.
+.TP
+.BR -I " \fIiface\fP, " --interface "=" \fIiface\fP
+Listen on interface.
+This option may appear an unlimited number of times.
+.sp
+
+.TP
+.BR -k " \fIstring\fP, " --keyfile "=" \fIstring\fP
+path to symmetric keys.
+.sp
+Specify the name and path of the symmetric key file.
+/etc/ntp.keys
+is the default.
+This is the same operation as the
+keys keyfile
+configuration file directive.
+.TP
+.BR -l " \fIstring\fP, " --logfile "=" \fIstring\fP
+path to the log file.
+.sp
+Specify the name and path of the log file.
+The default is the system log file.
+This is the same operation as the
+logfile logfile
+configuration file directive.
+.TP
+.BR -L ", " --novirtualips
+Do not listen to virtual IPs.
+.sp
+Do not listen to virtual IPs. The default is to listen.
+.TP
+.BR -n ", " --nofork
+Do not fork.
+.sp
+
+.TP
+.BR -N ", " --nice
+Run at high priority.
+.sp
+To the extent permitted by the operating system, run
+ntpd
+at the highest priority.
+.TP
+.BR -O " \fIstring\fP, " --servertime "=" \fIstring\fP
+Server time.
+.sp
+
+.TP
+.BR -p " \fIstring\fP, " --pidfile "=" \fIstring\fP
+path to the PID file.
+.sp
+Specify the name and path of the file used to record
+ntpd's
+process ID.
+This is the same operation as the
+pidfile pidfile
+configuration file directive.
+.TP
+.BR -P " \fInumber\fP, " --priority "=" \fInumber\fP
+Process priority.
+This option takes an integer number as its argument.
+.sp
+To the extent permitted by the operating system, run
+ntpd
+at the specified
+sched_setscheduler(SCHED_FIFO)
+priority.
+.TP
+.BR -q ", " --quit
+Set the time and quit.
+.sp
+ntpd
+will exit just after the first time the clock is set. This behavior mimics that of the
+ntpdate
+program, which is to be retired.
+The
+-g
+and
+-x
+options can be used with this option.
+Note: The kernel time discipline is disabled with this option.
+.TP
+.BR -r " \fIstring\fP, " --propagationdelay "=" \fIstring\fP
+Broadcast/propagation delay.
+.sp
+Specify the default propagation delay from the broadcast/multicast server to this client. This is necessary only if the delay cannot be computed automatically by the protocol.
+.TP
+.BR -U " \fInumber\fP, " --updateinterval "=" \fInumber\fP
+interval in seconds between scans for new or dropped interfaces.
+This option takes an integer number as its argument.
+.sp
+Give the time in seconds between two scans for new or dropped interfaces.
+For systems with routing socket support the scans will be performed shortly after the interface change
+has been detected by the system.
+Use 0 to disable scanning. 60 seconds is the minimum time between scans.
+.TP
+.BR -s " \fIstring\fP, " --statsdir "=" \fIstring\fP
+Statistics file location.
+.sp
+Specify the directory path for files created by the statistics facility.
+This is the same operation as the
+statsdir statsdir
+configuration file directive.
+.TP
+.BR -S " \fIstring\fP, " --endsimtime "=" \fIstring\fP
+Simulation end time.
+.sp
+
+.TP
+.BR -t " \fItkey\fP, " --trustedkey "=" \fItkey\fP
+Trusted key number.
+This option may appear an unlimited number of times.
+.sp
+Add a key number to the trusted key list.
+.TP
+.BR -T " \fIstring\fP, " --freqerr "=" \fIstring\fP
+Simulation frequency error.
+.sp
+
+.TP
+.BR -W " \fIstring\fP, " --walknoise "=" \fIstring\fP
+Simulation random walk noise.
+.sp
+
+.TP
+.BR -u " \fIstring\fP, " --user "=" \fIstring\fP
+Run as userid (or userid:groupid).
+.sp
+Specify a user, and optionally a group, to switch to.
+This option is only available if the OS supports to run the server without full root privileges.
+Currently, this option is supported under NetBSD (configure with
+--enable-clockctl
+) and Linux (configure with
+--enable-linuxcaps
+).
+.TP
+.BR -v " \fInvar\fP, " --var "=" \fInvar\fP
+make ARG an ntp variable (RW).
+This option may appear an unlimited number of times.
+.sp
+
+.TP
+.BR -V " \fIndvar\fP, " --dvar "=" \fIndvar\fP
+make ARG an ntp variable (RW|DEF).
+This option may appear an unlimited number of times.
+.sp
+
+.TP
+.BR -x " \fIstring\fP, " --slew "=" \fIstring\fP
+Slew up to 600 seconds.
+.sp
+Normally, the time is slewed if the offset is less than the step threshold, which is 128 ms by default, and stepped if above the threshold.
+This option sets the threshold to 600 s, which is well within the accuracy window to set the clock manually.
+Note: Since the slew rate of typical Unix kernels is limited to 0.5 ms/s, each second of adjustment requires an amortization interval of 2000 s.
+Thus, an adjustment as much as 600 s will take almost 14 days to complete.
+This option can be used with the
+-g
+and
+-q
+options.
+See the
+tinker
+configuration file directive for other options.
+Note: The kernel time discipline is disabled with this option.
+.TP
+.BR -Y " \fIstring\fP, " --ndelay "=" \fIstring\fP
+Simulation network delay.
+.sp
+
+.TP
+.BR -Z " \fIstring\fP, " --pdelay "=" \fIstring\fP
+Simulation processing delay.
+.sp
+
+.TP
+.BR \-? , " \--help"
+Display usage information and exit.
+.TP
+.BR \-! , " \--more-help"
+Extended usage information passed thru pager.
+.TP
+.BR \-> " [\fIrcfile\fP]," " \--save-opts" "[=\fIrcfile\fP]"
+Save the option state to \fIrcfile\fP.  The default is the \fIlast\fP
+configuration file listed in the \fBOPTION PRESETS\fP section, below.
+.TP
+.BR \-< " \fIrcfile\fP," " \--load-opts" "=\fIrcfile\fP," " --no-load-opts"
+Load options from \fIrcfile\fP.
+The \fIno-load-opts\fP form will disable the loading
+of earlier RC/INI files.  \fI--no-load-opts\fP is handled early,
+out of order.
+.TP
+.BR \-v " [{\fIv|c|n\fP}]," " \--version" "[=\fI{v|c|n}\fP]"
+Output version of program and exit.  The default mode is `v', a simple
+version.  The `c' mode will print copyright information and `n' will
+print the full copyright notice.
+.SH OPTION PRESETS
+Any option that is not marked as \fInot presettable\fP may be preset
+by loading values from configuration ("RC" or ".INI") file(s) and values from
+environment variables named:
+.nf
+  \fBNTPDSIM_<option-name>\fP or \fBNTPDSIM\fP
+.fi
+.aj
+The environmental presets take precedence (are processed later than)
+the configuration files.
+The \fIhomerc\fP files are "\fI$HOME\fP", "\fI.\fP", "\fI$HOME\fP", and "\fI.\fP".
+If any of these are directories, then the file \fI.ntprc\fP
+is searched for within those directories.
+.SH AUTHOR
+ntp.org
+.br
+Please send bug reports to:  http://bugs.ntp.isc.org, bugs@ntp.org
+
+.PP
+.nf
+.na
+see html/copyright.html
+.fi
+.ad
+.PP
+This manual page was \fIAutoGen\fP-erated from the \fBntpdsim\fP
+option definitions.
diff --git a/ntpdc/ntpdc-opts.c b/ntpdc/ntpdc-opts.c
new file mode 100644 (file)
index 0000000..23a8ae4
--- /dev/null
@@ -0,0 +1,606 @@
+/*   -*- buffer-read-only: t -*- vi: set ro:
+ *  
+ *  DO NOT EDIT THIS FILE   (ntpdc-opts.c)
+ *  
+ *  It has been AutoGen-ed  Tuesday June 27, 2006 at 10:16:51 PM EDT
+ *  From the definitions    ntpdc-opts.def
+ *  and the template file   options
+ */
+
+#define OPTION_CODE_COMPILE 1
+#include "ntpdc-opts.h"
+
+#ifdef  __cplusplus
+extern "C" {
+#endif
+tSCC zCopyright[] =
+       "ntpdc copyright (c) 1970-2006 ntp.org, all rights reserved";
+tSCC zCopyrightNotice[] =
+       
+/* extracted from /backroom/ntp-dev-hms/include/copyright.def near line 8 */
+"see html/copyright.html";
+extern tUsageProc optionUsage;
+
+/*
+ *  global included definitions
+ */
+#ifdef __windows
+  extern int atoi(const char*);
+#else
+# include <stdlib.h>
+#endif
+
+#ifndef NULL
+#  define NULL 0
+#endif
+#ifndef EXIT_SUCCESS
+#  define  EXIT_SUCCESS 0
+#endif
+#ifndef EXIT_FAILURE
+#  define  EXIT_FAILURE 1
+#endif
+/*
+ *  Ipv4 option description:
+ */
+tSCC    zIpv4Text[] =
+        "Force IPv4 DNS name resolution";
+tSCC    zIpv4_NAME[]               = "IPV4";
+tSCC    zIpv4_Name[]               = "ipv4";
+#define IPV4_FLAGS       (OPTST_DISABLED)
+
+/*
+ *  Ipv6 option description:
+ */
+tSCC    zIpv6Text[] =
+        "Force IPv6 DNS name resolution";
+tSCC    zIpv6_NAME[]               = "IPV6";
+tSCC    zIpv6_Name[]               = "ipv6";
+#define IPV6_FLAGS       (OPTST_DISABLED)
+
+/*
+ *  Command option description:
+ */
+tSCC    zCommandText[] =
+        "run a command and exit";
+tSCC    zCommand_NAME[]            = "COMMAND";
+tSCC    zCommand_Name[]            = "command";
+#define COMMAND_FLAGS       (OPTST_DISABLED | OPTST_STACKED \
+       | OPTST_SET_ARGTYPE(OPARG_TYPE_STRING))
+
+/*
+ *  Listpeers option description with
+ *  "Must also have options" and "Incompatible options":
+ */
+tSCC    zListpeersText[] =
+        "Print a list of the peers";
+tSCC    zListpeers_NAME[]          = "LISTPEERS";
+tSCC    zListpeers_Name[]          = "listpeers";
+static const int
+    aListpeersCantList[] = {
+    INDEX_OPT_COMMAND, NO_EQUIVALENT };
+#define LISTPEERS_FLAGS       (OPTST_DISABLED)
+
+/*
+ *  Peers option description with
+ *  "Must also have options" and "Incompatible options":
+ */
+tSCC    zPeersText[] =
+        "Print a list of the peers";
+tSCC    zPeers_NAME[]              = "PEERS";
+tSCC    zPeers_Name[]              = "peers";
+static const int
+    aPeersCantList[] = {
+    INDEX_OPT_COMMAND, NO_EQUIVALENT };
+#define PEERS_FLAGS       (OPTST_DISABLED)
+
+/*
+ *  Showpeers option description with
+ *  "Must also have options" and "Incompatible options":
+ */
+tSCC    zShowpeersText[] =
+        "Show a list of the peers";
+tSCC    zShowpeers_NAME[]          = "SHOWPEERS";
+tSCC    zShowpeers_Name[]          = "showpeers";
+static const int
+    aShowpeersCantList[] = {
+    INDEX_OPT_COMMAND, NO_EQUIVALENT };
+#define SHOWPEERS_FLAGS       (OPTST_DISABLED)
+
+/*
+ *  Interactive option description with
+ *  "Must also have options" and "Incompatible options":
+ */
+tSCC    zInteractiveText[] =
+        "Force ntpq to operate in interactive mode";
+tSCC    zInteractive_NAME[]        = "INTERACTIVE";
+tSCC    zInteractive_Name[]        = "interactive";
+static const int
+    aInteractiveCantList[] = {
+    INDEX_OPT_COMMAND,
+    INDEX_OPT_LISTPEERS,
+    INDEX_OPT_PEERS,
+    INDEX_OPT_SHOWPEERS, NO_EQUIVALENT };
+#define INTERACTIVE_FLAGS       (OPTST_DISABLED)
+
+/*
+ *  Debug_Level option description:
+ */
+tSCC    zDebug_LevelText[] =
+        "Increase output debug message level";
+tSCC    zDebug_Level_NAME[]        = "DEBUG_LEVEL";
+tSCC    zDebug_Level_Name[]        = "debug-level";
+#define DEBUG_LEVEL_FLAGS       (OPTST_DISABLED)
+
+/*
+ *  Set_Debug_Level option description:
+ */
+tSCC    zSet_Debug_LevelText[] =
+        "Set the output debug message level";
+tSCC    zSet_Debug_Level_NAME[]    = "SET_DEBUG_LEVEL";
+tSCC    zSet_Debug_Level_Name[]    = "set-debug-level";
+#define SET_DEBUG_LEVEL_FLAGS       (OPTST_DISABLED \
+       | OPTST_SET_ARGTYPE(OPARG_TYPE_STRING))
+
+/*
+ *  Numeric option description:
+ */
+tSCC    zNumericText[] =
+        "numeric host addresses";
+tSCC    zNumeric_NAME[]            = "NUMERIC";
+tSCC    zNumeric_Name[]            = "numeric";
+#define NUMERIC_FLAGS       (OPTST_DISABLED)
+
+/*
+ *  Help/More_Help/Version option descriptions:
+ */
+tSCC zHelpText[]       = "Display usage information and exit";
+tSCC zHelp_Name[]      = "help";
+
+tSCC zMore_HelpText[]  = "Extended usage information passed thru pager";
+tSCC zMore_Help_Name[] = "more-help";
+
+tSCC zVersionText[]    = "Output version information and exit";
+tSCC zVersion_Name[]   = "version";
+
+/*
+ *  Save/Load_Opts option description:
+ */
+tSCC zSave_OptsText[]     = "Save the option state to a config file";
+tSCC zSave_Opts_Name[]    = "save-opts";
+
+tSCC zLoad_OptsText[]     = "Load options from a config file";
+tSCC zLoad_Opts_NAME[]    = "LOAD_OPTS";
+
+tSCC zNotLoad_Opts_Name[] = "no-load-opts";
+tSCC zNotLoad_Opts_Pfx[]  = "no";
+#define zLoad_Opts_Name   (zNotLoad_Opts_Name + 3)
+/*
+ *  Declare option callback procedures
+ */
+/* extracted from optmain.tpl near line 586 */
+
+#if defined(TEST_NTPDC_OPTS)
+/*
+ *  Under test, omit argument processing, or call optionStackArg,
+ *  if multiple copies are allowed.
+ */
+extern tOptProc
+    optionPagedUsage, optionStackArg, optionVersionStderr;
+static tOptProc
+    doUsageOpt;
+
+/*
+ *  #define map the "normal" callout procs to the test ones...
+ */
+#define SET_DEBUG_LEVEL_OPT_PROC optionStackArg
+
+
+#else /* NOT defined TEST_NTPDC_OPTS */
+/*
+ *  When not under test, there are different procs to use
+ */
+extern tOptProc
+    optionPagedUsage, optionPrintVersion, optionStackArg;
+static tOptProc
+    doOptSet_Debug_Level, doUsageOpt;
+
+/*
+ *  #define map the "normal" callout procs
+ */
+#define SET_DEBUG_LEVEL_OPT_PROC doOptSet_Debug_Level
+
+#define SET_DEBUG_LEVEL_OPT_PROC doOptSet_Debug_Level
+#endif /* defined(TEST_NTPDC_OPTS) */
+#ifdef TEST_NTPDC_OPTS
+# define DOVERPROC optionVersionStderr
+#else
+# define DOVERPROC optionPrintVersion
+#endif /* TEST_NTPDC_OPTS */
+
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ *
+ *  Define the Ntpdc Option Descriptions.
+ */
+static tOptDesc optDesc[ OPTION_CT ] = {
+  {  /* entry idx, value */ 0, VALUE_OPT_IPV4,
+     /* equiv idx, value */ NO_EQUIVALENT, 0,
+     /* equivalenced to  */ NO_EQUIVALENT,
+     /* min, max, act ct */ 0, 1, 0,
+     /* opt state flags  */ IPV4_FLAGS, 0,
+     /* last opt argumnt */ NULL,
+     /* arg list/cookie  */ NULL,
+     /* must/cannot opts */ NULL, NULL,
+     /* option proc      */ NULL,
+     /* desc, NAME, name */ zIpv4Text, zIpv4_NAME, zIpv4_Name,
+     /* disablement strs */ NULL, NULL },
+
+  {  /* entry idx, value */ 1, VALUE_OPT_IPV6,
+     /* equiv idx, value */ NOLIMIT, NOLIMIT,
+     /* equivalenced to  */ INDEX_OPT_IPV4,
+     /* min, max, act ct */ 0, 1, 0,
+     /* opt state flags  */ IPV6_FLAGS, 0,
+     /* last opt argumnt */ NULL,
+     /* arg list/cookie  */ NULL,
+     /* must/cannot opts */ NULL, NULL,
+     /* option proc      */ NULL,
+     /* desc, NAME, name */ zIpv6Text, zIpv6_NAME, zIpv6_Name,
+     /* disablement strs */ NULL, NULL },
+
+  {  /* entry idx, value */ 2, VALUE_OPT_COMMAND,
+     /* equiv idx, value */ 2, VALUE_OPT_COMMAND,
+     /* equivalenced to  */ NO_EQUIVALENT,
+     /* min, max, act ct */ 0, NOLIMIT, 0,
+     /* opt state flags  */ COMMAND_FLAGS, 0,
+     /* last opt argumnt */ NULL,
+     /* arg list/cookie  */ NULL,
+     /* must/cannot opts */ NULL, NULL,
+     /* option proc      */ optionStackArg,
+     /* desc, NAME, name */ zCommandText, zCommand_NAME, zCommand_Name,
+     /* disablement strs */ NULL, NULL },
+
+  {  /* entry idx, value */ 3, VALUE_OPT_LISTPEERS,
+     /* equiv idx, value */ 3, VALUE_OPT_LISTPEERS,
+     /* equivalenced to  */ NO_EQUIVALENT,
+     /* min, max, act ct */ 0, 1, 0,
+     /* opt state flags  */ LISTPEERS_FLAGS, 0,
+     /* last opt argumnt */ NULL,
+     /* arg list/cookie  */ NULL,
+     /* must/cannot opts */ NULL, aListpeersCantList,
+     /* option proc      */ NULL,
+     /* desc, NAME, name */ zListpeersText, zListpeers_NAME, zListpeers_Name,
+     /* disablement strs */ NULL, NULL },
+
+  {  /* entry idx, value */ 4, VALUE_OPT_PEERS,
+     /* equiv idx, value */ 4, VALUE_OPT_PEERS,
+     /* equivalenced to  */ NO_EQUIVALENT,
+     /* min, max, act ct */ 0, 1, 0,
+     /* opt state flags  */ PEERS_FLAGS, 0,
+     /* last opt argumnt */ NULL,
+     /* arg list/cookie  */ NULL,
+     /* must/cannot opts */ NULL, aPeersCantList,
+     /* option proc      */ NULL,
+     /* desc, NAME, name */ zPeersText, zPeers_NAME, zPeers_Name,
+     /* disablement strs */ NULL, NULL },
+
+  {  /* entry idx, value */ 5, VALUE_OPT_SHOWPEERS,
+     /* equiv idx, value */ 5, VALUE_OPT_SHOWPEERS,
+     /* equivalenced to  */ NO_EQUIVALENT,
+     /* min, max, act ct */ 0, 1, 0,
+     /* opt state flags  */ SHOWPEERS_FLAGS, 0,
+     /* last opt argumnt */ NULL,
+     /* arg list/cookie  */ NULL,
+     /* must/cannot opts */ NULL, aShowpeersCantList,
+     /* option proc      */ NULL,
+     /* desc, NAME, name */ zShowpeersText, zShowpeers_NAME, zShowpeers_Name,
+     /* disablement strs */ NULL, NULL },
+
+  {  /* entry idx, value */ 6, VALUE_OPT_INTERACTIVE,
+     /* equiv idx, value */ 6, VALUE_OPT_INTERACTIVE,
+     /* equivalenced to  */ NO_EQUIVALENT,
+     /* min, max, act ct */ 0, 1, 0,
+     /* opt state flags  */ INTERACTIVE_FLAGS, 0,
+     /* last opt argumnt */ NULL,
+     /* arg list/cookie  */ NULL,
+     /* must/cannot opts */ NULL, aInteractiveCantList,
+     /* option proc      */ NULL,
+     /* desc, NAME, name */ zInteractiveText, zInteractive_NAME, zInteractive_Name,
+     /* disablement strs */ NULL, NULL },
+
+  {  /* entry idx, value */ 7, VALUE_OPT_DEBUG_LEVEL,
+     /* equiv idx, value */ 7, VALUE_OPT_DEBUG_LEVEL,
+     /* equivalenced to  */ NO_EQUIVALENT,
+     /* min, max, act ct */ 0, NOLIMIT, 0,
+     /* opt state flags  */ DEBUG_LEVEL_FLAGS, 0,
+     /* last opt argumnt */ NULL,
+     /* arg list/cookie  */ NULL,
+     /* must/cannot opts */ NULL, NULL,
+     /* option proc      */ NULL,
+     /* desc, NAME, name */ zDebug_LevelText, zDebug_Level_NAME, zDebug_Level_Name,
+     /* disablement strs */ NULL, NULL },
+
+  {  /* entry idx, value */ 8, VALUE_OPT_SET_DEBUG_LEVEL,
+     /* equiv idx, value */ 8, VALUE_OPT_SET_DEBUG_LEVEL,
+     /* equivalenced to  */ NO_EQUIVALENT,
+     /* min, max, act ct */ 0, NOLIMIT, 0,
+     /* opt state flags  */ SET_DEBUG_LEVEL_FLAGS, 0,
+     /* last opt argumnt */ NULL,
+     /* arg list/cookie  */ NULL,
+     /* must/cannot opts */ NULL, NULL,
+     /* option proc      */ SET_DEBUG_LEVEL_OPT_PROC,
+     /* desc, NAME, name */ zSet_Debug_LevelText, zSet_Debug_Level_NAME, zSet_Debug_Level_Name,
+     /* disablement strs */ NULL, NULL },
+
+  {  /* entry idx, value */ 9, VALUE_OPT_NUMERIC,
+     /* equiv idx, value */ 9, VALUE_OPT_NUMERIC,
+     /* equivalenced to  */ NO_EQUIVALENT,
+     /* min, max, act ct */ 0, 1, 0,
+     /* opt state flags  */ NUMERIC_FLAGS, 0,
+     /* last opt argumnt */ NULL,
+     /* arg list/cookie  */ NULL,
+     /* must/cannot opts */ NULL, NULL,
+     /* option proc      */ NULL,
+     /* desc, NAME, name */ zNumericText, zNumeric_NAME, zNumeric_Name,
+     /* disablement strs */ NULL, NULL },
+
+  {  /* entry idx, value */ INDEX_OPT_VERSION, VALUE_OPT_VERSION,
+     /* equiv idx value  */ NO_EQUIVALENT, 0,
+     /* equivalenced to  */ NO_EQUIVALENT,
+     /* min, max, act ct */ 0, 1, 0,
+     /* opt state flags  */ OPTST_SET_ARGTYPE(OPARG_TYPE_STRING)
+                          | OPTST_ARG_OPTIONAL, 0,
+     /* last opt argumnt */ NULL,
+     /* arg list/cookie  */ NULL,
+     /* must/cannot opts */ NULL, NULL,
+     /* option proc      */ DOVERPROC,
+     /* desc, NAME, name */ zVersionText, NULL, zVersion_Name,
+     /* disablement strs */ NULL, NULL },
+
+  {  /* entry idx, value */ INDEX_OPT_HELP, VALUE_OPT_HELP,
+     /* equiv idx value  */ NO_EQUIVALENT, 0,
+     /* equivalenced to  */ NO_EQUIVALENT,
+     /* min, max, act ct */ 0, 1, 0,
+     /* opt state flags  */ OPTST_IMM, 0,
+     /* last opt argumnt */ NULL,
+     /* arg list/cookie  */ NULL,
+     /* must/cannot opts */ NULL, NULL,
+     /* option proc      */ doUsageOpt,
+     /* desc, NAME, name */ zHelpText, NULL, zHelp_Name,
+     /* disablement strs */ NULL, NULL },
+
+  {  /* entry idx, value */ INDEX_OPT_MORE_HELP, VALUE_OPT_MORE_HELP,
+     /* equiv idx value  */ NO_EQUIVALENT, 0,
+     /* equivalenced to  */ NO_EQUIVALENT,
+     /* min, max, act ct */ 0, 1, 0,
+     /* opt state flags  */ OPTST_IMM, 0,
+     /* last opt argumnt */ NULL,
+     /* arg list/cookie  */ NULL,
+     /* must/cannot opts */ NULL,  NULL,
+     /* option proc      */ optionPagedUsage,
+     /* desc, NAME, name */ zMore_HelpText, NULL, zMore_Help_Name,
+     /* disablement strs */ NULL, NULL },
+
+  {  /* entry idx, value */ INDEX_OPT_SAVE_OPTS, VALUE_OPT_SAVE_OPTS,
+     /* equiv idx value  */ NO_EQUIVALENT, 0,
+     /* equivalenced to  */ NO_EQUIVALENT,
+     /* min, max, act ct */ 0, 1, 0,
+     /* opt state flags  */ OPTST_SET_ARGTYPE(OPARG_TYPE_STRING)
+                          | OPTST_ARG_OPTIONAL, 0,
+     /* last opt argumnt */ NULL,
+     /* arg list/cookie  */ NULL,
+     /* must/cannot opts */ NULL,  NULL,
+     /* option proc      */ NULL,
+     /* desc, NAME, name */ zSave_OptsText, NULL, zSave_Opts_Name,
+     /* disablement strs */ NULL, NULL },
+
+  {  /* entry idx, value */ INDEX_OPT_LOAD_OPTS, VALUE_OPT_LOAD_OPTS,
+     /* equiv idx value  */ NO_EQUIVALENT, 0,
+     /* equivalenced to  */ NO_EQUIVALENT,
+     /* min, max, act ct */ 0, NOLIMIT, 0,
+     /* opt state flags  */ OPTST_DISABLE_IMM | \
+                       OPTST_SET_ARGTYPE(OPARG_TYPE_STRING), 0,
+     /* last opt argumnt */ NULL,
+     /* arg list/cookie  */ NULL,
+     /* must/cannot opts */ NULL, NULL,
+     /* option proc      */ optionLoadOpt,
+     /* desc, NAME, name */ zLoad_OptsText, zLoad_Opts_NAME, zLoad_Opts_Name,
+     /* disablement strs */ zNotLoad_Opts_Name, zNotLoad_Opts_Pfx }
+};
+
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ *
+ *  Define the Ntpdc Option Environment
+ */
+tSCC   zPROGNAME[]   = "NTPDC";
+tSCC   zUsageTitle[] =
+"ntpdc - vendor-specific NTP query program - Ver. 4.2.3p12\n\
+USAGE:  %s [ -<flag> [<val>] | --<name>[{=| }<val>] ]...\n";
+tSCC   zRcName[]     = ".ntprc";
+tSCC*  apzHomeList[] = {
+       "$HOME",
+       ".",
+       NULL };
+
+tSCC   zBugsAddr[]    = "http://bugs.ntp.isc.org, bugs@ntp.org";
+#define zExplain NULL
+tSCC    zDetail[]     = "\n\
+The\n\
+[= prog-name =]\n\
+utility program is used to query an NTP daemon about its\n\
+current state and to request changes in that state.\n\
+It uses NTP mode 7 control message formats described in the source code.\n\
+The program may\n\
+be run either in interactive mode or controlled using command line\n\
+arguments.\n\
+Extensive state and statistics information is available\n\
+through the\n\
+[= prog-name =]\n\
+interface.\n\
+In addition, nearly all the\n\
+configuration options which can be specified at startup using\n\
+ntpd's configuration file may also be specified at run time using\n\
+[= prog-name =] .\n";
+tSCC    zFullVersion[] = NTPDC_FULL_VERSION;
+/* extracted from optcode near line 321 */
+
+#if defined(ENABLE_NLS)
+# define OPTPROC_BASE OPTPROC_TRANSLATE
+  static tOptionXlateProc translate_option_strings;
+#else
+# define OPTPROC_BASE OPTPROC_NONE
+# define translate_option_strings NULL
+#endif /* ENABLE_NLS */
+
+tOptions ntpdcOptions = {
+    OPTIONS_STRUCT_VERSION,
+    0, NULL,                    /* original argc + argv    */
+    ( OPTPROC_BASE
+    + OPTPROC_ERRSTOP
+    + OPTPROC_SHORTOPT
+    + OPTPROC_LONGOPT
+    + OPTPROC_NO_REQ_OPT
+    + OPTPROC_ENVIRON
+    + OPTPROC_NO_ARGS
+    + OPTPROC_HAS_IMMED ),
+    0, NULL,                    /* current option index, current option */
+    NULL,         NULL,         zPROGNAME,
+    zRcName,      zCopyright,   zCopyrightNotice,
+    zFullVersion, apzHomeList,  zUsageTitle,
+    zExplain,     zDetail,      optDesc,
+    zBugsAddr,                  /* address to send bugs to */
+    NULL, NULL,                 /* extensions/saved state  */
+    optionUsage,       /* usage procedure */
+    translate_option_strings,   /* translation procedure */
+    /*
+     *  Indexes to special options
+     */
+    { INDEX_OPT_MORE_HELP,
+      INDEX_OPT_SAVE_OPTS,
+      NO_EQUIVALENT /* index of '-#' option */,
+      NO_EQUIVALENT /* index of default opt */
+    },
+    OPTION_CT, 10 /* user option count */
+};
+
+/*
+ *  Create the static procedure(s) declared above.
+ */
+static void
+doUsageOpt(
+    tOptions*   pOptions,
+    tOptDesc*   pOptDesc )
+{
+    USAGE( EXIT_SUCCESS );
+}
+
+#if ! defined(TEST_NTPDC_OPTS)
+
+/* * * * * * *
+ *
+ *   For the set-debug-level option.
+ */
+static void
+doOptSet_Debug_Level(
+    tOptions*   pOptions,
+    tOptDesc*   pOptDesc )
+{
+DESC(DEBUG_LEVEL).optOccCt = atoi( pOptDesc->pzLastArg );
+}
+
+#endif /* defined(TEST_NTPDC_OPTS) */
+
+/* extracted from optmain.tpl near line 92 */
+
+#if defined(TEST_NTPDC_OPTS) /* TEST MAIN PROCEDURE: */
+
+int
+main( int argc, char** argv )
+{
+    int res = EXIT_SUCCESS;
+    (void)optionProcess( &ntpdcOptions, argc, argv );
+    {
+        void optionPutShell( tOptions* );
+        optionPutShell( &ntpdcOptions );
+    }
+    return res;
+}
+#endif  /* defined TEST_NTPDC_OPTS */
+/* extracted from optcode near line 418 */
+
+#if ENABLE_NLS
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+#include <autoopts/usage-txt.h>
+
+static char*
+AO_gettext( const char* pz )
+{
+    char* pzRes;
+    if (pz == NULL)
+        return NULL;
+    pzRes = _(pz);
+    if (pzRes == pz)
+        return pzRes;
+    pzRes = strdup( pzRes );
+    if (pzRes == NULL) {
+        fputs( _("No memory for duping translated strings\n"), stderr );
+        exit( EXIT_FAILURE );
+    }
+    return pzRes;
+}
+
+/*
+ *  This invokes the translation code (e.g. gettext(3)).
+ */
+static void
+translate_option_strings( void )
+{
+    /*
+     *  Guard against re-translation.  It won't work.  The strings will have
+     *  been changed by the first pass through this code.  One shot only.
+     */
+    if (option_usage_text.field_ct == 0)
+        return;
+    /*
+     *  Do the translations.  The first pointer follows the field count field.
+     *  The field count field is the size of a pointer.
+     */
+    {
+        char** ppz = (char**)(void*)&(option_usage_text);
+        int    ix  = option_usage_text.field_ct;
+
+        do {
+            ppz++;
+            *ppz = AO_gettext(*ppz);
+        } while (--ix > 0);
+    }
+    option_usage_text.field_ct = 0;
+
+    {
+        tOptDesc* pOD = ntpdcOptions.pOptDesc;
+        int       ix  = ntpdcOptions.optCt;
+
+        for (;;) {
+            pOD->pzText           = AO_gettext(pOD->pzText);
+            pOD->pz_NAME          = AO_gettext(pOD->pz_NAME);
+            pOD->pz_Name          = AO_gettext(pOD->pz_Name);
+            pOD->pz_DisableName   = AO_gettext(pOD->pz_DisableName);
+            pOD->pz_DisablePfx    = AO_gettext(pOD->pz_DisablePfx);
+            if (--ix <= 0)
+                break;
+            pOD++;
+        }
+    }
+    ntpdcOptions.pzCopyright   = AO_gettext(ntpdcOptions.pzCopyright);
+    ntpdcOptions.pzCopyNotice  = AO_gettext(ntpdcOptions.pzCopyNotice);
+    ntpdcOptions.pzFullVersion = AO_gettext(ntpdcOptions.pzFullVersion);
+    ntpdcOptions.pzUsageTitle  = AO_gettext(ntpdcOptions.pzUsageTitle);
+    ntpdcOptions.pzExplain     = AO_gettext(ntpdcOptions.pzExplain);
+    ntpdcOptions.pzDetail      = AO_gettext(ntpdcOptions.pzDetail);
+}
+
+#endif /* ENABLE_NLS */
+
+#ifdef  __cplusplus
+}
+#endif
diff --git a/ntpdc/ntpdc-opts.h b/ntpdc/ntpdc-opts.h
new file mode 100644 (file)
index 0000000..1fe5d66
--- /dev/null
@@ -0,0 +1,155 @@
+/*   -*- buffer-read-only: t -*- vi: set ro:
+ *  
+ *  DO NOT EDIT THIS FILE   (ntpdc-opts.h)
+ *  
+ *  It has been AutoGen-ed  Tuesday June 27, 2006 at 10:16:50 PM EDT
+ *  From the definitions    ntpdc-opts.def
+ *  and the template file   options
+ */
+/*
+ *  This file contains the programmatic interface to the Automated
+ *  Options generated for the ntpdc program.
+ *  These macros are documented in the AutoGen info file in the
+ *  "AutoOpts" chapter.  Please refer to that doc for usage help.
+ */
+#ifndef AUTOOPTS_NTPDC_OPTS_H_GUARD
+#define AUTOOPTS_NTPDC_OPTS_H_GUARD
+
+/*
+ * ntpdc copyright 1970-2006 ntp.org - all rights reserved
+ *
+ * see html/copyright.html
+ */
+#include "config.h"
+#include <autoopts/options.h>
+
+/*
+ *  Ensure that the library used for compiling this generated header is at
+ *  least as new as the version current when the header template was released
+ *  (not counting patch version increments).  Also ensure that the oldest
+ *  tolerable version is at least as old as what was current when the header
+ *  template was released.
+ */
+#define AO_TEMPLATE_VERSION 110592
+#if (AO_TEMPLATE_VERSION < OPTIONS_MINIMUM_VERSION) \
+ || (AO_TEMPLATE_VERSION > OPTIONS_STRUCT_VERSION)
+# error option template version mismatches autoopts/options.h header
+#endif
+
+/*
+ *  Enumeration of each option:
+ */
+typedef enum {
+        INDEX_OPT_IPV4             =  0,
+        INDEX_OPT_IPV6             =  1,
+        INDEX_OPT_COMMAND          =  2,
+        INDEX_OPT_LISTPEERS        =  3,
+        INDEX_OPT_PEERS            =  4,
+        INDEX_OPT_SHOWPEERS        =  5,
+        INDEX_OPT_INTERACTIVE      =  6,
+        INDEX_OPT_DEBUG_LEVEL      =  7,
+        INDEX_OPT_SET_DEBUG_LEVEL  =  8,
+        INDEX_OPT_NUMERIC          =  9,
+        INDEX_OPT_VERSION          = 10,
+        INDEX_OPT_HELP             = 11,
+        INDEX_OPT_MORE_HELP        = 12,
+        INDEX_OPT_SAVE_OPTS        = 13,
+        INDEX_OPT_LOAD_OPTS        = 14
+} teOptIndex;
+
+#define OPTION_CT    15
+#define NTPDC_VERSION       "4.2.3p12"
+#define NTPDC_FULL_VERSION  "ntpdc - vendor-specific NTP query program - Ver. 4.2.3p12"
+
+/*
+ *  Interface defines for all options.  Replace "n" with
+ *  the UPPER_CASED option name (as in the teOptIndex
+ *  enumeration above).  e.g. HAVE_OPT( IPV4 )
+ */
+#define        DESC(n) ntpdcOptions.pOptDesc[INDEX_OPT_ ## n]
+#define     HAVE_OPT(n) (! UNUSED_OPT(& DESC(n)))
+#define      OPT_ARG(n) (DESC(n).pzLastArg)
+#define    STATE_OPT(n) (DESC(n).fOptState & OPTST_SET_MASK)
+#define    COUNT_OPT(n) (DESC(n).optOccCt)
+#define    ISSEL_OPT(n) (SELECTED_OPT(&DESC(n)))
+#define ISUNUSED_OPT(n) (UNUSED_OPT(& DESC(n)))
+#define  ENABLED_OPT(n) (! DISABLED_OPT(& DESC(n)))
+#define  STACKCT_OPT(n) (((tArgList*)(DESC(n).optCookie))->useCt)
+#define STACKLST_OPT(n) (((tArgList*)(DESC(n).optCookie))->apzArgs)
+#define    CLEAR_OPT(n) STMTS( \
+                DESC(n).fOptState &= OPTST_PERSISTENT;   \
+                if ( (DESC(n).fOptState & OPTST_INITENABLED) == 0) \
+                    DESC(n).fOptState |= OPTST_DISABLED; \
+                DESC(n).optCookie = NULL )
+
+/*
+ *  Interface defines for specific options.
+ */
+#define VALUE_OPT_IPV4           '4'
+#define WHICH_OPT_IPV4           (DESC(IPV4).optActualValue)
+#define WHICH_IDX_IPV4           (DESC(IPV4).optActualIndex)
+#define VALUE_OPT_IPV6           '6'
+#define VALUE_OPT_COMMAND        'c'
+#define VALUE_OPT_LISTPEERS      'l'
+#define VALUE_OPT_PEERS          'p'
+#define VALUE_OPT_SHOWPEERS      's'
+#define VALUE_OPT_INTERACTIVE    'i'
+#define VALUE_OPT_DEBUG_LEVEL    'd'
+#define VALUE_OPT_SET_DEBUG_LEVEL 'D'
+#define VALUE_OPT_NUMERIC        'n'
+
+#define VALUE_OPT_VERSION       'v'
+#define VALUE_OPT_SAVE_OPTS     '>'
+#define VALUE_OPT_LOAD_OPTS     '<'
+#define VALUE_OPT_HELP          '?'
+#define VALUE_OPT_MORE_HELP     '!'
+#define SET_OPT_SAVE_OPTS(a)   STMTS( \
+        DESC(SAVE_OPTS).fOptState &= OPTST_PERSISTENT; \
+        DESC(SAVE_OPTS).fOptState |= OPTST_SET; \
+        DESC(SAVE_OPTS).pzLastArg  = (const char*)(a) )
+/*
+ *  Interface defines not associated with particular options
+ */
+#define ERRSKIP_OPTERR  STMTS( ntpdcOptions.fOptSet &= ~OPTPROC_ERRSTOP )
+#define ERRSTOP_OPTERR  STMTS( ntpdcOptions.fOptSet |= OPTPROC_ERRSTOP )
+#define RESTART_OPT(n)  STMTS( \
+                ntpdcOptions.curOptIdx = (n); \
+                ntpdcOptions.pzCurOpt  = NULL )
+#define START_OPT       RESTART_OPT(1)
+#define USAGE(c)        (*ntpdcOptions.pUsageProc)( &ntpdcOptions, c )
+/* extracted from opthead near line 289 */
+
+/* * * * * *
+ *
+ *  Declare the ntpdc option descriptor.
+ */
+#ifdef  __cplusplus
+extern "C" {
+#endif
+
+extern tOptions   ntpdcOptions;
+
+#ifndef _
+#  if ENABLE_NLS
+#    include <stdio.h>
+     static inline char* aoGetsText( const char* pz ) {
+         if (pz == NULL) return NULL;
+         return (char*)gettext( pz );
+     }
+#    define _(s)  aoGetsText(s)
+#  else  /* ENABLE_NLS */
+#    define _(s)  s
+#  endif /* ENABLE_NLS */
+#endif
+
+#ifdef  __cplusplus
+}
+#endif
+#endif /* AUTOOPTS_NTPDC_OPTS_H_GUARD */
+/*
+ * Local Variables:
+ * Mode: C
+ * c-file-style: "stroustrup"
+ * indent-tabs-mode: nil
+ * End:
+ * options.h ends here */
diff --git a/ntpdc/ntpdc-opts.menu b/ntpdc/ntpdc-opts.menu
new file mode 100644 (file)
index 0000000..42ca3b4
--- /dev/null
@@ -0,0 +1 @@
+* ntpdc Invocation::               Invoking ntpdc
diff --git a/ntpdc/ntpdc-opts.texi b/ntpdc/ntpdc-opts.texi
new file mode 100644 (file)
index 0000000..d08e837
--- /dev/null
@@ -0,0 +1,272 @@
+@node ntpdc Invocation
+@section Invoking ntpdc
+@pindex ntpdc
+@cindex vendor-specific NTP query program
+@ignore
+#  -*- buffer-read-only: t -*- vi: set ro:
+# 
+# DO NOT EDIT THIS FILE   (ntpdc-opts.texi)
+# 
+# It has been AutoGen-ed  Tuesday June 27, 2006 at 10:37:18 PM EDT
+# From the definitions    ntpdc-opts.def
+# and the template file   aginfo.tpl
+@end ignore
+This program has no explanation.
+
+The
+[= prog-name =]
+utility program is used to query an NTP daemon about its
+current state and to request changes in that state.
+It uses NTP mode 7 control message formats described in the source code.
+The program may
+be run either in interactive mode or controlled using command line
+arguments.
+Extensive state and statistics information is available
+through the
+[= prog-name =]
+interface.
+In addition, nearly all the
+configuration options which can be specified at startup using
+ntpd's configuration file may also be specified at run time using
+[= prog-name =] .
+
+
+
+This section was generated by @strong{AutoGen},
+the aginfo template and the option descriptions for the @command{ntpdc} program.  It documents the ntpdc usage text and option meanings.
+
+This software is released under a specialized copyright license.
+
+@menu
+* ntpdc usage::                  ntpdc usage help (-?)
+* ntpdc command::                command option (-c)
+* ntpdc debug-level::            debug-level option (-d)
+* ntpdc interactive::            interactive option (-i)
+* ntpdc ipv4::                   ipv4 option (-4)
+* ntpdc ipv6::                   ipv6 option (-6)
+* ntpdc listpeers::              listpeers option (-l)
+* ntpdc numeric::                numeric option (-n)
+* ntpdc peers::                  peers option (-p)
+* ntpdc set-debug-level::        set-debug-level option (-D)
+* ntpdc showpeers::              showpeers option (-s)
+@end menu
+
+@node ntpdc usage
+@subsection ntpdc usage help (-?)
+@cindex ntpdc usage
+
+This is the automatically generated usage text for ntpdc:
+
+@exampleindent 0
+@example
+ntpdc - vendor-specific NTP query program - Ver. 4.2.3p10
+USAGE:  ntpdc [ -<flag> [<val>] | --<name>[@{=| @}<val>] ]...
+  Flg Arg Option-Name    Description
+   -4 no  ipv4           Force IPv4 DNS name resolution
+   -6 no  ipv6           Force IPv6 DNS name resolution
+                                - an alternate for ipv4
+   -c Str command        run a command and exit
+                                - may appear multiple times
+   -l no  listpeers      Print a list of the peers
+                                - prohibits these options:
+                                command
+   -p no  peers          Print a list of the peers
+                                - prohibits these options:
+                                command
+   -s no  showpeers      Show a list of the peers
+                                - prohibits these options:
+                                command
+   -i no  interactive    Force ntpq to operate in interactive mode
+                                - prohibits these options:
+                                command
+                                listpeers
+                                peers
+                                showpeers
+   -d no  debug-level    Increase output debug message level
+                                - may appear multiple times
+   -D Str set-debug-level Set the output debug message level
+                                - may appear multiple times
+   -n no  numeric        numeric host addresses
+   -v opt version        Output version information and exit
+   -? no  help           Display usage information and exit
+   -! no  more-help      Extended usage information passed thru pager
+   -> opt save-opts      Save the option state to a config file
+   -< Str load-opts      Load options from a config file
+                                - disabled as --no-load-opts
+                                - may appear multiple times
+
+Options are specified by doubled hyphens and their name
+or by a single hyphen and the flag character.
+
+The following option preset mechanisms are supported:
+ - reading file /users/stenn/.ntprc
+ - reading file /deacon/backroom/ntp-dev-hms/ntpdc/.ntprc
+ - examining environment variables named NTPDC_*
+
+The
+[= prog-name =]
+utility program is used to query an NTP daemon about its
+current state and to request changes in that state.
+It uses NTP mode 7 control message formats described in the source code.
+The program may
+be run either in interactive mode or controlled using command line
+arguments.
+Extensive state and statistics information is available
+through the
+[= prog-name =]
+interface.
+In addition, nearly all the
+configuration options which can be specified at startup using
+ntpd's configuration file may also be specified at run time using
+[= prog-name =] .
+
+please send bug reports to:  http://bugs.ntp.isc.org, bugs@@ntp.org
+@end example
+@exampleindent 4
+
+@node ntpdc ipv4
+@subsection ipv4 option (-4)
+@cindex ntpdc-ipv4
+
+This is the ``force ipv4 dns name resolution'' option.
+
+This option has some usage constraints.  It:
+@itemize @bullet
+@item
+is a member of the ipv4 class of options.
+@end itemize
+
+Force DNS resolution of following host names on the command line
+to the IPv4 namespace.
+
+@node ntpdc ipv6
+@subsection ipv6 option (-6)
+@cindex ntpdc-ipv6
+
+This is the ``force ipv6 dns name resolution'' option.
+
+This option has some usage constraints.  It:
+@itemize @bullet
+@item
+is a member of the ipv4 class of options.
+@end itemize
+
+Force DNS resolution of following host names on the command line
+to the IPv6 namespace.
+
+@node ntpdc command
+@subsection command option (-c)
+@cindex ntpdc-command
+
+This is the ``run a command and exit'' option.
+
+This option has some usage constraints.  It:
+@itemize @bullet
+@item
+may appear an unlimited number of times.
+@end itemize
+
+The following argument is interpreted as an interactive format command
+and is added to the list of commands to be executed on the specified
+host(s).
+
+@node ntpdc listpeers
+@subsection listpeers option (-l)
+@cindex ntpdc-listpeers
+
+This is the ``print a list of the peers'' option.
+
+This option has some usage constraints.  It:
+@itemize @bullet
+@item
+must not appear in combination with any of the following options:
+command.
+@end itemize
+
+Print a list of the peers known to the server as well as a summary of
+their state. This is equivalent to the 'listpeers' interactive command.
+
+@node ntpdc peers
+@subsection peers option (-p)
+@cindex ntpdc-peers
+
+This is the ``print a list of the peers'' option.
+
+This option has some usage constraints.  It:
+@itemize @bullet
+@item
+must not appear in combination with any of the following options:
+command.
+@end itemize
+
+Print a list of the peers known to the server as well as a summary
+of their state. This is equivalent to the 'peers' interactive command.
+
+@node ntpdc showpeers
+@subsection showpeers option (-s)
+@cindex ntpdc-showpeers
+
+This is the ``show a list of the peers'' option.
+
+This option has some usage constraints.  It:
+@itemize @bullet
+@item
+must not appear in combination with any of the following options:
+command.
+@end itemize
+
+Print a list of the peers known to the server as well as a summary
+of their state. This is equivalent to the 'dmpeers' interactive command.
+
+@node ntpdc interactive
+@subsection interactive option (-i)
+@cindex ntpdc-interactive
+
+This is the ``force ntpq to operate in interactive mode'' option.
+
+This option has some usage constraints.  It:
+@itemize @bullet
+@item
+must not appear in combination with any of the following options:
+command, listpeers, peers, showpeers.
+@end itemize
+
+Force ntpq to operate in interactive mode.  Prompts will be written
+to the standard output and commands read from the standard input.
+
+@node ntpdc debug-level
+@subsection debug-level option (-d)
+@cindex ntpdc-debug-level
+
+This is the ``increase output debug message level'' option.
+
+This option has some usage constraints.  It:
+@itemize @bullet
+@item
+may appear an unlimited number of times.
+@end itemize
+
+Increase the debugging message output level.
+
+@node ntpdc set-debug-level
+@subsection set-debug-level option (-D)
+@cindex ntpdc-set-debug-level
+
+This is the ``set the output debug message level'' option.
+
+This option has some usage constraints.  It:
+@itemize @bullet
+@item
+may appear an unlimited number of times.
+@end itemize
+
+Set the output debugging level.  Can be supplied multiple times,
+but each overrides the previous value(s).
+
+@node ntpdc numeric
+@subsection numeric option (-n)
+@cindex ntpdc-numeric
+
+This is the ``numeric host addresses'' option.
+Output all host addresses in dotted-quad numeric format rather than
+converting to the canonical host names. 
diff --git a/ntpdc/ntpdc.1 b/ntpdc/ntpdc.1
new file mode 100644 (file)
index 0000000..4acd70e
--- /dev/null
@@ -0,0 +1,157 @@
+.TH NTPDC 1 2006-06-27 "" "Programmer's Manual"
+.\"  DO NOT EDIT THIS FILE   (ntpdc.1)
+.\"  
+.\"  It has been AutoGen-ed  Tuesday June 27, 2006 at 10:37:18 PM EDT
+.\"  From the definitions    ntpdc-opts.def
+.\"  and the template file   agman1.tpl
+.\"
+.SH NAME
+ntpdc \- vendor-specific NTP query program
+.SH SYNOPSIS
+.B ntpdc
+.\" Mixture of short (flag) options and long options
+.RB [ -\fIflag\fP " [\fIvalue\fP]]... [" --\fIopt-name\fP " [[=| ]\fIvalue\fP]]..."
+.PP
+All arguments must be options.
+.SH "DESCRIPTION"
+This manual page documents, briefly, the \fBntpdc\fP command.
+The
+[= prog-name =]
+utility program is used to query an NTP daemon about its
+current state and to request changes in that state.
+It uses NTP mode 7 control message formats described in the source code.
+The program may
+be run either in interactive mode or controlled using command line
+arguments.
+Extensive state and statistics information is available
+through the
+[= prog-name =]
+interface.
+In addition, nearly all the
+configuration options which can be specified at startup using
+ntpd's configuration file may also be specified at run time using
+[= prog-name =] .
+
+
+.SH OPTIONS
+.TP
+.BR -4 ", " --ipv4
+Force IPv4 DNS name resolution.
+This option is a member of the ipv4 class of options.
+.sp
+Force DNS resolution of following host names on the command line
+to the IPv4 namespace.
+.TP
+.BR -6 ", " --ipv6
+Force IPv6 DNS name resolution.
+This option is a member of the ipv4 class of options.
+.sp
+Force DNS resolution of following host names on the command line
+to the IPv6 namespace.
+.TP
+.BR -c " \fIcmd\fP, " --command "=" \fIcmd\fP
+run a command and exit.
+This option may appear an unlimited number of times.
+.sp
+The following argument is interpreted as an interactive format command
+and is added to the list of commands to be executed on the specified
+host(s).
+.TP
+.BR -l ", " --listpeers
+Print a list of the peers.
+This option must not appear in combination with any of the following options:
+command.
+.sp
+Print a list of the peers known to the server as well as a summary of
+their state. This is equivalent to the 'listpeers' interactive command.
+.TP
+.BR -p ", " --peers
+Print a list of the peers.
+This option must not appear in combination with any of the following options:
+command.
+.sp
+Print a list of the peers known to the server as well as a summary
+of their state. This is equivalent to the 'peers' interactive command.
+.TP
+.BR -s ", " --showpeers
+Show a list of the peers.
+This option must not appear in combination with any of the following options:
+command.
+.sp
+Print a list of the peers known to the server as well as a summary
+of their state. This is equivalent to the 'dmpeers' interactive command.
+.TP
+.BR -i ", " --interactive
+Force ntpq to operate in interactive mode.
+This option must not appear in combination with any of the following options:
+command, listpeers, peers, showpeers.
+.sp
+Force ntpq to operate in interactive mode.  Prompts will be written
+to the standard output and commands read from the standard input.
+.TP
+.BR -d ", " --debug-level
+Increase output debug message level.
+This option may appear an unlimited number of times.
+.sp
+Increase the debugging message output level.
+.TP
+.BR -D " \fIstring\fP, " --set-debug-level "=" \fIstring\fP
+Set the output debug message level.
+This option may appear an unlimited number of times.
+.sp
+Set the output debugging level.  Can be supplied multiple times,
+but each overrides the previous value(s).
+.TP
+.BR -n ", " --numeric
+numeric host addresses.
+.sp
+Output all host addresses in dotted-quad numeric format rather than
+converting to the canonical host names. 
+.TP
+.BR \-? , " \--help"
+Display usage information and exit.
+.TP
+.BR \-! , " \--more-help"
+Extended usage information passed thru pager.
+.TP
+.BR \-> " [\fIrcfile\fP]," " \--save-opts" "[=\fIrcfile\fP]"
+Save the option state to \fIrcfile\fP.  The default is the \fIlast\fP
+configuration file listed in the \fBOPTION PRESETS\fP section, below.
+.TP
+.BR \-< " \fIrcfile\fP," " \--load-opts" "=\fIrcfile\fP," " --no-load-opts"
+Load options from \fIrcfile\fP.
+The \fIno-load-opts\fP form will disable the loading
+of earlier RC/INI files.  \fI--no-load-opts\fP is handled early,
+out of order.
+.TP
+.BR \-v " [{\fIv|c|n\fP}]," " \--version" "[=\fI{v|c|n}\fP]"
+Output version of program and exit.  The default mode is `v', a simple
+version.  The `c' mode will print copyright information and `n' will
+print the full copyright notice.
+.SH OPTION PRESETS
+Any option that is not marked as \fInot presettable\fP may be preset
+by loading values from configuration ("RC" or ".INI") file(s) and values from
+environment variables named:
+.nf
+  \fBNTPDC_<option-name>\fP or \fBNTPDC\fP
+.fi
+.aj
+The environmental presets take precedence (are processed later than)
+the configuration files.
+The \fIhomerc\fP files are "\fI$HOME\fP", and "\fI.\fP".
+If any of these are directories, then the file \fI.ntprc\fP
+is searched for within those directories.
+.SH AUTHOR
+ntp.org
+.br
+Please send bug reports to:  http://bugs.ntp.isc.org, bugs@ntp.org
+
+.PP
+.nf
+.na
+see html/copyright.html
+.fi
+.ad
+.PP
+This manual page was \fIAutoGen\fP-erated from the \fBntpdc\fP
+option definitions.
diff --git a/ntpq/ntpq-opts.c b/ntpq/ntpq-opts.c
new file mode 100644 (file)
index 0000000..dbcee75
--- /dev/null
@@ -0,0 +1,781 @@
+/*   -*- buffer-read-only: t -*- vi: set ro:
+ *  
+ *  DO NOT EDIT THIS FILE   (ntpq-opts.c)
+ *  
+ *  It has been AutoGen-ed  Tuesday June 27, 2006 at 10:16:52 PM EDT
+ *  From the definitions    ntpq-opts.def
+ *  and the template file   options
+ */
+
+#define OPTION_CODE_COMPILE 1
+#include "ntpq-opts.h"
+
+#ifdef  __cplusplus
+extern "C" {
+#endif
+tSCC zCopyright[] =
+       "ntpq copyright (c) 1970-2006 ntp.org, all rights reserved";
+tSCC zCopyrightNotice[] =
+       
+/* extracted from /backroom/ntp-dev-hms/include/copyright.def near line 8 */
+"see html/copyright.html";
+extern tUsageProc optionUsage;
+
+/*
+ *  global included definitions
+ */
+#ifdef __windows
+  extern int atoi(const char*);
+#else
+# include <stdlib.h>
+#endif
+
+#ifndef NULL
+#  define NULL 0
+#endif
+#ifndef EXIT_SUCCESS
+#  define  EXIT_SUCCESS 0
+#endif
+#ifndef EXIT_FAILURE
+#  define  EXIT_FAILURE 1
+#endif
+/*
+ *  Ipv4 option description:
+ */
+tSCC    zIpv4Text[] =
+        "Force IPv4 DNS name resolution";
+tSCC    zIpv4_NAME[]               = "IPV4";
+tSCC    zIpv4_Name[]               = "ipv4";
+#define IPV4_FLAGS       (OPTST_DISABLED)
+
+/*
+ *  Ipv6 option description:
+ */
+tSCC    zIpv6Text[] =
+        "Force IPv6 DNS name resolution";
+tSCC    zIpv6_NAME[]               = "IPV6";
+tSCC    zIpv6_Name[]               = "ipv6";
+#define IPV6_FLAGS       (OPTST_DISABLED)
+
+/*
+ *  Command option description:
+ */
+tSCC    zCommandText[] =
+        "run a command and exit";
+tSCC    zCommand_NAME[]            = "COMMAND";
+tSCC    zCommand_Name[]            = "command";
+#define COMMAND_FLAGS       (OPTST_DISABLED | OPTST_STACKED \
+       | OPTST_SET_ARGTYPE(OPARG_TYPE_STRING))
+
+/*
+ *  Debug_Level option description:
+ */
+tSCC    zDebug_LevelText[] =
+        "Increase output debug message level";
+tSCC    zDebug_Level_NAME[]        = "DEBUG_LEVEL";
+tSCC    zDebug_Level_Name[]        = "debug-level";
+#define DEBUG_LEVEL_FLAGS       (OPTST_DISABLED)
+
+/*
+ *  Set_Debug_Level option description:
+ */
+tSCC    zSet_Debug_LevelText[] =
+        "Set the output debug message level";
+tSCC    zSet_Debug_Level_NAME[]    = "SET_DEBUG_LEVEL";
+tSCC    zSet_Debug_Level_Name[]    = "set-debug-level";
+#define SET_DEBUG_LEVEL_FLAGS       (OPTST_DISABLED \
+       | OPTST_SET_ARGTYPE(OPARG_TYPE_STRING))
+
+/*
+ *  Peers option description with
+ *  "Must also have options" and "Incompatible options":
+ */
+tSCC    zPeersText[] =
+        "Print a list of the peers";
+tSCC    zPeers_NAME[]              = "PEERS";
+tSCC    zPeers_Name[]              = "peers";
+static const int
+    aPeersCantList[] = {
+    INDEX_OPT_COMMAND, NO_EQUIVALENT };
+#define PEERS_FLAGS       (OPTST_DISABLED)
+
+/*
+ *  Interactive option description with
+ *  "Must also have options" and "Incompatible options":
+ */
+tSCC    zInteractiveText[] =
+        "Force ntpq to operate in interactive mode";
+tSCC    zInteractive_NAME[]        = "INTERACTIVE";
+tSCC    zInteractive_Name[]        = "interactive";
+static const int
+    aInteractiveCantList[] = {
+    INDEX_OPT_COMMAND,
+    INDEX_OPT_PEERS, NO_EQUIVALENT };
+#define INTERACTIVE_FLAGS       (OPTST_DISABLED)
+
+/*
+ *  Numeric option description:
+ */
+tSCC    zNumericText[] =
+        "numeric host addresses";
+tSCC    zNumeric_NAME[]            = "NUMERIC";
+tSCC    zNumeric_Name[]            = "numeric";
+#define NUMERIC_FLAGS       (OPTST_DISABLED)
+
+/*
+ *  Help/More_Help/Version option descriptions:
+ */
+tSCC zHelpText[]       = "Display usage information and exit";
+tSCC zHelp_Name[]      = "help";
+
+tSCC zMore_HelpText[]  = "Extended usage information passed thru pager";
+tSCC zMore_Help_Name[] = "more-help";
+
+tSCC zVersionText[]    = "Output version information and exit";
+tSCC zVersion_Name[]   = "version";
+
+/*
+ *  Save/Load_Opts option description:
+ */
+tSCC zSave_OptsText[]     = "Save the option state to a config file";
+tSCC zSave_Opts_Name[]    = "save-opts";
+
+tSCC zLoad_OptsText[]     = "Load options from a config file";
+tSCC zLoad_Opts_NAME[]    = "LOAD_OPTS";
+
+tSCC zNotLoad_Opts_Name[] = "no-load-opts";
+tSCC zNotLoad_Opts_Pfx[]  = "no";
+#define zLoad_Opts_Name   (zNotLoad_Opts_Name + 3)
+/*
+ *  Declare option callback procedures
+ */
+/* extracted from optmain.tpl near line 586 */
+
+#if defined(TEST_NTPQ_OPTS)
+/*
+ *  Under test, omit argument processing, or call optionStackArg,
+ *  if multiple copies are allowed.
+ */
+extern tOptProc
+    optionPagedUsage, optionStackArg, optionVersionStderr;
+static tOptProc
+    doUsageOpt;
+
+/*
+ *  #define map the "normal" callout procs to the test ones...
+ */
+#define SET_DEBUG_LEVEL_OPT_PROC optionStackArg
+
+
+#else /* NOT defined TEST_NTPQ_OPTS */
+/*
+ *  When not under test, there are different procs to use
+ */
+extern tOptProc
+    optionPagedUsage, optionPrintVersion, optionStackArg;
+static tOptProc
+    doOptSet_Debug_Level, doUsageOpt;
+
+/*
+ *  #define map the "normal" callout procs
+ */
+#define SET_DEBUG_LEVEL_OPT_PROC doOptSet_Debug_Level
+
+#define SET_DEBUG_LEVEL_OPT_PROC doOptSet_Debug_Level
+#endif /* defined(TEST_NTPQ_OPTS) */
+#ifdef TEST_NTPQ_OPTS
+# define DOVERPROC optionVersionStderr
+#else
+# define DOVERPROC optionPrintVersion
+#endif /* TEST_NTPQ_OPTS */
+
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ *
+ *  Define the Ntpq Option Descriptions.
+ */
+static tOptDesc optDesc[ OPTION_CT ] = {
+  {  /* entry idx, value */ 0, VALUE_OPT_IPV4,
+     /* equiv idx, value */ NO_EQUIVALENT, 0,
+     /* equivalenced to  */ NO_EQUIVALENT,
+     /* min, max, act ct */ 0, 1, 0,
+     /* opt state flags  */ IPV4_FLAGS, 0,
+     /* last opt argumnt */ NULL,
+     /* arg list/cookie  */ NULL,
+     /* must/cannot opts */ NULL, NULL,
+     /* option proc      */ NULL,
+     /* desc, NAME, name */ zIpv4Text, zIpv4_NAME, zIpv4_Name,
+     /* disablement strs */ NULL, NULL },
+
+  {  /* entry idx, value */ 1, VALUE_OPT_IPV6,
+     /* equiv idx, value */ NOLIMIT, NOLIMIT,
+     /* equivalenced to  */ INDEX_OPT_IPV4,
+     /* min, max, act ct */ 0, 1, 0,
+     /* opt state flags  */ IPV6_FLAGS, 0,
+     /* last opt argumnt */ NULL,
+     /* arg list/cookie  */ NULL,
+     /* must/cannot opts */ NULL, NULL,
+     /* option proc      */ NULL,
+     /* desc, NAME, name */ zIpv6Text, zIpv6_NAME, zIpv6_Name,
+     /* disablement strs */ NULL, NULL },
+
+  {  /* entry idx, value */ 2, VALUE_OPT_COMMAND,
+     /* equiv idx, value */ 2, VALUE_OPT_COMMAND,
+     /* equivalenced to  */ NO_EQUIVALENT,
+     /* min, max, act ct */ 0, NOLIMIT, 0,
+     /* opt state flags  */ COMMAND_FLAGS, 0,
+     /* last opt argumnt */ NULL,
+     /* arg list/cookie  */ NULL,
+     /* must/cannot opts */ NULL, NULL,
+     /* option proc      */ optionStackArg,
+     /* desc, NAME, name */ zCommandText, zCommand_NAME, zCommand_Name,
+     /* disablement strs */ NULL, NULL },
+
+  {  /* entry idx, value */ 3, VALUE_OPT_DEBUG_LEVEL,
+     /* equiv idx, value */ 3, VALUE_OPT_DEBUG_LEVEL,
+     /* equivalenced to  */ NO_EQUIVALENT,
+     /* min, max, act ct */ 0, NOLIMIT, 0,
+     /* opt state flags  */ DEBUG_LEVEL_FLAGS, 0,
+     /* last opt argumnt */ NULL,
+     /* arg list/cookie  */ NULL,
+     /* must/cannot opts */ NULL, NULL,
+     /* option proc      */ NULL,
+     /* desc, NAME, name */ zDebug_LevelText, zDebug_Level_NAME, zDebug_Level_Name,
+     /* disablement strs */ NULL, NULL },
+
+  {  /* entry idx, value */ 4, VALUE_OPT_SET_DEBUG_LEVEL,
+     /* equiv idx, value */ 4, VALUE_OPT_SET_DEBUG_LEVEL,
+     /* equivalenced to  */ NO_EQUIVALENT,
+     /* min, max, act ct */ 0, NOLIMIT, 0,
+     /* opt state flags  */ SET_DEBUG_LEVEL_FLAGS, 0,
+     /* last opt argumnt */ NULL,
+     /* arg list/cookie  */ NULL,
+     /* must/cannot opts */ NULL, NULL,
+     /* option proc      */ SET_DEBUG_LEVEL_OPT_PROC,
+     /* desc, NAME, name */ zSet_Debug_LevelText, zSet_Debug_Level_NAME, zSet_Debug_Level_Name,
+     /* disablement strs */ NULL, NULL },
+
+  {  /* entry idx, value */ 5, VALUE_OPT_PEERS,
+     /* equiv idx, value */ 5, VALUE_OPT_PEERS,
+     /* equivalenced to  */ NO_EQUIVALENT,
+     /* min, max, act ct */ 0, 1, 0,
+     /* opt state flags  */ PEERS_FLAGS, 0,
+     /* last opt argumnt */ NULL,
+     /* arg list/cookie  */ NULL,
+     /* must/cannot opts */ NULL, aPeersCantList,
+     /* option proc      */ NULL,
+     /* desc, NAME, name */ zPeersText, zPeers_NAME, zPeers_Name,
+     /* disablement strs */ NULL, NULL },
+
+  {  /* entry idx, value */ 6, VALUE_OPT_INTERACTIVE,
+     /* equiv idx, value */ 6, VALUE_OPT_INTERACTIVE,
+     /* equivalenced to  */ NO_EQUIVALENT,
+     /* min, max, act ct */ 0, 1, 0,
+     /* opt state flags  */ INTERACTIVE_FLAGS, 0,
+     /* last opt argumnt */ NULL,
+     /* arg list/cookie  */ NULL,
+     /* must/cannot opts */ NULL, aInteractiveCantList,
+     /* option proc      */ NULL,
+     /* desc, NAME, name */ zInteractiveText, zInteractive_NAME, zInteractive_Name,
+     /* disablement strs */ NULL, NULL },
+
+  {  /* entry idx, value */ 7, VALUE_OPT_NUMERIC,
+     /* equiv idx, value */ 7, VALUE_OPT_NUMERIC,
+     /* equivalenced to  */ NO_EQUIVALENT,
+     /* min, max, act ct */ 0, 1, 0,
+     /* opt state flags  */ NUMERIC_FLAGS, 0,
+     /* last opt argumnt */ NULL,
+     /* arg list/cookie  */ NULL,
+     /* must/cannot opts */ NULL, NULL,
+     /* option proc      */ NULL,
+     /* desc, NAME, name */ zNumericText, zNumeric_NAME, zNumeric_Name,
+     /* disablement strs */ NULL, NULL },
+
+  {  /* entry idx, value */ INDEX_OPT_VERSION, VALUE_OPT_VERSION,
+     /* equiv idx value  */ NO_EQUIVALENT, 0,
+     /* equivalenced to  */ NO_EQUIVALENT,
+     /* min, max, act ct */ 0, 1, 0,
+     /* opt state flags  */ OPTST_SET_ARGTYPE(OPARG_TYPE_STRING)
+                          | OPTST_ARG_OPTIONAL, 0,
+     /* last opt argumnt */ NULL,
+     /* arg list/cookie  */ NULL,
+     /* must/cannot opts */ NULL, NULL,
+     /* option proc      */ DOVERPROC,
+     /* desc, NAME, name */ zVersionText, NULL, zVersion_Name,
+     /* disablement strs */ NULL, NULL },
+
+  {  /* entry idx, value */ INDEX_OPT_HELP, VALUE_OPT_HELP,
+     /* equiv idx value  */ NO_EQUIVALENT, 0,
+     /* equivalenced to  */ NO_EQUIVALENT,
+     /* min, max, act ct */ 0, 1, 0,
+     /* opt state flags  */ OPTST_IMM, 0,
+     /* last opt argumnt */ NULL,
+     /* arg list/cookie  */ NULL,
+     /* must/cannot opts */ NULL, NULL,
+     /* option proc      */ doUsageOpt,
+     /* desc, NAME, name */ zHelpText, NULL, zHelp_Name,
+     /* disablement strs */ NULL, NULL },
+
+  {  /* entry idx, value */ INDEX_OPT_MORE_HELP, VALUE_OPT_MORE_HELP,
+     /* equiv idx value  */ NO_EQUIVALENT, 0,
+     /* equivalenced to  */ NO_EQUIVALENT,
+     /* min, max, act ct */ 0, 1, 0,
+     /* opt state flags  */ OPTST_IMM, 0,
+     /* last opt argumnt */ NULL,
+     /* arg list/cookie  */ NULL,
+     /* must/cannot opts */ NULL,  NULL,
+     /* option proc      */ optionPagedUsage,
+     /* desc, NAME, name */ zMore_HelpText, NULL, zMore_Help_Name,
+     /* disablement strs */ NULL, NULL },
+
+  {  /* entry idx, value */ INDEX_OPT_SAVE_OPTS, VALUE_OPT_SAVE_OPTS,
+     /* equiv idx value  */ NO_EQUIVALENT, 0,
+     /* equivalenced to  */ NO_EQUIVALENT,
+     /* min, max, act ct */ 0, 1, 0,
+     /* opt state flags  */ OPTST_SET_ARGTYPE(OPARG_TYPE_STRING)
+                          | OPTST_ARG_OPTIONAL, 0,
+     /* last opt argumnt */ NULL,
+     /* arg list/cookie  */ NULL,
+     /* must/cannot opts */ NULL,  NULL,
+     /* option proc      */ NULL,
+     /* desc, NAME, name */ zSave_OptsText, NULL, zSave_Opts_Name,
+     /* disablement strs */ NULL, NULL },
+
+  {  /* entry idx, value */ INDEX_OPT_LOAD_OPTS, VALUE_OPT_LOAD_OPTS,
+     /* equiv idx value  */ NO_EQUIVALENT, 0,
+     /* equivalenced to  */ NO_EQUIVALENT,
+     /* min, max, act ct */ 0, NOLIMIT, 0,
+     /* opt state flags  */ OPTST_DISABLE_IMM | \
+                       OPTST_SET_ARGTYPE(OPARG_TYPE_STRING), 0,
+     /* last opt argumnt */ NULL,
+     /* arg list/cookie  */ NULL,
+     /* must/cannot opts */ NULL, NULL,
+     /* option proc      */ optionLoadOpt,
+     /* desc, NAME, name */ zLoad_OptsText, zLoad_Opts_NAME, zLoad_Opts_Name,
+     /* disablement strs */ zNotLoad_Opts_Name, zNotLoad_Opts_Pfx }
+};
+
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ *
+ *  Define the Ntpq Option Environment
+ */
+tSCC   zPROGNAME[]   = "NTPQ";
+tSCC   zUsageTitle[] =
+"ntpq - standard NTP query program - Ver. 4.2.3p12\n\
+USAGE:  %s [ -<flag> [<val>] | --<name>[{=| }<val>] ]... [ host ...]\n";
+tSCC   zRcName[]     = ".ntprc";
+tSCC*  apzHomeList[] = {
+       "$HOME",
+       ".",
+       "$HOME",
+       ".",
+       NULL };
+
+tSCC   zBugsAddr[]    = "http://bugs.ntp.isc.org, bugs@ntp.org";
+#define zExplain NULL
+tSCC    zDetail[]     = "\n\
+The\n\
+[= prog-name =]\n\
+utility program is used to query NTP servers which\n\
+implement the standard NTP mode 6 control message formats defined\n\
+in Appendix B of the NTPv3 specification RFC1305, requesting\n\
+information about current state and/or changes in that state.\n\
+The same formats are used in NTPv4, although some of the\n\
+variables have changed and new ones added. The description on this\n\
+page is for the NTPv4 variables.\n\
+The program may be run either in interactive mode or controlled using\n\
+command line arguments.\n\
+Requests to read and write arbitrary\n\
+variables can be assembled, with raw and pretty-printed output\n\
+options being available.\n\
+The\n\
+[= prog-name =]\n\
+utility can also obtain and print a\n\
+list of peers in a common format by sending multiple queries to the\n\
+server.\n\n\
+If one or more request options is included on the command line\n\
+when\n\
+[= prog-name =]\n\
+is executed, each of the requests will be sent\n\
+to the NTP servers running on each of the hosts given as command\n\
+line arguments, or on localhost by default.\n\
+If no request options\n\
+are given,\n\
+[= prog-name =]\n\
+will attempt to read commands from the\n\
+standard input and execute these on the NTP server running on the\n\
+first host given on the command line, again defaulting to localhost\n\
+when no other host is specified.\n\
+The\n\
+[= prog-name =]\n\
+utility will prompt for\n\
+commands if the standard input is a terminal device.\n\n\
+The\n\
+[= prog-name =]\n\
+utility uses NTP mode 6 packets to communicate with the\n\
+NTP server, and hence can be used to query any compatible server on\n\
+the network which permits it.\n\
+Note that since NTP is a UDP protocol\n\
+this communication will be somewhat unreliable, especially over\n\
+large distances in terms of network topology.\n\
+The\n\
+[= prog-name =]\n\
+utility makes\n\
+one attempt to retransmit requests, and will time requests out if\n\
+the remote host is not heard from within a suitable timeout\n\
+time.\n\n\
+Specifying a\n\
+command line option other than\n\
+.Fl i\n\
+or\n\
+.Fl n\n\
+will\n\
+cause the specified query (queries) to be sent to the indicated\n\
+host(s) immediately.\n\
+Otherwise,\n\
+[= prog-name =]  \n\
+will attempt to read\n\
+interactive format commands from the standard input.\n\
+.Ss \"Internal Commands\"\n\
+Interactive format commands consist of a keyword followed by zero\n\
+to four arguments.\n\
+Only enough characters of the full keyword to\n\
+uniquely identify the command need be typed.\n\n\
+A\n\
+number of interactive format commands are executed entirely within\n\
+the\n\
+[= prog-name =]\n\
+utility itself and do not result in NTP mode 6\n\
+requests being sent to a server.\n\
+These are described following.\n\
+@table @code\n\
+@item ? [command_keyword]\n\
+@itemx help [command_keyword]\n\
+A\n\
+.Ql \\&?\n\
+by itself will print a list of all the command\n\
+keywords known to this incarnation of\n\
+[= prog-name =] .\n\
+A\n\
+.Ql \\&?\n\
+followed by a command keyword will print function and usage\n\
+information about the command.\n\
+This command is probably a better\n\
+source of information about\n\
+[= prog-name =]\n\
+than this manual\n\
+page.\n\
+@item addvars\n\
+.Ar variable_name [=value] ...\n\
+.Xc\n\
+@item rmvars variable_name ...\n\
+@item clearvars\n\
+The data carried by NTP mode 6 messages consists of a list of\n\
+items of the form\n\
+.Ql variable_name=value ,\n\
+where the\n\
+.Ql =value\n\
+is ignored, and can be omitted,\n\
+in requests to the server to read variables.\n\
+The\n\
+[= prog-name =]\n\
+utility maintains an internal list in which data to be included in control\n\
+messages can be assembled, and sent using the\n\
+.Ic readlist\n\
+and\n\
+.Ic writelist\n\
+commands described below.\n\
+The\n\
+.Ic addvars\n\
+command allows variables and their optional values to be added to\n\
+the list.\n\
+If more than one variable is to be added, the list should\n\
+be comma-separated and not contain white space.\n\
+The\n\
+.Ic rmvars\n\
+command can be used to remove individual variables from the list,\n\
+while the\n\
+.Ic clearlist\n\
+command removes all variables from the\n\
+list.\n\
+@item authenticate [ yes | no ]\n\
+Normally\n\
+[= prog-name =]\n\
+does not authenticate requests unless\n\
+they are write requests.\n\
+The command\n\
+.Ql authenticate yes\n\
+causes\n\
+[= prog-name =]\n\
+to send authentication with all requests it\n\
+makes.\n\
+Authenticated requests causes some servers to handle\n\
+requests slightly differently, and can occasionally melt the CPU in\n\
+fuzzballs if you turn authentication on before doing a\n\
+.Ic peer\n\
+display.\n\
+The command\n\
+.Ql authenticate\n\
+causes\n\
+[= prog-name =]\n\
+to display whether or not\n\
+[= prog-name =]\n\
+is currently autheinticating requests.\n\
+@item cooked\n\
+Causes output from query commands to be \"cooked\", so that\n\
+variables which are recognized by\n\
+[= prog-name =]\n\
+will have their\n\
+values reformatted for human consumption.\n\
+Variables which\n\
+[= prog-name =]\n\
+thinks should have a decodable value but didn't are\n\
+marked with a trailing\n\
+.Ql \\&? .\n\
+.@item debug [\n\
+.Cm more |\n\
+.Cm less |\n\
+.Cm off\n\
+]\n\
+.Xc\n\
+With no argument, displays the current debug level.\n\
+Otherwise, the debug level is changed to the indicated level.\n\
+@item delay milliseconds\n\
+Specify a time interval to be added to timestamps included in\n\
+requests which require authentication.\n\
+This is used to enable\n\
+(unreliable) server reconfiguration over long delay network paths\n\
+or between machines whose clocks are unsynchronized.\n\
+Actually the\n\
+server does not now require timestamps in authenticated requests,\n\
+so this command may be obsolete.\n\
+@item host hostname\n\
+Set the host to which future queries will be sent.\n\
+Hostname may\n\
+be either a host name or a numeric address.\n\
+@item hostnames Cm yes | Cm no\n\
+If\n\
+.Cm yes\n\
+is specified, host names are printed in\n\
+information displays.\n\
+If\n\
+.Cm no\n\
+is specified, numeric\n\
+addresses are printed instead.\n\
+The default is\n\
+.Cm yes ,\n\
+unless\n\
+modified using the command line\n\
+.Fl n\n\
+switch.\n\
+@item keyid keyid\n\
+This command allows the specification of a key number to be\n\
+used to authenticate configuration requests.\n\
+This must correspond\n\
+to a key number the server has been configured to use for this\n\
+purpose.\n\
+@item ntpversion [\n\
+.Cm 1 |\n\
+.Cm 2 |\n\
+.Cm 3 |\n\
+.Cm 4\n\
+]\n\
+.Xc\n\
+Sets the NTP version number which\n\
+[= prog-name =]\n\
+claims in\n\
+packets.\n\
+Defaults to 3, Note that mode 6 control messages (and\n\
+modes, for that matter) didn't exist in NTP version 1.\n\
+There appear\n\
+to be no servers left which demand version 1.\n\
+With no argument, displays the current NTP version that will be used\n\
+when communicating with servers.\n\
+@item quit\n\
+Exit\n\
+[= prog-name =] .\n\
+@item passwd\n\
+This command prompts you to type in a password (which will not\n\
+be echoed) which will be used to authenticate configuration\n\
+requests.\n\
+The password must correspond to the key configured for\n\
+use by the NTP server for this purpose if such requests are to be\n\
+successful.\n\
+@item raw\n\
+Causes all output from query commands is printed as received\n\
+from the remote server.\n\
+The only formating/interpretation done on\n\
+the data is to transform nonascii data into a printable (but barely\n\
+understandable) form.\n\
+@item timeout Ar milliseconds\n\
+Specify a timeout period for responses to server queries.\n\
+The\n\
+default is about 5000 milliseconds.\n\
+Note that since\n\
+[= prog-name =]\n\
+retries each query once after a timeout, the total waiting time for\n\
+a timeout will be twice the timeout value set.\n\
+@end table\n";
+tSCC    zFullVersion[] = NTPQ_FULL_VERSION;
+/* extracted from optcode near line 321 */
+
+#if defined(ENABLE_NLS)
+# define OPTPROC_BASE OPTPROC_TRANSLATE
+  static tOptionXlateProc translate_option_strings;
+#else
+# define OPTPROC_BASE OPTPROC_NONE
+# define translate_option_strings NULL
+#endif /* ENABLE_NLS */
+
+tOptions ntpqOptions = {
+    OPTIONS_STRUCT_VERSION,
+    0, NULL,                    /* original argc + argv    */
+    ( OPTPROC_BASE
+    + OPTPROC_ERRSTOP
+    + OPTPROC_SHORTOPT
+    + OPTPROC_LONGOPT
+    + OPTPROC_NO_REQ_OPT
+    + OPTPROC_ENVIRON
+    + OPTPROC_HAS_IMMED ),
+    0, NULL,                    /* current option index, current option */
+    NULL,         NULL,         zPROGNAME,
+    zRcName,      zCopyright,   zCopyrightNotice,
+    zFullVersion, apzHomeList,  zUsageTitle,
+    zExplain,     zDetail,      optDesc,
+    zBugsAddr,                  /* address to send bugs to */
+    NULL, NULL,                 /* extensions/saved state  */
+    optionUsage,       /* usage procedure */
+    translate_option_strings,   /* translation procedure */
+    /*
+     *  Indexes to special options
+     */
+    { INDEX_OPT_MORE_HELP,
+      INDEX_OPT_SAVE_OPTS,
+      NO_EQUIVALENT /* index of '-#' option */,
+      NO_EQUIVALENT /* index of default opt */
+    },
+    OPTION_CT, 8 /* user option count */
+};
+
+/*
+ *  Create the static procedure(s) declared above.
+ */
+static void
+doUsageOpt(
+    tOptions*   pOptions,
+    tOptDesc*   pOptDesc )
+{
+    USAGE( EXIT_SUCCESS );
+}
+
+#if ! defined(TEST_NTPQ_OPTS)
+
+/* * * * * * *
+ *
+ *   For the set-debug-level option.
+ */
+static void
+doOptSet_Debug_Level(
+    tOptions*   pOptions,
+    tOptDesc*   pOptDesc )
+{
+DESC(DEBUG_LEVEL).optOccCt = atoi( pOptDesc->pzLastArg );
+}
+
+#endif /* defined(TEST_NTPQ_OPTS) */
+
+/* extracted from optmain.tpl near line 92 */
+
+#if defined(TEST_NTPQ_OPTS) /* TEST MAIN PROCEDURE: */
+
+int
+main( int argc, char** argv )
+{
+    int res = EXIT_SUCCESS;
+    (void)optionProcess( &ntpqOptions, argc, argv );
+    {
+        void optionPutShell( tOptions* );
+        optionPutShell( &ntpqOptions );
+    }
+    return res;
+}
+#endif  /* defined TEST_NTPQ_OPTS */
+/* extracted from optcode near line 418 */
+
+#if ENABLE_NLS
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+#include <autoopts/usage-txt.h>
+
+static char*
+AO_gettext( const char* pz )
+{
+    char* pzRes;
+    if (pz == NULL)
+        return NULL;
+    pzRes = _(pz);
+    if (pzRes == pz)
+        return pzRes;
+    pzRes = strdup( pzRes );
+    if (pzRes == NULL) {
+        fputs( _("No memory for duping translated strings\n"), stderr );
+        exit( EXIT_FAILURE );
+    }
+    return pzRes;
+}
+
+/*
+ *  This invokes the translation code (e.g. gettext(3)).
+ */
+static void
+translate_option_strings( void )
+{
+    /*
+     *  Guard against re-translation.  It won't work.  The strings will have
+     *  been changed by the first pass through this code.  One shot only.
+     */
+    if (option_usage_text.field_ct == 0)
+        return;
+    /*
+     *  Do the translations.  The first pointer follows the field count field.
+     *  The field count field is the size of a pointer.
+     */
+    {
+        char** ppz = (char**)(void*)&(option_usage_text);
+        int    ix  = option_usage_text.field_ct;
+
+        do {
+            ppz++;
+            *ppz = AO_gettext(*ppz);
+        } while (--ix > 0);
+    }
+    option_usage_text.field_ct = 0;
+
+    {
+        tOptDesc* pOD = ntpqOptions.pOptDesc;
+        int       ix  = ntpqOptions.optCt;
+
+        for (;;) {
+            pOD->pzText           = AO_gettext(pOD->pzText);
+            pOD->pz_NAME          = AO_gettext(pOD->pz_NAME);
+            pOD->pz_Name          = AO_gettext(pOD->pz_Name);
+            pOD->pz_DisableName   = AO_gettext(pOD->pz_DisableName);
+            pOD->pz_DisablePfx    = AO_gettext(pOD->pz_DisablePfx);
+            if (--ix <= 0)
+                break;
+            pOD++;
+        }
+    }
+    ntpqOptions.pzCopyright   = AO_gettext(ntpqOptions.pzCopyright);
+    ntpqOptions.pzCopyNotice  = AO_gettext(ntpqOptions.pzCopyNotice);
+    ntpqOptions.pzFullVersion = AO_gettext(ntpqOptions.pzFullVersion);
+    ntpqOptions.pzUsageTitle  = AO_gettext(ntpqOptions.pzUsageTitle);
+    ntpqOptions.pzExplain     = AO_gettext(ntpqOptions.pzExplain);
+    ntpqOptions.pzDetail      = AO_gettext(ntpqOptions.pzDetail);
+}
+
+#endif /* ENABLE_NLS */
+
+#ifdef  __cplusplus
+}
+#endif
diff --git a/ntpq/ntpq-opts.h b/ntpq/ntpq-opts.h
new file mode 100644 (file)
index 0000000..2992708
--- /dev/null
@@ -0,0 +1,151 @@
+/*   -*- buffer-read-only: t -*- vi: set ro:
+ *  
+ *  DO NOT EDIT THIS FILE   (ntpq-opts.h)
+ *  
+ *  It has been AutoGen-ed  Tuesday June 27, 2006 at 10:16:52 PM EDT
+ *  From the definitions    ntpq-opts.def
+ *  and the template file   options
+ */
+/*
+ *  This file contains the programmatic interface to the Automated
+ *  Options generated for the ntpq program.
+ *  These macros are documented in the AutoGen info file in the
+ *  "AutoOpts" chapter.  Please refer to that doc for usage help.
+ */
+#ifndef AUTOOPTS_NTPQ_OPTS_H_GUARD
+#define AUTOOPTS_NTPQ_OPTS_H_GUARD
+
+/*
+ * ntpq copyright 1970-2006 ntp.org - all rights reserved
+ *
+ * see html/copyright.html
+ */
+#include "config.h"
+#include <autoopts/options.h>
+
+/*
+ *  Ensure that the library used for compiling this generated header is at
+ *  least as new as the version current when the header template was released
+ *  (not counting patch version increments).  Also ensure that the oldest
+ *  tolerable version is at least as old as what was current when the header
+ *  template was released.
+ */
+#define AO_TEMPLATE_VERSION 110592
+#if (AO_TEMPLATE_VERSION < OPTIONS_MINIMUM_VERSION) \
+ || (AO_TEMPLATE_VERSION > OPTIONS_STRUCT_VERSION)
+# error option template version mismatches autoopts/options.h header
+#endif
+
+/*
+ *  Enumeration of each option:
+ */
+typedef enum {
+        INDEX_OPT_IPV4             =  0,
+        INDEX_OPT_IPV6             =  1,
+        INDEX_OPT_COMMAND          =  2,
+        INDEX_OPT_DEBUG_LEVEL      =  3,
+        INDEX_OPT_SET_DEBUG_LEVEL  =  4,
+        INDEX_OPT_PEERS            =  5,
+        INDEX_OPT_INTERACTIVE      =  6,
+        INDEX_OPT_NUMERIC          =  7,
+        INDEX_OPT_VERSION          = 8,
+        INDEX_OPT_HELP             = 9,
+        INDEX_OPT_MORE_HELP        = 10,
+        INDEX_OPT_SAVE_OPTS        = 11,
+        INDEX_OPT_LOAD_OPTS        = 12
+} teOptIndex;
+
+#define OPTION_CT    13
+#define NTPQ_VERSION       "4.2.3p12"
+#define NTPQ_FULL_VERSION  "ntpq - standard NTP query program - Ver. 4.2.3p12"
+
+/*
+ *  Interface defines for all options.  Replace "n" with
+ *  the UPPER_CASED option name (as in the teOptIndex
+ *  enumeration above).  e.g. HAVE_OPT( IPV4 )
+ */
+#define        DESC(n) ntpqOptions.pOptDesc[INDEX_OPT_ ## n]
+#define     HAVE_OPT(n) (! UNUSED_OPT(& DESC(n)))
+#define      OPT_ARG(n) (DESC(n).pzLastArg)
+#define    STATE_OPT(n) (DESC(n).fOptState & OPTST_SET_MASK)
+#define    COUNT_OPT(n) (DESC(n).optOccCt)
+#define    ISSEL_OPT(n) (SELECTED_OPT(&DESC(n)))
+#define ISUNUSED_OPT(n) (UNUSED_OPT(& DESC(n)))
+#define  ENABLED_OPT(n) (! DISABLED_OPT(& DESC(n)))
+#define  STACKCT_OPT(n) (((tArgList*)(DESC(n).optCookie))->useCt)
+#define STACKLST_OPT(n) (((tArgList*)(DESC(n).optCookie))->apzArgs)
+#define    CLEAR_OPT(n) STMTS( \
+                DESC(n).fOptState &= OPTST_PERSISTENT;   \
+                if ( (DESC(n).fOptState & OPTST_INITENABLED) == 0) \
+                    DESC(n).fOptState |= OPTST_DISABLED; \
+                DESC(n).optCookie = NULL )
+
+/*
+ *  Interface defines for specific options.
+ */
+#define VALUE_OPT_IPV4           '4'
+#define WHICH_OPT_IPV4           (DESC(IPV4).optActualValue)
+#define WHICH_IDX_IPV4           (DESC(IPV4).optActualIndex)
+#define VALUE_OPT_IPV6           '6'
+#define VALUE_OPT_COMMAND        'c'
+#define VALUE_OPT_DEBUG_LEVEL    'd'
+#define VALUE_OPT_SET_DEBUG_LEVEL 'D'
+#define VALUE_OPT_PEERS          'p'
+#define VALUE_OPT_INTERACTIVE    'i'
+#define VALUE_OPT_NUMERIC        'n'
+
+#define VALUE_OPT_VERSION       'v'
+#define VALUE_OPT_SAVE_OPTS     '>'
+#define VALUE_OPT_LOAD_OPTS     '<'
+#define VALUE_OPT_HELP          '?'
+#define VALUE_OPT_MORE_HELP     '!'
+#define SET_OPT_SAVE_OPTS(a)   STMTS( \
+        DESC(SAVE_OPTS).fOptState &= OPTST_PERSISTENT; \
+        DESC(SAVE_OPTS).fOptState |= OPTST_SET; \
+        DESC(SAVE_OPTS).pzLastArg  = (const char*)(a) )
+/*
+ *  Interface defines not associated with particular options
+ */
+#define ERRSKIP_OPTERR  STMTS( ntpqOptions.fOptSet &= ~OPTPROC_ERRSTOP )
+#define ERRSTOP_OPTERR  STMTS( ntpqOptions.fOptSet |= OPTPROC_ERRSTOP )
+#define RESTART_OPT(n)  STMTS( \
+                ntpqOptions.curOptIdx = (n); \
+                ntpqOptions.pzCurOpt  = NULL )
+#define START_OPT       RESTART_OPT(1)
+#define USAGE(c)        (*ntpqOptions.pUsageProc)( &ntpqOptions, c )
+/* extracted from opthead near line 289 */
+
+/* * * * * *
+ *
+ *  Declare the ntpq option descriptor.
+ */
+#ifdef  __cplusplus
+extern "C" {
+#endif
+
+extern tOptions   ntpqOptions;
+
+#ifndef _
+#  if ENABLE_NLS
+#    include <stdio.h>
+     static inline char* aoGetsText( const char* pz ) {
+         if (pz == NULL) return NULL;
+         return (char*)gettext( pz );
+     }
+#    define _(s)  aoGetsText(s)
+#  else  /* ENABLE_NLS */
+#    define _(s)  s
+#  endif /* ENABLE_NLS */
+#endif
+
+#ifdef  __cplusplus
+}
+#endif
+#endif /* AUTOOPTS_NTPQ_OPTS_H_GUARD */
+/*
+ * Local Variables:
+ * Mode: C
+ * c-file-style: "stroustrup"
+ * indent-tabs-mode: nil
+ * End:
+ * options.h ends here */
diff --git a/ntpq/ntpq-opts.menu b/ntpq/ntpq-opts.menu
new file mode 100644 (file)
index 0000000..c06f90d
--- /dev/null
@@ -0,0 +1 @@
+* ntpq Invocation::                Invoking ntpq
diff --git a/ntpq/ntpq-opts.texi b/ntpq/ntpq-opts.texi
new file mode 100644 (file)
index 0000000..46fa0c8
--- /dev/null
@@ -0,0 +1,691 @@
+@node ntpq Invocation
+@section Invoking ntpq
+@pindex ntpq
+@cindex standard NTP query program
+@ignore
+#  -*- buffer-read-only: t -*- vi: set ro:
+# 
+# DO NOT EDIT THIS FILE   (ntpq-opts.texi)
+# 
+# It has been AutoGen-ed  Tuesday June 27, 2006 at 10:37:24 PM EDT
+# From the definitions    ntpq-opts.def
+# and the template file   aginfo.tpl
+@end ignore
+This program has no explanation.
+
+The
+[= prog-name =]
+utility program is used to query NTP servers which
+implement the standard NTP mode 6 control message formats defined
+in Appendix B of the NTPv3 specification RFC1305, requesting
+information about current state and/or changes in that state.
+The same formats are used in NTPv4, although some of the
+variables have changed and new ones added. The description on this
+page is for the NTPv4 variables.
+The program may be run either in interactive mode or controlled using
+command line arguments.
+Requests to read and write arbitrary
+variables can be assembled, with raw and pretty-printed output
+options being available.
+The
+[= prog-name =]
+utility can also obtain and print a
+list of peers in a common format by sending multiple queries to the
+server.
+
+If one or more request options is included on the command line
+when
+[= prog-name =]
+is executed, each of the requests will be sent
+to the NTP servers running on each of the hosts given as command
+line arguments, or on localhost by default.
+If no request options
+are given,
+[= prog-name =]
+will attempt to read commands from the
+standard input and execute these on the NTP server running on the
+first host given on the command line, again defaulting to localhost
+when no other host is specified.
+The
+[= prog-name =]
+utility will prompt for
+commands if the standard input is a terminal device.
+
+The
+[= prog-name =]
+utility uses NTP mode 6 packets to communicate with the
+NTP server, and hence can be used to query any compatible server on
+the network which permits it.
+Note that since NTP is a UDP protocol
+this communication will be somewhat unreliable, especially over
+large distances in terms of network topology.
+The
+[= prog-name =]
+utility makes
+one attempt to retransmit requests, and will time requests out if
+the remote host is not heard from within a suitable timeout
+time.
+
+Specifying a
+command line option other than
+.Fl i
+or
+.Fl n
+will
+cause the specified query (queries) to be sent to the indicated
+host(s) immediately.
+Otherwise,
+[= prog-name =]  
+will attempt to read
+interactive format commands from the standard input.
+.Ss "Internal Commands"
+Interactive format commands consist of a keyword followed by zero
+to four arguments.
+Only enough characters of the full keyword to
+uniquely identify the command need be typed.
+
+A
+number of interactive format commands are executed entirely within
+the
+[= prog-name =]
+utility itself and do not result in NTP mode 6
+requests being sent to a server.
+These are described following.
+@table @code
+@item ? [command_keyword]
+@itemx help [command_keyword]
+A
+.Ql \&?
+by itself will print a list of all the command
+keywords known to this incarnation of
+[= prog-name =] .
+A
+.Ql \&?
+followed by a command keyword will print function and usage
+information about the command.
+This command is probably a better
+source of information about
+[= prog-name =]
+than this manual
+page.
+@item addvars
+.Ar variable_name [=value] ...
+.Xc
+@item rmvars variable_name ...
+@item clearvars
+The data carried by NTP mode 6 messages consists of a list of
+items of the form
+.Ql variable_name=value ,
+where the
+.Ql =value
+is ignored, and can be omitted,
+in requests to the server to read variables.
+The
+[= prog-name =]
+utility maintains an internal list in which data to be included in control
+messages can be assembled, and sent using the
+.Ic readlist
+and
+.Ic writelist
+commands described below.
+The
+.Ic addvars
+command allows variables and their optional values to be added to
+the list.
+If more than one variable is to be added, the list should
+be comma-separated and not contain white space.
+The
+.Ic rmvars
+command can be used to remove individual variables from the list,
+while the
+.Ic clearlist
+command removes all variables from the
+list.
+@item authenticate [ yes | no ]
+Normally
+[= prog-name =]
+does not authenticate requests unless
+they are write requests.
+The command
+.Ql authenticate yes
+causes
+[= prog-name =]
+to send authentication with all requests it
+makes.
+Authenticated requests causes some servers to handle
+requests slightly differently, and can occasionally melt the CPU in
+fuzzballs if you turn authentication on before doing a
+.Ic peer
+display.
+The command
+.Ql authenticate
+causes
+[= prog-name =]
+to display whether or not
+[= prog-name =]
+is currently autheinticating requests.
+@item cooked
+Causes output from query commands to be "cooked", so that
+variables which are recognized by
+[= prog-name =]
+will have their
+values reformatted for human consumption.
+Variables which
+[= prog-name =]
+thinks should have a decodable value but didn't are
+marked with a trailing
+.Ql \&? .
+.@item debug [
+.Cm more |
+.Cm less |
+.Cm off
+]
+.Xc
+With no argument, displays the current debug level.
+Otherwise, the debug level is changed to the indicated level.
+@item delay milliseconds
+Specify a time interval to be added to timestamps included in
+requests which require authentication.
+This is used to enable
+(unreliable) server reconfiguration over long delay network paths
+or between machines whose clocks are unsynchronized.
+Actually the
+server does not now require timestamps in authenticated requests,
+so this command may be obsolete.
+@item host hostname
+Set the host to which future queries will be sent.
+Hostname may
+be either a host name or a numeric address.
+@item hostnames Cm yes | Cm no
+If
+.Cm yes
+is specified, host names are printed in
+information displays.
+If
+.Cm no
+is specified, numeric
+addresses are printed instead.
+The default is
+.Cm yes ,
+unless
+modified using the command line
+.Fl n
+switch.
+@item keyid keyid
+This command allows the specification of a key number to be
+used to authenticate configuration requests.
+This must correspond
+to a key number the server has been configured to use for this
+purpose.
+@item ntpversion [
+.Cm 1 |
+.Cm 2 |
+.Cm 3 |
+.Cm 4
+]
+.Xc
+Sets the NTP version number which
+[= prog-name =]
+claims in
+packets.
+Defaults to 3, Note that mode 6 control messages (and
+modes, for that matter) didn't exist in NTP version 1.
+There appear
+to be no servers left which demand version 1.
+With no argument, displays the current NTP version that will be used
+when communicating with servers.
+@item quit
+Exit
+[= prog-name =] .
+@item passwd
+This command prompts you to type in a password (which will not
+be echoed) which will be used to authenticate configuration
+requests.
+The password must correspond to the key configured for
+use by the NTP server for this purpose if such requests are to be
+successful.
+@item raw
+Causes all output from query commands is printed as received
+from the remote server.
+The only formating/interpretation done on
+the data is to transform nonascii data into a printable (but barely
+understandable) form.
+@item timeout Ar milliseconds
+Specify a timeout period for responses to server queries.
+The
+default is about 5000 milliseconds.
+Note that since
+[= prog-name =]
+retries each query once after a timeout, the total waiting time for
+a timeout will be twice the timeout value set.
+@end table
+
+
+This section was generated by @strong{AutoGen},
+the aginfo template and the option descriptions for the @command{ntpq} program.  It documents the ntpq usage text and option meanings.
+
+This software is released under a specialized copyright license.
+
+@menu
+* ntpq usage::                  ntpq usage help (-?)
+* ntpq command::                command option (-c)
+* ntpq debug-level::            debug-level option (-d)
+* ntpq interactive::            interactive option (-i)
+* ntpq ipv4::                   ipv4 option (-4)
+* ntpq ipv6::                   ipv6 option (-6)
+* ntpq numeric::                numeric option (-n)
+* ntpq peers::                  peers option (-p)
+* ntpq set-debug-level::        set-debug-level option (-D)
+@end menu
+
+@node ntpq usage
+@subsection ntpq usage help (-?)
+@cindex ntpq usage
+
+This is the automatically generated usage text for ntpq:
+
+@exampleindent 0
+@example
+ntpq - standard NTP query program - Ver. 4.2.3p10
+USAGE:  ntpq [ -<flag> [<val>] | --<name>[@{=| @}<val>] ]... [ host ...]
+  Flg Arg Option-Name    Description
+   -4 no  ipv4           Force IPv4 DNS name resolution
+   -6 no  ipv6           Force IPv6 DNS name resolution
+                                - an alternate for ipv4
+   -c Str command        run a command and exit
+                                - may appear multiple times
+   -d no  debug-level    Increase output debug message level
+                                - may appear multiple times
+   -D Str set-debug-level Set the output debug message level
+                                - may appear multiple times
+   -p no  peers          Print a list of the peers
+                                - prohibits these options:
+                                command
+   -i no  interactive    Force ntpq to operate in interactive mode
+                                - prohibits these options:
+                                command
+                                peers
+   -n no  numeric        numeric host addresses
+   -v opt version        Output version information and exit
+   -? no  help           Display usage information and exit
+   -! no  more-help      Extended usage information passed thru pager
+   -> opt save-opts      Save the option state to a config file
+   -< Str load-opts      Load options from a config file
+                                - disabled as --no-load-opts
+                                - may appear multiple times
+
+Options are specified by doubled hyphens and their name
+or by a single hyphen and the flag character.
+
+The following option preset mechanisms are supported:
+ - reading file /users/stenn/.ntprc
+ - reading file /deacon/backroom/ntp-dev-hms/ntpq/.ntprc
+ - reading file /users/stenn/.ntprc
+ - reading file /deacon/backroom/ntp-dev-hms/ntpq/.ntprc
+ - examining environment variables named NTPQ_*
+
+The
+[= prog-name =]
+utility program is used to query NTP servers which
+implement the standard NTP mode 6 control message formats defined
+in Appendix B of the NTPv3 specification RFC1305, requesting
+information about current state and/or changes in that state.
+The same formats are used in NTPv4, although some of the
+variables have changed and new ones added. The description on this
+page is for the NTPv4 variables.
+The program may be run either in interactive mode or controlled using
+command line arguments.
+Requests to read and write arbitrary
+variables can be assembled, with raw and pretty-printed output
+options being available.
+The
+[= prog-name =]
+utility can also obtain and print a
+list of peers in a common format by sending multiple queries to the
+server.
+
+If one or more request options is included on the command line
+when
+[= prog-name =]
+is executed, each of the requests will be sent
+to the NTP servers running on each of the hosts given as command
+line arguments, or on localhost by default.
+If no request options
+are given,
+[= prog-name =]
+will attempt to read commands from the
+standard input and execute these on the NTP server running on the
+first host given on the command line, again defaulting to localhost
+when no other host is specified.
+The
+[= prog-name =]
+utility will prompt for
+commands if the standard input is a terminal device.
+
+The
+[= prog-name =]
+utility uses NTP mode 6 packets to communicate with the
+NTP server, and hence can be used to query any compatible server on
+the network which permits it.
+Note that since NTP is a UDP protocol
+this communication will be somewhat unreliable, especially over
+large distances in terms of network topology.
+The
+[= prog-name =]
+utility makes
+one attempt to retransmit requests, and will time requests out if
+the remote host is not heard from within a suitable timeout
+time.
+
+Specifying a
+command line option other than
+.Fl i
+or
+.Fl n
+will
+cause the specified query (queries) to be sent to the indicated
+host(s) immediately.
+Otherwise,
+[= prog-name =]  
+will attempt to read
+interactive format commands from the standard input.
+.Ss "Internal Commands"
+Interactive format commands consist of a keyword followed by zero
+to four arguments.
+Only enough characters of the full keyword to
+uniquely identify the command need be typed.
+
+A
+number of interactive format commands are executed entirely within
+the
+[= prog-name =]
+utility itself and do not result in NTP mode 6
+requests being sent to a server.
+These are described following.
+@@table @@code
+@@item ? [command_keyword]
+@@itemx help [command_keyword]
+A
+.Ql \&?
+by itself will print a list of all the command
+keywords known to this incarnation of
+[= prog-name =] .
+A
+.Ql \&?
+followed by a command keyword will print function and usage
+information about the command.
+This command is probably a better
+source of information about
+[= prog-name =]
+than this manual
+page.
+@@item addvars
+.Ar variable_name [=value] ...
+.Xc
+@@item rmvars variable_name ...
+@@item clearvars
+The data carried by NTP mode 6 messages consists of a list of
+items of the form
+.Ql variable_name=value ,
+where the
+.Ql =value
+is ignored, and can be omitted,
+in requests to the server to read variables.
+The
+[= prog-name =]
+utility maintains an internal list in which data to be included in control
+messages can be assembled, and sent using the
+.Ic readlist
+and
+.Ic writelist
+commands described below.
+The
+.Ic addvars
+command allows variables and their optional values to be added to
+the list.
+If more than one variable is to be added, the list should
+be comma-separated and not contain white space.
+The
+.Ic rmvars
+command can be used to remove individual variables from the list,
+while the
+.Ic clearlist
+command removes all variables from the
+list.
+@@item authenticate [ yes | no ]
+Normally
+[= prog-name =]
+does not authenticate requests unless
+they are write requests.
+The command
+.Ql authenticate yes
+causes
+[= prog-name =]
+to send authentication with all requests it
+makes.
+Authenticated requests causes some servers to handle
+requests slightly differently, and can occasionally melt the CPU in
+fuzzballs if you turn authentication on before doing a
+.Ic peer
+display.
+The command
+.Ql authenticate
+causes
+[= prog-name =]
+to display whether or not
+[= prog-name =]
+is currently autheinticating requests.
+@@item cooked
+Causes output from query commands to be "cooked", so that
+variables which are recognized by
+[= prog-name =]
+will have their
+values reformatted for human consumption.
+Variables which
+[= prog-name =]
+thinks should have a decodable value but didn't are
+marked with a trailing
+.Ql \&? .
+.@@item debug [
+.Cm more |
+.Cm less |
+.Cm off
+]
+.Xc
+With no argument, displays the current debug level.
+Otherwise, the debug level is changed to the indicated level.
+@@item delay milliseconds
+Specify a time interval to be added to timestamps included in
+requests which require authentication.
+This is used to enable
+(unreliable) server reconfiguration over long delay network paths
+or between machines whose clocks are unsynchronized.
+Actually the
+server does not now require timestamps in authenticated requests,
+so this command may be obsolete.
+@@item host hostname
+Set the host to which future queries will be sent.
+Hostname may
+be either a host name or a numeric address.
+@@item hostnames Cm yes | Cm no
+If
+.Cm yes
+is specified, host names are printed in
+information displays.
+If
+.Cm no
+is specified, numeric
+addresses are printed instead.
+The default is
+.Cm yes ,
+unless
+modified using the command line
+.Fl n
+switch.
+@@item keyid keyid
+This command allows the specification of a key number to be
+used to authenticate configuration requests.
+This must correspond
+to a key number the server has been configured to use for this
+purpose.
+@@item ntpversion [
+.Cm 1 |
+.Cm 2 |
+.Cm 3 |
+.Cm 4
+]
+.Xc
+Sets the NTP version number which
+[= prog-name =]
+claims in
+packets.
+Defaults to 3, Note that mode 6 control messages (and
+modes, for that matter) didn't exist in NTP version 1.
+There appear
+to be no servers left which demand version 1.
+With no argument, displays the current NTP version that will be used
+when communicating with servers.
+@@item quit
+Exit
+[= prog-name =] .
+@@item passwd
+This command prompts you to type in a password (which will not
+be echoed) which will be used to authenticate configuration
+requests.
+The password must correspond to the key configured for
+use by the NTP server for this purpose if such requests are to be
+successful.
+@@item raw
+Causes all output from query commands is printed as received
+from the remote server.
+The only formating/interpretation done on
+the data is to transform nonascii data into a printable (but barely
+understandable) form.
+@@item timeout Ar milliseconds
+Specify a timeout period for responses to server queries.
+The
+default is about 5000 milliseconds.
+Note that since
+[= prog-name =]
+retries each query once after a timeout, the total waiting time for
+a timeout will be twice the timeout value set.
+@@end table
+
+please send bug reports to:  http://bugs.ntp.isc.org, bugs@@ntp.org
+@end example
+@exampleindent 4
+
+@node ntpq ipv4
+@subsection ipv4 option (-4)
+@cindex ntpq-ipv4
+
+This is the ``force ipv4 dns name resolution'' option.
+
+This option has some usage constraints.  It:
+@itemize @bullet
+@item
+is a member of the ipv4 class of options.
+@end itemize
+
+Force DNS resolution of following host names on the command line
+to the IPv4 namespace.
+
+@node ntpq ipv6
+@subsection ipv6 option (-6)
+@cindex ntpq-ipv6
+
+This is the ``force ipv6 dns name resolution'' option.
+
+This option has some usage constraints.  It:
+@itemize @bullet
+@item
+is a member of the ipv4 class of options.
+@end itemize
+
+Force DNS resolution of following host names on the command line
+to the IPv6 namespace.
+
+@node ntpq command
+@subsection command option (-c)
+@cindex ntpq-command
+
+This is the ``run a command and exit'' option.
+
+This option has some usage constraints.  It:
+@itemize @bullet
+@item
+may appear an unlimited number of times.
+@end itemize
+
+The following argument is interpreted as an interactive format command
+and is added to the list of commands to be executed on the specified
+host(s).
+
+@node ntpq debug-level
+@subsection debug-level option (-d)
+@cindex ntpq-debug-level
+
+This is the ``increase output debug message level'' option.
+
+This option has some usage constraints.  It:
+@itemize @bullet
+@item
+may appear an unlimited number of times.
+@end itemize
+
+Increase the debugging message output level.
+
+@node ntpq set-debug-level
+@subsection set-debug-level option (-D)
+@cindex ntpq-set-debug-level
+
+This is the ``set the output debug message level'' option.
+
+This option has some usage constraints.  It:
+@itemize @bullet
+@item
+may appear an unlimited number of times.
+@end itemize
+
+Set the output debugging level.  Can be supplied multiple times,
+but each overrides the previous value(s).
+
+@node ntpq peers
+@subsection peers option (-p)
+@cindex ntpq-peers
+
+This is the ``print a list of the peers'' option.
+
+This option has some usage constraints.  It:
+@itemize @bullet
+@item
+must not appear in combination with any of the following options:
+command.
+@end itemize
+
+Print a list of the peers known to the server as well as a summary
+of their state. This is equivalent to the 'peers' interactive command.
+
+@node ntpq interactive
+@subsection interactive option (-i)
+@cindex ntpq-interactive
+
+This is the ``force ntpq to operate in interactive mode'' option.
+
+This option has some usage constraints.  It:
+@itemize @bullet
+@item
+must not appear in combination with any of the following options:
+command, peers.
+@end itemize
+
+Force ntpq to operate in interactive mode.  Prompts will be written
+to the standard output and commands read from the standard input.
+
+@node ntpq numeric
+@subsection numeric option (-n)
+@cindex ntpq-numeric
+
+This is the ``numeric host addresses'' option.
+Output all host addresses in dotted-quad numeric format rather than
+converting to the canonical host names. 
diff --git a/ntpq/ntpq.1 b/ntpq/ntpq.1
new file mode 100644 (file)
index 0000000..c1ae560
--- /dev/null
@@ -0,0 +1,385 @@
+.TH NTPQ 1 2006-06-27 "" "Programmer's Manual"
+.\"  DO NOT EDIT THIS FILE   (ntpq.1)
+.\"  
+.\"  It has been AutoGen-ed  Tuesday June 27, 2006 at 10:37:24 PM EDT
+.\"  From the definitions    ntpq-opts.def
+.\"  and the template file   agman1.tpl
+.\"
+.SH NAME
+ntpq \- standard NTP query program
+.SH SYNOPSIS
+.B ntpq
+.\" Mixture of short (flag) options and long options
+.RB [ -\fIflag\fP " [\fIvalue\fP]]... [" --\fIopt-name\fP " [[=| ]\fIvalue\fP]]..."
+.br
+.in +8
+[ host ...]
+.SH "DESCRIPTION"
+This manual page documents, briefly, the \fBntpq\fP command.
+The
+[= prog-name =]
+utility program is used to query NTP servers which
+implement the standard NTP mode 6 control message formats defined
+in Appendix B of the NTPv3 specification RFC1305, requesting
+information about current state and/or changes in that state.
+The same formats are used in NTPv4, although some of the
+variables have changed and new ones added. The description on this
+page is for the NTPv4 variables.
+The program may be run either in interactive mode or controlled using
+command line arguments.
+Requests to read and write arbitrary
+variables can be assembled, with raw and pretty-printed output
+options being available.
+The
+[= prog-name =]
+utility can also obtain and print a
+list of peers in a common format by sending multiple queries to the
+server.
+
+If one or more request options is included on the command line
+when
+[= prog-name =]
+is executed, each of the requests will be sent
+to the NTP servers running on each of the hosts given as command
+line arguments, or on localhost by default.
+If no request options
+are given,
+[= prog-name =]
+will attempt to read commands from the
+standard input and execute these on the NTP server running on the
+first host given on the command line, again defaulting to localhost
+when no other host is specified.
+The
+[= prog-name =]
+utility will prompt for
+commands if the standard input is a terminal device.
+
+The
+[= prog-name =]
+utility uses NTP mode 6 packets to communicate with the
+NTP server, and hence can be used to query any compatible server on
+the network which permits it.
+Note that since NTP is a UDP protocol
+this communication will be somewhat unreliable, especially over
+large distances in terms of network topology.
+The
+[= prog-name =]
+utility makes
+one attempt to retransmit requests, and will time requests out if
+the remote host is not heard from within a suitable timeout
+time.
+
+Specifying a
+command line option other than
+.Fl i
+or
+.Fl n
+will
+cause the specified query (queries) to be sent to the indicated
+host(s) immediately.
+Otherwise,
+[= prog-name =]  
+will attempt to read
+interactive format commands from the standard input.
+.Ss "Internal Commands"
+Interactive format commands consist of a keyword followed by zero
+to four arguments.
+Only enough characters of the full keyword to
+uniquely identify the command need be typed.
+
+A
+number of interactive format commands are executed entirely within
+the
+[= prog-name =]
+utility itself and do not result in NTP mode 6
+requests being sent to a server.
+These are described following.
+.sp
+.IR "? [command_keyword]"
+.sp 1x help [command_keyword]
+A
+.Ql \\&?
+by itself will print a list of all the command
+keywords known to this incarnation of
+[= prog-name =] .
+A
+.Ql \\&?
+followed by a command keyword will print function and usage
+information about the command.
+This command is probably a better
+source of information about
+[= prog-name =]
+than this manual
+page.
+.sp
+.IR "addvars"
+.Ar variable_name [=value] ...
+.Xc
+.sp
+.IR "rmvars variable_name ..."
+.sp
+.IR "clearvars"
+The data carried by NTP mode 6 messages consists of a list of
+items of the form
+.Ql variable_name=value ,
+where the
+.Ql =value
+is ignored, and can be omitted,
+in requests to the server to read variables.
+The
+[= prog-name =]
+utility maintains an internal list in which data to be included in control
+messages can be assembled, and sent using the
+.Ic readlist
+and
+.Ic writelist
+commands described below.
+The
+.Ic addvars
+command allows variables and their optional values to be added to
+the list.
+If more than one variable is to be added, the list should
+be comma-separated and not contain white space.
+The
+.Ic rmvars
+command can be used to remove individual variables from the list,
+while the
+.Ic clearlist
+command removes all variables from the
+list.
+.sp
+.IR "authenticate [ yes | no ]"
+Normally
+[= prog-name =]
+does not authenticate requests unless
+they are write requests.
+The command
+.Ql authenticate yes
+causes
+[= prog-name =]
+to send authentication with all requests it
+makes.
+Authenticated requests causes some servers to handle
+requests slightly differently, and can occasionally melt the CPU in
+fuzzballs if you turn authentication on before doing a
+.Ic peer
+display.
+The command
+.Ql authenticate
+causes
+[= prog-name =]
+to display whether or not
+[= prog-name =]
+is currently autheinticating requests.
+.sp
+.IR "cooked"
+Causes output from query commands to be "cooked", so that
+variables which are recognized by
+[= prog-name =]
+will have their
+values reformatted for human consumption.
+Variables which
+[= prog-name =]
+thinks should have a decodable value but didn't are
+marked with a trailing
+.Ql \\&? .
+.@item debug [
+.Cm more |
+.Cm less |
+.Cm off
+]
+.Xc
+With no argument, displays the current debug level.
+Otherwise, the debug level is changed to the indicated level.
+.sp
+.IR "delay milliseconds"
+Specify a time interval to be added to timestamps included in
+requests which require authentication.
+This is used to enable
+(unreliable) server reconfiguration over long delay network paths
+or between machines whose clocks are unsynchronized.
+Actually the
+server does not now require timestamps in authenticated requests,
+so this command may be obsolete.
+.sp
+.IR "host hostname"
+Set the host to which future queries will be sent.
+Hostname may
+be either a host name or a numeric address.
+.sp
+.IR "hostnames Cm yes | Cm no"
+If
+.Cm yes
+is specified, host names are printed in
+information displays.
+If
+.Cm no
+is specified, numeric
+addresses are printed instead.
+The default is
+.Cm yes ,
+unless
+modified using the command line
+.Fl n
+switch.
+.sp
+.IR "keyid keyid"
+This command allows the specification of a key number to be
+used to authenticate configuration requests.
+This must correspond
+to a key number the server has been configured to use for this
+purpose.
+.sp
+.IR "ntpversion ["
+.Cm 1 |
+.Cm 2 |
+.Cm 3 |
+.Cm 4
+]
+.Xc
+Sets the NTP version number which
+[= prog-name =]
+claims in
+packets.
+Defaults to 3, Note that mode 6 control messages (and
+modes, for that matter) didn't exist in NTP version 1.
+There appear
+to be no servers left which demand version 1.
+With no argument, displays the current NTP version that will be used
+when communicating with servers.
+.sp
+.IR "quit"
+Exit
+[= prog-name =] .
+.sp
+.IR "passwd"
+This command prompts you to type in a password (which will not
+be echoed) which will be used to authenticate configuration
+requests.
+The password must correspond to the key configured for
+use by the NTP server for this purpose if such requests are to be
+successful.
+.sp
+.IR "raw"
+Causes all output from query commands is printed as received
+from the remote server.
+The only formating/interpretation done on
+the data is to transform nonascii data into a printable (but barely
+understandable) form.
+.sp
+.IR "timeout Ar milliseconds"
+Specify a timeout period for responses to server queries.
+The
+default is about 5000 milliseconds.
+Note that since
+[= prog-name =]
+retries each query once after a timeout, the total waiting time for
+a timeout will be twice the timeout value set.
+.br
+
+.SH OPTIONS
+.TP
+.BR -4 ", " --ipv4
+Force IPv4 DNS name resolution.
+This option is a member of the ipv4 class of options.
+.sp
+Force DNS resolution of following host names on the command line
+to the IPv4 namespace.
+.TP
+.BR -6 ", " --ipv6
+Force IPv6 DNS name resolution.
+This option is a member of the ipv4 class of options.
+.sp
+Force DNS resolution of following host names on the command line
+to the IPv6 namespace.
+.TP
+.BR -c " \fIcmd\fP, " --command "=" \fIcmd\fP
+run a command and exit.
+This option may appear an unlimited number of times.
+.sp
+The following argument is interpreted as an interactive format command
+and is added to the list of commands to be executed on the specified
+host(s).
+.TP
+.BR -d ", " --debug-level
+Increase output debug message level.
+This option may appear an unlimited number of times.
+.sp
+Increase the debugging message output level.
+.TP
+.BR -D " \fIstring\fP, " --set-debug-level "=" \fIstring\fP
+Set the output debug message level.
+This option may appear an unlimited number of times.
+.sp
+Set the output debugging level.  Can be supplied multiple times,
+but each overrides the previous value(s).
+.TP
+.BR -p ", " --peers
+Print a list of the peers.
+This option must not appear in combination with any of the following options:
+command.
+.sp
+Print a list of the peers known to the server as well as a summary
+of their state. This is equivalent to the 'peers' interactive command.
+.TP
+.BR -i ", " --interactive
+Force ntpq to operate in interactive mode.
+This option must not appear in combination with any of the following options:
+command, peers.
+.sp
+Force ntpq to operate in interactive mode.  Prompts will be written
+to the standard output and commands read from the standard input.
+.TP
+.BR -n ", " --numeric
+numeric host addresses.
+.sp
+Output all host addresses in dotted-quad numeric format rather than
+converting to the canonical host names. 
+.TP
+.BR \-? , " \--help"
+Display usage information and exit.
+.TP
+.BR \-! , " \--more-help"
+Extended usage information passed thru pager.
+.TP
+.BR \-> " [\fIrcfile\fP]," " \--save-opts" "[=\fIrcfile\fP]"
+Save the option state to \fIrcfile\fP.  The default is the \fIlast\fP
+configuration file listed in the \fBOPTION PRESETS\fP section, below.
+.TP
+.BR \-< " \fIrcfile\fP," " \--load-opts" "=\fIrcfile\fP," " --no-load-opts"
+Load options from \fIrcfile\fP.
+The \fIno-load-opts\fP form will disable the loading
+of earlier RC/INI files.  \fI--no-load-opts\fP is handled early,
+out of order.
+.TP
+.BR \-v " [{\fIv|c|n\fP}]," " \--version" "[=\fI{v|c|n}\fP]"
+Output version of program and exit.  The default mode is `v', a simple
+version.  The `c' mode will print copyright information and `n' will
+print the full copyright notice.
+.SH OPTION PRESETS
+Any option that is not marked as \fInot presettable\fP may be preset
+by loading values from configuration ("RC" or ".INI") file(s) and values from
+environment variables named:
+.nf
+  \fBNTPQ_<option-name>\fP or \fBNTPQ\fP
+.fi
+.aj
+The environmental presets take precedence (are processed later than)
+the configuration files.
+The \fIhomerc\fP files are "\fI$HOME\fP", "\fI.\fP", "\fI$HOME\fP", and "\fI.\fP".
+If any of these are directories, then the file \fI.ntprc\fP
+is searched for within those directories.
+.SH AUTHOR
+ntp.org
+.br
+Please send bug reports to:  http://bugs.ntp.isc.org, bugs@ntp.org
+
+.PP
+.nf
+.na
+see html/copyright.html
+.fi
+.ad
+.PP
+This manual page was \fIAutoGen\fP-erated from the \fBntpq\fP
+option definitions.
diff --git a/sntp/libopts/COPYING.lgpl b/sntp/libopts/COPYING.lgpl
new file mode 100644 (file)
index 0000000..52f31fd
--- /dev/null
@@ -0,0 +1,502 @@
+                 GNU LESSER GENERAL PUBLIC LICENSE
+                      Version 2.1, February 1999
+
+ Copyright (C) 1991, 1999 Free Software Foundation, Inc.
+ 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+[This is the first released version of the Lesser GPL.  It also counts
+ as the successor of the GNU Library Public License, version 2, hence
+ the version number 2.1.]
+
+                           Preamble
+
+  The licenses for most software are designed to take away your
+freedom to share and change it.  By contrast, the GNU General Public
+Licenses are intended to guarantee your freedom to share and change
+free software--to make sure the software is free for all its users.
+
+  This license, the Lesser General Public License, applies to some
+specially designated software packages--typically libraries--of the
+Free Software Foundation and other authors who decide to use it.  You
+can use it too, but we suggest you first think carefully about whether
+this license or the ordinary General Public License is the better
+strategy to use in any particular case, based on the explanations below.
+
+  When we speak of free software, we are referring to freedom of use,
+not price.  Our General Public Licenses are designed to make sure that
+you have the freedom to distribute copies of free software (and charge
+for this service if you wish); that you receive source code or can get
+it if you want it; that you can change the software and use pieces of
+it in new free programs; and that you are informed that you can do
+these things.
+
+  To protect your rights, we need to make restrictions that forbid
+distributors to deny you these rights or to ask you to surrender these
+rights.  These restrictions translate to certain responsibilities for
+you if you distribute copies of the library or if you modify it.
+
+  For example, if you distribute copies of the library, whether gratis
+or for a fee, you must give the recipients all the rights that we gave
+you.  You must make sure that they, too, receive or can get the source
+code.  If you link other code with the library, you must provide
+complete object files to the recipients, so that they can relink them
+with the library after making changes to the library and recompiling
+it.  And you must show them these terms so they know their rights.
+
+  We protect your rights with a two-step method: (1) we copyright the
+library, and (2) we offer you this license, which gives you legal
+permission to copy, distribute and/or modify the library.
+
+  To protect each distributor, we want to make it very clear that
+there is no warranty for the free library.  Also, if the library is
+modified by someone else and passed on, the recipients should know
+that what they have is not the original version, so that the original
+author's reputation will not be affected by problems that might be
+introduced by others.
+
+  Finally, software patents pose a constant threat to the existence of
+any free program.  We wish to make sure that a company cannot
+effectively restrict the users of a free program by obtaining a
+restrictive license from a patent holder.  Therefore, we insist that
+any patent license obtained for a version of the library must be
+consistent with the full freedom of use specified in this license.
+
+  Most GNU software, including some libraries, is covered by the
+ordinary GNU General Public License.  This license, the GNU Lesser
+General Public License, applies to certain designated libraries, and
+is quite different from the ordinary General Public License.  We use
+this license for certain libraries in order to permit linking those
+libraries into non-free programs.
+
+  When a program is linked with a library, whether statically or using
+a shared library, the combination of the two is legally speaking a
+combined work, a derivative of the original library.  The ordinary
+General Public License therefore permits such linking only if the
+entire combination fits its criteria of freedom.  The Lesser General
+Public License permits more lax criteria for linking other code with
+the library.
+
+  We call this license the "Lesser" General Public License because it
+does Less to protect the user's freedom than the ordinary General
+Public License.  It also provides other free software developers Less
+of an advantage over competing non-free programs.  These disadvantages
+are the reason we use the ordinary General Public License for many
+libraries.  However, the Lesser license provides advantages in certain
+special circumstances.
+
+  For example, on rare occasions, there may be a special need to
+encourage the widest possible use of a certain library, so that it becomes
+a de-facto standard.  To achieve this, non-free programs must be
+allowed to use the library.  A more frequent case is that a free
+library does the same job as widely used non-free libraries.  In this
+case, there is little to gain by limiting the free library to free
+software only, so we use the Lesser General Public License.
+
+  In other cases, permission to use a particular library in non-free
+programs enables a greater number of people to use a large body of
+free software.  For example, permission to use the GNU C Library in
+non-free programs enables many more people to use the whole GNU
+operating system, as well as its variant, the GNU/Linux operating
+system.
+
+  Although the Lesser General Public License is Less protective of the
+users' freedom, it does ensure that the user of a program that is
+linked with the Library has the freedom and the wherewithal to run
+that program using a modified version of the Library.
+
+  The precise terms and conditions for copying, distribution and
+modification follow.  Pay close attention to the difference between a
+"work based on the library" and a "work that uses the library".  The
+former contains code derived from the library, whereas the latter must
+be combined with the library in order to run.
+
+                 GNU LESSER GENERAL PUBLIC LICENSE
+   TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+  0. This License Agreement applies to any software library or other
+program which contains a notice placed by the copyright holder or
+other authorized party saying it may be distributed under the terms of
+this Lesser General Public License (also called "this License").
+Each licensee is addressed as "you".
+
+  A "library" means a collection of software functions and/or data
+prepared so as to be conveniently linked with application programs
+(which use some of those functions and data) to form executables.
+
+  The "Library", below, refers to any such software library or work
+which has been distributed under these terms.  A "work based on the
+Library" means either the Library or any derivative work under
+copyright law: that is to say, a work containing the Library or a
+portion of it, either verbatim or with modifications and/or translated
+straightforwardly into another language.  (Hereinafter, translation is
+included without limitation in the term "modification".)
+
+  "Source code" for a work means the preferred form of the work for
+making modifications to it.  For a library, complete source code means
+all the source code for all modules it contains, plus any associated
+interface definition files, plus the scripts used to control compilation
+and installation of the library.
+
+  Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope.  The act of
+running a program using the Library is not restricted, and output from
+such a program is covered only if its contents constitute a work based
+on the Library (independent of the use of the Library in a tool for
+writing it).  Whether that is true depends on what the Library does
+and what the program that uses the Library does.
+  
+  1. You may copy and distribute verbatim copies of the Library's
+complete source code as you receive it, in any medium, provided that
+you conspicuously and appropriately publish on each copy an
+appropriate copyright notice and disclaimer of warranty; keep intact
+all the notices that refer to this License and to the absence of any
+warranty; and distribute a copy of this License along with the
+Library.
+
+  You may charge a fee for the physical act of transferring a copy,
+and you may at your option offer warranty protection in exchange for a
+fee.
+
+  2. You may modify your copy or copies of the Library or any portion
+of it, thus forming a work based on the Library, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+    a) The modified work must itself be a software library.
+
+    b) You must cause the files modified to carry prominent notices
+    stating that you changed the files and the date of any change.
+
+    c) You must cause the whole of the work to be licensed at no
+    charge to all third parties under the terms of this License.
+
+    d) If a facility in the modified Library refers to a function or a
+    table of data to be supplied by an application program that uses
+    the facility, other than as an argument passed when the facility
+    is invoked, then you must make a good faith effort to ensure that,
+    in the event an application does not supply such function or
+    table, the facility still operates, and performs whatever part of
+    its purpose remains meaningful.
+
+    (For example, a function in a library to compute square roots has
+    a purpose that is entirely well-defined independent of the
+    application.  Therefore, Subsection 2d requires that any
+    application-supplied function or table used by this function must
+    be optional: if the application does not supply it, the square
+    root function must still compute square roots.)
+
+These requirements apply to the modified work as a whole.  If
+identifiable sections of that work are not derived from the Library,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works.  But when you
+distribute the same sections as part of a whole which is a work based
+on the Library, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote
+it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Library.
+
+In addition, mere aggregation of another work not based on the Library
+with the Library (or with a work based on the Library) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+  3. You may opt to apply the terms of the ordinary GNU General Public
+License instead of this License to a given copy of the Library.  To do
+this, you must alter all the notices that refer to this License, so
+that they refer to the ordinary GNU General Public License, version 2,
+instead of to this License.  (If a newer version than version 2 of the
+ordinary GNU General Public License has appeared, then you can specify
+that version instead if you wish.)  Do not make any other change in
+these notices.
+
+  Once this change is made in a given copy, it is irreversible for
+that copy, so the ordinary GNU General Public License applies to all
+subsequent copies and derivative works made from that copy.
+
+  This option is useful when you wish to copy part of the code of
+the Library into a program that is not a library.
+
+  4. You may copy and distribute the Library (or a portion or
+derivative of it, under Section 2) in object code or executable form
+under the terms of Sections 1 and 2 above provided that you accompany
+it with the complete corresponding machine-readable source code, which
+must be distributed under the terms of Sections 1 and 2 above on a
+medium customarily used for software interchange.
+
+  If distribution of object code is made by offering access to copy
+from a designated place, then offering equivalent access to copy the
+source code from the same place satisfies the requirement to
+distribute the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+  5. A program that contains no derivative of any portion of the
+Library, but is designed to work with the Library by being compiled or
+linked with it, is called a "work that uses the Library".  Such a
+work, in isolation, is not a derivative work of the Library, and
+therefore falls outside the scope of this License.
+
+  However, linking a "work that uses the Library" with the Library
+creates an executable that is a derivative of the Library (because it
+contains portions of the Library), rather than a "work that uses the
+library".  The executable is therefore covered by this License.
+Section 6 states terms for distribution of such executables.
+
+  When a "work that uses the Library" uses material from a header file
+that is part of the Library, the object code for the work may be a
+derivative work of the Library even though the source code is not.
+Whether this is true is especially significant if the work can be
+linked without the Library, or if the work is itself a library.  The
+threshold for this to be true is not precisely defined by law.
+
+  If such an object file uses only numerical parameters, data
+structure layouts and accessors, and small macros and small inline
+functions (ten lines or less in length), then the use of the object
+file is unrestricted, regardless of whether it is legally a derivative
+work.  (Executables containing this object code plus portions of the
+Library will still fall under Section 6.)
+
+  Otherwise, if the work is a derivative of the Library, you may
+distribute the object code for the work under the terms of Section 6.
+Any executables containing that work also fall under Section 6,
+whether or not they are linked directly with the Library itself.
+
+  6. As an exception to the Sections above, you may also combine or
+link a "work that uses the Library" with the Library to produce a
+work containing portions of the Library, and distribute that work
+under terms of your choice, provided that the terms permit
+modification of the work for the customer's own use and reverse
+engineering for debugging such modifications.
+
+  You must give prominent notice with each copy of the work that the
+Library is used in it and that the Library and its use are covered by
+this License.  You must supply a copy of this License.  If the work
+during execution displays copyright notices, you must include the
+copyright notice for the Library among them, as well as a reference
+directing the user to the copy of this License.  Also, you must do one
+of these things:
+
+    a) Accompany the work with the complete corresponding
+    machine-readable source code for the Library including whatever
+    changes were used in the work (which must be distributed under
+    Sections 1 and 2 above); and, if the work is an executable linked
+    with the Library, with the complete machine-readable "work that
+    uses the Library", as object code and/or source code, so that the
+    user can modify the Library and then relink to produce a modified
+    executable containing the modified Library.  (It is understood
+    that the user who changes the contents of definitions files in the
+    Library will not necessarily be able to recompile the application
+    to use the modified definitions.)
+
+    b) Use a suitable shared library mechanism for linking with the
+    Library.  A suitable mechanism is one that (1) uses at run time a
+    copy of the library already present on the user's computer system,
+    rather than copying library functions into the executable, and (2)
+    will operate properly with a modified version of the library, if
+    the user installs one, as long as the modified version is
+    interface-compatible with the version that the work was made with.
+
+    c) Accompany the work with a written offer, valid for at
+    least three years, to give the same user the materials
+    specified in Subsection 6a, above, for a charge no more
+    than the cost of performing this distribution.
+
+    d) If distribution of the work is made by offering access to copy
+    from a designated place, offer equivalent access to copy the above
+    specified materials from the same place.
+
+    e) Verify that the user has already received a copy of these
+    materials or that you have already sent this user a copy.
+
+  For an executable, the required form of the "work that uses the
+Library" must include any data and utility programs needed for
+reproducing the executable from it.  However, as a special exception,
+the materials to be distributed need not include anything that is
+normally distributed (in either source or binary form) with the major
+components (compiler, kernel, and so on) of the operating system on
+which the executable runs, unless that component itself accompanies
+the executable.
+
+  It may happen that this requirement contradicts the license
+restrictions of other proprietary libraries that do not normally
+accompany the operating system.  Such a contradiction means you cannot
+use both them and the Library together in an executable that you
+distribute.
+
+  7. You may place library facilities that are a work based on the
+Library side-by-side in a single library together with other library
+facilities not covered by this License, and distribute such a combined
+library, provided that the separate distribution of the work based on
+the Library and of the other library facilities is otherwise
+permitted, and provided that you do these two things:
+
+    a) Accompany the combined library with a copy of the same work
+    based on the Library, uncombined with any other library
+    facilities.  This must be distributed under the terms of the
+    Sections above.
+
+    b) Give prominent notice with the combined library of the fact
+    that part of it is a work based on the Library, and explaining
+    where to find the accompanying uncombined form of the same work.
+
+  8. You may not copy, modify, sublicense, link with, or distribute
+the Library except as expressly provided under this License.  Any
+attempt otherwise to copy, modify, sublicense, link with, or
+distribute the Library is void, and will automatically terminate your
+rights under this License.  However, parties who have received copies,
+or rights, from you under this License will not have their licenses
+terminated so long as such parties remain in full compliance.
+
+  9. You are not required to accept this License, since you have not
+signed it.  However, nothing else grants you permission to modify or
+distribute the Library or its derivative works.  These actions are
+prohibited by law if you do not accept this License.  Therefore, by
+modifying or distributing the Library (or any work based on the
+Library), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Library or works based on it.
+
+  10. Each time you redistribute the Library (or any work based on the
+Library), the recipient automatically receives a license from the
+original licensor to copy, distribute, link with or modify the Library
+subject to these terms and conditions.  You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties with
+this License.
+
+  11. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License.  If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Library at all.  For example, if a patent
+license would not permit royalty-free redistribution of the Library by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Library.
+
+If any portion of this section is held invalid or unenforceable under any
+particular circumstance, the balance of the section is intended to apply,
+and the section as a whole is intended to apply in other circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system which is
+implemented by public license practices.  Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+  12. If the distribution and/or use of the Library is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Library under this License may add
+an explicit geographical distribution limitation excluding those countries,
+so that distribution is permitted only in or among countries not thus
+excluded.  In such case, this License incorporates the limitation as if
+written in the body of this License.
+
+  13. The Free Software Foundation may publish revised and/or new
+versions of the Lesser General Public License from time to time.
+Such new versions will be similar in spirit to the present version,
+but may differ in detail to address new problems or concerns.
+
+Each version is given a distinguishing version number.  If the Library
+specifies a version number of this License which applies to it and
+"any later version", you have the option of following the terms and
+conditions either of that version or of any later version published by
+the Free Software Foundation.  If the Library does not specify a
+license version number, you may choose any version ever published by
+the Free Software Foundation.
+
+  14. If you wish to incorporate parts of the Library into other free
+programs whose distribution conditions are incompatible with these,
+write to the author to ask for permission.  For software which is
+copyrighted by the Free Software Foundation, write to the Free
+Software Foundation; we sometimes make exceptions for this.  Our
+decision will be guided by the two goals of preserving the free status
+of all derivatives of our free software and of promoting the sharing
+and reuse of software generally.
+
+                           NO WARRANTY
+
+  15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO
+WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW.
+EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR
+OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY
+KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+PURPOSE.  THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE
+LIBRARY IS WITH YOU.  SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME
+THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
+
+  16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN
+WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY
+AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU
+FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR
+CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE
+LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
+RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
+FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
+SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+DAMAGES.
+
+                    END OF TERMS AND CONDITIONS
+
+           How to Apply These Terms to Your New Libraries
+
+  If you develop a new library, and you want it to be of the greatest
+possible use to the public, we recommend making it free software that
+everyone can redistribute and change.  You can do so by permitting
+redistribution under these terms (or, alternatively, under the terms of the
+ordinary General Public License).
+
+  To apply these terms, attach the following notices to the library.  It is
+safest to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least the
+"copyright" line and a pointer to where the full notice is found.
+
+    <one line to give the library's name and a brief idea of what it does.>
+    Copyright (C) <year>  <name of author>
+
+    This library is free software; you can redistribute it and/or
+    modify it under the terms of the GNU Lesser General Public
+    License as published by the Free Software Foundation; either
+    version 2.1 of the License, or (at your option) any later version.
+
+    This library is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+    Lesser General Public License for more details.
+
+    You should have received a copy of the GNU Lesser General Public
+    License along with this library; if not, write to the Free Software
+    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
+
+Also add information on how to contact you by electronic and paper mail.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the library, if
+necessary.  Here is a sample; alter the names:
+
+  Yoyodyne, Inc., hereby disclaims all copyright interest in the
+  library `Frob' (a library for tweaking knobs) written by James Random Hacker.
+
+  <signature of Ty Coon>, 1 April 1990
+  Ty Coon, President of Vice
+
+That's all there is to it!
diff --git a/sntp/libopts/COPYING.mbsd b/sntp/libopts/COPYING.mbsd
new file mode 100644 (file)
index 0000000..8a70427
--- /dev/null
@@ -0,0 +1,26 @@
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+    1. Redistributions of source code must retain the above copyright
+       notice, this list of conditions and the following disclaimer.
+
+    2. Redistributions in binary form must reproduce the above
+       copyright notice, this list of conditions and the following
+       disclaimer in the documentation and/or other materials provided
+       with the distribution.
+
+    3. The name of the author may not be used to endorse or promote
+       products derived from this software without specific prior
+       written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
+INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
+IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE.
diff --git a/sntp/libopts/MakeDefs.inc b/sntp/libopts/MakeDefs.inc
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/sntp/libopts/Makefile.am b/sntp/libopts/Makefile.am
new file mode 100644 (file)
index 0000000..ca0f8a6
--- /dev/null
@@ -0,0 +1,20 @@
+## LIBOPTS Makefile
+MAINTAINERCLEANFILES  = Makefile.in
+lib_LTLIBRARIES       = libopts.la
+libopts_la_SOURCES    = libopts.c
+libopts_la_CPPFLAGS   = -I$(top_srcdir)
+libopts_la_LDFLAGS    = -version-info  27:1:2
+EXTRA_DIST            = \
+    COPYING.lgpl         COPYING.mbsd         MakeDefs.inc  \
+    README               autoopts/options.h   autoopts/usage-txt.h  \
+    autoopts.c           autoopts.h           boolean.c  \
+    compat/compat.h      compat/pathfind.c    compat/snprintf.c  \
+    compat/strdup.c      configfile.c         cook.c  \
+    enumeration.c        environment.c        genshell.c  \
+    genshell.h           load.c               m4/libopts.m4  \
+    m4/liboptschk.m4     makeshell.c          nested.c  \
+    numeric.c            pgusage.c            proto.h  \
+    putshell.c           restore.c            save.c  \
+    sort.c               stack.c              streqvcmp.c  \
+    text_mmap.c          tokenize.c           usage.c  \
+    version.c
diff --git a/sntp/libopts/README b/sntp/libopts/README
new file mode 100644 (file)
index 0000000..7f426fa
--- /dev/null
@@ -0,0 +1,93 @@
+        THIS TARBALL IS NOT A FULL DISTRIBUTION.
+
+The contents of this tarball is designed to be incorporated into
+software packages that utilize the AutoOpts option automation
+package and are intended to be installed on systems that may not
+have libopts installed.  It is redistributable under the terms
+of either the LGPL (see COPYING.lgpl) or under the terms of
+the advertising clause free BSD license (see COPYING.mbsd).
+
+Usage Instructions for autoconf/automake/libtoolized projects:
+
+1. Install the unrolled tarball into your package source tree,
+   copying ``libopts.m4'' to your autoconf macro directory.
+
+   In your bootstrap (pre-configure) script, you can do this:
+
+      rm -rf libopts libopts-*
+      gunzip -c `autoopts-config libsrc` | tar -xvf -
+      mv -f libopts-*.*.* libopts
+      cp -fp libopts/m4/*.m4 m4/.
+
+   I tend to put my configure auxiliary files in "m4".
+   Whatever directory you choose, if it is not ".", then
+   be sure to tell autoconf about it with:
+
+      AC_CONFIG_AUX_DIR(m4)
+
+   This is one macro where you *MUST* remember to *NOT* quote
+   the argument.  If you do, automake will get lost.
+
+2. Add the following to your ``configure.ac'' file:
+
+      LIBOPTS_CHECK
+
+   or:
+
+      LIBOPTS_CHECK([relative/path/to/libopts])
+
+   This macro will automatically invoke
+
+      AC_CONFIG_FILES( [relative/path/to/libopts/Makefile] )
+
+   The default ``relative/path/to/libopts'' is simply
+   ``libopts''.
+
+3. Add the following to your top level ``Makefile.am'' file:
+
+      if NEED_LIBOPTS
+         SUBDIRS += $(LIBOPTS_DIR)
+      endif
+
+   where ``<...>'' can be whatever other files or directories
+   you may need.  The SUBDIRS must be properly ordered.
+   *PLEASE NOTE* it is crucial that the SUBDIRS be set under the
+   control of an automake conditional.  To work correctly,
+   automake has to know the range of possible values of SUBDIRS.
+   It's a magical name with magical properties.  ``NEED_LIBOPTS''
+   will be correctly set by the ``LIBOPTS_CHECK'' macro, above.
+
+4. Add ``$(LIBOPTS_CFLAGS)'' to relevant compiler flags and
+   ``$(LIBOPTS_LDADD)'' to relevant link options whereever
+   you need them in your build tree.
+
+5. Make sure your object files explicitly depend upon the
+   generated options header file.  e.g.:
+
+     $(prog_OBJECTS) : prog-opts.h
+     prog-opts.h : prog-opts.c
+     prog-opts.c : prog-opts.def
+         autogen prog-opts.def
+
+6. *OPTIONAL* --
+   If you are creating man pages and texi documentation from
+   the program options, you will need these rules somewhere, too:
+
+     man_MANS = prog.1
+     prog.1 : prog-opts.def
+         autogen -Tagman1.tpl -bprog prog-opts.def
+
+     prog-invoke.texi : prog-opts.def
+         autogen -Taginfo.tpl -bprog-invoke prog-opts.def
+
+If your package does not utilize the auto* tools, then you
+will need to hand craft the rules for building the library.
+
+LICENSING:
+
+This material is copyright 1993-2006 by Bruce Korb.
+You are licensed to use this under the terms of either
+the GNU Lesser General Public License (see: COPYING.lgpl), or,
+at your option, the modified Berkeley Software Distribution
+License (see:  COPYING.mbsd).  Both of these files should be
+included with this tarball.
diff --git a/sntp/libopts/autoopts.c b/sntp/libopts/autoopts.c
new file mode 100644 (file)
index 0000000..6d88967
--- /dev/null
@@ -0,0 +1,1043 @@
+
+/*
+ *  $Id: autoopts.c,v 4.14 2006/03/25 19:24:56 bkorb Exp $
+ *  Time-stamp:      "2005-10-29 13:19:36 bkorb"
+ *
+ *  This file contains all of the routines that must be linked into
+ *  an executable to use the generated option processing.  The optional
+ *  routines are in separately compiled modules so that they will not
+ *  necessarily be linked in.
+ */
+
+/*
+ *  Automated Options copyright 1992-2006 Bruce Korb
+ *
+ *  Automated Options is free software.
+ *  You may redistribute it and/or modify it under the terms of the
+ *  GNU General Public License, as published by the Free Software
+ *  Foundation; either version 2, or (at your option) any later version.
+ *
+ *  Automated Options is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with Automated Options.  See the file "COPYING".  If not,
+ *  write to:  The Free Software Foundation, Inc.,
+ *             51 Franklin Street, Fifth Floor,
+ *             Boston, MA  02110-1301, USA.
+ *
+ * As a special exception, Bruce Korb gives permission for additional
+ * uses of the text contained in his release of AutoOpts.
+ *
+ * The exception is that, if you link the AutoOpts library with other
+ * files to produce an executable, this does not by itself cause the
+ * resulting executable to be covered by the GNU General Public License.
+ * Your use of that executable is in no way restricted on account of
+ * linking the AutoOpts library code into it.
+ *
+ * This exception does not however invalidate any other reasons why
+ * the executable file might be covered by the GNU General Public License.
+ *
+ * This exception applies only to the code released by Bruce Korb under
+ * the name AutoOpts.  If you copy code from other sources under the
+ * General Public License into a copy of AutoOpts, as the General Public
+ * License permits, the exception does not apply to the code that you add
+ * in this way.  To avoid misleading anyone as to the status of such
+ * modified files, you must delete this exception notice from them.
+ *
+ * If you write modifications of your own for AutoOpts, it is your choice
+ * whether to permit this exception to apply to your modifications.
+ * If you do not wish that, delete this exception notice.
+ */
+
+#ifndef HAVE_PATHFIND
+#  include "compat/pathfind.c"
+#endif
+
+#ifndef HAVE_LIBSNPRINTFV
+# ifndef HAVE_SNPRINTF
+#   include "compat/snprintf.c"
+# endif
+
+# ifndef HAVE_STRDUP
+#   include "compat/strdup.c"
+# endif
+#endif
+
+static const char zNil[] = "";
+
+#define SKIP_RC_FILES(po) \
+    DISABLED_OPT(&((po)->pOptDesc[ (po)->specOptIdx.save_opts+1]))
+
+/* = = = START-STATIC-FORWARD = = = */
+/* static forward declarations maintained by :mkfwd */
+static tSuccess
+findOptDesc( tOptions* pOpts, tOptState* pOptState );
+
+static tSuccess
+nextOption( tOptions* pOpts, tOptState* pOptState );
+
+static tSuccess
+doPresets( tOptions* pOpts );
+
+static int
+checkConsistency( tOptions* pOpts );
+/* = = = END-STATIC-FORWARD = = = */
+
+/*
+ *  handleOption
+ *
+ *  This routine handles equivalencing, sets the option state flags and
+ *  invokes the handler procedure, if any.
+ */
+LOCAL tSuccess
+handleOption( tOptions* pOpts, tOptState* pOptState )
+{
+    /*
+     *  Save a copy of the option procedure pointer.
+     *  If this is an equivalence class option, we still want this proc.
+     */
+    tOptDesc* pOD = pOptState->pOD;
+    tOptProc* pOP = pOD->pOptProc;
+
+    pOD->pzLastArg =  pOptState->pzOptArg;
+
+    /*
+     *  IF we are presetting options, then we will ignore any un-presettable
+     *  options.  They are the ones either marked as such.
+     */
+    if (  ((pOpts->fOptSet & OPTPROC_PRESETTING) != 0)
+       && ((pOD->fOptState & OPTST_NO_INIT) != 0)
+       )
+        return PROBLEM;
+
+    /*
+     *  IF this is an equivalence class option,
+     *  THEN
+     *      Save the option value that got us to this option
+     *      entry.  (It may not be pOD->optChar[0], if this is an
+     *      equivalence entry.)
+     *      set the pointer to the equivalence class base
+     */
+    if (pOD->optEquivIndex != NO_EQUIVALENT) {
+        tOptDesc* p = pOpts->pOptDesc + pOD->optEquivIndex;
+
+        /*
+         * IF the current option state has not been defined (set on the
+         *    command line), THEN we will allow continued resetting of
+         *    the value.  Once "defined", then it must not change.
+         */
+        if ((pOD->fOptState & OPTST_DEFINED) != 0) {
+            /*
+             *  The equivalenced-to option has been found on the command
+             *  line before.  Make sure new occurrences are the same type.
+             *
+             *  IF this option has been previously equivalenced and
+             *     it was not the same equivalenced-to option,
+             *  THEN we have a usage problem.
+             */
+            if (p->optActualIndex != pOD->optIndex) {
+                fprintf( stderr, (char*)zMultiEquiv, p->pz_Name, pOD->pz_Name,
+                         (pOpts->pOptDesc + p->optActualIndex)->pz_Name);
+                return FAILURE;
+            }
+        } else {
+            /*
+             *  Set the equivalenced-to actual option index to no-equivalent
+             *  so that we set all the entries below.  This option may either
+             *  never have been selected before, or else it was selected by
+             *  some sort of "presetting" mechanism.
+             */
+            p->optActualIndex = NO_EQUIVALENT;
+        }
+
+        if (p->optActualIndex != pOD->optIndex) {
+            /*
+             *  First time through, copy over the state
+             *  and add in the equivalence flag
+             */
+            p->optActualValue = pOD->optValue;
+            p->optActualIndex = pOD->optIndex;
+            pOptState->flags |= OPTST_EQUIVALENCE;
+        }
+
+        /*
+         *  Copy the most recent option argument.  set membership state
+         *  is kept in ``p->optCookie''.  Do not overwrite.
+         */
+        p->pzLastArg = pOD->pzLastArg;
+        pOD = p;
+
+    } else {
+        pOD->optActualValue = pOD->optValue;
+        pOD->optActualIndex = pOD->optIndex;
+    }
+
+    pOD->fOptState &= OPTST_PERSISTENT;
+    pOD->fOptState |= (pOptState->flags & ~OPTST_PERSISTENT);
+
+    /*
+     *  Keep track of count only for DEFINED (command line) options.
+     *  IF we have too many, build up an error message and bail.
+     */
+    if (  (pOD->fOptState & OPTST_DEFINED)
+       && (++pOD->optOccCt > pOD->optMaxCt)  )  {
+        const char* pzEqv =
+            (pOD->optEquivIndex != NO_EQUIVALENT) ? zEquiv : zNil;
+
+        if ((pOpts->fOptSet & OPTPROC_ERRSTOP) != 0) {
+            const char* pzFmt = (pOD->optMaxCt > 1) ? zAtMost : zOnlyOne;
+            fputs( zErrOnly, stderr );
+            fprintf( stderr, pzFmt, pOD->pz_Name, pzEqv,
+                     pOD->optMaxCt );
+        }
+
+        return FAILURE;
+    }
+
+    /*
+     *  If provided a procedure to call, call it
+     */
+    if (pOP != (tpOptProc)NULL)
+        (*pOP)( pOpts, pOD );
+
+    return SUCCESS;
+}
+
+
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ *
+ *  HUNT FOR OPTIONS IN THE ARGUMENT LIST
+ *
+ *  The next four procedures are "private" to nextOption().
+ *  nextOption() uses findOptDesc() to find the next descriptor and it, in
+ *  turn, uses longOptionFind() and shortOptionFind() to actually do the hunt.
+ *
+ *  longOptionFind
+ *
+ *  Find the long option descriptor for the current option
+ */
+LOCAL tSuccess
+longOptionFind( tOptions* pOpts, char* pzOptName, tOptState* pOptState )
+{
+    ag_bool    disable  = AG_FALSE;
+    char*      pzEq     = strchr( pzOptName, '=' );
+    tOptDesc*  pOD      = pOpts->pOptDesc;
+    int        idx      = 0;
+    int        idxLim   = pOpts->optCt;
+    int        matchCt  = 0;
+    int        matchIdx = 0;
+    int        nameLen;
+
+    /*
+     *  IF the value is attached to the name,
+     *  THEN clip it off.
+     *  Either way, figure out how long our name is
+     */
+    if (pzEq != NULL) {
+        nameLen = (int)(pzEq - pzOptName);
+        *pzEq = NUL;
+    } else nameLen = strlen( pzOptName );
+
+    do  {
+        if (SKIP_OPT(pOD))
+            continue;
+
+        if (strneqvcmp( pzOptName, pOD->pz_Name, nameLen ) == 0) {
+            /*
+             *  IF we have a complete match
+             *  THEN it takes priority over any already located partial
+             */
+            if (pOD->pz_Name[ nameLen ] == NUL) {
+                matchCt  = 1;
+                matchIdx = idx;
+                break;
+            }
+        }
+
+        /*
+         *  IF       there is a disable name
+         *     *AND* no argument value has been supplied
+         *              (disabled options may have no argument)
+         *     *AND* the option name matches the disable name
+         *  THEN ...
+         */
+        else if (  (pOD->pz_DisableName != NULL)
+                && (strneqvcmp(pzOptName, pOD->pz_DisableName, nameLen) == 0)
+                )  {
+            disable  = AG_TRUE;
+
+            /*
+             *  IF we have a complete match
+             *  THEN it takes priority over any already located partial
+             */
+            if (pOD->pz_DisableName[ nameLen ] == NUL) {
+                matchCt  = 1;
+                matchIdx = idx;
+                break;
+            }
+        }
+
+        else
+            continue;
+
+        /*
+         *  We found a partial match, either regular or disabling.
+         *  Remember the index for later.
+         */
+        matchIdx = idx;
+
+        if (++matchCt > 1)
+            break;
+
+    } while (pOD++, (++idx < idxLim));
+
+    if (pzEq != NULL)
+        *(pzEq++) = '=';
+
+    /*
+     *  Make sure we either found an exact match or found only one partial
+     */
+    if (matchCt == 1) {
+        /*
+         *  IF we found a disablement name,
+         *  THEN set the bit in the callers' flag word
+         */
+        if (disable)
+            pOptState->flags |= OPTST_DISABLED;
+
+        pOptState->pOD      = pOpts->pOptDesc + matchIdx;
+        pOptState->pzOptArg = pzEq;
+        pOptState->optType  = TOPT_LONG;
+        return SUCCESS;
+    }
+
+    /*
+     *  IF there is no equal sign
+     *     *AND* we are using named arguments
+     *     *AND* there is a default named option,
+     *  THEN return that option.
+     */
+    if (  (pzEq == NULL)
+       && NAMED_OPTS(pOpts)
+       && (pOpts->specOptIdx.default_opt != NO_EQUIVALENT)) {
+        pOptState->pOD = pOpts->pOptDesc + pOpts->specOptIdx.default_opt;
+
+        pOptState->pzOptArg = pzOptName;
+        pOptState->optType  = TOPT_DEFAULT;
+        return SUCCESS;
+    }
+
+    /*
+     *  IF we are to stop on errors (the default, actually)
+     *  THEN call the usage procedure.
+     */
+    if ((pOpts->fOptSet & OPTPROC_ERRSTOP) != 0) {
+        fprintf( stderr, zIllOptStr, pOpts->pzProgPath,
+                 (matchCt == 0) ? zIllegal : zAmbiguous, pzOptName );
+        (*pOpts->pUsageProc)( pOpts, EXIT_FAILURE );
+    }
+
+    return FAILURE;
+}
+
+
+/*
+ *  shortOptionFind
+ *
+ *  Find the short option descriptor for the current option
+ */
+LOCAL tSuccess
+shortOptionFind( tOptions* pOpts, tAoUC optValue, tOptState* pOptState )
+{
+    tOptDesc*  pRes = pOpts->pOptDesc;
+    int        ct   = pOpts->optCt;
+
+    /*
+     *  Search the option list
+     */
+    for (;;) {
+        /*
+         *  IF the values match,
+         *  THEN we stop here
+         */
+        if ((! SKIP_OPT(pRes)) && (optValue == pRes->optValue)) {
+            pOptState->pOD     = pRes;
+            pOptState->optType = TOPT_SHORT;
+            return SUCCESS;
+        }
+
+        /*
+         *  Advance to next option description
+         */
+        pRes++;
+
+        /*
+         *  IF we have searched everything, ...
+         */
+        if (--ct <= 0)
+            break;
+    }
+
+    /*
+     *  IF    the character value is a digit
+     *    AND there is a special number option ("-n")
+     *  THEN the result is the "option" itself and the
+     *       option is the specially marked "number" option.
+     */
+    if (  isdigit( optValue )
+       && (pOpts->specOptIdx.number_option != NO_EQUIVALENT) ) {
+        pOptState->pOD = \
+        pRes           = pOpts->pOptDesc + pOpts->specOptIdx.number_option;
+        (pOpts->pzCurOpt)--;
+        pOptState->optType = TOPT_SHORT;
+        return SUCCESS;
+    }
+
+    /*
+     *  IF we are to stop on errors (the default, actually)
+     *  THEN call the usage procedure.
+     */
+    if ((pOpts->fOptSet & OPTPROC_ERRSTOP) != 0) {
+        fprintf( stderr, zIllOptChr, pOpts->pzProgPath, optValue );
+        (*pOpts->pUsageProc)( pOpts, EXIT_FAILURE );
+    }
+
+    return FAILURE;
+}
+
+
+/*
+ *  findOptDesc
+ *
+ *  Find the option descriptor for the current option
+ */
+static tSuccess
+findOptDesc( tOptions* pOpts, tOptState* pOptState )
+{
+    /*
+     *  IF we are continuing a short option list (e.g. -xyz...)
+     *  THEN continue a single flag option.
+     *  OTHERWISE see if there is room to advance and then do so.
+     */
+    if ((pOpts->pzCurOpt != NULL) && (*pOpts->pzCurOpt != NUL))
+        return shortOptionFind( pOpts, *pOpts->pzCurOpt, pOptState );
+
+    if (pOpts->curOptIdx >= pOpts->origArgCt)
+        return PROBLEM; /* NORMAL COMPLETION */
+
+    pOpts->pzCurOpt = pOpts->origArgVect[ pOpts->curOptIdx ];
+
+    /*
+     *  IF all arguments must be named options, ...
+     */
+    if (NAMED_OPTS(pOpts)) {
+        char* pz = pOpts->pzCurOpt;
+        pOpts->curOptIdx++;
+
+        /*
+         *  Skip over any flag/option markers.
+         *  In this mode, they are not required.
+         */
+        while (*pz == '-') pz++;
+
+        return longOptionFind( pOpts, pz, pOptState );
+    }
+
+    /*
+     *  Note the kind of flag/option marker
+     */
+    if (*((pOpts->pzCurOpt)++) != '-')
+        return PROBLEM; /* NORMAL COMPLETION - this + rest are operands */
+
+    /*
+     *  Special hack for a hyphen by itself
+     */
+    if (*(pOpts->pzCurOpt) == NUL)
+        return PROBLEM; /* NORMAL COMPLETION - this + rest are operands */
+
+    /*
+     *  The current argument is to be processed as an option argument
+     */
+    pOpts->curOptIdx++;
+
+    /*
+     *  We have an option marker.
+     *  Test the next character for long option indication
+     */
+    if (pOpts->pzCurOpt[0] == '-') {
+        if (*++(pOpts->pzCurOpt) == NUL)
+            /*
+             *  NORMAL COMPLETION - NOT this arg, but rest are operands
+             */
+            return PROBLEM;
+
+        /*
+         *  We do not allow the hyphen to be used as a flag value.
+         *  Therefore, if long options are not to be accepted, we punt.
+         */
+        if ((pOpts->fOptSet & OPTPROC_LONGOPT) == 0) {
+            fprintf( stderr, zIllOptStr, pOpts->pzProgPath,
+                     zIllegal, pOpts->pzCurOpt-2 );
+            return FAILURE;
+        }
+
+        return longOptionFind( pOpts, pOpts->pzCurOpt, pOptState );
+    }
+
+    /*
+     *  If short options are not allowed, then do long
+     *  option processing.  Otherwise the character must be a
+     *  short (i.e. single character) option.
+     */
+    if ((pOpts->fOptSet & OPTPROC_SHORTOPT) != 0)
+        return shortOptionFind( pOpts, *pOpts->pzCurOpt, pOptState );
+
+    return longOptionFind( pOpts, pOpts->pzCurOpt, pOptState );
+}
+
+
+/*
+ *  nextOption
+ *
+ *  Find the option descriptor and option argument (if any) for the
+ *  next command line argument.  DO NOT modify the descriptor.  Put
+ *  all the state in the state argument so that the option can be skipped
+ *  without consequence (side effect).
+ */
+static tSuccess
+nextOption( tOptions* pOpts, tOptState* pOptState )
+{
+    tSuccess res;
+    enum { ARG_NONE, ARG_MAY, ARG_MUST } arg_type = ARG_NONE;
+
+    res = findOptDesc( pOpts, pOptState );
+    if (! SUCCESSFUL( res ))
+        return res;
+    pOptState->flags |= (pOptState->pOD->fOptState & OPTST_PERSISTENT);
+
+    /*
+     *  Figure out what to do about option arguments.  An argument may be
+     *  required, not associated with the option, or be optional.  We detect the
+     *  latter by examining for an option marker on the next possible argument.
+     *  Disabled mode option selection also disables option arguments.
+     */
+    if ((pOptState->flags & OPTST_DISABLED) != 0)
+        arg_type = ARG_NONE;
+    else if (OPTST_GET_ARGTYPE(pOptState->flags) == OPARG_TYPE_NONE)
+        arg_type = ARG_NONE;
+    else if (pOptState->flags & OPTST_ARG_OPTIONAL)
+        arg_type = ARG_MAY;
+    else
+        arg_type = ARG_MUST;
+
+    switch (arg_type) {
+    case ARG_MUST:
+        /*
+         *  An option argument is required.  Long options can either have
+         *  a separate command line argument, or an argument attached by
+         *  the '=' character.  Figure out which.
+         */
+        switch (pOptState->optType) {
+        case TOPT_SHORT:
+            /*
+             *  See if an arg string follows the flag character
+             */
+            if (*++(pOpts->pzCurOpt) == NUL)
+                pOpts->pzCurOpt = pOpts->origArgVect[ pOpts->curOptIdx++ ];
+            pOptState->pzOptArg = pOpts->pzCurOpt;
+            break;
+
+        case TOPT_LONG:
+            /*
+             *  See if an arg string has already been assigned (glued on
+             *  with an `=' character)
+             */
+            if (pOptState->pzOptArg == NULL)
+                pOptState->pzOptArg = pOpts->origArgVect[ pOpts->curOptIdx++ ];
+            break;
+
+        default:
+#ifdef DEBUG
+            fputs( "AutoOpts lib error: option type not selected\n",
+                   stderr );
+            exit( EXIT_FAILURE );
+#endif
+
+        case TOPT_DEFAULT:
+            /*
+             *  The option was selected by default.  The current token is
+             *  the option argument.
+             */
+            break;
+        }
+
+        /*
+         *  Make sure we did not overflow the argument list.
+         */
+        if (pOpts->curOptIdx > pOpts->origArgCt) {
+            fprintf( stderr, zMisArg, pOpts->pzProgPath,
+                     pOptState->pOD->pz_Name );
+            return FAILURE;
+        }
+
+        pOpts->pzCurOpt = NULL;  /* next time advance to next arg */
+        break;
+
+    case ARG_MAY:
+        /*
+         *  An option argument is optional.
+         */
+        switch (pOptState->optType) {
+        case TOPT_SHORT:
+            if (*++pOpts->pzCurOpt != NUL)
+                pOptState->pzOptArg = pOpts->pzCurOpt;
+            else {
+                char* pzLA = pOpts->origArgVect[ pOpts->curOptIdx ];
+
+                /*
+                 *  BECAUSE it is optional, we must make sure
+                 *  we did not find another flag and that there
+                 *  is such an argument.
+                 */
+                if ((pzLA == NULL) || (*pzLA == '-'))
+                    pOptState->pzOptArg = NULL;
+                else {
+                    pOpts->curOptIdx++; /* argument found */
+                    pOptState->pzOptArg = pzLA;
+                }
+            }
+            break;
+
+        case TOPT_LONG:
+            /*
+             *  Look for an argument if we don't already have one (glued on
+             *  with a `=' character) *AND* we are not in named argument mode
+             */
+            if (  (pOptState->pzOptArg == NULL)
+               && (! NAMED_OPTS(pOpts))) {
+                char* pzLA = pOpts->origArgVect[ pOpts->curOptIdx ];
+
+                /*
+                 *  BECAUSE it is optional, we must make sure
+                 *  we did not find another flag and that there
+                 *  is such an argument.
+                 */
+                if ((pzLA == NULL) || (*pzLA == '-'))
+                    pOptState->pzOptArg = NULL;
+                else {
+                    pOpts->curOptIdx++; /* argument found */
+                    pOptState->pzOptArg = pzLA;
+                }
+            }
+            break;
+
+        default:
+        case TOPT_DEFAULT:
+            fputs( "AutoOpts lib error: defaulted to option with optional arg\n",
+                   stderr );
+            exit( EXIT_FAILURE );
+        }
+
+        /*
+         *  After an option with an optional argument, we will
+         *  *always* start with the next option because if there
+         *  were any characters following the option name/flag,
+         *  they would be interpreted as the argument.
+         */
+        pOpts->pzCurOpt = NULL;
+        break;
+
+    default: /* CANNOT */
+        /*
+         *  No option argument.  Make sure next time around we find
+         *  the correct option flag character for short options
+         */
+        if (pOptState->optType == TOPT_SHORT)
+            (pOpts->pzCurOpt)++;
+
+        /*
+         *  It is a long option.  Make sure there was no ``=xxx'' argument
+         */
+        else if (pOptState->pzOptArg != NULL) {
+            fprintf( stderr, zNoArg, pOpts->pzProgPath,
+                     pOptState->pOD->pz_Name );
+            return FAILURE;
+        }
+
+        /*
+         *  It is a long option.  Advance to next command line argument.
+         */
+        else
+            pOpts->pzCurOpt = NULL;
+    }
+
+    return SUCCESS;
+}
+
+
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ *
+ *  DO PRESETS
+ *
+ *  The next several routines do the immediate action pass on the command
+ *  line options, then the environment variables, then the config files in
+ *  reverse order.  Once done with that, the order is reversed and all
+ *  the config files and environment variables are processed again, this
+ *  time only processing the non-immediate action options.  doPresets()
+ *  will then return for optionProcess() to do the final pass on the command
+ *  line arguments.
+ */
+
+/*
+ *  doImmediateOpts - scan the command line for immediate action options
+ */
+LOCAL tSuccess
+doImmediateOpts( tOptions* pOpts )
+{
+    pOpts->curOptIdx = 1;     /* start by skipping program name */
+    pOpts->pzCurOpt  = NULL;
+
+    /*
+     *  Examine all the options from the start.  We process any options that
+     *  are marked for immediate processing.
+     */
+    for (;;) {
+        tOptState optState = OPTSTATE_INITIALIZER(PRESET);
+
+        switch (nextOption( pOpts, &optState )) {
+        case FAILURE: goto optionsDone;
+        case PROBLEM: return SUCCESS; /* no more args */
+        case SUCCESS: break;
+        }
+
+        /*
+         *  IF this *is* an immediate-attribute option, then do it.
+         */
+        if (! DO_IMMEDIATELY(optState.flags))
+            continue;
+
+        if (! SUCCESSFUL( handleOption( pOpts, &optState )))
+            break;
+    } optionsDone:;
+
+    if ((pOpts->fOptSet & OPTPROC_ERRSTOP) != 0)
+        (*pOpts->pUsageProc)( pOpts, EXIT_FAILURE );
+    return FAILURE;
+}
+
+
+LOCAL tSuccess
+doRegularOpts( tOptions* pOpts )
+{
+    /*
+     *  Now, process all the options from our current position onward.
+     *  (This allows interspersed options and arguments for the few
+     *  non-standard programs that require it.)
+     */
+    for (;;) {
+        tOptState optState = OPTSTATE_INITIALIZER(DEFINED);
+
+        switch (nextOption( pOpts, &optState )) {
+        case FAILURE: goto optionsDone;
+        case PROBLEM: return SUCCESS; /* no more args */
+        case SUCCESS: break;
+        }
+
+        /*
+         *  IF this is not being processed normally (i.e. is immediate action)
+         *  THEN skip it (unless we are supposed to do it a second time).
+         */
+        if (! DO_NORMALLY(optState.flags)) {
+            if (! DO_SECOND_TIME(optState.flags))
+                continue;
+            optState.pOD->optOccCt--; /* don't count last time */
+        }
+
+        if (! SUCCESSFUL( handleOption( pOpts, &optState )))
+            break;
+    } optionsDone:;
+    if ((pOpts->fOptSet & OPTPROC_ERRSTOP) != 0)
+        (*pOpts->pUsageProc)( pOpts, EXIT_FAILURE );
+    return FAILURE;
+}
+
+
+/*
+ *  doPresets - check for preset values from a config file or the envrionment
+ */
+static tSuccess
+doPresets( tOptions* pOpts )
+{
+    if (! SUCCESSFUL( doImmediateOpts( pOpts )))
+        return FAILURE;
+
+    /*
+     *  Until we return from this procedure, disable non-presettable opts
+     */
+    pOpts->fOptSet |= OPTPROC_PRESETTING;
+    /*
+     *  IF there are no config files,
+     *  THEN do any environment presets and leave.
+     */
+    if (  (pOpts->papzHomeList == NULL)
+       || SKIP_RC_FILES(pOpts) )  {
+        doEnvPresets( pOpts, ENV_ALL );
+    }
+    else {
+        doEnvPresets( pOpts, ENV_IMM );
+        internalFileLoad( pOpts );
+        doEnvPresets( pOpts, ENV_NON_IMM );
+    }
+    pOpts->fOptSet &= ~OPTPROC_PRESETTING;
+
+    return SUCCESS;
+}
+
+
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ *
+ *  VERIFY OPTION CONSISTENCY
+ *
+ *  Make sure that the argument list passes our consistency tests.
+ */
+static int
+checkConsistency( tOptions* pOpts )
+{
+    int        errCt = 0;
+    tOptDesc*  pOD   = pOpts->pOptDesc;
+    int        oCt   = pOpts->presetOptCt;
+
+    /*
+     *  FOR each of "oCt" options, ...
+     */
+    for (;;) {
+        const int*  pMust = pOD->pOptMust;
+        const int*  pCant = pOD->pOptCant;
+
+        /*
+         *  IF the current option was provided on the command line
+         *  THEN ensure that any "MUST" requirements are not
+         *       "DEFAULT" (unspecified) *AND* ensure that any
+         *       "CANT" options have not been SET or DEFINED.
+         */
+        if (SELECTED_OPT(pOD)) {
+            if (pMust != NULL) for (;;) {
+                tOptDesc*  p = pOpts->pOptDesc + *(pMust++);
+                if (UNUSED_OPT(p)) {
+                    const tOptDesc* pN = pOpts->pOptDesc + pMust[-1];
+                    errCt++;
+                    fprintf( stderr, zReqFmt, pOD->pz_Name, pN->pz_Name );
+                }
+
+                if (*pMust == NO_EQUIVALENT)
+                    break;
+            }
+
+            if (pCant != NULL) for (;;) {
+                tOptDesc*  p = pOpts->pOptDesc + *(pCant++);
+                if (SELECTED_OPT(p)) {
+                    const tOptDesc* pN = pOpts->pOptDesc + pCant[-1];
+                    errCt++;
+                    fprintf( stderr, zCantFmt, pOD->pz_Name, pN->pz_Name );
+                }
+
+                if (*pCant == NO_EQUIVALENT)
+                    break;
+            }
+        }
+
+        /*
+         *  IF       this option is not equivalenced to another,
+         *        OR it is equivalenced to itself (is the equiv. root)
+         *  THEN we need to make sure it occurs often enough.
+         */
+        if (  (pOD->optEquivIndex == NO_EQUIVALENT)
+           || (pOD->optEquivIndex == pOD->optIndex) )   do {
+            /*
+             *  IF the occurrence counts have been satisfied,
+             *  THEN there is no problem.
+             */
+            if (pOD->optOccCt >= pOD->optMinCt)
+                break;
+
+            /*
+             *  IF MUST_SET means SET and PRESET are okay,
+             *  so min occurrence count doesn't count
+             */
+            if (  (pOD->fOptState & OPTST_MUST_SET)
+               && (pOD->fOptState & (OPTST_PRESET | OPTST_SET)) )
+                break;
+
+            errCt++;
+            if (pOD->optMinCt > 1)
+                fprintf( stderr, zNotEnough, pOD->pz_Name, pOD->optMinCt );
+            else fprintf( stderr, zNeedOne, pOD->pz_Name );
+           } while (0);
+
+        if (--oCt <= 0)
+            break;
+        pOD++;
+    }
+
+    /*
+     *  IF we are stopping on errors, check to see if any remaining
+     *  arguments are required to be there or prohibited from being there.
+     */
+    if ((pOpts->fOptSet & OPTPROC_ERRSTOP) != 0) {
+
+        /*
+         *  Check for prohibition
+         */
+        if ((pOpts->fOptSet & OPTPROC_NO_ARGS) != 0) {
+            if (pOpts->origArgCt > pOpts->curOptIdx) {
+                fprintf( stderr, zNoArgs, pOpts->pzProgName );
+                ++errCt;
+            }
+        }
+
+        /*
+         *  ELSE not prohibited, check for being required
+         */
+        else if ((pOpts->fOptSet & OPTPROC_ARGS_REQ) != 0) {
+            if (pOpts->origArgCt <= pOpts->curOptIdx) {
+                fprintf( stderr, zArgsMust, pOpts->pzProgName );
+                ++errCt;
+            }
+        }
+    }
+
+    return errCt;
+}
+
+
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ *
+ *  THESE ROUTINES ARE CALLABLE FROM THE GENERATED OPTION PROCESSING CODE
+ */
+/*=--subblock=arg=arg_type,arg_name,arg_desc =*/
+/*=*
+ * library:  opts
+ * header:   your-opts.h
+ *
+ * lib_description:
+ *
+ *  These are the routines that libopts users may call directly from their
+ *  code.  There are several other routines that can be called by code
+ *  generated by the libopts option templates, but they are not to be
+ *  called from any other user code.  The @file{options.h} header is
+ *  fairly clear about this, too.
+=*/
+
+/*=export_func optionProcess
+ *
+ * what: this is the main option processing routine
+ *
+ * arg:  + tOptions* + pOpts + program options descriptor +
+ * arg:  + int       + argc  + program arg count  +
+ * arg:  + char**    + argv  + program arg vector +
+ *
+ * ret_type:  int
+ * ret_desc:  the count of the arguments processed
+ *
+ * doc:
+ *
+ * This is the main entry point for processing options.  It is intended
+ * that this procedure be called once at the beginning of the execution of
+ * a program.  Depending on options selected earlier, it is sometimes
+ * necessary to stop and restart option processing, or to select completely
+ * different sets of options.  This can be done easily, but you generally
+ * do not want to do this.
+ *
+ * The number of arguments processed always includes the program name.
+ * If one of the arguments is "--", then it is counted and the processing
+ * stops.  If an error was encountered and errors are to be tolerated, then
+ * the returned value is the index of the argument causing the error.
+ * A hyphen by itself ("-") will also cause processing to stop and will
+ * @emph{not} be counted among the processed arguments.  A hyphen by itself
+ * is treated as an operand.  Encountering an operand stops option
+ * processing.
+ *
+ * err:  Errors will cause diagnostics to be printed.  @code{exit(3)} may
+ *       or may not be called.  It depends upon whether or not the options
+ *       were generated with the "allow-errors" attribute, or if the
+ *       ERRSKIP_OPTERR or ERRSTOP_OPTERR macros were invoked.
+=*/
+int
+optionProcess(
+    tOptions*  pOpts,
+    int        argCt,
+    char**     argVect )
+{
+    if (! SUCCESSFUL( validateOptionsStruct( pOpts, argVect[0] )))
+        exit( EXIT_FAILURE );
+
+    /*
+     *  Establish the real program name, the program full path,
+     *  and do all the presetting the first time thru only.
+     */
+    if ((pOpts->fOptSet & OPTPROC_INITDONE) == 0) {
+        pOpts->origArgCt   = argCt;
+        pOpts->origArgVect = argVect;
+        pOpts->fOptSet    |= OPTPROC_INITDONE;
+
+        if (! SUCCESSFUL( doPresets( pOpts )))
+            return 0;
+
+        if ((pOpts->fOptSet & OPTPROC_REORDER) != 0)
+            optionSort( pOpts );
+
+        pOpts->curOptIdx   = 1;
+        pOpts->pzCurOpt    = NULL;
+    }
+
+    /*
+     *  IF we are (re)starting,
+     *  THEN reset option location
+     */
+    else if (pOpts->curOptIdx <= 0) {
+        pOpts->curOptIdx = 1;
+        pOpts->pzCurOpt  = NULL;
+    }
+
+    if (! SUCCESSFUL( doRegularOpts( pOpts )))
+        return pOpts->origArgCt;
+
+    /*
+     *  IF    there were no errors
+     *    AND we have RC/INI files
+     *    AND there is a request to save the files
+     *  THEN do that now before testing for conflicts.
+     *       (conflicts are ignored in preset options)
+     */
+    if (pOpts->specOptIdx.save_opts != 0) {
+        tOptDesc*  pOD = pOpts->pOptDesc + pOpts->specOptIdx.save_opts;
+
+        if (SELECTED_OPT( pOD )) {
+            optionSaveFile( pOpts );
+            exit( EXIT_SUCCESS );
+        }
+    }
+
+    /*
+     *  IF we are checking for errors,
+     *  THEN look for too few occurrences of required options
+     */
+    if ((pOpts->fOptSet & OPTPROC_ERRSTOP) != 0) {
+        if (checkConsistency( pOpts ) != 0)
+            (*pOpts->pUsageProc)( pOpts, EXIT_FAILURE );
+    }
+
+    return pOpts->curOptIdx;
+}
+
+/*
+ * Local Variables:
+ * mode: C
+ * c-file-style: "stroustrup"
+ * tab-width: 4
+ * indent-tabs-mode: nil
+ * End:
+ * end of autoopts/autoopts.c */
diff --git a/sntp/libopts/autoopts.h b/sntp/libopts/autoopts.h
new file mode 100644 (file)
index 0000000..af01f07
--- /dev/null
@@ -0,0 +1,321 @@
+
+/*
+ *  Time-stamp:      "2005-10-29 15:06:44 bkorb"
+ *
+ *  autoopts.h  $Id: autoopts.h,v 4.17 2006/03/25 19:24:56 bkorb Exp $
+ *  Time-stamp:      "2005-02-14 05:59:50 bkorb"
+ *
+ *  This file defines all the global structures and special values
+ *  used in the automated option processing library.
+ */
+
+/*
+ *  Automated Options copyright 1992-2006 Bruce Korb
+ *
+ *  Automated Options is free software.
+ *  You may redistribute it and/or modify it under the terms of the
+ *  GNU General Public License, as published by the Free Software
+ *  Foundation; either version 2, or (at your option) any later version.
+ *
+ *  Automated Options is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with Automated Options.  See the file "COPYING".  If not,
+ *  write to:  The Free Software Foundation, Inc.,
+ *             51 Franklin Street, Fifth Floor,
+ *             Boston, MA  02110-1301, USA.
+ *
+ * As a special exception, Bruce Korb gives permission for additional
+ * uses of the text contained in his release of AutoOpts.
+ *
+ * The exception is that, if you link the AutoOpts library with other
+ * files to produce an executable, this does not by itself cause the
+ * resulting executable to be covered by the GNU General Public License.
+ * Your use of that executable is in no way restricted on account of
+ * linking the AutoOpts library code into it.
+ *
+ * This exception does not however invalidate any other reasons why
+ * the executable file might be covered by the GNU General Public License.
+ *
+ * This exception applies only to the code released by Bruce Korb under
+ * the name AutoOpts.  If you copy code from other sources under the
+ * General Public License into a copy of AutoOpts, as the General Public
+ * License permits, the exception does not apply to the code that you add
+ * in this way.  To avoid misleading anyone as to the status of such
+ * modified files, you must delete this exception notice from them.
+ *
+ * If you write modifications of your own for AutoOpts, it is your choice
+ * whether to permit this exception to apply to your modifications.
+ * If you do not wish that, delete this exception notice.
+ */
+
+#ifndef AUTOGEN_AUTOOPTS_H
+#define AUTOGEN_AUTOOPTS_H
+
+#include "compat/compat.h"
+
+#define AO_NAME_LIMIT    127
+#define AO_NAME_SIZE     (AO_NAME_LIMIT + 1)
+
+#ifndef MAXPATHLEN
+#  ifdef PATH_MAX
+#    define MAXPATHLEN   PATH_MAX
+#  else
+#    define MAXPATHLEN   4096
+#  endif
+#else
+#  if defined(PATH_MAX) && (PATH_MAX > MAXPATHLEN)
+#     undef  MAXPATHLEN
+#     define MAXPATHLEN  PATH_MAX
+#  endif
+#endif
+
+#undef  EXPORT
+#define EXPORT
+
+/*
+ *  Convert the number to a list usable in a printf call
+ */
+#define NUM_TO_VER(n)       ((n) >> 12), ((n) >> 7) & 0x001F, (n) & 0x007F
+
+#define NAMED_OPTS(po) \
+        (((po)->fOptSet & (OPTPROC_SHORTOPT | OPTPROC_LONGOPT)) == 0)
+
+#define SKIP_OPT(p)  (((p)->fOptState & (OPTST_DOCUMENT|OPTST_OMITTED)) != 0)
+
+typedef int tDirection;
+#define DIRECTION_PRESET  -1
+#define DIRECTION_PROCESS  1
+#define DIRECTION_CALLED   0
+
+#define PROCESSING(d)     ((d)>0)
+#define PRESETTING(d)     ((d)<0)
+
+#define ISNAMECHAR( c )    (isalnum(c) || ((c) == '_') || ((c) == '-'))
+
+/*
+ *  Procedure success codes
+ *
+ *  USAGE:  define procedures to return "tSuccess".  Test their results
+ *          with the SUCCEEDED, FAILED and HADGLITCH macros.
+ */
+#define SUCCESS  ((tSuccess) 0)
+#define FAILURE  ((tSuccess)-1)
+#define PROBLEM  ((tSuccess) 1)
+
+typedef int tSuccess;
+
+#define SUCCEEDED( p )     ((p) == SUCCESS)
+#define SUCCESSFUL( p )    SUCCEEDED( p )
+#define FAILED( p )        ((p) <  SUCCESS)
+#define HADGLITCH( p )     ((p) >  SUCCESS)
+
+/*
+ *  The pager state is used by optionPagedUsage() procedure.
+ *  When it runs, it sets itself up to be called again on exit.
+ *  If, however, a routine needs a child process to do some work
+ *  before it is done, then 'pagerState' must be set to
+ *  'PAGER_STATE_CHILD' so that optionPagedUsage() will not try
+ *  to run the pager program before its time.
+ */
+typedef enum {
+    PAGER_STATE_INITIAL,
+    PAGER_STATE_READY,
+    PAGER_STATE_CHILD
+} tePagerState;
+
+extern tePagerState pagerState;
+
+typedef enum {
+    ENV_ALL,
+    ENV_IMM,
+    ENV_NON_IMM
+} teEnvPresetType;
+
+typedef enum {
+    TOPT_UNDEFINED = 0,
+    TOPT_SHORT,
+    TOPT_LONG,
+    TOPT_DEFAULT
+} teOptType;
+
+typedef struct {
+    tOptDesc*  pOD;
+    tCC*       pzOptArg;
+    tAoUL      flags;
+    teOptType  optType;
+} tOptState;
+#define OPTSTATE_INITIALIZER(st) \
+    { NULL, NULL, OPTST_ ## st, TOPT_UNDEFINED }
+
+#define TEXTTO_TABLE \
+        _TT_( LONGUSAGE ) \
+        _TT_( USAGE ) \
+        _TT_( VERSION )
+#define _TT_(n) \
+        TT_ ## n ,
+
+typedef enum { TEXTTO_TABLE COUNT_TT } teTextTo;
+
+#undef _TT_
+
+typedef struct {
+    tCC*    pzStr;
+    tCC*    pzReq;
+    tCC*    pzNum;
+    tCC*    pzKey;
+    tCC*    pzKeyL;
+    tCC*    pzBool;
+    tCC*    pzNest;
+    tCC*    pzOpt;
+    tCC*    pzNo;
+    tCC*    pzBrk;
+    tCC*    pzNoF;
+    tCC*    pzSpc;
+    tCC*    pzOptFmt;
+} arg_types_t;
+
+#  define AGALOC( c, w )        malloc( c )
+#  define AGREALOC( p, c, w )   realloc( p, c )
+#  define AGFREE( p )           free( p )
+#  define AGDUPSTR( p, s, w )   p = strdup( s )
+#  define TAGMEM( m, t )
+
+#ifdef AUTOGEN_BUILD
+#  include <snprintfv/printf.h>
+#endif /* AUTOGEN_BUILD */
+
+/*
+ *  DO option handling?
+ *
+ *  Options are examined at two times:  at immediate handling time and at
+ *  normal handling time.  If an option is disabled, the timing may be
+ *  different from the handling of the undisabled option.  The OPTST_DIABLED
+ *  bit indicates the state of the currently discovered option.
+ *  So, here's how it works:
+ *
+ *  A) handling at "immediate" time, either 1 or 2:
+ *
+ *  1.  OPTST_DISABLED is not set:
+ *      IMM           must be set
+ *      DISABLE_IMM   don't care
+ *      TWICE         don't care
+ *      DISABLE_TWICE don't care
+ *      0 -and-  1 x x x
+ *
+ *  2.  OPTST_DISABLED is set:
+ *      IMM           don't care
+ *      DISABLE_IMM   must be set
+ *      TWICE         don't care
+ *      DISABLE_TWICE don't care
+ *      1 -and-  x 1 x x
+ */
+#define DO_IMMEDIATELY(_flg) \
+    (  (((_flg) & (OPTST_DISABLED|OPTST_IMM)) == OPTST_IMM) \
+    || (   ((_flg) & (OPTST_DISABLED|OPTST_DISABLE_IMM))    \
+        == (OPTST_DISABLED|OPTST_DISABLE_IMM)  ))
+
+/*  B) handling at "regular" time because it was not immediate
+ *
+ *  1.  OPTST_DISABLED is not set:
+ *      IMM           must *NOT* be set
+ *      DISABLE_IMM   don't care
+ *      TWICE         don't care
+ *      DISABLE_TWICE don't care
+ *      0 -and-  0 x x x
+ *
+ *  2.  OPTST_DISABLED is set:
+ *      IMM           don't care
+ *      DISABLE_IMM   don't care
+ *      TWICE         must be set
+ *      DISABLE_TWICE don't care
+ *      1 -and-  x x 1 x
+ */
+#define DO_NORMALLY(_flg) ( \
+       (((_flg) & (OPTST_DISABLED|OPTST_IMM))            == 0)  \
+    || (((_flg) & (OPTST_DISABLED|OPTST_DISABLE_IMM))    ==     \
+                  OPTST_DISABLED)  )
+
+/*  C)  handling at "regular" time because it is to be handled twice.
+ *      The immediate bit was already tested and found to be set:
+ *
+ *  3.  OPTST_DISABLED is not set:
+ *      IMM           is set (but don't care)
+ *      DISABLE_IMM   don't care
+ *      TWICE         must be set
+ *      DISABLE_TWICE don't care
+ *      0 -and-  ? x 1 x
+ *
+ *  4.  OPTST_DISABLED is set:
+ *      IMM           don't care
+ *      DISABLE_IMM   is set (but don't care)
+ *      TWICE         don't care
+ *      DISABLE_TWICE must be set
+ *      1 -and-  x ? x 1
+ */
+#define DO_SECOND_TIME(_flg) ( \
+       (((_flg) & (OPTST_DISABLED|OPTST_TWICE))          ==     \
+                  OPTST_TWICE)                                  \
+    || (((_flg) & (OPTST_DISABLED|OPTST_DISABLE_TWICE))  ==     \
+                  (OPTST_DISABLED|OPTST_DISABLE_TWICE)  ))
+
+/*
+ *  text_mmap structure.  Only active on platforms with mmap(2).
+ */
+#ifdef HAVE_SYS_MMAN_H
+#  include <sys/mman.h>
+#else
+#  ifndef  PROT_READ
+#   define PROT_READ    0x01
+#  endif
+#  ifndef  PROT_WRITE
+#   define PROT_WRITE   0x02
+#  endif
+#  ifndef  MAP_SHARED
+#   define MAP_SHARED   0x01
+#  endif
+#  ifndef  MAP_PRIVATE
+#   define MAP_PRIVATE  0x02
+#  endif
+#endif
+
+#ifndef MAP_FAILED
+#  define  MAP_FAILED   ((void*)-1)
+#endif
+
+#ifndef  _SC_PAGESIZE
+# ifdef  _SC_PAGE_SIZE
+#  define _SC_PAGESIZE _SC_PAGE_SIZE
+# endif
+#endif
+
+/*
+ *  Define and initialize all the user visible strings.
+ *  We do not do translations.  If translations are to be done, then
+ *  the client will provide a callback for that purpose.
+ */
+#undef DO_TRANSLATIONS
+#include "autoopts/usage-txt.h"
+
+/*
+ *  File pointer for usage output
+ */
+extern FILE* option_usage_fp;
+
+extern tOptProc optionPrintVersion, optionPagedUsage, optionLoadOpt;
+
+#define LOCAL static
+#include "proto.h"
+
+#endif /* AUTOGEN_AUTOOPTS_H */
+/*
+ * Local Variables:
+ * mode: C
+ * c-file-style: "stroustrup"
+ * tab-width: 4
+ * indent-tabs-mode: nil
+ * End:
+ * end of autoopts/autoopts.h */
diff --git a/sntp/libopts/autoopts/options.h b/sntp/libopts/autoopts/options.h
new file mode 100644 (file)
index 0000000..150af3f
--- /dev/null
@@ -0,0 +1,908 @@
+/*   -*- buffer-read-only: t -*- vi: set ro:
+ *  
+ *  DO NOT EDIT THIS FILE   (options.h)
+ *  
+ *  It has been AutoGen-ed  Sunday April  9, 2006 at 11:49:19 AM PDT
+ *  From the definitions    funcs.def
+ *  and the template file   options_h
+ *
+ *  This file defines all the global structures and special values
+ *  used in the automated option processing library.
+ *
+ *  Automated Options copyright 1992-Y Bruce Korb
+ *
+ *  AutoOpts is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public
+ *  License as published by the Free Software Foundation; either
+ *  version 2.1 of the License, or (at your option) any later version.
+ *  
+ *  AutoOpts is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *  
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with AutoOpts.  If not, write to:
+ *     The Free Software Foundation, Inc.,
+ *     51 Franklin Street, Fifth Floor
+ *     Boston, MA  02110-1301, USA.
+ */
+#ifndef AUTOOPTS_OPTIONS_H_GUARD
+#define AUTOOPTS_OPTIONS_H_GUARD
+#include <sys/types.h>
+
+#if defined(HAVE_STDINT_H)
+# include <stdint.h>
+#elif defined(HAVE_INTTYPES_H)
+# include <inttypes.h>
+#endif /* HAVE_STDINT/INTTYPES_H */
+
+#if defined(HAVE_LIMITS_H)
+# include <limits.h>
+#elif defined(HAVE_SYS_LIMITS_H)
+# include <sys/limits.h>
+#endif /* HAVE_LIMITS/SYS_LIMITS_H */
+
+/*
+ *  PUBLIC DEFINES
+ *
+ *  The following defines may be used in applications that need to test the
+ *  state of an option.  To test against these masks and values, a pointer
+ *  to an option descriptor must be obtained.  There are two ways:
+ *
+ *  1. inside an option processing procedure, it is the second argument,
+ *  conventionally "tOptDesc* pOD".
+ *
+ *  2.  Outside of an option procedure (or to reference a different option
+ *  descriptor), use either "&DESC( opt_name )" or "&pfx_DESC( opt_name )".
+ *
+ *  See the relevant generated header file to determine which and what
+ *  values for "opt_name" are available.
+ */
+
+typedef enum {
+    OPARG_TYPE_NONE             = 0,
+    OPARG_TYPE_STRING           = 1,    /* default type/ vanilla string      */
+    OPARG_TYPE_ENUMERATION      = 2,    /* opt arg is an enum (keyword list) */
+    OPARG_TYPE_BOOLEAN          = 3,    /* opt arg is boolean-valued         */
+    OPARG_TYPE_MEMBERSHIP       = 4,    /* opt arg sets set membership bits  */
+    OPARG_TYPE_NUMERIC          = 5,    /* opt arg has numeric value         */
+    OPARG_TYPE_HIERARCHY        = 6     /* option arg is hierarchical value  */
+} teOptArgType;
+
+typedef struct optionValue {
+    teOptArgType        valType;
+    char*               pzName;
+    union {
+        char            strVal[1];      /* OPARG_TYPE_STRING      */
+        int             enumVal;        /* OPARG_TYPE_ENUMERATION */
+        int             boolVal;        /* OPARG_TYPE_BOOLEAN     */
+        long            setVal;         /* OPARG_TYPE_MEMBERSHIP  */
+        long            longVal;        /* OPARG_TYPE_NUMERIC     */
+        void*           nestVal;        /* OPARG_TYPE_HIERARCHY   */
+    } v;
+} tOptionValue;
+
+#define OPTST_SET_ARGTYPE(n) ((n) << 12)
+#define OPTST_GET_ARGTYPE(f) (((f) & OPTST_ARG_TYPE_MASK) >> 12)
+
+/*
+ *  Bits in the fOptState option descriptor field.
+ */
+#define OPTST_INIT           0x0000000  /* Initial compiled value            */
+#define OPTST_SET            0x0000001  /* Set via the "SET_OPT()" macro     */
+#define OPTST_PRESET         0x0000002  /* Set via an RC/INI file            */
+#define OPTST_DEFINED        0x0000004  /* Set via a command line option     */
+
+#define OPTST_SET_MASK       0x0000007  /* mask of flags that show set state */
+
+#define OPTST_EQUIVALENCE    0x0000010  /* selected by equiv'ed option       */
+#define OPTST_DISABLED       0x0000020  /* option is in disabled state       */
+
+#define OPTST_NO_INIT        0x0000100  /* option cannot be preset           */
+#define OPTST_NUMBER_OPT     0x0000200  /* opt value (flag) is any digit     */
+#define OPTST_STACKED        0x0000400  /* opt uses optionStackArg procedure */
+#define OPTST_INITENABLED    0x0000800  /* option defaults to enabled        */
+#define OPTST_ARG_TYPE_MASK  0x000F000  /* bits used to specify opt arg type */
+#define OPTST_ARG_OPTIONAL   0x0010000  /* the option argument not required  */
+#define OPTST_IMM            0x0020000  /* process option on first pass      */
+#define OPTST_DISABLE_IMM    0x0040000  /* process disablement on first pass */
+#define OPTST_OMITTED        0x0080000  /* compiled out of program           */
+#define OPTST_MUST_SET       0x0100000  /* must be set or pre-set            */
+#define OPTST_DOCUMENT       0x0200000  /* opt is for documentation only     */
+#define OPTST_TWICE          0x0400000  /* process option twice - imm + reg  */
+#define OPTST_DISABLE_TWICE  0x0800000  /* process disabled option twice     */
+
+#define OPTST_PERSISTENT     0xFFFFF00  /* mask of flags that do not change  */
+
+#define SELECTED_OPT( pod )  ( (pod)->fOptState & (OPTST_SET | OPTST_DEFINED))
+#define UNUSED_OPT(   pod )  (((pod)->fOptState & OPTST_SET_MASK) == 0)
+#define DISABLED_OPT( pod )  ( (pod)->fOptState & OPTST_DISABLED)
+#define OPTION_STATE( pod )  ((pod)->fOptState)
+
+/*
+ *  PRIVATE INTERFACES
+ *
+ *  The following values are used in the generated code to communicate
+ *  with the option library procedures.  They are not for public use
+ *  and may be subject to change.
+ */
+
+/*
+ *  Define any special processing flags
+ */
+#define OPTPROC_NONE        0x000000
+#define OPTPROC_LONGOPT     0x000001 /* Process long style options      */
+#define OPTPROC_SHORTOPT    0x000002 /* Process short style "flags"     */
+#define OPTPROC_ERRSTOP     0x000004 /* Stop on argument errors         */
+#define OPTPROC_DISABLEDOPT 0x000008 /* Current option is disabled      */
+#define OPTPROC_NO_REQ_OPT  0x000010 /* no options are required         */
+#define OPTPROC_NUM_OPT     0x000020 /* there is a number option        */
+#define OPTPROC_INITDONE    0x000040 /* have initializations been done? */
+#define OPTPROC_NEGATIONS   0x000080 /* any negation options?           */
+#define OPTPROC_ENVIRON     0x000100 /* check environment?              */
+#define OPTPROC_NO_ARGS     0x000200 /* Disallow remaining arguments    */
+#define OPTPROC_ARGS_REQ    0x000400 /* Require arguments after options */
+#define OPTPROC_REORDER     0x000800 /* reorder arguments after options */
+#define OPTPROC_GNUUSAGE    0x001000 /* emit usage in GNU style         */
+#define OPTPROC_TRANSLATE   0x002000 /* Translate strings in tOptions   */
+#define OPTPROC_HAS_IMMED   0x004000 /* program defines immed options   */
+#define OPTPROC_PRESETTING  0x800000 /* opt processing in preset state  */
+
+#define STMTS(s)  do { s; } while (0)
+
+/*
+ *  The following must be #defined instead of typedef-ed
+ *  because "static const" cannot both be applied to a type,
+ *  tho each individually can...so they all are
+ */
+#define tSCC        static const char
+#define tCC         const char
+#define tAoSC       static char
+#define tAoUC       unsigned char
+#define tAoUI       unsigned int
+#define tAoUL       unsigned long
+#define tAoUS       unsigned short
+
+/*
+ *  It is so disgusting that there must be so many ways
+ *  of specifying TRUE and FALSE.
+ */
+typedef enum { AG_FALSE = 0, AG_TRUE } ag_bool;
+
+/*
+ *  Define a structure that describes each option and
+ *  a pointer to the procedure that handles it.
+ *  The argument is the count of this flag previously seen.
+ */
+typedef struct options  tOptions;
+typedef struct optDesc  tOptDesc;
+typedef struct optNames tOptNames;
+
+/*
+ *  The option procedures do the special processing for each
+ *  option flag that needs it.
+ */
+typedef void (tOptProc)( tOptions*  pOpts, tOptDesc* pOptDesc );
+typedef tOptProc*  tpOptProc;
+
+/*
+ *  The usage procedure will never return.  It calls "exit(2)"
+ *  with the "exitCode" argument passed to it.
+ */
+typedef void (tUsageProc)( tOptions* pOpts, int exitCode );
+typedef tUsageProc* tpUsageProc;
+
+/*
+ *  Special definitions.  "NOLIMIT" is the 'max' value to use when
+ *  a flag may appear multiple times without limit.  "NO_EQUIVALENT"
+ *  is an illegal value for 'optIndex' (option description index).
+ */
+#define NOLIMIT          USHRT_MAX
+#define OPTION_LIMIT     SHRT_MAX
+#define NO_EQUIVALENT    (OPTION_LIMIT+1)
+
+/*
+ *  Special values for optValue.  It must not be generatable from the
+ *  computation "optIndex +96".  Since "optIndex" is limited to 100, ...
+ */
+#define NUMBER_OPTION    '#'
+
+typedef struct argList tArgList;
+#define MIN_ARG_ALLOC_CT   6
+#define INCR_ARG_ALLOC_CT  8
+struct argList {
+    int             useCt;
+    int             allocCt;
+    tCC*            apzArgs[ MIN_ARG_ALLOC_CT ];
+};
+
+/*
+ *  Descriptor structure for each option.
+ *  Only the fields marked "PUBLIC" are for public use.
+ */
+struct optDesc {
+    tAoUS           optIndex;         /* PUBLIC */
+    tAoUS           optValue;         /* PUBLIC */
+    tAoUS           optActualIndex;   /* PUBLIC */
+    tAoUS           optActualValue;   /* PUBLIC */
+
+    tAoUS           optEquivIndex;    /* PUBLIC */
+    tAoUS           optMinCt;
+    tAoUS           optMaxCt;
+    tAoUS           optOccCt;         /* PUBLIC */
+
+    tAoUI           fOptState;        /* PUBLIC */
+    tAoUI           reserved;
+    tCC*            pzLastArg;        /* PUBLIC */
+    void*           optCookie;        /* PUBLIC */
+
+    const int *     pOptMust;
+    const int *     pOptCant;
+    tpOptProc       pOptProc;
+    const char*     pzText;
+
+    const char*     pz_NAME;
+    const char*     pz_Name;
+    const char*     pz_DisableName;
+    const char*     pz_DisablePfx;
+};
+
+/*
+ *  Some options need special processing, so we store their
+ *  indexes in a known place:
+ */
+typedef struct optSpecIndex tOptSpecIndex;
+struct optSpecIndex {
+    tAoUS           more_help;
+    tAoUS           save_opts;
+    tAoUS           number_option;
+    tAoUS           default_opt;
+};
+
+#define  OPTIONS_STRUCT_VERSION  110594
+#define  OPTIONS_VERSION_STRING  "27:1:2"
+#define  OPTIONS_MINIMUM_VERSION 102400
+#define  OPTIONS_MIN_VER_STRING  "25:0:0"
+
+/*
+ *  The procedure generated for translating option text
+ */
+typedef void (tOptionXlateProc)(void);
+
+struct options {
+    const int         structVersion;
+    int               origArgCt;
+    char**            origArgVect;
+    unsigned int      fOptSet;
+    unsigned int      curOptIdx;
+    char*             pzCurOpt;
+
+    const char*       pzProgPath;
+    const char*       pzProgName;
+    const char*       pzPROGNAME;
+    const char*       pzRcName;
+    const char*       pzCopyright;
+    const char*       pzCopyNotice;
+    const char*       pzFullVersion;
+    const char**      papzHomeList;
+    const char*       pzUsageTitle;
+    const char*       pzExplain;
+    const char*       pzDetail;
+    tOptDesc*         pOptDesc;
+    const char*       pzBugAddr;
+
+    void*             pExtensions;
+    void*             pSavedState;
+
+    tpUsageProc       pUsageProc;
+    tOptionXlateProc* pTransProc;
+
+    tOptSpecIndex     specOptIdx;
+    const int         optCt;
+    const int         presetOptCt;
+};
+
+/*
+ *  "token list" structure returned by "string_tokenize()"
+ */
+typedef struct {
+    unsigned long   tkn_ct;
+    unsigned char*  tkn_list[1];
+} token_list_t;
+
+/*
+ *  Hide the interface - it pollutes a POSIX claim, but leave it for
+ *  anyone #include-ing this header
+ */
+#define strneqvcmp      option_strneqvcmp
+#define streqvcmp       option_streqvcmp
+#define streqvmap       option_streqvmap
+#define strequate       option_strequate
+#define strtransform    option_strtransform
+
+/*
+ *  This is an output only structure used by text_mmap and text_munmap.
+ *  Clients must not alter the contents and must provide it to both
+ *  the text_mmap and text_munmap procedures.  BE ADVISED: if you are
+ *  mapping the file with PROT_WRITE the NUL byte at the end MIGHT NOT
+ *  BE WRITABLE.  In any event, that byte is not be written back
+ *  to the source file.  ALSO: if "txt_data" is valid and "txt_errno"
+ *  is not zero, then there *may* not be a terminating NUL.
+ */
+typedef struct {
+    void*       txt_data;      /* text file data   */
+    size_t      txt_size;      /* actual file size */
+    size_t      txt_full_size; /* mmaped mem size  */
+    int         txt_fd;        /* file descriptor  */
+    int         txt_zero_fd;   /* fd for /dev/zero */
+    int         txt_errno;     /* warning code     */
+    int         txt_prot;      /* "prot" flags     */
+    int         txt_flags;     /* mapping type     */
+    int         txt_alloc;     /* if we malloced memory */
+} tmap_info_t;
+
+#define TEXT_MMAP_FAILED_ADDR(a)  ((void*)(a) ==  (void*)MAP_FAILED)
+
+/*
+ *  When loading a line (or block) of text as an option, the value can
+ *  be processed in any of several modes:
+ *
+ *  @table @samp
+ *  @item keep
+ *  Every part of the value between the delimiters is saved.
+ *
+ *  @item uncooked
+ *  Even if the value begins with quote characters, do not do quote processing.
+ *
+ *  @item cooked
+ *  If the value looks like a quoted string, then process it.
+ *  Double quoted strings are processed the way strings are in "C" programs,
+ *  except they are treated as regular characters if the following character
+ *  is not a well-established escape sequence.
+ *  Single quoted strings (quoted with apostrophies) are handled the way
+ *  strings are handled in shell scripts, *except* that backslash escapes
+ *  are honored before backslash escapes and apostrophies.
+ *  @end table
+ */
+typedef enum {
+    OPTION_LOAD_COOKED,
+    OPTION_LOAD_UNCOOKED,
+    OPTION_LOAD_KEEP
+} tOptionLoadMode;
+
+#ifdef  __cplusplus
+extern "C" {
+#define CPLUSPLUS_CLOSER }
+#else
+#define CPLUSPLUS_CLOSER
+#endif
+
+/*
+ *  The following routines may be coded into AutoOpts client code:
+ */
+
+/* From: tokenize.c line 115
+ *
+ * ao_string_tokenize - tokenize an input string
+ *
+ * Arguments:
+ *   string       string to be tokenized
+ *
+ * Returns: token_list_t* - pointer to a structure that lists each token
+ *
+ *  This function will convert one input string into a list of strings.
+ *  The list of strings is derived by separating the input based on
+ *  white space separation.  However, if the input contains either single
+ *  or double quote characters, then the text after that character up to
+ *  a matching quote will become the string in the list.
+ *  
+ *  The returned pointer should be deallocated with @code{free(3C)} when
+ *  are done using the data.  The data are placed in a single block of
+ *  allocated memory.  Do not deallocate individual token/strings.
+ *  
+ *  The structure pointed to will contain at least these two fields:
+ *  @table @samp
+ *  @item tkn_ct
+ *  The number of tokens found in the input string.
+ *  @item tok_list
+ *  An array of @code{tkn_ct + 1} pointers to substring tokens, with
+ *  the last pointer set to NULL.
+ *  @end table
+ *  
+ *  There are two types of quoted strings: single quoted (@code{'}) and
+ *  double quoted (@code{"}).  Singly quoted strings are fairly raw in that
+ *  escape characters (@code{\\}) are simply another character, except when
+ *  preceding the following characters:
+ *  @example
+ *  @code{\\}  double backslashes reduce to one
+ *  @code{'}   incorporates the single quote into the string
+ *  @code{\n}  suppresses both the backslash and newline character
+ *  @end example
+ *  
+ *  Double quote strings are formed according to the rules of string
+ *  constants in ANSI-C programs.
+ */
+extern token_list_t* ao_string_tokenize( const char* );
+
+
+/* From: configfile.c line 113
+ *
+ * configFileLoad - parse a configuration file
+ *
+ * Arguments:
+ *   pzFile       the file to load
+ *
+ * Returns: const tOptionValue* - An allocated, compound value structure
+ *
+ *  This routine will load a named configuration file and parse the
+ *  text as a hierarchically valued option.  The option descriptor
+ *  created from an option definition file is not used via this interface.
+ *  The returned value is "named" with the input file name and is of
+ *  type "@code{OPARG_TYPE_HIERARCHY}".  It may be used in calls to
+ *  @code{optionGetValue()}, @code{optionNextValue()} and
+ *  @code{optionUnloadNested()}.
+ */
+extern const tOptionValue* configFileLoad( const char* );
+
+
+/* From: configfile.c line 869
+ *
+ * optionFileLoad - Load the locatable config files, in order
+ *
+ * Arguments:
+ *   pOpts        program options descriptor
+ *   pzProg       program name
+ *
+ * Returns: int - 0 -> SUCCESS, -1 -> FAILURE
+ *
+ *  This function looks in all the specified directories for a configuration
+ *  file ("rc" file or "ini" file) and processes any found twice.  The first
+ *  time through, they are processed in reverse order (last file first).  At
+ *  that time, only "immediate action" configurables are processed.  For
+ *  example, if the last named file specifies not processing any more
+ *  configuration files, then no more configuration files will be processed.
+ *  Such an option in the @strong{first} named directory will have no effect.
+ *  
+ *  Once the immediate action configurables have been handled, then the
+ *  directories are handled in normal, forward order.  In that way, later
+ *  config files can override the settings of earlier config files.
+ *  
+ *  See the AutoOpts documentation for a thorough discussion of the
+ *  config file format.
+ *  
+ *  Configuration files not found or not decipherable are simply ignored.
+ */
+extern int optionFileLoad( tOptions*, const char* );
+
+
+/* From: configfile.c line 241
+ *
+ * optionFindNextValue - find a hierarcicaly valued option instance
+ *
+ * Arguments:
+ *   pOptDesc     an option with a nested arg type
+ *   pPrevVal     the last entry
+ *   name         name of value to find
+ *   value        the matching value
+ *
+ * Returns: const tOptionValue* - a compound value structure
+ *
+ *  This routine will find the next entry in a nested value option or
+ *  configurable.  It will search through the list and return the next entry
+ *  that matches the criteria.
+ */
+extern const tOptionValue* optionFindNextValue( const tOptDesc*, const tOptionValue*, const char*, const char* );
+
+
+/* From: configfile.c line 166
+ *
+ * optionFindValue - find a hierarcicaly valued option instance
+ *
+ * Arguments:
+ *   pOptDesc     an option with a nested arg type
+ *   name         name of value to find
+ *   value        the matching value
+ *
+ * Returns: const tOptionValue* - a compound value structure
+ *
+ *  This routine will find an entry in a nested value option or configurable.
+ *  It will search through the list and return a matching entry.
+ */
+extern const tOptionValue* optionFindValue( const tOptDesc*, const char*, const char* );
+
+
+/* From: restore.c line 157
+ *
+ * optionFree - free allocated option processing memory
+ *
+ * Arguments:
+ *   pOpts        program options descriptor
+ *
+ *  AutoOpts sometimes allocates memory and puts pointers to it in the
+ *  option state structures.  This routine deallocates all such memory.
+ */
+extern void optionFree( tOptions* );
+
+
+/* From: configfile.c line 310
+ *
+ * optionGetValue - get a specific value from a hierarcical list
+ *
+ * Arguments:
+ *   pOptValue    a hierarchcal value
+ *   valueName    name of value to get
+ *
+ * Returns: const tOptionValue* - a compound value structure
+ *
+ *  This routine will find an entry in a nested value option or configurable.
+ *  If "valueName" is NULL, then the first entry is returned.  Otherwise,
+ *  the first entry with a name that exactly matches the argument will be
+ *  returned.
+ */
+extern const tOptionValue* optionGetValue( const tOptionValue*, const char* );
+
+
+/* From: load.c line 477
+ *
+ * optionLoadLine - process a string for an option name and value
+ *
+ * Arguments:
+ *   pOpts        program options descriptor
+ *   pzLine       NUL-terminated text
+ *
+ *  This is a client program callable routine for setting options from, for
+ *  example, the contents of a file that they read in.  Only one option may
+ *  appear in the text.  It will be treated as a normal (non-preset) option.
+ *  
+ *  When passed a pointer to the option struct and a string, it will find
+ *  the option named by the first token on the string and set the option
+ *  argument to the remainder of the string.  The caller must NUL terminate
+ *  the string.  Any embedded new lines will be included in the option
+ *  argument.  If the input looks like one or more quoted strings, then the
+ *  input will be "cooked".  The "cooking" is identical to the string
+ *  formation used in AutoGen definition files (@pxref{basic expression}),
+ *  except that you may not use backquotes.
+ */
+extern void optionLoadLine( tOptions*, const char* );
+
+
+/* From: configfile.c line 369
+ *
+ * optionNextValue - get the next value from a hierarchical list
+ *
+ * Arguments:
+ *   pOptValue    a hierarchcal list value
+ *   pOldValue    a value from this list
+ *
+ * Returns: const tOptionValue* - a compound value structure
+ *
+ *  This routine will return the next entry after the entry passed in.  At the
+ *  end of the list, NULL will be returned.  If the entry is not found on the
+ *  list, NULL will be returned and "@var{errno}" will be set to EINVAL.
+ *  The "@var{pOldValue}" must have been gotten from a prior call to this
+ *  routine or to "@code{opitonGetValue()}".
+ */
+extern const tOptionValue* optionNextValue( const tOptionValue*, const tOptionValue* );
+
+
+/* From: usage.c line 128
+ *
+ * optionOnlyUsage - Print usage text for just the options
+ *
+ * Arguments:
+ *   pOpts        program options descriptor
+ *   ex_code      exit code for calling exit(3)
+ *
+ *  This routine will print only the usage for each option.
+ *  This function may be used when the emitted usage must incorporate
+ *  information not available to AutoOpts.
+ */
+extern void optionOnlyUsage( tOptions*, int );
+
+
+/* From: autoopts.c line 934
+ *
+ * optionProcess - this is the main option processing routine
+ *
+ * Arguments:
+ *   pOpts        program options descriptor
+ *   argc         program arg count
+ *   argv         program arg vector
+ *
+ * Returns: int - the count of the arguments processed
+ *
+ *  This is the main entry point for processing options.  It is intended
+ *  that this procedure be called once at the beginning of the execution of
+ *  a program.  Depending on options selected earlier, it is sometimes
+ *  necessary to stop and restart option processing, or to select completely
+ *  different sets of options.  This can be done easily, but you generally
+ *  do not want to do this.
+ *  
+ *  The number of arguments processed always includes the program name.
+ *  If one of the arguments is "--", then it is counted and the processing
+ *  stops.  If an error was encountered and errors are to be tolerated, then
+ *  the returned value is the index of the argument causing the error.
+ *  A hyphen by itself ("-") will also cause processing to stop and will
+ *  @emph{not} be counted among the processed arguments.  A hyphen by itself
+ *  is treated as an operand.  Encountering an operand stops option
+ *  processing.
+ */
+extern int optionProcess( tOptions*, int, char** );
+
+
+/* From: restore.c line 121
+ *
+ * optionRestore - restore option state from memory copy
+ *
+ * Arguments:
+ *   pOpts        program options descriptor
+ *
+ *  Copy back the option state from saved memory.
+ *  The allocated memory is left intact, so this routine can be
+ *  called repeatedly without having to call optionSaveState again.
+ *  If you are restoring a state that was saved before the first call
+ *  to optionProcess(3AO), then you may change the contents of the
+ *  argc/argv parameters to optionProcess.
+ */
+extern void optionRestore( tOptions* );
+
+
+/* From: save.c line 325
+ *
+ * optionSaveFile - saves the option state to a file
+ *
+ * Arguments:
+ *   pOpts        program options descriptor
+ *
+ *  This routine will save the state of option processing to a file.  The name
+ *  of that file can be specified with the argument to the @code{--save-opts}
+ *  option, or by appending the @code{rcfile} attribute to the last
+ *  @code{homerc} attribute.  If no @code{rcfile} attribute was specified, it
+ *  will default to @code{.@i{programname}rc}.  If you wish to specify another
+ *  file, you should invoke the @code{SET_OPT_SAVE_OPTS( @i{filename} )} macro.
+ */
+extern void optionSaveFile( tOptions* );
+
+
+/* From: restore.c line 54
+ *
+ * optionSaveState - saves the option state to memory
+ *
+ * Arguments:
+ *   pOpts        program options descriptor
+ *
+ *  This routine will allocate enough memory to save the current
+ *  option processing state.  If this routine has been called before,
+ *  that memory will be reused.  You may only save one copy of the
+ *  option state.  This routine may be called before optionProcess(3AO).
+ *  If you do call it before the first call to optionProcess, then
+ *  you may also change the contents of argc/argv after you call
+ *  optionRestore(3AO)
+ */
+extern void optionSaveState( tOptions* );
+
+
+/* From: nested.c line 527
+ *
+ * optionUnloadNested - Deallocate the memory for a nested value
+ *
+ * Arguments:
+ *   pOptVal      the hierarchical value
+ *
+ *  A nested value needs to be deallocated.  The pointer passed in should
+ *  have been gotten from a call to @code{configFileLoad()} (See
+ *  @pxref{libopts-configFileLoad}).
+ */
+extern void optionUnloadNested( const tOptionValue* );
+
+
+/* From: version.c line 58
+ *
+ * optionVersion - return the compiled AutoOpts version number
+ *
+ * Returns: const char* - the version string in constant memory
+ *
+ *  Returns the full version string compiled into the library.
+ *  The returned string cannot be modified.
+ */
+extern const char* optionVersion( void );
+
+
+/* From: ../compat/pathfind.c line 24
+ *
+ * pathfind - fild a file in a list of directories
+ *
+ * Arguments:
+ *   path         colon separated list of search directories
+ *   file         the name of the file to look for
+ *   mode         the mode bits that must be set to match
+ *
+ * Returns: char* - the path to the located file
+ *
+ * the pathfind function is available only if HAVE_PATHFIND is not defined
+ *
+ *  pathfind looks for a a file with name "FILE" and "MODE" access
+ *  along colon delimited "PATH", and returns the full pathname as a
+ *  string, or NULL if not found.  If "FILE" contains a slash, then
+ *  it is treated as a relative or absolute path and "PATH" is ignored.
+ *  
+ *  @strong{NOTE}: this function is compiled into @file{libopts} only if
+ *  it is not natively supplied.
+ *  
+ *  The "MODE" argument is a string of option letters chosen from the
+ *  list below:
+ *  @example
+ *  Letter    Meaning
+ *  r         readable
+ *  w         writable
+ *  x         executable
+ *  f         normal file       (NOT IMPLEMENTED)
+ *  b         block special     (NOT IMPLEMENTED)
+ *  c         character special (NOT IMPLEMENTED)
+ *  d         directory         (NOT IMPLEMENTED)
+ *  p         FIFO (pipe)       (NOT IMPLEMENTED)
+ *  u         set user ID bit   (NOT IMPLEMENTED)
+ *  g         set group ID bit  (NOT IMPLEMENTED)
+ *  k         sticky bit        (NOT IMPLEMENTED)
+ *  s         size nonzero      (NOT IMPLEMENTED)
+ *  @end example
+ */
+#ifndef HAVE_PATHFIND
+extern char* pathfind( const char*, const char*, const char* );
+#endif /* HAVE_PATHFIND */
+
+
+/* From: streqvcmp.c line 233
+ *
+ * strequate - map a list of characters to the same value
+ *
+ * Arguments:
+ *   ch_list      characters to equivalence
+ *
+ *  Each character in the input string get mapped to the first character
+ *  in the string.
+ *  This function name is mapped to option_strequate so as to not conflict
+ *  with the POSIX name space.
+ */
+extern void strequate( const char* );
+
+
+/* From: streqvcmp.c line 143
+ *
+ * streqvcmp - compare two strings with an equivalence mapping
+ *
+ * Arguments:
+ *   str1         first string
+ *   str2         second string
+ *
+ * Returns: int - the difference between two differing characters
+ *
+ *  Using a character mapping, two strings are compared for "equivalence".
+ *  Each input character is mapped to a comparison character and the
+ *  mapped-to characters are compared for the two NUL terminated input strings.
+ *  This function name is mapped to option_streqvcmp so as to not conflict
+ *  with the POSIX name space.
+ */
+extern int streqvcmp( const char*, const char* );
+
+
+/* From: streqvcmp.c line 180
+ *
+ * streqvmap - Set the character mappings for the streqv functions
+ *
+ * Arguments:
+ *   From         Input character
+ *   To           Mapped-to character
+ *   ct           compare length
+ *
+ *  Set the character mapping.  If the count (@code{ct}) is set to zero, then
+ *  the map is cleared by setting all entries in the map to their index
+ *  value.  Otherwise, the "@code{From}" character is mapped to the "@code{To}"
+ *  character.  If @code{ct} is greater than 1, then @code{From} and @code{To}
+ *  are incremented and the process repeated until @code{ct} entries have been
+ *  set. For example,
+ *  @example
+ *  streqvmap( 'a', 'A', 26 );
+ *  @end example
+ *  @noindent
+ *  will alter the mapping so that all English lower case letters
+ *  will map to upper case.
+ *  
+ *  This function name is mapped to option_streqvmap so as to not conflict
+ *  with the POSIX name space.
+ */
+extern void streqvmap( char, char, int );
+
+
+/* From: streqvcmp.c line 102
+ *
+ * strneqvcmp - compare two strings with an equivalence mapping
+ *
+ * Arguments:
+ *   str1         first string
+ *   str2         second string
+ *   ct           compare length
+ *
+ * Returns: int - the difference between two differing characters
+ *
+ *  Using a character mapping, two strings are compared for "equivalence".
+ *  Each input character is mapped to a comparison character and the
+ *  mapped-to characters are compared for the two NUL terminated input strings.
+ *  The comparison is limited to @code{ct} bytes.
+ *  This function name is mapped to option_strneqvcmp so as to not conflict
+ *  with the POSIX name space.
+ */
+extern int strneqvcmp( const char*, const char*, int );
+
+
+/* From: streqvcmp.c line 259
+ *
+ * strtransform - convert a string into its mapped-to value
+ *
+ * Arguments:
+ *   dest         output string
+ *   src          input string
+ *
+ *  Each character in the input string is mapped and the mapped-to
+ *  character is put into the output.
+ *  This function name is mapped to option_strtransform so as to not conflict
+ *  with the POSIX name space.
+ */
+extern void strtransform( char*, const char* );
+
+/*  AutoOpts PRIVATE FUNCTIONS:  */
+tOptProc optionStackArg, optionUnstackArg, optionBooleanVal, optionNumericVal;
+
+extern char* ao_string_cook( char*, int* );
+
+extern unsigned int ao_string_cook_escape_char( const char*, char*, char );
+
+extern void genshelloptUsage( tOptions*, int );
+
+extern void optionBooleanVal( tOptions*, tOptDesc* );
+
+extern char* optionEnumerationVal( tOptions*, tOptDesc*, const char**, unsigned int );
+
+extern const char* optionKeywordName( tOptDesc*, unsigned int );
+
+extern tOptionValue* optionLoadNested( const char*, const char*, size_t, tOptionLoadMode );
+
+extern void optionLoadOpt( tOptions*, tOptDesc* );
+
+extern ag_bool optionMakePath( char*, int, const char*, const char* );
+
+extern void optionNestedVal( tOptions*, tOptDesc* );
+
+extern void optionNumericVal( tOptions*, tOptDesc* );
+
+extern void optionPagedUsage( tOptions*, tOptDesc* );
+
+extern void optionParseShell( tOptions* );
+
+extern void optionPrintVersion( tOptions*, tOptDesc* );
+
+extern void optionPutShell( tOptions* );
+
+extern void optionSetMembers( tOptions*, tOptDesc*, const char**, unsigned int );
+
+extern void optionStackArg( tOptions*, tOptDesc* );
+
+extern void optionUnstackArg( tOptions*, tOptDesc* );
+
+extern void optionUsage( tOptions*, int );
+
+extern void optionVersionStderr( tOptions*, tOptDesc* );
+
+extern void* text_mmap( const char*, int, int, tmap_info_t* );
+
+extern int text_munmap( tmap_info_t* );
+
+CPLUSPLUS_CLOSER
+#endif /* AUTOOPTS_OPTIONS_H_GUARD */
+/*
+ * Local Variables:
+ * c-file-style: "stroustrup"
+ * indent-tabs-mode: nil
+ * End:
+ * options.h ends here */
diff --git a/sntp/libopts/autoopts/usage-txt.h b/sntp/libopts/autoopts/usage-txt.h
new file mode 100644 (file)
index 0000000..9953efa
--- /dev/null
@@ -0,0 +1,479 @@
+/*   -*- buffer-read-only: t -*- vi: set ro:
+ *  
+ *  DO NOT EDIT THIS FILE   (usage-txt.h)
+ *  
+ *  It has been AutoGen-ed  Sunday April  9, 2006 at 11:49:19 AM PDT
+ *  From the definitions    usage-txt.def
+ *  and the template file   usage-txt.tpl
+ *
+ *  This file handles all the bookkeeping required for tracking all the little
+ *  tiny strings used by the AutoOpts library.  There are 114
+ *  of them.  This is not versioned because it is entirely internal to the
+ *  library and accessed by client code only in a very well-controlled way:
+ *  they may substitute translated strings using a procedure that steps through
+ *  all the string pointers.
+ *
+ *  AutoOpts is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public
+ *  License as published by the Free Software Foundation; either
+ *  version 2.1 of the License, or (at your option) any later version.
+ *  
+ *  AutoOpts is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *  
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with AutoOpts.  If not, write to:
+ *     The Free Software Foundation, Inc.,
+ *     51 Franklin Street, Fifth Floor
+ *     Boston, MA  02110-1301, USA.
+ */
+#ifndef AUTOOPTS_USAGE_TXT_H_GUARD
+#define AUTOOPTS_USAGE_TXT_H_GUARD
+
+#undef  cch_t
+#define cch_t const char
+
+/*
+ *  One structure to hold all the pointers to all the stringlets.
+ */
+typedef struct {
+  int       field_ct;
+  char*     utpz_GnuBoolArg;
+  char*     utpz_GnuKeyArg;
+  char*     utpz_GnuKeyLArg;
+  char*     utpz_GnuNumArg;
+  char*     utpz_GnuStrArg;
+  cch_t*    apz_str[ 109 ];
+} usage_text_t;
+
+/*
+ *  Declare the global structure with all the pointers to translated
+ *  strings.  This is then used by the usage generation procedure.
+ */
+extern usage_text_t option_usage_text;
+
+#if defined(AUTOOPTS_INTERNAL) /* DEFINE ALL THE STRINGS = = = = = */
+/*
+ *  Provide a mapping from a short name to fields in this structure.
+ */
+#define zAO_Bad               (option_usage_text.apz_str[0])
+#define zAO_Big               (option_usage_text.apz_str[1])
+#define zAO_Err               (option_usage_text.apz_str[2])
+#define zAO_Sml               (option_usage_text.apz_str[3])
+#define zAll                  (option_usage_text.apz_str[4])
+#define zAlt                  (option_usage_text.apz_str[5])
+#define zAmbigKey             (option_usage_text.apz_str[6])
+#define zAmbiguous            (option_usage_text.apz_str[7])
+#define zArgsMust             (option_usage_text.apz_str[8])
+#define zAtMost               (option_usage_text.apz_str[9])
+#define zAuto                 (option_usage_text.apz_str[10])
+#define zBadPipe              (option_usage_text.apz_str[11])
+#define zBadVerArg            (option_usage_text.apz_str[12])
+#define zCantFmt              (option_usage_text.apz_str[13])
+#define zCantSave             (option_usage_text.apz_str[14])
+#define zDefaultOpt           (option_usage_text.apz_str[15])
+#define zDis                  (option_usage_text.apz_str[16])
+#define zEnab                 (option_usage_text.apz_str[17])
+#define zEquiv                (option_usage_text.apz_str[18])
+#define zErrOnly              (option_usage_text.apz_str[19])
+#define zExamineFmt           (option_usage_text.apz_str[20])
+#define zFiveSpaces           (option_usage_text.apz_str[21])
+#define zFlagOkay             (option_usage_text.apz_str[22])
+#define zFmtFmt               (option_usage_text.apz_str[23])
+#define zForkFail             (option_usage_text.apz_str[24])
+#define zFSErrOptLoad         (option_usage_text.apz_str[25])
+#define zFSErrReadFile        (option_usage_text.apz_str[26])
+#define zGenshell             (option_usage_text.apz_str[27])
+#define zGnuBoolArg           (option_usage_text.utpz_GnuBoolArg)
+#define zGnuBreak             (option_usage_text.apz_str[28])
+#define zGnuKeyArg            (option_usage_text.utpz_GnuKeyArg)
+#define zGnuKeyLArg           (option_usage_text.utpz_GnuKeyLArg)
+#define zGnuNestArg           (option_usage_text.apz_str[29])
+#define zGnuNumArg            (option_usage_text.utpz_GnuNumArg)
+#define zGnuOptArg            (option_usage_text.apz_str[30])
+#define zGnuOptFmt            (option_usage_text.apz_str[31])
+#define zGnuStrArg            (option_usage_text.utpz_GnuStrArg)
+#define zHomePath             (option_usage_text.apz_str[32])
+#define zIllOptChr            (option_usage_text.apz_str[33])
+#define zIllOptStr            (option_usage_text.apz_str[34])
+#define zIllegal              (option_usage_text.apz_str[35])
+#define zInvalOptDesc         (option_usage_text.apz_str[36])
+#define zKeyWords             (option_usage_text.apz_str[37])
+#define zLoadCooked           (option_usage_text.apz_str[38])
+#define zLoadKeep             (option_usage_text.apz_str[39])
+#define zLoadType             (option_usage_text.apz_str[40])
+#define zLoadUncooked         (option_usage_text.apz_str[41])
+#define zLtypeInteger         (option_usage_text.apz_str[42])
+#define zLtypeNest            (option_usage_text.apz_str[43])
+#define zLtypeString          (option_usage_text.apz_str[44])
+#define zLtypeBool            (option_usage_text.apz_str[45])
+#define zLtypeKeyword         (option_usage_text.apz_str[46])
+#define zLtypeSetMembership   (option_usage_text.apz_str[47])
+#define zMembers              (option_usage_text.apz_str[48])
+#define zMisArg               (option_usage_text.apz_str[49])
+#define zMultiEquiv           (option_usage_text.apz_str[50])
+#define zMust                 (option_usage_text.apz_str[51])
+#define zNeedOne              (option_usage_text.apz_str[52])
+#define zNoArg                (option_usage_text.apz_str[53])
+#define zNoArgs               (option_usage_text.apz_str[54])
+#define zNoCreat              (option_usage_text.apz_str[55])
+#define zNoFlags              (option_usage_text.apz_str[56])
+#define zNoKey                (option_usage_text.apz_str[57])
+#define zNoLim                (option_usage_text.apz_str[58])
+#define zNoPreset             (option_usage_text.apz_str[59])
+#define zNoRq_NoShrtTtl       (option_usage_text.apz_str[60])
+#define zNoRq_ShrtTtl         (option_usage_text.apz_str[61])
+#define zNoStat               (option_usage_text.apz_str[62])
+#define zNoState              (option_usage_text.apz_str[63])
+#define zNone                 (option_usage_text.apz_str[64])
+#define zNotDef               (option_usage_text.apz_str[65])
+#define zNotEnough            (option_usage_text.apz_str[66])
+#define zNotFile              (option_usage_text.apz_str[67])
+#define zNotNumber            (option_usage_text.apz_str[68])
+#define zNrmOptFmt            (option_usage_text.apz_str[69])
+#define zNumberOpt            (option_usage_text.apz_str[70])
+#define zOneSpace             (option_usage_text.apz_str[71])
+#define zOnlyOne              (option_usage_text.apz_str[72])
+#define zOptsOnly             (option_usage_text.apz_str[73])
+#define zPathFmt              (option_usage_text.apz_str[74])
+#define zPlsSendBugs          (option_usage_text.apz_str[75])
+#define zPreset               (option_usage_text.apz_str[76])
+#define zPresetFile           (option_usage_text.apz_str[77])
+#define zPresetIntro          (option_usage_text.apz_str[78])
+#define zProg                 (option_usage_text.apz_str[79])
+#define zProhib               (option_usage_text.apz_str[80])
+#define zReorder              (option_usage_text.apz_str[81])
+#define zReqFmt               (option_usage_text.apz_str[82])
+#define zReqOptFmt            (option_usage_text.apz_str[83])
+#define zReqThese             (option_usage_text.apz_str[84])
+#define zReq_NoShrtTtl        (option_usage_text.apz_str[85])
+#define zReq_ShrtTtl          (option_usage_text.apz_str[86])
+#define zSepChars             (option_usage_text.apz_str[87])
+#define zSetMembers           (option_usage_text.apz_str[88])
+#define zSetMemberSettings    (option_usage_text.apz_str[89])
+#define zShrtGnuOptFmt        (option_usage_text.apz_str[90])
+#define zSixSpaces            (option_usage_text.apz_str[91])
+#define zStdBoolArg           (option_usage_text.apz_str[92])
+#define zStdBreak             (option_usage_text.apz_str[93])
+#define zStdKeyArg            (option_usage_text.apz_str[94])
+#define zStdKeyLArg           (option_usage_text.apz_str[95])
+#define zStdNestArg           (option_usage_text.apz_str[96])
+#define zStdNoArg             (option_usage_text.apz_str[97])
+#define zStdNumArg            (option_usage_text.apz_str[98])
+#define zStdOptArg            (option_usage_text.apz_str[99])
+#define zStdReqArg            (option_usage_text.apz_str[100])
+#define zStdStrArg            (option_usage_text.apz_str[101])
+#define zTabHyp               (option_usage_text.apz_str[102])
+#define zTabHypAnd            (option_usage_text.apz_str[103])
+#define zTabout               (option_usage_text.apz_str[104])
+#define zThreeSpaces          (option_usage_text.apz_str[105])
+#define zTwoSpaces            (option_usage_text.apz_str[106])
+#define zUpTo                 (option_usage_text.apz_str[107])
+#define zValidKeys            (option_usage_text.apz_str[108])
+
+  /*
+   *  First, set up the strings.  Some of these are writable.  These are all in
+   *  English.  This gets compiled into libopts and is distributed here so that
+   *  xgettext (or equivalents) can extract these strings for translation.
+   */
+
+  static cch_t   eng_zAO_Bad[] =
+       "AutoOpts function called without option descriptor\n";
+  static cch_t   eng_zAO_Big[] =
+       "\tThis exceeds the compiled library version:  ";
+  static cch_t   eng_zAO_Err[] =
+       "Automated Options Processing Error!\n\
+\t%s called AutoOpts function with structure version %d:%d:%d.\n";
+  static cch_t   eng_zAO_Sml[] =
+       "\tThis is less than the minimum library version:  ";
+  static cch_t   eng_zAll[] =
+       "all";
+  static cch_t   eng_zAlt[] =
+       "\t\t\t\t- an alternate for %s\n";
+  static cch_t   eng_zAmbigKey[] =
+       "%s error:  the keyword `%s' is ambiguous\n";
+  static cch_t   eng_zAmbiguous[] =
+       "ambiguous";
+  static cch_t   eng_zArgsMust[] =
+       "%s: Command line arguments required\n";
+  static cch_t   eng_zAtMost[] =
+       "%4$d %1$s%s options allowed\n";
+  static cch_t   eng_zAuto[] =
+       "version and help options:";
+  static cch_t   eng_zBadPipe[] =
+       "Error %d (%s) from the pipe(2) syscall\n";
+  static cch_t   eng_zBadVerArg[] =
+       "ERROR: version option argument '%c' invalid.  Use:\n\
+\t'v' - version only\n\
+\t'c' - version and copyright\n\
+\t'n' - version and copyright notice\n";
+  static cch_t   eng_zCantFmt[] =
+       "ERROR:  %s option conflicts with the %s option\n";
+  static cch_t   eng_zCantSave[] =
+       "%s(optionSaveState): error: cannot allocate %d bytes\n";
+  static cch_t   eng_zDefaultOpt[] =
+       "\t\t\t\t- default option for unnamed options\n";
+  static cch_t   eng_zDis[] =
+       "\t\t\t\t- disabled as --%s\n";
+  static cch_t   eng_zEnab[] =
+       "\t\t\t\t- enabled by default\n";
+  static cch_t   eng_zEquiv[] =
+       "-equivalence";
+  static cch_t   eng_zErrOnly[] =
+       "ERROR:  only ";
+  static cch_t   eng_zExamineFmt[] =
+       " - examining environment variables named %s_*\n";
+  static cch_t   eng_zFiveSpaces[] =
+       "     ";
+  static cch_t   eng_zFlagOkay[] =
+       "Options are specified by doubled hyphens and their name\n\
+or by a single hyphen and the flag character.\n";
+  static cch_t   eng_zFmtFmt[] =
+       "%%-%ds %%s\n";
+  static cch_t   eng_zForkFail[] =
+       "fs error %d (%s) on fork - cannot obtain %s usage\n";
+  static cch_t   eng_zFSErrOptLoad[] =
+       "File error %d (%s) opening %s for loading options\n";
+  static cch_t   eng_zFSErrReadFile[] =
+       "fs error %d (%s) reading file %s\n";
+  static cch_t   eng_zGenshell[] =
+       "\n\
+= = = = = = = =\n\n\
+This incarnation of genshell will produce\n\
+a shell script to parse the options for %s:\n\n";
+  static char    eng_zGnuBoolArg[] =
+       "=T/F";
+  static cch_t   eng_zGnuBreak[] =
+       "\n\
+%s\n\n";
+  static char    eng_zGnuKeyArg[] =
+       "=KWd";
+  static char    eng_zGnuKeyLArg[] =
+       "=Mbr";
+  static cch_t   eng_zGnuNestArg[] =
+       "=Cplx";
+  static char    eng_zGnuNumArg[] =
+       "=num";
+  static cch_t   eng_zGnuOptArg[] =
+       "[=arg]";
+  static cch_t   eng_zGnuOptFmt[] =
+       "--%2$s%1$s";
+  static char    eng_zGnuStrArg[] =
+       "=str";
+  static cch_t   eng_zHomePath[] =
+       " - reading file /... %s's exe directory .../%s \n";
+  static cch_t   eng_zIllOptChr[] =
+       "%s: illegal option -- %c\n";
+  static cch_t   eng_zIllOptStr[] =
+       "%s: %s option -- %s\n";
+  static cch_t   eng_zIllegal[] =
+       "illegal";
+  static cch_t   eng_zInvalOptDesc[] =
+       "AutoOpts ERROR:  invalid option descriptor for %s\n";
+  static cch_t   eng_zKeyWords[] =
+       "words=";
+  static cch_t   eng_zLoadCooked[] =
+       "cooked";
+  static cch_t   eng_zLoadKeep[] =
+       "keep";
+  static cch_t   eng_zLoadType[] =
+       "type=";
+  static cch_t   eng_zLoadUncooked[] =
+       "uncooked";
+  static cch_t   eng_zLtypeInteger[] =
+       "integer";
+  static cch_t   eng_zLtypeNest[] =
+       "nested";
+  static cch_t   eng_zLtypeString[] =
+       "string";
+  static cch_t   eng_zLtypeBool[] =
+       "bool";
+  static cch_t   eng_zLtypeKeyword[] =
+       "keyword";
+  static cch_t   eng_zLtypeSetMembership[] =
+       "set";
+  static cch_t   eng_zMembers[] =
+       "\t\t\t\t- is a set membership option\n";
+  static cch_t   eng_zMisArg[] =
+       "%s: option `%s' requires an argument\n";
+  static cch_t   eng_zMultiEquiv[] =
+       "Equivalenced option '%s' was equivalenced to both\n\
+\t'%s' and '%s'";
+  static cch_t   eng_zMust[] =
+       "\t\t\t\t- must appear between %d and %d times\n";
+  static cch_t   eng_zNeedOne[] =
+       "ERROR:  The %s option is required\n";
+  static cch_t   eng_zNoArg[] =
+       "%s: option `%s' cannot have an argument\n";
+  static cch_t   eng_zNoArgs[] =
+       "%s: Command line arguments not allowed\n";
+  static cch_t   eng_zNoCreat[] =
+       "error %d (%s) creating %s\n";
+  static cch_t   eng_zNoFlags[] =
+       "Options are specified by single or double hyphens and their name.\n";
+  static cch_t   eng_zNoKey[] =
+       "%s error:  `%s' does not match any keywords\n";
+  static cch_t   eng_zNoLim[] =
+       "\t\t\t\t- may appear multiple times\n";
+  static cch_t   eng_zNoPreset[] =
+       "\t\t\t\t- may not be preset\n";
+  static cch_t   eng_zNoRq_NoShrtTtl[] =
+       "   Arg Option-Name    Description\n";
+  static cch_t   eng_zNoRq_ShrtTtl[] =
+       "  Flg Arg Option-Name    Description\n";
+  static cch_t   eng_zNoStat[] =
+       "error %d (%s) stat-ing %s\n";
+  static cch_t   eng_zNoState[] =
+       "%s(optionRestore): error: no saved option state\n";
+  static cch_t   eng_zNone[] =
+       "none";
+  static cch_t   eng_zNotDef[] =
+       "'%s' not defined\n";
+  static cch_t   eng_zNotEnough[] =
+       "ERROR:  The %s option must appear %d times\n";
+  static cch_t   eng_zNotFile[] =
+       "error:  cannot load options from non-regular file %s\n";
+  static cch_t   eng_zNotNumber[] =
+       "%s error:  `%s' is not a recognizable number\n";
+  static cch_t   eng_zNrmOptFmt[] =
+       " %3s %s";
+  static cch_t   eng_zNumberOpt[] =
+       "The '-#<number>' option may omit the hash char\n";
+  static cch_t   eng_zOneSpace[] =
+       " ";
+  static cch_t   eng_zOnlyOne[] =
+       "one %s%s option allowed\n";
+  static cch_t   eng_zOptsOnly[] =
+       "All arguments are named options.\n";
+  static cch_t   eng_zPathFmt[] =
+       " - reading file %s";
+  static cch_t   eng_zPlsSendBugs[] =
+       "\n\
+please send bug reports to:  %s\n";
+  static cch_t   eng_zPreset[] =
+       "\t\t\t\t- may NOT appear - preset only\n";
+  static cch_t   eng_zPresetFile[] =
+       "#  preset/initialization file\n\
+#  %s#\n";
+  static cch_t   eng_zPresetIntro[] =
+       "\n\
+The following option preset mechanisms are supported:\n";
+  static cch_t   eng_zProg[] =
+       "program";
+  static cch_t   eng_zProhib[] =
+       "prohibits these options:\n";
+  static cch_t   eng_zReorder[] =
+       "Operands and options may be intermixed.  They will be reordered.\n";
+  static cch_t   eng_zReqFmt[] =
+       "ERROR:  %s option requires the %s option\n";
+  static cch_t   eng_zReqOptFmt[] =
+       " %3s %-14s %s";
+  static cch_t   eng_zReqThese[] =
+       "requires these options:\n";
+  static cch_t   eng_zReq_NoShrtTtl[] =
+       "   Arg Option-Name   Req?  Description\n";
+  static cch_t   eng_zReq_ShrtTtl[] =
+       "  Flg Arg Option-Name   Req?  Description\n";
+  static cch_t   eng_zSepChars[] =
+       "-_^";
+  static cch_t   eng_zSetMembers[] =
+       "members=";
+  static cch_t   eng_zSetMemberSettings[] =
+       "or you may use a numeric representation.  Preceding these with a '!' will\n\
+clear the bits, specifying 'none' will clear all bits, and 'all' will set them\n\
+all.  Multiple entries may be passed as an option argument list.\n";
+  static cch_t   eng_zShrtGnuOptFmt[] =
+       "%s";
+  static cch_t   eng_zSixSpaces[] =
+       "      ";
+  static cch_t   eng_zStdBoolArg[] =
+       "T/F";
+  static cch_t   eng_zStdBreak[] =
+       "\n\
+%s\n\n\
+%s";
+  static cch_t   eng_zStdKeyArg[] =
+       "KWd";
+  static cch_t   eng_zStdKeyLArg[] =
+       "Mbr";
+  static cch_t   eng_zStdNestArg[] =
+       "Cpx";
+  static cch_t   eng_zStdNoArg[] =
+       "no ";
+  static cch_t   eng_zStdNumArg[] =
+       "Num";
+  static cch_t   eng_zStdOptArg[] =
+       "opt";
+  static cch_t   eng_zStdReqArg[] =
+       "YES";
+  static cch_t   eng_zStdStrArg[] =
+       "Str";
+  static cch_t   eng_zTabHyp[] =
+       "\t\t\t\t- ";
+  static cch_t   eng_zTabHypAnd[] =
+       "\t\t\t\t-- and ";
+  static cch_t   eng_zTabout[] =
+       "\t\t\t\t%s\n";
+  static cch_t   eng_zThreeSpaces[] =
+       "   ";
+  static cch_t   eng_zTwoSpaces[] =
+       "  ";
+  static cch_t   eng_zUpTo[] =
+       "\t\t\t\t- may appear up to %d times\n";
+  static cch_t   eng_zValidKeys[] =
+       "The valid \"%s\" option keywords are:\n";
+
+  /*
+   *  Now, define (and initialize) the structure that contains
+   *  the pointers to all these strings.
+   *  Aren't you glad you don't maintain this by hand?
+   */
+  usage_text_t option_usage_text = {
+    114,
+    eng_zGnuBoolArg, eng_zGnuKeyArg,  eng_zGnuKeyLArg, eng_zGnuNumArg,
+    eng_zGnuStrArg,
+    {
+      eng_zAO_Bad,             eng_zAO_Big,             eng_zAO_Err,
+      eng_zAO_Sml,             eng_zAll,                eng_zAlt,
+      eng_zAmbigKey,           eng_zAmbiguous,          eng_zArgsMust,
+      eng_zAtMost,             eng_zAuto,               eng_zBadPipe,
+      eng_zBadVerArg,          eng_zCantFmt,            eng_zCantSave,
+      eng_zDefaultOpt,         eng_zDis,                eng_zEnab,
+      eng_zEquiv,              eng_zErrOnly,            eng_zExamineFmt,
+      eng_zFiveSpaces,         eng_zFlagOkay,           eng_zFmtFmt,
+      eng_zForkFail,           eng_zFSErrOptLoad,       eng_zFSErrReadFile,
+      eng_zGenshell,           eng_zGnuBreak,           eng_zGnuNestArg,
+      eng_zGnuOptArg,          eng_zGnuOptFmt,          eng_zHomePath,
+      eng_zIllOptChr,          eng_zIllOptStr,          eng_zIllegal,
+      eng_zInvalOptDesc,       eng_zKeyWords,           eng_zLoadCooked,
+      eng_zLoadKeep,           eng_zLoadType,           eng_zLoadUncooked,
+      eng_zLtypeInteger,       eng_zLtypeNest,          eng_zLtypeString,
+      eng_zLtypeBool,          eng_zLtypeKeyword,       eng_zLtypeSetMembership,
+      eng_zMembers,            eng_zMisArg,             eng_zMultiEquiv,
+      eng_zMust,               eng_zNeedOne,            eng_zNoArg,
+      eng_zNoArgs,             eng_zNoCreat,            eng_zNoFlags,
+      eng_zNoKey,              eng_zNoLim,              eng_zNoPreset,
+      eng_zNoRq_NoShrtTtl,     eng_zNoRq_ShrtTtl,       eng_zNoStat,
+      eng_zNoState,            eng_zNone,               eng_zNotDef,
+      eng_zNotEnough,          eng_zNotFile,            eng_zNotNumber,
+      eng_zNrmOptFmt,          eng_zNumberOpt,          eng_zOneSpace,
+      eng_zOnlyOne,            eng_zOptsOnly,           eng_zPathFmt,
+      eng_zPlsSendBugs,        eng_zPreset,             eng_zPresetFile,
+      eng_zPresetIntro,        eng_zProg,               eng_zProhib,
+      eng_zReorder,            eng_zReqFmt,             eng_zReqOptFmt,
+      eng_zReqThese,           eng_zReq_NoShrtTtl,      eng_zReq_ShrtTtl,
+      eng_zSepChars,           eng_zSetMembers,         eng_zSetMemberSettings,
+      eng_zShrtGnuOptFmt,      eng_zSixSpaces,          eng_zStdBoolArg,
+      eng_zStdBreak,           eng_zStdKeyArg,          eng_zStdKeyLArg,
+      eng_zStdNestArg,         eng_zStdNoArg,           eng_zStdNumArg,
+      eng_zStdOptArg,          eng_zStdReqArg,          eng_zStdStrArg,
+      eng_zTabHyp,             eng_zTabHypAnd,          eng_zTabout,
+      eng_zThreeSpaces,        eng_zTwoSpaces,          eng_zUpTo,
+      eng_zValidKeys
+    }
+  };
+
+#endif /* DO_TRANSLATIONS */
+#endif /* AUTOOPTS_USAGE_TXT_H_GUARD */
diff --git a/sntp/libopts/boolean.c b/sntp/libopts/boolean.c
new file mode 100644 (file)
index 0000000..30ccd0d
--- /dev/null
@@ -0,0 +1,102 @@
+
+/*
+ *  $Id: boolean.c,v 4.5 2006/03/25 19:24:56 bkorb Exp $
+ * Time-stamp:      "2005-02-14 08:24:12 bkorb"
+ *
+ *   Automated Options Paged Usage module.
+ *
+ *  This routine will run run-on options through a pager so the
+ *  user may examine, print or edit them at their leisure.
+ */
+
+/*
+ *  Automated Options copyright 1992-2006 Bruce Korb
+ *
+ *  Automated Options is free software.
+ *  You may redistribute it and/or modify it under the terms of the
+ *  GNU General Public License, as published by the Free Software
+ *  Foundation; either version 2, or (at your option) any later version.
+ *
+ *  Automated Options is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with Automated Options.  See the file "COPYING".  If not,
+ *  write to:  The Free Software Foundation, Inc.,
+ *             51 Franklin Street, Fifth Floor,
+ *             Boston, MA  02110-1301, USA.
+ *
+ * As a special exception, Bruce Korb gives permission for additional
+ * uses of the text contained in his release of AutoOpts.
+ *
+ * The exception is that, if you link the AutoOpts library with other
+ * files to produce an executable, this does not by itself cause the
+ * resulting executable to be covered by the GNU General Public License.
+ * Your use of that executable is in no way restricted on account of
+ * linking the AutoOpts library code into it.
+ *
+ * This exception does not however invalidate any other reasons why
+ * the executable file might be covered by the GNU General Public License.
+ *
+ * This exception applies only to the code released by Bruce Korb under
+ * the name AutoOpts.  If you copy code from other sources under the
+ * General Public License into a copy of AutoOpts, as the General Public
+ * License permits, the exception does not apply to the code that you add
+ * in this way.  To avoid misleading anyone as to the status of such
+ * modified files, you must delete this exception notice from them.
+ *
+ * If you write modifications of your own for AutoOpts, it is your choice
+ * whether to permit this exception to apply to your modifications.
+ * If you do not wish that, delete this exception notice.
+ */
+
+/*=export_func  optionBooleanVal
+ * private:
+ *
+ * what:  Decipher a boolean value
+ * arg:   + tOptions* + pOpts    + program options descriptor +
+ * arg:   + tOptDesc* + pOptDesc + the descriptor for this arg +
+ *
+ * doc:
+ *  Decipher a true or false value for a boolean valued option argument.
+ *  The value is true, unless it starts with 'n' or 'f' or "#f" or
+ *  it is an empty string or it is a number that evaluates to zero.
+=*/
+void
+optionBooleanVal( tOptions* pOpts, tOptDesc* pOD )
+{
+    long  val;
+    char* pz;
+    ag_bool  res = AG_TRUE;
+
+    switch (*(pOD->pzLastArg)) {
+    case '0':
+        val = strtol( pOD->pzLastArg, &pz, 0 );
+        if ((val != 0) || (*pz != NUL))
+            break;
+        /* FALLTHROUGH */
+    case 'N':
+    case 'n':
+    case 'F':
+    case 'f':
+    case NUL:
+        res = AG_FALSE;
+        break;
+    case '#':
+        if (pOD->pzLastArg[1] != 'f')
+            break;
+        res = AG_FALSE;
+    }
+
+    pOD->pzLastArg = (char*)res;
+}
+/*
+ * Local Variables:
+ * mode: C
+ * c-file-style: "stroustrup"
+ * tab-width: 4
+ * indent-tabs-mode: nil
+ * End:
+ * end of autoopts/boolean.c */
diff --git a/sntp/libopts/compat/compat.h b/sntp/libopts/compat/compat.h
new file mode 100644 (file)
index 0000000..5c9e923
--- /dev/null
@@ -0,0 +1,292 @@
+/*  -*- Mode: C -*-  */
+
+/* --- fake the preprocessor into handlng portability */
+/*
+ *  Time-stamp:      "2005-09-21 20:56:13 bkorb"
+ *
+ * Author:           Gary V Vaughan <gvaughan@oranda.demon.co.uk>
+ * Created:          Mon Jun 30 15:54:46 1997
+ *
+ * $Id: compat.h,v 4.6 2005/10/02 16:34:30 bkorb Exp $
+ */
+#ifndef COMPAT_H
+#define COMPAT_H 1
+
+#ifndef HAVE_CONFIG_H
+#  error "compat.h" requires "config.h"
+#endif
+
+#include <config.h>
+
+#ifndef HAVE_STRSIGNAL
+   char * strsignal( int signo );
+#endif
+
+#define  _GNU_SOURCE    1 /* for strsignal in GNU's libc */
+#define  __USE_GNU      1 /* exact same thing as above   */
+#define  __EXTENSIONS__ 1 /* and another way to call for it */
+
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ *
+ *  SYSTEM HEADERS:
+ */
+#include <sys/types.h>
+#include <sys/mman.h>
+#include <sys/param.h>
+#if HAVE_SYS_PROCSET_H
+#  include <sys/procset.h>
+#endif
+#include <sys/stat.h>
+#include <sys/wait.h>
+
+#if defined( HAVE_POSIX_SYSINFO )
+#  include <sys/systeminfo.h>
+#elif defined( HAVE_UNAME_SYSCALL )
+#  include <sys/utsname.h>
+#endif
+
+#ifdef DAEMON_ENABLED
+#  if HAVE_SYS_STROPTS_H
+#  include <sys/stropts.h>
+#  endif
+
+#  if HAVE_SYS_SOCKET_H
+#  include <sys/socket.h>
+#  endif
+
+#  if ! defined(HAVE_SYS_POLL_H) && ! defined(HAVE_SYS_SELECT_H)
+#    error This system cannot support daemon processing
+#  endif
+
+#  if HAVE_SYS_POLL_H
+#  include <sys/poll.h>
+#  endif
+
+#  if HAVE_SYS_SELECT_H
+#  include <sys/select.h>
+#  endif
+
+#  if HAVE_NETINET_IN_H
+#  include <netinet/in.h>
+#  endif
+
+#  if HAVE_SYS_UN_H
+#  include <sys/un.h>
+#  endif
+#endif
+
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ *
+ *  USER HEADERS:
+ */
+#include <stdio.h>
+#include <assert.h>
+#include <ctype.h>
+
+/*
+ *  Directory opening stuff:
+ */
+# if defined (_POSIX_SOURCE)
+/* Posix does not require that the d_ino field be present, and some
+   systems do not provide it. */
+#    define REAL_DIR_ENTRY(dp) 1
+# else /* !_POSIX_SOURCE */
+#    define REAL_DIR_ENTRY(dp) (dp->d_ino != 0)
+# endif /* !_POSIX_SOURCE */
+
+# if defined (HAVE_DIRENT_H)
+#   include <dirent.h>
+#   define D_NAMLEN(dirent) strlen((dirent)->d_name)
+# else /* !HAVE_DIRENT_H */
+#   define dirent direct
+#   define D_NAMLEN(dirent) (dirent)->d_namlen
+#   if defined (HAVE_SYS_NDIR_H)
+#     include <sys/ndir.h>
+#   endif /* HAVE_SYS_NDIR_H */
+#   if defined (HAVE_SYS_DIR_H)
+#     include <sys/dir.h>
+#   endif /* HAVE_SYS_DIR_H */
+#   if defined (HAVE_NDIR_H)
+#     include <ndir.h>
+#   endif /* HAVE_NDIR_H */
+# endif /* !HAVE_DIRENT_H */
+
+#include <errno.h>
+#ifdef HAVE_FCNTL_H
+# include <fcntl.h>
+#endif
+#ifndef O_NONBLOCK
+# define O_NONBLOCK FNDELAY
+#endif
+
+#if defined(HAVE_LIBGEN) && defined(HAVE_LIBGEN_H)
+#  include <libgen.h>
+#endif
+
+#include <limits.h>
+#include <memory.h>
+#include <setjmp.h>
+#include <signal.h>
+
+#if defined( HAVE_STDINT_H )
+#  include <stdint.h>
+#elif defined( HAVE_INTTYPES_H )
+#  include <inttypes.h>
+#endif
+
+#include <stdlib.h>
+#include <string.h>
+
+#include <time.h>
+#include <utime.h>
+
+#ifdef HAVE_UNISTD_H
+#  include <unistd.h>
+#endif
+
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ *
+ *  FIXUPS and CONVIENCE STUFF:
+ */
+#ifdef __cplusplus
+#   define EXTERN extern "C"
+#else
+#   define EXTERN extern
+#endif
+
+/* some systems #def errno! and others do not declare it!! */
+#ifndef errno
+   extern int errno;
+#endif
+
+/* Some machines forget this! */
+
+# ifndef EXIT_FAILURE
+#   define EXIT_SUCCESS 0
+#   define EXIT_FAILURE 1
+# endif
+
+#ifndef NUL
+#  define NUL '\0'
+#endif
+
+#ifndef NULL
+#  define NULL 0
+#endif
+
+#if !defined (MAXPATHLEN) && defined (HAVE_SYS_PARAM_H)
+#  include <sys/param.h>
+#endif /* !MAXPATHLEN && HAVE_SYS_PARAM_H */
+
+#if !defined (MAXPATHLEN) && defined (PATH_MAX)
+#  define MAXPATHLEN PATH_MAX
+#endif /* !MAXPATHLEN && PATH_MAX */
+
+#if !defined (MAXPATHLEN)
+#  define MAXPATHLEN 4096
+#endif /* MAXPATHLEN */
+
+#ifndef LONG_MAX
+#  define LONG_MAX      ~(1L << (8*sizeof(long) -1))
+#  define INT_MAX       ~(1 << (8*sizeof(int) -1))
+#endif
+
+#ifndef ULONG_MAX
+#  define ULONG_MAX     ~(OUL)
+#  define UINT_MAX      ~(OU)
+#endif
+
+#ifndef SHORT_MAX
+#  define SHORT_MAX     ~(1 << (8*sizeof(short) -1))
+#else
+#  define USHORT_MAX    ~(OUS)
+#endif
+
+#ifndef HAVE_INT8_T
+  typedef signed char       int8_t;
+#endif
+#ifndef HAVE_UINT8_T
+  typedef unsigned char     uint8_t;
+#endif
+#ifndef HAVE_INT16_T
+  typedef signed short      int16_t;
+#endif
+#ifndef HAVE_UINT16_T
+  typedef unsigned short    uint16_t;
+#endif
+
+#ifndef HAVE_INT32_T
+# if SIZEOF_INT == 4
+       typedef signed int      int32_t;
+# elif SIZEOF_LONG == 4
+       typedef signed long     int32_t;
+# endif
+#endif
+
+#ifndef HAVE_UINT32_T
+# if SIZEOF_INT == 4
+       typedef unsigned int    uint32_t;
+# elif SIZEOF_LONG == 4
+       typedef unsigned long   uint32_t;
+# else
+#   error Cannot create a uint32_t type.
+# endif
+#endif
+
+#ifndef HAVE_INTPTR_T
+  typedef signed long   intptr_t;
+#endif
+#ifndef HAVE_UINTPTR_T
+  typedef unsigned long uintptr_t;
+#endif
+
+/* redefine these for BSD style string libraries */
+#ifndef HAVE_STRCHR
+#  define strchr        index
+#  define strrchr       rindex
+#endif
+
+#ifdef USE_FOPEN_BINARY
+#  ifndef FOPEN_BINARY_FLAG
+#    define FOPEN_BINARY_FLAG   "b"
+#  endif
+#  ifndef FOPEN_TEXT_FLAG
+#    define FOPEN_TEXT_FLAG     "t"
+#  endif
+#else
+#  ifndef FOPEN_BINARY_FLAG
+#    define FOPEN_BINARY_FLAG
+#  endif
+#  ifndef FOPEN_TEXT_FLAG
+#    define FOPEN_TEXT_FLAG
+#  endif
+#endif
+
+#ifndef STR
+#  define _STR(s) #s
+#  define STR(s)  _STR(s)
+#endif
+
+/* ##### Pointer sized word ##### */
+
+/* FIXME:  the MAX stuff in here is broken! */
+#if SIZEOF_CHARP > SIZEOF_INT
+   typedef long t_word;
+   #define WORD_MAX  LONG_MAX
+   #define WORD_MIN  LONG_MIN
+#else /* SIZEOF_CHARP <= SIZEOF_INT */
+   typedef int t_word;
+   #define WORD_MAX  INT_MAX
+   #define WORD_MIN  INT_MIN
+#endif
+
+#endif /* COMPAT_H */
+
+/*
+ * Local Variables:
+ * mode: C
+ * c-file-style: "stroustrup"
+ * tab-width: 4
+ * indent-tabs-mode: nil
+ * End:
+ * end of compat/compat.h */
diff --git a/sntp/libopts/compat/pathfind.c b/sntp/libopts/compat/pathfind.c
new file mode 100644 (file)
index 0000000..4da759f
--- /dev/null
@@ -0,0 +1,330 @@
+/*  -*- Mode: C -*-  */
+
+/* pathfind.c --- find a FILE  MODE along PATH */
+
+/*
+ * Author:           Gary V Vaughan <gvaughan@oranda.demon.co.uk>
+ * Created:          Tue Jun 24 15:07:31 1997
+ * Last Modified:    $Date: 2005/07/27 17:26:32 $
+ *            by: bkorb
+ *
+ * $Id: pathfind.c,v 4.4 2005/07/27 17:26:32 bkorb Exp $
+ */
+
+/* Code: */
+
+#include "compat.h"
+#ifndef HAVE_PATHFIND
+
+static char* make_absolute( const char *string, const char *dot_path );
+static char* canonicalize_pathname( char *path );
+static char* extract_colon_unit( char* dir, const char *string, int *p_index );
+
+
+/*=export_func pathfind
+ *
+ * what: fild a file in a list of directories
+ *
+ * ifndef: HAVE_PATHFIND
+ *
+ * arg:  + const char* + path + colon separated list of search directories +
+ * arg:  + const char* + file + the name of the file to look for +
+ * arg:  + const char* + mode + the mode bits that must be set to match +
+ *
+ * ret_type:  char*
+ * ret_desc:  the path to the located file
+ *
+ * doc:
+ *
+ * pathfind looks for a a file with name "FILE" and "MODE" access
+ * along colon delimited "PATH", and returns the full pathname as a
+ * string, or NULL if not found.  If "FILE" contains a slash, then
+ * it is treated as a relative or absolute path and "PATH" is ignored.
+ *
+ * @strong{NOTE}: this function is compiled into @file{libopts} only if
+ * it is not natively supplied.
+ *
+ * The "MODE" argument is a string of option letters chosen from the
+ * list below:
+ * @example
+ *          Letter    Meaning
+ *          r         readable
+ *          w         writable
+ *          x         executable
+ *          f         normal file       (NOT IMPLEMENTED)
+ *          b         block special     (NOT IMPLEMENTED)
+ *          c         character special (NOT IMPLEMENTED)
+ *          d         directory         (NOT IMPLEMENTED)
+ *          p         FIFO (pipe)       (NOT IMPLEMENTED)
+ *          u         set user ID bit   (NOT IMPLEMENTED)
+ *          g         set group ID bit  (NOT IMPLEMENTED)
+ *          k         sticky bit        (NOT IMPLEMENTED)
+ *          s         size nonzero      (NOT IMPLEMENTED)
+ * @end example
+ *
+ * example:
+ * To find the "ls" command using the "PATH" environment variable:
+ * @example
+ *    #include <stdlib.h>
+ *    char* pz_ls = pathfind( getenv("PATH"), "ls", "rx" );
+ *    <<do whatever with pz_ls>>
+ *    free( pz_ls );
+ * @end example
+ * The path is allocated with @code{malloc(3C)}, so you must @code{free(3C)}
+ * the result.  Also, do not use unimplemented file modes.  :-)
+ *
+ * err:  returns NULL if the file is not found.
+=*/
+char*
+pathfind( const char*  path,
+          const char*  fileName,
+          const char*  mode )
+{
+    int   p_index   = 0;
+    int   mode_bits = 0;
+    char* pathName  = NULL;
+    char  zPath[ MAXPATHLEN + 1 ];
+
+    if (strchr( mode, 'r' )) mode_bits |= R_OK;
+    if (strchr( mode, 'w' )) mode_bits |= W_OK;
+    if (strchr( mode, 'x' )) mode_bits |= X_OK;
+
+    /*
+     *  FOR each non-null entry in the colon-separated path, DO ...
+     */
+    for (;;) {
+        DIR*  dirP;
+        char* colon_unit = extract_colon_unit( zPath, path, &p_index );
+
+        /*
+         *  IF no more entries, THEN quit
+         */
+        if (colon_unit == NULL)
+            break;
+
+        dirP = opendir( colon_unit );
+
+        /*
+         *  IF the directory is inaccessable, THEN next directory
+         */
+        if (dirP == NULL)
+            continue;
+
+        /*
+         *  FOR every entry in the given directory, ...
+         */
+        for (;;) {
+            struct dirent *entP = readdir( dirP );
+
+            if (entP == (struct dirent*)NULL)
+                break;
+
+            /*
+             *  IF the file name matches the one we are looking for, ...
+             */
+            if (strcmp( entP->d_name, fileName ) == 0) {
+                char* pzFullName = make_absolute( fileName, colon_unit);
+
+                /*
+                 *  Make sure we can access it in the way we want
+                 */
+                if (access( pzFullName, mode_bits ) >= 0) {
+                    /*
+                     *  We can, so normalize the name and return it below
+                     */
+                    pathName = canonicalize_pathname( pzFullName );
+                }
+
+                free( (void*)pzFullName );
+                break;
+            }
+        }
+        
+        closedir( dirP );
+
+        if (pathName != NULL)
+            break;
+    }
+
+    return pathName;
+}
+
+/*
+ * Turn STRING  (a pathname) into an  absolute  pathname, assuming  that
+ * DOT_PATH contains the symbolic location of  `.'.  This always returns
+ * a new string, even if STRING was an absolute pathname to begin with.
+ */
+static char*
+make_absolute( const char *string, const char *dot_path )
+{
+    char *result;
+    int result_len;
+  
+    if (!dot_path || *string == '/') {
+        result = strdup( string );
+    } else {
+        if (dot_path && dot_path[0]) {
+            result = malloc( 2 + strlen( dot_path ) + strlen( string ) );
+            strcpy( result, dot_path );
+            result_len = strlen( result );
+            if (result[result_len - 1] != '/') {
+                result[result_len++] = '/';
+                result[result_len] = '\0';
+            }    
+        } else {
+            result = malloc( 3 + strlen( string ) );
+            result[0] = '.'; result[1] = '/'; result[2] = '\0';
+            result_len = 2;
+        }
+
+        strcpy( result + result_len, string );
+    }
+
+    return result;
+}
+
+/*
+ * Canonicalize PATH, and return a  new path.  The new path differs from
+ * PATH in that:
+ *
+ *    Multiple `/'s     are collapsed to a single `/'.
+ *    Leading `./'s     are removed.
+ *    Trailing `/.'s    are removed.
+ *    Trailing `/'s     are removed.
+ *    Non-leading `../'s and trailing `..'s are handled by removing
+ *                    portions of the path.
+ */
+static char*
+canonicalize_pathname( char *path )
+{
+    int i, start;
+    char stub_char, *result;
+
+    /* The result cannot be larger than the input PATH. */
+    result = strdup( path );
+
+    stub_char = (*path == '/') ? '/' : '.';
+
+    /* Walk along RESULT looking for things to compact. */
+    i = 0;
+    while (result[i]) {
+        while (result[i] != '\0' && result[i] != '/')
+            i++;
+
+        start = i++;
+
+        /* If we didn't find any  slashes, then there is nothing left to
+         * do.
+         */
+        if (!result[start])
+            break;
+
+        /* Handle multiple `/'s in a row. */
+        while (result[i] == '/')
+            i++;
+
+#if !defined (apollo)
+        if ((start + 1) != i)
+#else
+        if ((start + 1) != i && (start != 0 || i != 2))
+#endif /* apollo */
+        {
+            strcpy( result + start + 1, result + i );
+            i = start + 1;
+        }
+
+        /* Handle backquoted `/'. */
+        if (start > 0 && result[start - 1] == '\\')
+            continue;
+
+        /* Check for trailing `/', and `.' by itself. */
+        if ((start && !result[i])
+            || (result[i] == '.' && !result[i+1])) {
+            result[--i] = '\0';
+            break;
+        }
+
+        /* Check for `../', `./' or trailing `.' by itself. */
+        if (result[i] == '.') {
+            /* Handle `./'. */
+            if (result[i + 1] == '/') {
+                strcpy( result + i, result + i + 1 );
+                i = (start < 0) ? 0 : start;
+                continue;
+            }
+
+            /* Handle `../' or trailing `..' by itself. */
+            if (result[i + 1] == '.' &&
+                (result[i + 2] == '/' || !result[i + 2])) {
+                while (--start > -1 && result[start] != '/')
+                    ;
+                strcpy( result + start + 1, result + i + 2 );
+                i = (start < 0) ? 0 : start;
+                continue;
+            }
+        }
+    }
+
+    if (!*result) {
+        *result = stub_char;
+        result[1] = '\0';
+    }
+
+    return result;
+}
+
+/*
+ * Given a  string containing units of information separated  by colons,
+ * return the next one  pointed to by (P_INDEX), or NULL if there are no
+ * more.  Advance (P_INDEX) to the character after the colon.
+ */
+static char*
+extract_colon_unit( char* pzDir, const char *string, int *p_index )
+{
+    char*  pzDest = pzDir;
+    int    ix     = *p_index;
+
+    if (string == NULL)
+        return NULL;
+
+    if ((unsigned)ix >= strlen( string ))
+        return NULL;
+
+    {
+        const char* pzSrc = string + ix;
+
+        while (*pzSrc == ':')  pzSrc++;
+
+        for (;;) {
+            char ch = (*(pzDest++) = *(pzSrc++));
+            switch (ch) {
+            case ':':
+                pzDest[-1] = NUL;
+            case NUL:
+                goto copy_done;
+            }
+
+            if ((pzDest - pzDir) >= MAXPATHLEN)
+                break;
+        } copy_done:;
+
+        ix = pzSrc - string;
+    }
+
+    if (*pzDir == NUL)
+        return NULL;
+
+    *p_index = ix;
+    return pzDir;
+}
+
+#endif /* HAVE_PATHFIND */
+
+/*
+ * Local Variables:
+ * mode: C
+ * c-file-style: "stroustrup"
+ * tab-width: 4
+ * indent-tabs-mode: nil
+ * End:
+ * end of compat/pathfind.c */
diff --git a/sntp/libopts/compat/snprintf.c b/sntp/libopts/compat/snprintf.c
new file mode 100644 (file)
index 0000000..0215578
--- /dev/null
@@ -0,0 +1,36 @@
+
+#ifndef HAVE_VPRINTF
+#include "choke-me: no vprintf and no snprintf"
+#endif
+
+static int
+snprintf(char *str, size_t n, const char *fmt, ...)
+{
+    va_list ap;
+    int rval;
+
+#ifdef VSPRINTF_CHARSTAR
+    char *rp;
+    va_start(ap, fmt);
+    rp = vsprintf(str, fmt, ap);
+    va_end(ap);
+    rval = strlen(rp);
+
+#else
+    va_start(ap, fmt);
+    rval = vsprintf(str, fmt, ap);
+    va_end(ap);
+#endif
+
+    return rval;
+}
+
+static int
+vsnprintf( char *str, size_t n, const char *fmt, va_list ap )
+{
+#ifdef VSPRINTF_CHARSTAR
+    return (strlen(vsprintf(str, fmt, ap)));
+#else
+    return (vsprintf(str, fmt, ap));
+#endif
+}
diff --git a/sntp/libopts/compat/strdup.c b/sntp/libopts/compat/strdup.c
new file mode 100644 (file)
index 0000000..34dbcc5
--- /dev/null
@@ -0,0 +1,19 @@
+/*
+ * Platforms without strdup ?!?!?!
+ */
+
+static char *
+strdup( const char *s )
+{
+    char *cp;
+
+    if (s == NULL)
+       return NULL;
+
+    cp = (char *) AGALOC((unsigned) (strlen(s)+1), "strdup");
+
+    if (cp != NULL)
+       (void) strcpy(cp, s);
+
+    return cp;
+}
diff --git a/sntp/libopts/configfile.c b/sntp/libopts/configfile.c
new file mode 100644 (file)
index 0000000..4a2155a
--- /dev/null
@@ -0,0 +1,1277 @@
+/*
+ *  $Id: configfile.c,v 4.12 2006/03/25 19:24:56 bkorb Exp $
+ *  Time-stamp:      "2005-10-16 15:16:32 bkorb"
+ *
+ *  configuration/rc/ini file handling.
+ */
+
+/*
+ *  Automated Options copyright 1992-2006 Bruce Korb
+ *
+ *  Automated Options is free software.
+ *  You may redistribute it and/or modify it under the terms of the
+ *  GNU General Public License, as published by the Free Software
+ *  Foundation; either version 2, or (at your option) any later version.
+ *
+ *  Automated Options is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with Automated Options.  See the file "COPYING".  If not,
+ *  write to:  The Free Software Foundation, Inc.,
+ *             51 Franklin Street, Fifth Floor,
+ *             Boston, MA  02110-1301, USA.
+ *
+ * As a special exception, Bruce Korb gives permission for additional
+ * uses of the text contained in his release of AutoOpts.
+ *
+ * The exception is that, if you link the AutoOpts library with other
+ * files to produce an executable, this does not by itself cause the
+ * resulting executable to be covered by the GNU General Public License.
+ * Your use of that executable is in no way restricted on account of
+ * linking the AutoOpts library code into it.
+ *
+ * This exception does not however invalidate any other reasons why
+ * the executable file might be covered by the GNU General Public License.
+ *
+ * This exception applies only to the code released by Bruce Korb under
+ * the name AutoOpts.  If you copy code from other sources under the
+ * General Public License into a copy of AutoOpts, as the General Public
+ * License permits, the exception does not apply to the code that you add
+ * in this way.  To avoid misleading anyone as to the status of such
+ * modified files, you must delete this exception notice from them.
+ *
+ * If you write modifications of your own for AutoOpts, it is your choice
+ * whether to permit this exception to apply to your modifications.
+ * If you do not wish that, delete this exception notice.
+ */
+
+/* = = = START-STATIC-FORWARD = = = */
+/* static forward declarations maintained by :mkfwd */
+static void
+filePreset(
+    tOptions*     pOpts,
+    const char*   pzFileName,
+    int           direction );
+
+static char*
+handleComment( char* pzText );
+
+static char*
+handleConfig(
+    tOptions*     pOpts,
+    tOptState*    pOS,
+    char*         pzText,
+    int           direction );
+
+static char*
+handleDirective(
+    tOptions*     pOpts,
+    char*         pzText );
+
+static char*
+handleProgramSection(
+    tOptions*     pOpts,
+    char*         pzText );
+
+static char*
+handleStructure(
+    tOptions*     pOpts,
+    tOptState*    pOS,
+    char*         pzText,
+    int           direction );
+
+static char*
+parseKeyWordType(
+    tOptions*     pOpts,
+    char*         pzText,
+    tOptionValue* pType );
+
+static char*
+parseLoadMode(
+    char*               pzText,
+    tOptionLoadMode*    pMode );
+
+static char*
+parseSetMemType(
+    tOptions*     pOpts,
+    char*         pzText,
+    tOptionValue* pType );
+
+static char*
+parseValueType(
+    char*         pzText,
+    tOptionValue* pType );
+
+static char*
+skipUnknown( char* pzText );
+/* = = = END-STATIC-FORWARD = = = */
+
+
+/*=export_func  configFileLoad
+ *
+ * what:  parse a configuration file
+ * arg:   + const char*     + pzFile + the file to load +
+ *
+ * ret_type:  const tOptionValue*
+ * ret_desc:  An allocated, compound value structure
+ *
+ * doc:
+ *  This routine will load a named configuration file and parse the
+ *  text as a hierarchically valued option.  The option descriptor
+ *  created from an option definition file is not used via this interface.
+ *  The returned value is "named" with the input file name and is of
+ *  type "@code{OPARG_TYPE_HIERARCHY}".  It may be used in calls to
+ *  @code{optionGetValue()}, @code{optionNextValue()} and
+ *  @code{optionUnloadNested()}.
+ *
+ * err:
+ *  If the file cannot be loaded or processed, @code{NULL} is returned and
+ *  @var{errno} is set.  It may be set by a call to either @code{open(2)}
+ *  @code{mmap(2)} or other file system calls, or it may be:
+ *  @itemize @bullet
+ *  @item
+ *  @code{ENOENT} - the file was empty.
+ *  @item
+ *  @code{EINVAL} - the file contents are invalid -- not properly formed.
+ *  @item
+ *  @code{ENOMEM} - not enough memory to allocate the needed structures.
+ *  @end itemize
+=*/
+const tOptionValue*
+configFileLoad( const char* pzFile )
+{
+    tmap_info_t   cfgfile;
+    tOptionValue* pRes = NULL;
+    char* pzText =
+        text_mmap( pzFile, PROT_READ, MAP_PRIVATE, &cfgfile );
+
+    if (TEXT_MMAP_FAILED_ADDR(pzText))
+        return NULL; /* errno is set */
+
+    pRes = optionLoadNested(pzText, pzFile, strlen(pzFile), OPTION_LOAD_COOKED);
+
+    if (pRes == NULL) {
+        int err = errno;
+        text_munmap( &cfgfile );
+        errno = err;
+    } else
+        text_munmap( &cfgfile );
+    return pRes;
+}
+
+
+/*=export_func  optionFindValue
+ *
+ * what:  find a hierarcicaly valued option instance
+ * arg:   + const tOptDesc* + pOptDesc + an option with a nested arg type +
+ * arg:   + const char*     + name     + name of value to find +
+ * arg:   + const char*     + value    + the matching value    +
+ *
+ * ret_type:  const tOptionValue*
+ * ret_desc:  a compound value structure
+ *
+ * doc:
+ *  This routine will find an entry in a nested value option or configurable.
+ *  It will search through the list and return a matching entry.
+ *
+ * err:
+ *  The returned result is NULL and errno is set:
+ *  @itemize @bullet
+ *  @item
+ *  @code{EINVAL} - the @code{pOptValue} does not point to a valid
+ *  hierarchical option value.
+ *  @item
+ *  @code{ENOENT} - no entry matched the given name.
+ *  @end itemize
+=*/
+const tOptionValue*
+optionFindValue( const tOptDesc* pOptDesc,
+                 const char* pzName, const char* pzVal )
+{
+    const tOptionValue* pRes = NULL;
+
+    if (  (pOptDesc == NULL)
+       || (OPTST_GET_ARGTYPE(pOptDesc->fOptState) != OPARG_TYPE_HIERARCHY))  {
+        errno = EINVAL;
+    }
+
+    else if (pOptDesc->optCookie == NULL) {
+        errno = ENOENT;
+    }
+
+    else do {
+        tArgList* pAL = pOptDesc->optCookie;
+        int ct = pAL->useCt;
+        const tOptionValue** ppOV =
+            (const tOptionValue**)(void*)&(pAL->apzArgs);
+
+        if (ct == 0) {
+            errno = ENOENT;
+            break;
+        }
+
+        if (pzName == NULL) {
+            pRes = *ppOV;
+            break;
+        }
+
+        while (--ct >= 0) {
+            const tOptionValue* pOV = *(ppOV++);
+            const tOptionValue* pRV = optionGetValue( pOV, pzName );
+
+            if (pRV == NULL)
+                continue;
+
+            if (pzVal == NULL) {
+                pRes = pOV;
+                break;
+            }
+        }
+        if (pRes == NULL)
+            errno = ENOENT;
+    } while (0);
+
+    return pRes;
+}
+
+
+/*=export_func  optionFindNextValue
+ *
+ * what:  find a hierarcicaly valued option instance
+ * arg:   + const tOptDesc* + pOptDesc + an option with a nested arg type +
+ * arg:   + const tOptionValue* + pPrevVal + the last entry +
+ * arg:   + const char*     + name     + name of value to find +
+ * arg:   + const char*     + value    + the matching value    +
+ *
+ * ret_type:  const tOptionValue*
+ * ret_desc:  a compound value structure
+ *
+ * doc:
+ *  This routine will find the next entry in a nested value option or
+ *  configurable.  It will search through the list and return the next entry
+ *  that matches the criteria.
+ *
+ * err:
+ *  The returned result is NULL and errno is set:
+ *  @itemize @bullet
+ *  @item
+ *  @code{EINVAL} - the @code{pOptValue} does not point to a valid
+ *  hierarchical option value.
+ *  @item
+ *  @code{ENOENT} - no entry matched the given name.
+ *  @end itemize
+=*/
+const tOptionValue*
+optionFindNextValue( const tOptDesc* pOptDesc, const tOptionValue* pPrevVal,
+                 const char* pzName, const char* pzVal )
+{
+    int foundOldVal = 0;
+    tOptionValue* pRes = NULL;
+
+    if (  (pOptDesc == NULL)
+       || (OPTST_GET_ARGTYPE(pOptDesc->fOptState) != OPARG_TYPE_HIERARCHY))  {
+        errno = EINVAL;
+    }
+
+    else if (pOptDesc->optCookie == NULL) {
+        errno = ENOENT;
+    }
+
+    else do {
+        tArgList* pAL = pOptDesc->optCookie;
+        int ct = pAL->useCt;
+        tOptionValue** ppOV = (tOptionValue**)(void*)&(pAL->apzArgs);
+
+        if (ct == 0) {
+            errno = ENOENT;
+            break;
+        }
+
+        while (--ct >= 0) {
+            tOptionValue* pOV = *(ppOV++);
+            if (foundOldVal) {
+                pRes = pOV;
+                break;
+            }
+            if (pOV == pPrevVal)
+                foundOldVal = 1;
+        }
+        if (pRes == NULL)
+            errno = ENOENT;
+    } while (0);
+
+    return pRes;
+}
+
+
+/*=export_func  optionGetValue
+ *
+ * what:  get a specific value from a hierarcical list
+ * arg:   + const tOptionValue* + pOptValue + a hierarchcal value +
+ * arg:   + const char*   + valueName + name of value to get +
+ *
+ * ret_type:  const tOptionValue*
+ * ret_desc:  a compound value structure
+ *
+ * doc:
+ *  This routine will find an entry in a nested value option or configurable.
+ *  If "valueName" is NULL, then the first entry is returned.  Otherwise,
+ *  the first entry with a name that exactly matches the argument will be
+ *  returned.
+ *
+ * err:
+ *  The returned result is NULL and errno is set:
+ *  @itemize @bullet
+ *  @item
+ *  @code{EINVAL} - the @code{pOptValue} does not point to a valid
+ *  hierarchical option value.
+ *  @item
+ *  @code{ENOENT} - no entry matched the given name.
+ *  @end itemize
+=*/
+const tOptionValue*
+optionGetValue( const tOptionValue* pOld, const char* pzValName )
+{
+    tArgList*     pAL;
+    tOptionValue* pRes = NULL;
+
+    if ((pOld == NULL) || (pOld->valType != OPARG_TYPE_HIERARCHY)) {
+        errno = EINVAL;
+        return NULL;
+    }
+    pAL = pOld->v.nestVal;
+
+    if (pAL->useCt > 0) {
+        int ct = pAL->useCt;
+        tOptionValue** papOV = (tOptionValue**)(pAL->apzArgs);
+
+        if (pzValName == NULL) {
+            pRes = *papOV;
+        }
+
+        else do {
+            tOptionValue* pOV = *(papOV++);
+            if (strcmp( pOV->pzName, pzValName ) == 0) {
+                pRes = pOV;
+                break;
+            }
+        } while (--ct > 0);
+    }
+    if (pRes == NULL)
+        errno = ENOENT;
+    return pRes;
+}
+
+
+/*=export_func  optionNextValue
+ *
+ * what:  get the next value from a hierarchical list
+ * arg:   + const tOptionValue* + pOptValue + a hierarchcal list value +
+ * arg:   + const tOptionValue* + pOldValue + a value from this list   +
+ *
+ * ret_type:  const tOptionValue*
+ * ret_desc:  a compound value structure
+ *
+ * doc:
+ *  This routine will return the next entry after the entry passed in.  At the
+ *  end of the list, NULL will be returned.  If the entry is not found on the
+ *  list, NULL will be returned and "@var{errno}" will be set to EINVAL.
+ *  The "@var{pOldValue}" must have been gotten from a prior call to this
+ *  routine or to "@code{opitonGetValue()}".
+ *
+ * err:
+ *  The returned result is NULL and errno is set:
+ *  @itemize @bullet
+ *  @item
+ *  @code{EINVAL} - the @code{pOptValue} does not point to a valid
+ *  hierarchical option value or @code{pOldValue} does not point to a
+ *  member of that option value.
+ *  @item
+ *  @code{ENOENT} - the supplied @code{pOldValue} pointed to the last entry.
+ *  @end itemize
+=*/
+const tOptionValue*
+optionNextValue( const tOptionValue* pOVList, const tOptionValue* pOldOV )
+{
+    tArgList*     pAL;
+    tOptionValue* pRes = NULL;
+    int           err  = EINVAL;
+
+    if ((pOVList == NULL) || (pOVList->valType != OPARG_TYPE_HIERARCHY)) {
+        errno = EINVAL;
+        return NULL;
+    }
+    pAL = pOVList->v.nestVal;
+    {
+        int   ct   = pAL->useCt;
+        tOptionValue** papNV = (tOptionValue**)(pAL->apzArgs);
+
+        while (ct-- > 0) {
+            tOptionValue* pNV = *(papNV++);
+            if (pNV == pOldOV) {
+                if (ct == 0) {
+                    err = ENOENT;
+
+                } else {
+                    err  = 0;
+                    pRes = *papNV;
+                }
+                break;
+            }
+        }
+    }
+    if (err != 0)
+        errno = err;
+    return pRes;
+}
+
+
+/*  filePreset
+ *
+ *  Load a file containing presetting information (a configuration file).
+ */
+static void
+filePreset(
+    tOptions*     pOpts,
+    const char*   pzFileName,
+    int           direction )
+{
+    tmap_info_t   cfgfile;
+    char*         pzFileText =
+        text_mmap( pzFileName, PROT_READ|PROT_WRITE, MAP_PRIVATE, &cfgfile );
+    tOptState     st = OPTSTATE_INITIALIZER(PRESET);
+
+    if (TEXT_MMAP_FAILED_ADDR(pzFileText))
+        return;
+
+    if (direction == DIRECTION_CALLED) {
+        st.flags  = OPTST_DEFINED;
+        direction = DIRECTION_PROCESS;
+    }
+
+    /*
+     *  IF this is called via "optionProcess", then we are presetting.
+     *  This is the default and the PRESETTING bit will be set.
+     *  If this is called via "optionFileLoad", then the bit is not set
+     *  and we consider stuff set herein to be "set" by the client program.
+     */
+    if ((pOpts->fOptSet & OPTPROC_PRESETTING) == 0)
+        st.flags = OPTST_SET;
+
+    do  {
+        while (isspace( *pzFileText ))  pzFileText++;
+
+        if (isalpha( *pzFileText )) {
+            pzFileText = handleConfig( pOpts, &st, pzFileText, direction );
+
+        } else switch (*pzFileText) {
+        case '<':
+            if (isalpha( pzFileText[1] ))
+                pzFileText = handleStructure(pOpts, &st, pzFileText, direction);
+
+            else switch (pzFileText[1]) {
+            case '?':
+                pzFileText = handleDirective( pOpts, pzFileText );
+                break;
+
+            case '!':
+                pzFileText = handleComment( pzFileText );
+                break;
+
+            case '/':
+                pzFileText = strchr( pzFileText+2, '>' );
+                if (pzFileText++ != NULL)
+                    break;
+
+            default:
+                goto all_done;
+            }
+            break;
+
+        case '[':
+            pzFileText = handleProgramSection( pOpts, pzFileText );
+            break;
+
+        case '#':
+            pzFileText = strchr( pzFileText+1, '\n' );
+            break;
+
+        default:
+            goto all_done; /* invalid format */
+        }
+    } while (pzFileText != NULL);
+
+ all_done:
+    text_munmap( &cfgfile );
+}
+
+
+/*  handleComment
+ *
+ *  "pzText" points to a "<!" sequence.
+ *  Theoretically, we should ensure that it begins with "<!--",
+ *  but actually I don't care that much.  It ends with "-->".
+ */
+static char*
+handleComment( char* pzText )
+{
+    char* pz = strstr( pzText, "-->" );
+    if (pz != NULL)
+        pz += 3;
+    return pz;
+}
+
+
+/*  handleConfig
+ *
+ *  "pzText" points to the start of some value name.
+ *  The end of the entry is the end of the line that is not preceded by
+ *  a backslash escape character.  The string value is always processed
+ *  in "cooked" mode.
+ */
+static char*
+handleConfig(
+    tOptions*     pOpts,
+    tOptState*    pOS,
+    char*         pzText,
+    int           direction )
+{
+    char* pzName = pzText++;
+    char* pzEnd  = strchr( pzText, '\n' );
+
+    while (ISNAMECHAR( *pzText ))  pzText++;
+    while (isspace( *pzText )) pzText++;
+    if (pzText > pzEnd) {
+    name_only:
+        *pzEnd++ = NUL;
+        loadOptionLine( pOpts, pOS, pzName, direction, OPTION_LOAD_UNCOOKED );
+        return pzEnd;
+    }
+
+    /*
+     *  Either the first character after the name is a ':' or '=',
+     *  or else we must have skipped over white space.  Anything else
+     *  is an invalid format and we give up parsing the text.
+     */
+    if ((*pzText == '=') || (*pzText == ':')) {
+        while (isspace( *++pzText ))   ;
+        if (pzText > pzEnd)
+            goto name_only;
+    } else if (! isspace(pzText[-1]))
+        return NULL;
+
+    /*
+     *  IF the value is continued, remove the backslash escape and push "pzEnd"
+     *  on to a newline *not* preceded by a backslash.
+     */
+    if (pzEnd[-1] == '\\') {
+        char* pcD = pzEnd-1;
+        char* pcS = pzEnd;
+
+        for (;;) {
+            char ch = *(pcS++);
+            switch (ch) {
+            case NUL:
+                pcS = NULL;
+
+            case '\n':
+                *pcD = NUL;
+                pzEnd = pcS;
+                goto copy_done;
+
+            case '\\':
+                if (*pcS == '\n') {
+                    ch = *(pcS++);
+                }
+                /* FALLTHROUGH */
+            default:
+                *(pcD++) = ch;
+            }
+        } copy_done:;
+
+    } else {
+        /*
+         *  The newline was not preceded by a backslash.  NUL it out
+         */
+        *(pzEnd++) = NUL;
+    }
+
+    /*
+     *  "pzName" points to what looks like text for one option/configurable.
+     *  It is NUL terminated.  Process it.
+     */
+    loadOptionLine( pOpts, pOS, pzName, direction, OPTION_LOAD_UNCOOKED );
+
+    return pzEnd;
+}
+
+
+/*  handleDirective
+ *
+ *  "pzText" points to a "<?" sequence.
+ *  For the moment, we only handle "<?program" directives.
+ */
+static char*
+handleDirective(
+    tOptions*     pOpts,
+    char*         pzText )
+{
+    char   ztitle[32] = "<?";
+    size_t title_len = strlen( zProg );
+    size_t name_len;
+
+    if (  (strncmp( pzText+2, zProg, title_len ) != 0)
+       || (! isspace( pzText[title_len+2] )) )  {
+        pzText = strchr( pzText+2, '>' );
+        if (pzText != NULL)
+            pzText++;
+        return pzText;
+    }
+
+    name_len = strlen( pOpts->pzProgName );
+    strcpy( ztitle+2, zProg );
+    title_len += 2;
+
+    do  {
+        pzText += title_len;
+
+        if (isspace(*pzText)) {
+            while (isspace(*pzText))  pzText++;
+            if (  (strneqvcmp( pzText, pOpts->pzProgName, name_len ) == 0)
+               && (pzText[name_len] == '>'))  {
+                pzText += name_len + 1;
+                break;
+            }
+        }
+
+        pzText = strstr( pzText, ztitle );
+    } while (pzText != NULL);
+
+    return pzText;
+}
+
+
+/*  handleProgramSection
+ *
+ *  "pzText" points to a '[' character.
+ *  The "traditional" [PROG_NAME] segmentation of the config file.
+ *  Do not ever mix with the "<?program prog-name>" variation.
+ */
+static char*
+handleProgramSection(
+    tOptions*     pOpts,
+    char*         pzText )
+{
+    size_t len = strlen( pOpts->pzPROGNAME );
+    if (   (strncmp( pzText+1, pOpts->pzPROGNAME, len ) == 0)
+        && (pzText[len+1] == ']'))
+        return strchr( pzText + len + 2, '\n' );
+
+    if (len > 16)
+        return NULL;
+
+    {
+        char z[24];
+        sprintf( z, "[%s]", pOpts->pzPROGNAME );
+        pzText = strstr( pzText, z );
+    }
+
+    if (pzText != NULL)
+        pzText = strchr( pzText, '\n' );
+    return pzText;
+}
+
+
+/*  handleStructure
+ *
+ *  "pzText" points to a '<' character, followed by an alpha.
+ *  The end of the entry is either the "/>" following the name, or else a
+ *  "</name>" string.
+ */
+static char*
+handleStructure(
+    tOptions*     pOpts,
+    tOptState*    pOS,
+    char*         pzText,
+    int           direction )
+{
+    tOptionLoadMode mode = OPTION_LOAD_UNCOOKED;
+    tOptionValue     valu;
+
+    char* pzName = ++pzText;
+    char* pcNulPoint;
+
+    while (ISNAMECHAR( *pzText ))  pzText++;
+    pcNulPoint = pzText;
+    valu.valType = OPARG_TYPE_STRING;
+
+    switch (*pzText) {
+    case ' ':
+    case '\t':
+        pzText = parseAttributes( pOpts, pzText, &mode, &valu );
+        if (*pzText == '>')
+            break;
+        if (*pzText != '/')
+            return NULL;
+
+    case '/':
+        if (pzText[1] != '>')
+            return NULL;
+        *pzText = NUL;
+        pzText += 2;
+        loadOptionLine( pOpts, pOS, pzName, direction, OPTION_LOAD_KEEP );
+        return pzText;
+
+    case '>':
+        break;
+
+    default:
+        pzText = strchr( pzText, '>');
+        if (pzText != NULL)
+            pzText++;
+        return pzText;
+    }
+
+    /*
+     *  If we are here, we have a value.  Separate the name from the
+     *  value for a moment.
+     */
+    *pcNulPoint = NUL;
+
+    /*
+     *  Find the end of the option text and NUL terminate it
+     */
+    {
+        char   z[64], *pz = z;
+        size_t len = strlen(pzName) + 4;
+        if (len > sizeof(z))
+            pz = AGALOC(len, "scan name");
+
+        sprintf( pz, "</%s>", pzName );
+        *pzText = ' ';
+        pzText = strstr( pzText, pz );
+        if (pz != z) free(pz);
+
+        if (pzText == NULL)
+            return pzText;
+
+        *pzText = NUL;
+
+        pzText += len-1;
+    }
+
+    /*
+     *  Rejoin the name and value for parsing by "loadOptionLine()".
+     */
+    *(pcNulPoint++) = ' ';
+
+    /*
+     *  "pzName" points to what looks like text for one option/configurable.
+     *  It is NUL terminated.  Process it.
+     */
+    loadOptionLine( pOpts, pOS, pzName, direction, mode );
+
+    return pzText;
+}
+
+
+/*  internalFileLoad
+ *
+ *  Load a configuration file.  This may be invoked either from
+ *  scanning the "homerc" list, or from a specific file request.
+ *  (see "optionFileLoad()", the implementation for --load-opts)
+ */
+LOCAL void
+internalFileLoad( tOptions* pOpts )
+{
+    int     idx;
+    int     inc = DIRECTION_PRESET;
+    char    zFileName[ MAXPATHLEN+1 ];
+
+    if (pOpts->papzHomeList == NULL)
+        return;
+
+    /*
+     *  Find the last RC entry (highest priority entry)
+     */
+    for (idx = 0; pOpts->papzHomeList[ idx+1 ] != NULL; ++idx)  ;
+
+    /*
+     *  For every path in the home list, ...  *TWICE* We start at the last
+     *  (highest priority) entry, work our way down to the lowest priority,
+     *  handling the immediate options.
+     *  Then we go back up, doing the normal options.
+     */
+    for (;;) {
+        struct stat StatBuf;
+        cch_t*  pzPath;
+
+        /*
+         *  IF we've reached the bottom end, change direction
+         */
+        if (idx < 0) {
+            inc = DIRECTION_PROCESS;
+            idx = 0;
+        }
+
+        pzPath = pOpts->papzHomeList[ idx ];
+
+        /*
+         *  IF we've reached the top end, bail out
+         */
+        if (pzPath == NULL)
+            break;
+
+        idx += inc;
+
+        if (! optionMakePath( zFileName, sizeof( zFileName ),
+                              pzPath, pOpts->pzProgPath ))
+            continue;
+
+        /*
+         *  IF the file name we constructed is a directory,
+         *  THEN append the Resource Configuration file name
+         *  ELSE we must have the complete file name
+         */
+        if (stat( zFileName, &StatBuf ) != 0)
+            continue; /* bogus name - skip the home list entry */
+
+        if (S_ISDIR( StatBuf.st_mode )) {
+            size_t len = strlen( zFileName );
+            char* pz;
+
+            if (len + 1 + strlen( pOpts->pzRcName ) >= sizeof( zFileName ))
+                continue;
+
+            pz = zFileName + len;
+            if (pz[-1] != '/')
+                *(pz++) = '/';
+            strcpy( pz, pOpts->pzRcName );
+        }
+
+        filePreset( pOpts, zFileName, inc );
+
+        /*
+         *  IF we are now to skip config files AND we are presetting,
+         *  THEN change direction.  We must go the other way.
+         */
+        if (SKIP_RC_FILES(pOpts) && PRESETTING(inc)) {
+            idx -= inc;  /* go back and reprocess current file */
+            inc =  DIRECTION_PROCESS;
+        }
+    } /* For every path in the home list, ... */
+}
+
+
+/*=export_func optionFileLoad
+ *
+ * what: Load the locatable config files, in order
+ *
+ * arg:  + tOptions*   + pOpts  + program options descriptor +
+ * arg:  + const char* + pzProg + program name +
+ *
+ * ret_type:  int
+ * ret_desc:  0 -> SUCCESS, -1 -> FAILURE
+ *
+ * doc:
+ *
+ * This function looks in all the specified directories for a configuration
+ * file ("rc" file or "ini" file) and processes any found twice.  The first
+ * time through, they are processed in reverse order (last file first).  At
+ * that time, only "immediate action" configurables are processed.  For
+ * example, if the last named file specifies not processing any more
+ * configuration files, then no more configuration files will be processed.
+ * Such an option in the @strong{first} named directory will have no effect.
+ *
+ * Once the immediate action configurables have been handled, then the
+ * directories are handled in normal, forward order.  In that way, later
+ * config files can override the settings of earlier config files.
+ *
+ * See the AutoOpts documentation for a thorough discussion of the
+ * config file format.
+ *
+ * Configuration files not found or not decipherable are simply ignored.
+ *
+ * err:  Returns the value, "-1" if the program options descriptor
+ *       is out of date or indecipherable.  Otherwise, the value "0" will
+ *       always be returned.
+=*/
+int
+optionFileLoad( tOptions* pOpts, const char* pzProgram )
+{
+    if (! SUCCESSFUL( validateOptionsStruct( pOpts, pzProgram )))
+        return -1;
+
+    pOpts->pzProgName = pzProgram;
+    internalFileLoad( pOpts );
+    return 0;
+}
+
+
+/*=export_func  optionLoadOpt
+ * private:
+ *
+ * what:  Load an option rc/ini file
+ * arg:   + tOptions* + pOpts    + program options descriptor +
+ * arg:   + tOptDesc* + pOptDesc + the descriptor for this arg +
+ *
+ * doc:
+ *  Processes the options found in the file named with pOptDesc->pzLastArg.
+=*/
+void
+optionLoadOpt( tOptions* pOpts, tOptDesc* pOptDesc )
+{
+    /*
+     *  IF the option is not being disabled,
+     *  THEN load the file.  There must be a file.
+     *  (If it is being disabled, then the disablement processing
+     *  already took place.  It must be done to suppress preloading
+     *  of ini/rc files.)
+     */
+    if (! DISABLED_OPT( pOptDesc )) {
+        struct stat sb;
+        if (stat( pOptDesc->pzLastArg, &sb ) != 0) {
+            if ((pOpts->fOptSet & OPTPROC_ERRSTOP) == 0)
+                return;
+
+            fprintf( stderr, zFSErrOptLoad, errno, strerror( errno ),
+                     pOptDesc->pzLastArg );
+            (*pOpts->pUsageProc)( pOpts, EXIT_FAILURE );
+            /* NOT REACHED */
+        }
+
+        if (! S_ISREG( sb.st_mode )) {
+            if ((pOpts->fOptSet & OPTPROC_ERRSTOP) == 0)
+                return;
+
+            fprintf( stderr, zNotFile, pOptDesc->pzLastArg );
+            (*pOpts->pUsageProc)( pOpts, EXIT_FAILURE );
+            /* NOT REACHED */
+        }
+
+        filePreset(pOpts, pOptDesc->pzLastArg, DIRECTION_CALLED);
+    }
+}
+
+
+/*  parseAttributes
+ *
+ *  Parse the various attributes of an XML-styled config file entry
+ */
+LOCAL char*
+parseAttributes(
+    tOptions*           pOpts,
+    char*               pzText,
+    tOptionLoadMode*    pMode,
+    tOptionValue*       pType )
+{
+    size_t lenLoadType = strlen( zLoadType );
+    size_t lenKeyWords = strlen( zKeyWords );
+    size_t lenSetMem   = strlen( zSetMembers );
+
+    do  {
+        switch (*pzText) {
+        case '/': pType->valType = OPARG_TYPE_NONE;
+        case '>': return pzText;
+
+        default:
+        case NUL: return NULL;
+
+        case ' ':
+        case '\t':
+        case '\n':
+        case '\f':
+        case '\r':
+        case '\v':
+            break;
+        }
+
+        while (isspace( *++pzText ))   ;
+
+        if (strncmp( pzText, zLoadType, lenLoadType ) == 0) {
+            pzText = parseValueType( pzText+lenLoadType, pType );
+            continue;
+        }
+
+        if (strncmp( pzText, zKeyWords, lenKeyWords ) == 0) {
+            pzText = parseKeyWordType( pOpts, pzText+lenKeyWords, pType );
+            continue;
+        }
+
+        if (strncmp( pzText, zSetMembers, lenSetMem ) == 0) {
+            pzText = parseSetMemType( pOpts, pzText+lenSetMem, pType );
+            continue;
+        }
+
+        pzText = parseLoadMode( pzText, pMode );
+    } while (pzText != NULL);
+
+    return pzText;
+}
+
+
+/*  parseKeyWordType
+ *
+ *  "pzText" points to the character after "words=".
+ *  What should follow is a name of a keyword (enumeration) list.
+ */
+static char*
+parseKeyWordType(
+    tOptions*     pOpts,
+    char*         pzText,
+    tOptionValue* pType )
+{
+    return skipUnknown( pzText );
+}
+
+
+/*  parseLoadMode
+ *
+ *  "pzText" points to some name character.  We check for "cooked" or
+ *  "uncooked" or "keep".  This function should handle any attribute
+ *  that does not have an associated value.
+ */
+static char*
+parseLoadMode(
+    char*               pzText,
+    tOptionLoadMode*    pMode )
+{
+    {
+        size_t len = strlen(zLoadCooked);
+        if (strncmp( pzText, zLoadCooked, len ) == 0) {
+            if (  (pzText[len] == '>')
+               || (pzText[len] == '/')
+               || isspace(pzText[len])) {
+                *pMode = OPTION_LOAD_COOKED;
+                return pzText + len;
+            }
+            goto unknown;
+        }
+    }
+
+    {
+        size_t len = strlen(zLoadUncooked);
+        if (strncmp( pzText, zLoadUncooked, len ) == 0) {
+            if (  (pzText[len] == '>')
+               || (pzText[len] == '/')
+               || isspace(pzText[len])) {
+                *pMode = OPTION_LOAD_UNCOOKED;
+                return pzText + len;
+            }
+            goto unknown;
+        }
+    }
+
+    {
+        size_t len = strlen(zLoadKeep);
+        if (strncmp( pzText, zLoadKeep, len ) == 0) {
+            if (  (pzText[len] == '>')
+               || (pzText[len] == '/')
+               || isspace(pzText[len])) {
+                *pMode = OPTION_LOAD_KEEP;
+                return pzText + len;
+            }
+            goto unknown;
+        }
+    }
+
+  unknown:
+    return skipUnknown( pzText );
+}
+
+
+/*  parseSetMemType
+ *
+ *  "pzText" points to the character after "members="
+ *  What should follow is a name of a "set membership".
+ *  A collection of bit flags.
+ */
+static char*
+parseSetMemType(
+    tOptions*     pOpts,
+    char*         pzText,
+    tOptionValue* pType )
+{
+    return skipUnknown( pzText );
+}
+
+
+/*  parseValueType
+ *
+ *  "pzText" points to the character after "type="
+ */
+static char*
+parseValueType(
+    char*         pzText,
+    tOptionValue* pType )
+{
+    {
+        size_t len = strlen(zLtypeString);
+        if (strncmp( pzText, zLtypeString, len ) == 0) {
+            if ((pzText[len] == '>') || isspace(pzText[len])) {
+                pType->valType = OPARG_TYPE_STRING;
+                return pzText + len;
+            }
+            goto unknown;
+        }
+    }
+
+    {
+        size_t len = strlen(zLtypeInteger);
+        if (strncmp( pzText, zLtypeInteger, len ) == 0) {
+            if ((pzText[len] == '>') || isspace(pzText[len])) {
+                pType->valType = OPARG_TYPE_NUMERIC;
+                return pzText + len;
+            }
+            goto unknown;
+        }
+    }
+
+    {
+        size_t len = strlen(zLtypeBool);
+        if (strncmp( pzText, zLtypeBool, len ) == 0) {
+            if ((pzText[len] == '>') || isspace(pzText[len])) {
+                pType->valType = OPARG_TYPE_BOOLEAN;
+                return pzText + len;
+            }
+            goto unknown;
+        }
+    }
+
+    {
+        size_t len = strlen(zLtypeKeyword);
+        if (strncmp( pzText, zLtypeKeyword, len ) == 0) {
+            if ((pzText[len] == '>') || isspace(pzText[len])) {
+                pType->valType = OPARG_TYPE_ENUMERATION;
+                return pzText + len;
+            }
+            goto unknown;
+        }
+    }
+
+    {
+        size_t len = strlen(zLtypeSetMembership);
+        if (strncmp( pzText, zLtypeSetMembership, len ) == 0) {
+            if ((pzText[len] == '>') || isspace(pzText[len])) {
+                pType->valType = OPARG_TYPE_MEMBERSHIP;
+                return pzText + len;
+            }
+            goto unknown;
+        }
+    }
+
+    {
+        size_t len = strlen(zLtypeNest);
+        if (strncmp( pzText, zLtypeNest, len ) == 0) {
+            if ((pzText[len] == '>') || isspace(pzText[len])) {
+                pType->valType = OPARG_TYPE_HIERARCHY;
+                return pzText + len;
+            }
+            goto unknown;
+        }
+    }
+
+  unknown:
+    pType->valType = OPARG_TYPE_NONE;
+    return skipUnknown( pzText );
+}
+
+
+/*  skipUnknown
+ *
+ *  Skip over some unknown attribute
+ */
+static char*
+skipUnknown( char* pzText )
+{
+    for (;; pzText++) {
+        if (isspace( *pzText ))  return pzText;
+        switch (*pzText) {
+        case NUL: return NULL;
+        case '/':
+        case '>': return pzText;
+        }
+    }
+}
+
+
+/*  validateOptionsStruct
+ *
+ *  Make sure the option descriptor is there and that we understand it.
+ *  This should be called from any user entry point where one needs to
+ *  worry about validity.  (Some entry points are free to assume that
+ *  the call is not the first to the library and, thus, that this has
+ *  already been called.)
+ */
+LOCAL tSuccess
+validateOptionsStruct( tOptions* pOpts, const char* pzProgram )
+{
+    if (pOpts == NULL) {
+        fputs( zAO_Bad, stderr );
+        exit( EXIT_FAILURE );
+    }
+
+    /*
+     *  IF the client has enabled translation and the translation procedure
+     *  is available, then go do it.
+     */
+    if (  ((pOpts->fOptSet & OPTPROC_TRANSLATE) != 0)
+       && (pOpts->pTransProc != 0) ) {
+        (*pOpts->pTransProc)();
+        pOpts->fOptSet &= ~OPTPROC_TRANSLATE;
+    }
+
+    /*
+     *  IF the struct version is not the current, and also
+     *     either too large (?!) or too small,
+     *  THEN emit error message and fail-exit
+     */
+    if (  ( pOpts->structVersion  != OPTIONS_STRUCT_VERSION  )
+       && (  (pOpts->structVersion > OPTIONS_STRUCT_VERSION  )
+          || (pOpts->structVersion < OPTIONS_MINIMUM_VERSION )
+       )  )  {
+
+        fprintf( stderr, zAO_Err, pOpts->origArgVect[0],
+                 NUM_TO_VER( pOpts->structVersion ));
+        if (pOpts->structVersion > OPTIONS_STRUCT_VERSION )
+            fputs( zAO_Big, stderr );
+        else
+            fputs( zAO_Sml, stderr );
+
+        return FAILURE;
+    }
+
+    /*
+     *  If the program name hasn't been set, then set the name and the path
+     *  and the set of equivalent characters.
+     */
+    if (pOpts->pzProgName == NULL) {
+        const char* pz = strrchr( pzProgram, '/' );
+
+        if (pz == NULL)
+             pOpts->pzProgName = pzProgram;
+        else pOpts->pzProgName = pz+1;
+
+        pOpts->pzProgPath = pzProgram;
+
+        /*
+         *  when comparing long names, these are equivalent
+         */
+        strequate( zSepChars );
+    }
+
+    return SUCCESS;
+}
+
+
+/**
+ * Local Variables:
+ * mode: C
+ * c-file-style: "stroustrup"
+ * tab-width: 4
+ * indent-tabs-mode: nil
+ * End:
+ * end of autoopts/configfile.c */
diff --git a/sntp/libopts/cook.c b/sntp/libopts/cook.c
new file mode 100644 (file)
index 0000000..763f697
--- /dev/null
@@ -0,0 +1,355 @@
+
+/*
+ *  $Id: cook.c,v 4.3 2006/03/25 19:24:56 bkorb Exp $
+ *  Time-stamp:      "2005-05-20 13:58:56 bkorb"
+ *
+ *  This file contains the routines that deal with processing quoted strings
+ *  into an internal format.
+ */
+
+/*
+ *  Automated Options copyright 1992-2006 Bruce Korb
+ *
+ *  Automated Options is free software.
+ *  You may redistribute it and/or modify it under the terms of the
+ *  GNU General Public License, as published by the Free Software
+ *  Foundation; either version 2, or (at your option) any later version.
+ *
+ *  Automated Options is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with Automated Options.  See the file "COPYING".  If not,
+ *  write to:  The Free Software Foundation, Inc.,
+ *             51 Franklin Street, Fifth Floor,
+ *             Boston, MA  02110-1301, USA.
+ *
+ * As a special exception, Bruce Korb gives permission for additional
+ * uses of the text contained in his release of AutoOpts.
+ *
+ * The exception is that, if you link the AutoOpts library with other
+ * files to produce an executable, this does not by itself cause the
+ * resulting executable to be covered by the GNU General Public License.
+ * Your use of that executable is in no way restricted on account of
+ * linking the AutoOpts library code into it.
+ *
+ * This exception does not however invalidate any other reasons why
+ * the executable file might be covered by the GNU General Public License.
+ *
+ * This exception applies only to the code released by Bruce Korb under
+ * the name AutoOpts.  If you copy code from other sources under the
+ * General Public License into a copy of AutoOpts, as the General Public
+ * License permits, the exception does not apply to the code that you add
+ * in this way.  To avoid misleading anyone as to the status of such
+ * modified files, you must delete this exception notice from them.
+ *
+ * If you write modifications of your own for AutoOpts, it is your choice
+ * whether to permit this exception to apply to your modifications.
+ * If you do not wish that, delete this exception notice.
+ */
+
+/* = = = START-STATIC-FORWARD = = = */
+/* static forward declarations maintained by :mkfwd */
+/* = = = END-STATIC-FORWARD = = = */
+
+/*=export_func  ao_string_cook_escape_char
+ * private:
+ *
+ * what:  escape-process a string fragment
+ * arg:   + const char* + pzScan  + points to character after the escape +
+ * arg:   + char*       + pRes    + Where to put the result byte +
+ * arg:   + char        + nl_ch   + replacement char if scanned char is \n +
+ *
+ * ret-type: unsigned int
+ * ret-desc: The number of bytes consumed processing the escaped character.
+ *
+ * doc:
+ *
+ *  This function converts "t" into "\t" and all your other favorite
+ *  escapes, including numeric ones:  hex and ocatal, too.
+ *  The returned result tells the caller how far to advance the
+ *  scan pointer (passed in).  The default is to just pass through the
+ *  escaped character and advance the scan by one.
+ *
+ *  Some applications need to keep an escaped newline, others need to
+ *  suppress it.  This is accomplished by supplying a '\n' replacement
+ *  character that is different from \n, if need be.  For example, use
+ *  0x7F and never emit a 0x7F.
+ *
+ * err:  @code{NULL} is returned if the string(s) is/are mal-formed.
+=*/
+unsigned int
+ao_string_cook_escape_char( const char* pzIn, char* pRes, char nl )
+{
+    unsigned int  res = 1;
+
+    switch (*pRes = *pzIn++) {
+    case NUL:         /* NUL - end of input string */
+        return 0;
+    case '\r':
+        if (*pzIn != '\n')
+            return 1;
+        res++;
+        /* FALLTHROUGH */
+    case '\n':        /* NL  - emit newline        */
+        *pRes = nl;
+        return res;
+
+    case 'a': *pRes = '\a'; break;
+    case 'b': *pRes = '\b'; break;
+    case 'f': *pRes = '\f'; break;
+    case 'n': *pRes = '\n'; break;
+    case 'r': *pRes = '\r'; break;
+    case 't': *pRes = '\t'; break;
+    case 'v': *pRes = '\v'; break;
+
+    case 'x':         /* HEX Escape       */
+        if (isxdigit( *pzIn ))  {
+            unsigned int  val;
+            unsigned char ch = *pzIn++;
+
+            if ((ch >= 'A') && (ch <= 'F'))
+                val = 10 + (ch - 'A');
+            else if ((ch >= 'a') && (ch <= 'f'))
+                val = 10 + (ch - 'a');
+            else val = ch - '0';
+
+            ch = *pzIn;
+
+            if (! isxdigit( ch )) {
+                *pRes = val;
+                res   = 2;
+                break;
+            }
+            val <<= 4;
+            if ((ch >= 'A') && (ch <= 'F'))
+                val += 10 + (ch - 'A');
+            else if ((ch >= 'a') && (ch <= 'f'))
+                val += 10 + (ch - 'a');
+            else val += ch - '0';
+
+            res = 3;
+            *pRes = val;
+        }
+        break;
+
+    default:
+        /*
+         *  IF the character copied was an octal digit,
+         *  THEN set the output character to an octal value
+         */
+        if (isdigit( *pRes ) && (*pRes < '8'))  {
+            unsigned int  val = *pRes - '0';
+            unsigned char ch  = *pzIn++;
+
+            /*
+             *  IF the second character is *not* an octal digit,
+             *  THEN save the value and bail
+             */
+            if ((ch < '0') || (ch > '7')) {
+                *pRes = val;
+                break;
+            }
+
+            val = (val<<3) + (ch - '0');
+            ch  = *pzIn;
+            res = 2;
+
+            /*
+             *  IF the THIRD character is *not* an octal digit,
+             *  THEN save the value and bail
+             */
+            if ((ch < '0') || (ch > '7')) {
+                *pRes = val;
+                break;
+            }
+
+            /*
+             *  IF the new value would not be too large,
+             *  THEN add on the third and last character value
+             */
+            if ((val<<3) < 0xFF) {
+                val = (val<<3) + (ch - '0');
+                res = 3;
+            }
+
+            *pRes = val;
+            break;
+        }
+    }
+
+    return res;
+}
+
+
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ *
+ *  A quoted string has been found.
+ *  Find the end of it and compress any escape sequences.
+ */
+/*=export_func  ao_string_cook
+ * private:
+ *
+ * what:  concatenate and escape-process strings
+ * arg:   + char* + pzScan     + The *MODIFIABLE* input buffer +
+ * arg:   + int*  + pLineCt    + The (possibly NULL) pointer to a line count +
+ *
+ * ret-type: char*
+ * ret-desc: The address of the text following the processed strings.
+ *           The return value is NULL if the strings are ill-formed.
+ *
+ * doc:
+ *
+ *  A series of one or more quoted strings are concatenated together.
+ *  If they are quoted with double quotes (@code{"}), then backslash
+ *  escapes are processed per the C programming language.  If they are
+ *  single quote strings, then the backslashes are honored only when they
+ *  precede another backslash or a single quote character.
+ *
+ * err:  @code{NULL} is returned if the string(s) is/are mal-formed.
+=*/
+char*
+ao_string_cook( char* pzScan, int* pLineCt )
+{
+    int   l = 0;
+    char  q = *pzScan;
+
+    /*
+     *  It is a quoted string.  Process the escape sequence characters
+     *  (in the set "abfnrtv") and make sure we find a closing quote.
+     */
+    char* pzD = pzScan++;
+    char* pzS = pzScan;
+
+    if (pLineCt == NULL)
+        pLineCt = &l;
+
+    for (;;) {
+        /*
+         *  IF the next character is the quote character, THEN we may end the
+         *  string.  We end it unless the next non-blank character *after* the
+         *  string happens to also be a quote.  If it is, then we will change
+         *  our quote character to the new quote character and continue
+         *  condensing text.
+         */
+        while (*pzS == q) {
+            *pzD = NUL; /* This is probably the end of the line */
+            pzS++;
+
+        scan_for_quote:
+            while (isspace(*pzS))
+                if (*(pzS++) == '\n')
+                    (*pLineCt)++;
+
+            /*
+             *  IF the next character is a quote character,
+             *  THEN we will concatenate the strings.
+             */
+            switch (*pzS) {
+            case '"':
+            case '\'':
+                break;
+
+            case '/':
+                /*
+                 *  Allow for a comment embedded in the concatenated string.
+                 */
+                switch (pzS[1]) {
+                default:  return NULL;
+                case '/':
+                    /*
+                     *  Skip to end of line
+                     */
+                    pzS = strchr( pzS, '\n' );
+                    if (pzS == NULL)
+                        return NULL;
+                    (*pLineCt)++;
+                    break;
+
+                case '*':
+                {
+                    char* p = strstr( pzS+2, "*/" );
+                    /*
+                     *  Skip to terminating star slash
+                     */
+                    if (p == NULL)
+                        return NULL;
+                    while (pzS < p) {
+                        if (*(pzS++) == '\n')
+                            (*pLineCt)++;
+                    }
+
+                    pzS = p + 2;
+                }
+                }
+                goto scan_for_quote;
+
+            default:
+                /*
+                 *  The next non-whitespace character is not a quote.
+                 *  The series of quoted strings has come to an end.
+                 */
+                return pzS;
+            }
+
+            q = *(pzS++);  /* assign new quote character and advance scan */
+        }
+
+        /*
+         *  We are inside a quoted string.  Copy text.
+         */
+        switch (*(pzD++) = *(pzS++)) {
+        case NUL:
+            return NULL;
+
+        case '\n':
+            (*pLineCt)++;
+            break;
+
+        case '\\':
+            /*
+             *  IF we are escaping a new line,
+             *  THEN drop both the escape and the newline from
+             *       the result string.
+             */
+            if (*pzS == '\n') {
+                pzS++;
+                pzD--;
+                (*pLineCt)++;
+            }
+
+            /*
+             *  ELSE IF the quote character is '"' or '`',
+             *  THEN we do the full escape character processing
+             */
+            else if (q != '\'') {
+                int ct = ao_string_cook_escape_char( pzS, pzD-1, '\n' );
+                if (ct == 0)
+                    return NULL;
+
+                pzS += ct;
+            }     /* if (q != '\'')                  */
+
+            /*
+             *  OTHERWISE, we only process "\\", "\'" and "\#" sequences.
+             *  The latter only to easily hide preprocessing directives.
+             */
+            else switch (*pzS) {
+            case '\\':
+            case '\'':
+            case '#':
+                pzD[-1] = *pzS++;
+            }
+        }     /* switch (*(pzD++) = *(pzS++))    */
+    }         /* for (;;)                        */
+}
+/*
+ * Local Variables:
+ * mode: C
+ * c-file-style: "stroustrup"
+ * tab-width: 4
+ * indent-tabs-mode: nil
+ * End:
+ * end of autoopts/cook.c */
diff --git a/sntp/libopts/enumeration.c b/sntp/libopts/enumeration.c
new file mode 100644 (file)
index 0000000..86f7cc0
--- /dev/null
@@ -0,0 +1,485 @@
+
+/*
+ *  $Id: enumeration.c,v 4.9 2006/03/25 19:24:56 bkorb Exp $
+ * Time-stamp:      "2005-12-09 06:37:15 bkorb"
+ *
+ *   Automated Options Paged Usage module.
+ *
+ *  This routine will run run-on options through a pager so the
+ *  user may examine, print or edit them at their leisure.
+ */
+
+/*
+ *  Automated Options copyright 1992-2006 Bruce Korb
+ *
+ *  Automated Options is free software.
+ *  You may redistribute it and/or modify it under the terms of the
+ *  GNU General Public License, as published by the Free Software
+ *  Foundation; either version 2, or (at your option) any later version.
+ *
+ *  Automated Options is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with Automated Options.  See the file "COPYING".  If not,
+ *  write to:  The Free Software Foundation, Inc.,
+ *             51 Franklin Street, Fifth Floor,
+ *             Boston, MA  02110-1301, USA.
+ *
+ * As a special exception, Bruce Korb gives permission for additional
+ * uses of the text contained in his release of AutoOpts.
+ *
+ * The exception is that, if you link the AutoOpts library with other
+ * files to produce an executable, this does not by itself cause the
+ * resulting executable to be covered by the GNU General Public License.
+ * Your use of that executable is in no way restricted on account of
+ * linking the AutoOpts library code into it.
+ *
+ * This exception does not however invalidate any other reasons why
+ * the executable file might be covered by the GNU General Public License.
+ *
+ * This exception applies only to the code released by Bruce Korb under
+ * the name AutoOpts.  If you copy code from other sources under the
+ * General Public License into a copy of AutoOpts, as the General Public
+ * License permits, the exception does not apply to the code that you add
+ * in this way.  To avoid misleading anyone as to the status of such
+ * modified files, you must delete this exception notice from them.
+ *
+ * If you write modifications of your own for AutoOpts, it is your choice
+ * whether to permit this exception to apply to your modifications.
+ * If you do not wish that, delete this exception notice.
+ */
+
+tSCC*  pz_enum_err_fmt;
+
+/* = = = START-STATIC-FORWARD = = = */
+/* static forward declarations maintained by :mkfwd */
+static void
+enumError(
+    tOptions* pOpts,
+    tOptDesc* pOD,
+    tCC**     paz_names,
+    int       name_ct );
+
+static uintptr_t
+findName(
+    tCC*          pzName,
+    tOptions*     pOpts,
+    tOptDesc*     pOD,
+    tCC**         paz_names,
+    unsigned int  name_ct );
+/* = = = END-STATIC-FORWARD = = = */
+
+static void
+enumError(
+    tOptions* pOpts,
+    tOptDesc* pOD,
+    tCC**     paz_names,
+    int       name_ct )
+{
+    size_t max_len = 0;
+    size_t ttl_len = 0;
+
+    if (pOpts != NULL)
+        fprintf( option_usage_fp, pz_enum_err_fmt,
+                 pOpts->pzProgName, pOD->pzLastArg );
+
+    fprintf( option_usage_fp, zValidKeys, pOD->pz_Name );
+
+    if (**paz_names == 0x7F) {
+        paz_names++;
+        name_ct--;
+    }
+
+    /*
+     *  Figure out the maximum length of any name, plus the total length
+     *  of all the names.
+     */
+    {
+        tCC** paz = paz_names;
+        int   ct  = name_ct;
+
+        do  {
+            size_t len = strlen( *(paz++) ) + 1;
+            if (len > max_len)
+                max_len = len;
+            ttl_len += len;
+        } while (--ct > 0);
+    }
+
+    /*
+     *  IF any one entry is about 1/2 line or longer, print one per line
+     */
+    if (max_len > 35) {
+        do  {
+            fprintf( option_usage_fp, "  %s\n", *(paz_names++) );
+        } while (--name_ct > 0);
+    }
+
+    /*
+     *  ELSE IF they all fit on one line, then do so.
+     */
+    else if (ttl_len < 76) {
+        fputc( ' ', option_usage_fp );
+        do  {
+            fputc( ' ', option_usage_fp );
+            fputs( *(paz_names++), option_usage_fp );
+        } while (--name_ct > 0);
+        fputc( '\n', option_usage_fp );
+    }
+
+    /*
+     *  Otherwise, columnize the output
+     */
+    else {
+        int   ent_no = 0;
+        char  zFmt[16];  /* format for all-but-last entries on a line */
+
+        sprintf( zFmt, "%%-%ds", max_len );
+        max_len = 78 / max_len; /* max_len is now max entries on a line */
+        fputs( "  ", option_usage_fp );
+
+        /*
+         *  Loop through all but the last entry
+         */
+        while (--name_ct > 0) {
+            if (++ent_no == max_len) {
+                /*
+                 *  Last entry on a line.  Start next line, too.
+                 */
+                fprintf( option_usage_fp, "%s\n  ", *(paz_names++) );
+                ent_no = 0;
+            }
+
+            else
+                fprintf( option_usage_fp, zFmt, *(paz_names++) );
+        }
+        fprintf( option_usage_fp, "%s\n", *paz_names );
+    }
+
+    /*
+     *  IF we do not have a pOpts pointer, then this output is being requested
+     *  by the usage procedure.  Let's not re-invoke it recursively.
+     */
+    if (pOpts != NULL)
+        (*(pOpts->pUsageProc))( pOpts, EXIT_FAILURE );
+    if (OPTST_GET_ARGTYPE(pOD->fOptState) == OPARG_TYPE_MEMBERSHIP)
+        fputs( zSetMemberSettings, option_usage_fp );
+}
+
+
+static uintptr_t
+findName(
+    tCC*          pzName,
+    tOptions*     pOpts,
+    tOptDesc*     pOD,
+    tCC**         paz_names,
+    unsigned int  name_ct )
+{
+    uintptr_t     res = name_ct;
+    size_t        len = strlen( (char*)pzName );
+    uintptr_t     idx;
+    /*
+     *  Look for an exact match, but remember any partial matches.
+     *  Multiple partial matches means we have an ambiguous match.
+     */
+    for (idx = 0; idx < name_ct; idx++) {
+        if (strncmp( (char*)paz_names[idx], (char*)pzName, len ) == 0) {
+            if (paz_names[idx][len] == NUL)
+                return idx;  /* full match */
+
+            if (res != name_ct) {
+                pz_enum_err_fmt = zAmbigKey;
+                option_usage_fp = stderr;
+                enumError( pOpts, pOD, paz_names, name_ct );
+            }
+            res = idx; /* save partial match */
+        }
+    }
+
+    /*
+     *  no partial match -> error
+     */
+    if (res == name_ct) {
+        pz_enum_err_fmt = zNoKey;
+        option_usage_fp = stderr;
+        enumError( pOpts, pOD, paz_names, name_ct );
+    }
+
+    /*
+     *  Return the matching index as a char* pointer.
+     *  The result gets stashed in a char* pointer, so it will have to fit.
+     */
+    return res;
+}
+
+
+/*=export_func  optionKeywordName
+ * what:  Convert between enumeration values and strings
+ * private:
+ *
+ * arg:   tOptDesc*,     pOD,       enumeration option description
+ * arg:   unsigned int,  enum_val,  the enumeration value to map
+ *
+ * ret_type:  const char*
+ * ret_desc:  the enumeration name from const memory
+ *
+ * doc:   This converts an enumeration value into the matching string.
+=*/
+const char*
+optionKeywordName(
+    tOptDesc*     pOD,
+    unsigned int  enum_val )
+{
+    tOptDesc od;
+
+    od.pzLastArg = (const char*)(uintptr_t)enum_val;
+    (*(pOD->pOptProc))( (void*)(2UL), &od );
+    return od.pzLastArg;
+}
+
+
+/*=export_func  optionEnumerationVal
+ * what:  Convert from a string to an enumeration value
+ * private:
+ *
+ * arg:   tOptions*,     pOpts,     the program options descriptor
+ * arg:   tOptDesc*,     pOD,       enumeration option description
+ * arg:   const char**,  paz_names, list of enumeration names
+ * arg:   unsigned int,  name_ct,   number of names in list
+ *
+ * ret_type:  char*
+ * ret_desc:  the enumeration value cast as a char*
+ *
+ * doc:   This converts the pzLastArg string from the option description
+ *        into the index corresponding to an entry in the name list.
+ *        This will match the generated enumeration value.
+ *        Full matches are always accepted.  Partial matches are accepted
+ *        if there is only one partial match.
+=*/
+char*
+optionEnumerationVal(
+    tOptions*     pOpts,
+    tOptDesc*     pOD,
+    tCC**         paz_names,
+    unsigned int  name_ct )
+{
+    /*
+     *  IF the program option descriptor pointer is invalid,
+     *  then it is some sort of special request.
+     */
+    switch ((uintptr_t)pOpts) {
+    case 0UL:
+        /*
+         *  print the list of enumeration names.
+         */
+        enumError( pOpts, pOD, paz_names, name_ct );
+        return (char*)0UL;
+
+    case 1UL:
+    {
+        unsigned int ix = (uintptr_t)(pOD->pzLastArg);
+        /*
+         *  print the name string.
+         */
+        if (ix >= name_ct)
+            printf( "INVALID-%d", ix );
+        else
+            fputs( paz_names[ ix ], stdout );
+        return (char*)0UL;
+    }
+    case 2UL:
+    {
+        tSCC zInval[] = "*INVALID*";
+        unsigned int ix = (uintptr_t)(pOD->pzLastArg);
+        /*
+         *  Replace the enumeration value with the name string.
+         */
+        if (ix >= name_ct)
+            return (char*)zInval;
+
+        return (char*)paz_names[ ix ];
+    }
+    default:
+        break;
+    }
+
+    return (char*)findName( pOD->pzLastArg, pOpts, pOD, paz_names, name_ct );
+}
+
+
+/*=export_func  optionSetMembers
+ * what:  Convert between bit flag values and strings
+ * private:
+ *
+ * arg:   tOptions*,     pOpts,     the program options descriptor
+ * arg:   tOptDesc*,     pOD,       enumeration option description
+ * arg:   const char**,  paz_names, list of enumeration names
+ * arg:   unsigned int,  name_ct,   number of names in list
+ *
+ * doc:   This converts the pzLastArg string from the option description
+ *        into the index corresponding to an entry in the name list.
+ *        This will match the generated enumeration value.
+ *        Full matches are always accepted.  Partial matches are accepted
+ *        if there is only one partial match.
+=*/
+void
+optionSetMembers(
+    tOptions*     pOpts,
+    tOptDesc*     pOD,
+    tCC**         paz_names,
+    unsigned int  name_ct )
+{
+    /*
+     *  IF the program option descriptor pointer is invalid,
+     *  then it is some sort of special request.
+     */
+    switch ((uintptr_t)pOpts) {
+    case 0UL:
+        /*
+         *  print the list of enumeration names.
+         */
+        enumError( pOpts, pOD, paz_names, name_ct );
+        return;
+
+    case 1UL:
+    {
+        /*
+         *  print the name string.
+         */
+        uintptr_t bits = (uintptr_t)pOD->optCookie;
+        uintptr_t res  = 0;
+        size_t    len  = 0;
+
+        while (bits != 0) {
+            if (bits & 1) {
+                if (len++ > 0) fputs( " | ", stdout );
+                fputs( paz_names[ res ], stdout );
+            }
+            if (++res >= name_ct) break;
+            bits >>= 1;
+        }
+        return;
+    }
+
+    case 2UL:
+    {
+        char*     pz;
+        uintptr_t bits = (uintptr_t)pOD->optCookie;
+        uintptr_t res  = 0;
+        size_t    len  = 0;
+
+        /*
+         *  Replace the enumeration value with the name string.
+         *  First, determine the needed length, then allocate and fill in.
+         */
+        while (bits != 0) {
+            if (bits & 1)
+                len += strlen( paz_names[ res ]) + 8;
+            if (++res >= name_ct) break;
+            bits >>= 1;
+        }
+
+        pOD->pzLastArg = pz = malloc( len );
+        /*
+         *  Start by clearing all the bits.  We want to turn off any defaults
+         *  because we will be restoring to current state, not adding to
+         *  the default set of bits.
+         */
+        strcpy( pz, "none" );
+        pz += 4;
+        bits = (uintptr_t)pOD->optCookie;
+        res = 0;
+        while (bits != 0) {
+            if (bits & 1) {
+                strcpy( pz, " + " );
+                strcpy( pz+3, paz_names[ res ]);
+                pz += strlen( paz_names[ res ]) + 3;
+            }
+            if (++res >= name_ct) break;
+            bits >>= 1;
+        }
+        return;
+    }
+
+    default:
+        break;
+    }
+
+    {
+        tCC*      pzArg = pOD->pzLastArg;
+        uintptr_t res;
+        if ((pzArg == NULL) || (*pzArg == NUL)) {
+            pOD->optCookie = (void*)0;
+            return;
+        }
+
+        res = (uintptr_t)pOD->optCookie;
+        for (;;) {
+            tSCC zSpn[] = " ,|+\t\r\f\n";
+            int  iv, len;
+
+            pzArg += strspn( pzArg, zSpn );
+            iv = (*pzArg == '!');
+            if (iv)
+                pzArg += strspn( pzArg+1, zSpn ) + 1;
+
+            len = strcspn( pzArg, zSpn );
+            if (len == 0)
+                break;
+
+            if ((len == 3) && (strncmp( pzArg, zAll, 3 ) == 0)) {
+                if (iv)
+                     res = 0;
+                else res = ~0;
+            }
+            else if ((len == 4) && (strncmp( pzArg, zNone, 4 ) == 0)) {
+                if (! iv)
+                    res = 0;
+            }
+            else do {
+                char* pz;
+                uintptr_t bit = strtoul( pzArg, &pz, 0 );
+
+                if (pz != pzArg + len) {
+                    char z[ AO_NAME_SIZE ];
+                    tCC* p;
+                    if (*pz != NUL) {
+                        if (len >= AO_NAME_LIMIT)
+                            break;
+                        strncpy( z, pzArg, len );
+                        z[len] = NUL;
+                        p = z;
+                    } else {
+                        p = pzArg;
+                    }
+
+                    bit = 1UL << findName(p, pOpts, pOD, paz_names, name_ct);
+                }
+                if (iv)
+                     res &= ~bit;
+                else res |= bit;
+            } while (0);
+
+            if (pzArg[len] == NUL)
+                break;
+            pzArg += len + 1;
+        }
+        if (name_ct < (8 * sizeof( uintptr_t ))) {
+            res &= (1UL << name_ct) - 1UL;
+        }
+
+        pOD->optCookie = (void*)res;
+    }
+}
+
+/*
+ * Local Variables:
+ * mode: C
+ * c-file-style: "stroustrup"
+ * tab-width: 4
+ * indent-tabs-mode: nil
+ * End:
+ * end of autoopts/enumeration.c */
diff --git a/sntp/libopts/environment.c b/sntp/libopts/environment.c
new file mode 100644 (file)
index 0000000..285b229
--- /dev/null
@@ -0,0 +1,261 @@
+
+/*
+ *  $Id: environment.c,v 4.8 2006/03/25 19:24:56 bkorb Exp $
+ * Time-stamp:      "2005-10-29 13:23:59 bkorb"
+ *
+ *  This file contains all of the routines that must be linked into
+ *  an executable to use the generated option processing.  The optional
+ *  routines are in separately compiled modules so that they will not
+ *  necessarily be linked in.
+ */
+
+/*
+ *  Automated Options copyright 1992-2006 Bruce Korb
+ *
+ *  Automated Options is free software.
+ *  You may redistribute it and/or modify it under the terms of the
+ *  GNU General Public License, as published by the Free Software
+ *  Foundation; either version 2, or (at your option) any later version.
+ *
+ *  Automated Options is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with Automated Options.  See the file "COPYING".  If not,
+ *  write to:  The Free Software Foundation, Inc.,
+ *             51 Franklin Street, Fifth Floor,
+ *             Boston, MA  02110-1301, USA.
+ *
+ * As a special exception, Bruce Korb gives permission for additional
+ * uses of the text contained in his release of AutoOpts.
+ *
+ * The exception is that, if you link the AutoOpts library with other
+ * files to produce an executable, this does not by itself cause the
+ * resulting executable to be covered by the GNU General Public License.
+ * Your use of that executable is in no way restricted on account of
+ * linking the AutoOpts library code into it.
+ *
+ * This exception does not however invalidate any other reasons why
+ * the executable file might be covered by the GNU General Public License.
+ *
+ * This exception applies only to the code released by Bruce Korb under
+ * the name AutoOpts.  If you copy code from other sources under the
+ * General Public License into a copy of AutoOpts, as the General Public
+ * License permits, the exception does not apply to the code that you add
+ * in this way.  To avoid misleading anyone as to the status of such
+ * modified files, you must delete this exception notice from them.
+ *
+ * If you write modifications of your own for AutoOpts, it is your choice
+ * whether to permit this exception to apply to your modifications.
+ * If you do not wish that, delete this exception notice.
+ */
+
+/* = = = START-STATIC-FORWARD = = = */
+/* static forward declarations maintained by :mkfwd */
+/* = = = END-STATIC-FORWARD = = = */
+
+/*
+ *  doPrognameEnv - check for preset values from the ${PROGNAME}
+ *  environment variable.  This is accomplished by parsing the text into
+ *  tokens, temporarily replacing the arg vector and calling
+ *  doImmediateOpts and/or doRegularOpts.
+ */
+LOCAL void
+doPrognameEnv( tOptions* pOpts, teEnvPresetType type )
+{
+    const char*   pczOptStr = getenv( pOpts->pzPROGNAME );
+    token_list_t* pTL;
+    int           sv_argc;
+    tAoUI         sv_flag;
+    char**        sv_argv;
+
+    /*
+     *  IF there is no such environment variable
+     *   *or* there is, but we are doing immediate opts and there are
+     *        no immediate opts to do (--help inside $PROGNAME is silly,
+     *        but --no-load-defs is not, so that is marked)
+     *  THEN bail out now.  (
+     */
+    if (  (pczOptStr == NULL)
+       || (  (type == ENV_IMM)
+          && ((pOpts->fOptSet & OPTPROC_HAS_IMMED) == 0)  )  )
+        return;
+
+    /*
+     *  Tokenize the string.  If there's nothing of interest, we'll bail
+     *  here immediately.
+     */
+    pTL = ao_string_tokenize( pczOptStr );
+    if (pTL == NULL)
+        return;
+
+    /*
+     *  Substitute our $PROGNAME argument list for the real one
+     */
+    sv_argc = pOpts->origArgCt;
+    sv_argv = pOpts->origArgVect;
+    sv_flag = pOpts->fOptSet;
+
+    /*
+     *  We add a bogus pointer to the start of the list.  The program name
+     *  has already been pulled from "argv", so it won't get dereferenced.
+     *  The option scanning code will skip the "program name" at the start
+     *  of this list of tokens, so we accommodate this way ....
+     */
+    pOpts->origArgVect = (char**)(pTL->tkn_list - 1);
+    pOpts->origArgCt   = pTL->tkn_ct   + 1;
+    pOpts->fOptSet    &= ~OPTPROC_ERRSTOP;
+
+    pOpts->curOptIdx   = 1;
+    pOpts->pzCurOpt    = NULL;
+
+    switch (type) {
+    case ENV_IMM:
+        /*
+         *  We know the OPTPROC_HAS_IMMED bit is set.
+         */
+        (void)doImmediateOpts( pOpts );
+        break;
+
+    case ENV_NON_IMM:
+        (void)doRegularOpts( pOpts );
+        break;
+
+    default:
+        /*
+         *  Only to immediate opts if the OPTPROC_HAS_IMMED bit is set.
+         */
+        if (pOpts->fOptSet & OPTPROC_HAS_IMMED) {
+            (void)doImmediateOpts( pOpts );
+            pOpts->curOptIdx = 1;
+            pOpts->pzCurOpt  = NULL;
+        }
+        (void)doRegularOpts( pOpts );
+        break;
+    }
+
+    /*
+     *  Free up the temporary arg vector and restore the original program args.
+     */
+    free( pTL );
+    pOpts->origArgVect = sv_argv;
+    pOpts->origArgCt   = sv_argc;
+    pOpts->fOptSet     = sv_flag;
+}
+
+
+/*
+ *  doEnvPresets - check for preset values from the envrionment
+ *  This routine should process in all, immediate or normal modes....
+ */
+LOCAL void
+doEnvPresets( tOptions* pOpts, teEnvPresetType type )
+{
+    int        ct;
+    tOptState  st;
+    char*      pzFlagName;
+    size_t     spaceLeft;
+    char       zEnvName[ AO_NAME_SIZE ];
+
+    /*
+     *  Finally, see if we are to look at the environment
+     *  variables for initial values.
+     */
+    if ((pOpts->fOptSet & OPTPROC_ENVIRON) == 0)
+        return;
+
+    doPrognameEnv( pOpts, type );
+
+    ct  = pOpts->presetOptCt;
+    st.pOD = pOpts->pOptDesc;
+
+    pzFlagName = zEnvName
+        + snprintf( zEnvName, sizeof( zEnvName ), "%s_", pOpts->pzPROGNAME );
+    spaceLeft = AO_NAME_SIZE - (pzFlagName - zEnvName) - 1;
+
+    for (;ct-- > 0; st.pOD++) {
+        /*
+         *  If presetting is disallowed, then skip this entry
+         */
+        if (  ((st.pOD->fOptState & OPTST_NO_INIT) != 0)
+           || (st.pOD->optEquivIndex != NO_EQUIVALENT)  )
+            continue;
+
+        /*
+         *  IF there is no such environment variable,
+         *  THEN skip this entry, too.
+         */
+        if (strlen( st.pOD->pz_NAME ) >= spaceLeft)
+            continue;
+
+        /*
+         *  Set up the option state
+         */
+        strcpy( pzFlagName, st.pOD->pz_NAME );
+        st.pzOptArg = getenv( zEnvName );
+        if (st.pzOptArg == NULL)
+            continue;
+        st.flags    = OPTST_PRESET | st.pOD->fOptState;
+        st.optType  = TOPT_UNDEFINED;
+
+        if (  (st.pOD->pz_DisablePfx != NULL)
+           && (streqvcmp( st.pzOptArg, st.pOD->pz_DisablePfx ) == 0)) {
+            st.flags |= OPTST_DISABLED;
+            st.pzOptArg = NULL;
+        }
+
+        switch (type) {
+        case ENV_IMM:
+            /*
+             *  Process only immediate actions
+             */
+            if (DO_IMMEDIATELY(st.flags))
+                break;
+            continue;
+
+        case ENV_NON_IMM:
+            /*
+             *  Process only NON immediate actions
+             */
+            if (DO_NORMALLY(st.flags) || DO_SECOND_TIME(st.flags))
+                break;
+            continue;
+
+        default: /* process everything */
+            break;
+        }
+
+        /*
+         *  Make sure the option value string is persistent and consistent.
+         *  This may be a memory leak, but we cannot do anything about it.
+         *
+         *  The interpretation of the option value depends
+         *  on the type of value argument the option takes
+         */
+        if (st.pzOptArg != NULL) {
+            if (OPTST_GET_ARGTYPE(st.pOD->fOptState) == OPARG_TYPE_NONE) {
+                st.pzOptArg = NULL;
+            } else if (  (st.pOD->fOptState & OPTST_ARG_OPTIONAL)
+                      && (*st.pzOptArg == NUL)) {
+                    st.pzOptArg = NULL;
+            } else if (*st.pzOptArg == NUL) {
+                st.pzOptArg = zNil;
+            } else {
+                AGDUPSTR( st.pzOptArg, st.pzOptArg, "option argument" );
+            }
+        }
+
+        handleOption( pOpts, &st );
+    }
+}
+
+/*
+ * Local Variables:
+ * mode: C
+ * c-file-style: "stroustrup"
+ * tab-width: 4
+ * indent-tabs-mode: nil
+ * End:
+ * end of autoopts/environment.c */
diff --git a/sntp/libopts/genshell.c b/sntp/libopts/genshell.c
new file mode 100644 (file)
index 0000000..5b321cf
--- /dev/null
@@ -0,0 +1,301 @@
+/*   -*- buffer-read-only: t -*- vi: set ro:
+ *  
+ *  DO NOT EDIT THIS FILE   (genshell.c)
+ *  
+ *  It has been AutoGen-ed  Sunday April  9, 2006 at 11:49:19 AM PDT
+ *  From the definitions    genshell.def
+ *  and the template file   options
+ */
+
+#define OPTION_CODE_COMPILE 1
+#include "genshell.h"
+
+#ifdef  __cplusplus
+extern "C" {
+#endif
+tSCC zCopyright[] =
+       "genshellopt copyright (c) 1999-2006 Bruce Korb, all rights reserved";
+tSCC zCopyrightNotice[] =
+       "genshellopt is free software; you can redistribute it and/or\n\
+modify it under the terms of the GNU Lesser General Public\n\
+License as published by the Free Software Foundation; either\n\
+version 2.1 of the License, or (at your option) any later version.\n\n\
+genshellopt is distributed in the hope that it will be useful,\n\
+but WITHOUT ANY WARRANTY; without even the implied warranty of\n\
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n\
+Lesser General Public License for more details.\n\n\
+You should have received a copy of the GNU Lesser General Public\n\
+License along with genshellopt.  If not, write to:\n\
+\tThe Free Software Foundation, Inc.,\n\
+\t51 Franklin Street, Fifth Floor\n\
+\tBoston, MA  02110-1301, USA.";
+extern tUsageProc genshelloptUsage;
+
+#ifndef NULL
+#  define NULL 0
+#endif
+#ifndef EXIT_SUCCESS
+#  define  EXIT_SUCCESS 0
+#endif
+#ifndef EXIT_FAILURE
+#  define  EXIT_FAILURE 1
+#endif
+/*
+ *  Script option description:
+ */
+tSCC    zScriptText[] =
+        "Output Script File";
+tSCC    zScript_NAME[]             = "SCRIPT";
+tSCC    zScript_Name[]             = "script";
+#define SCRIPT_FLAGS       (OPTST_DISABLED \
+       | OPTST_SET_ARGTYPE(OPARG_TYPE_STRING))
+
+/*
+ *  Shell option description:
+ */
+tSCC    zShellText[] =
+        "Shell name (follows \"#!\" magic)";
+tSCC    zShell_NAME[]              = "SHELL";
+tSCC    zNotShell_Name[]           = "no-shell";
+tSCC    zNotShell_Pfx[]            = "no";
+#define zShell_Name                  (zNotShell_Name + 3)
+#define SHELL_FLAGS       (OPTST_INITENABLED \
+       | OPTST_SET_ARGTYPE(OPARG_TYPE_STRING))
+
+/*
+ *  Help/More_Help/Version option descriptions:
+ */
+tSCC zHelpText[]       = "Display usage information and exit";
+tSCC zHelp_Name[]      = "help";
+
+tSCC zMore_HelpText[]  = "Extended usage information passed thru pager";
+tSCC zMore_Help_Name[] = "more-help";
+
+tSCC zVersionText[]    = "Output version information and exit";
+tSCC zVersion_Name[]   = "version";
+/*
+ *  Declare option callback procedures
+ */
+extern tOptProc
+    optionPagedUsage, optionPrintVersion;
+static tOptProc
+    doUsageOpt;
+
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ *
+ *  Define the Genshellopt Option Descriptions.
+ */
+static tOptDesc optDesc[ OPTION_CT ] = {
+  {  /* entry idx, value */ 0, VALUE_OPT_SCRIPT,
+     /* equiv idx, value */ 0, VALUE_OPT_SCRIPT,
+     /* equivalenced to  */ NO_EQUIVALENT,
+     /* min, max, act ct */ 0, 1, 0,
+     /* opt state flags  */ SCRIPT_FLAGS, 0,
+     /* last opt argumnt */ NULL,
+     /* arg list/cookie  */ NULL,
+     /* must/cannot opts */ NULL, NULL,
+     /* option proc      */ NULL,
+     /* desc, NAME, name */ zScriptText, zScript_NAME, zScript_Name,
+     /* disablement strs */ NULL, NULL },
+
+  {  /* entry idx, value */ 1, VALUE_OPT_SHELL,
+     /* equiv idx, value */ 1, VALUE_OPT_SHELL,
+     /* equivalenced to  */ NO_EQUIVALENT,
+     /* min, max, act ct */ 0, 1, 0,
+     /* opt state flags  */ SHELL_FLAGS, 0,
+     /* last opt argumnt */ NULL,
+     /* arg list/cookie  */ NULL,
+     /* must/cannot opts */ NULL, NULL,
+     /* option proc      */ NULL,
+     /* desc, NAME, name */ zShellText, zShell_NAME, zShell_Name,
+     /* disablement strs */ zNotShell_Name, zNotShell_Pfx },
+
+  {  /* entry idx, value */ INDEX_OPT_VERSION, VALUE_OPT_VERSION,
+     /* equiv idx value  */ NO_EQUIVALENT, 0,
+     /* equivalenced to  */ NO_EQUIVALENT,
+     /* min, max, act ct */ 0, 1, 0,
+     /* opt state flags  */ OPTST_SET_ARGTYPE(OPARG_TYPE_STRING)
+                          | OPTST_ARG_OPTIONAL, 0,
+     /* last opt argumnt */ NULL,
+     /* arg list/cookie  */ NULL,
+     /* must/cannot opts */ NULL, NULL,
+     /* option proc      */ optionPrintVersion,
+     /* desc, NAME, name */ zVersionText, NULL, zVersion_Name,
+     /* disablement strs */ NULL, NULL },
+
+  {  /* entry idx, value */ INDEX_OPT_HELP, VALUE_OPT_HELP,
+     /* equiv idx value  */ NO_EQUIVALENT, 0,
+     /* equivalenced to  */ NO_EQUIVALENT,
+     /* min, max, act ct */ 0, 1, 0,
+     /* opt state flags  */ OPTST_IMM, 0,
+     /* last opt argumnt */ NULL,
+     /* arg list/cookie  */ NULL,
+     /* must/cannot opts */ NULL, NULL,
+     /* option proc      */ doUsageOpt,
+     /* desc, NAME, name */ zHelpText, NULL, zHelp_Name,
+     /* disablement strs */ NULL, NULL },
+
+  {  /* entry idx, value */ INDEX_OPT_MORE_HELP, VALUE_OPT_MORE_HELP,
+     /* equiv idx value  */ NO_EQUIVALENT, 0,
+     /* equivalenced to  */ NO_EQUIVALENT,
+     /* min, max, act ct */ 0, 1, 0,
+     /* opt state flags  */ OPTST_IMM, 0,
+     /* last opt argumnt */ NULL,
+     /* arg list/cookie  */ NULL,
+     /* must/cannot opts */ NULL,  NULL,
+     /* option proc      */ optionPagedUsage,
+     /* desc, NAME, name */ zMore_HelpText, NULL, zMore_Help_Name,
+     /* disablement strs */ NULL, NULL }
+};
+
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ *
+ *  Define the Genshellopt Option Environment
+ */
+tSCC   zPROGNAME[]   = "GENSHELLOPT";
+tSCC   zUsageTitle[] =
+"genshellopt - Generate Shell Option Processing Script - Ver. 1\n\
+USAGE:  %s [ -<flag> [<val>] | --<name>[{=| }<val>] ]...\n";
+#define zRcName     NULL
+#define apzHomeList NULL
+
+tSCC   zBugsAddr[]    = "autogen-users@lists.sf.net";
+tSCC   zExplain[]     = "\n\
+Note that `shell' is only useful if the output file does not already\n\
+exist.  If it does, then the shell name and optional first argument\n\
+will be extracted from the script file.\n";
+tSCC    zDetail[]     = "\n\
+If the script file already exists and contains Automated Option Processing\n\
+text, the second line of the file through the ending tag will be replaced\n\
+by the newly generated text.  The first `#!' line will be regenerated.\n";
+tSCC    zFullVersion[] = GENSHELLOPT_FULL_VERSION;
+/* extracted from optcode near line 321 */
+
+#if defined(ENABLE_NLS)
+# define OPTPROC_BASE OPTPROC_TRANSLATE
+  static tOptionXlateProc translate_option_strings;
+#else
+# define OPTPROC_BASE OPTPROC_NONE
+# define translate_option_strings NULL
+#endif /* ENABLE_NLS */
+
+tOptions genshelloptOptions = {
+    OPTIONS_STRUCT_VERSION,
+    0, NULL,                    /* original argc + argv    */
+    ( OPTPROC_BASE
+    + OPTPROC_ERRSTOP
+    + OPTPROC_SHORTOPT
+    + OPTPROC_LONGOPT
+    + OPTPROC_NO_REQ_OPT
+    + OPTPROC_NEGATIONS
+    + OPTPROC_NO_ARGS ),
+    0, NULL,                    /* current option index, current option */
+    NULL,         NULL,         zPROGNAME,
+    zRcName,      zCopyright,   zCopyrightNotice,
+    zFullVersion, apzHomeList,  zUsageTitle,
+    zExplain,     zDetail,      optDesc,
+    zBugsAddr,                  /* address to send bugs to */
+    NULL, NULL,                 /* extensions/saved state  */
+    genshelloptUsage,       /* usage procedure */
+    translate_option_strings,   /* translation procedure */
+    /*
+     *  Indexes to special options
+     */
+    { INDEX_OPT_MORE_HELP,
+       0 /* no option state saving */,
+      NO_EQUIVALENT /* index of '-#' option */,
+      NO_EQUIVALENT /* index of default opt */
+    },
+    OPTION_CT, 2 /* user option count */
+};
+
+/*
+ *  Create the static procedure(s) declared above.
+ */
+static void
+doUsageOpt(
+    tOptions*   pOptions,
+    tOptDesc*   pOptDesc )
+{
+    USAGE( EXIT_SUCCESS );
+}
+/* extracted from optcode near line 418 */
+
+#if ENABLE_NLS
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+#include <autoopts/usage-txt.h>
+
+static char*
+AO_gettext( const char* pz )
+{
+    char* pzRes;
+    if (pz == NULL)
+        return NULL;
+    pzRes = _(pz);
+    if (pzRes == pz)
+        return pzRes;
+    pzRes = strdup( pzRes );
+    if (pzRes == NULL) {
+        fputs( _("No memory for duping translated strings\n"), stderr );
+        exit( EXIT_FAILURE );
+    }
+    return pzRes;
+}
+
+/*
+ *  This invokes the translation code (e.g. gettext(3)).
+ */
+static void
+translate_option_strings( void )
+{
+    /*
+     *  Guard against re-translation.  It won't work.  The strings will have
+     *  been changed by the first pass through this code.  One shot only.
+     */
+    if (option_usage_text.field_ct == 0)
+        return;
+    /*
+     *  Do the translations.  The first pointer follows the field count field.
+     *  The field count field is the size of a pointer.
+     */
+    {
+        char** ppz = (char**)(void*)&(option_usage_text);
+        int    ix  = option_usage_text.field_ct;
+
+        do {
+            ppz++;
+            *ppz = AO_gettext(*ppz);
+        } while (--ix > 0);
+    }
+    option_usage_text.field_ct = 0;
+
+    {
+        tOptDesc* pOD = genshelloptOptions.pOptDesc;
+        int       ix  = genshelloptOptions.optCt;
+
+        for (;;) {
+            pOD->pzText           = AO_gettext(pOD->pzText);
+            pOD->pz_NAME          = AO_gettext(pOD->pz_NAME);
+            pOD->pz_Name          = AO_gettext(pOD->pz_Name);
+            pOD->pz_DisableName   = AO_gettext(pOD->pz_DisableName);
+            pOD->pz_DisablePfx    = AO_gettext(pOD->pz_DisablePfx);
+            if (--ix <= 0)
+                break;
+            pOD++;
+        }
+    }
+    genshelloptOptions.pzCopyright   = AO_gettext(genshelloptOptions.pzCopyright);
+    genshelloptOptions.pzCopyNotice  = AO_gettext(genshelloptOptions.pzCopyNotice);
+    genshelloptOptions.pzFullVersion = AO_gettext(genshelloptOptions.pzFullVersion);
+    genshelloptOptions.pzUsageTitle  = AO_gettext(genshelloptOptions.pzUsageTitle);
+    genshelloptOptions.pzExplain     = AO_gettext(genshelloptOptions.pzExplain);
+    genshelloptOptions.pzDetail      = AO_gettext(genshelloptOptions.pzDetail);
+}
+
+#endif /* ENABLE_NLS */
+
+#ifdef  __cplusplus
+}
+#endif
diff --git a/sntp/libopts/genshell.h b/sntp/libopts/genshell.h
new file mode 100644 (file)
index 0000000..621fbc4
--- /dev/null
@@ -0,0 +1,142 @@
+/*   -*- buffer-read-only: t -*- vi: set ro:
+ *  
+ *  DO NOT EDIT THIS FILE   (genshell.h)
+ *  
+ *  It has been AutoGen-ed  Sunday April  9, 2006 at 11:49:19 AM PDT
+ *  From the definitions    genshell.def
+ *  and the template file   options
+ */
+/*
+ *  This file contains the programmatic interface to the Automated
+ *  Options generated for the genshellopt program.
+ *  These macros are documented in the AutoGen info file in the
+ *  "AutoOpts" chapter.  Please refer to that doc for usage help.
+ */
+#ifndef AUTOOPTS_GENSHELL_H_GUARD
+#define AUTOOPTS_GENSHELL_H_GUARD
+
+/*
+ * genshellopt copyright 1999-2006 Bruce Korb - all rights reserved
+ *
+ * genshellopt is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ * 
+ * genshellopt is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ * 
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with genshellopt.  If not, write to:
+ *     The Free Software Foundation, Inc.,
+ *     51 Franklin Street, Fifth Floor
+ *     Boston, MA  02110-1301, USA.
+ */
+#include <autoopts/options.h>
+
+/*
+ *  Ensure that the library used for compiling this generated header is at
+ *  least as new as the version current when the header template was released
+ *  (not counting patch version increments).  Also ensure that the oldest
+ *  tolerable version is at least as old as what was current when the header
+ *  template was released.
+ */
+#define AO_TEMPLATE_VERSION 110592
+#if (AO_TEMPLATE_VERSION < OPTIONS_MINIMUM_VERSION) \
+ || (AO_TEMPLATE_VERSION > OPTIONS_STRUCT_VERSION)
+# error option template version mismatches autoopts/options.h header
+#endif
+
+/*
+ *  Enumeration of each option:
+ */
+typedef enum {
+        INDEX_OPT_SCRIPT           =  0,
+        INDEX_OPT_SHELL            =  1,
+        INDEX_OPT_VERSION          = 2,
+        INDEX_OPT_HELP             = 3,
+        INDEX_OPT_MORE_HELP        = 4
+} teOptIndex;
+
+#define OPTION_CT    5
+#define GENSHELLOPT_VERSION       "1"
+#define GENSHELLOPT_FULL_VERSION  "genshellopt - Generate Shell Option Processing Script - Ver. 1"
+
+/*
+ *  Interface defines for all options.  Replace "n" with
+ *  the UPPER_CASED option name (as in the teOptIndex
+ *  enumeration above).  e.g. HAVE_OPT( SCRIPT )
+ */
+#define        DESC(n) genshelloptOptions.pOptDesc[INDEX_OPT_ ## n]
+#define     HAVE_OPT(n) (! UNUSED_OPT(& DESC(n)))
+#define      OPT_ARG(n) (DESC(n).pzLastArg)
+#define    STATE_OPT(n) (DESC(n).fOptState & OPTST_SET_MASK)
+#define    COUNT_OPT(n) (DESC(n).optOccCt)
+#define    ISSEL_OPT(n) (SELECTED_OPT(&DESC(n)))
+#define ISUNUSED_OPT(n) (UNUSED_OPT(& DESC(n)))
+#define  ENABLED_OPT(n) (! DISABLED_OPT(& DESC(n)))
+#define  STACKCT_OPT(n) (((tArgList*)(DESC(n).optCookie))->useCt)
+#define STACKLST_OPT(n) (((tArgList*)(DESC(n).optCookie))->apzArgs)
+#define    CLEAR_OPT(n) STMTS( \
+                DESC(n).fOptState &= OPTST_PERSISTENT;   \
+                if ( (DESC(n).fOptState & OPTST_INITENABLED) == 0) \
+                    DESC(n).fOptState |= OPTST_DISABLED; \
+                DESC(n).optCookie = NULL )
+
+/*
+ *  Interface defines for specific options.
+ */
+#define VALUE_OPT_SCRIPT         'o'
+#define VALUE_OPT_SHELL          's'
+
+#define VALUE_OPT_VERSION       'v'
+#define VALUE_OPT_HELP          '?'
+#define VALUE_OPT_MORE_HELP     '!'
+/*
+ *  Interface defines not associated with particular options
+ */
+#define ERRSKIP_OPTERR  STMTS( genshelloptOptions.fOptSet &= ~OPTPROC_ERRSTOP )
+#define ERRSTOP_OPTERR  STMTS( genshelloptOptions.fOptSet |= OPTPROC_ERRSTOP )
+#define RESTART_OPT(n)  STMTS( \
+                genshelloptOptions.curOptIdx = (n); \
+                genshelloptOptions.pzCurOpt  = NULL )
+#define START_OPT       RESTART_OPT(1)
+#define USAGE(c)        (*genshelloptOptions.pUsageProc)( &genshelloptOptions, c )
+/* extracted from opthead near line 289 */
+
+/* * * * * *
+ *
+ *  Declare the genshellopt option descriptor.
+ */
+#ifdef  __cplusplus
+extern "C" {
+#endif
+
+extern tOptions   genshelloptOptions;
+
+#ifndef _
+#  if ENABLE_NLS
+#    include <stdio.h>
+     static inline char* aoGetsText( const char* pz ) {
+         if (pz == NULL) return NULL;
+         return (char*)gettext( pz );
+     }
+#    define _(s)  aoGetsText(s)
+#  else  /* ENABLE_NLS */
+#    define _(s)  s
+#  endif /* ENABLE_NLS */
+#endif
+
+#ifdef  __cplusplus
+}
+#endif
+#endif /* AUTOOPTS_GENSHELL_H_GUARD */
+/*
+ * Local Variables:
+ * Mode: C
+ * c-file-style: "stroustrup"
+ * indent-tabs-mode: nil
+ * End:
+ * options.h ends here */
diff --git a/sntp/libopts/libopts.c b/sntp/libopts/libopts.c
new file mode 100644 (file)
index 0000000..960a492
--- /dev/null
@@ -0,0 +1,30 @@
+#define AUTOOPTS_INTERNAL
+#include "compat/compat.h"
+#define HAVE_LIBSNPRINTFV
+#include "autoopts/options.h"
+#include "autoopts/usage-txt.h"
+#include "genshell.h"
+#include "autoopts.h"
+#include "proto.h"
+#include "autoopts.c"
+#include "boolean.c"
+#include "configfile.c"
+#include "cook.c"
+#include "enumeration.c"
+#include "environment.c"
+#include "genshell.c"
+#include "load.c"
+#include "makeshell.c"
+#include "nested.c"
+#include "numeric.c"
+#include "pgusage.c"
+#include "putshell.c"
+#include "restore.c"
+#include "save.c"
+#include "sort.c"
+#include "stack.c"
+#include "streqvcmp.c"
+#include "text_mmap.c"
+#include "tokenize.c"
+#include "usage.c"
+#include "version.c"
diff --git a/sntp/libopts/load.c b/sntp/libopts/load.c
new file mode 100644 (file)
index 0000000..e5a2b8f
--- /dev/null
@@ -0,0 +1,520 @@
+
+/*
+ *  $Id: load.c,v 4.18 2006/03/25 19:24:56 bkorb Exp $
+ *  Time-stamp:      "2005-10-29 14:45:36 bkorb"
+ *
+ *  This file contains the routines that deal with processing text strings
+ *  for options, either from a NUL-terminated string passed in or from an
+ *  rc/ini file.
+ */
+
+/*
+ *  Automated Options copyright 1992-2006 Bruce Korb
+ *
+ *  Automated Options is free software.
+ *  You may redistribute it and/or modify it under the terms of the
+ *  GNU General Public License, as published by the Free Software
+ *  Foundation; either version 2, or (at your option) any later version.
+ *
+ *  Automated Options is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with Automated Options.  See the file "COPYING".  If not,
+ *  write to:  The Free Software Foundation, Inc.,
+ *             51 Franklin Street, Fifth Floor,
+ *             Boston, MA  02110-1301, USA.
+ *
+ * As a special exception, Bruce Korb gives permission for additional
+ * uses of the text contained in his release of AutoOpts.
+ *
+ * The exception is that, if you link the AutoOpts library with other
+ * files to produce an executable, this does not by itself cause the
+ * resulting executable to be covered by the GNU General Public License.
+ * Your use of that executable is in no way restricted on account of
+ * linking the AutoOpts library code into it.
+ *
+ * This exception does not however invalidate any other reasons why
+ * the executable file might be covered by the GNU General Public License.
+ *
+ * This exception applies only to the code released by Bruce Korb under
+ * the name AutoOpts.  If you copy code from other sources under the
+ * General Public License into a copy of AutoOpts, as the General Public
+ * License permits, the exception does not apply to the code that you add
+ * in this way.  To avoid misleading anyone as to the status of such
+ * modified files, you must delete this exception notice from them.
+ *
+ * If you write modifications of your own for AutoOpts, it is your choice
+ * whether to permit this exception to apply to your modifications.
+ * If you do not wish that, delete this exception notice.
+ */
+
+/* = = = START-STATIC-FORWARD = = = */
+/* static forward declarations maintained by :mkfwd */
+static ag_bool
+insertProgramPath(
+    char*   pzBuf,
+    int     bufSize,
+    tCC*    pzName,
+    tCC*    pzProgPath );
+
+static ag_bool
+insertEnvVal(
+    char*   pzBuf,
+    int     bufSize,
+    tCC*    pzName,
+    tCC*    pzProgPath );
+
+static char*
+assembleArgValue( char* pzTxt, tOptionLoadMode mode );
+/* = = = END-STATIC-FORWARD = = = */
+
+/*=export_func  optionMakePath
+ * private:
+ *
+ * what:  translate and construct a path
+ * arg:   + char*       + pzBuf      + The result buffer +
+ * arg:   + int         + bufSize    + The size of this buffer +
+ * arg:   + const char* + pzName     + The input name +
+ * arg:   + const char* + pzProgPath + The full path of the current program +
+ *
+ * ret-type: ag_bool
+ * ret-desc: AG_TRUE if the name was handled, otherwise AG_FALSE.
+ *           If the name does not start with ``$'', then it is handled
+ *           simply by copying the input name to the output buffer and
+ *           resolving the name with either @code{canonicalize_file_name(3GLIBC)}
+ *           or @code{realpath(3C)}.
+ *
+ * doc:
+ *
+ *  This routine will copy the @code{pzName} input name into the @code{pzBuf}
+ *  output buffer, carefully not exceeding @code{bufSize} bytes.  If the
+ *  first character of the input name is a @code{'$'} character, then there
+ *  is special handling:
+ *  @*
+ *  @code{$$} is replaced with the directory name of the @code{pzProgPath},
+ *  searching @code{$PATH} if necessary.
+ *  @*
+ *  @code{$NAME} is replaced by the contents of the @code{NAME} environment
+ *  variable.
+ *
+ *  Please note: both @code{$$} and @code{$NAME} must be at the start of the
+ *     @code{pzName} string and must either be the entire string or be followed
+ *     by the @code{'/'} character.
+ *
+ * err:  @code{AG_FALSE} is returned if:
+ *       @*
+ *       @bullet{} The input name exceeds @code{bufSize} bytes.
+ *       @*
+ *       @bullet{} @code{$$} or @code{$NAME} is not the full string and
+ *                 the next character is not '/'.
+ *       @*
+ *       @bullet{} @code{NAME} is not a known environment variable
+ *       @*
+ *       @bullet{} @code{canonicalize_file_name} or @code{realpath} return
+ *                 errors (cannot resolve the resulting path).
+=*/
+ag_bool
+optionMakePath(
+    char*   pzBuf,
+    int     bufSize,
+    tCC*    pzName,
+    tCC*    pzProgPath )
+{
+    ag_bool res = AG_TRUE;
+
+    if (bufSize <= strlen( pzName ))
+        return AG_FALSE;
+
+    /*
+     *  IF not an environment variable, just copy the data
+     */
+    if (*pzName != '$') {
+        tCC*  pzS = pzName;
+        char* pzD = pzBuf;
+        int   ct  = bufSize;
+
+        for (;;) {
+            if ( (*(pzD++) = *(pzS++)) == NUL)
+                break;
+            if (--ct <= 0)
+                return AG_FALSE;
+        }
+    }
+
+    /*
+     *  IF the name starts with "$$", then it must be "$$" or
+     *  it must start with "$$/".  In either event, replace the "$$"
+     *  with the path to the executable and append a "/" character.
+     */
+    else if (pzName[1] == '$')
+        res = insertProgramPath( pzBuf, bufSize, pzName, pzProgPath );
+    else
+        res = insertEnvVal( pzBuf, bufSize, pzName, pzProgPath );
+
+    if (! res)
+        return AG_FALSE;
+
+#if defined(HAVE_CANONICALIZE_FILE_NAME)
+    {
+        char* pz = canonicalize_file_name(pzBuf);
+        if (pz == NULL)
+            return AG_FALSE;
+        if (strlen(pz) < bufSize)
+            strcpy(pzBuf, pz);
+        free(pz);
+    }
+
+#elif defined(HAVE_REALPATH)
+    {
+        char z[ PATH_MAX+1 ];
+
+        if (realpath( pzBuf, z ) == NULL)
+            return AG_FALSE;
+
+        if (strlen(z) < bufSize)
+            strcpy( pzBuf, z );
+    }
+#endif
+
+    return AG_TRUE;
+}
+
+
+static ag_bool
+insertProgramPath(
+    char*   pzBuf,
+    int     bufSize,
+    tCC*    pzName,
+    tCC*    pzProgPath )
+{
+    tCC*    pzPath;
+    tCC*    pz;
+    int     skip = 2;
+
+    switch (pzName[2]) {
+    case '/':
+        skip = 3;
+    case NUL:
+        break;
+    default:
+        return AG_FALSE;
+    }
+
+    /*
+     *  See if the path is included in the program name.
+     *  If it is, we're done.  Otherwise, we have to hunt
+     *  for the program using "pathfind".
+     */
+    if (strchr( pzProgPath, '/' ) != NULL)
+        pzPath = pzProgPath;
+    else {
+        pzPath = pathfind( getenv( "PATH" ), (char*)pzProgPath, "rx" );
+
+        if (pzPath == NULL)
+            return AG_FALSE;
+    }
+
+    pz = strrchr( pzPath, '/' );
+
+    /*
+     *  IF we cannot find a directory name separator,
+     *  THEN we do not have a path name to our executable file.
+     */
+    if (pz == NULL)
+        return AG_FALSE;
+
+    pzName += skip;
+
+    /*
+     *  Concatenate the file name to the end of the executable path.
+     *  The result may be either a file or a directory.
+     */
+    if ((pz - pzPath)+1 + strlen(pzName) >= bufSize)
+        return AG_FALSE;
+
+    memcpy( pzBuf, pzPath, (pz - pzPath)+1 );
+    strcpy( pzBuf + (pz - pzPath) + 1, pzName );
+
+    /*
+     *  If the "pzPath" path was gotten from "pathfind()", then it was
+     *  allocated and we need to deallocate it.
+     */
+    if (pzPath != pzProgPath)
+        free( (void*)pzPath );
+    return AG_TRUE;
+}
+
+
+static ag_bool
+insertEnvVal(
+    char*   pzBuf,
+    int     bufSize,
+    tCC*    pzName,
+    tCC*    pzProgPath )
+{
+    char* pzDir = pzBuf;
+
+    for (;;) {
+        char ch = *++pzName;
+        if (! ISNAMECHAR( ch ))
+            break;
+        *(pzDir++) = ch;
+    }
+
+    if (pzDir == pzBuf)
+        return AG_FALSE;
+
+    *pzDir = NUL;
+
+    pzDir = getenv( pzBuf );
+
+    /*
+     *  Environment value not found -- skip the home list entry
+     */
+    if (pzDir == NULL)
+        return AG_FALSE;
+
+    if (strlen( pzDir ) + 1 + strlen( pzName ) >= bufSize)
+        return AG_FALSE;
+
+    sprintf( pzBuf, "%s%s", pzDir, pzName );
+    return AG_TRUE;
+}
+
+
+LOCAL void
+mungeString( char* pzTxt, tOptionLoadMode mode )
+{
+    char* pzE;
+
+    if (mode == OPTION_LOAD_KEEP)
+        return;
+
+    if (isspace( *pzTxt )) {
+        char* pzS = pzTxt;
+        char* pzD = pzTxt;
+        while (isspace( *++pzS ))  ;
+        while ((*(pzD++) = *(pzS++)) != NUL)   ;
+        pzE = pzD-1;
+    } else
+        pzE = pzTxt + strlen( pzTxt );
+
+    while ((pzE > pzTxt) && isspace( pzE[-1] ))  pzE--;
+    *pzE = NUL;
+
+    if (mode == OPTION_LOAD_UNCOOKED)
+        return;
+
+    switch (*pzTxt) {
+    default: return;
+    case '"':
+    case '\'': break;
+    }
+
+    switch (pzE[-1]) {
+    default: return;
+    case '"':
+    case '\'': break;
+    }
+
+    (void)ao_string_cook( pzTxt, NULL );
+}
+
+
+static char*
+assembleArgValue( char* pzTxt, tOptionLoadMode mode )
+{
+    tSCC zBrk[] = " \t:=";
+    char* pzEnd = strpbrk( pzTxt, zBrk );
+    int   space_break;
+
+    /*
+     *  Not having an argument to a configurable name is okay.
+     */
+    if (pzEnd == NULL)
+        return pzTxt + strlen(pzTxt);
+
+    /*
+     *  If we are keeping all whitespace, then the value starts with the
+     *  character that follows the end of the configurable name, regardless
+     *  of which character caused it.
+     */
+    if (mode == OPTION_LOAD_KEEP) {
+        *(pzEnd++) = NUL;
+        return pzEnd;
+    }
+
+    /*
+     *  If the name ended on a white space character, remember that
+     *  because we'll have to skip over an immediately following ':' or '='
+     *  (and the white space following *that*).
+     */
+    space_break = isspace(*pzEnd);
+    *(pzEnd++) = NUL;
+    while (isspace(*pzEnd))  pzEnd++;
+    if (space_break && ((*pzEnd == ':') || (*pzEnd == '=')))
+        pzEnd++;
+
+    mungeString( pzEnd, mode );
+    return pzEnd;
+}
+
+
+/*
+ *  Load an option from a block of text.  The text must start with the
+ *  configurable/option name and be followed by its associated value.
+ *  That value may be processed in any of several ways.  See "tOptionLoadMode"
+ *  in autoopts.h.
+ */
+LOCAL void
+loadOptionLine(
+    tOptions*   pOpts,
+    tOptState*  pOS,
+    char*       pzLine,
+    tDirection  direction,
+    tOptionLoadMode   load_mode )
+{
+    while (isspace( *pzLine ))  pzLine++;
+
+    {
+        char* pzArg = assembleArgValue( pzLine, load_mode );
+
+        if (! SUCCESSFUL( longOptionFind( pOpts, pzLine, pOS )))
+            return;
+        if (pOS->flags & OPTST_NO_INIT)
+            return;
+        pOS->pzOptArg = pzArg;
+    }
+
+    switch (pOS->flags & (OPTST_IMM|OPTST_DISABLE_IMM)) {
+    case 0:
+        /*
+         *  The selected option has no immediate action.
+         *  THEREFORE, if the direction is PRESETTING
+         *  THEN we skip this option.
+         */
+        if (PRESETTING(direction))
+            return;
+        break;
+
+    case OPTST_IMM:
+        if (PRESETTING(direction)) {
+            /*
+             *  We are in the presetting direction with an option we handle
+             *  immediately for enablement, but normally for disablement.
+             *  Therefore, skip if disabled.
+             */
+            if ((pOS->flags & OPTST_DISABLED) == 0)
+                return;
+        } else {
+            /*
+             *  We are in the processing direction with an option we handle
+             *  immediately for enablement, but normally for disablement.
+             *  Therefore, skip if NOT disabled.
+             */
+            if ((pOS->flags & OPTST_DISABLED) != 0)
+                return;
+        }
+        break;
+
+    case OPTST_DISABLE_IMM:
+        if (PRESETTING(direction)) {
+            /*
+             *  We are in the presetting direction with an option we handle
+             *  immediately for disablement, but normally for disablement.
+             *  Therefore, skip if NOT disabled.
+             */
+            if ((pOS->flags & OPTST_DISABLED) != 0)
+                return;
+        } else {
+            /*
+             *  We are in the processing direction with an option we handle
+             *  immediately for disablement, but normally for disablement.
+             *  Therefore, skip if disabled.
+             */
+            if ((pOS->flags & OPTST_DISABLED) == 0)
+                return;
+        }
+        break;
+
+    case OPTST_IMM|OPTST_DISABLE_IMM:
+        /*
+         *  The selected option is always for immediate action.
+         *  THEREFORE, if the direction is PROCESSING
+         *  THEN we skip this option.
+         */
+        if (PROCESSING(direction))
+            return;
+        break;
+    }
+
+    /*
+     *  Fix up the args.
+     */
+    if (OPTST_GET_ARGTYPE(pOS->pOD->fOptState) == OPARG_TYPE_NONE) {
+        if (*pOS->pzOptArg != NUL)
+            return;
+        pOS->pzOptArg = NULL;
+
+    } else if (pOS->pOD->fOptState & OPTST_ARG_OPTIONAL) {
+        if (*pOS->pzOptArg == NUL)
+             pOS->pzOptArg = NULL;
+        else AGDUPSTR( pOS->pzOptArg, pOS->pzOptArg, "option argument" );
+
+    } else {
+        if (*pOS->pzOptArg == NUL)
+             pOS->pzOptArg = zNil;
+        else AGDUPSTR( pOS->pzOptArg, pOS->pzOptArg, "option argument" );
+    }
+
+    handleOption( pOpts, pOS );
+}
+
+
+/*=export_func  optionLoadLine
+ *
+ * what:  process a string for an option name and value
+ *
+ * arg:   tOptions*,   pOpts,  program options descriptor
+ * arg:   const char*, pzLine, NUL-terminated text
+ *
+ * doc:
+ *
+ *  This is a client program callable routine for setting options from, for
+ *  example, the contents of a file that they read in.  Only one option may
+ *  appear in the text.  It will be treated as a normal (non-preset) option.
+ *
+ *  When passed a pointer to the option struct and a string, it will find
+ *  the option named by the first token on the string and set the option
+ *  argument to the remainder of the string.  The caller must NUL terminate
+ *  the string.  Any embedded new lines will be included in the option
+ *  argument.  If the input looks like one or more quoted strings, then the
+ *  input will be "cooked".  The "cooking" is identical to the string
+ *  formation used in AutoGen definition files (@pxref{basic expression}),
+ *  except that you may not use backquotes.
+ *
+ * err:   Invalid options are silently ignored.  Invalid option arguments
+ *        will cause a warning to print, but the function should return.
+=*/
+void
+optionLoadLine(
+    tOptions*  pOpts,
+    tCC*       pzLine )
+{
+    tOptState st = OPTSTATE_INITIALIZER(SET);
+    char* pz;
+    AGDUPSTR( pz, pzLine, "user option line" );
+    loadOptionLine( pOpts, &st, pz, DIRECTION_PROCESS, OPTION_LOAD_COOKED );
+    AGFREE( pz );
+}
+/*
+ * Local Variables:
+ * mode: C
+ * c-file-style: "stroustrup"
+ * tab-width: 4
+ * indent-tabs-mode: nil
+ * End:
+ * end of autoopts/load.c */
diff --git a/sntp/libopts/m4/libopts.m4 b/sntp/libopts/m4/libopts.m4
new file mode 100644 (file)
index 0000000..085c776
--- /dev/null
@@ -0,0 +1,487 @@
+dnl  -*- buffer-read-only: t -*- vi: set ro:
+dnl 
+dnl DO NOT EDIT THIS FILE   (libopts.m4)
+dnl 
+dnl It has been AutoGen-ed  Sunday April  9, 2006 at 11:49:18 AM PDT
+dnl From the definitions    libopts.def
+dnl and the template file   conftest.tpl
+dnl
+dnl do always before generated macros:
+dnl
+AC_DEFUN([INVOKE_LIBOPTS_MACROS_FIRST],[
+[if test X${INVOKE_LIBOPTS_MACROS_FIRST_done} != Xyes ; then]
+  # =================
+  # AC_HEADER_STDC
+  # =================
+  AC_HEADER_STDC
+  # =================
+  # AC_HEADER_DIRENT
+  # =================
+  AC_HEADER_DIRENT
+  
+  # =================
+  # AC_CHECK_HEADERS
+  # =================
+  AC_CHECK_HEADERS(dlfcn.h errno.h fcntl.h libgen.h memory.h netinet/in.h \
+    setjmp.h sys/mman.h sys/param.h sys/poll.h sys/procset.h sys/select.h \
+    sys/socket.h sys/stropts.h sys/time.h sys/un.h sys/wait.h unistd.h)
+  
+  # --------------------------------------------
+  # Verify certain entries from AC_CHECK_HEADERS
+  # --------------------------------------------
+  [for f in sys_types sys_mman sys_param sys_stat sys_wait \
+           string errno stdlib memory setjmp
+  do eval as_ac_var=\${ac_cv_header_${f}_h+set}
+     test "${as_ac_var}" = set] || \
+       AC_MSG_ERROR([You must have ${f}.h on your system])
+  done
+  
+  # ================================================
+  # AC_CHECK_HEADERS: stdarg.h is present define HAVE_STDARG_H, otherwise
+  # if varargs.h is present define HAVE_VARARGS_H.
+  # ================================================
+  AC_CHECK_HEADERS(stdarg.h varargs.h, break)
+  [if test `eval echo '${'$as_ac_Header'}'` != yes; then]
+    AC_MSG_ERROR([You must have stdarg.h or varargs.h on your system])
+  fi
+  
+  # ================================================
+  # Similarly for the string.h and strings.h headers
+  # ================================================
+  AC_CHECK_HEADERS(string.h strings.h, break)
+  [if test `eval echo '${'$as_ac_Header'}'` != yes; then]
+    AC_MSG_ERROR([You must have string.h or strings.h on your system])
+  fi
+  
+  # =====================
+  # ...and limits headers
+  # =====================
+  AC_CHECK_HEADERS(limits.h sys/limits.h values.h, break)
+  [if test `eval echo '${'$as_ac_Header'}'` != yes; then]
+    AC_MSG_ERROR([You must have one of limits.h, sys/limits.h or values.h])
+  fi
+  
+  # ========================
+  # ...and int types headers
+  # ========================
+  AC_CHECK_HEADERS(stdint.h inttypes.h, break)
+  AC_CHECK_TYPES([int8_t, uint8_t, int16_t, uint16_t, int32_t, uint32_t,
+     intptr_t])
+  
+  # ====================
+  # uintptr type & sizes
+  # ====================
+  AC_CHECK_TYPES([uintptr_t], ,
+         [AC_DEFINE([uintptr_t], unsigned long,
+                    [Alternate uintptr_t for systems without it.])])
+  AC_CHECK_SIZEOF(char*, 4)
+  AC_CHECK_SIZEOF(int,   4)
+  AC_CHECK_SIZEOF(long,  4)
+  AC_CHECK_SIZEOF(short, 2)
+  
+  # ----------------------------------------------------------------------
+  # AC_CHECK_LIB for SVR4 libgen, and use it if it defines pathfind.
+  # ----------------------------------------------------------------------
+  AC_CHECK_LIB(gen, pathfind)
+  AC_FUNC_VPRINTF
+  AC_CHECK_FUNCS([mmap canonicalize_file_name snprintf strdup])
+[  INVOKE_LIBOPTS_MACROS_FIRST_done=yes
+fi]])
+
+dnl
+dnl @synopsis  INVOKE_LIBOPTS_MACROS
+dnl
+dnl  This macro will invoke the AutoConf macros specified in libopts.def
+dnl  that have not been disabled with "omit-invocation".
+dnl
+AC_DEFUN([LIBOPTS_WITH_REGEX_HEADER],[
+  AC_ARG_WITH([regex-header],
+    AC_HELP_STRING([--with-regex-header], [a reg expr header is specified]),
+    [libopts_cv_with_regex_header=${with_regex_header}],
+    AC_CACHE_CHECK([whether a reg expr header is specified], libopts_cv_with_regex_header,
+      libopts_cv_with_regex_header=no)
+  ) # end of AC_ARG_WITH
+
+  if test "X${libopts_cv_with_regex_header}" != Xno
+  then
+    AC_DEFINE_UNQUOTED([REGEX_HEADER],[<${libopts_cv_with_regex_header}>])
+  else
+    AC_DEFINE([REGEX_HEADER],[<regex.h>],[name of regex header file])
+  fi
+  
+]) # end of AC_DEFUN of LIBOPTS_WITH_REGEX_HEADER
+
+
+AC_DEFUN([LIBOPTS_WITHLIB_REGEX],[
+  AC_ARG_WITH([libregex],
+    AC_HELP_STRING([--with-libregex], [libregex installation prefix]),
+    [libopts_cv_with_libregex_root=${with_libregex}],
+    AC_CACHE_CHECK([whether with-libregex was specified], libopts_cv_with_libregex_root,
+      libopts_cv_with_libregex_root=no)
+  ) # end of AC_ARG_WITH libregex
+
+  if test "${with_libguile+set}" = set && \
+     test "${withval}" = no
+  then ## disabled by request
+    libopts_cv_with_libregex_root=no
+    libopts_cv_with_libregex_cflags=no
+    libopts_cv_with_libregex_libs=no
+  else
+
+  AC_ARG_WITH([libregex-cflags],
+    AC_HELP_STRING([--with-libregex-cflags], [libregex compile flags]),
+    [libopts_cv_with_libregex_cflags=${with_regex_cflags}],
+    AC_CACHE_CHECK([whether with-libregex-cflags was specified], libopts_cv_with_libregex_cflags,
+      libopts_cv_with_libregex_cflags=no)
+  ) # end of AC_ARG_WITH libregex-cflags
+
+  AC_ARG_WITH([libregex-libs],
+    AC_HELP_STRING([--with-libregex-libs], [libregex link command arguments]),
+    [libopts_cv_with_libregex_libs=${with_regex_libs}],
+    AC_CACHE_CHECK([whether with-libregex-libs was specified], libopts_cv_with_libregex_libs,
+      libopts_cv_with_libregex_libs=no)
+  ) # end of AC_ARG_WITH libregex-libs
+
+  case "X${libopts_cv_with_libregex_cflags}" in
+  Xyes|Xno|X )
+    case "X${libopts_cv_with_libregex_root}" in
+    Xyes|Xno|X ) libopts_cv_with_libregex_cflags=no ;;
+    * )        libopts_cv_with_libregex_cflags=-I${libopts_cv_with_libregex_root}/include ;;
+    esac
+  esac
+  case "X${libopts_cv_with_libregex_libs}" in
+  Xyes|Xno|X )
+    case "X${libopts_cv_with_libregex_root}" in
+    Xyes|Xno|X ) libopts_cv_with_libregex_libs=no ;;
+    * )        libopts_cv_with_libregex_libs="-L${libopts_cv_with_libregex_root}/lib -lregex";;
+    esac
+  esac
+  libopts_save_CPPFLAGS="${CPPFLAGS}"
+  libopts_save_LIBS="${LIBS}"
+  fi ## disabled by request
+
+  case "X${libopts_cv_with_libregex_cflags}" in
+  Xyes|Xno|X )
+    libopts_cv_with_libregex_cflags="" ;;
+  * ) CPPFLAGS="${CPPFLAGS} ${libopts_cv_with_libregex_cflags}" ;;
+  esac
+  case "X${libopts_cv_with_libregex_libs}" in
+  Xyes|Xno|X )
+    libopts_cv_with_libregex_libs="" ;;
+  * )
+    LIBS="${LIBS} ${libopts_cv_with_libregex_libs}" ;;
+  esac
+  LIBREGEX_CFLAGS=""
+  LIBREGEX_LIBS=""
+  AC_MSG_CHECKING([whether libregex functions properly])
+  AC_CACHE_VAL([libopts_cv_with_libregex],[
+  AC_TRY_RUN([@%:@include <stdio.h>
+@%:@include <stdlib.h>
+@%:@include <sys/types.h>
+@%:@include REGEX_HEADER
+static regex_t re;
+void comp_re( const char* pzPat ) {
+  int res = regcomp( &re, pzPat, REG_EXTENDED|REG_ICASE|REG_NEWLINE );
+  if (res == 0) return;
+  exit( res ); }
+int main() {
+  regmatch_t m@<:@2@:>@;
+  comp_re( "^.*\@S|@"   );
+  comp_re( "()|no.*" );
+  comp_re( "."       );
+  if (regexec( &re, "X", 2, m, 0 ) != 0)  return 1;
+  if ((m@<:@0@:>@.rm_so != 0) || (m@<:@0@:>@.rm_eo != 1)) {
+    fputs( "error: regex -->.<-- did not match\n", stderr );
+    return 1;
+  }
+  return 0; }],
+    [libopts_cv_with_libregex=yes], [libopts_cv_with_libregex=no],
+    [libopts_cv_with_libregex=no]) # end of AC_TRY_RUN 
+  ]) # end of AC_CACHE_VAL for libopts_cv_with_libregex
+  AC_MSG_RESULT([${libopts_cv_with_libregex}])
+
+  if test "X${libopts_cv_with_libregex}" = Xno
+  then
+    CPPFLAGS="${libopts_save_CPPFLAGS}"
+    LIBS="${libopts_save_LIBS}"
+               cat >&2 <<'_EOF_'
+I cannot detect POSIX compliant regcomp/regexec routines.
+These are required for AutoGen to work correctly.  If you have
+such a library present on your system, you must specify it by
+setting the LIBS environment variable, e.g., "LIBS='-lregex'".
+If you do not have such a library on your system, then you should
+download and install, for example, the one from:
+    ftp://ftp.gnu.org/gnu/rx/
+_EOF_
+AC_MSG_ERROR([Cannot find working POSIX regex library])
+  fi
+  
+]) # end of AC_DEFUN of LIBOPTS_WITHLIB_REGEX
+
+
+AC_DEFUN([LIBOPTS_RUN_PATHFIND],[
+  AC_MSG_CHECKING([whether pathfind(3) works])
+  AC_CACHE_VAL([libopts_cv_run_pathfind],[
+  AC_TRY_RUN([@%:@include <string.h>
+@%:@include <stdlib.h>
+int main (int argc, char** argv) {
+   char* pz = pathfind( getenv( "PATH" ), "sh", "x" );
+   return (pz == 0) ? 1 : 0;
+}],
+    [libopts_cv_run_pathfind=yes],[libopts_cv_run_pathfind=no],[libopts_cv_run_pathfind=no]
+  ) # end of TRY_RUN
+  ]) # end of AC_CACHE_VAL for libopts_cv_run_pathfind
+  AC_MSG_RESULT([${libopts_cv_run_pathfind}])
+
+  if test "X${libopts_cv_run_pathfind}" != Xno
+  then
+    AC_DEFINE([HAVE_PATHFIND],[1],
+        [Define this if pathfind(3) works])
+  fi
+  
+]) # end of AC_DEFUN of LIBOPTS_RUN_PATHFIND
+
+
+AC_DEFUN([LIBOPTS_TEST_DEV_ZERO],[
+  AC_MSG_CHECKING([whether /dev/zero is readable device])
+  AC_CACHE_VAL([libopts_cv_test_dev_zero],[
+    libopts_cv_test_dev_zero=`exec 2> /dev/null
+dzero=\`ls -l /dev/zero | egrep ^c......r\`
+test -z "${dzero}" && exit 1
+echo ${dzero}`
+    if test $? -ne 0
+    then libopts_cv_test_dev_zero=no
+    elif test -z "$libopts_cv_test_dev_zero"
+    then libopts_cv_test_dev_zero=no
+    fi
+  ]) # end of CACHE_VAL of libopts_cv_test_dev_zero
+  AC_MSG_RESULT([${libopts_cv_test_dev_zero}])
+
+  if test "X${libopts_cv_test_dev_zero}" != Xno
+  then
+    AC_DEFINE([HAVE_DEV_ZERO],[1],
+        [Define this if /dev/zero is readable device])
+  fi
+  
+]) # end of AC_DEFUN of LIBOPTS_TEST_DEV_ZERO
+
+
+AC_DEFUN([LIBOPTS_RUN_REALPATH],[
+  AC_MSG_CHECKING([whether we have a functional realpath(3C)])
+  AC_CACHE_VAL([libopts_cv_run_realpath],[
+  AC_TRY_RUN([@%:@include <limits.h>
+@%:@include <stdlib.h>
+int main (int argc, char** argv) {
+@%:@ifndef PATH_MAX
+choke me!!
+@%:@else
+   char zPath@<:@PATH_MAX+1@:>@;
+@%:@endif
+   char *pz = realpath(argv@<:@0@:>@, zPath);
+   return (pz == zPath) ? 0 : 1;
+}],
+    [libopts_cv_run_realpath=yes],[libopts_cv_run_realpath=no],[libopts_cv_run_realpath=no]
+  ) # end of TRY_RUN
+  ]) # end of AC_CACHE_VAL for libopts_cv_run_realpath
+  AC_MSG_RESULT([${libopts_cv_run_realpath}])
+
+  if test "X${libopts_cv_run_realpath}" != Xno
+  then
+    AC_DEFINE([HAVE_REALPATH],[1],
+        [Define this if we have a functional realpath(3C)])
+  fi
+  
+]) # end of AC_DEFUN of LIBOPTS_RUN_REALPATH
+
+
+AC_DEFUN([LIBOPTS_RUN_STRFTIME],[
+  AC_MSG_CHECKING([whether strftime() works])
+  AC_CACHE_VAL([libopts_cv_run_strftime],[
+  AC_TRY_RUN([@%:@include <time.h>
+@%:@include <string.h>
+char t_buf@<:@ 64 @:>@;
+int main() {
+  static const char z@<:@@:>@ = "Thursday Aug 28 240";
+  struct tm tm;
+  tm.tm_sec   = 36;  /* seconds after the minute @<:@0, 61@:>@  */
+  tm.tm_min   = 44;  /* minutes after the hour @<:@0, 59@:>@ */
+  tm.tm_hour  = 12;  /* hour since midnight @<:@0, 23@:>@ */
+  tm.tm_mday  = 28;  /* day of the month @<:@1, 31@:>@ */
+  tm.tm_mon   =  7;  /* months since January @<:@0, 11@:>@ */
+  tm.tm_year  = 86;  /* years since 1900 */
+  tm.tm_wday  =  4;  /* days since Sunday @<:@0, 6@:>@ */
+  tm.tm_yday  = 239; /* days since January 1 @<:@0, 365@:>@ */
+  tm.tm_isdst =  1;  /* flag for daylight savings time */
+  strftime( t_buf, sizeof( t_buf ), "%A %b %d %j", &tm );
+  return (strcmp( t_buf, z ) != 0); }],
+    [libopts_cv_run_strftime=yes],[libopts_cv_run_strftime=no],[libopts_cv_run_strftime=no]
+  ) # end of TRY_RUN
+  ]) # end of AC_CACHE_VAL for libopts_cv_run_strftime
+  AC_MSG_RESULT([${libopts_cv_run_strftime}])
+
+  if test "X${libopts_cv_run_strftime}" != Xno
+  then
+    AC_DEFINE([HAVE_STRFTIME],[1],
+        [Define this if strftime() works])
+  fi
+  
+]) # end of AC_DEFUN of LIBOPTS_RUN_STRFTIME
+
+
+AC_DEFUN([LIBOPTS_RUN_FOPEN_BINARY],[
+  AC_MSG_CHECKING([whether fopen accepts "b" mode])
+  AC_CACHE_VAL([libopts_cv_run_fopen_binary],[
+  AC_TRY_RUN([@%:@include <stdio.h>
+int main (int argc, char** argv) {
+FILE* fp = fopen("conftest.@S|@ac_ext", "rb");
+return (fp == NULL) ? 1 : fclose(fp); }],
+    [libopts_cv_run_fopen_binary=yes],[libopts_cv_run_fopen_binary=no],[libopts_cv_run_fopen_binary=no]
+  ) # end of TRY_RUN
+  ]) # end of AC_CACHE_VAL for libopts_cv_run_fopen_binary
+  AC_MSG_RESULT([${libopts_cv_run_fopen_binary}])
+
+  if test "X${libopts_cv_run_fopen_binary}" != Xno
+  then
+    AC_DEFINE([FOPEN_BINARY_FLAG],"b",
+       [fopen(3) accepts a 'b' in the mode flag])
+  else
+    AC_DEFINE([FOPEN_BINARY_FLAG],"",
+       [fopen(3) accepts a 'b' in the mode flag])
+  fi
+  
+]) # end of AC_DEFUN of LIBOPTS_RUN_FOPEN_BINARY
+
+
+AC_DEFUN([LIBOPTS_RUN_FOPEN_TEXT],[
+  AC_MSG_CHECKING([whether fopen accepts "t" mode])
+  AC_CACHE_VAL([libopts_cv_run_fopen_text],[
+  AC_TRY_RUN([@%:@include <stdio.h>
+int main (int argc, char** argv) {
+FILE* fp = fopen("conftest.@S|@ac_ext", "rt");
+return (fp == NULL) ? 1 : fclose(fp); }],
+    [libopts_cv_run_fopen_text=yes],[libopts_cv_run_fopen_text=no],[libopts_cv_run_fopen_text=no]
+  ) # end of TRY_RUN
+  ]) # end of AC_CACHE_VAL for libopts_cv_run_fopen_text
+  AC_MSG_RESULT([${libopts_cv_run_fopen_text}])
+
+  if test "X${libopts_cv_run_fopen_text}" != Xno
+  then
+    AC_DEFINE([FOPEN_TEXT_FLAG],"t",
+       [fopen(3) accepts a 't' in the mode flag])
+  else
+    AC_DEFINE([FOPEN_TEXT_FLAG],"",
+       [fopen(3) accepts a 't' in the mode flag])
+  fi
+  
+]) # end of AC_DEFUN of LIBOPTS_RUN_FOPEN_TEXT
+
+
+AC_DEFUN([INVOKE_LIBOPTS_MACROS],[
+  INVOKE_LIBOPTS_MACROS_FIRST
+  # Check to see if a reg expr header is specified.
+  LIBOPTS_WITH_REGEX_HEADER
+
+  # Check to see if a working libregex can be found.
+  LIBOPTS_WITHLIB_REGEX
+
+  # Check to see if pathfind(3) works.
+  LIBOPTS_RUN_PATHFIND
+
+  # Check to see if /dev/zero is readable device.
+  LIBOPTS_TEST_DEV_ZERO
+
+  # Check to see if we have a functional realpath(3C).
+  LIBOPTS_RUN_REALPATH
+
+  # Check to see if strftime() works.
+  LIBOPTS_RUN_STRFTIME
+
+  # Check to see if fopen accepts "b" mode.
+  LIBOPTS_RUN_FOPEN_BINARY
+
+  # Check to see if fopen accepts "t" mode.
+  LIBOPTS_RUN_FOPEN_TEXT
+
+]) # end AC_DEFUN of INVOKE_LIBOPTS_MACROS
+
+dnl @synopsis  LIBOPTS_CHECK
+dnl
+dnl If autoopts-config works, add the linking information to LIBS.
+dnl Otherwise, add ``libopts-${ao_rev}'' to SUBDIRS and run all
+dnl the config tests that the library needs.  Invoke the
+dnl "INVOKE_LIBOPTS_MACROS" macro iff we are building libopts.
+dnl
+dnl Default to system libopts
+dnl
+AC_DEFUN([LIBOPTS_CHECK],[
+  [NEED_LIBOPTS_DIR='']
+  m4_pushdef([AO_Libopts_Dir],
+           [ifelse($1, , [libopts], [$1])])
+  AC_SUBST(LIBOPTS_DIR, AO_Libopts_Dir)
+  AC_ARG_ENABLE([local-libopts],
+    AC_HELP_STRING([--enable-local-libopts],
+       [Force using the supplied libopts tearoff code]),[
+    if test x$enableval = xyes ; then
+       AC_MSG_NOTICE([Using supplied libopts tearoff])
+       LIBOPTS_LDADD='$(top_builddir)/AO_Libopts_Dir/libopts.la'
+       LIBOPTS_CFLAGS='-I$(top_srcdir)/AO_Libopts_Dir'
+       NEED_LIBOPTS_DIR=true
+    fi])
+
+  [if test -z "${NEED_LIBOPTS_DIR}" ; then]
+     AC_MSG_CHECKING([whether autoopts-config can be found])
+     AC_ARG_WITH([autoopts-config],
+        AC_HELP_STRING([--with-autoopts-config],
+             [specify the config-info script]),
+        [lo_cv_with_autoopts_config=${with_autoopts_config}],
+        AC_CACHE_CHECK([whether autoopts-config is specified],
+             [lo_cv_with_autoopts_config],
+             [if autoopts-config --help 2>/dev/null 1>&2
+        then lo_cv_with_autoopts_config=autoopts-config
+        elif libopts-config --help 2>/dev/null 1>&2
+        then lo_cv_with_autoopts_config=libopts-config
+        else lo_cv_with_autoopts_config=no ; fi])
+     ) # end of AC_ARG_WITH
+
+     AC_CACHE_VAL([lo_cv_test_autoopts],[
+        if test -z "${lo_cv_with_autoopts_config}" \
+                -o X"${lo_cv_with_autoopts_config}" = Xno
+        then
+           if autoopts-config --help 2>/dev/null 1>&2
+           then lo_cv_with_autoopts_config=autoopts-config
+           elif libopts-config --help 2>/dev/null 1>&2
+           then lo_cv_with_autoopts_config=libopts-config
+           else lo_cv_with_autoopts_config=false ; fi
+        fi
+        lo_cv_test_autoopts=`
+            ${lo_cv_with_autoopts_config} --libs` 2> /dev/null
+        if test $? -ne 0 -o -z "${lo_cv_test_autoopts}"
+        then lo_cv_test_autoopts=no ; fi
+     ]) # end of CACHE_VAL
+     AC_MSG_RESULT([${lo_cv_test_autoopts}])
+
+     [if test "X${lo_cv_test_autoopts}" != Xno
+     then
+        LIBOPTS_LDADD="${lo_cv_test_autoopts}"
+        LIBOPTS_CFLAGS="`${lo_cv_with_autoopts_config} --cflags`"
+     else
+        LIBOPTS_LDADD='$(top_builddir)/]AO_Libopts_Dir[/libopts.la'
+        LIBOPTS_CFLAGS='-I$(top_srcdir)/]AO_Libopts_Dir['
+        NEED_LIBOPTS_DIR=true
+     fi
+  fi # end of if test -z "${NEED_LIBOPTS_DIR}"]
+
+  AM_CONDITIONAL([NEED_LIBOPTS], [test -n "${NEED_LIBOPTS_DIR}"])
+  AC_SUBST(LIBOPTS_LDADD)
+  AC_SUBST(LIBOPTS_CFLAGS)
+  AC_SUBST(LIBOPTS_DIR, AO_Libopts_Dir)
+  AC_CONFIG_FILES(AO_Libopts_Dir/Makefile)
+  m4_popdef([AO_Libopts_Dir])
+
+  [if test -n "${NEED_LIBOPTS_DIR}" ; then]
+    INVOKE_LIBOPTS_MACROS
+  else
+    INVOKE_LIBOPTS_MACROS_FIRST
+  [fi
+# end of AC_DEFUN of LIBOPTS_CHECK]
+])
diff --git a/sntp/libopts/m4/liboptschk.m4 b/sntp/libopts/m4/liboptschk.m4
new file mode 100644 (file)
index 0000000..26f9c24
--- /dev/null
@@ -0,0 +1,39 @@
+# liboptschk.m4 serial 1 (autogen - 5.7.3)
+dnl Copyright (C) 2005 Free Software Foundation, Inc.
+dnl This file is free software; the Free Software Foundation
+dnl gives unlimited permission to copy and/or distribute it,
+dnl with or without modifications, as long as this notice is preserved.
+dnl
+dnl This file can can be used in projects which are not available under
+dnl the GNU General Public License or the GNU Library General Public
+dnl License but which still want to provide support for the GNU gettext
+dnl functionality.
+dnl Please note that the actual code of the GNU gettext library is covered
+dnl by the GNU Library General Public License, and the rest of the GNU
+dnl gettext package package is covered by the GNU General Public License.
+dnl They are *not* in the public domain.
+
+dnl Authors:
+dnl   Ulrich Drepper <drepper@cygnus.com>, 1995-2000.
+dnl   Bruno Haible <haible@clisp.cons.org>, 2000-2003.
+
+AC_PREREQ(2.50)
+
+AC_DEFUN([ag_FIND_LIBOPTS],
+    [if test "X${ac_cv_header_autoopts_options_h}" == Xno
+    then
+      :
+    else
+      f=`autoopts-config cflags` 2>/dev/null
+      test X"${f}" = X && f=`libopts-config cflags` 2>/dev/null
+      if test X"${f}" = X
+      then
+        :
+      else
+        AC_DEFINE([HAVE_LIBOPTS],[1],[define if we can find libopts])
+        CFLAGS="${CFLAGS} ${f}"
+        f=`autoopts-config ldflags` 2>/dev/null
+        test X"${f}" = X && f=`libopts-config ldflags` 2>/dev/null
+        LIBS="${LIBS} ${f}"
+      fi
+    fi])
diff --git a/sntp/libopts/makeshell.c b/sntp/libopts/makeshell.c
new file mode 100644 (file)
index 0000000..32bcaa3
--- /dev/null
@@ -0,0 +1,1100 @@
+
+/*
+ *  $Id: makeshell.c,v 4.8 2006/03/25 19:24:56 bkorb Exp $
+ * Time-stamp:      "2005-10-29 13:23:33 bkorb"
+ *
+ *  This module will interpret the options set in the tOptions
+ *  structure and create a Bourne shell script capable of parsing them.
+ */
+
+/*
+ *  Automated Options copyright 1992-2006 Bruce Korb
+ *
+ *  Automated Options is free software.
+ *  You may redistribute it and/or modify it under the terms of the
+ *  GNU General Public License, as published by the Free Software
+ *  Foundation; either version 2, or (at your option) any later version.
+ *
+ *  Automated Options is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with Automated Options.  See the file "COPYING".  If not,
+ *  write to:  The Free Software Foundation, Inc.,
+ *             51 Franklin Street, Fifth Floor,
+ *             Boston, MA  02110-1301, USA.
+ *
+ * As a special exception, Bruce Korb gives permission for additional
+ * uses of the text contained in his release of AutoOpts.
+ *
+ * The exception is that, if you link the AutoOpts library with other
+ * files to produce an executable, this does not by itself cause the
+ * resulting executable to be covered by the GNU General Public License.
+ * Your use of that executable is in no way restricted on account of
+ * linking the AutoOpts library code into it.
+ *
+ * This exception does not however invalidate any other reasons why
+ * the executable file might be covered by the GNU General Public License.
+ *
+ * This exception applies only to the code released by Bruce Korb under
+ * the name AutoOpts.  If you copy code from other sources under the
+ * General Public License into a copy of AutoOpts, as the General Public
+ * License permits, the exception does not apply to the code that you add
+ * in this way.  To avoid misleading anyone as to the status of such
+ * modified files, you must delete this exception notice from them.
+ *
+ * If you write modifications of your own for AutoOpts, it is your choice
+ * whether to permit this exception to apply to your modifications.
+ * If you do not wish that, delete this exception notice.
+ */
+
+tOptions*  pShellParseOptions = NULL;
+
+/* * * * * * * * * * * * * * * * * * * * *
+ *
+ *  Setup Format Strings
+ */
+tSCC zStartMarker[] =
+"# # # # # # # # # # -- do not modify this marker --\n#\n"
+"#  DO NOT EDIT THIS SECTION";
+
+tSCC zPreamble[] =
+"%s OF %s\n#\n"
+"#  From here to the next `-- do not modify this marker --',\n"
+"#  the text has been generated %s\n";
+
+tSCC zEndPreamble[] =
+"#  From the %s option definitions\n#\n";
+
+tSCC zMultiDef[] = "\n"
+"if test -z \"${%1$s_%2$s}\"\n"
+"then\n"
+"  %1$s_%2$s_CT=0\n"
+"else\n"
+"  %1$s_%2$s_CT=1\n"
+"  %1$s_%2$s_1=\"${%1$s_%2$s}\"\n"
+"fi\n"
+"export %1$s_%2$s_CT";
+
+tSCC zSingleDef[] = "\n"
+"%1$s_%2$s=\"${%1$s_%2$s-'%3$s'}\"\n"
+"%1$s_%2$s_set=false\n"
+"export %1$s_%2$s\n";
+
+tSCC zSingleNoDef[] = "\n"
+"%1$s_%2$s=\"${%1$s_%2$s}\"\n"
+"%1$s_%2$s_set=false\n"
+"export %1$s_%2$s\n";
+
+/* * * * * * * * * * * * * * * * * * * * *
+ *
+ *  LOOP START
+ *
+ *  The loop may run in either of two modes:
+ *  all options are named options (loop only)
+ *  regular, marked option processing.
+ */
+tSCC zLoopCase[] = "\n"
+"OPT_PROCESS=true\n"
+"OPT_ARG=\"$1\"\n\n"
+"while ${OPT_PROCESS} && [ $# -gt 0 ]\ndo\n"
+"    OPT_ELEMENT=''\n"
+"    OPT_ARG_VAL=''\n\n"
+     /*
+      *  'OPT_ARG' may or may not match the current $1
+      */
+"    case \"${OPT_ARG}\" in\n"
+"    -- )\n"
+"        OPT_PROCESS=false\n"
+"        shift\n"
+"        ;;\n\n";
+
+tSCC zLoopOnly[] = "\n"
+"OPT_ARG=\"$1\"\n\n"
+"while [ $# -gt 0 ]\ndo\n"
+"    OPT_ELEMENT=''\n"
+"    OPT_ARG_VAL=''\n\n"
+"    OPT_ARG=\"${1}\"\n";
+
+/* * * * * * * * * * * * * * * *
+ *
+ *  CASE SELECTORS
+ *
+ *  If the loop runs as a regular option loop,
+ *  then we must have selectors for each acceptable option
+ *  type (long option, flag character and non-option)
+ */
+tSCC zLongSelection[] =
+"    --* )\n";
+
+tSCC zFlagSelection[] =
+"    -* )\n";
+
+tSCC zEndSelection[] =
+"        ;;\n\n";
+
+tSCC zNoSelection[] =
+"    * )\n"
+"         OPT_PROCESS=false\n"
+"         ;;\n"
+"    esac\n\n";
+
+/* * * * * * * * * * * * * * * *
+ *
+ *  LOOP END
+ */
+tSCC zLoopEnd[] =
+"    if [ -n \"${OPT_ARG_VAL}\" ]\n"
+"    then\n"
+"        eval %1$s_${OPT_NAME}${OPT_ELEMENT}=\"'${OPT_ARG_VAL}'\"\n"
+"        export %1$s_${OPT_NAME}${OPT_ELEMENT}\n"
+"    fi\n"
+"done\n\n"
+"unset OPT_PROCESS || :\n"
+"unset OPT_ELEMENT || :\n"
+"unset OPT_ARG || :\n"
+"unset OPT_ARG_NEEDED || :\n"
+"unset OPT_NAME || :\n"
+"unset OPT_CODE || :\n"
+"unset OPT_ARG_VAL || :\n%2$s";
+
+tSCC zTrailerMarker[] = "\n"
+"# # # # # # # # # #\n#\n"
+"#  END OF AUTOMATED OPTION PROCESSING\n"
+"#\n# # # # # # # # # # -- do not modify this marker --\n";
+
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ *
+ *  OPTION SELECTION
+ */
+tSCC zOptionCase[] =
+"        case \"${OPT_CODE}\" in\n";
+
+tSCC zOptionPartName[] =
+"        '%s' | \\\n";
+
+tSCC zOptionFullName[] =
+"        '%s' )\n";
+
+tSCC zOptionFlag[] =
+"        '%c' )\n";
+
+tSCC zOptionEndSelect[] =
+"            ;;\n\n";
+
+tSCC zOptionUnknown[] =
+"        * )\n"
+"            echo Unknown %s: \"${OPT_CODE}\" >&2\n"
+"            echo \"$%s_USAGE_TEXT\"\n"
+"            exit 1\n"
+"            ;;\n"
+"        esac\n\n";
+
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ *
+ *  OPTION PROCESSING
+ *
+ *  Formats for emitting the text for handling particular options
+ */
+tSCC zTextExit[] =
+"            echo \"$%s_%s_TEXT\"\n"
+"            exit 0\n";
+
+tSCC zPagedUsageExit[] =
+"            echo \"$%s_LONGUSAGE_TEXT\" | ${PAGER-more}\n"
+"            exit 0\n";
+
+tSCC zCmdFmt[] =
+"            %s\n";
+
+tSCC zCountTest[] =
+"            if [ $%1$s_%2$s_CT -ge %3$d ] ; then\n"
+"                echo Error:  more than %3$d %2$s options >&2\n"
+"                echo \"$%1$s_USAGE_TEXT\"\n"
+"                exit 1 ; fi\n";
+
+tSCC zMultiArg[] =
+"            %1$s_%2$s_CT=`expr ${%1$s_%2$s_CT} + 1`\n"
+"            OPT_ELEMENT=\"_${%1$s_%2$s_CT}\"\n"
+"            OPT_NAME='%2$s'\n";
+
+tSCC zSingleArg[] =
+"            if [ -n \"${%1$s_%2$s}\" ] && ${%1$s_%2$s_set} ; then\n"
+"                echo Error:  duplicate %2$s option >&2\n"
+"                echo \"$%1$s_USAGE_TEXT\"\n"
+"                exit 1 ; fi\n"
+"            %1$s_%2$s_set=true\n"
+"            OPT_NAME='%2$s'\n";
+
+tSCC zNoMultiArg[] =
+"            %1$s_%2$s_CT=0\n"
+"            OPT_ELEMENT=''\n"
+"            %1$s_%2$s='%3$s'\n"
+"            export %1$s_%2$s\n"
+"            OPT_NAME='%2$s'\n";
+
+tSCC zNoSingleArg[] =
+"            if [ -n \"${%1$s_%2$s}\" ] && ${%1$s_%2$s_set} ; then\n"
+"                echo Error:  duplicate %2$s option >&2\n"
+"                echo \"$%1$s_USAGE_TEXT\"\n"
+"                exit 1 ; fi\n"
+"            %1$s_%2$s_set=true\n"
+"            %1$s_%2$s='%3$s'\n"
+"            export %1$s_%2$s\n"
+"            OPT_NAME='%2$s'\n";
+
+tSCC zMayArg[]  =
+"            eval %1$s_%2$s${OPT_ELEMENT}=true\n"
+"            export %1$s_%2$s${OPT_ELEMENT}\n"
+"            OPT_ARG_NEEDED=OK\n";
+
+tSCC zMustArg[] =
+"            OPT_ARG_NEEDED=YES\n";
+
+tSCC zCantArg[] =
+"            eval %1$s_%2$s${OPT_ELEMENT}=true\n"
+"            export %1$s_%2$s${OPT_ELEMENT}\n"
+"            OPT_ARG_NEEDED=NO\n";
+
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ *
+ *  LONG OPTION PROCESSING
+ *
+ *  Formats for emitting the text for handling long option types
+ */
+tSCC zLongOptInit[] =
+"        OPT_CODE=`echo \"X${OPT_ARG}\"|sed 's/^X-*//'`\n"
+"        shift\n"
+"        OPT_ARG=\"$1\"\n\n"
+"        case \"${OPT_CODE}\" in *=* )\n"
+"            OPT_ARG_VAL=`echo \"${OPT_CODE}\"|sed 's/^[^=]*=//'`\n"
+"            OPT_CODE=`echo \"${OPT_CODE}\"|sed 's/=.*$//'` ;; esac\n\n";
+
+tSCC zLongOptArg[] =
+"        case \"${OPT_ARG_NEEDED}\" in\n"
+"        NO )\n"
+"            OPT_ARG_VAL=''\n"
+"            ;;\n\n"
+"        YES )\n"
+"            if [ -z \"${OPT_ARG_VAL}\" ]\n"
+"            then\n"
+"                if [ $# -eq 0 ]\n"
+"                then\n"
+"                    echo No argument provided for ${OPT_NAME} option >&2\n"
+"                    echo \"$%s_USAGE_TEXT\"\n"
+"                    exit 1\n"
+"                fi\n\n"
+"                OPT_ARG_VAL=\"${OPT_ARG}\"\n"
+"                shift\n"
+"                OPT_ARG=\"$1\"\n"
+"            fi\n"
+"            ;;\n\n"
+"        OK )\n"
+"            if [ -z \"${OPT_ARG_VAL}\" ] && [ $# -gt 0 ]\n"
+"            then\n"
+"                case \"${OPT_ARG}\" in -* ) ;; * )\n"
+"                    OPT_ARG_VAL=\"${OPT_ARG}\"\n"
+"                    shift\n"
+"                    OPT_ARG=\"$1\" ;; esac\n"
+"            fi\n"
+"            ;;\n"
+"        esac\n";
+
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ *
+ *  FLAG OPTION PROCESSING
+ *
+ *  Formats for emitting the text for handling flag option types
+ */
+tSCC zFlagOptInit[] =
+"        OPT_CODE=`echo \"X${OPT_ARG}\" | sed 's/X-\\(.\\).*/\\1/'`\n"
+"        OPT_ARG=` echo \"X${OPT_ARG}\" | sed 's/X-.//'`\n\n";
+
+tSCC zFlagOptArg[] =
+"        case \"${OPT_ARG_NEEDED}\" in\n"
+"        NO )\n"
+"            if [ -n \"${OPT_ARG}\" ]\n"
+"            then\n"
+"                OPT_ARG=-\"${OPT_ARG}\"\n"
+"            else\n"
+"                shift\n"
+"                OPT_ARG=\"$1\"\n"
+"            fi\n"
+"            ;;\n\n"
+"        YES )\n"
+"            if [ -n \"${OPT_ARG}\" ]\n"
+"            then\n"
+"                OPT_ARG_VAL=\"${OPT_ARG}\"\n\n"
+"            else\n"
+"                if [ $# -eq 0 ]\n"
+"                then\n"
+"                    echo No argument provided for ${OPT_NAME} option >&2\n"
+"                    echo \"$%s_USAGE_TEXT\"\n"
+"                    exit 1\n"
+"                fi\n"
+"                shift\n"
+"                OPT_ARG_VAL=\"$1\"\n"
+"            fi\n\n"
+"            shift\n"
+"            OPT_ARG=\"$1\"\n"
+"            ;;\n\n"
+"        OK )\n"
+"            if [ -n \"${OPT_ARG}\" ]\n"
+"            then\n"
+"                OPT_ARG_VAL=\"${OPT_ARG}\"\n"
+"                shift\n"
+"                OPT_ARG=\"$1\"\n\n"
+"            else\n"
+"                shift\n"
+"                if [ $# -gt 0 ]\n"
+"                then\n"
+"                    case \"$1\" in -* ) ;; * )\n"
+"                        OPT_ARG_VAL=\"$1\"\n"
+"                        shift ;; esac\n"
+"                    OPT_ARG=\"$1\"\n"
+"                fi\n"
+"            fi\n"
+"            ;;\n"
+"        esac\n";
+
+tSCC* pzShell = NULL;
+static char*  pzLeader  = NULL;
+static char*  pzTrailer = NULL;
+
+/* = = = START-STATIC-FORWARD = = = */
+/* static forward declarations maintained by :mkfwd */
+static void
+textToVariable( tOptions* pOpts, teTextTo whichVar, tOptDesc* pOD );
+
+static void
+emitUsage( tOptions* pOpts );
+
+static void
+emitSetup( tOptions* pOpts );
+
+static void
+printOptionAction( tOptions* pOpts, tOptDesc* pOptDesc );
+
+static void
+printOptionInaction( tOptions* pOpts, tOptDesc* pOptDesc );
+
+static void
+emitFlag( tOptions* pOpts );
+
+static void
+emitMatchExpr( tCC* pzMatchName, tOptDesc* pCurOpt, tOptions* pOpts );
+
+static void
+emitLong( tOptions* pOpts );
+
+static void
+openOutput( const char* pzFile );
+/* = = = END-STATIC-FORWARD = = = */
+
+/*=export_func  optionParseShell
+ * private:
+ *
+ * what:  Decipher a boolean value
+ * arg:   + tOptions* + pOpts    + program options descriptor +
+ *
+ * doc:
+ *  Emit a shell script that will parse the command line options.
+=*/
+void
+optionParseShell( tOptions* pOpts )
+{
+    /*
+     *  Check for our SHELL option now.
+     *  IF the output file contains the "#!" magic marker,
+     *  it will override anything we do here.
+     */
+    if (HAVE_OPT( SHELL ))
+        pzShell = OPT_ARG( SHELL );
+
+    else if (! ENABLED_OPT( SHELL ))
+        pzShell = NULL;
+
+    else if ((pzShell = getenv( "SHELL" )),
+             pzShell == NULL)
+
+        pzShell = "/bin/sh";
+
+    /*
+     *  Check for a specified output file
+     */
+    if (HAVE_OPT( SCRIPT ))
+        openOutput( OPT_ARG( SCRIPT ));
+
+    emitUsage( pOpts );
+    emitSetup( pOpts );
+
+    /*
+     *  There are four modes of option processing.
+     */
+    switch (pOpts->fOptSet & (OPTPROC_LONGOPT|OPTPROC_SHORTOPT)) {
+    case OPTPROC_LONGOPT:
+        fputs( zLoopCase,        stdout );
+
+        fputs( zLongSelection,   stdout );
+        fputs( zLongOptInit,     stdout );
+        emitLong( pOpts );
+        printf( zLongOptArg,     pOpts->pzPROGNAME );
+        fputs( zEndSelection,    stdout );
+
+        fputs( zNoSelection,     stdout );
+        break;
+
+    case 0:
+        fputs( zLoopOnly,        stdout );
+        fputs( zLongOptInit,     stdout );
+        emitLong( pOpts );
+        printf( zLongOptArg,     pOpts->pzPROGNAME );
+        break;
+
+    case OPTPROC_SHORTOPT:
+        fputs( zLoopCase,        stdout );
+
+        fputs( zFlagSelection,   stdout );
+        fputs( zFlagOptInit,     stdout );
+        emitFlag( pOpts );
+        printf( zFlagOptArg,     pOpts->pzPROGNAME );
+        fputs( zEndSelection,    stdout );
+
+        fputs( zNoSelection,     stdout );
+        break;
+
+    case OPTPROC_LONGOPT|OPTPROC_SHORTOPT:
+        fputs( zLoopCase,        stdout );
+
+        fputs( zLongSelection,   stdout );
+        fputs( zLongOptInit,     stdout );
+        emitLong( pOpts );
+        printf( zLongOptArg,     pOpts->pzPROGNAME );
+        fputs( zEndSelection,    stdout );
+
+        fputs( zFlagSelection,   stdout );
+        fputs( zFlagOptInit,     stdout );
+        emitFlag( pOpts );
+        printf( zFlagOptArg,     pOpts->pzPROGNAME );
+        fputs( zEndSelection,    stdout );
+
+        fputs( zNoSelection,     stdout );
+        break;
+    }
+
+    printf( zLoopEnd, pOpts->pzPROGNAME, zTrailerMarker );
+    if ((pzTrailer != NULL) && (*pzTrailer != '\0'))
+        fputs( pzTrailer, stdout );
+    else if (ENABLED_OPT( SHELL ))
+        printf( "\nenv | egrep %s_\n", pOpts->pzPROGNAME );
+
+    fflush( stdout );
+    fchmod( STDOUT_FILENO, 0755 );
+    fclose( stdout );
+}
+
+
+static void
+textToVariable( tOptions* pOpts, teTextTo whichVar, tOptDesc* pOD )
+{
+    int  nlHoldCt = 0;
+    int  pipeFd[2];
+    FILE* fp;
+
+#   define _TT_(n) tSCC z ## n [] = #n;
+    TEXTTO_TABLE
+#   undef _TT_
+#   define _TT_(n) z ## n ,
+      static const char*  apzTTNames[] = { TEXTTO_TABLE };
+#   undef _TT_
+
+    printf( "%s_%s_TEXT='", pOpts->pzPROGNAME, apzTTNames[ whichVar ]);
+    fflush( stdout );
+
+    if (pipe( pipeFd ) != 0) {
+        fprintf( stderr, zBadPipe, errno, strerror( errno ));
+        exit( EXIT_FAILURE );
+    }
+
+    switch (fork()) {
+    case -1:
+        fprintf( stderr, zForkFail, errno, strerror(errno), pOpts->pzProgName);
+        exit( EXIT_FAILURE );
+        break;
+
+    case 0:
+        dup2( pipeFd[1], STDERR_FILENO );
+        dup2( pipeFd[1], STDOUT_FILENO );
+        close( pipeFd[0] );
+
+        switch (whichVar) {
+        case TT_LONGUSAGE:
+            (*(pOpts->pUsageProc))( pOpts, EXIT_SUCCESS );
+            /* NOTREACHED */
+            exit( EXIT_FAILURE );
+
+        case TT_USAGE:
+            (*(pOpts->pUsageProc))( pOpts, EXIT_FAILURE );
+            /* NOTREACHED */
+            exit( EXIT_FAILURE );
+
+        case TT_VERSION:
+            pOD->pzLastArg = "c";
+            optionPrintVersion( pOpts, pOD );
+            /* NOTREACHED */
+
+        default:
+            exit( EXIT_FAILURE );
+        }
+
+    default:
+        close( pipeFd[1] );
+        fp = fdopen( pipeFd[0], "r" FOPEN_BINARY_FLAG );
+    }
+
+    for (;;) {
+        int  ch = fgetc( fp );
+        switch (ch) {
+
+        case '\n':
+            nlHoldCt++;
+            break;
+
+        case '\'':
+            while (nlHoldCt > 0) {
+                fputc( '\n', stdout );
+                nlHoldCt--;
+            }
+            fputs( "'\\''", stdout );
+            break;
+
+        case EOF:
+            goto endCharLoop;
+
+        default:
+            while (nlHoldCt > 0) {
+                fputc( '\n', stdout );
+                nlHoldCt--;
+            }
+            fputc( ch, stdout );
+            break;
+        }
+    } endCharLoop:;
+
+    fputs( "'\n\n", stdout );
+    close( pipeFd[0] );
+}
+
+
+static void
+emitUsage( tOptions* pOpts )
+{
+    char     zTimeBuf[ AO_NAME_SIZE ];
+
+    /*
+     *  First, switch stdout to the output file name.
+     *  Then, change the program name to the one defined
+     *  by the definitions (rather than the current
+     *  executable name).  Down case the upper cased name.
+     */
+    if (pzLeader != NULL)
+        fputs( pzLeader, stdout );
+
+    {
+        tSCC    zStdout[] = "stdout";
+        tCC*    pzOutName;
+
+        {
+            time_t    curTime = time( NULL );
+            struct tm*  pTime = localtime( &curTime );
+            strftime( zTimeBuf, AO_NAME_SIZE, "%A %B %e, %Y at %r %Z", pTime );
+        }
+
+        if (HAVE_OPT( SCRIPT ))
+             pzOutName = OPT_ARG( SCRIPT );
+        else pzOutName = zStdout;
+
+        if ((pzLeader == NULL) && (pzShell != NULL))
+            printf( "#! %s\n", pzShell );
+
+        printf( zPreamble, zStartMarker, pzOutName, zTimeBuf );
+    }
+
+    /*
+     *  Get a copy of the original program name in lower case
+     */
+    {
+        char* pzPN = zTimeBuf;
+        tCC*  pz   = pOpts->pzPROGNAME;
+        for (;;) {
+            if ((*pzPN++ = tolower( *pz++ )) == '\0')
+                break;
+        }
+    }
+
+    printf( zEndPreamble, pOpts->pzPROGNAME );
+
+    pOpts->pzProgPath = pOpts->pzProgName = zTimeBuf;
+    textToVariable( pOpts, TT_LONGUSAGE, NULL );
+    textToVariable( pOpts, TT_USAGE,     NULL );
+
+    {
+        tOptDesc* pOptDesc = pOpts->pOptDesc;
+        int       optionCt = pOpts->optCt;
+
+        for (;;) {
+            if (pOptDesc->pOptProc == optionPrintVersion) {
+                textToVariable( pOpts, TT_VERSION, pOptDesc );
+                break;
+            }
+
+            if (--optionCt <= 0)
+                break;
+            pOptDesc++;
+        }
+    }
+}
+
+
+static void
+emitSetup( tOptions* pOpts )
+{
+    tOptDesc* pOptDesc = pOpts->pOptDesc;
+    int       optionCt = pOpts->presetOptCt;
+    const char* pzFmt;
+    const char* pzDefault;
+
+    for (;optionCt > 0; pOptDesc++, --optionCt) {
+        char zVal[16];
+
+        /*
+         *  Options that are either usage documentation or are compiled out
+         *  are not to be processed.
+         */
+        if (SKIP_OPT(pOptDesc) || (pOptDesc->pz_NAME == NULL))
+            continue;
+
+        if (pOptDesc->optMaxCt > 1)
+             pzFmt = zMultiDef;
+        else pzFmt = zSingleDef;
+
+        /*
+         *  IF this is an enumeration/bitmask option, then convert the value
+         *  to a string before printing the default value.
+         */
+        switch (OPTST_GET_ARGTYPE(pOptDesc->fOptState)) {
+        case OPARG_TYPE_ENUMERATION:
+            (*(pOptDesc->pOptProc))( (tOptions*)2UL, pOptDesc );
+            pzDefault = pOptDesc->pzLastArg;
+            break;
+
+        /*
+         *  Numeric and membership bit options are just printed as a number.
+         */
+        case OPARG_TYPE_NUMERIC:
+        case OPARG_TYPE_MEMBERSHIP:
+            snprintf( zVal, sizeof( zVal ), "%ld", (tAoUL)pOptDesc->pzLastArg );
+            pzDefault = zVal;
+            break;
+
+        default:
+            if (pOptDesc->pzLastArg == NULL) {
+                if (pzFmt == zSingleDef)
+                    pzFmt = zSingleNoDef;
+                pzDefault = NULL;
+            }
+            else
+                pzDefault = pOptDesc->pzLastArg;
+        }
+
+        printf( pzFmt, pOpts->pzPROGNAME, pOptDesc->pz_NAME, pzDefault );
+    }
+}
+
+
+static void
+printOptionAction( tOptions* pOpts, tOptDesc* pOptDesc )
+{
+    if (pOptDesc->pOptProc == optionPrintVersion)
+        printf( zTextExit, pOpts->pzPROGNAME, "VERSION" );
+
+    else if (pOptDesc->pOptProc == optionPagedUsage)
+        printf( zPagedUsageExit, pOpts->pzPROGNAME );
+
+    else if (pOptDesc->pOptProc == optionLoadOpt) {
+        printf( zCmdFmt, "echo 'Warning:  Cannot load options files' >&2" );
+        printf( zCmdFmt, "OPT_ARG_NEEDED=YES" );
+
+    } else if (pOptDesc->pz_NAME == NULL) {
+
+        if (pOptDesc->pOptProc == NULL) {
+            printf( zCmdFmt, "echo 'Warning:  Cannot save options files' "
+                    ">&2" );
+            printf( zCmdFmt, "OPT_ARG_NEEDED=OK" );
+        } else
+            printf( zTextExit, pOpts->pzPROGNAME, "LONGUSAGE" );
+
+    } else {
+        if (pOptDesc->optMaxCt == 1)
+            printf( zSingleArg, pOpts->pzPROGNAME, pOptDesc->pz_NAME );
+        else {
+            if ((unsigned)pOptDesc->optMaxCt < NOLIMIT)
+                printf( zCountTest, pOpts->pzPROGNAME,
+                        pOptDesc->pz_NAME, pOptDesc->optMaxCt );
+
+            printf( zMultiArg, pOpts->pzPROGNAME, pOptDesc->pz_NAME );
+        }
+
+        /*
+         *  Fix up the args.
+         */
+        if (OPTST_GET_ARGTYPE(pOptDesc->fOptState) == OPARG_TYPE_NONE) {
+            printf( zCantArg, pOpts->pzPROGNAME, pOptDesc->pz_NAME );
+
+        } else if (pOptDesc->fOptState & OPTST_ARG_OPTIONAL) {
+            printf( zMayArg,  pOpts->pzPROGNAME, pOptDesc->pz_NAME );
+
+        } else {
+            fputs( zMustArg, stdout );
+        }
+    }
+    fputs( zOptionEndSelect, stdout );
+}
+
+
+static void
+printOptionInaction( tOptions* pOpts, tOptDesc* pOptDesc )
+{
+    if (pOptDesc->pOptProc == optionLoadOpt) {
+        printf( zCmdFmt, "echo 'Warning:  Cannot suppress the loading of "
+                "options files' >&2" );
+
+    } else if (pOptDesc->optMaxCt == 1)
+        printf( zNoSingleArg, pOpts->pzPROGNAME,
+                pOptDesc->pz_NAME, pOptDesc->pz_DisablePfx );
+    else
+        printf( zNoMultiArg, pOpts->pzPROGNAME,
+                pOptDesc->pz_NAME, pOptDesc->pz_DisablePfx );
+
+    printf( zCmdFmt, "OPT_ARG_NEEDED=NO" );
+    fputs( zOptionEndSelect, stdout );
+}
+
+
+static void
+emitFlag( tOptions* pOpts )
+{
+    tOptDesc* pOptDesc = pOpts->pOptDesc;
+    int       optionCt = pOpts->optCt;
+
+    fputs( zOptionCase, stdout );
+
+    for (;optionCt > 0; pOptDesc++, --optionCt) {
+
+        if (SKIP_OPT(pOptDesc))
+            continue;
+
+        if (isprint( pOptDesc->optValue )) {
+            printf( zOptionFlag, pOptDesc->optValue );
+            printOptionAction( pOpts, pOptDesc );
+        }
+    }
+    printf( zOptionUnknown, "flag", pOpts->pzPROGNAME );
+}
+
+
+/*
+ *  Emit the match text for a long option
+ */
+static void
+emitMatchExpr( tCC* pzMatchName, tOptDesc* pCurOpt, tOptions* pOpts )
+{
+    tOptDesc* pOD = pOpts->pOptDesc;
+    int       oCt = pOpts->optCt;
+    int       min = 1;
+    char      zName[ 256 ];
+    char*     pz  = zName;
+
+    for (;;) {
+        int matchCt = 0;
+
+        /*
+         *  Omit the current option, Documentation opts and compiled out opts.
+         */
+        if ((pOD == pCurOpt) || SKIP_OPT(pOD)){
+            if (--oCt <= 0)
+                break;
+            pOD++;
+            continue;
+        }
+
+        /*
+         *  Check each character of the name case insensitively.
+         *  They must not be the same.  They cannot be, because it would
+         *  not compile correctly if they were.
+         */
+        while (  toupper( pOD->pz_Name[matchCt] )
+              == toupper( pzMatchName[matchCt] ))
+            matchCt++;
+
+        if (matchCt > min)
+            min = matchCt;
+
+        /*
+         *  Check the disablement name, too.
+         */
+        if (pOD->pz_DisableName != NULL) {
+            matchCt = 0;
+            while (  toupper( pOD->pz_DisableName[matchCt] )
+                  == toupper( pzMatchName[matchCt] ))
+                matchCt++;
+            if (matchCt > min)
+                min = matchCt;
+        }
+        if (--oCt <= 0)
+            break;
+        pOD++;
+    }
+
+    /*
+     *  IF the 'min' is all or one short of the name length,
+     *  THEN the entire string must be matched.
+     */
+    if (  (pzMatchName[min  ] == NUL)
+       || (pzMatchName[min+1] == NUL) )
+        printf( zOptionFullName, pzMatchName );
+
+    else {
+        int matchCt = 0;
+        for (; matchCt <= min; matchCt++)
+            *pz++ = pzMatchName[matchCt];
+
+        for (;;) {
+            *pz = NUL;
+            printf( zOptionPartName, zName );
+            *pz++ = pzMatchName[matchCt++];
+            if (pzMatchName[matchCt] == NUL) {
+                *pz = NUL;
+                printf( zOptionFullName, zName );
+                break;
+            }
+        }
+    }
+}
+
+
+/*
+ *  Emit GNU-standard long option handling code
+ */
+static void
+emitLong( tOptions* pOpts )
+{
+    tOptDesc* pOD = pOpts->pOptDesc;
+    int       ct  = pOpts->optCt;
+
+    fputs( zOptionCase, stdout );
+
+    /*
+     *  do each option, ...
+     */
+    do  {
+        /*
+         *  Documentation & compiled-out options
+         */
+        if (SKIP_OPT(pOD))
+            continue;
+
+        emitMatchExpr( pOD->pz_Name, pOD, pOpts );
+        printOptionAction( pOpts, pOD );
+
+        /*
+         *  Now, do the same thing for the disablement version of the option.
+         */
+        if (pOD->pz_DisableName != NULL) {
+            emitMatchExpr( pOD->pz_DisableName, pOD, pOpts );
+            printOptionInaction( pOpts, pOD );
+        }
+    } while (pOD++, --ct > 0);
+
+    printf( zOptionUnknown, "option", pOpts->pzPROGNAME );
+}
+
+
+static void
+openOutput( const char* pzFile )
+{
+    FILE* fp;
+    char* pzData = NULL;
+    struct stat stbf;
+
+    do  {
+        char*  pzScan;
+        int    sizeLeft;
+
+        /*
+         *  IF we cannot stat the file,
+         *  THEN assume we are creating a new file.
+         *       Skip the loading of the old data.
+         */
+        if (stat( pzFile, &stbf ) != 0)
+            break;
+
+        /*
+         *  The file must be a regular file
+         */
+        if (! S_ISREG( stbf.st_mode )) {
+            fprintf( stderr, zNotFile, pzFile );
+            exit( EXIT_FAILURE );
+        }
+
+        pzData = (char*)malloc( stbf.st_size + 1 );
+        fp = fopen( pzFile, "r" FOPEN_BINARY_FLAG );
+
+        sizeLeft = stbf.st_size;
+        pzScan   = pzData;
+
+        /*
+         *  Read in all the data as fast as our OS will let us.
+         */
+        for (;;) {
+            int inct = fread( (void*)pzScan, 1, sizeLeft, fp );
+            if (inct == 0)
+                break;
+
+            pzScan   += inct;
+            sizeLeft -= inct;
+
+            if (sizeLeft == 0)
+                break;
+        }
+
+        /*
+         *  NUL-terminate the leader and look for the trailer
+         */
+        *pzScan = '\0';
+        fclose( fp );
+        pzScan  = strstr( pzData, zStartMarker );
+        if (pzScan == NULL) {
+            pzTrailer = pzData;
+            break;
+        }
+
+        *(pzScan++) = NUL;
+        pzScan  = strstr( pzScan, zTrailerMarker );
+        if (pzScan == NULL) {
+            pzTrailer = pzData;
+            break;
+        }
+
+        /*
+         *  Check to see if the data contains
+         *  our marker.  If it does, then we will skip over it
+         */
+        pzTrailer = pzScan + sizeof( zTrailerMarker ) - 1;
+        pzLeader  = pzData;
+    } while (AG_FALSE);
+
+    freopen( pzFile, "w" FOPEN_BINARY_FLAG, stdout );
+}
+
+
+/*=export_func genshelloptUsage
+ * private:
+ * what: The usage function for the genshellopt generated program
+ *
+ * arg:  + tOptions* + pOpts    + program options descriptor +
+ * arg:  + int       + exitCode + usage text type to produce +
+ *
+ * doc:
+ *  This function is used to create the usage strings for the option
+ *  processing shell script code.  Two child processes are spawned
+ *  each emitting the usage text in either the short (error exit)
+ *  style or the long style.  The generated program will capture this
+ *  and create shell script variables containing the two types of text.
+=*/
+void
+genshelloptUsage( tOptions*  pOpts, int exitCode )
+{
+    /*
+     *  IF not EXIT_SUCCESS,
+     *  THEN emit the short form of usage.
+     */
+    if (exitCode != EXIT_SUCCESS)
+        optionUsage( pOpts, exitCode );
+    fflush( stderr );
+    fflush( stdout );
+
+    option_usage_fp = stdout;
+
+    /*
+     *  First, print our usage
+     */
+    switch (fork()) {
+    case -1:
+        optionUsage( pOpts, EXIT_FAILURE );
+        /*NOTREACHED*/
+        _exit( EXIT_FAILURE );
+
+    case 0:
+        pagerState = PAGER_STATE_CHILD;
+        optionUsage( pOpts, EXIT_SUCCESS );
+        /*NOTREACHED*/
+        _exit( EXIT_FAILURE );
+
+    default:
+    {
+        int  stat;
+        wait( &stat );
+    }
+    }
+
+    /*
+     *  Generate the pzProgName, since optionProcess() normally
+     *  gets it from the command line
+     */
+    {
+        char* pz;
+        AGDUPSTR( pz, pShellParseOptions->pzPROGNAME, "program name" );
+        pShellParseOptions->pzProgName = pz;
+        while (*pz != NUL) {
+            *pz = tolower( *pz );
+            pz++;
+        }
+    }
+
+    /*
+     *  Separate the makeshell usage from the client usage
+     */
+    fprintf( option_usage_fp, zGenshell, pShellParseOptions->pzProgName );
+    fflush( option_usage_fp );
+
+    /*
+     *  Now, print the client usage.
+     */
+    switch (fork()) {
+    case 0:
+        pagerState = PAGER_STATE_CHILD;
+        /*FALLTHROUGH*/
+    case -1:
+        optionUsage( pShellParseOptions, EXIT_FAILURE );
+
+    default:
+    {
+        int  stat;
+        wait( &stat );
+    }
+    }
+
+    exit( EXIT_SUCCESS );
+}
+
+/*
+ * Local Variables:
+ * mode: C
+ * c-file-style: "stroustrup"
+ * tab-width: 4
+ * indent-tabs-mode: nil
+ * End:
+ * end of autoopts/makeshell.c */
diff --git a/sntp/libopts/nested.c b/sntp/libopts/nested.c
new file mode 100644 (file)
index 0000000..ef32f28
--- /dev/null
@@ -0,0 +1,705 @@
+
+/*
+ *  $Id: nested.c,v 4.4 2006/03/25 19:24:56 bkorb Exp $
+ *  Time-stamp:      "2005-07-27 10:10:28 bkorb"
+ *
+ *   Automated Options Nested Values module.
+ */
+
+/*
+ *  Automated Options copyright 1992-2006 Bruce Korb
+ *
+ *  Automated Options is free software.
+ *  You may redistribute it and/or modify it under the terms of the
+ *  GNU General Public License, as published by the Free Software
+ *  Foundation; either version 2, or (at your option) any later version.
+ *
+ *  Automated Options is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with Automated Options.  See the file "COPYING".  If not,
+ *  write to:  The Free Software Foundation, Inc.,
+ *             51 Franklin Street, Fifth Floor,
+ *             Boston, MA  02110-1301, USA.
+ *
+ * As a special exception, Bruce Korb gives permission for additional
+ * uses of the text contained in his release of AutoOpts.
+ *
+ * The exception is that, if you link the AutoOpts library with other
+ * files to produce an executable, this does not by itself cause the
+ * resulting executable to be covered by the GNU General Public License.
+ * Your use of that executable is in no way restricted on account of
+ * linking the AutoOpts library code into it.
+ *
+ * This exception does not however invalidate any other reasons why
+ * the executable file might be covered by the GNU General Public License.
+ *
+ * This exception applies only to the code released by Bruce Korb under
+ * the name AutoOpts.  If you copy code from other sources under the
+ * General Public License into a copy of AutoOpts, as the General Public
+ * License permits, the exception does not apply to the code that you add
+ * in this way.  To avoid misleading anyone as to the status of such
+ * modified files, you must delete this exception notice from them.
+ *
+ * If you write modifications of your own for AutoOpts, it is your choice
+ * whether to permit this exception to apply to your modifications.
+ * If you do not wish that, delete this exception notice.
+ */
+/* = = = START-STATIC-FORWARD = = = */
+/* static forward declarations maintained by :mkfwd */
+static void
+removeBackslashes( char* pzSrc );
+
+static const char*
+scanQuotedString( const char* pzTxt );
+
+static tOptionValue*
+addStringValue( void** pp, const char* pzName, size_t nameLen,
+                const char* pzValue, size_t dataLen );
+
+static tOptionValue*
+addBoolValue( void** pp, const char* pzName, size_t nameLen,
+                const char* pzValue, size_t dataLen );
+
+static tOptionValue*
+addNumberValue( void** pp, const char* pzName, size_t nameLen,
+                const char* pzValue, size_t dataLen );
+
+static tOptionValue*
+addNestedValue( void** pp, const char* pzName, size_t nameLen,
+                char* pzValue, size_t dataLen, tOptionLoadMode mode );
+
+static const char*
+scanNameEntry( const char* pzName, tOptionValue* pRes, tOptionLoadMode mode );
+
+static const char*
+scanXmlEntry( const char* pzName, tOptionValue* pRes, tOptionLoadMode mode );
+
+static void
+unloadNestedArglist( tArgList* pAL );
+
+static void
+sortNestedList( tArgList* pAL );
+/* = = = END-STATIC-FORWARD = = = */
+
+/*  removeBackslashes
+ *
+ *  This function assumes that all newline characters were preceeded by
+ *  backslashes that need removal.
+ */
+static void
+removeBackslashes( char* pzSrc )
+{
+    char* pzD = strchr(pzSrc, '\n');
+
+    if (pzD == NULL)
+        return;
+    *--pzD = '\n';
+
+    for (;;) {
+        char ch = ((*pzD++) = *(pzSrc++));
+        switch (ch) {
+        case '\n': *--pzD = ch; break;
+        case NUL:  return;
+        default:
+            ;
+        }
+    }
+}
+
+
+/*  scanQuotedString
+ *
+ *  Find the end of a quoted string, skipping escaped quote characters.
+ */
+static const char*
+scanQuotedString( const char* pzTxt )
+{
+    char q = *(pzTxt++); /* remember the type of quote */
+
+    for (;;) {
+        char ch = *(pzTxt++);
+        if (ch == NUL)
+            return pzTxt-1;
+
+        if (ch == q)
+            return pzTxt;
+
+        if (ch == '\\') {
+            ch = *(pzTxt++);
+            /*
+             *  IF the next character is NUL, drop the backslash, too.
+             */
+            if (ch == NUL)
+                return pzTxt - 2;
+
+            /*
+             *  IF the quote character or the escape character were escaped,
+             *  then skip both, as long as the string does not end.
+             */
+            if ((ch == q) || (ch == '\\')) {
+                if (*(pzTxt++) == NUL)
+                    return pzTxt-1;
+            }
+        }
+    }
+}
+
+
+/*  addStringValue
+ *
+ *  Associate a name with either a string or no value.
+ */
+static tOptionValue*
+addStringValue( void** pp, const char* pzName, size_t nameLen,
+                const char* pzValue, size_t dataLen )
+{
+    tOptionValue* pNV;
+    size_t sz = nameLen + dataLen + sizeof(*pNV);
+
+    pNV = AGALOC( sz, "option name/str value pair" );
+    if (pNV == NULL)
+        return NULL;
+
+    if (pzValue == NULL) {
+        pNV->valType = OPARG_TYPE_NONE;
+        pNV->pzName = pNV->v.strVal;
+
+    } else {
+        pNV->valType = OPARG_TYPE_STRING;
+        if (dataLen > 0)
+            memcpy( pNV->v.strVal, pzValue, dataLen );
+        pNV->v.strVal[dataLen] = NUL;
+        pNV->pzName = pNV->v.strVal + dataLen + 1;
+    }
+
+    memcpy( pNV->pzName, pzName, nameLen );
+    pNV->pzName[ nameLen ] = NUL;
+    addArgListEntry( pp, pNV );
+    return pNV;
+}
+
+
+/*  addBoolValue
+ *
+ *  Associate a name with either a string or no value.
+ */
+static tOptionValue*
+addBoolValue( void** pp, const char* pzName, size_t nameLen,
+                const char* pzValue, size_t dataLen )
+{
+    tOptionValue* pNV;
+    size_t sz = nameLen + sizeof(*pNV) + 1;
+
+    pNV = AGALOC( sz, "option name/bool value pair" );
+    if (pNV == NULL)
+        return NULL;
+    while (isspace( *pzValue ) && (dataLen > 0)) {
+        dataLen--; pzValue++;
+    }
+    if (dataLen == 0)
+        pNV->v.boolVal = 0;
+    else if (isdigit( *pzValue ))
+        pNV->v.boolVal = atoi( pzValue );
+    else switch (*pzValue) {
+    case 'f':
+    case 'F':
+    case 'n':
+    case 'N':
+        pNV->v.boolVal = 0; break;
+    default:
+        pNV->v.boolVal = 1;
+    }
+
+    pNV->valType = OPARG_TYPE_BOOLEAN;
+    pNV->pzName = (char*)(pNV + 1);
+    memcpy( pNV->pzName, pzName, nameLen );
+    pNV->pzName[ nameLen ] = NUL;
+    addArgListEntry( pp, pNV );
+    return pNV;
+}
+
+
+/*  addNumberValue
+ *
+ *  Associate a name with either a string or no value.
+ */
+static tOptionValue*
+addNumberValue( void** pp, const char* pzName, size_t nameLen,
+                const char* pzValue, size_t dataLen )
+{
+    tOptionValue* pNV;
+    size_t sz = nameLen + sizeof(*pNV) + 1;
+
+    pNV = AGALOC( sz, "option name/bool value pair" );
+    if (pNV == NULL)
+        return NULL;
+    while (isspace( *pzValue ) && (dataLen > 0)) {
+        dataLen--; pzValue++;
+    }
+    if (dataLen == 0)
+        pNV->v.boolVal = 0;
+    else
+        pNV->v.boolVal = atoi( pzValue );
+
+    pNV->valType = OPARG_TYPE_NUMERIC;
+    pNV->pzName = (char*)(pNV + 1);
+    memcpy( pNV->pzName, pzName, nameLen );
+    pNV->pzName[ nameLen ] = NUL;
+    addArgListEntry( pp, pNV );
+    return pNV;
+}
+
+
+/*  addNestedValue
+ *
+ *  Associate a name with either a string or no value.
+ */
+static tOptionValue*
+addNestedValue( void** pp, const char* pzName, size_t nameLen,
+                char* pzValue, size_t dataLen, tOptionLoadMode mode )
+{
+    tOptionValue* pNV;
+
+    if (dataLen == 0) {
+        size_t sz = nameLen + sizeof(*pNV) + 1;
+        pNV = AGALOC( sz, "empty nested value pair" );
+        if (pNV == NULL)
+            return NULL;
+        pNV->v.nestVal = NULL;
+        pNV->valType = OPARG_TYPE_HIERARCHY;
+        pNV->pzName = (char*)(pNV + 1);
+        memcpy( pNV->pzName, pzName, nameLen );
+        pNV->pzName[ nameLen ] = NUL;
+
+    } else {
+        pNV = optionLoadNested( pzValue, pzName, nameLen, mode );
+    }
+
+    if (pNV != NULL)
+        addArgListEntry( pp, pNV );
+
+    return pNV;
+}
+
+
+/*  scanNameEntry
+ *
+ *  We have an entry that starts with a name.  Find the end of it, cook it
+ *  (if called for) and create the name/value association.
+ */
+static const char*
+scanNameEntry( const char* pzName, tOptionValue* pRes, tOptionLoadMode mode )
+{
+    tOptionValue* pNV;
+    const char* pzScan = pzName+1;
+    const char* pzVal;
+    size_t nameLen = 1;
+    size_t dataLen = 0;
+
+    while (ISNAMECHAR( *pzScan ))  { pzScan++; nameLen++; }
+
+    while (isspace( *pzScan )) {
+        char ch = *(pzScan++);
+        if ((ch == '\n') || (ch == ',')) {
+            addStringValue( &(pRes->v.nestVal), pzName, nameLen, NULL, 0 );
+            return pzScan - 1;
+        }
+    }
+
+    switch (*pzScan) {
+    case '=':
+    case ':':
+        while (isspace( *++pzScan ))  ;
+        switch (*pzScan) {
+        case ',':  goto comma_char;
+        case '"':
+        case '\'': goto quote_char;
+        case NUL:  addStringValue( &(pRes->v.nestVal), pzName, nameLen, NULL, 0);
+                   goto leave_scan_name;
+        default:   goto default_char;
+        }
+
+    case ',':
+    comma_char:
+        pzScan++;
+        /* FALLTHROUGH */
+
+    case NUL:
+        addStringValue( &(pRes->v.nestVal), pzName, nameLen, NULL, 0 );
+        break;
+
+    case '"':
+    case '\'':
+    quote_char:
+        pzVal = pzScan;
+        pzScan = scanQuotedString( pzScan );
+        dataLen = pzScan - pzVal;
+        pNV = addStringValue( &(pRes->v.nestVal), pzName, nameLen,
+                              pzVal, dataLen );
+        if ((pNV != NULL) && (mode == OPTION_LOAD_COOKED))
+            ao_string_cook( pNV->v.strVal, NULL );
+        break;
+
+    default:
+    default_char:
+        /*
+         *  We have found some strange text value.  It ends with a newline
+         *  or a comma.
+         */
+        pzVal = pzScan;
+        for (;;) {
+            char ch = *(pzScan++);
+            switch (ch) {
+            case '\n':
+                if ((pzScan > pzVal + 2) && (pzScan[-2] == '\\'))
+                    continue;
+                /* FALLTHROUGH */
+
+            case ',':
+                dataLen = (pzScan - pzVal) - 1;
+                pNV = addStringValue( &(pRes->v.nestVal), pzName, nameLen,
+                                      pzVal, dataLen );
+                if (pNV != NULL)
+                    removeBackslashes( pNV->v.strVal );
+                goto leave_scan_name;
+            }
+        }
+        break;
+    } leave_scan_name:;
+
+    return pzScan;
+}
+
+
+/*  scanXmlEntry
+ *
+ *  We've found a '<' character.  We ignore this if it is a comment or a
+ *  directive.  If it is something else, then whatever it is we are looking
+ *  at is bogus.  Returning NULL stops processing.
+ */
+static const char*
+scanXmlEntry( const char* pzName, tOptionValue* pRes, tOptionLoadMode mode )
+{
+    size_t nameLen = 1, valLen = 0;
+    const char*   pzScan = ++pzName;
+    const char*   pzVal;
+    tOptionValue  valu;
+    tOptionValue* pNewVal;
+
+    if (! isalpha(*pzName)) {
+        switch (*pzName) {
+        default:
+            pzName = NULL;
+            break;
+
+        case '!':
+            pzName = strstr( pzName, "-->" );
+            if (pzName != NULL)
+                pzName += 3;
+            break;
+
+        case '?':
+            pzName = strchr( pzName, '>' );
+            if (pzName != NULL)
+                pzName++;
+            break;
+        }
+        return pzName;
+    }
+
+    while (isalpha( *++pzScan ))  nameLen++;
+    if (nameLen > 64)
+        return NULL;
+    valu.valType = OPARG_TYPE_STRING;
+
+    switch (*pzScan) {
+    case ' ':
+    case '\t':
+        pzScan = parseAttributes( NULL, (char*)pzScan, &mode, &valu );
+        if (*pzScan == '>') {
+            pzScan++;
+            break;
+        }
+
+        if (*pzScan != '/')
+            return NULL;
+        /* FALLTHROUGH */
+
+    case '/':
+        if (*++pzScan != '>')
+            return NULL;
+        addStringValue( &(pRes->v.nestVal), pzName, nameLen, NULL, 0 );
+        return pzScan+2;
+
+    default:  return NULL;
+    case '>': break;
+    }
+
+    pzVal = pzScan;
+
+    {
+        char z[68];
+        char* pzD = z;
+        int  ct = nameLen;
+        const char* pzS = pzName;
+
+        *(pzD++) = '<';
+        *(pzD++) = '/';
+
+        do  {
+            *(pzD++) = *(pzS++);
+        } while (--ct > 0);
+        *(pzD++) = '>';
+        *pzD = NUL;
+
+        pzScan = strstr( pzScan, z );
+        if (pzScan == NULL)
+            return NULL;
+        valLen = (pzScan - pzVal);
+        pzScan += nameLen + 3;
+        while (isspace( *pzScan ))  pzScan++;
+    }
+
+    switch (valu.valType) {
+    case OPARG_TYPE_NONE:
+        addStringValue( &(pRes->v.nestVal), pzName, nameLen, NULL, 0 );
+        break;
+
+    case OPARG_TYPE_STRING:
+        pNewVal =
+            addStringValue( &(pRes->v.nestVal), pzName, nameLen, pzVal, valLen );
+        if (mode == OPTION_LOAD_KEEP)
+            break;
+        mungeString( pNewVal->v.strVal, mode );
+        break;
+
+    case OPARG_TYPE_BOOLEAN:
+        addBoolValue(   &(pRes->v.nestVal), pzName, nameLen, pzVal, valLen );
+        break;
+
+    case OPARG_TYPE_NUMERIC:
+        addNumberValue( &(pRes->v.nestVal), pzName, nameLen, pzVal, valLen );
+        break;
+
+    case OPARG_TYPE_HIERARCHY:
+    {
+        char* pz = AGALOC( valLen+1, "hierarchical scan" );
+        if (pz == NULL)
+            break;
+        memcpy( pz, pzVal, valLen );
+        pz[valLen] = NUL;
+        addNestedValue( &(pRes->v.nestVal), pzName, nameLen, pz, valLen, mode );
+        free(pz);
+        break;
+    }
+
+    case OPARG_TYPE_ENUMERATION:
+    case OPARG_TYPE_MEMBERSHIP:
+    default:
+        break;
+    }
+
+    return pzScan;
+}
+
+
+static void
+unloadNestedArglist( tArgList* pAL )
+{
+    int ct = pAL->useCt;
+    tOptionValue** ppNV = (tOptionValue**)(pAL->apzArgs);
+
+    while (ct-- > 0) {
+        tOptionValue* pNV = *(ppNV++);
+        if (pNV->valType == OPARG_TYPE_HIERARCHY)
+            unloadNestedArglist( pNV->v.nestVal );
+        free( pNV );
+    }
+
+    free( (void*)pAL );
+}
+
+
+/*=export_func  optionUnloadNested
+ *
+ * what:  Deallocate the memory for a nested value
+ * arg:   + const tOptionValue* + pOptVal + the hierarchical value +
+ *
+ * doc:
+ *  A nested value needs to be deallocated.  The pointer passed in should
+ *  have been gotten from a call to @code{configFileLoad()} (See
+ *  @pxref{libopts-configFileLoad}).
+=*/
+void
+optionUnloadNested( const tOptionValue* pOV )
+{
+    if (pOV == NULL) return;
+    if (pOV->valType != OPARG_TYPE_HIERARCHY) {
+        errno = EINVAL;
+        return;
+    }
+
+    unloadNestedArglist( pOV->v.nestVal );
+
+    free( (void*)pOV );
+}
+
+
+/*  sortNestedList
+ *
+ *  This is a _stable_ sort.  The entries are sorted alphabetically,
+ *  but within entries of the same name the ordering is unchanged.
+ *  Typically, we also hope the input is sorted.
+ */
+static void
+sortNestedList( tArgList* pAL )
+{
+    int ix;
+    int lm = pAL->useCt;
+
+    /*
+     *  This loop iterates "useCt" - 1 times.
+     */
+    for (ix = 0; ++ix < lm;) {
+        int iy = ix-1;
+        tOptionValue* pNewNV = (tOptionValue*)pAL->apzArgs[ix];
+        tOptionValue* pOldNV = (tOptionValue*)pAL->apzArgs[iy];
+
+        /*
+         *  For as long as the new entry precedes the "old" entry,
+         *  move the old pointer.  Stop before trying to extract the
+         *  "-1" entry.
+         */
+        while (strcmp( pOldNV->pzName, pNewNV->pzName ) > 0) {
+            pAL->apzArgs[iy+1] = (void*)pOldNV;
+            pOldNV = (tOptionValue*)pAL->apzArgs[--iy];
+            if (iy < 0)
+                break;
+        }
+
+        /*
+         *  Always store the pointer.  Sometimes it is redundant,
+         *  but the redundancy is cheaper than a test and branch sequence.
+         */
+        pAL->apzArgs[iy+1] = (void*)pNewNV;
+    }
+}
+
+
+/*=export_func  optionLoadNested
+ * private:
+ *
+ * what:  parse a hierarchical option argument
+ * arg:   + const char*     + pzTxt   + the text to scan +
+ * arg:   + const char*     + pzName  + the name for the text +
+ * arg:   + size_t          + nameLen + the length of "name"  +
+ * arg:   + tOptionLoadMode + mode    + the value formation mode    +
+ *
+ * ret_type:  tOptionValue*
+ * ret_desc:  An allocated, compound value structure
+ *
+ * doc:
+ *  A block of text represents a series of values.  It may be an
+ *  entire configuration file, or it may be an argument to an
+ *  option that takes a hierarchical value.
+=*/
+tOptionValue*
+optionLoadNested( const char* pzTxt, const char* pzName, size_t nameLen,
+                  tOptionLoadMode mode )
+{
+    tOptionValue* pRes;
+    tArgList*     pAL;
+
+    /*
+     *  Make sure we have some data and we have space to put what we find.
+     */
+    if (pzTxt == NULL) {
+        errno = EINVAL;
+        return NULL;
+    }
+    while (isspace( *pzTxt ))  pzTxt++;
+    if (*pzTxt == NUL) {
+        errno = ENOENT;
+        return NULL;
+    }
+    pRes = AGALOC( sizeof(*pRes) + nameLen + 1, "nested args" );
+    if (pRes == NULL) {
+        errno = ENOMEM;
+        return NULL;
+    }
+    pRes->valType   = OPARG_TYPE_HIERARCHY;
+    pRes->pzName    = (char*)(pRes + 1);
+    memcpy( pRes->pzName, pzName, nameLen );
+    pRes->pzName[ nameLen ] = NUL;
+
+    pAL = AGALOC( sizeof(*pAL), "nested arg list" );
+    if (pAL == NULL) {
+        free( pRes );
+        return NULL;
+    }
+    pRes->v.nestVal = pAL;
+    pAL->useCt   = 0;
+    pAL->allocCt = MIN_ARG_ALLOC_CT;
+
+    /*
+     *  Scan until we hit a NUL.
+     */
+    do  {
+        while (isspace( *pzTxt ))  pzTxt++;
+        if (isalpha( *pzTxt )) {
+            pzTxt = scanNameEntry( pzTxt, pRes, mode );
+        }
+        else switch (*pzTxt) {
+        case NUL: goto scan_done;
+        case '<': pzTxt = scanXmlEntry( pzTxt, pRes, mode );
+                  if (*pzTxt == ',') pzTxt++; break;
+        case '#': pzTxt = strchr( pzTxt, '\n' );             break;
+        default:  goto woops;
+        }
+    } while (pzTxt != NULL); scan_done:;
+
+    pAL = pRes->v.nestVal;
+    if (pAL->useCt != 0) {
+        sortNestedList( pAL );
+        return pRes;
+    }
+
+ woops:
+    free( pRes->v.nestVal );
+    free( pRes );
+    return NULL;
+}
+
+
+/*=export_func  optionNestedVal
+ * private:
+ *
+ * what:  parse a hierarchical option argument
+ * arg:   + tOptions* + pOpts    + program options descriptor +
+ * arg:   + tOptDesc* + pOptDesc + the descriptor for this arg +
+ *
+ * doc:
+ *  Nested value was found on the command line
+=*/
+void
+optionNestedVal( tOptions* pOpts, tOptDesc* pOD )
+{
+    tOptionValue* pOV =
+        optionLoadNested(pOD->pzLastArg, pOD->pz_Name, strlen( pOD->pz_Name ),
+                         OPTION_LOAD_UNCOOKED);
+
+    if (pOV != NULL)
+        addArgListEntry( &(pOD->optCookie), (void*)pOV );
+}
+/*
+ * Local Variables:
+ * mode: C
+ * c-file-style: "stroustrup"
+ * tab-width: 4
+ * indent-tabs-mode: nil
+ * End:
+ * end of autoopts/nested.c */
diff --git a/sntp/libopts/numeric.c b/sntp/libopts/numeric.c
new file mode 100644 (file)
index 0000000..54be7c1
--- /dev/null
@@ -0,0 +1,89 @@
+
+/*
+ *  $Id: numeric.c,v 4.6 2006/03/25 19:24:56 bkorb Exp $
+ *  Time-stamp:      "2005-02-14 08:22:56 bkorb"
+ */
+
+/*
+ *  Automated Options copyright 1992-2006 Bruce Korb
+ *
+ *  Automated Options is free software.
+ *  You may redistribute it and/or modify it under the terms of the
+ *  GNU General Public License, as published by the Free Software
+ *  Foundation; either version 2, or (at your option) any later version.
+ *
+ *  Automated Options is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with Automated Options.  See the file "COPYING".  If not,
+ *  write to:  The Free Software Foundation, Inc.,
+ *             51 Franklin Street, Fifth Floor,
+ *             Boston, MA  02110-1301, USA.
+ *
+ * As a special exception, Bruce Korb gives permission for additional
+ * uses of the text contained in his release of AutoOpts.
+ *
+ * The exception is that, if you link the AutoOpts library with other
+ * files to produce an executable, this does not by itself cause the
+ * resulting executable to be covered by the GNU General Public License.
+ * Your use of that executable is in no way restricted on account of
+ * linking the AutoOpts library code into it.
+ *
+ * This exception does not however invalidate any other reasons why
+ * the executable file might be covered by the GNU General Public License.
+ *
+ * This exception applies only to the code released by Bruce Korb under
+ * the name AutoOpts.  If you copy code from other sources under the
+ * General Public License into a copy of AutoOpts, as the General Public
+ * License permits, the exception does not apply to the code that you add
+ * in this way.  To avoid misleading anyone as to the status of such
+ * modified files, you must delete this exception notice from them.
+ *
+ * If you write modifications of your own for AutoOpts, it is your choice
+ * whether to permit this exception to apply to your modifications.
+ * If you do not wish that, delete this exception notice.
+ */
+
+/*=export_func  optionNumericVal
+ * private:
+ *
+ * what:  Decipher a boolean value
+ * arg:   + tOptions* + pOpts    + program options descriptor +
+ * arg:   + tOptDesc* + pOptDesc + the descriptor for this arg +
+ *
+ * doc:
+ *  Decipher a numeric value.
+=*/
+void
+optionNumericVal( tOptions* pOpts, tOptDesc* pOD )
+{
+    char* pz;
+    long  val;
+
+    /*
+     *  Numeric options may have a range associated with it.
+     *  If it does, the usage procedure requests that it be
+     *  emitted by passing a NULL pOD pointer.
+     */
+    if ((pOD == NULL) || (pOD->pzLastArg == NULL))
+        return;
+
+    val = strtol( pOD->pzLastArg, &pz, 0 );
+    if (*pz != NUL) {
+        fprintf( stderr, zNotNumber, pOpts->pzProgName, pOD->pzLastArg );
+        (*(pOpts->pUsageProc))(pOpts, EXIT_FAILURE);
+    }
+
+    pOD->pzLastArg = (char*)val;
+}
+/*
+ * Local Variables:
+ * mode: C
+ * c-file-style: "stroustrup"
+ * tab-width: 4
+ * indent-tabs-mode: nil
+ * End:
+ * end of autoopts/numeric.c */
diff --git a/sntp/libopts/pgusage.c b/sntp/libopts/pgusage.c
new file mode 100644 (file)
index 0000000..9842a72
--- /dev/null
@@ -0,0 +1,154 @@
+
+/*
+ *  $Id: pgusage.c,v 4.7 2006/03/25 19:24:56 bkorb Exp $
+ * Time-stamp:      "2005-10-29 13:23:12 bkorb"
+ *
+ *   Automated Options Paged Usage module.
+ *
+ *  This routine will run run-on options through a pager so the
+ *  user may examine, print or edit them at their leisure.
+ */
+
+/*
+ *  Automated Options copyright 1992-2006 Bruce Korb
+ *
+ *  Automated Options is free software.
+ *  You may redistribute it and/or modify it under the terms of the
+ *  GNU General Public License, as published by the Free Software
+ *  Foundation; either version 2, or (at your option) any later version.
+ *
+ *  Automated Options is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with Automated Options.  See the file "COPYING".  If not,
+ *  write to:  The Free Software Foundation, Inc.,
+ *             51 Franklin Street, Fifth Floor,
+ *             Boston, MA  02110-1301, USA.
+ *
+ * As a special exception, Bruce Korb gives permission for additional
+ * uses of the text contained in his release of AutoOpts.
+ *
+ * The exception is that, if you link the AutoOpts library with other
+ * files to produce an executable, this does not by itself cause the
+ * resulting executable to be covered by the GNU General Public License.
+ * Your use of that executable is in no way restricted on account of
+ * linking the AutoOpts library code into it.
+ *
+ * This exception does not however invalidate any other reasons why
+ * the executable file might be covered by the GNU General Public License.
+ *
+ * This exception applies only to the code released by Bruce Korb under
+ * the name AutoOpts.  If you copy code from other sources under the
+ * General Public License into a copy of AutoOpts, as the General Public
+ * License permits, the exception does not apply to the code that you add
+ * in this way.  To avoid misleading anyone as to the status of such
+ * modified files, you must delete this exception notice from them.
+ *
+ * If you write modifications of your own for AutoOpts, it is your choice
+ * whether to permit this exception to apply to your modifications.
+ * If you do not wish that, delete this exception notice.
+ */
+
+tePagerState pagerState = PAGER_STATE_INITIAL;
+
+/*=export_func  optionPagedUsage
+ * private:
+ *
+ * what:  Decipher a boolean value
+ * arg:   + tOptions* + pOpts    + program options descriptor +
+ * arg:   + tOptDesc* + pOptDesc + the descriptor for this arg +
+ *
+ * doc:
+ *  Run the usage output through a pager.
+ *  This is very handy if it is very long.
+=*/
+void
+optionPagedUsage( tOptions* pOptions, tOptDesc* pOD )
+{
+    static pid_t     my_pid;
+    char zPageUsage[ 1024 ];
+
+    /*
+     *  IF we are being called after the usage proc is done
+     *     (and thus has called "exit(2)")
+     *  THEN invoke the pager to page through the usage file we created.
+     */
+    switch (pagerState) {
+    case PAGER_STATE_INITIAL:
+    {
+        my_pid  = getpid();
+#ifdef HAVE_SNPRINTF
+        snprintf(zPageUsage, sizeof(zPageUsage), "/tmp/use.%lu", (tAoUL)my_pid);
+#else
+        sprintf( zPageUsage, "/tmp/use.%lu", (tAoUL)my_pid );
+#endif
+        unlink( zPageUsage );
+
+        /*
+         *  Set usage output to this temporary file
+         */
+        option_usage_fp = fopen( zPageUsage, "w" FOPEN_BINARY_FLAG );
+        if (option_usage_fp == NULL)
+            _exit( EXIT_FAILURE );
+
+        pagerState = PAGER_STATE_READY;
+
+        /*
+         *  Set up so this routine gets called during the exit logic
+         */
+        atexit( (void(*)(void))optionPagedUsage );
+
+        /*
+         *  The usage procedure will now put the usage information into
+         *  the temporary file we created above.
+         */
+        (*pOptions->pUsageProc)( pOptions, EXIT_SUCCESS );
+
+        /*NOTREACHED*/
+        _exit( EXIT_FAILURE );
+    }
+
+    case PAGER_STATE_READY:
+    {
+        tSCC zPage[]  = "%1$s /tmp/use.%2$lu ; rm -f /tmp/use.%2$lu";
+        char* pzPager = getenv( "PAGER" );
+
+        /*
+         *  Use the "more(1)" program if "PAGER" has not been defined
+         */
+        if (pzPager == NULL)
+            pzPager = "more";
+
+        /*
+         *  Page the file and remove it when done.
+         */
+#ifdef HAVE_SNPRINTF
+        snprintf(zPageUsage, sizeof(zPageUsage), zPage, pzPager, (tAoUL)my_pid);
+#else
+        sprintf( zPageUsage, zPage, pzPager, (tAoUL)my_pid );
+#endif
+        fclose( stderr );
+        dup2( STDOUT_FILENO, STDERR_FILENO );
+
+        system( zPageUsage );
+    }
+
+    case PAGER_STATE_CHILD:
+        /*
+         *  This is a child process used in creating shell script usage.
+         */
+        break;
+    }
+}
+
+/*
+ * Local Variables:
+ * mode: C
+ * c-file-style: "stroustrup"
+ * tab-width: 4
+ * indent-tabs-mode: nil
+ * End:
+ * end of autoopts/pgusage.c */
diff --git a/sntp/libopts/proto.h b/sntp/libopts/proto.h
new file mode 100644 (file)
index 0000000..f150501
--- /dev/null
@@ -0,0 +1,88 @@
+/* -*- buffer-read-only: t -*- vi: set ro:
+ *
+ * Prototypes for autoopts
+ * Generated Sun Apr  9 11:50:00 PDT 2006
+ */
+#ifndef AUTOOPTS_PROTO_H_GUARD
+#define AUTOOPTS_PROTO_H_GUARD 1
+#ifndef LOCAL
+#  define LOCAL extern
+#  define REDEF_LOCAL 1
+#else
+#  undef  REDEF_LOCAL
+#endif
+/*
+ *  Extracted from autoopts.c
+ */
+LOCAL tSuccess
+handleOption( tOptions* pOpts, tOptState* pOptState );
+
+LOCAL tSuccess
+longOptionFind( tOptions* pOpts, char* pzOptName, tOptState* pOptState );
+
+LOCAL tSuccess
+shortOptionFind( tOptions* pOpts, tAoUC optValue, tOptState* pOptState );
+
+LOCAL tSuccess
+doImmediateOpts( tOptions* pOpts );
+
+LOCAL tSuccess
+doRegularOpts( tOptions* pOpts );
+
+/*
+ *  Extracted from configfile.c
+ */
+LOCAL void
+internalFileLoad( tOptions* pOpts );
+
+LOCAL char*
+parseAttributes(
+    tOptions*           pOpts,
+    char*               pzText,
+    tOptionLoadMode*    pMode,
+    tOptionValue*       pType );
+
+LOCAL tSuccess
+validateOptionsStruct( tOptions* pOpts, const char* pzProgram );
+
+/*
+ *  Extracted from environment.c
+ */
+LOCAL void
+doPrognameEnv( tOptions* pOpts, teEnvPresetType type );
+
+LOCAL void
+doEnvPresets( tOptions* pOpts, teEnvPresetType type );
+
+/*
+ *  Extracted from load.c
+ */
+LOCAL void
+mungeString( char* pzTxt, tOptionLoadMode mode );
+
+LOCAL void
+loadOptionLine(
+    tOptions*   pOpts,
+    tOptState*  pOS,
+    char*       pzLine,
+    tDirection  direction,
+    tOptionLoadMode   load_mode );
+
+/*
+ *  Extracted from sort.c
+ */
+LOCAL void
+optionSort( tOptions* pOpts );
+
+/*
+ *  Extracted from stack.c
+ */
+LOCAL void
+addArgListEntry( void** ppAL, void* entry );
+
+#ifdef REDEF_LOCAL
+#  undef LOCAL
+#  define LOCAL
+#endif
+
+#endif /* AUTOOPTS_PROTO_H_GUARD */
diff --git a/sntp/libopts/putshell.c b/sntp/libopts/putshell.c
new file mode 100644 (file)
index 0000000..feed57b
--- /dev/null
@@ -0,0 +1,333 @@
+
+/*
+ *  $Id: putshell.c,v 4.9 2006/03/25 19:24:56 bkorb Exp $
+ * Time-stamp:      "2005-12-13 10:28:47 bkorb"
+ *
+ *  This module will interpret the options set in the tOptions
+ *  structure and print them to standard out in a fashion that
+ *  will allow them to be interpreted by the Bourne or Korn shells.
+ */
+
+/*
+ *  Automated Options copyright 1992-2006 Bruce Korb
+ *
+ *  Automated Options is free software.
+ *  You may redistribute it and/or modify it under the terms of the
+ *  GNU General Public License, as published by the Free Software
+ *  Foundation; either version 2, or (at your option) any later version.
+ *
+ *  Automated Options is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with Automated Options.  See the file "COPYING".  If not,
+ *  write to:  The Free Software Foundation, Inc.,
+ *             51 Franklin Street, Fifth Floor,
+ *             Boston, MA  02110-1301, USA.
+ *
+ * As a special exception, Bruce Korb gives permission for additional
+ * uses of the text contained in his release of AutoOpts.
+ *
+ * The exception is that, if you link the AutoOpts library with other
+ * files to produce an executable, this does not by itself cause the
+ * resulting executable to be covered by the GNU General Public License.
+ * Your use of that executable is in no way restricted on account of
+ * linking the AutoOpts library code into it.
+ *
+ * This exception does not however invalidate any other reasons why
+ * the executable file might be covered by the GNU General Public License.
+ *
+ * This exception applies only to the code released by Bruce Korb under
+ * the name AutoOpts.  If you copy code from other sources under the
+ * General Public License into a copy of AutoOpts, as the General Public
+ * License permits, the exception does not apply to the code that you add
+ * in this way.  To avoid misleading anyone as to the status of such
+ * modified files, you must delete this exception notice from them.
+ *
+ * If you write modifications of your own for AutoOpts, it is your choice
+ * whether to permit this exception to apply to your modifications.
+ * If you do not wish that, delete this exception notice.
+ */
+
+/* = = = START-STATIC-FORWARD = = = */
+/* static forward declarations maintained by :mkfwd */
+static void
+putQuotedStr( tCC* pzStr );
+/* = = = END-STATIC-FORWARD = = = */
+
+/*
+ *  Make sure embedded single quotes come out okay.  The initial quote has
+ *  been emitted and the closing quote will be upon return.
+ */
+static void
+putQuotedStr( tCC* pzStr )
+{
+    /*
+     *  Handle empty strings to make the rest of the logic simpler.
+     */
+    if ((pzStr == NULL) || (*pzStr == NUL)) {
+        fputs( "''", stdout );
+        return;
+    }
+
+    /*
+     *  Emit any single quotes/apostrophes at the start of the string and
+     *  bail if that is all we need to do.
+     */
+    while (*pzStr == '\'') {
+        fputs( "\\'", stdout );
+        pzStr++;
+    }
+    if (*pzStr == NUL)
+        return;
+
+    /*
+     *  Start the single quote string
+     */
+    fputc( '\'', stdout );
+    for (;;) {
+        tCC* pz = strchr( pzStr, '\'' );
+        if (pz == NULL)
+            break;
+
+        /*
+         *  Emit the string up to the single quote (apostrophe) we just found.
+         */
+        fwrite( pzStr, (pz - pzStr), 1, stdout );
+        fputc( '\'', stdout );
+        pzStr = pz;
+
+        /*
+         *  Emit an escaped apostrophe for every one we find.
+         *  If that ends the string, do not re-open the single quotes.
+         */
+        while (*++pzStr == '\'')   fputs( "\\'", stdout );
+        if (*pzStr == NUL)
+            return;
+
+        fputc( '\'', stdout );
+    }
+
+    /*
+     *  If we broke out of the loop, we must still emit the remaining text
+     *  and then close the single quote string.
+     */
+    fputs( pzStr, stdout );
+    fputc( '\'', stdout );
+}
+
+
+/*=export_func  optionPutShell
+ * what:  write a portable shell script to parse options
+ * private:
+ * arg:   tOptions*, pOpts, the program options descriptor
+ * doc:   This routine will emit portable shell script text for parsing
+ *        the options described in the option definitions.
+=*/
+void
+optionPutShell( tOptions* pOpts )
+{
+    int  optIx = 0;
+    tSCC zOptCtFmt[]  = "OPTION_CT=%d\nexport OPTION_CT\n";
+    tSCC zOptNumFmt[] = "%1$s_%2$s=%3$d # 0x%3$X\nexport %1$s_%2$s\n";
+    tSCC zOptDisabl[] = "%1$s_%2$s=%3$s\nexport %1$s_%2$s\n";
+    tSCC zOptValFmt[] = "%s_%s=";
+    tSCC zOptEnd[]    = "\nexport %s_%s\n";
+    tSCC zFullOptFmt[]= "%1$s_%2$s='%3$s'\nexport %1$s_%2$s\n";
+    tSCC zEquivMode[] = "%1$s_%2$s_MODE='%3$s'\nexport %1$s_%2$s_MODE\n";
+
+    printf( zOptCtFmt, pOpts->curOptIdx-1 );
+
+    do  {
+        tOptDesc* pOD = pOpts->pOptDesc + optIx;
+
+        if (SKIP_OPT(pOD))
+            continue;
+
+        /*
+         *  Equivalence classes are hard to deal with.  Where the
+         *  option data wind up kind of squishes around.  For the purposes
+         *  of emitting shell state, they are not recommended, but we'll
+         *  do something.  I guess we'll emit the equivalenced-to option
+         *  at the point in time when the base option is found.
+         */
+        if (pOD->optEquivIndex != NO_EQUIVALENT)
+            continue; /* equivalence to a different option */
+
+        /*
+         *  Equivalenced to a different option.  Process the current option
+         *  as the equivalenced-to option.  Keep the persistent state bits,
+         *  but copy over the set-state bits.
+         */
+        if (pOD->optActualIndex != optIx) {
+            tOptDesc* p = pOpts->pOptDesc + pOD->optActualIndex;
+            p->pzLastArg = pOD->pzLastArg;
+            p->fOptState &= OPTST_PERSISTENT;
+            p->fOptState |= pOD->fOptState & ~OPTST_PERSISTENT;
+            printf( zEquivMode, pOpts->pzPROGNAME, pOD->pz_NAME, p->pz_NAME );
+            pOD = p;
+        }
+
+        /*
+         *  If the argument type is a set membership bitmask, then we always
+         *  emit the thing.  We do this because it will always have some sort
+         *  of bitmask value and we need to emit the bit values.
+         */
+        if (OPTST_GET_ARGTYPE(pOD->fOptState) == OPARG_TYPE_MEMBERSHIP) {
+            char* pz;
+            uintptr_t val = 1;
+            printf( zOptNumFmt, pOpts->pzPROGNAME, pOD->pz_NAME,
+                    (uintptr_t)(pOD->optCookie) );
+            pOD->optCookie = (void*)(uintptr_t)~0UL;
+            (*(pOD->pOptProc))( (tOptions*)2UL, pOD );
+
+            /*
+             *  We are building the typeset list.  The list returned starts with
+             *  'none + ' for use by option saving stuff.  We must ignore that.
+             */
+            pz = (char*)pOD->pzLastArg + 7;
+            while (*pz != NUL) {
+                printf( "typeset -x -i %s_", pOD->pz_NAME );
+                pz += strspn( pz, " +\t\n\f" );
+                for (;;) {
+                    char ch = *(pz++);
+                         if (islower( ch ))  fputc( toupper( ch ), stdout );
+                    else if (isalnum( ch ))  fputc( ch, stdout );
+                    else if (isspace( ch )
+                          || (ch == '+'))    goto name_done;
+                    else if (ch == NUL)      { pz--; goto name_done; }
+                    else fputc( '_', stdout );
+                } name_done:;
+                printf( "=%1$ld # 0x%1$lX\n", val );
+                val <<= 1;
+            }
+            free( (void*)(pOD->pzLastArg) );
+            continue;
+        }
+
+        /*
+         *  IF the option was either specified or it wakes up enabled,
+         *  then we will emit information.  Otherwise, skip it.
+         *  The idea is that if someone defines an option to initialize
+         *  enabled, we should tell our shell script that it is enabled.
+         */
+        if (UNUSED_OPT( pOD ) && DISABLED_OPT( pOD ))
+            continue;
+
+        /*
+         *  Handle stacked arguments
+         */
+        if (  (pOD->fOptState & OPTST_STACKED)
+           && (pOD->optCookie != NULL) )  {
+            tSCC zOptCookieCt[] = "%1$s_%2$s_CT=%3$d\nexport %1$s_%2$s_CT\n";
+
+            tArgList*    pAL = (tArgList*)pOD->optCookie;
+            tCC**        ppz = pAL->apzArgs;
+            int          ct  = pAL->useCt;
+
+            printf( zOptCookieCt, pOpts->pzPROGNAME, pOD->pz_NAME, ct );
+
+            while (--ct >= 0) {
+                tSCC zOptNumArg[] = "%s_%s_%d=";
+                tSCC zOptEnd[]    = "\nexport %s_%s_%d\n";
+
+                printf( zOptNumArg, pOpts->pzPROGNAME, pOD->pz_NAME,
+                        pAL->useCt - ct );
+                putQuotedStr( *(ppz++) );
+                printf( zOptEnd, pOpts->pzPROGNAME, pOD->pz_NAME,
+                        pAL->useCt - ct );
+            }
+        }
+
+        /*
+         *  If the argument has been disabled,
+         *  Then set its value to the disablement string
+         */
+        else if ((pOD->fOptState & OPTST_DISABLED) != 0)
+            printf( zOptDisabl, pOpts->pzPROGNAME, pOD->pz_NAME,
+                    (pOD->pz_DisablePfx != NULL)
+                    ? pOD->pz_DisablePfx : "false" );
+
+        /*
+         *  If the argument type is numeric, the last arg pointer
+         *  is really the VALUE of the string that was pointed to.
+         */
+        else if (OPTST_GET_ARGTYPE(pOD->fOptState) == OPARG_TYPE_NUMERIC)
+            printf( zOptNumFmt, pOpts->pzPROGNAME, pOD->pz_NAME,
+                    (uintptr_t)(pOD->pzLastArg) );
+
+        /*
+         *  If the argument type is an enumeration, then it is much
+         *  like a text value, except we call the callback function
+         *  to emit the value corresponding to the "pzLastArg" number.
+         */
+        else if (OPTST_GET_ARGTYPE(pOD->fOptState) == OPARG_TYPE_ENUMERATION) {
+            printf( zOptValFmt, pOpts->pzPROGNAME, pOD->pz_NAME );
+            fputc( '\'', stdout );
+            (*(pOD->pOptProc))( (tOptions*)1UL, pOD );
+            fputc( '\'', stdout );
+            printf( zOptEnd, pOpts->pzPROGNAME, pOD->pz_NAME );
+        }
+
+        /*
+         *  If the argument type is numeric, the last arg pointer
+         *  is really the VALUE of the string that was pointed to.
+         */
+        else if (OPTST_GET_ARGTYPE(pOD->fOptState) == OPARG_TYPE_BOOLEAN)
+            printf( zFullOptFmt, pOpts->pzPROGNAME, pOD->pz_NAME,
+                    ((uintptr_t)(pOD->pzLastArg) == 0) ? "false" : "true" );
+
+        /*
+         *  IF the option has an empty value,
+         *  THEN we set the argument to the occurrence count.
+         */
+        else if (  (pOD->pzLastArg == NULL)
+                || (pOD->pzLastArg[0] == NUL) )
+
+            printf( zOptNumFmt, pOpts->pzPROGNAME, pOD->pz_NAME,
+                    (int)pOD->optOccCt );
+
+        /*
+         *  This option has a text value
+         */
+        else {
+            printf( zOptValFmt, pOpts->pzPROGNAME, pOD->pz_NAME );
+            putQuotedStr( pOD->pzLastArg );
+            printf( zOptEnd, pOpts->pzPROGNAME, pOD->pz_NAME );
+        }
+    } while (++optIx < pOpts->presetOptCt );
+
+    if (  ((pOpts->fOptSet & OPTPROC_REORDER) != 0)
+       && (pOpts->curOptIdx < pOpts->origArgCt)) {
+        fputs( "set --", stdout );
+        for (optIx = pOpts->curOptIdx; optIx < pOpts->origArgCt; optIx++) {
+            char* pzArg = pOpts->origArgVect[ optIx ];
+            if (strchr( pzArg, '\'' ) == NULL)
+                printf( " '%s'", pzArg );
+            else {
+                fputs( " '", stdout );
+                for (;;) {
+                    char ch = *(pzArg++);
+                    switch (ch) {
+                    case '\'':  fputs( "'\\''", stdout ); break;
+                    case NUL:   goto arg_done;
+                    default:    fputc( ch, stdout ); break;
+                    }
+                } arg_done:;
+                fputc( '\'', stdout );
+            }
+        }
+        fputs( "\nOPTION_CT=0\n", stdout );
+    }
+}
+
+/*
+ * Local Variables:
+ * mode: C
+ * c-file-style: "stroustrup"
+ * tab-width: 4
+ * indent-tabs-mode: nil
+ * End:
+ * end of autoopts/putshell.c */
diff --git a/sntp/libopts/restore.c b/sntp/libopts/restore.c
new file mode 100644 (file)
index 0000000..959e0f9
--- /dev/null
@@ -0,0 +1,207 @@
+
+/*
+ *  restore.c  $Id: restore.c,v 4.6 2006/03/25 19:24:56 bkorb Exp $
+ * Time-stamp:      "2005-02-23 15:10:20 bkorb"
+ *
+ *  This module's routines will save the current option state to memory
+ *  and restore it.  If saved prior to the initial optionProcess call,
+ *  then the initial state will be restored.
+ */
+
+/*
+ *  Automated Options copyright 1992-2006 Bruce Korb
+ *
+ *  Automated Options is free software.
+ *  You may redistribute it and/or modify it under the terms of the
+ *  GNU General Public License, as published by the Free Software
+ *  Foundation; either version 2, or (at your option) any later version.
+ *
+ *  Automated Options is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with Automated Options.  See the file "COPYING".  If not,
+ *  write to:  The Free Software Foundation, Inc.,
+ *             51 Franklin Street, Fifth Floor,
+ *             Boston, MA  02110-1301, USA.
+ *
+ * As a special exception, Bruce Korb gives permission for additional
+ * uses of the text contained in his release of AutoOpts.
+ *
+ * The exception is that, if you link the AutoOpts library with other
+ * files to produce an executable, this does not by itself cause the
+ * resulting executable to be covered by the GNU General Public License.
+ * Your use of that executable is in no way restricted on account of
+ * linking the AutoOpts library code into it.
+ *
+ * This exception does not however invalidate any other reasons why
+ * the executable file might be covered by the GNU General Public License.
+ *
+ * This exception applies only to the code released by Bruce Korb under
+ * the name AutoOpts.  If you copy code from other sources under the
+ * General Public License into a copy of AutoOpts, as the General Public
+ * License permits, the exception does not apply to the code that you add
+ * in this way.  To avoid misleading anyone as to the status of such
+ * modified files, you must delete this exception notice from them.
+ *
+ * If you write modifications of your own for AutoOpts, it is your choice
+ * whether to permit this exception to apply to your modifications.
+ * If you do not wish that, delete this exception notice.
+ */
+
+/*=export_func optionSaveState
+ *
+ * what:  saves the option state to memory
+ * arg:   tOptions*, pOpts, program options descriptor
+ *
+ * doc:   This routine will allocate enough memory to save the current
+ *        option processing state.  If this routine has been called before,
+ *        that memory will be reused.  You may only save one copy of the
+ *        option state.  This routine may be called before optionProcess(3AO).
+ *        If you do call it before the first call to optionProcess, then
+ *        you may also change the contents of argc/argv after you call
+ *        optionRestore(3AO)
+ *
+ * err:   If it fails to allocate the memory,
+ *        it will print a message to stderr and exit.
+ *        Otherwise, it will always succeed.
+=*/
+void
+optionSaveState( tOptions* pOpts )
+{
+    if (pOpts->pSavedState == NULL) {
+        size_t sz = sizeof( *pOpts ) + (pOpts->optCt * sizeof( tOptDesc ));
+        pOpts->pSavedState = AGALOC( sz, "saved option state" );
+        if (pOpts->pSavedState == NULL) {
+            tCC* pzName = pOpts->pzProgName;
+            if (pzName == NULL) {
+                pzName = pOpts->pzPROGNAME;
+                if (pzName == NULL)
+                    pzName = zNil;
+            }
+            fprintf( stderr, zCantSave, pzName, sz );
+            exit( EXIT_FAILURE );
+        }
+    }
+
+    {
+        tOptions* p   = pOpts->pSavedState;
+        tOptDesc* pOD = pOpts->pOptDesc;
+        int       ct  = pOpts->optCt;
+
+        memcpy( p, pOpts, sizeof( *p ));
+        memcpy( p + 1, pOpts->pOptDesc, p->optCt * sizeof( tOptDesc ));
+
+        /*
+         *  Make sure that allocated stuff is only referenced in the
+         *  archived copy of the data.
+         */
+        for (; ct-- > 0; pOD++)  {
+            switch (OPTST_GET_ARGTYPE(pOD->fOptState)) {
+            case OPARG_TYPE_STRING:
+                if (pOD->fOptState & OPTST_STACKED) {
+                    tOptDesc* q = p->pOptDesc + (pOD - pOpts->pOptDesc);
+                    q->optCookie = NULL;
+                }
+                break;
+
+            case OPARG_TYPE_HIERARCHY:
+            {
+                tOptDesc* q = p->pOptDesc + (pOD - pOpts->pOptDesc);
+                q->optCookie = NULL;
+            }
+            }
+        }
+    }
+}
+
+
+/*=export_func optionRestore
+ *
+ * what:  restore option state from memory copy
+ * arg:   tOptions*, pOpts, program options descriptor
+ *
+ * doc:  Copy back the option state from saved memory.
+ *       The allocated memory is left intact, so this routine can be
+ *       called repeatedly without having to call optionSaveState again.
+ *       If you are restoring a state that was saved before the first call
+ *       to optionProcess(3AO), then you may change the contents of the
+ *       argc/argv parameters to optionProcess.
+ *
+ * err:  If you have not called @code{optionSaveState} before, a diagnostic is
+ *       printed to @code{stderr} and exit is called.
+=*/
+void
+optionRestore( tOptions* pOpts )
+{
+    tOptions* p = (tOptions*)pOpts->pSavedState;
+
+    if (p == NULL) {
+        tCC* pzName = pOpts->pzProgName;
+        if (pzName == NULL) {
+            pzName = pOpts->pzPROGNAME;
+            if (pzName == NULL)
+                pzName = zNil;
+        }
+        fprintf( stderr, zNoState, pzName );
+        exit( EXIT_FAILURE );
+    }
+    memcpy( pOpts, p, sizeof( *p ));
+    memcpy( pOpts->pOptDesc, p+1, p->optCt * sizeof( tOptDesc ));
+}
+
+/* = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = */
+
+/*=export_func optionFree
+ *
+ * what:  free allocated option processing memory
+ * arg:   tOptions*, pOpts, program options descriptor
+ *
+ * doc:   AutoOpts sometimes allocates memory and puts pointers to it in the
+ *        option state structures.  This routine deallocates all such memory.
+ *
+ * err:   As long as memory has not been corrupted,
+ *        this routine is always successful.
+=*/
+void
+optionFree( tOptions* pOpts )
+{
+    if (pOpts->pSavedState != NULL) {
+        AGFREE( pOpts->pSavedState );
+        pOpts->pSavedState = NULL;
+    }
+    {
+        tOptDesc* p = pOpts->pOptDesc;
+        int ct = pOpts->optCt;
+        do  {
+            switch (OPTST_GET_ARGTYPE(p->fOptState)) {
+            case OPARG_TYPE_STRING:
+                if (  (p->fOptState & OPTST_STACKED)
+                   && (p->optCookie != NULL)) {
+                    AGFREE( p->optCookie );
+                    p->fOptState &= OPTST_PERSISTENT;
+                    if ((p->fOptState & OPTST_INITENABLED) == 0)
+                        p->fOptState |= OPTST_DISABLED;
+                }
+                break;
+
+            case OPARG_TYPE_HIERARCHY:
+                if (p->optCookie != NULL)
+                    optionUnloadNested(p->optCookie);
+                break;
+            }
+
+            p->optCookie = NULL;
+        } while (p++, --ct > 0);
+    }
+}
+/*
+ * Local Variables:
+ * mode: C
+ * c-file-style: "stroustrup"
+ * tab-width: 4
+ * indent-tabs-mode: nil
+ * End:
+ * end of autoopts/restore.c */
diff --git a/sntp/libopts/save.c b/sntp/libopts/save.c
new file mode 100644 (file)
index 0000000..51fa212
--- /dev/null
@@ -0,0 +1,499 @@
+
+/*
+ *  save.c  $Id: save.c,v 4.12 2006/03/25 19:24:56 bkorb Exp $
+ * Time-stamp:      "2005-02-20 13:49:46 bkorb"
+ *
+ *  This module's routines will take the currently set options and
+ *  store them into an ".rc" file for re-interpretation the next
+ *  time the invoking program is run.
+ */
+
+/*
+ *  Automated Options copyright 1992-2006 Bruce Korb
+ *
+ *  Automated Options is free software.
+ *  You may redistribute it and/or modify it under the terms of the
+ *  GNU General Public License, as published by the Free Software
+ *  Foundation; either version 2, or (at your option) any later version.
+ *
+ *  Automated Options is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with Automated Options.  See the file "COPYING".  If not,
+ *  write to:  The Free Software Foundation, Inc.,
+ *             51 Franklin Street, Fifth Floor,
+ *             Boston, MA  02110-1301, USA.
+ *
+ * As a special exception, Bruce Korb gives permission for additional
+ * uses of the text contained in his release of AutoOpts.
+ *
+ * The exception is that, if you link the AutoOpts library with other
+ * files to produce an executable, this does not by itself cause the
+ * resulting executable to be covered by the GNU General Public License.
+ * Your use of that executable is in no way restricted on account of
+ * linking the AutoOpts library code into it.
+ *
+ * This exception does not however invalidate any other reasons why
+ * the executable file might be covered by the GNU General Public License.
+ *
+ * This exception applies only to the code released by Bruce Korb under
+ * the name AutoOpts.  If you copy code from other sources under the
+ * General Public License into a copy of AutoOpts, as the General Public
+ * License permits, the exception does not apply to the code that you add
+ * in this way.  To avoid misleading anyone as to the status of such
+ * modified files, you must delete this exception notice from them.
+ *
+ * If you write modifications of your own for AutoOpts, it is your choice
+ * whether to permit this exception to apply to your modifications.
+ * If you do not wish that, delete this exception notice.
+ */
+
+tSCC  zWarn[] = "%s WARNING:  cannot save options - ";
+
+/* = = = START-STATIC-FORWARD = = = */
+/* static forward declarations maintained by :mkfwd */
+static tCC*
+findDirName( tOptions* pOpts, int* p_free );
+
+static tCC*
+findFileName( tOptions* pOpts, int* p_free_name );
+
+static void
+printEntry(
+    FILE*      fp,
+    tOptDesc*  p,
+    tCC*       pzLA );
+/* = = = END-STATIC-FORWARD = = = */
+
+static tCC*
+findDirName( tOptions* pOpts, int* p_free )
+{
+    tCC*  pzDir;
+
+    if (pOpts->specOptIdx.save_opts == 0)
+        return NULL;
+
+    pzDir = pOpts->pOptDesc[ pOpts->specOptIdx.save_opts ].pzLastArg;
+    if ((pzDir != NULL) && (*pzDir != NUL))
+        return pzDir;
+
+    /*
+     *  This function only works if there is a directory where
+     *  we can stash the RC (INI) file.
+     */
+    {
+        tCC* const* papz = pOpts->papzHomeList;
+        if (papz == NULL)
+            return NULL;
+
+        while (papz[1] != NULL) papz++;
+        pzDir = *papz;
+    }
+
+    /*
+     *  IF it does not require deciphering an env value, then just copy it
+     */
+    if (*pzDir != '$')
+        return pzDir;
+
+    {
+        tCC*  pzEndDir = strchr( ++pzDir, '/' );
+        char* pzFileName;
+        char* pzEnv;
+
+        if (pzEndDir != NULL) {
+            char z[ AO_NAME_SIZE ];
+            if ((pzEndDir - pzDir) > AO_NAME_LIMIT )
+                return NULL;
+            strncpy( z, pzDir, (pzEndDir - pzDir) );
+            z[ (pzEndDir - pzDir) ] = NUL;
+            pzEnv = getenv( z );
+        } else {
+
+            /*
+             *  Make sure we can get the env value (after stripping off
+             *  any trailing directory or file names)
+             */
+            pzEnv = getenv( pzDir );
+        }
+
+        if (pzEnv == NULL) {
+            fprintf( stderr, zWarn, pOpts->pzProgName );
+            fprintf( stderr, zNotDef, pzDir );
+            return NULL;
+        }
+
+        if (pzEndDir == NULL)
+            return pzEnv;
+
+        {
+            size_t sz = strlen( pzEnv ) + strlen( pzEndDir ) + 2;
+            pzFileName = (char*)AGALOC( sz, "dir name" );
+        }
+
+        if (pzFileName == NULL)
+            return NULL;
+
+        *p_free = 1;
+        /*
+         *  Glue together the full name into the allocated memory.
+         *  FIXME: We lose track of this memory.
+         */
+        sprintf( pzFileName, "%s/%s", pzEnv, pzEndDir );
+        return pzFileName;
+    }
+}
+
+
+static tCC*
+findFileName( tOptions* pOpts, int* p_free_name )
+{
+    tCC*   pzDir;
+    struct stat stBuf;
+    int    free_dir_name = 0;
+
+    pzDir = findDirName( pOpts, &free_dir_name );
+    if (pzDir == NULL)
+        return NULL;
+
+    /*
+     *  See if we can find the specified directory.  We use a once-only loop
+     *  structure so we can bail out early.
+     */
+    if (stat( pzDir, &stBuf ) != 0) do {
+
+        /*
+         *  IF we could not, check to see if we got a full
+         *  path to a file name that has not been created yet.
+         */
+        if (errno == ENOENT) {
+            char z[MAXPATHLEN];
+
+            /*
+             *  Strip off the last component, stat the remaining string and
+             *  that string must name a directory
+             */
+            char* pzDirCh = strrchr( pzDir, '/' );
+            if (pzDirCh == NULL) {
+                stBuf.st_mode = S_IFREG;
+                continue;  /* bail out of error condition */
+            }
+
+            strncpy( z, pzDir, pzDirCh - pzDir );
+            z[ pzDirCh - pzDir ] = NUL;
+
+            if (  (stat( z, &stBuf ) == 0)
+               && S_ISDIR( stBuf.st_mode )) {
+
+                /*
+                 *  We found the directory.  Restore the file name and
+                 *  mark the full name as a regular file
+                 */
+                stBuf.st_mode = S_IFREG;
+                continue;  /* bail out of error condition */
+            }
+        }
+
+        /*
+         *  We got a bogus name.
+         */
+        fprintf( stderr, zWarn, pOpts->pzProgName );
+        fprintf( stderr, zNoStat, errno, strerror( errno ), pzDir );
+        if (free_dir_name)
+            AGFREE( (void*)pzDir );
+        return NULL;
+    } while (0);
+
+    /*
+     *  IF what we found was a directory,
+     *  THEN tack on the config file name
+     */
+    if (S_ISDIR( stBuf.st_mode )) {
+        size_t sz = strlen( pzDir ) + strlen( pOpts->pzRcName ) + 2;
+
+        {
+            char*  pzPath = (char*)AGALOC( sz, "file name" );
+#ifdef HAVE_SNPRINTF
+            snprintf( pzPath, sz, "%s/%s", pzDir, pOpts->pzRcName );
+#else
+            sprintf( pzPath, "%s/%s", pzDir, pOpts->pzRcName );
+#endif
+            if (free_dir_name)
+                AGFREE( (void*)pzDir );
+            pzDir = pzPath;
+            free_dir_name = 1;
+        }
+
+        /*
+         *  IF we cannot stat the object for any reason other than
+         *     it does not exist, then we bail out
+         */
+        if (stat( pzDir, &stBuf ) != 0) {
+            if (errno != ENOENT) {
+                fprintf( stderr, zWarn, pOpts->pzProgName );
+                fprintf( stderr, zNoStat, errno, strerror( errno ),
+                         pzDir );
+                AGFREE( (void*)pzDir );
+                return NULL;
+            }
+
+            /*
+             *  It does not exist yet, but it will be a regular file
+             */
+            stBuf.st_mode = S_IFREG;
+        }
+    }
+
+    /*
+     *  Make sure that whatever we ultimately found, that it either is
+     *  or will soon be a file.
+     */
+    if (! S_ISREG( stBuf.st_mode )) {
+        fprintf( stderr, zWarn, pOpts->pzProgName );
+        fprintf( stderr, zNotFile, pzDir );
+        if (free_dir_name)
+            AGFREE( (void*)pzDir );
+        return NULL;
+    }
+
+    /*
+     *  Get rid of the old file
+     */
+    unlink( pzDir );
+    *p_free_name = free_dir_name;
+    return pzDir;
+}
+
+
+static void
+printEntry(
+    FILE*      fp,
+    tOptDesc*  p,
+    tCC*       pzLA )
+{
+    /*
+     *  There is an argument.  Pad the name so values line up
+     */
+    fprintf( fp, "%-18s",
+             (DISABLED_OPT( p )) ? p->pz_DisableName : p->pz_Name );
+
+    /*
+     *  IF the option is numeric only,
+     *  THEN the char pointer is really the number
+     */
+    if (OPTST_GET_ARGTYPE(p->fOptState) == OPARG_TYPE_NUMERIC)
+        fprintf( fp, "  %d\n", (t_word)pzLA );
+
+    /*
+     *  OTHERWISE, FOR each line of the value text, ...
+     */
+    else if (pzLA == NULL)
+        fputc( '\n', fp );
+
+    else {
+        fputc( ' ', fp ); fputc( ' ', fp );
+        for (;;) {
+            tCC* pzNl = strchr( pzLA, '\n' );
+
+            /*
+             *  IF this is the last line
+             *  THEN bail and print it
+             */
+            if (pzNl == NULL)
+                break;
+
+            /*
+             *  Print the continuation and the text from the current line
+             */
+            fwrite( pzLA, pzNl - pzLA, 1, fp );
+            pzLA = pzNl+1; /* advance the Last Arg pointer */
+            fputs( "\\\n", fp );
+        }
+
+        /*
+         *  Terminate the entry
+         */
+        fputs( pzLA, fp );
+        fputc( '\n', fp );
+    }
+}
+
+
+/*=export_func  optionSaveFile
+ *
+ * what:  saves the option state to a file
+ *
+ * arg:   tOptions*,   pOpts,  program options descriptor
+ *
+ * doc:
+ *
+ * This routine will save the state of option processing to a file.  The name
+ * of that file can be specified with the argument to the @code{--save-opts}
+ * option, or by appending the @code{rcfile} attribute to the last
+ * @code{homerc} attribute.  If no @code{rcfile} attribute was specified, it
+ * will default to @code{.@i{programname}rc}.  If you wish to specify another
+ * file, you should invoke the @code{SET_OPT_SAVE_OPTS( @i{filename} )} macro.
+ *
+ * err:
+ *
+ * If no @code{homerc} file was specified, this routine will silently return
+ * and do nothing.  If the output file cannot be created or updated, a message
+ * will be printed to @code{stderr} and the routine will return.
+=*/
+void
+optionSaveFile( tOptions* pOpts )
+{
+    tOptDesc* pOD;
+    int       ct;
+    FILE*     fp;
+
+    {
+        int   free_name = 0;
+        tCC*  pzFName = findFileName( pOpts, &free_name );
+        if (pzFName == NULL)
+            return;
+
+        fp = fopen( pzFName, "w" FOPEN_BINARY_FLAG );
+        if (fp == NULL) {
+            fprintf( stderr, zWarn, pOpts->pzProgName );
+            fprintf( stderr, zNoCreat, errno, strerror( errno ), pzFName );
+            if (free_name)
+                AGFREE((void*) pzFName );
+            return;
+        }
+
+        if (free_name)
+            AGFREE( (void*)pzFName );
+    }
+
+    {
+        const char*  pz = pOpts->pzUsageTitle;
+        fputs( "#  ", fp );
+        do { fputc( *pz, fp ); } while (*(pz++) != '\n');
+    }
+
+    {
+        time_t  timeVal = time( NULL );
+        char*   pzTime  = ctime( &timeVal );
+
+        fprintf( fp, zPresetFile, pzTime );
+#ifdef HAVE_ALLOCATED_CTIME
+        /*
+         *  The return values for ctime(), localtime(), and gmtime()
+         *  normally point to static data that is overwritten by each call.
+         *  The test to detect allocated ctime, so we leak the memory.
+         */
+        AGFREE( (void*)pzTime );
+#endif
+    }
+
+    /*
+     *  FOR each of the defined options, ...
+     */
+    ct  = pOpts->presetOptCt;
+    pOD = pOpts->pOptDesc;
+    do  {
+        int arg_state;
+        tOptDesc*  p;
+
+        /*
+         *  IF    the option has not been defined
+         *     OR it does not take an initialization value
+         *     OR it is equivalenced to another option
+         *  THEN continue (ignore it)
+         */
+        if (UNUSED_OPT( pOD ))
+            continue;
+
+        if ((pOD->fOptState & (OPTST_NO_INIT|OPTST_DOCUMENT|OPTST_OMITTED))
+            != 0)
+            continue;
+
+        if (  (pOD->optEquivIndex != NO_EQUIVALENT)
+              && (pOD->optEquivIndex != pOD->optIndex))
+            continue;
+
+        /*
+         *  Set a temporary pointer to the real option description
+         *  (i.e. account for equivalencing)
+         */
+        p = ((pOD->fOptState & OPTST_EQUIVALENCE) != 0)
+            ? (pOpts->pOptDesc + pOD->optActualIndex) : pOD;
+
+        /*
+         *  IF    no arguments are allowed
+         *  THEN just print the name and continue
+         */
+        if (OPTST_GET_ARGTYPE(pOD->fOptState) == OPARG_TYPE_NONE) {
+            fprintf( fp, "%s\n",
+                     (DISABLED_OPT( p )) ? p->pz_DisableName : p->pz_Name );
+            continue;
+        }
+
+        arg_state = OPTST_GET_ARGTYPE(p->fOptState);
+        switch (arg_state) {
+        case 0:
+        case OPARG_TYPE_NUMERIC:
+            printEntry( fp, p, p->pzLastArg );
+            break;
+
+        case OPARG_TYPE_STRING:
+            if (p->fOptState & OPTST_STACKED) {
+                tArgList*  pAL = (tArgList*)p->optCookie;
+                int        uct = pAL->useCt;
+                tCC**      ppz = pAL->apzArgs;
+
+                /*
+                 *  Disallow multiple copies of disabled options.
+                 */
+                if (uct > 1)
+                    p->fOptState &= ~OPTST_DISABLED;
+
+                while (uct-- > 0)
+                    printEntry( fp, p, *(ppz++) );
+            } else {
+                printEntry( fp, p, p->pzLastArg );
+            }
+            break;
+
+        case OPARG_TYPE_ENUMERATION:
+        case OPARG_TYPE_MEMBERSHIP:
+        {
+            tCC* val = p->pzLastArg;
+            /*
+             *  This is a magic incantation that will convert the
+             *  bit flag values back into a string suitable for printing.
+             */
+            (*(p->pOptProc))( (tOptions*)2UL, p );
+            printEntry( fp, p, p->pzLastArg );
+            if ((p->pzLastArg != NULL) && (arg_state != OPARG_TYPE_ENUMERATION))
+                /*
+                 *  bit flag and enumeration strings get allocated
+                 */
+                AGFREE( (void*)p->pzLastArg );
+            p->pzLastArg = val;
+            break;
+        }
+
+        case OPARG_TYPE_BOOLEAN:
+            printEntry( fp, p, (p->pzLastArg != 0) ? "true" : "false" );
+            break;
+
+        default:
+            break; /* cannot handle - skip it */
+        }
+    } while ( (pOD++), (--ct > 0));
+
+    fclose( fp );
+}
+/*
+ * Local Variables:
+ * mode: C
+ * c-file-style: "stroustrup"
+ * tab-width: 4
+ * indent-tabs-mode: nil
+ * End:
+ * end of autoopts/save.c */
diff --git a/sntp/libopts/sort.c b/sntp/libopts/sort.c
new file mode 100644 (file)
index 0000000..e7f29ed
--- /dev/null
@@ -0,0 +1,369 @@
+
+/*
+ *  sort.c  $Id: sort.c,v 4.7 2006/03/25 19:24:56 bkorb Exp $
+ * Time-stamp:      "2005-02-20 17:18:41 bkorb"
+ *
+ *  This module implements argument sorting.
+ */
+
+/*
+ *  Automated Options copyright 1992-2006 Bruce Korb
+ *
+ *  Automated Options is free software.
+ *  You may redistribute it and/or modify it under the terms of the
+ *  GNU General Public License, as published by the Free Software
+ *  Foundation; either version 2, or (at your option) any later version.
+ *
+ *  Automated Options is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with Automated Options.  See the file "COPYING".  If not,
+ *  write to:  The Free Software Foundation, Inc.,
+ *             51 Franklin Street, Fifth Floor,
+ *             Boston, MA  02110-1301, USA.
+ *
+ * As a special exception, Bruce Korb gives permission for additional
+ * uses of the text contained in his release of AutoOpts.
+ *
+ * The exception is that, if you link the AutoOpts library with other
+ * files to produce an executable, this does not by itself cause the
+ * resulting executable to be covered by the GNU General Public License.
+ * Your use of that executable is in no way restricted on account of
+ * linking the AutoOpts library code into it.
+ *
+ * This exception does not however invalidate any other reasons why
+ * the executable file might be covered by the GNU General Public License.
+ *
+ * This exception applies only to the code released by Bruce Korb under
+ * the name AutoOpts.  If you copy code from other sources under the
+ * General Public License into a copy of AutoOpts, as the General Public
+ * License permits, the exception does not apply to the code that you add
+ * in this way.  To avoid misleading anyone as to the status of such
+ * modified files, you must delete this exception notice from them.
+ *
+ * If you write modifications of your own for AutoOpts, it is your choice
+ * whether to permit this exception to apply to your modifications.
+ * If you do not wish that, delete this exception notice.
+ */
+
+/* = = = START-STATIC-FORWARD = = = */
+/* static forward declarations maintained by :mkfwd */
+static tSuccess
+mustHandleArg( tOptions* pOpts, char* pzArg, tOptState* pOS,
+               char** ppzOpts, int* pOptsIdx );
+
+static tSuccess
+mayHandleArg( tOptions* pOpts, char* pzArg, tOptState* pOS,
+              char** ppzOpts, int* pOptsIdx );
+
+static tSuccess
+checkShortOpts( tOptions* pOpts, char* pzArg, tOptState* pOS,
+                char** ppzOpts, int* pOptsIdx );
+/* = = = END-STATIC-FORWARD = = = */
+
+/*
+ *  "mustHandleArg" and "mayHandleArg" are really similar.  The biggest
+ *  difference is that "may" will consume the next argument only if it
+ *  does not start with a hyphen and "must" will consume it, hyphen or not.
+ */
+static tSuccess
+mustHandleArg( tOptions* pOpts, char* pzArg, tOptState* pOS,
+               char** ppzOpts, int* pOptsIdx )
+{
+    /*
+     *  An option argument is required.  Long options can either have
+     *  a separate command line argument, or an argument attached by
+     *  the '=' character.  Figure out which.
+     */
+    switch (pOS->optType) {
+    case TOPT_SHORT:
+        /*
+         *  See if an arg string follows the flag character.  If not,
+         *  the next arg must be the option argument.
+         */
+        if (*pzArg != NUL)
+            return SUCCESS;
+        break;
+
+    case TOPT_LONG:
+        /*
+         *  See if an arg string has already been assigned (glued on
+         *  with an `=' character).  If not, the next is the opt arg.
+         */
+        if (pOS->pzOptArg != NULL)
+            return SUCCESS;
+        break;
+
+    default:
+        return FAILURE;
+    }
+    if (pOpts->curOptIdx >= pOpts->origArgCt)
+        return FAILURE;
+
+    ppzOpts[ (*pOptsIdx)++ ] = pOpts->origArgVect[ (pOpts->curOptIdx)++ ];
+    return SUCCESS;
+}
+
+static tSuccess
+mayHandleArg( tOptions* pOpts, char* pzArg, tOptState* pOS,
+              char** ppzOpts, int* pOptsIdx )
+{
+    /*
+     *  An option argument is optional.
+     */
+    switch (pOS->optType) {
+    case TOPT_SHORT:
+        /*
+         *  IF nothing is glued on after the current flag character,
+         *  THEN see if there is another argument.  If so and if it
+         *  does *NOT* start with a hyphen, then it is the option arg.
+         */
+        if (*pzArg != NUL)
+            return SUCCESS;
+        break;
+
+    case TOPT_LONG:
+        /*
+         *  Look for an argument if we don't already have one (glued on
+         *  with a `=' character)
+         */
+        if (pOS->pzOptArg != NULL)
+            return SUCCESS;
+        break;
+
+    default:
+        return FAILURE;
+    }
+    if (pOpts->curOptIdx >= pOpts->origArgCt)
+        return PROBLEM;
+
+    pzArg = pOpts->origArgVect[ pOpts->curOptIdx ];
+    if (*pzArg != '-')
+        ppzOpts[ (*pOptsIdx)++ ] = pOpts->origArgVect[ (pOpts->curOptIdx)++ ];
+    return SUCCESS;
+}
+
+/*
+ *  Process a string of short options glued together.  If the last one
+ *  does or may take an argument, the do the argument processing and leave.
+ */
+static tSuccess
+checkShortOpts( tOptions* pOpts, char* pzArg, tOptState* pOS,
+                char** ppzOpts, int* pOptsIdx )
+{
+    while (*pzArg != NUL) {
+        if (FAILED( shortOptionFind( pOpts, *pzArg, pOS )))
+            return FAILURE;
+
+        /*
+         *  See if we can have an arg.
+         */
+        if (OPTST_GET_ARGTYPE(pOS->pOD->fOptState) == OPARG_TYPE_NONE) {
+            pzArg++;
+
+        } else if (pOS->pOD->fOptState & OPTST_ARG_OPTIONAL) {
+            /*
+             *  Take an argument if it is not attached and it does not
+             *  start with a hyphen.
+             */
+            if (pzArg[1] != NUL)
+                return SUCCESS;
+
+            pzArg = pOpts->origArgVect[ pOpts->curOptIdx ];
+            if (*pzArg != '-')
+                ppzOpts[ (*pOptsIdx)++ ] =
+                    pOpts->origArgVect[ (pOpts->curOptIdx)++ ];
+            return SUCCESS;
+
+        } else {
+            /*
+             *  IF we need another argument, be sure it is there and
+             *  take it.
+             */
+            if (pzArg[1] == NUL) {
+                if (pOpts->curOptIdx >= pOpts->origArgCt)
+                    return FAILURE;
+                ppzOpts[ (*pOptsIdx)++ ] =
+                    pOpts->origArgVect[ (pOpts->curOptIdx)++ ];
+            }
+            return SUCCESS;
+        }
+    }
+    return SUCCESS;
+}
+
+/*
+ *  If the program wants sorted options (separated operands and options),
+ *  then this routine will to the trick.
+ */
+LOCAL void
+optionSort( tOptions* pOpts )
+{
+    char** ppzOpts;
+    char** ppzOpds;
+    int    optsIdx = 0;
+    int    opdsIdx = 0;
+
+    tOptState os = OPTSTATE_INITIALIZER(DEFINED);
+
+    /*
+     *  Disable for POSIX conformance
+     */
+    if (getenv( "POSIXLY_CORRECT" ) != NULL) {
+        errno = 0;
+        return;
+    }
+
+    errno = ENOENT;
+
+    /*
+     *  If all arguments are named, we can't sort 'em.  There are no operands.
+     */
+    if (NAMED_OPTS(pOpts))
+        return;
+
+    /*
+     *  Make sure we can allocate two full-sized arg vectors.
+     */
+    ppzOpts = malloc( pOpts->origArgCt * sizeof( char* ));
+    if (ppzOpts == NULL)
+        goto exit_no_mem;
+
+    ppzOpds = malloc( pOpts->origArgCt * sizeof( char* ));
+    if (ppzOpds == NULL) {
+        free( ppzOpts );
+        goto exit_no_mem;
+    }
+
+    pOpts->curOptIdx = 1;
+    pOpts->pzCurOpt  = NULL;
+
+    /*
+     *  Now, process all the options from our current position onward.
+     *  (This allows interspersed options and arguments for the few
+     *  non-standard programs that require it.)
+     */
+    for (;;) {
+        char* pzArg;
+        tSuccess res;
+
+        /*
+         *  If we're out of arguments, we're done.  Join the option and
+         *  operand lists into the original argument vector.
+         */
+        if (pOpts->curOptIdx >= pOpts->origArgCt) {
+            errno = 0;
+            goto joinLists;
+        }
+
+        pzArg = pOpts->origArgVect[ pOpts->curOptIdx ];
+        if (*pzArg != '-') {
+            ppzOpds[ opdsIdx++ ] = pOpts->origArgVect[ (pOpts->curOptIdx)++ ];
+            continue;
+        }
+
+        switch (pzArg[1]) {
+        case NUL:
+            /*
+             *  A regular option.  Put it on the operand list.
+             */
+            ppzOpds[ opdsIdx++ ] = pOpts->origArgVect[ (pOpts->curOptIdx)++ ];
+            continue;
+
+        case '-':
+            /*
+             *  Two consecutive hypens.  Put them on the options list and then
+             *  _always_ force the remainder of the arguments to be operands.
+             */
+            if (pzArg[2] == NUL) {
+                ppzOpts[ optsIdx++ ] =
+                    pOpts->origArgVect[ (pOpts->curOptIdx)++ ];
+                goto restOperands;
+            }
+            res = longOptionFind( pOpts, pzArg+2, &os );
+            break;
+
+        default:
+            /*
+             *  If short options are not allowed, then do long
+             *  option processing.  Otherwise the character must be a
+             *  short (i.e. single character) option.
+             */
+            if ((pOpts->fOptSet & OPTPROC_SHORTOPT) == 0) {
+                res = longOptionFind( pOpts, pzArg+1, &os );
+            } else {
+                res = shortOptionFind( pOpts, pzArg[1], &os );
+            }
+            break;
+        }
+        if (FAILED( res )) {
+            errno = EIO;
+            goto freeTemps;
+        }
+
+        /*
+         *  We've found an option.  Add the argument to the option list.
+         *  Next, we have to see if we need to pull another argument to be
+         *  used as the option argument.
+         */
+        ppzOpts[ optsIdx++ ] = pOpts->origArgVect[ (pOpts->curOptIdx)++ ];
+
+        if (OPTST_GET_ARGTYPE(os.pOD->fOptState) == OPARG_TYPE_NONE) {
+            /*
+             *  No option argument.  If we have a short option here,
+             *  then scan for short options until we get to the end
+             *  of the argument string.
+             */
+            if (  (os.optType == TOPT_SHORT)
+               && FAILED( checkShortOpts( pOpts, pzArg+2, &os,
+                                          ppzOpts, &optsIdx )) )  {
+                errno = EIO;
+                goto freeTemps;
+            }
+
+        } else if (os.pOD->fOptState & OPTST_ARG_OPTIONAL) {
+            switch (mayHandleArg( pOpts, pzArg+2, &os, ppzOpts, &optsIdx )) {
+            case FAILURE: errno = EIO; goto freeTemps;
+            case PROBLEM: errno = 0;   goto joinLists;
+            }
+
+        } else {
+            switch (mustHandleArg( pOpts, pzArg+2, &os, ppzOpts, &optsIdx )) {
+            case PROBLEM:
+            case FAILURE: errno = EIO; goto freeTemps;
+            }
+        }
+    } /* for (;;) */
+
+ restOperands:
+    while (pOpts->curOptIdx < pOpts->origArgCt)
+        ppzOpds[ opdsIdx++ ] = pOpts->origArgVect[ (pOpts->curOptIdx)++ ];
+
+ joinLists:
+    if (optsIdx > 0)
+        memcpy( pOpts->origArgVect + 1, ppzOpts, optsIdx * sizeof( char* ));
+    if (opdsIdx > 0)
+        memcpy( pOpts->origArgVect + 1 + optsIdx,
+                ppzOpds, opdsIdx * sizeof( char* ));
+
+ freeTemps:
+    free( ppzOpts );
+    free( ppzOpds );
+    return;
+
+ exit_no_mem:
+    errno = ENOMEM;
+    return;
+}
+
+/*
+ * Local Variables:
+ * mode: C
+ * c-file-style: "stroustrup"
+ * tab-width: 4
+ * indent-tabs-mode: nil
+ * End:
+ * end of autoopts/sort.c */
diff --git a/sntp/libopts/stack.c b/sntp/libopts/stack.c
new file mode 100644 (file)
index 0000000..bbea334
--- /dev/null
@@ -0,0 +1,224 @@
+
+/*
+ *  stack.c
+ *  $Id: stack.c,v 4.6 2006/03/25 19:24:56 bkorb Exp $
+ *  Time-stamp:      "2005-02-20 16:33:20 bkorb"
+ *
+ *  This is a special option processing routine that will save the
+ *  argument to an option in a FIFO queue.
+ */
+
+/*
+ *  Automated Options copyright 1992-2006 Bruce Korb
+ *
+ *  Automated Options is free software.
+ *  You may redistribute it and/or modify it under the terms of the
+ *  GNU General Public License, as published by the Free Software
+ *  Foundation; either version 2, or (at your option) any later version.
+ *
+ *  Automated Options is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with Automated Options.  See the file "COPYING".  If not,
+ *  write to:  The Free Software Foundation, Inc.,
+ *             51 Franklin Street, Fifth Floor,
+ *             Boston, MA  02110-1301, USA.
+ *
+ * As a special exception, Bruce Korb gives permission for additional
+ * uses of the text contained in his release of AutoOpts.
+ *
+ * The exception is that, if you link the AutoOpts library with other
+ * files to produce an executable, this does not by itself cause the
+ * resulting executable to be covered by the GNU General Public License.
+ * Your use of that executable is in no way restricted on account of
+ * linking the AutoOpts library code into it.
+ *
+ * This exception does not however invalidate any other reasons why
+ * the executable file might be covered by the GNU General Public License.
+ *
+ * This exception applies only to the code released by Bruce Korb under
+ * the name AutoOpts.  If you copy code from other sources under the
+ * General Public License into a copy of AutoOpts, as the General Public
+ * License permits, the exception does not apply to the code that you add
+ * in this way.  To avoid misleading anyone as to the status of such
+ * modified files, you must delete this exception notice from them.
+ *
+ * If you write modifications of your own for AutoOpts, it is your choice
+ * whether to permit this exception to apply to your modifications.
+ * If you do not wish that, delete this exception notice.
+ */
+
+#include REGEX_HEADER
+
+/*=export_func  optionUnstackArg
+ * private:
+ *
+ * what:  Remove option args from a stack
+ * arg:   + tOptions* + pOpts    + program options descriptor +
+ * arg:   + tOptDesc* + pOptDesc + the descriptor for this arg +
+ *
+ * doc:
+ *  Invoked for options that are equivalenced to stacked options.
+=*/
+void
+optionUnstackArg(
+    tOptions*  pOpts,
+    tOptDesc*  pOptDesc )
+{
+    int       res;
+
+    tArgList* pAL = (tArgList*)pOptDesc->optCookie;
+    /*
+     *  IF we don't have any stacked options,
+     *  THEN indicate that we don't have any of these options
+     */
+    if (pAL == NULL) {
+        pOptDesc->fOptState &= OPTST_PERSISTENT;
+        if ( (pOptDesc->fOptState & OPTST_INITENABLED) == 0)
+            pOptDesc->fOptState |= OPTST_DISABLED;
+        return;
+    }
+
+    {
+        regex_t   re;
+        int       i, ct, dIdx;
+
+        if (regcomp( &re, pOptDesc->pzLastArg, REG_NOSUB ) != 0)
+            return;
+
+        /*
+         *  search the list for the entry(s) to remove.  Entries that
+         *  are removed are *not* copied into the result.  The source
+         *  index is incremented every time.  The destination only when
+         *  we are keeping a define.
+         */
+        for (i = 0, dIdx = 0, ct = pAL->useCt; --ct >= 0; i++) {
+            tCC*      pzSrc = pAL->apzArgs[ i ];
+            char*     pzEq  = strchr( pzSrc, '=' );
+
+            if (pzEq != NULL)
+                *pzEq = NUL;
+
+            res = regexec( &re, pzSrc, (size_t)0, NULL, 0 );
+            switch (res) {
+            case 0:
+                /*
+                 *  Remove this entry by reducing the in-use count
+                 *  and *not* putting the string pointer back into
+                 *  the list.
+                 */
+                pAL->useCt--;
+                break;
+
+            default:
+            case REG_NOMATCH:
+                if (pzEq != NULL)
+                    *pzEq = '=';
+
+                /*
+                 *  IF we have dropped an entry
+                 *  THEN we have to move the current one.
+                 */
+                if (dIdx != i)
+                    pAL->apzArgs[ dIdx ] = pzSrc;
+                dIdx++;
+            }
+        }
+
+        regfree( &re );
+    }
+
+    /*
+     *  IF we have unstacked everything,
+     *  THEN indicate that we don't have any of these options
+     */
+    if (pAL->useCt == 0) {
+        pOptDesc->fOptState &= OPTST_PERSISTENT;
+        if ( (pOptDesc->fOptState & OPTST_INITENABLED) == 0)
+            pOptDesc->fOptState |= OPTST_DISABLED;
+        free( (void*)pAL );
+        pOptDesc->optCookie = NULL;
+    }
+}
+
+
+/*
+ *  Put an entry into an argument list.  The first argument points to
+ *  a pointer to the argument list structure.  It gets passed around
+ *  as an opaque address.
+ */
+LOCAL void
+addArgListEntry( void** ppAL, void* entry )
+{
+    tArgList* pAL = *(void**)ppAL;
+
+    /*
+     *  IF we have never allocated one of these,
+     *  THEN allocate one now
+     */
+    if (pAL == NULL) {
+        pAL = (tArgList*)AGALOC( sizeof( *pAL ), "new option arg stack" );
+        if (pAL == NULL)
+            return;
+        pAL->useCt   = 0;
+        pAL->allocCt = MIN_ARG_ALLOC_CT;
+        *ppAL = (void*)pAL;
+    }
+
+    /*
+     *  ELSE if we are out of room
+     *  THEN make it bigger
+     */
+    else if (pAL->useCt >= pAL->allocCt) {
+        size_t sz = sizeof( *pAL );
+        pAL->allocCt += INCR_ARG_ALLOC_CT;
+
+        /*
+         *  The base structure contains space for MIN_ARG_ALLOC_CT
+         *  pointers.  We subtract it off to find our augment size.
+         */
+        sz += sizeof(char*) * (pAL->allocCt - MIN_ARG_ALLOC_CT);
+        pAL = (tArgList*)AGREALOC( (void*)pAL, sz, "expanded opt arg stack" );
+        if (pAL == NULL)
+            return;
+        *ppAL = (void*)pAL;
+    }
+
+    /*
+     *  Insert the new argument into the list
+     */
+    pAL->apzArgs[ (pAL->useCt)++ ] = entry;
+}
+
+
+/*=export_func  optionStackArg
+ * private:
+ *
+ * what:  put option args on a stack
+ * arg:   + tOptions* + pOpts    + program options descriptor +
+ * arg:   + tOptDesc* + pOptDesc + the descriptor for this arg +
+ *
+ * doc:
+ *  Keep an entry-ordered list of option arguments.
+=*/
+void
+optionStackArg(
+    tOptions*  pOpts,
+    tOptDesc*  pOD )
+{
+    if (pOD->pzLastArg == NULL)
+        return;
+
+    addArgListEntry( &(pOD->optCookie), (void*)pOD->pzLastArg );
+}
+/*
+ * Local Variables:
+ * mode: C
+ * c-file-style: "stroustrup"
+ * tab-width: 4
+ * indent-tabs-mode: nil
+ * End:
+ * end of autoopts/stack.c */
diff --git a/sntp/libopts/streqvcmp.c b/sntp/libopts/streqvcmp.c
new file mode 100644 (file)
index 0000000..135e235
--- /dev/null
@@ -0,0 +1,292 @@
+
+/*
+ *  $Id: streqvcmp.c,v 4.7 2006/03/25 19:24:56 bkorb Exp $
+ * Time-stamp:      "2005-10-29 14:05:07 bkorb"
+ *
+ *  String Equivalence Comparison
+ *
+ *  These routines allow any character to be mapped to any other
+ *  character before comparison.  In processing long option names,
+ *  the characters "-", "_" and "^" all need to be equivalent
+ *  (because they are treated so by different development environments).
+ */
+
+/*
+ *  Automated Options copyright 1992-2006 Bruce Korb
+ *
+ *  Automated Options is free software.
+ *  You may redistribute it and/or modify it under the terms of the
+ *  GNU General Public License, as published by the Free Software
+ *  Foundation; either version 2, or (at your option) any later version.
+ *
+ *  Automated Options is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with Automated Options.  See the file "COPYING".  If not,
+ *  write to:  The Free Software Foundation, Inc.,
+ *             51 Franklin Street, Fifth Floor,
+ *             Boston, MA  02110-1301, USA.
+ *
+ * As a special exception, Bruce Korb gives permission for additional
+ * uses of the text contained in his release of AutoOpts.
+ *
+ * The exception is that, if you link the AutoOpts library with other
+ * files to produce an executable, this does not by itself cause the
+ * resulting executable to be covered by the GNU General Public License.
+ * Your use of that executable is in no way restricted on account of
+ * linking the AutoOpts library code into it.
+ *
+ * This exception does not however invalidate any other reasons why
+ * the executable file might be covered by the GNU General Public License.
+ *
+ * This exception applies only to the code released by Bruce Korb under
+ * the name AutoOpts.  If you copy code from other sources under the
+ * General Public License into a copy of AutoOpts, as the General Public
+ * License permits, the exception does not apply to the code that you add
+ * in this way.  To avoid misleading anyone as to the status of such
+ * modified files, you must delete this exception notice from them.
+ *
+ * If you write modifications of your own for AutoOpts, it is your choice
+ * whether to permit this exception to apply to your modifications.
+ * If you do not wish that, delete this exception notice.
+ */
+
+/*
+ * This array is designed for mapping upper and lower case letter
+ * together for a case independent comparison.  The mappings are
+ * based upon ascii character sequences.
+ */
+static unsigned char charmap[] = {
+    0x00, 0x01, 0x02, 0x03,  0x04, 0x05, 0x06, '\a',
+    '\b', '\t', '\n', '\v',  '\f', '\r', 0x0E, 0x0F,
+    0x10, 0x11, 0x12, 0x13,  0x14, 0x15, 0x16, 0x17,
+    0x18, 0x19, 0x1A, 0x1B,  0x1C, 0x1D, 0x1E, 0x1F,
+
+    ' ',  '!',  '"',  '#',   '$',  '%',  '&',  '\'',
+    '(',  ')',  '*',  '+',   ',',  '-',  '.',  '/',
+    '0',  '1',  '2',  '3',   '4',  '5',  '6',  '7',
+    '8',  '9',  ':',  ';',   '<',  '=',  '>',  '?',
+
+    '@',  'a',  'b',  'c',   'd',  'e',  'f',  'g',
+    'h',  'i',  'j',  'k',   'l',  'm',  'n',  'o',
+    'p',  'q',  'r',  's',   't',  'u',  'v',  'w',
+    'x',  'y',  'z',  '[',   '\\', ']',  '^',  '_',
+    '`',  'a',  'b',  'c',   'd',  'e',  'f',  'g',
+    'h',  'i',  'j',  'k',   'l',  'm',  'n',  'o',
+    'p',  'q',  'r',  's',   't',  'u',  'v',  'w',
+    'x',  'y',  'z',  '{',   '|',  '}',  '~',  0x7f,
+
+    0x80, 0x81, 0x82, 0x83,  0x84, 0x85, 0x86, 0x87,
+    0x88, 0x89, 0x8A, 0x8B,  0x8C, 0x8D, 0x8E, 0x8F,
+    0x90, 0x91, 0x92, 0x93,  0x94, 0x95, 0x96, 0x97,
+    0x98, 0x99, 0x9A, 0x9B,  0x9C, 0x9D, 0x9E, 0x9F,
+    0xA0, 0xA1, 0xA2, 0xA3,  0xA4, 0xA5, 0xA6, 0xA7,
+    0xA8, 0xA9, 0xAA, 0xAB,  0xAC, 0xAD, 0xAE, 0xAF,
+    0xB0, 0xB1, 0xB2, 0xB3,  0xB4, 0xB5, 0xB6, 0xB7,
+    0xB8, 0xB9, 0xBA, 0xBB,  0xBC, 0xBD, 0xBE, 0xBF,
+
+    0xC0, 0xC1, 0xC2, 0xC3,  0xC4, 0xC5, 0xC6, 0xC7,
+    0xC8, 0xC9, 0xCA, 0xCB,  0xCC, 0xCD, 0xCE, 0xCF,
+    0xD0, 0xD1, 0xD2, 0xD3,  0xD4, 0xD5, 0xD6, 0xD7,
+    0xD8, 0xD9, 0xDA, 0xDB,  0xDC, 0xDD, 0xDE, 0xDF,
+    0xE0, 0xE1, 0xE2, 0xE3,  0xE4, 0xE5, 0xE6, 0xE7,
+    0xE8, 0xE9, 0xEA, 0xEB,  0xEC, 0xED, 0xEE, 0xEF,
+    0xF0, 0xF1, 0xF2, 0xF3,  0xF4, 0xF5, 0xF6, 0xF7,
+    0xF8, 0xF9, 0xFA, 0xFB,  0xFC, 0xFD, 0xFE, 0xFF,
+};
+
+
+/*=export_func strneqvcmp
+ *
+ * what: compare two strings with an equivalence mapping
+ *
+ * arg:  + const char* + str1 + first string +
+ * arg:  + const char* + str2 + second string +
+ * arg:  + int         + ct   + compare length +
+ *
+ * ret_type:  int
+ * ret_desc:  the difference between two differing characters
+ *
+ * doc:
+ *
+ * Using a character mapping, two strings are compared for "equivalence".
+ * Each input character is mapped to a comparison character and the
+ * mapped-to characters are compared for the two NUL terminated input strings.
+ * The comparison is limited to @code{ct} bytes.
+ * This function name is mapped to option_strneqvcmp so as to not conflict
+ * with the POSIX name space.
+ *
+ * err:  none checked.  Caller responsible for seg faults.
+=*/
+int
+strneqvcmp( tCC* s1, tCC* s2, int ct )
+{
+    for (; ct > 0; --ct) {
+        unsigned char u1 = (unsigned char) *s1++;
+        unsigned char u2 = (unsigned char) *s2++;
+        int dif = charmap[ u1 ] - charmap[ u2 ];
+
+        if (dif != 0)
+            return dif;
+
+        if (u1 == NUL)
+            return 0;
+    }
+
+    return 0;
+}
+
+
+/*=export_func streqvcmp
+ *
+ * what: compare two strings with an equivalence mapping
+ *
+ * arg:  + const char* + str1 + first string +
+ * arg:  + const char* + str2 + second string +
+ *
+ * ret_type:  int
+ * ret_desc:  the difference between two differing characters
+ *
+ * doc:
+ *
+ * Using a character mapping, two strings are compared for "equivalence".
+ * Each input character is mapped to a comparison character and the
+ * mapped-to characters are compared for the two NUL terminated input strings.
+ * This function name is mapped to option_streqvcmp so as to not conflict
+ * with the POSIX name space.
+ *
+ * err:  none checked.  Caller responsible for seg faults.
+=*/
+int
+streqvcmp( tCC* s1, tCC* s2 )
+{
+    for (;;) {
+        unsigned char u1 = (unsigned char) *s1++;
+        unsigned char u2 = (unsigned char) *s2++;
+        int dif = charmap[ u1 ] - charmap[ u2 ];
+
+        if (dif != 0)
+            return dif;
+
+        if (u1 == NUL)
+            return 0;
+    }
+}
+
+
+/*=export_func streqvmap
+ *
+ * what: Set the character mappings for the streqv functions
+ *
+ * arg:  + char + From + Input character +
+ * arg:  + char + To   + Mapped-to character +
+ * arg:  + int  + ct   + compare length +
+ *
+ * doc:
+ *
+ * Set the character mapping.  If the count (@code{ct}) is set to zero, then
+ * the map is cleared by setting all entries in the map to their index
+ * value.  Otherwise, the "@code{From}" character is mapped to the "@code{To}"
+ * character.  If @code{ct} is greater than 1, then @code{From} and @code{To}
+ * are incremented and the process repeated until @code{ct} entries have been
+ * set. For example,
+ * @example
+ *    streqvmap( 'a', 'A', 26 );
+ * @end example
+ * @noindent
+ * will alter the mapping so that all English lower case letters
+ * will map to upper case.
+ *
+ * This function name is mapped to option_streqvmap so as to not conflict
+ * with the POSIX name space.
+ *
+ * err:  none.
+=*/
+void
+streqvmap( char From, char To, int ct )
+{
+    if (ct == 0) {
+        ct = sizeof( charmap ) - 1;
+        do  {
+            charmap[ ct ] = ct;
+        } while (--ct >= 0);
+    }
+
+    else {
+        int  chTo   = (int)To   & 0xFF;
+        int  chFrom = (int)From & 0xFF;
+
+        do  {
+            charmap[ chFrom ] = (unsigned)chTo;
+            chFrom++;
+            chTo++;
+            if ((chFrom >= sizeof( charmap )) || (chTo >= sizeof( charmap )))
+                break;
+        } while (--ct > 0);
+    }
+}
+
+
+/*=export_func strequate
+ *
+ * what: map a list of characters to the same value
+ *
+ * arg:  + const char* + ch_list + characters to equivalence +
+ *
+ * doc:
+ *
+ * Each character in the input string get mapped to the first character
+ * in the string.
+ * This function name is mapped to option_strequate so as to not conflict
+ * with the POSIX name space.
+ *
+ * err:  none.
+=*/
+void
+strequate( const char* s )
+{
+    if ((s != NULL) && (*s != NUL)) {
+        unsigned char equiv = (unsigned)*s;
+        while (*s != NUL)
+            charmap[ (unsigned)*(s++) ] = equiv;
+    }
+}
+
+
+/*=export_func strtransform
+ *
+ * what: convert a string into its mapped-to value
+ *
+ * arg:  + char*       + dest + output string +
+ * arg:  + const char* + src  + input string +
+ *
+ * doc:
+ *
+ * Each character in the input string is mapped and the mapped-to
+ * character is put into the output.
+ * This function name is mapped to option_strtransform so as to not conflict
+ * with the POSIX name space.
+ *
+ * err:  none.
+=*/
+void
+strtransform( d, s )
+    char*       d;
+    const char* s;
+{
+    do  {
+        *(d++) = (char)charmap[ (unsigned)*s ];
+    } while (*(s++) != NUL);
+}
+
+/*
+ * Local Variables:
+ * mode: C
+ * c-file-style: "stroustrup"
+ * tab-width: 4
+ * indent-tabs-mode: nil
+ * End:
+ * end of autoopts/streqvcmp.c */
diff --git a/sntp/libopts/text_mmap.c b/sntp/libopts/text_mmap.c
new file mode 100644 (file)
index 0000000..825cd90
--- /dev/null
@@ -0,0 +1,367 @@
+/*
+ * $Id: text_mmap.c,v 4.11 2006/02/01 17:18:00 bkorb Exp $
+ *
+ * Time-stamp:      "2006-02-01 08:45:37 bkorb"
+ */
+
+#ifndef MAP_ANONYMOUS 
+#  ifdef   MAP_ANON 
+#  define  MAP_ANONYMOUS   MAP_ANON 
+#  endif 
+#endif 
+
+/*
+ *  Some weird systems require that a specifically invalid FD number
+ *  get passed in as an argument value.  Which value is that?  Well,
+ *  as everybody knows, if open(2) fails, it returns -1, so that must
+ *  be the value.  :)
+ */
+#define AO_INVALID_FD  -1
+
+#define FILE_WRITABLE(_prt,_flg) \
+       ((_prt & PROT_WRITE) && (_flg & (MAP_SHARED|MAP_PRIVATE) == MAP_SHARED))
+#define MAP_FAILED_PTR ((void*)MAP_FAILED)
+
+/*=export_func  text_mmap
+ * private:
+ *
+ * what:  map a text file with terminating NUL
+ *
+ * arg:   const char*,  pzFile,  name of the file to map
+ * arg:   int,          prot,    mmap protections (see mmap(2))
+ * arg:   int,          flags,   mmap flags (see mmap(2))
+ * arg:   tmap_info_t*, mapinfo, returned info about the mapping
+ *
+ * ret-type:   void*
+ * ret-desc:   The mmaped data address
+ *
+ * doc:
+ *
+ * This routine will mmap a file into memory ensuring that there is at least
+ * one @file{NUL} character following the file data.  It will return the
+ * address where the file contents have been mapped into memory.  If there is a
+ * problem, then it will return @code{MAP_FAILED} and set @file{errno}
+ * appropriately.
+ *
+ * The named file does not exist, @code{stat(2)} will set @file{errno} as it
+ * will.  If the file is not a regular file, @file{errno} will be
+ * @code{EINVAL}.  At that point, @code{open(2)} is attempted with the access
+ * bits set appropriately for the requested @code{mmap(2)} protections and flag
+ * bits.  On failure, @file{errno} will be set according to the documentation
+ * for @code{open(2)}.  If @code{mmap(2)} fails, @file{errno} will be set as
+ * that routine sets it.  If @code{text_mmap} works to this point, a valid
+ * address will be returned, but there may still be ``issues''.
+ *
+ * If the file size is not an even multiple of the system page size, then
+ * @code{text_map} will return at this point and @file{errno} will be zero.
+ * Otherwise, an anonymous map is attempted.  If not available, then an attempt
+ * is made to @code{mmap(2)} @file{/dev/zero}.  If any of these fail, the
+ * address of the file's data is returned, bug @code{no} @file{NUL} characters
+ * are mapped after the end of the data.
+ *
+ * see: mmap(2), open(2), stat(2)
+ *
+ * err: Any error code issued by mmap(2), open(2), stat(2) is possible.
+ *      Additionally, if the specified file is not a regular file, then
+ *      errno will be set to @code{EINVAL}.
+ *
+ * example:
+ * #include <mylib.h>
+ * tmap_info_t mi;
+ * int no_nul;
+ * void* data = text_mmap( "file", PROT_WRITE, MAP_PRIVATE, &mi );
+ * if (data == MAP_FAILED) return;
+ * no_nul = (mi.txt_size == mi.txt_full_size);
+ * << use the data >>
+ * text_munmap( &mi );
+=*/
+void*
+text_mmap( const char* pzFile, int prot, int flags, tmap_info_t* pMI )
+{
+    memset( pMI, 0, sizeof(*pMI) );
+#ifdef HAVE_MMAP
+    pMI->txt_zero_fd = -1;
+#endif
+    pMI->txt_fd = -1;
+
+    /*
+     *  Make sure we can stat the regular file.  Save the file size.
+     */
+    {
+        struct stat sb;
+        if (stat( pzFile, &sb ) != 0) {
+            pMI->txt_errno = errno;
+            return MAP_FAILED_PTR;
+        }
+
+        if (! S_ISREG( sb.st_mode )) {
+            pMI->txt_errno = errno = EINVAL;
+            return MAP_FAILED_PTR;
+        }
+
+        pMI->txt_size = sb.st_size;
+    }
+
+    /*
+     *  Map mmap flags and protections into open flags and do the open.
+     */
+    {
+        int o_flag;
+        /*
+         *  See if we will be updating the file.  If we can alter the memory
+         *  and if we share the data and we are *not* copy-on-writing the data,
+         *  then our updates will show in the file, so we must open with
+         *  write access.
+         */
+        if (FILE_WRITABLE(prot,flags))
+            o_flag = O_RDWR;
+        else
+            o_flag = O_RDONLY;
+
+        /*
+         *  If you're not sharing the file and you are writing to it,
+         *  then don't let anyone else have access to the file.
+         */
+        if (((flags & MAP_SHARED) == 0) && (prot & PROT_WRITE))
+            o_flag |= O_EXCL;
+
+        pMI->txt_fd = open( pzFile, o_flag );
+    }
+
+    if (pMI->txt_fd == AO_INVALID_FD) {
+        pMI->txt_errno = errno;
+        return MAP_FAILED_PTR;
+    }
+
+#ifdef HAVE_MMAP /* * * * * WITH MMAP * * * * * */
+    /*
+     *  do the mmap.  If we fail, then preserve errno, close the file and
+     *  return the failure.
+     */
+    pMI->txt_data = mmap( NULL, pMI->txt_size+1, prot, flags, pMI->txt_fd, 0 );
+    if (pMI->txt_data == MAP_FAILED_PTR) {
+        pMI->txt_errno = errno;
+        goto fail_return;
+    }
+
+    /*
+     *  Most likely, everything will turn out fine now.  The only difficult
+     *  part at this point is coping with files with sizes that are a multiple
+     *  of the page size.  Handling that is what this whole thing is about.
+     */
+    pMI->txt_zero_fd = -1;
+    pMI->txt_errno   = 0;
+
+    {
+        void* pNuls;
+#ifdef _SC_PAGESIZE
+        size_t pgsz = sysconf(_SC_PAGESIZE);
+#else
+        size_t pgsz = getpagesize();
+#endif
+        /*
+         *  Compute the pagesize rounded mapped memory size.
+         *  IF this is not the same as the file size, then there are NUL's
+         *  at the end of the file mapping and all is okay.
+         */
+        pMI->txt_full_size = (pMI->txt_size + (pgsz - 1)) & ~(pgsz - 1);
+        if (pMI->txt_size != pMI->txt_full_size)
+            return pMI->txt_data;
+
+        /*
+         *  Still here?  We have to remap the trailing inaccessible page
+         *  either anonymously or to /dev/zero.
+         */
+        pMI->txt_full_size += pgsz;
+#if defined(MAP_ANONYMOUS)
+        pNuls = mmap(
+                (void*)(((char*)pMI->txt_data) + pMI->txt_size),
+                pgsz, PROT_READ|PROT_WRITE,
+                MAP_ANONYMOUS|MAP_FIXED|MAP_PRIVATE, AO_INVALID_FD, 0 );
+
+        if (pNuls != MAP_FAILED_PTR)
+            return pMI->txt_data;
+
+        pMI->txt_errno = errno;
+#endif
+
+#if defined(HAVE_DEV_ZERO)
+        pMI->txt_zero_fd = open( "/dev/zero", O_RDONLY );
+
+        if (pMI->txt_zero_fd == AO_INVALID_FD) {
+            pMI->txt_errno = errno;
+
+        } else {
+            pNuls = mmap(
+                    (void*)(((char*)pMI->txt_data) + pMI->txt_size), pgsz,
+                    PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED,
+                    pMI->txt_zero_fd, 0 );
+
+            if (pNuls != MAP_FAILED_PTR)
+                return pMI->txt_data;
+
+            pMI->txt_errno = errno;
+            close( pMI->txt_zero_fd );
+            pMI->txt_zero_fd = -1;
+        }
+#endif
+
+        pMI->txt_full_size = pMI->txt_size;
+    }
+
+    {
+        void* p = AGALOC( pMI->txt_size+1, "file text" );
+        if (pMI->txt_data == NULL) {
+            pMI->txt_errno = ENOMEM;
+            goto fail_return;
+        }
+        memcpy( p, pMI->txt_data, pMI->txt_size );
+        ((char*)p)[pMI->txt_size] = NUL;
+        munmap(pMI->txt_data, pMI->txt_size );
+        pMI->txt_data = p;
+    }
+    pMI->txt_alloc = 1;
+    return pMI->txt_data;
+
+#else /* * * * * * no HAVE_MMAP * * * * * */
+
+    pMI->txt_data = AGALOC( pMI->txt_size+1, "file text" );
+    if (pMI->txt_data == NULL) {
+        pMI->txt_errno = ENOMEM;
+        goto fail_return;
+    }
+
+    {
+        size_t sz = pMI->txt_size;
+        char*  pz = pMI->txt_data;
+
+        while (sz > 0) {
+            ssize_t rdct = read( pMI->txt_fd, pz, sz );
+            if (rdct <= 0) {
+                pMI->txt_errno = errno;
+                fprintf( stderr, zFSErrReadFile,
+                         errno, strerror( errno ), pzFile );
+                free( pMI->txt_data );
+                goto fail_return;
+            }
+
+            pz += rdct;
+            sz -= rdct;
+        }
+
+        *pz = NUL;
+    }
+
+    /*
+     *  We never need a dummy page mapped in
+     */
+    pMI->txt_zero_fd = -1;
+    pMI->txt_errno   = 0;
+
+    return pMI->txt_data;
+
+#endif /* * * * * * no HAVE_MMAP * * * * * */
+
+ fail_return:
+    if (pMI->txt_fd >= 0) {
+        close( pMI->txt_fd );
+        pMI->txt_fd = -1;
+    }
+    errno = pMI->txt_errno;
+    pMI->txt_data = MAP_FAILED_PTR;
+    return pMI->txt_data;
+}
+
+
+/*=export_func  text_munmap
+ * private:
+ *
+ * what:  unmap the data mapped in by text_mmap
+ *
+ * arg:   tmap_info_t*, mapinfo, info about the mapping
+ *
+ * ret-type:   int
+ * ret-desc:   -1 or 0.  @file{errno} will have the error code.
+ *
+ * doc:
+ *
+ * This routine will unmap the data mapped in with @code{text_mmap} and close
+ * the associated file descriptors opened by that function.
+ *
+ * see: munmap(2), close(2)
+ *
+ * err: Any error code issued by munmap(2) or close(2) is possible.
+=*/
+int
+text_munmap( tmap_info_t* pMI )
+{
+#ifdef HAVE_MMAP
+    int res = 0;
+    if (pMI->txt_alloc) {
+        /*
+         *  IF the user has write permission and the text is not mapped private,
+         *  then write back any changes.  Hopefully, nobody else has modified
+         *  the file in the mean time.
+         */
+        if (   ((pMI->txt_prot & PROT_WRITE) != 0)
+            && ((pMI->txt_flags & MAP_PRIVATE) == 0))  {
+
+            if (lseek( pMI->txt_fd, 0, SEEK_SET) != 0)
+                goto error_return;
+
+            res = (write( pMI->txt_fd, pMI->txt_data, pMI->txt_size ) < 0)
+                ? errno : 0;
+        }
+
+        AGFREE( pMI->txt_data );
+        errno = res;
+    } else {
+        res = munmap( pMI->txt_data, pMI->txt_full_size );
+    }
+    if (res != 0)
+        goto error_return;
+
+    res = close( pMI->txt_fd );
+    if (res != 0)
+        goto error_return;
+
+    pMI->txt_fd = -1;
+    errno = 0;
+    if (pMI->txt_zero_fd != -1) {
+        res = close( pMI->txt_zero_fd );
+        pMI->txt_zero_fd = -1;
+    }
+
+ error_return:
+    pMI->txt_errno = errno;
+    return res;
+#else  /* HAVE_MMAP */
+
+    errno = 0;
+    /*
+     *  IF the memory is writable *AND* it is not private (copy-on-write)
+     *     *AND* the memory is "sharable" (seen by other processes)
+     *  THEN rewrite the data.
+     */
+    if (   FILE_WRITABLE(pMI->txt_prot, pMI->txt_flags)
+        && (lseek( pMI->txt_fd, 0, SEEK_SET ) >= 0) ) {
+        write( pMI->txt_fd, pMI->txt_data, pMI->txt_size );
+    }
+
+    close( pMI->txt_fd );
+    pMI->txt_fd = -1;
+    pMI->txt_errno = errno;
+    free( pMI->txt_data );
+
+    return pMI->txt_errno;
+#endif /* HAVE_MMAP */
+}
+
+/*
+ * Local Variables:
+ * mode: C
+ * c-file-style: "stroustrup"
+ * tab-width: 4
+ * indent-tabs-mode: nil
+ * End:
+ * end of autoopts/text_mmap.c */
diff --git a/sntp/libopts/tokenize.c b/sntp/libopts/tokenize.c
new file mode 100644 (file)
index 0000000..074473c
--- /dev/null
@@ -0,0 +1,322 @@
+/*
+ *  This file defines the string_tokenize interface
+ * Time-stamp:      "2005-04-25 18:47:21 bkorb"
+ *
+ *  string_tokenize copyright 2005 Bruce Korb
+ *
+ *  string_tokenize is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public
+ *  License as published by the Free Software Foundation; either
+ *  version 2.1 of the License, or (at your option) any later version.
+ *
+ *  string_tokenize is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with string_tokenize; if not, write to:
+ *             The Free Software Foundation, Inc.,
+ *             51 Franklin Street, Fifth Floor,
+ *             Boston, MA  02110-1301, USA.
+ */
+#include <ctype.h>
+#include <errno.h>
+#include <stdlib.h>
+
+#define cc_t   const unsigned char
+#define ch_t   unsigned char
+
+/* = = = START-STATIC-FORWARD = = = */
+/* static forward declarations maintained by :mkfwd */
+static void
+copy_cooked( ch_t** ppDest, cc_t** ppSrc );
+
+static void
+copy_raw( ch_t** ppDest, cc_t** ppSrc );
+/* = = = END-STATIC-FORWARD = = = */
+
+static void
+copy_cooked( ch_t** ppDest, cc_t** ppSrc )
+{
+    ch_t* pDest = (ch_t*)*ppDest;
+    const ch_t* pSrc  = (const ch_t*)(*ppSrc + 1);
+
+    for (;;) {
+        ch_t ch = *(pSrc++);
+        switch (ch) {
+        case NUL:   *ppSrc = NULL; return;
+        case '"':   goto done;
+        case '\\':
+            pSrc += ao_string_cook_escape_char( (char*)pSrc, (char*)&ch, 0x7F );
+            if (ch == 0x7F)
+                break;
+            /* FALLTHROUGH */
+
+        default:
+            *(pDest++) = ch;
+        }
+    }
+
+ done:
+    *ppDest = (ch_t*)pDest; /* next spot for storing character */
+    *ppSrc  = (ch_t*)pSrc;  /* char following closing quote    */
+}
+
+
+static void
+copy_raw( ch_t** ppDest, cc_t** ppSrc )
+{
+    ch_t* pDest = *ppDest;
+    cc_t* pSrc  = *ppSrc + 1;
+
+    for (;;) {
+        ch_t ch = *(pSrc++);
+        switch (ch) {
+        case NUL:   *ppSrc = NULL; return;
+        case '\'':  goto done;
+        case '\\':
+            /*
+             *  *Four* escapes are handled:  newline removal, escape char
+             *  quoting and apostrophe quoting
+             */
+            switch (*pSrc) {
+            case NUL:   *ppSrc = NULL; return;
+            case '\r':
+                if (*(++pSrc) == '\n')
+                    ++pSrc;
+                continue;
+
+            case '\n':
+                ++pSrc;
+                continue;
+
+            case '\'':
+                ch = '\'';
+                /* FALLTHROUGH */
+
+            case '\\':
+                ++pSrc;
+                break;
+            }
+            /* FALLTHROUGH */
+
+        default:
+            *(pDest++) = ch;
+        }
+    }
+
+ done:
+    *ppDest = pDest; /* next spot for storing character */
+    *ppSrc  = pSrc;  /* char following closing quote    */
+}
+
+
+/*=export_func ao_string_tokenize
+ *
+ * what: tokenize an input string
+ *
+ * arg:  + const char* + string + string to be tokenized +
+ *
+ * ret_type:  token_list_t*
+ * ret_desc:  pointer to a structure that lists each token
+ *
+ * doc:
+ *
+ * This function will convert one input string into a list of strings.
+ * The list of strings is derived by separating the input based on
+ * white space separation.  However, if the input contains either single
+ * or double quote characters, then the text after that character up to
+ * a matching quote will become the string in the list.
+ *
+ *  The returned pointer should be deallocated with @code{free(3C)} when
+ *  are done using the data.  The data are placed in a single block of
+ *  allocated memory.  Do not deallocate individual token/strings.
+ *
+ *  The structure pointed to will contain at least these two fields:
+ *  @table @samp
+ *  @item tkn_ct
+ *  The number of tokens found in the input string.
+ *  @item tok_list
+ *  An array of @code{tkn_ct + 1} pointers to substring tokens, with
+ *  the last pointer set to NULL.
+ *  @end table
+ *
+ * There are two types of quoted strings: single quoted (@code{'}) and
+ * double quoted (@code{"}).  Singly quoted strings are fairly raw in that
+ * escape characters (@code{\\}) are simply another character, except when
+ * preceding the following characters:
+ * @example
+ * @code{\\}  double backslashes reduce to one
+ * @code{'}   incorporates the single quote into the string
+ * @code{\n}  suppresses both the backslash and newline character
+ * @end example
+ *
+ * Double quote strings are formed according to the rules of string
+ * constants in ANSI-C programs.
+ *
+ * example:
+ * @example
+ *    #include <stdlib.h>
+ *    int ix;
+ *    token_list_t* ptl = ao_string_tokenize( some_string )
+ *    for (ix = 0; ix < ptl->tkn_ct; ix++)
+ *       do_something_with_tkn( ptl->tkn_list[ix] );
+ *    free( ptl );
+ * @end example
+ * Note that everything is freed with the one call to @code{free(3C)}.
+ *
+ * err:
+ *  NULL is returned and @code{errno} will be set to indicate the problem:
+ *  @itemize @bullet
+ *  @item
+ *  @code{EINVAL} - There was an unterminated quoted string.
+ *  @item
+ *  @code{ENOENT} - The input string was empty.
+ *  @item
+ *  @code{ENOMEM} - There is not enough memory.
+ *  @end itemize
+=*/
+token_list_t*
+ao_string_tokenize( const char* str )
+{
+    int max_token_ct = 1; /* allow for trailing NUL on string */
+    token_list_t* res;
+
+    if (str == NULL)  goto bogus_str;
+
+    /*
+     *  Trim leading white space.  Use "ENOENT" and a NULL return to indicate
+     *  an empty string was passed.
+     */
+    while (isspace( *str ))  str++;
+    if (*str == NUL) {
+    bogus_str:
+        errno = ENOENT;
+        return NULL;
+    }
+
+    /*
+     *  Take an approximate count of tokens.  If no quoted strings are used,
+     *  it will be accurate.  If quoted strings are used, it will be a little
+     *  high and we'll squander the space for a few extra pointers.
+     */
+    {
+        cc_t* pz = (cc_t*)str;
+
+        do {
+            max_token_ct++;
+            while (! isspace( *++pz ))
+                if (*pz == NUL) goto found_nul;
+            while (isspace( *pz ))  pz++;
+        } while (*pz != NUL);
+
+    found_nul:
+        ;
+    }
+
+    res = malloc( sizeof(*res) + strlen(str) + (max_token_ct * sizeof(ch_t*)) );
+    if (res == NULL) {
+        errno = ENOMEM;
+        return res;
+    }
+
+    /*
+     *  Now copy each token into the output buffer.
+     */
+    {
+        ch_t* pzDest = (ch_t*)(res->tkn_list + (max_token_ct + 1));
+        res->tkn_ct  = 0;
+
+        do  {
+            res->tkn_list[ res->tkn_ct++ ] = pzDest;
+            for (;;) {
+                char ch = *str;
+                if (isspace( ch )) {
+                found_white_space:
+                    while (isspace( *++str ))  ;
+                    break;
+                }
+
+                switch (ch) {
+                case '"':
+                    copy_cooked( &pzDest, (cc_t**)&str );
+                    if (str == NULL) {
+                        free(res);
+                        errno = EINVAL;
+                        return NULL;
+                    }
+                    if (isspace( *str ))
+                        goto found_white_space;
+                    break;
+
+                case '\'':
+                    copy_raw( &pzDest, (cc_t**)&str );
+                    if (str == NULL) {
+                        free(res);
+                        errno = EINVAL;
+                        return NULL;
+                    }
+                    if (isspace( *str ))
+                        goto found_white_space;
+                    break;
+
+                case NUL:
+                    goto copy_done;
+
+                default:
+                    str++;
+                    *(pzDest++) = ch;
+                }
+            } copy_done:;
+
+            /*
+             * NUL terminate the last token and see if we have any more tokens.
+             */
+            *(pzDest++) = NUL;
+        } while (*str != NUL);
+
+        res->tkn_list[ res->tkn_ct ] = NULL;
+    }
+
+    return res;
+}
+
+#ifdef TEST
+#include <stdio.h>
+#include <string.h>
+
+int
+main( int argc, char** argv )
+{
+    if (argc == 1) {
+        printf("USAGE:  %s arg [ ... ]\n", *argv);
+        return 1;
+    }
+    while (--argc > 0) {
+        char* arg = *(++argv);
+        token_list_t* p = ao_string_tokenize( arg );
+        if (p == NULL) {
+            printf( "Parsing string ``%s'' failed:\n\terrno %d (%s)\n",
+                    arg, errno, strerror( errno ));
+        } else {
+            int ix = 0;
+            printf( "Parsed string ``%s''\ninto %d tokens:\n", arg, p->tkn_ct );
+            do {
+                printf( " %3d:  ``%s''\n", ix+1, p->tkn_list[ix] );
+            } while (++ix < p->tkn_ct);
+            free(p);
+        }
+    }
+    return 0;
+}
+#endif
+
+/*
+ * Local Variables:
+ * mode: C
+ * c-file-style: "stroustrup"
+ * tab-width: 4
+ * indent-tabs-mode: nil
+ * End:
+ * end of autoopts/tokenize.c */
diff --git a/sntp/libopts/usage.c b/sntp/libopts/usage.c
new file mode 100644 (file)
index 0000000..5d36ab9
--- /dev/null
@@ -0,0 +1,732 @@
+
+/*
+ *  usage.c  $Id: usage.c,v 4.11 2006/03/25 19:24:57 bkorb Exp $
+ * Time-stamp:      "2006-02-04 13:35:26 bkorb"
+ *
+ *  This module implements the default usage procedure for
+ *  Automated Options.  It may be overridden, of course.
+ *
+ *  Sort options:
+    --start=END-[S]TATIC-FORWARD --patt='^/\*($|[^:])' \
+    --out=xx.c key='^[a-zA-Z0-9_]+\(' --trail='^/\*:' \
+    --spac=2 --input=usage.c
+ */
+
+/*
+ *  Automated Options copyright 1992-2006 Bruce Korb
+ *
+ *  Automated Options is free software.
+ *  You may redistribute it and/or modify it under the terms of the
+ *  GNU General Public License, as published by the Free Software
+ *  Foundation; either version 2, or (at your option) any later version.
+ *
+ *  Automated Options is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with Automated Options.  See the file "COPYING".  If not,
+ *  write to:  The Free Software Foundation, Inc.,
+ *             51 Franklin Street, Fifth Floor,
+ *             Boston, MA  02110-1301, USA.
+ *
+ * As a special exception, Bruce Korb gives permission for additional
+ * uses of the text contained in his release of AutoOpts.
+ *
+ * The exception is that, if you link the AutoOpts library with other
+ * files to produce an executable, this does not by itself cause the
+ * resulting executable to be covered by the GNU General Public License.
+ * Your use of that executable is in no way restricted on account of
+ * linking the AutoOpts library code into it.
+ *
+ * This exception does not however invalidate any other reasons why
+ * the executable file might be covered by the GNU General Public License.
+ *
+ * This exception applies only to the code released by Bruce Korb under
+ * the name AutoOpts.  If you copy code from other sources under the
+ * General Public License into a copy of AutoOpts, as the General Public
+ * License permits, the exception does not apply to the code that you add
+ * in this way.  To avoid misleading anyone as to the status of such
+ * modified files, you must delete this exception notice from them.
+ *
+ * If you write modifications of your own for AutoOpts, it is your choice
+ * whether to permit this exception to apply to your modifications.
+ * If you do not wish that, delete this exception notice.
+ */
+
+#define OPTPROC_L_N_S  (OPTPROC_LONGOPT | OPTPROC_SHORTOPT)
+
+static arg_types_t argTypes;
+
+FILE* option_usage_fp = NULL;
+static char    zOptFmtLine[ 16 ];
+static ag_bool displayEnum;
+
+/* = = = START-STATIC-FORWARD = = = */
+/* static forward declarations maintained by :mkfwd */
+static ag_bool
+checkGNUUsage( tOptions* pOpts );
+
+static void
+printExtendedUsage(
+    tOptions*     pOptions,
+    tOptDesc*     pOD,
+    arg_types_t*  pAT );
+
+static void
+printInitList(
+    tCC**    papz,
+    ag_bool* pInitIntro,
+    tCC*     pzRc,
+    tCC*     pzPN );
+
+static void
+printOneUsage(
+    tOptions*     pOptions,
+    tOptDesc*     pOD,
+    arg_types_t*  pAT );
+
+static void
+printOptionUsage(
+    tOptions* pOpts,
+    int       ex_code,
+    tCC*      pOptTitle );
+
+static void
+printProgramDetails( tOptions* pOptions );
+
+static int
+setGnuOptFmts( tOptions* pOpts, tCC** ppT );
+
+static int
+setStdOptFmts( tOptions* pOpts, tCC** ppT );
+/* = = = END-STATIC-FORWARD = = = */
+
+
+/*
+ *  Figure out if we should try to format usage text sort-of like
+ *  the way many GNU programs do.
+ */
+static ag_bool
+checkGNUUsage( tOptions* pOpts )
+{
+    char* pz = getenv( "AUTOOPTS_USAGE" );
+    if (pz == NULL)
+        ;
+
+    else if (streqvcmp( pz, "gnu" ) == 0)
+        pOpts->fOptSet |= OPTPROC_GNUUSAGE;
+
+    else if (streqvcmp( pz, "autoopts" ) == 0)
+        pOpts->fOptSet &= ~OPTPROC_GNUUSAGE;
+
+    return (pOpts->fOptSet & OPTPROC_GNUUSAGE) ? AG_TRUE : AG_FALSE;
+}
+
+
+/*=export_func  optionOnlyUsage
+ *
+ * what:  Print usage text for just the options
+ * arg:   + tOptions*   + pOpts    + program options descriptor +
+ * arg:   + int         + ex_code  + exit code for calling exit(3) +
+ *
+ * doc:
+ *  This routine will print only the usage for each option.
+ *  This function may be used when the emitted usage must incorporate
+ *  information not available to AutoOpts.
+=*/
+void
+optionOnlyUsage(
+    tOptions* pOpts,
+    int       ex_code )
+{
+    tCC* pOptTitle;
+
+    /*
+     *  Determine which header and which option formatting strings to use
+     */
+    if (checkGNUUsage(pOpts)) {
+        (void)setGnuOptFmts( pOpts, &pOptTitle );
+    }
+    else {
+        (void)setStdOptFmts( pOpts, &pOptTitle );
+    }
+
+    printOptionUsage( pOpts, ex_code, pOptTitle );
+}
+
+
+/*=export_func  optionUsage
+ * private:
+ *
+ * what:  Print usage text
+ * arg:   + tOptions* + pOptions + program options descriptor +
+ * arg:   + int       + exitCode + exit code for calling exit(3) +
+ *
+ * doc:
+ *  This routine will print usage in both GNU-standard and AutoOpts-expanded
+ *  formats.  The descriptor specifies the default, but AUTOOPTS_USAGE will
+ *  over-ride this, providing the value of it is set to either "gnu" or
+ *  "autoopts".  This routine will @strong{not} return.
+=*/
+void
+optionUsage(
+    tOptions* pOptions,
+    int       exitCode )
+{
+    displayEnum = AG_FALSE;
+
+    /*
+     *  Paged usage will preset option_usage_fp to an output file.
+     *  If it hasn't already been set, then set it to standard output
+     *  on successful exit (help was requested), otherwise error out.
+     */
+    if (option_usage_fp == NULL)
+        option_usage_fp = (exitCode != EXIT_SUCCESS) ? stderr : stdout;
+
+    fprintf( option_usage_fp, pOptions->pzUsageTitle, pOptions->pzProgName );
+
+    {
+        tCC* pOptTitle;
+
+        /*
+         *  Determine which header and which option formatting strings to use
+         */
+        if (checkGNUUsage(pOptions)) {
+            int flen = setGnuOptFmts( pOptions, &pOptTitle );
+            sprintf( zOptFmtLine, zFmtFmt, flen );
+            fputc( '\n', option_usage_fp );
+        }
+        else {
+            int flen = setStdOptFmts( pOptions, &pOptTitle );
+            sprintf( zOptFmtLine, zFmtFmt, flen );
+
+            /*
+             *  When we exit with EXIT_SUCCESS and the first option is a doc
+             *  option, we do *NOT* want to emit the column headers.
+             *  Otherwise, we do.
+             */
+            if (  (exitCode != EXIT_SUCCESS)
+               || ((pOptions->pOptDesc->fOptState & OPTST_DOCUMENT) == 0) )
+
+                fputs( pOptTitle, option_usage_fp );
+        }
+
+        printOptionUsage( pOptions, exitCode, pOptTitle );
+    }
+
+    /*
+     *  Describe the mechanics of denoting the options
+     */
+    switch (pOptions->fOptSet & OPTPROC_L_N_S) {
+    case OPTPROC_L_N_S:     fputs( zFlagOkay, option_usage_fp ); break;
+    case OPTPROC_SHORTOPT:  break;
+    case OPTPROC_LONGOPT:   fputs( zNoFlags,  option_usage_fp ); break;
+    case 0:                 fputs( zOptsOnly, option_usage_fp ); break;
+    }
+
+    if ((pOptions->fOptSet & OPTPROC_NUM_OPT) != 0) {
+        fputs( zNumberOpt, option_usage_fp );
+    }
+
+    if ((pOptions->fOptSet & OPTPROC_REORDER) != 0) {
+        fputs( zReorder, option_usage_fp );
+    }
+
+    if (pOptions->pzExplain != NULL)
+        fputs( pOptions->pzExplain, option_usage_fp );
+
+    /*
+     *  IF the user is asking for help (thus exiting with SUCCESS),
+     *  THEN see what additional information we can provide.
+     */
+    if (exitCode == EXIT_SUCCESS)
+        printProgramDetails( pOptions );
+
+    if (pOptions->pzBugAddr != NULL)
+        fprintf( option_usage_fp, zPlsSendBugs, pOptions->pzBugAddr );
+    fflush( option_usage_fp );
+
+    exit( exitCode );
+}
+
+
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ *
+ *   PER OPTION TYPE USAGE INFORMATION
+ */
+static void
+printExtendedUsage(
+    tOptions*     pOptions,
+    tOptDesc*     pOD,
+    arg_types_t*  pAT )
+{
+    /*
+     *  IF there are option conflicts or dependencies,
+     *  THEN print them here.
+     */
+    if (  (pOD->pOptMust != NULL)
+       || (pOD->pOptCant != NULL) ) {
+
+        fputs( zTabHyp, option_usage_fp );
+
+        /*
+         *  DEPENDENCIES:
+         */
+        if (pOD->pOptMust != NULL) {
+            const int* pOptNo = pOD->pOptMust;
+
+            fputs( zReqThese, option_usage_fp );
+            for (;;) {
+                fprintf( option_usage_fp, zTabout, pOptions->pOptDesc[
+                             *pOptNo ].pz_Name );
+                if (*++pOptNo == NO_EQUIVALENT)
+                    break;
+            }
+
+            if (pOD->pOptCant != NULL)
+                fputs( zTabHypAnd, option_usage_fp );
+        }
+
+        /*
+         *  CONFLICTS:
+         */
+        if (pOD->pOptCant != NULL) {
+            const int* pOptNo = pOD->pOptCant;
+
+            fputs( zProhib, option_usage_fp );
+            for (;;) {
+                fprintf( option_usage_fp, zTabout, pOptions->pOptDesc[
+                             *pOptNo ].pz_Name );
+                if (*++pOptNo == NO_EQUIVALENT)
+                    break;
+            }
+        }
+    }
+
+    /*
+     *  IF there is a disablement string
+     *  THEN print the disablement info
+     */
+    if (pOD->pz_DisableName != NULL )
+        fprintf( option_usage_fp, zDis, pOD->pz_DisableName );
+
+    /*
+     *  IF the numeric option has a special callback,
+     *  THEN call it, requesting the range or other special info
+     */
+    if (  (OPTST_GET_ARGTYPE(pOD->fOptState) == OPARG_TYPE_NUMERIC)
+       && (pOD->pOptProc != NULL)
+       && (pOD->pOptProc != optionNumericVal) ) {
+        (*(pOD->pOptProc))( pOptions, NULL );
+    }
+
+    /*
+     *  IF the option defaults to being enabled,
+     *  THEN print that out
+     */
+    if (pOD->fOptState & OPTST_INITENABLED)
+        fputs( zEnab, option_usage_fp );
+
+    /*
+     *  IF  the option is in an equivalence class
+     *        AND not the designated lead
+     *  THEN print equivalence and leave it at that.
+     */
+    if (  (pOD->optEquivIndex != NO_EQUIVALENT)
+       && (pOD->optEquivIndex != pOD->optActualIndex )  )  {
+        fprintf( option_usage_fp, zAlt,
+                 pOptions->pOptDesc[ pOD->optEquivIndex ].pz_Name );
+        return;
+    }
+
+    /*
+     *  IF this particular option can NOT be preset
+     *    AND some form of presetting IS allowed,
+     *  THEN advise that this option may not be preset.
+     */
+    if (  ((pOD->fOptState & OPTST_NO_INIT) != 0)
+       && (  (pOptions->papzHomeList != NULL)
+          || (pOptions->pzPROGNAME != NULL)
+       )  )
+
+        fputs( zNoPreset, option_usage_fp );
+
+    /*
+     *  Print the appearance requirements.
+     */
+    if (OPTST_GET_ARGTYPE(pOD->fOptState) == OPARG_TYPE_MEMBERSHIP)
+        fputs( zMembers, option_usage_fp );
+
+    else switch (pOD->optMinCt) {
+    case 1:
+    case 0:
+        switch (pOD->optMaxCt) {
+        case 0:       fputs( zPreset, option_usage_fp ); break;
+        case NOLIMIT: fputs( zNoLim, option_usage_fp );  break;
+        case 1:       break;
+            /*
+             * IF the max is more than one but limited, print "UP TO" message
+             */
+        default:      fprintf( option_usage_fp, zUpTo, pOD->optMaxCt );  break;
+        }
+        break;
+
+    default:
+        /*
+         *  More than one is required.  Print the range.
+         */
+        fprintf( option_usage_fp, zMust, pOD->optMinCt, pOD->optMaxCt );
+    }
+
+    if (  NAMED_OPTS( pOptions )
+       && (pOptions->specOptIdx.default_opt == pOD->optIndex))
+        fputs( zDefaultOpt, option_usage_fp );
+}
+
+
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ *
+ *   Figure out where all the initialization files might live.
+ *   This requires translating some environment variables and
+ *   testing to see if a name is a directory or a file.  It's
+ *   squishy, but important to tell users how to find these files.
+ */
+static void
+printInitList(
+    tCC**    papz,
+    ag_bool* pInitIntro,
+    tCC*     pzRc,
+    tCC*     pzPN )
+{
+    char zPath[ MAXPATHLEN+1 ];
+
+    if (papz == NULL)
+        return;
+
+    fputs( zPresetIntro, option_usage_fp );
+    *pInitIntro = AG_FALSE;
+
+    for (;;) {
+        const char* pzPath = *(papz++);
+
+        if (pzPath == NULL)
+            break;
+
+        if (optionMakePath( zPath, sizeof( zPath ), pzPath, pzPN ))
+            pzPath = zPath;
+
+        /*
+         *  Print the name of the "homerc" file.  If the "rcfile" name is
+         *  not empty, we may or may not print that, too...
+         */
+        fprintf( option_usage_fp, zPathFmt, pzPath );
+        if (*pzRc != NUL) {
+            struct stat sb;
+
+            /*
+             *  IF the "homerc" file is a directory,
+             *  then append the "rcfile" name.
+             */
+            if (  (stat( pzPath, &sb ) == 0)
+              &&  S_ISDIR( sb.st_mode ) ) {
+                fputc( '/', option_usage_fp );
+                fputs( pzRc, option_usage_fp );
+            }
+        }
+
+        fputc( '\n', option_usage_fp );
+    }
+}
+
+
+/*
+ *  Print the usage information for a single option.
+ */
+static void
+printOneUsage(
+    tOptions*     pOptions,
+    tOptDesc*     pOD,
+    arg_types_t*  pAT )
+{
+    /*
+     *  Flag prefix: IF no flags at all, then omit it.  If not printable
+     *  (not allowed for this option), then blank, else print it.
+     *  Follow it with a comma if we are doing GNU usage and long
+     *  opts are to be printed too.
+     */
+    if ((pOptions->fOptSet & OPTPROC_SHORTOPT) == 0)
+        fputs( pAT->pzSpc, option_usage_fp );
+    else if (! isgraph( pOD->optValue)) {
+        if (  (pOptions->fOptSet & (OPTPROC_GNUUSAGE|OPTPROC_LONGOPT))
+           == (OPTPROC_GNUUSAGE|OPTPROC_LONGOPT))
+            fputc( ' ', option_usage_fp );
+        fputs( pAT->pzNoF, option_usage_fp );
+    } else {
+        fprintf( option_usage_fp, "   -%c", pOD->optValue );
+        if (  (pOptions->fOptSet & (OPTPROC_GNUUSAGE|OPTPROC_LONGOPT))
+           == (OPTPROC_GNUUSAGE|OPTPROC_LONGOPT))
+            fputs( ", ", option_usage_fp );
+    }
+
+    {
+        char  z[ 80 ];
+        tCC*  pzArgType;
+        /*
+         *  Determine the argument type string first on its usage, then,
+         *  when the option argument is required, base the type string on the
+         *  argument type.
+         */
+        if (OPTST_GET_ARGTYPE(pOD->fOptState) == OPARG_TYPE_NONE) {
+            pzArgType = pAT->pzNo;
+
+        } else if (pOD->fOptState & OPTST_ARG_OPTIONAL) {
+            pzArgType = pAT->pzOpt;
+
+        } else switch (OPTST_GET_ARGTYPE(pOD->fOptState)) {
+        case OPARG_TYPE_ENUMERATION: pzArgType = pAT->pzKey;  break;
+        case OPARG_TYPE_MEMBERSHIP:  pzArgType = pAT->pzKeyL; break;
+        case OPARG_TYPE_BOOLEAN:     pzArgType = pAT->pzBool; break;
+        case OPARG_TYPE_NUMERIC:     pzArgType = pAT->pzNum;  break;
+        case OPARG_TYPE_HIERARCHY:   pzArgType = pAT->pzNest; break;
+        case OPARG_TYPE_STRING:      pzArgType = pAT->pzStr;  break;
+        default:                     goto bogus_desc;         break;
+        }
+
+        snprintf( z, sizeof(z), pAT->pzOptFmt, pzArgType, pOD->pz_Name,
+                  (pOD->optMinCt != 0) ? pAT->pzReq : pAT->pzOpt );
+
+        fprintf( option_usage_fp, zOptFmtLine, z, pOD->pzText );
+
+        switch (OPTST_GET_ARGTYPE(pOD->fOptState)) {
+        case OPARG_TYPE_ENUMERATION:
+        case OPARG_TYPE_MEMBERSHIP:
+            displayEnum = (pOD->pOptProc != NULL) ? AG_TRUE : displayEnum;
+        }
+    }
+    return;
+
+ bogus_desc:
+    fprintf( stderr, zInvalOptDesc, pOD->pz_Name );
+    exit( EXIT_FAILURE );
+}
+
+
+/*
+ *  Print out the usage information for just the options.
+ */
+static void
+printOptionUsage(
+    tOptions* pOpts,
+    int       ex_code,
+    tCC*      pOptTitle )
+{
+    int        ct     = pOpts->optCt;
+    int        optNo  = 0;
+    tOptDesc*  pOD    = pOpts->pOptDesc;
+    int        docCt  = 0;
+
+    do  {
+        if ((pOD->fOptState & OPTST_OMITTED) != 0)
+            continue;
+
+        if ((pOD->fOptState & OPTST_DOCUMENT) != 0) {
+            if (ex_code == EXIT_SUCCESS) {
+                fprintf(option_usage_fp, argTypes.pzBrk, pOD->pzText,
+                        pOptTitle);
+                docCt++;
+            }
+
+            continue;
+        }
+
+        /*
+         *  IF       this is the first auto-opt maintained option
+         *    *AND*  we are doing a full help
+         *    *AND*  there are documentation options
+         *    *AND*  the last one was not a doc option,
+         *  THEN document that the remaining options are not user opts
+         */
+        if (  (pOpts->presetOptCt == optNo)
+              && (ex_code == EXIT_SUCCESS)
+              && (docCt > 0)
+              && ((pOD[-1].fOptState & OPTST_DOCUMENT) == 0) )
+            fprintf( option_usage_fp, argTypes.pzBrk, zAuto, pOptTitle );
+
+        printOneUsage( pOpts, pOD, &argTypes );
+
+        /*
+         *  IF we were invoked because of the --help option,
+         *  THEN print all the extra info
+         */
+        if (ex_code == EXIT_SUCCESS)
+            printExtendedUsage( pOpts, pOD, &argTypes );
+
+    }  while (pOD++, optNo++, (--ct > 0));
+
+    fputc( '\n', option_usage_fp );
+}
+
+
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ *
+ *   PROGRAM DETAILS
+ */
+static void
+printProgramDetails( tOptions* pOptions )
+{
+    ag_bool  initIntro = AG_TRUE;
+
+    /*
+     *  Display all the places we look for config files
+     */
+    printInitList( pOptions->papzHomeList, &initIntro,
+                   pOptions->pzRcName, pOptions->pzProgPath );
+
+    /*
+     *  Let the user know about environment variable settings
+     */
+    if ((pOptions->fOptSet & OPTPROC_ENVIRON) != 0) {
+        if (initIntro)
+            fputs( zPresetIntro, option_usage_fp );
+
+        fprintf( option_usage_fp, zExamineFmt, pOptions->pzPROGNAME );
+    }
+
+    /*
+     *  IF we found an enumeration,
+     *  THEN hunt for it again.  Call the handler proc with a NULL
+     *       option struct pointer.  That tells it to display the keywords.
+     */
+    if (displayEnum) {
+        int        ct     = pOptions->optCt;
+        int        optNo  = 0;
+        tOptDesc*  pOD    = pOptions->pOptDesc;
+
+        fputc( '\n', option_usage_fp );
+        fflush( option_usage_fp );
+        do  {
+            switch (OPTST_GET_ARGTYPE(pOD->fOptState)) {
+            case OPARG_TYPE_ENUMERATION:
+            case OPARG_TYPE_MEMBERSHIP:
+                (*(pOD->pOptProc))( NULL, pOD );
+            }
+        }  while (pOD++, optNo++, (--ct > 0));
+    }
+
+    /*
+     *  If there is a detail string, now is the time for that.
+     */
+    if (pOptions->pzDetail != NULL)
+        fputs( pOptions->pzDetail, option_usage_fp );
+}
+
+
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ *
+ *   OPTION LINE FORMATTING SETUP
+ *
+ *  The "OptFmt" formats receive three arguments:
+ *  1.  the type of the option's argument
+ *  2.  the long name of the option
+ *  3.  "YES" or "no ", depending on whether or not the option must appear
+ *      on the command line.
+ *  These formats are used immediately after the option flag (if used) has
+ *  been printed.
+ *
+ *  Set up the formatting for GNU-style output
+ */
+static int
+setGnuOptFmts( tOptions* pOpts, tCC** ppT )
+{
+    int  flen = 22;
+    *ppT = zNoRq_ShrtTtl;
+
+    argTypes.pzStr  = zGnuStrArg;
+    argTypes.pzReq  = zOneSpace;
+    argTypes.pzNum  = zGnuNumArg;
+    argTypes.pzKey  = zGnuKeyArg;
+    argTypes.pzKeyL = zGnuKeyLArg;
+    argTypes.pzBool = zGnuBoolArg;
+    argTypes.pzNest = zGnuNestArg;
+    argTypes.pzOpt  = zGnuOptArg;
+    argTypes.pzNo   = zOneSpace;
+    argTypes.pzBrk  = zGnuBreak;
+    argTypes.pzNoF  = zSixSpaces;
+    argTypes.pzSpc  = zThreeSpaces;
+
+    switch (pOpts->fOptSet & OPTPROC_L_N_S) {
+    case OPTPROC_L_N_S:    argTypes.pzOptFmt = zGnuOptFmt;     break;
+    case OPTPROC_LONGOPT:  argTypes.pzOptFmt = zGnuOptFmt;     break;
+    case 0:                argTypes.pzOptFmt = zGnuOptFmt + 2; break;
+    case OPTPROC_SHORTOPT:
+        argTypes.pzOptFmt = zShrtGnuOptFmt;
+        zGnuStrArg[0] = zGnuNumArg[0] = zGnuKeyArg[0] = zGnuBoolArg[0] = ' ';
+        argTypes.pzOpt = " [arg]";
+        flen = 8;
+        break;
+    }
+
+    return flen;
+}
+
+
+/*
+ *  Standard (AutoOpts normal) option line formatting
+ */
+static int
+setStdOptFmts( tOptions* pOpts, tCC** ppT )
+{
+    int  flen = 0;
+
+    argTypes.pzStr  = zStdStrArg;
+    argTypes.pzReq  = zStdReqArg;
+    argTypes.pzNum  = zStdNumArg;
+    argTypes.pzKey  = zStdKeyArg;
+    argTypes.pzKeyL = zStdKeyLArg;
+    argTypes.pzBool = zStdBoolArg;
+    argTypes.pzNest = zStdNestArg;
+    argTypes.pzOpt  = zStdOptArg;
+    argTypes.pzNo   = zStdNoArg;
+    argTypes.pzBrk  = zStdBreak;
+    argTypes.pzNoF  = zFiveSpaces;
+    argTypes.pzSpc  = zTwoSpaces;
+
+    switch (pOpts->fOptSet & (OPTPROC_NO_REQ_OPT | OPTPROC_SHORTOPT)) {
+    case (OPTPROC_NO_REQ_OPT | OPTPROC_SHORTOPT):
+        *ppT = zNoRq_ShrtTtl;
+        argTypes.pzOptFmt = zNrmOptFmt;
+        flen = 19;
+        break;
+
+    case OPTPROC_NO_REQ_OPT:
+        *ppT = zNoRq_NoShrtTtl;
+        argTypes.pzOptFmt = zNrmOptFmt;
+        flen = 19;
+        break;
+
+    case OPTPROC_SHORTOPT:
+        *ppT = zReq_ShrtTtl;
+        argTypes.pzOptFmt = zReqOptFmt;
+        flen = 24;
+        break;
+
+    case 0:
+        *ppT = zReq_NoShrtTtl;
+        argTypes.pzOptFmt = zReqOptFmt;
+        flen = 24;
+    }
+
+    return flen;
+}
+
+
+/*:
+ * Local Variables:
+ * mode: C
+ * c-file-style: "stroustrup"
+ * tab-width: 4
+ * indent-tabs-mode: nil
+ * End:
+ * end of autoopts/usage.c */
diff --git a/sntp/libopts/version.c b/sntp/libopts/version.c
new file mode 100644 (file)
index 0000000..ede9173
--- /dev/null
@@ -0,0 +1,181 @@
+
+/*  $Id: version.c,v 4.7 2006/03/25 19:24:57 bkorb Exp $
+ * Time-stamp:      "2005-12-13 10:29:09 bkorb"
+ *
+ *  This module implements the default usage procedure for
+ *  Automated Options.  It may be overridden, of course.
+ */
+
+static const char zAOV[] =
+    "Automated Options version %s, copyright (c) 1999-2006 Bruce Korb\n";
+
+/*  Automated Options is free software.
+ *  You may redistribute it and/or modify it under the terms of the
+ *  GNU General Public License, as published by the Free Software
+ *  Foundation; either version 2, or (at your option) any later version.
+ *
+ *  Automated Options is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with Automated Options.  See the file "COPYING".  If not,
+ *  write to:  The Free Software Foundation, Inc.,
+ *             51 Franklin Street, Fifth Floor,
+ *             Boston, MA  02110-1301, USA.
+ *
+ * As a special exception, Bruce Korb gives permission for additional
+ * uses of the text contained in his release of AutoOpts.
+ *
+ * The exception is that, if you link the AutoOpts library with other
+ * files to produce an executable, this does not by itself cause the
+ * resulting executable to be covered by the GNU General Public License.
+ * Your use of that executable is in no way restricted on account of
+ * linking the AutoOpts library code into it.
+ *
+ * This exception does not however invalidate any other reasons why
+ * the executable file might be covered by the GNU General Public License.
+ *
+ * This exception applies only to the code released by Bruce Korb under
+ * the name AutoOpts.  If you copy code from other sources under the
+ * General Public License into a copy of AutoOpts, as the General Public
+ * License permits, the exception does not apply to the code that you add
+ * in this way.  To avoid misleading anyone as to the status of such
+ * modified files, you must delete this exception notice from them.
+ *
+ * If you write modifications of your own for AutoOpts, it is your choice
+ * whether to permit this exception to apply to your modifications.
+ * If you do not wish that, delete this exception notice.
+ */
+
+/* = = = START-STATIC-FORWARD = = = */
+/* static forward declarations maintained by :mkfwd */
+static void
+printVersion( tOptions* pOpts, tOptDesc* pOD, FILE* fp );
+/* = = = END-STATIC-FORWARD = = = */
+
+/*=export_func  optionVersion
+ *
+ * what:     return the compiled AutoOpts version number
+ * ret_type: const char*
+ * ret_desc: the version string in constant memory
+ * doc:
+ *  Returns the full version string compiled into the library.
+ *  The returned string cannot be modified.
+=*/
+const char*
+optionVersion( void )
+{
+    static const char zVersion[] =
+        STR( AO_CURRENT.AO_REVISION );
+
+    return zVersion;
+}
+
+
+static void
+printVersion( tOptions* pOpts, tOptDesc* pOD, FILE* fp )
+{
+    char swCh;
+
+    if (pOD->pzLastArg == NULL)
+         swCh = 'v';
+    else swCh = pOD->pzLastArg[0];
+
+    if (pOpts->pzFullVersion != NULL) {
+        fputs( pOpts->pzFullVersion, fp );
+        fputc( '\n', fp );
+
+    } else {
+        const char *pz = pOpts->pzUsageTitle;
+        do { fputc( *pz, fp ); } while (*(pz++) != '\n');
+    }
+
+    switch (swCh) {
+    case NUL:
+    case 'v':
+    case 'V':
+        break;
+
+    case 'c':
+    case 'C':
+        if (pOpts->pzCopyright != NULL) {
+            fputs( pOpts->pzCopyright, fp );
+            fputc( '\n', fp );
+        }
+        fprintf( fp, zAOV, optionVersion() );
+        if (pOpts->pzBugAddr != NULL)
+            fprintf( fp, zPlsSendBugs, pOpts->pzBugAddr );
+        break;
+
+    case 'n':
+    case 'N':
+        if (pOpts->pzCopyright != NULL) {
+            fputs( pOpts->pzCopyright, fp );
+            fputc( '\n', fp );
+            fputc( '\n', fp );
+        }
+
+        if (pOpts->pzCopyNotice != NULL) {
+            fputs( pOpts->pzCopyNotice, fp );
+            fputc( '\n', fp );
+        }
+
+        fprintf( fp, zAOV, optionVersion() );
+        if (pOpts->pzBugAddr != NULL)
+            fprintf( fp, zPlsSendBugs, pOpts->pzBugAddr );
+        break;
+
+    default:
+        fprintf( stderr, zBadVerArg, swCh );
+        exit( EXIT_FAILURE );
+    }
+
+    exit( EXIT_SUCCESS );
+}
+
+/*=export_func  optionPrintVersion
+ * private:
+ *
+ * what:  Print the program version
+ * arg:   + tOptions* + pOpts    + program options descriptor +
+ * arg:   + tOptDesc* + pOptDesc + the descriptor for this arg +
+ *
+ * doc:
+ *  This routine will print the version to stdout.
+=*/
+void
+optionPrintVersion( pOpts, pOD )
+    tOptions*  pOpts;
+    tOptDesc*  pOD;
+{
+    printVersion( pOpts, pOD, stdout );
+}
+
+/*=export_func  optionVersionStderr
+ * private:
+ *
+ * what:  Print the program version to stderr
+ * arg:   + tOptions* + pOpts    + program options descriptor +
+ * arg:   + tOptDesc* + pOptDesc + the descriptor for this arg +
+ *
+ * doc:
+ *  This routine will print the version to stderr.
+=*/
+void
+optionVersionStderr( pOpts, pOD )
+    tOptions*  pOpts;
+    tOptDesc*  pOD;
+{
+    printVersion( pOpts, pOD, stderr );
+}
+
+/*
+ * Local Variables:
+ * mode: C
+ * c-file-style: "stroustrup"
+ * tab-width: 4
+ * indent-tabs-mode: nil
+ * End:
+ * end of autoopts/version.c */
diff --git a/sntp/sntp-opts.c b/sntp/sntp-opts.c
new file mode 100644 (file)
index 0000000..5ea1b83
--- /dev/null
@@ -0,0 +1,742 @@
+/*   -*- buffer-read-only: t -*- vi: set ro:
+ *  
+ *  DO NOT EDIT THIS FILE   (sntp-opts.c)
+ *  
+ *  It has been AutoGen-ed  Tuesday June 27, 2006 at 10:16:53 PM EDT
+ *  From the definitions    sntp-opts.def
+ *  and the template file   options
+ */
+
+#define OPTION_CODE_COMPILE 1
+#include "sntp-opts.h"
+
+#ifdef  __cplusplus
+extern "C" {
+#endif
+tSCC zCopyright[] =
+       "sntp copyright (c) 1970-2006 ntp.org, all rights reserved";
+tSCC zCopyrightNotice[] =
+       
+/* extracted from sntp-opts.def near line 10 */
+"See the sntp/Copyright file";
+extern tUsageProc optionUsage;
+
+#ifndef NULL
+#  define NULL 0
+#endif
+#ifndef EXIT_SUCCESS
+#  define  EXIT_SUCCESS 0
+#endif
+#ifndef EXIT_FAILURE
+#  define  EXIT_FAILURE 1
+#endif
+/*
+ *  Ipv4 option description:
+ */
+tSCC    zIpv4Text[] =
+        "Force IPv4 DNS name resolution";
+tSCC    zIpv4_NAME[]               = "IPV4";
+tSCC    zIpv4_Name[]               = "ipv4";
+#define IPV4_FLAGS       (OPTST_DISABLED)
+
+/*
+ *  Ipv6 option description:
+ */
+tSCC    zIpv6Text[] =
+        "Force IPv6 DNS name resolution";
+tSCC    zIpv6_NAME[]               = "IPV6";
+tSCC    zIpv6_Name[]               = "ipv6";
+#define IPV6_FLAGS       (OPTST_DISABLED)
+
+/*
+ *  Normalverbose option description with
+ *  "Must also have options" and "Incompatible options":
+ */
+tSCC    zNormalverboseText[] =
+        "Slightly verbose";
+tSCC    zNormalverbose_NAME[]      = "NORMALVERBOSE";
+tSCC    zNormalverbose_Name[]      = "normalverbose";
+static const int
+    aNormalverboseCantList[] = {
+    INDEX_OPT_EXTRAVERBOSE,
+    INDEX_OPT_MEGAVERBOSE, NO_EQUIVALENT };
+#define NORMALVERBOSE_FLAGS       (OPTST_DISABLED)
+
+/*
+ *  Extraverbose option description with
+ *  "Must also have options" and "Incompatible options":
+ */
+tSCC    zExtraverboseText[] =
+        "Extra verbose";
+tSCC    zExtraverbose_NAME[]       = "EXTRAVERBOSE";
+tSCC    zExtraverbose_Name[]       = "extraverbose";
+static const int
+    aExtraverboseCantList[] = {
+    INDEX_OPT_NORMALVERBOSE,
+    INDEX_OPT_MEGAVERBOSE, NO_EQUIVALENT };
+#define EXTRAVERBOSE_FLAGS       (OPTST_DISABLED)
+
+/*
+ *  Megaverbose option description with
+ *  "Must also have options" and "Incompatible options":
+ */
+tSCC    zMegaverboseText[] =
+        "Mega verbose";
+tSCC    zMegaverbose_NAME[]        = "MEGAVERBOSE";
+tSCC    zMegaverbose_Name[]        = "megaverbose";
+static const int
+    aMegaverboseCantList[] = {
+    INDEX_OPT_NORMALVERBOSE,
+    INDEX_OPT_EXTRAVERBOSE, NO_EQUIVALENT };
+#define MEGAVERBOSE_FLAGS       (OPTST_DISABLED)
+
+/*
+ *  Settimeofday option description with
+ *  "Must also have options" and "Incompatible options":
+ */
+tSCC    zSettimeofdayText[] =
+        "Set (step) the time with settimeofday()";
+tSCC    zSettimeofday_NAME[]       = "SETTIMEOFDAY";
+tSCC    zSettimeofday_Name[]       = "settimeofday";
+static const int
+    aSettimeofdayCantList[] = {
+    INDEX_OPT_ADJTIME, NO_EQUIVALENT };
+#define SETTIMEOFDAY_FLAGS       (OPTST_DISABLED)
+
+/*
+ *  Adjtime option description with
+ *  "Must also have options" and "Incompatible options":
+ */
+tSCC    zAdjtimeText[] =
+        "Set (slew) the time with adjtime()";
+tSCC    zAdjtime_NAME[]            = "ADJTIME";
+tSCC    zAdjtime_Name[]            = "adjtime";
+static const int
+    aAdjtimeCantList[] = {
+    INDEX_OPT_SETTIMEOFDAY, NO_EQUIVALENT };
+#define ADJTIME_FLAGS       (OPTST_DISABLED)
+
+/*
+ *  Help/More_Help/Version option descriptions:
+ */
+tSCC zHelpText[]       = "Display usage information and exit";
+tSCC zHelp_Name[]      = "help";
+
+tSCC zMore_HelpText[]  = "Extended usage information passed thru pager";
+tSCC zMore_Help_Name[] = "more-help";
+
+tSCC zVersionText[]    = "Output version information and exit";
+tSCC zVersion_Name[]   = "version";
+
+/*
+ *  Save/Load_Opts option description:
+ */
+tSCC zSave_OptsText[]     = "Save the option state to a config file";
+tSCC zSave_Opts_Name[]    = "save-opts";
+
+tSCC zLoad_OptsText[]     = "Load options from a config file";
+tSCC zLoad_Opts_NAME[]    = "LOAD_OPTS";
+
+tSCC zNotLoad_Opts_Name[] = "no-load-opts";
+tSCC zNotLoad_Opts_Pfx[]  = "no";
+#define zLoad_Opts_Name   (zNotLoad_Opts_Name + 3)
+/*
+ *  Declare option callback procedures
+ */
+/* extracted from optmain.tpl near line 586 */
+
+#if defined(TEST_SNTP_OPTS)
+/*
+ *  Under test, omit argument processing, or call optionStackArg,
+ *  if multiple copies are allowed.
+ */
+extern tOptProc
+    optionPagedUsage, optionVersionStderr;
+static tOptProc
+    doUsageOpt;
+
+#else /* NOT defined TEST_SNTP_OPTS */
+/*
+ *  When not under test, there are different procs to use
+ */
+extern tOptProc
+    optionPagedUsage, optionPrintVersion;
+static tOptProc
+    doUsageOpt;
+#endif /* defined(TEST_SNTP_OPTS) */
+#ifdef TEST_SNTP_OPTS
+# define DOVERPROC optionVersionStderr
+#else
+# define DOVERPROC optionPrintVersion
+#endif /* TEST_SNTP_OPTS */
+
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ *
+ *  Define the Sntp Option Descriptions.
+ */
+static tOptDesc optDesc[ OPTION_CT ] = {
+  {  /* entry idx, value */ 0, VALUE_OPT_IPV4,
+     /* equiv idx, value */ NO_EQUIVALENT, 0,
+     /* equivalenced to  */ NO_EQUIVALENT,
+     /* min, max, act ct */ 0, 1, 0,
+     /* opt state flags  */ IPV4_FLAGS, 0,
+     /* last opt argumnt */ NULL,
+     /* arg list/cookie  */ NULL,
+     /* must/cannot opts */ NULL, NULL,
+     /* option proc      */ NULL,
+     /* desc, NAME, name */ zIpv4Text, zIpv4_NAME, zIpv4_Name,
+     /* disablement strs */ NULL, NULL },
+
+  {  /* entry idx, value */ 1, VALUE_OPT_IPV6,
+     /* equiv idx, value */ NOLIMIT, NOLIMIT,
+     /* equivalenced to  */ INDEX_OPT_IPV4,
+     /* min, max, act ct */ 0, 1, 0,
+     /* opt state flags  */ IPV6_FLAGS, 0,
+     /* last opt argumnt */ NULL,
+     /* arg list/cookie  */ NULL,
+     /* must/cannot opts */ NULL, NULL,
+     /* option proc      */ NULL,
+     /* desc, NAME, name */ zIpv6Text, zIpv6_NAME, zIpv6_Name,
+     /* disablement strs */ NULL, NULL },
+
+  {  /* entry idx, value */ 2, VALUE_OPT_NORMALVERBOSE,
+     /* equiv idx, value */ 2, VALUE_OPT_NORMALVERBOSE,
+     /* equivalenced to  */ NO_EQUIVALENT,
+     /* min, max, act ct */ 0, 1, 0,
+     /* opt state flags  */ NORMALVERBOSE_FLAGS, 0,
+     /* last opt argumnt */ NULL,
+     /* arg list/cookie  */ NULL,
+     /* must/cannot opts */ NULL, aNormalverboseCantList,
+     /* option proc      */ NULL,
+     /* desc, NAME, name */ zNormalverboseText, zNormalverbose_NAME, zNormalverbose_Name,
+     /* disablement strs */ NULL, NULL },
+
+  {  /* entry idx, value */ 3, VALUE_OPT_EXTRAVERBOSE,
+     /* equiv idx, value */ 3, VALUE_OPT_EXTRAVERBOSE,
+     /* equivalenced to  */ NO_EQUIVALENT,
+     /* min, max, act ct */ 0, 1, 0,
+     /* opt state flags  */ EXTRAVERBOSE_FLAGS, 0,
+     /* last opt argumnt */ NULL,
+     /* arg list/cookie  */ NULL,
+     /* must/cannot opts */ NULL, aExtraverboseCantList,
+     /* option proc      */ NULL,
+     /* desc, NAME, name */ zExtraverboseText, zExtraverbose_NAME, zExtraverbose_Name,
+     /* disablement strs */ NULL, NULL },
+
+  {  /* entry idx, value */ 4, VALUE_OPT_MEGAVERBOSE,
+     /* equiv idx, value */ 4, VALUE_OPT_MEGAVERBOSE,
+     /* equivalenced to  */ NO_EQUIVALENT,
+     /* min, max, act ct */ 0, 1, 0,
+     /* opt state flags  */ MEGAVERBOSE_FLAGS, 0,
+     /* last opt argumnt */ NULL,
+     /* arg list/cookie  */ NULL,
+     /* must/cannot opts */ NULL, aMegaverboseCantList,
+     /* option proc      */ NULL,
+     /* desc, NAME, name */ zMegaverboseText, zMegaverbose_NAME, zMegaverbose_Name,
+     /* disablement strs */ NULL, NULL },
+
+  {  /* entry idx, value */ 5, VALUE_OPT_SETTIMEOFDAY,
+     /* equiv idx, value */ 5, VALUE_OPT_SETTIMEOFDAY,
+     /* equivalenced to  */ NO_EQUIVALENT,
+     /* min, max, act ct */ 0, 1, 0,
+     /* opt state flags  */ SETTIMEOFDAY_FLAGS, 0,
+     /* last opt argumnt */ NULL,
+     /* arg list/cookie  */ NULL,
+     /* must/cannot opts */ NULL, aSettimeofdayCantList,
+     /* option proc      */ NULL,
+     /* desc, NAME, name */ zSettimeofdayText, zSettimeofday_NAME, zSettimeofday_Name,
+     /* disablement strs */ NULL, NULL },
+
+  {  /* entry idx, value */ 6, VALUE_OPT_ADJTIME,
+     /* equiv idx, value */ 6, VALUE_OPT_ADJTIME,
+     /* equivalenced to  */ NO_EQUIVALENT,
+     /* min, max, act ct */ 0, 1, 0,
+     /* opt state flags  */ ADJTIME_FLAGS, 0,
+     /* last opt argumnt */ NULL,
+     /* arg list/cookie  */ NULL,
+     /* must/cannot opts */ NULL, aAdjtimeCantList,
+     /* option proc      */ NULL,
+     /* desc, NAME, name */ zAdjtimeText, zAdjtime_NAME, zAdjtime_Name,
+     /* disablement strs */ NULL, NULL },
+
+  {  /* entry idx, value */ INDEX_OPT_VERSION, VALUE_OPT_VERSION,
+     /* equiv idx value  */ NO_EQUIVALENT, 0,
+     /* equivalenced to  */ NO_EQUIVALENT,
+     /* min, max, act ct */ 0, 1, 0,
+     /* opt state flags  */ OPTST_SET_ARGTYPE(OPARG_TYPE_STRING)
+                          | OPTST_ARG_OPTIONAL, 0,
+     /* last opt argumnt */ NULL,
+     /* arg list/cookie  */ NULL,
+     /* must/cannot opts */ NULL, NULL,
+     /* option proc      */ DOVERPROC,
+     /* desc, NAME, name */ zVersionText, NULL, zVersion_Name,
+     /* disablement strs */ NULL, NULL },
+
+  {  /* entry idx, value */ INDEX_OPT_HELP, VALUE_OPT_HELP,
+     /* equiv idx value  */ NO_EQUIVALENT, 0,
+     /* equivalenced to  */ NO_EQUIVALENT,
+     /* min, max, act ct */ 0, 1, 0,
+     /* opt state flags  */ OPTST_IMM, 0,
+     /* last opt argumnt */ NULL,
+     /* arg list/cookie  */ NULL,
+     /* must/cannot opts */ NULL, NULL,
+     /* option proc      */ doUsageOpt,
+     /* desc, NAME, name */ zHelpText, NULL, zHelp_Name,
+     /* disablement strs */ NULL, NULL },
+
+  {  /* entry idx, value */ INDEX_OPT_MORE_HELP, VALUE_OPT_MORE_HELP,
+     /* equiv idx value  */ NO_EQUIVALENT, 0,
+     /* equivalenced to  */ NO_EQUIVALENT,
+     /* min, max, act ct */ 0, 1, 0,
+     /* opt state flags  */ OPTST_IMM, 0,
+     /* last opt argumnt */ NULL,
+     /* arg list/cookie  */ NULL,
+     /* must/cannot opts */ NULL,  NULL,
+     /* option proc      */ optionPagedUsage,
+     /* desc, NAME, name */ zMore_HelpText, NULL, zMore_Help_Name,
+     /* disablement strs */ NULL, NULL },
+
+  {  /* entry idx, value */ INDEX_OPT_SAVE_OPTS, VALUE_OPT_SAVE_OPTS,
+     /* equiv idx value  */ NO_EQUIVALENT, 0,
+     /* equivalenced to  */ NO_EQUIVALENT,
+     /* min, max, act ct */ 0, 1, 0,
+     /* opt state flags  */ OPTST_SET_ARGTYPE(OPARG_TYPE_STRING)
+                          | OPTST_ARG_OPTIONAL, 0,
+     /* last opt argumnt */ NULL,
+     /* arg list/cookie  */ NULL,
+     /* must/cannot opts */ NULL,  NULL,
+     /* option proc      */ NULL,
+     /* desc, NAME, name */ zSave_OptsText, NULL, zSave_Opts_Name,
+     /* disablement strs */ NULL, NULL },
+
+  {  /* entry idx, value */ INDEX_OPT_LOAD_OPTS, VALUE_OPT_LOAD_OPTS,
+     /* equiv idx value  */ NO_EQUIVALENT, 0,
+     /* equivalenced to  */ NO_EQUIVALENT,
+     /* min, max, act ct */ 0, NOLIMIT, 0,
+     /* opt state flags  */ OPTST_DISABLE_IMM | \
+                       OPTST_SET_ARGTYPE(OPARG_TYPE_STRING), 0,
+     /* last opt argumnt */ NULL,
+     /* arg list/cookie  */ NULL,
+     /* must/cannot opts */ NULL, NULL,
+     /* option proc      */ optionLoadOpt,
+     /* desc, NAME, name */ zLoad_OptsText, zLoad_Opts_NAME, zLoad_Opts_Name,
+     /* disablement strs */ zNotLoad_Opts_Name, zNotLoad_Opts_Pfx }
+};
+
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ *
+ *  Define the Sntp Option Environment
+ */
+tSCC   zPROGNAME[]   = "SNTP";
+tSCC   zUsageTitle[] =
+"sntp - standard SNTP program - Ver. 4.2.3p12\n\
+USAGE:  %s [ -<flag> | --<name> ]...\n";
+tSCC   zRcName[]     = ".ntprc";
+tSCC*  apzHomeList[] = {
+       "$HOME",
+       ".",
+       NULL };
+
+tSCC   zBugsAddr[]    = "http://bugs.ntp.isc.org, bugs@ntp.org";
+#define zExplain NULL
+tSCC    zDetail[]     = "\n\
+.I sntp\n\
+can be used as a SNTP client to query a NTP or SNTP server and either display\n\
+the time or set the local system's time (given suitable privilege).  It can be\n\
+run as an interactive command, in a\n\
+.I cron\n\
+job or as a daemon.  It can be run as a daemon to provide a SNTP server for\n\
+other clients.  NTP is the Network Time Protocol (RFC 1305) and SNTP is the\n\
+Simple Network Time Protocol (RFC 2030, which supersedes RFC 1769).\n\
+.SS Options\n\
+.PP\n\
+.I sntp\n\
+recognizes the following options:\n\
+.TP\n\
+.B \\-v\n\
+indicates that diagnostic messages for non-fatal errors and a limited amount of\n\
+tracing should be written to standard error.  Fatal ones always produce a\n\
+diagnostic.  This option should be set when there is a suspected problem with\n\
+the server, network or the source.\n\
+.TP\n\
+.B \\-V\n\
+requests more and less comprehensible output, mainly for investigating problems\n\
+with apparently inconsistent timestamps.  This option should be set when the\n\
+program fails with a message indicating that is the trouble.\n\
+.TP\n\
+.B \\-W\n\
+requests very verbose debugging output, and will interfere with the timing\n\
+when writing to the terminal (because of line buffered output from C).  Note\n\
+that the times produced by this are the corrections needed, and not the error\n\
+in the local clock.  This option should be set only when debugging the source.\n\
+.TP\n\
+.B \\-q\n\
+indicates that it should query a daemon save file being maintained by it.\n\
+This needs no privilege and will change neither the save file nor the clock.\n\
+.PP\n\
+The default is that it should behave as a client, and the following options\n\
+are then relevant:\n\
+.TP\n\
+.B \\-r\n\
+indicates that the system clock should be reset by\n\
+.IR settimeofday .\n\
+Naturally, this will work only if the user has enough privilege.\n\
+.TP\n\
+.B \\-a\n\
+indicates that the system clock should be reset by\n\
+.IR adjtime .\n\
+Naturally, this will work only if the user has enough privilege.\n\
+.PP\n\
+The default is to write the estimated correct local date and time (i.e. not\n\
+UTC) to the standard output in a format like\n\
+.BR \"'1996 Oct 15 20:17:25.123 + 4.567 +/- 0.089 secs'\" ,\n\
+where the\n\
+.B \"'+ 4.567 +/- 0.089 secs'\"\n\
+indicates the estimated error in the time on the local system.  In daemon mode,\n\
+it will add drift information in a format like\n\
+.BR \"' + 1.3 +/- 0.1 ppm'\" ,\n\
+and display this at roughly\n\
+.I separation\n\
+intervals (see under the\n\
+.B \\-x\n\
+option for details).\n\
+.TP\n\
+.BI \\-l \" lockfile\"\n\
+sets the name of the lock file to ensure that there is only\n\
+one copy of\n\
+.I sntp\n\
+running at once.  The default is installation-dependent, but will usually be\n\
+.IR /etc/sntp.pid .\n\
+.TP\n\
+.BI \\-e \" minerr\"\n\
+sets the maximum ignorable variation between the clocks to\n\
+.IR minerr .\n\
+Acceptable values are from 0.001 to 1, and the default is 0.1 if a NTP host is\n\
+is specified and 0.5 otherwise.\n\
+.TP\n\
+.BI \\-E \" maxerr\"\n\
+sets the maximum value of various delays that are deemed acceptable to\n\
+.IR maxerr .\n\
+Acceptable values are from 1 to 60, and the default is 5.  It should sometimes\n\
+be increased if there are problems with the network, NTP server or system\n\
+clock, but take care.\n\
+.TP\n\
+.BI \\-P  \" prompt\"\n\
+sets the maximum clock change that will be made automatically to\n\
+.IR maxerr .\n\
+Acceptable values are from 1 to 3600 or\n\
+.IR no ,\n\
+and the default is 30.  If the program is being run interactively in ordinary\n\
+client mode, and the system clock is to be changed, larger corrections will\n\
+prompt the user for confirmation.  Specifying\n\
+.I no\n\
+will disable this and the correction will be made regardless.\n\
+.TP\n\
+.BI \\-c \" count\"\n\
+sets the maximum number of NTP packets required to\n\
+.IR count .\n\
+Acceptable values are from 1 to 25 if a NTP host is specified and from 5 to 25\n\
+otherwise, and the default is 5.  If the maximum isn't enough, the system needs\n\
+a better consistency algorithm than this program uses.\n\
+.TP\n\
+.BI \\-d \" delay\"\n\
+sets a rough limit on the total running time to\n\
+.I delay\n\
+seconds.  Acceptable values are from 1 to 3600, and the default is 15 if a NTP\n\
+host is specified and 300 otherwise.\n\
+.TP\n\
+.BI \\-x \" separation\"\n\
+causes the program to run as a daemon (i.e. forever), and to estimate and \n\
+correct for the clock drift.\n\
+.I separation\n\
+sets the minimum time between calls to the server in minutes if a NTP host is\n\
+specified, and between broadcast packets if not.  Acceptable values are from 1\n\
+to 1440 (a day), and the default (if\n\
+.B \\-x\n\
+is specified but\n\
+.I separation\n\
+is omitted) is 300.\n\
+.TP\n\
+.BI \\-f \" savefile\"\n\
+may be used with the\n\
+.B \\-x\n\
+option to store a record of previous packets, which speeds up recalculating\n\
+the drift after\n\
+.I sntp\n\
+has to be restarted (e.g. because of network or server outages).  In order to\n\
+restart the data,\n\
+.I sntp\n\
+must be restarted reasonably soon after it died (within a few times the value of\n\
+.IR separation ),\n\
+with the same value of the\n\
+.B \\-c\n\
+option, the same value of\n\
+.IR separation ,\n\
+in the same mode (i.e. broadcast or client), though the NTP servers need not\n\
+be the same for client mode, and with compatible values of other settings.\n\
+Note that the file will be created with the default ownerships and permissions,\n\
+using standard C facilities.  The default is installation-dependent, but will\n\
+usually be\n\
+.IR /etc/sntp.state .\n\
+.TP\n\
+.B -4\n\
+force IPv4 DNS resolution.\n\
+.TP\n\
+.B -6\n\
+force IPv6 DNS resolution.\n\
+.PP\n\
+.B address(es)\n\
+are the DNS names or IP numbers of hosts to use for the challenge and response\n\
+protocol; if no names are given, the program waits for broadcasts.  Polling a\n\
+server is vastly more reliable than listening to broadcasts.  Note that a\n\
+single component numeric address is not allowed, to avoid ambiguities.  If\n\
+more than one name is give, they will be used in a round-robin fashion.\n\
+.PP\n\
+Constraints:\n\
+.IP\n\
+.B minerr\n\
+must be less than\n\
+.B maxerr\n\
+which must be less than\n\
+.B delay\n\
+(or, if a NTP host is not specified\n\
+.BR delay / count \"),\"\n\
+and\n\
+.B count\n\
+must be less than half of\n\
+.BR delay .\n\
+.IP\n\
+In update mode,\n\
+.B maxerr\n\
+must be less than\n\
+.BR prompt.\n\
+.IP\n\
+In daemon mode (i.e. when\n\
+.B \\-x\n\
+is specified),\n\
+.B minerr\n\
+must be less than\n\
+.B maxerr\n\
+which must be less than\n\
+.B separation\n\
+(note that this is in minutes, not seconds, but the numeric value is compared).\n\
+.PP\n\
+Note that none of the above values are closely linked to the limits described\n\
+in the NTP protocol (RFC 1305).\n\
+.SH USAGE\n\
+The simplest use of this program is as an unprivileged command to check the\n\
+current time and error in the local clock.  For example:\n\
+.IP\n\
+.B sntp ntpserver.somewhere\n\
+.PP\n\
+It can be run as a unprivileged background process to check on the clock drift\n\
+as well as the current error; this will probably fail if the local clock is\n\
+reset while it is running.  For example:\n\
+.IP\n\
+.B sntp -x ntpserver.somewhere > output 2>\\&1 \\&\n\
+.PP\n\
+With suitable privilege, it can be run as a command or in a\n\
+.I cron\n\
+job to reset the local clock from a reliable server, like the\n\
+.I ntpdate\n\
+and\n\
+.I rdate\n\
+commands.  For example:\n\
+.IP\n\
+.B sntp -a ntpserver.somewhere\n\
+.PP\n\
+It can also be run as a daemon to keep the local clock in step.  For example:\n\
+.IP\n\
+.B sntp -a -x ntpserver.somewhere > output 2>\\&1 \\&\n\
+.PP\n\
+More information on how to use this utility is given in the\n\
+.I README\n\
+file in the distribution.  In particular, this\n\
+.I man\n\
+page does not describe how to set it up as a server, which needs special care\n\
+to avoid propagating misinformation.\n\
+.SH RETURN VALUE\n\
+When used as a client in non-daemon mode, the program returns a zero exit\n\
+status for success, and a non-zero one otherwise. When used as a daemon\n\
+(either client or server), it does not return except after a serious error.\n\
+.SH BUGS\n\
+The program implements the SNTP protocol, and does not provide all NTP \n\
+facilities.  In particular, it contains no checks against any form of spoofing.\n\
+If this is a serious concern, some network security mechanism (like a firewall\n\
+or even just\n\
+.IR tcpwrappers )\n\
+should be installed.\n\
+.PP\n\
+There are some errors, ambiguities and inconsistencies in the RFCs, and this\n\
+code may not interwork with all other NTP implementations.  Any unreasonable\n\
+restrictions should be reported as bugs to whoever is responsible.  It may\n\
+be difficult to find out who that is.\n\
+.PP\n\
+The program will stop as soon as it feels that things have got out of control.\n\
+In client daemon mode, it will usually fail during an extended period of\n\
+network or server inaccessibility or excessively slow performance, or when the\n\
+local clock is reset by another process.  It will then need restarting\n\
+manually.  Experienced system administrators can write a shell script, a\n\
+.I cron\n\
+job or put it in\n\
+.IR inittab ,\n\
+to do this automatically.\n\
+.PP\n\
+The error cannot be estimated reliably with broadcast packets or for the drift\n\
+in daemon mode (even with client-server packets), and the guess made by the\n\
+program may be wrong (possibly even very wrong).  If this is a problem, then\n\
+setting the\n\
+.B \\-c\n\
+option to a larger value may help.  Or it may not.\n\
+.SH AUTHOR\n\
+.I sntp\n\
+was developed by N.M. Maclaren of the University of Cambridge Computing\n\
+Service.\n";
+tSCC    zFullVersion[] = SNTP_FULL_VERSION;
+/* extracted from optcode near line 321 */
+
+#if defined(ENABLE_NLS)
+# define OPTPROC_BASE OPTPROC_TRANSLATE
+  static tOptionXlateProc translate_option_strings;
+#else
+# define OPTPROC_BASE OPTPROC_NONE
+# define translate_option_strings NULL
+#endif /* ENABLE_NLS */
+
+tOptions sntpOptions = {
+    OPTIONS_STRUCT_VERSION,
+    0, NULL,                    /* original argc + argv    */
+    ( OPTPROC_BASE
+    + OPTPROC_ERRSTOP
+    + OPTPROC_SHORTOPT
+    + OPTPROC_LONGOPT
+    + OPTPROC_NO_REQ_OPT
+    + OPTPROC_ENVIRON
+    + OPTPROC_NO_ARGS
+    + OPTPROC_HAS_IMMED ),
+    0, NULL,                    /* current option index, current option */
+    NULL,         NULL,         zPROGNAME,
+    zRcName,      zCopyright,   zCopyrightNotice,
+    zFullVersion, apzHomeList,  zUsageTitle,
+    zExplain,     zDetail,      optDesc,
+    zBugsAddr,                  /* address to send bugs to */
+    NULL, NULL,                 /* extensions/saved state  */
+    optionUsage,       /* usage procedure */
+    translate_option_strings,   /* translation procedure */
+    /*
+     *  Indexes to special options
+     */
+    { INDEX_OPT_MORE_HELP,
+      INDEX_OPT_SAVE_OPTS,
+      NO_EQUIVALENT /* index of '-#' option */,
+      NO_EQUIVALENT /* index of default opt */
+    },
+    OPTION_CT, 7 /* user option count */
+};
+
+/*
+ *  Create the static procedure(s) declared above.
+ */
+static void
+doUsageOpt(
+    tOptions*   pOptions,
+    tOptDesc*   pOptDesc )
+{
+    USAGE( EXIT_SUCCESS );
+}
+/* extracted from optmain.tpl near line 92 */
+
+#if defined(TEST_SNTP_OPTS) /* TEST MAIN PROCEDURE: */
+
+int
+main( int argc, char** argv )
+{
+    int res = EXIT_SUCCESS;
+    (void)optionProcess( &sntpOptions, argc, argv );
+    {
+        void optionPutShell( tOptions* );
+        optionPutShell( &sntpOptions );
+    }
+    return res;
+}
+#endif  /* defined TEST_SNTP_OPTS */
+/* extracted from optcode near line 418 */
+
+#if ENABLE_NLS
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+#include <autoopts/usage-txt.h>
+
+static char*
+AO_gettext( const char* pz )
+{
+    char* pzRes;
+    if (pz == NULL)
+        return NULL;
+    pzRes = _(pz);
+    if (pzRes == pz)
+        return pzRes;
+    pzRes = strdup( pzRes );
+    if (pzRes == NULL) {
+        fputs( _("No memory for duping translated strings\n"), stderr );
+        exit( EXIT_FAILURE );
+    }
+    return pzRes;
+}
+
+/*
+ *  This invokes the translation code (e.g. gettext(3)).
+ */
+static void
+translate_option_strings( void )
+{
+    /*
+     *  Guard against re-translation.  It won't work.  The strings will have
+     *  been changed by the first pass through this code.  One shot only.
+     */
+    if (option_usage_text.field_ct == 0)
+        return;
+    /*
+     *  Do the translations.  The first pointer follows the field count field.
+     *  The field count field is the size of a pointer.
+     */
+    {
+        char** ppz = (char**)(void*)&(option_usage_text);
+        int    ix  = option_usage_text.field_ct;
+
+        do {
+            ppz++;
+            *ppz = AO_gettext(*ppz);
+        } while (--ix > 0);
+    }
+    option_usage_text.field_ct = 0;
+
+    {
+        tOptDesc* pOD = sntpOptions.pOptDesc;
+        int       ix  = sntpOptions.optCt;
+
+        for (;;) {
+            pOD->pzText           = AO_gettext(pOD->pzText);
+            pOD->pz_NAME          = AO_gettext(pOD->pz_NAME);
+            pOD->pz_Name          = AO_gettext(pOD->pz_Name);
+            pOD->pz_DisableName   = AO_gettext(pOD->pz_DisableName);
+            pOD->pz_DisablePfx    = AO_gettext(pOD->pz_DisablePfx);
+            if (--ix <= 0)
+                break;
+            pOD++;
+        }
+    }
+    sntpOptions.pzCopyright   = AO_gettext(sntpOptions.pzCopyright);
+    sntpOptions.pzCopyNotice  = AO_gettext(sntpOptions.pzCopyNotice);
+    sntpOptions.pzFullVersion = AO_gettext(sntpOptions.pzFullVersion);
+    sntpOptions.pzUsageTitle  = AO_gettext(sntpOptions.pzUsageTitle);
+    sntpOptions.pzExplain     = AO_gettext(sntpOptions.pzExplain);
+    sntpOptions.pzDetail      = AO_gettext(sntpOptions.pzDetail);
+}
+
+#endif /* ENABLE_NLS */
+
+#ifdef  __cplusplus
+}
+#endif
diff --git a/sntp/sntp-opts.h b/sntp/sntp-opts.h
new file mode 100644 (file)
index 0000000..5f4e88a
--- /dev/null
@@ -0,0 +1,149 @@
+/*   -*- buffer-read-only: t -*- vi: set ro:
+ *  
+ *  DO NOT EDIT THIS FILE   (sntp-opts.h)
+ *  
+ *  It has been AutoGen-ed  Tuesday June 27, 2006 at 10:16:53 PM EDT
+ *  From the definitions    sntp-opts.def
+ *  and the template file   options
+ */
+/*
+ *  This file contains the programmatic interface to the Automated
+ *  Options generated for the sntp program.
+ *  These macros are documented in the AutoGen info file in the
+ *  "AutoOpts" chapter.  Please refer to that doc for usage help.
+ */
+#ifndef AUTOOPTS_SNTP_OPTS_H_GUARD
+#define AUTOOPTS_SNTP_OPTS_H_GUARD
+
+/*
+ * sntp copyright 1970-2006 ntp.org - all rights reserved
+ *
+ * See the sntp/Copyright file
+ */
+#include "config.h"
+#include <autoopts/options.h>
+
+/*
+ *  Ensure that the library used for compiling this generated header is at
+ *  least as new as the version current when the header template was released
+ *  (not counting patch version increments).  Also ensure that the oldest
+ *  tolerable version is at least as old as what was current when the header
+ *  template was released.
+ */
+#define AO_TEMPLATE_VERSION 110592
+#if (AO_TEMPLATE_VERSION < OPTIONS_MINIMUM_VERSION) \
+ || (AO_TEMPLATE_VERSION > OPTIONS_STRUCT_VERSION)
+# error option template version mismatches autoopts/options.h header
+#endif
+
+/*
+ *  Enumeration of each option:
+ */
+typedef enum {
+        INDEX_OPT_IPV4             =  0,
+        INDEX_OPT_IPV6             =  1,
+        INDEX_OPT_NORMALVERBOSE    =  2,
+        INDEX_OPT_EXTRAVERBOSE     =  3,
+        INDEX_OPT_MEGAVERBOSE      =  4,
+        INDEX_OPT_SETTIMEOFDAY     =  5,
+        INDEX_OPT_ADJTIME          =  6,
+        INDEX_OPT_VERSION          = 7,
+        INDEX_OPT_HELP             = 8,
+        INDEX_OPT_MORE_HELP        = 9,
+        INDEX_OPT_SAVE_OPTS        = 10,
+        INDEX_OPT_LOAD_OPTS        = 11
+} teOptIndex;
+
+#define OPTION_CT    12
+#define SNTP_VERSION       "4.2.3p12"
+#define SNTP_FULL_VERSION  "sntp - standard SNTP program - Ver. 4.2.3p12"
+
+/*
+ *  Interface defines for all options.  Replace "n" with
+ *  the UPPER_CASED option name (as in the teOptIndex
+ *  enumeration above).  e.g. HAVE_OPT( IPV4 )
+ */
+#define        DESC(n) sntpOptions.pOptDesc[INDEX_OPT_ ## n]
+#define     HAVE_OPT(n) (! UNUSED_OPT(& DESC(n)))
+#define      OPT_ARG(n) (DESC(n).pzLastArg)
+#define    STATE_OPT(n) (DESC(n).fOptState & OPTST_SET_MASK)
+#define    COUNT_OPT(n) (DESC(n).optOccCt)
+#define    ISSEL_OPT(n) (SELECTED_OPT(&DESC(n)))
+#define ISUNUSED_OPT(n) (UNUSED_OPT(& DESC(n)))
+#define  ENABLED_OPT(n) (! DISABLED_OPT(& DESC(n)))
+#define  STACKCT_OPT(n) (((tArgList*)(DESC(n).optCookie))->useCt)
+#define STACKLST_OPT(n) (((tArgList*)(DESC(n).optCookie))->apzArgs)
+#define    CLEAR_OPT(n) STMTS( \
+                DESC(n).fOptState &= OPTST_PERSISTENT;   \
+                if ( (DESC(n).fOptState & OPTST_INITENABLED) == 0) \
+                    DESC(n).fOptState |= OPTST_DISABLED; \
+                DESC(n).optCookie = NULL )
+
+/*
+ *  Interface defines for specific options.
+ */
+#define VALUE_OPT_IPV4           '4'
+#define WHICH_OPT_IPV4           (DESC(IPV4).optActualValue)
+#define WHICH_IDX_IPV4           (DESC(IPV4).optActualIndex)
+#define VALUE_OPT_IPV6           '6'
+#define VALUE_OPT_NORMALVERBOSE  'v'
+#define VALUE_OPT_EXTRAVERBOSE   'V'
+#define VALUE_OPT_MEGAVERBOSE    'W'
+#define VALUE_OPT_SETTIMEOFDAY   'r'
+#define VALUE_OPT_ADJTIME        'a'
+
+#define VALUE_OPT_VERSION       'v'
+#define VALUE_OPT_SAVE_OPTS     '>'
+#define VALUE_OPT_LOAD_OPTS     '<'
+#define VALUE_OPT_HELP          '?'
+#define VALUE_OPT_MORE_HELP     '!'
+#define SET_OPT_SAVE_OPTS(a)   STMTS( \
+        DESC(SAVE_OPTS).fOptState &= OPTST_PERSISTENT; \
+        DESC(SAVE_OPTS).fOptState |= OPTST_SET; \
+        DESC(SAVE_OPTS).pzLastArg  = (const char*)(a) )
+/*
+ *  Interface defines not associated with particular options
+ */
+#define ERRSKIP_OPTERR  STMTS( sntpOptions.fOptSet &= ~OPTPROC_ERRSTOP )
+#define ERRSTOP_OPTERR  STMTS( sntpOptions.fOptSet |= OPTPROC_ERRSTOP )
+#define RESTART_OPT(n)  STMTS( \
+                sntpOptions.curOptIdx = (n); \
+                sntpOptions.pzCurOpt  = NULL )
+#define START_OPT       RESTART_OPT(1)
+#define USAGE(c)        (*sntpOptions.pUsageProc)( &sntpOptions, c )
+/* extracted from opthead near line 289 */
+
+/* * * * * *
+ *
+ *  Declare the sntp option descriptor.
+ */
+#ifdef  __cplusplus
+extern "C" {
+#endif
+
+extern tOptions   sntpOptions;
+
+#ifndef _
+#  if ENABLE_NLS
+#    include <stdio.h>
+     static inline char* aoGetsText( const char* pz ) {
+         if (pz == NULL) return NULL;
+         return (char*)gettext( pz );
+     }
+#    define _(s)  aoGetsText(s)
+#  else  /* ENABLE_NLS */
+#    define _(s)  s
+#  endif /* ENABLE_NLS */
+#endif
+
+#ifdef  __cplusplus
+}
+#endif
+#endif /* AUTOOPTS_SNTP_OPTS_H_GUARD */
+/*
+ * Local Variables:
+ * Mode: C
+ * c-file-style: "stroustrup"
+ * indent-tabs-mode: nil
+ * End:
+ * options.h ends here */
diff --git a/sntp/sntp-opts.menu b/sntp/sntp-opts.menu
new file mode 100644 (file)
index 0000000..e3c8d81
--- /dev/null
@@ -0,0 +1 @@
+* sntp Invocation::                Invoking sntp
diff --git a/sntp/sntp-opts.texi b/sntp/sntp-opts.texi
new file mode 100644 (file)
index 0000000..d1c6974
--- /dev/null
@@ -0,0 +1,410 @@
+@node sntp Invocation
+@section Invoking sntp
+@pindex sntp
+@cindex standard SNTP program
+@ignore
+#  -*- buffer-read-only: t -*- vi: set ro:
+# 
+# DO NOT EDIT THIS FILE   (sntp-opts.texi)
+# 
+# It has been AutoGen-ed  Tuesday June 27, 2006 at 10:37:30 PM EDT
+# From the definitions    sntp-opts.def
+# and the template file   aginfo.tpl
+@end ignore
+This program has no explanation.
+
+.I sntp
+can be used as a SNTP client to query a NTP or SNTP server and either display
+the time or set the local system's time (given suitable privilege).  It can be
+run as an interactive command, in a
+.I cron
+job or as a daemon.  It can be run as a daemon to provide a SNTP server for
+other clients.  NTP is the Network Time Protocol (RFC 1305) and SNTP is the
+Simple Network Time Protocol (RFC 2030, which supersedes RFC 1769).
+.SS Options
+.PP
+.I sntp
+recognizes the following options:
+.TP
+.B \-v
+indicates that diagnostic messages for non-fatal errors and a limited amount of
+tracing should be written to standard error.  Fatal ones always produce a
+diagnostic.  This option should be set when there is a suspected problem with
+the server, network or the source.
+.TP
+.B \-V
+requests more and less comprehensible output, mainly for investigating problems
+with apparently inconsistent timestamps.  This option should be set when the
+program fails with a message indicating that is the trouble.
+.TP
+.B \-W
+requests very verbose debugging output, and will interfere with the timing
+when writing to the terminal (because of line buffered output from C).  Note
+that the times produced by this are the corrections needed, and not the error
+in the local clock.  This option should be set only when debugging the source.
+.TP
+.B \-q
+indicates that it should query a daemon save file being maintained by it.
+This needs no privilege and will change neither the save file nor the clock.
+.PP
+The default is that it should behave as a client, and the following options
+are then relevant:
+.TP
+.B \-r
+indicates that the system clock should be reset by
+.IR settimeofday .
+Naturally, this will work only if the user has enough privilege.
+.TP
+.B \-a
+indicates that the system clock should be reset by
+.IR adjtime .
+Naturally, this will work only if the user has enough privilege.
+.PP
+The default is to write the estimated correct local date and time (i.e. not
+UTC) to the standard output in a format like
+.BR "'1996 Oct 15 20:17:25.123 + 4.567 +/- 0.089 secs'" ,
+where the
+.B "'+ 4.567 +/- 0.089 secs'"
+indicates the estimated error in the time on the local system.  In daemon mode,
+it will add drift information in a format like
+.BR "' + 1.3 +/- 0.1 ppm'" ,
+and display this at roughly
+.I separation
+intervals (see under the
+.B \-x
+option for details).
+.TP
+.BI \-l " lockfile"
+sets the name of the lock file to ensure that there is only
+one copy of
+.I sntp
+running at once.  The default is installation-dependent, but will usually be
+.IR /etc/sntp.pid .
+.TP
+.BI \-e " minerr"
+sets the maximum ignorable variation between the clocks to
+.IR minerr .
+Acceptable values are from 0.001 to 1, and the default is 0.1 if a NTP host is
+is specified and 0.5 otherwise.
+.TP
+.BI \-E " maxerr"
+sets the maximum value of various delays that are deemed acceptable to
+.IR maxerr .
+Acceptable values are from 1 to 60, and the default is 5.  It should sometimes
+be increased if there are problems with the network, NTP server or system
+clock, but take care.
+.TP
+.BI \-P  " prompt"
+sets the maximum clock change that will be made automatically to
+.IR maxerr .
+Acceptable values are from 1 to 3600 or
+.IR no ,
+and the default is 30.  If the program is being run interactively in ordinary
+client mode, and the system clock is to be changed, larger corrections will
+prompt the user for confirmation.  Specifying
+.I no
+will disable this and the correction will be made regardless.
+.TP
+.BI \-c " count"
+sets the maximum number of NTP packets required to
+.IR count .
+Acceptable values are from 1 to 25 if a NTP host is specified and from 5 to 25
+otherwise, and the default is 5.  If the maximum isn't enough, the system needs
+a better consistency algorithm than this program uses.
+.TP
+.BI \-d " delay"
+sets a rough limit on the total running time to
+.I delay
+seconds.  Acceptable values are from 1 to 3600, and the default is 15 if a NTP
+host is specified and 300 otherwise.
+.TP
+.BI \-x " separation"
+causes the program to run as a daemon (i.e. forever), and to estimate and 
+correct for the clock drift.
+.I separation
+sets the minimum time between calls to the server in minutes if a NTP host is
+specified, and between broadcast packets if not.  Acceptable values are from 1
+to 1440 (a day), and the default (if
+.B \-x
+is specified but
+.I separation
+is omitted) is 300.
+.TP
+.BI \-f " savefile"
+may be used with the
+.B \-x
+option to store a record of previous packets, which speeds up recalculating
+the drift after
+.I sntp
+has to be restarted (e.g. because of network or server outages).  In order to
+restart the data,
+.I sntp
+must be restarted reasonably soon after it died (within a few times the value of
+.IR separation ),
+with the same value of the
+.B \-c
+option, the same value of
+.IR separation ,
+in the same mode (i.e. broadcast or client), though the NTP servers need not
+be the same for client mode, and with compatible values of other settings.
+Note that the file will be created with the default ownerships and permissions,
+using standard C facilities.  The default is installation-dependent, but will
+usually be
+.IR /etc/sntp.state .
+.TP
+.B -4
+force IPv4 DNS resolution.
+.TP
+.B -6
+force IPv6 DNS resolution.
+.PP
+.B address(es)
+are the DNS names or IP numbers of hosts to use for the challenge and response
+protocol; if no names are given, the program waits for broadcasts.  Polling a
+server is vastly more reliable than listening to broadcasts.  Note that a
+single component numeric address is not allowed, to avoid ambiguities.  If
+more than one name is give, they will be used in a round-robin fashion.
+.PP
+Constraints:
+.IP
+.B minerr
+must be less than
+.B maxerr
+which must be less than
+.B delay
+(or, if a NTP host is not specified
+.BR delay / count "),"
+and
+.B count
+must be less than half of
+.BR delay .
+.IP
+In update mode,
+.B maxerr
+must be less than
+.BR prompt.
+.IP
+In daemon mode (i.e. when
+.B \-x
+is specified),
+.B minerr
+must be less than
+.B maxerr
+which must be less than
+.B separation
+(note that this is in minutes, not seconds, but the numeric value is compared).
+.PP
+Note that none of the above values are closely linked to the limits described
+in the NTP protocol (RFC 1305).
+.SH USAGE
+The simplest use of this program is as an unprivileged command to check the
+current time and error in the local clock.  For example:
+.IP
+.B sntp ntpserver.somewhere
+.PP
+It can be run as a unprivileged background process to check on the clock drift
+as well as the current error; this will probably fail if the local clock is
+reset while it is running.  For example:
+.IP
+.B sntp -x ntpserver.somewhere > output 2>\&1 \&
+.PP
+With suitable privilege, it can be run as a command or in a
+.I cron
+job to reset the local clock from a reliable server, like the
+.I ntpdate
+and
+.I rdate
+commands.  For example:
+.IP
+.B sntp -a ntpserver.somewhere
+.PP
+It can also be run as a daemon to keep the local clock in step.  For example:
+.IP
+.B sntp -a -x ntpserver.somewhere > output 2>\&1 \&
+.PP
+More information on how to use this utility is given in the
+.I README
+file in the distribution.  In particular, this
+.I man
+page does not describe how to set it up as a server, which needs special care
+to avoid propagating misinformation.
+.SH RETURN VALUE
+When used as a client in non-daemon mode, the program returns a zero exit
+status for success, and a non-zero one otherwise. When used as a daemon
+(either client or server), it does not return except after a serious error.
+.SH BUGS
+The program implements the SNTP protocol, and does not provide all NTP 
+facilities.  In particular, it contains no checks against any form of spoofing.
+If this is a serious concern, some network security mechanism (like a firewall
+or even just
+.IR tcpwrappers )
+should be installed.
+.PP
+There are some errors, ambiguities and inconsistencies in the RFCs, and this
+code may not interwork with all other NTP implementations.  Any unreasonable
+restrictions should be reported as bugs to whoever is responsible.  It may
+be difficult to find out who that is.
+.PP
+The program will stop as soon as it feels that things have got out of control.
+In client daemon mode, it will usually fail during an extended period of
+network or server inaccessibility or excessively slow performance, or when the
+local clock is reset by another process.  It will then need restarting
+manually.  Experienced system administrators can write a shell script, a
+.I cron
+job or put it in
+.IR inittab ,
+to do this automatically.
+.PP
+The error cannot be estimated reliably with broadcast packets or for the drift
+in daemon mode (even with client-server packets), and the guess made by the
+program may be wrong (possibly even very wrong).  If this is a problem, then
+setting the
+.B \-c
+option to a larger value may help.  Or it may not.
+.SH AUTHOR
+.I sntp
+was developed by N.M. Maclaren of the University of Cambridge Computing
+Service.
+
+This section was generated by @strong{AutoGen},
+the aginfo template and the option descriptions for the @command{sntp} program.  It documents the sntp usage text and option meanings.
+
+This software is released under a specialized copyright license.
+
+@menu
+* sntp usage::                  sntp usage help (-?)
+* sntp adjtime::                adjtime option (-a)
+* sntp extraverbose::           extraverbose option (-V)
+* sntp ipv4::                   ipv4 option (-4)
+* sntp ipv6::                   ipv6 option (-6)
+* sntp megaverbose::            megaverbose option (-W)
+* sntp normalverbose::          normalverbose option (-v)
+* sntp settimeofday::           settimeofday option (-r)
+@end menu
+
+@node sntp usage
+@subsection sntp usage help (-?)
+@cindex sntp usage
+
+This is the automatically generated usage text for sntp:
+
+@exampleindent 0
+@example
+sntp is unavailable - no --help
+@end example
+@exampleindent 4
+
+@node sntp ipv4
+@subsection ipv4 option (-4)
+@cindex sntp-ipv4
+
+This is the ``force ipv4 dns name resolution'' option.
+
+This option has some usage constraints.  It:
+@itemize @bullet
+@item
+is a member of the ipv4 class of options.
+@end itemize
+
+Force DNS resolution of following host names on the command line
+to the IPv4 namespace.
+
+@node sntp ipv6
+@subsection ipv6 option (-6)
+@cindex sntp-ipv6
+
+This is the ``force ipv6 dns name resolution'' option.
+
+This option has some usage constraints.  It:
+@itemize @bullet
+@item
+is a member of the ipv4 class of options.
+@end itemize
+
+Force DNS resolution of following host names on the command line
+to the IPv6 namespace.
+
+@node sntp normalverbose
+@subsection normalverbose option (-v)
+@cindex sntp-normalverbose
+
+This is the ``slightly verbose'' option.
+
+This option has some usage constraints.  It:
+@itemize @bullet
+@item
+must not appear in combination with any of the following options:
+extraverbose, megaverbose.
+@end itemize
+
+Diagnostic messages for non-fatal errors and a limited amount of
+tracing should be written to standard error.  Fatal ones always
+produce a diagnostic.  This option should be set when there is a
+suspected problem with the server, network or the source.
+
+@node sntp extraverbose
+@subsection extraverbose option (-V)
+@cindex sntp-extraverbose
+
+This is the ``extra verbose'' option.
+
+This option has some usage constraints.  It:
+@itemize @bullet
+@item
+must not appear in combination with any of the following options:
+normalverbose, megaverbose.
+@end itemize
+
+Produce more and less comprehensible output, mainly for investigating
+problems with apparently inconsistent timestamps.  This option should
+be set when the program fails with a message indicating that is the
+trouble.
+
+@node sntp megaverbose
+@subsection megaverbose option (-W)
+@cindex sntp-megaverbose
+
+This is the ``mega verbose'' option.
+
+This option has some usage constraints.  It:
+@itemize @bullet
+@item
+must not appear in combination with any of the following options:
+normalverbose, extraverbose.
+@end itemize
+
+Very verbose debugging output that will interfere with the timing
+when writing to the terminal (because of line buffered output from C).
+Note that the times produced by this are the corrections needed, and
+not the error in the local clock.  This option should be set only when
+debugging the source.
+
+@node sntp settimeofday
+@subsection settimeofday option (-r)
+@cindex sntp-settimeofday
+
+This is the ``set (step) the time with settimeofday()'' option.
+
+This option has some usage constraints.  It:
+@itemize @bullet
+@item
+must not appear in combination with any of the following options:
+adjtime.
+@end itemize
+
+
+
+@node sntp adjtime
+@subsection adjtime option (-a)
+@cindex sntp-adjtime
+
+This is the ``set (slew) the time with adjtime()'' option.
+
+This option has some usage constraints.  It:
+@itemize @bullet
+@item
+must not appear in combination with any of the following options:
+settimeofday.
+@end itemize
+
+
diff --git a/util/ntp-keygen-opts.c b/util/ntp-keygen-opts.c
new file mode 100644 (file)
index 0000000..d24e876
--- /dev/null
@@ -0,0 +1,989 @@
+/*   -*- buffer-read-only: t -*- vi: set ro:
+ *  
+ *  DO NOT EDIT THIS FILE   (ntp-keygen-opts.c)
+ *  
+ *  It has been AutoGen-ed  Tuesday June 27, 2006 at 10:16:55 PM EDT
+ *  From the definitions    ntp-keygen-opts.def
+ *  and the template file   options
+ */
+#include <stdio.h>
+#include <limits.h>
+#define OPTION_CODE_COMPILE 1
+#include "ntp-keygen-opts.h"
+
+#ifdef  __cplusplus
+extern "C" {
+#endif
+tSCC zCopyright[] =
+       "ntp-keygen copyright (c) 1970-2006 ntp.org, all rights reserved";
+tSCC zCopyrightNotice[] =
+       
+/* extracted from /backroom/ntp-dev-hms/include/copyright.def near line 8 */
+"see html/copyright.html";
+extern tUsageProc optionUsage;
+
+/*
+ *  global included definitions
+ */
+#include <stdlib.h>
+#ifdef __windows
+  extern int atoi(const char*);
+#else
+# include <stdlib.h>
+#endif
+
+#ifndef NULL
+#  define NULL 0
+#endif
+#ifndef EXIT_SUCCESS
+#  define  EXIT_SUCCESS 0
+#endif
+#ifndef EXIT_FAILURE
+#  define  EXIT_FAILURE 1
+#endif
+/*
+ *  Certificate option description:
+ */
+#ifdef OPENSSL
+tSCC    zCertificateText[] =
+        "certificate scheme";
+tSCC    zCertificate_NAME[]        = "CERTIFICATE";
+tSCC    zCertificate_Name[]        = "certificate";
+#define CERTIFICATE_FLAGS       (OPTST_DISABLED \
+       | OPTST_SET_ARGTYPE(OPARG_TYPE_STRING))
+
+#else   /* disable Certificate */
+#define VALUE_OPT_CERTIFICATE NO_EQUIVALENT
+#define CERTIFICATE_FLAGS       (OPTST_OMITTED | OPTST_NO_INIT)
+#define zCertificateText       NULL
+#define zCertificate_NAME      NULL
+#define zCertificate_Name      NULL
+#endif  /* OPENSSL */
+
+/*
+ *  Debug_Level option description:
+ */
+tSCC    zDebug_LevelText[] =
+        "Increase output debug message level";
+tSCC    zDebug_Level_NAME[]        = "DEBUG_LEVEL";
+tSCC    zDebug_Level_Name[]        = "debug-level";
+#define DEBUG_LEVEL_FLAGS       (OPTST_DISABLED)
+
+/*
+ *  Set_Debug_Level option description:
+ */
+tSCC    zSet_Debug_LevelText[] =
+        "Set the output debug message level";
+tSCC    zSet_Debug_Level_NAME[]    = "SET_DEBUG_LEVEL";
+tSCC    zSet_Debug_Level_Name[]    = "set-debug-level";
+#define SET_DEBUG_LEVEL_FLAGS       (OPTST_DISABLED \
+       | OPTST_SET_ARGTYPE(OPARG_TYPE_STRING))
+
+/*
+ *  Id_Key option description:
+ */
+#ifdef OPENSSL
+tSCC    zId_KeyText[] =
+        "Write identity keys";
+tSCC    zId_Key_NAME[]             = "ID_KEY";
+tSCC    zId_Key_Name[]             = "id-key";
+#define ID_KEY_FLAGS       (OPTST_DISABLED)
+
+#else   /* disable Id_Key */
+#define VALUE_OPT_ID_KEY NO_EQUIVALENT
+#define ID_KEY_FLAGS       (OPTST_OMITTED | OPTST_NO_INIT)
+#define zId_KeyText       NULL
+#define zId_Key_NAME      NULL
+#define zId_Key_Name      NULL
+#endif  /* OPENSSL */
+
+/*
+ *  Gq_Params option description:
+ */
+#ifdef OPENSSL
+tSCC    zGq_ParamsText[] =
+        "Generate GQ parameters and keys";
+tSCC    zGq_Params_NAME[]          = "GQ_PARAMS";
+tSCC    zGq_Params_Name[]          = "gq-params";
+#define GQ_PARAMS_FLAGS       (OPTST_DISABLED)
+
+#else   /* disable Gq_Params */
+#define VALUE_OPT_GQ_PARAMS NO_EQUIVALENT
+#define GQ_PARAMS_FLAGS       (OPTST_OMITTED | OPTST_NO_INIT)
+#define zGq_ParamsText       NULL
+#define zGq_Params_NAME      NULL
+#define zGq_Params_Name      NULL
+#endif  /* OPENSSL */
+
+/*
+ *  Gq_Keys option description:
+ */
+#ifdef OPENSSL
+tSCC    zGq_KeysText[] =
+        "update GQ keys";
+tSCC    zGq_Keys_NAME[]            = "GQ_KEYS";
+tSCC    zGq_Keys_Name[]            = "gq-keys";
+#define GQ_KEYS_FLAGS       (OPTST_DISABLED)
+
+#else   /* disable Gq_Keys */
+#define VALUE_OPT_GQ_KEYS NO_EQUIVALENT
+#define GQ_KEYS_FLAGS       (OPTST_OMITTED | OPTST_NO_INIT)
+#define zGq_KeysText       NULL
+#define zGq_Keys_NAME      NULL
+#define zGq_Keys_Name      NULL
+#endif  /* OPENSSL */
+
+/*
+ *  Host_Key option description:
+ */
+#ifdef OPENSSL
+tSCC    zHost_KeyText[] =
+        "generate RSA host key";
+tSCC    zHost_Key_NAME[]           = "HOST_KEY";
+tSCC    zHost_Key_Name[]           = "host-key";
+#define HOST_KEY_FLAGS       (OPTST_DISABLED)
+
+#else   /* disable Host_Key */
+#define VALUE_OPT_HOST_KEY NO_EQUIVALENT
+#define HOST_KEY_FLAGS       (OPTST_OMITTED | OPTST_NO_INIT)
+#define zHost_KeyText       NULL
+#define zHost_Key_NAME      NULL
+#define zHost_Key_Name      NULL
+#endif  /* OPENSSL */
+
+/*
+ *  Iffkey option description:
+ */
+#ifdef OPENSSL
+tSCC    zIffkeyText[] =
+        "generate IFF parameters";
+tSCC    zIffkey_NAME[]             = "IFFKEY";
+tSCC    zIffkey_Name[]             = "iffkey";
+#define IFFKEY_FLAGS       (OPTST_DISABLED)
+
+#else   /* disable Iffkey */
+#define VALUE_OPT_IFFKEY NO_EQUIVALENT
+#define IFFKEY_FLAGS       (OPTST_OMITTED | OPTST_NO_INIT)
+#define zIffkeyText       NULL
+#define zIffkey_NAME      NULL
+#define zIffkey_Name      NULL
+#endif  /* OPENSSL */
+
+/*
+ *  Issuer_Name option description:
+ */
+#ifdef OPENSSL
+tSCC    zIssuer_NameText[] =
+        "set issuer name";
+tSCC    zIssuer_Name_NAME[]        = "ISSUER_NAME";
+tSCC    zIssuer_Name_Name[]        = "issuer-name";
+#define ISSUER_NAME_FLAGS       (OPTST_DISABLED)
+
+#else   /* disable Issuer_Name */
+#define VALUE_OPT_ISSUER_NAME NO_EQUIVALENT
+#define ISSUER_NAME_FLAGS       (OPTST_OMITTED | OPTST_NO_INIT)
+#define zIssuer_NameText       NULL
+#define zIssuer_Name_NAME      NULL
+#define zIssuer_Name_Name      NULL
+#endif  /* OPENSSL */
+
+/*
+ *  Md5key option description:
+ */
+tSCC    zMd5keyText[] =
+        "generate MD5 keys";
+tSCC    zMd5key_NAME[]             = "MD5KEY";
+tSCC    zMd5key_Name[]             = "md5key";
+#define MD5KEY_FLAGS       (OPTST_DISABLED)
+
+/*
+ *  Modulus option description:
+ */
+#ifdef OPENSSL
+tSCC    zModulusText[] =
+        "modulus";
+tSCC    zModulus_NAME[]            = "MODULUS";
+tSCC    zModulus_Name[]            = "modulus";
+#define MODULUS_FLAGS       (OPTST_DISABLED \
+       | OPTST_SET_ARGTYPE(OPARG_TYPE_NUMERIC))
+
+#else   /* disable Modulus */
+#define VALUE_OPT_MODULUS NO_EQUIVALENT
+#define MODULUS_FLAGS       (OPTST_OMITTED | OPTST_NO_INIT)
+#define zModulusText       NULL
+#define zModulus_NAME      NULL
+#define zModulus_Name      NULL
+#endif  /* OPENSSL */
+
+/*
+ *  Pvt_Cert option description:
+ */
+#ifdef OPENSSL
+tSCC    zPvt_CertText[] =
+        "generate PC private certificate";
+tSCC    zPvt_Cert_NAME[]           = "PVT_CERT";
+tSCC    zPvt_Cert_Name[]           = "pvt-cert";
+#define PVT_CERT_FLAGS       (OPTST_DISABLED)
+
+#else   /* disable Pvt_Cert */
+#define VALUE_OPT_PVT_CERT NO_EQUIVALENT
+#define PVT_CERT_FLAGS       (OPTST_OMITTED | OPTST_NO_INIT)
+#define zPvt_CertText       NULL
+#define zPvt_Cert_NAME      NULL
+#define zPvt_Cert_Name      NULL
+#endif  /* OPENSSL */
+
+/*
+ *  Pvt_Passwd option description:
+ */
+#ifdef OPENSSL
+tSCC    zPvt_PasswdText[] =
+        "output private password";
+tSCC    zPvt_Passwd_NAME[]         = "PVT_PASSWD";
+tSCC    zPvt_Passwd_Name[]         = "pvt-passwd";
+#define PVT_PASSWD_FLAGS       (OPTST_DISABLED \
+       | OPTST_SET_ARGTYPE(OPARG_TYPE_STRING))
+
+#else   /* disable Pvt_Passwd */
+#define VALUE_OPT_PVT_PASSWD NO_EQUIVALENT
+#define PVT_PASSWD_FLAGS       (OPTST_OMITTED | OPTST_NO_INIT)
+#define zPvt_PasswdText       NULL
+#define zPvt_Passwd_NAME      NULL
+#define zPvt_Passwd_Name      NULL
+#endif  /* OPENSSL */
+
+/*
+ *  Get_Pvt_Passwd option description:
+ */
+#ifdef OPENSSL
+tSCC    zGet_Pvt_PasswdText[] =
+        "input private password";
+tSCC    zGet_Pvt_Passwd_NAME[]     = "GET_PVT_PASSWD";
+tSCC    zGet_Pvt_Passwd_Name[]     = "get-pvt-passwd";
+#define GET_PVT_PASSWD_FLAGS       (OPTST_DISABLED \
+       | OPTST_SET_ARGTYPE(OPARG_TYPE_STRING))
+
+#else   /* disable Get_Pvt_Passwd */
+#define VALUE_OPT_GET_PVT_PASSWD NO_EQUIVALENT
+#define GET_PVT_PASSWD_FLAGS       (OPTST_OMITTED | OPTST_NO_INIT)
+#define zGet_Pvt_PasswdText       NULL
+#define zGet_Pvt_Passwd_NAME      NULL
+#define zGet_Pvt_Passwd_Name      NULL
+#endif  /* OPENSSL */
+
+/*
+ *  Sign_Key option description:
+ */
+#ifdef OPENSSL
+tSCC    zSign_KeyText[] =
+        "generate sign key (RSA or DSA)";
+tSCC    zSign_Key_NAME[]           = "SIGN_KEY";
+tSCC    zSign_Key_Name[]           = "sign-key";
+#define SIGN_KEY_FLAGS       (OPTST_DISABLED \
+       | OPTST_SET_ARGTYPE(OPARG_TYPE_STRING))
+
+#else   /* disable Sign_Key */
+#define VALUE_OPT_SIGN_KEY NO_EQUIVALENT
+#define SIGN_KEY_FLAGS       (OPTST_OMITTED | OPTST_NO_INIT)
+#define zSign_KeyText       NULL
+#define zSign_Key_NAME      NULL
+#define zSign_Key_Name      NULL
+#endif  /* OPENSSL */
+
+/*
+ *  Subject_Name option description:
+ */
+#ifdef OPENSSL
+tSCC    zSubject_NameText[] =
+        "set subject name";
+tSCC    zSubject_Name_NAME[]       = "SUBJECT_NAME";
+tSCC    zSubject_Name_Name[]       = "subject-name";
+#define SUBJECT_NAME_FLAGS       (OPTST_DISABLED \
+       | OPTST_SET_ARGTYPE(OPARG_TYPE_STRING))
+
+#else   /* disable Subject_Name */
+#define VALUE_OPT_SUBJECT_NAME NO_EQUIVALENT
+#define SUBJECT_NAME_FLAGS       (OPTST_OMITTED | OPTST_NO_INIT)
+#define zSubject_NameText       NULL
+#define zSubject_Name_NAME      NULL
+#define zSubject_Name_Name      NULL
+#endif  /* OPENSSL */
+
+/*
+ *  Trusted_Cert option description:
+ */
+#ifdef OPENSSL
+tSCC    zTrusted_CertText[] =
+        "trusted certificate (TC scheme)";
+tSCC    zTrusted_Cert_NAME[]       = "TRUSTED_CERT";
+tSCC    zTrusted_Cert_Name[]       = "trusted-cert";
+#define TRUSTED_CERT_FLAGS       (OPTST_DISABLED)
+
+#else   /* disable Trusted_Cert */
+#define VALUE_OPT_TRUSTED_CERT NO_EQUIVALENT
+#define TRUSTED_CERT_FLAGS       (OPTST_OMITTED | OPTST_NO_INIT)
+#define zTrusted_CertText       NULL
+#define zTrusted_Cert_NAME      NULL
+#define zTrusted_Cert_Name      NULL
+#endif  /* OPENSSL */
+
+/*
+ *  Mv_Params option description:
+ */
+#ifdef OPENSSL
+tSCC    zMv_ParamsText[] =
+        "generate <num> MV parameters";
+tSCC    zMv_Params_NAME[]          = "MV_PARAMS";
+tSCC    zMv_Params_Name[]          = "mv-params";
+#define MV_PARAMS_FLAGS       (OPTST_DISABLED \
+       | OPTST_SET_ARGTYPE(OPARG_TYPE_NUMERIC))
+
+#else   /* disable Mv_Params */
+#define VALUE_OPT_MV_PARAMS NO_EQUIVALENT
+#define MV_PARAMS_FLAGS       (OPTST_OMITTED | OPTST_NO_INIT)
+#define zMv_ParamsText       NULL
+#define zMv_Params_NAME      NULL
+#define zMv_Params_Name      NULL
+#endif  /* OPENSSL */
+
+/*
+ *  Mv_Keys option description:
+ */
+#ifdef OPENSSL
+tSCC    zMv_KeysText[] =
+        "update <num> MV keys";
+tSCC    zMv_Keys_NAME[]            = "MV_KEYS";
+tSCC    zMv_Keys_Name[]            = "mv-keys";
+#define MV_KEYS_FLAGS       (OPTST_DISABLED \
+       | OPTST_SET_ARGTYPE(OPARG_TYPE_NUMERIC))
+
+#else   /* disable Mv_Keys */
+#define VALUE_OPT_MV_KEYS NO_EQUIVALENT
+#define MV_KEYS_FLAGS       (OPTST_OMITTED | OPTST_NO_INIT)
+#define zMv_KeysText       NULL
+#define zMv_Keys_NAME      NULL
+#define zMv_Keys_Name      NULL
+#endif  /* OPENSSL */
+
+/*
+ *  Help/More_Help/Version option descriptions:
+ */
+tSCC zHelpText[]       = "Display usage information and exit";
+tSCC zHelp_Name[]      = "help";
+
+tSCC zMore_HelpText[]  = "Extended usage information passed thru pager";
+tSCC zMore_Help_Name[] = "more-help";
+
+tSCC zVersionText[]    = "Output version information and exit";
+tSCC zVersion_Name[]   = "version";
+
+/*
+ *  Save/Load_Opts option description:
+ */
+tSCC zSave_OptsText[]     = "Save the option state to a config file";
+tSCC zSave_Opts_Name[]    = "save-opts";
+
+tSCC zLoad_OptsText[]     = "Load options from a config file";
+tSCC zLoad_Opts_NAME[]    = "LOAD_OPTS";
+
+tSCC zNotLoad_Opts_Name[] = "no-load-opts";
+tSCC zNotLoad_Opts_Pfx[]  = "no";
+#define zLoad_Opts_Name   (zNotLoad_Opts_Name + 3)
+/*
+ *  Declare option callback procedures
+ */
+#ifndef OPENSSL
+#define doOptModulus doUsageOpt
+#endif
+#ifndef OPENSSL
+#define optionNumericVal doUsageOpt
+#endif
+#ifndef OPENSSL
+#define optionNumericVal doUsageOpt
+#endif
+/* extracted from optmain.tpl near line 586 */
+
+#if defined(TEST_NTP_KEYGEN_OPTS)
+/*
+ *  Under test, omit argument processing, or call optionStackArg,
+ *  if multiple copies are allowed.
+ */
+extern tOptProc
+    optionNumericVal, optionPagedUsage, optionVersionStderr;
+static tOptProc
+    doOptModulus, doUsageOpt;
+
+/*
+ *  #define map the "normal" callout procs to the test ones...
+ */
+#define SET_DEBUG_LEVEL_OPT_PROC optionStackArg
+
+
+#else /* NOT defined TEST_NTP_KEYGEN_OPTS */
+/*
+ *  When not under test, there are different procs to use
+ */
+extern tOptProc
+    optionNumericVal, optionPagedUsage, optionPrintVersion;
+static tOptProc
+    doOptModulus, doOptSet_Debug_Level, doUsageOpt;
+
+/*
+ *  #define map the "normal" callout procs
+ */
+#define SET_DEBUG_LEVEL_OPT_PROC doOptSet_Debug_Level
+
+#define SET_DEBUG_LEVEL_OPT_PROC doOptSet_Debug_Level
+#endif /* defined(TEST_NTP_KEYGEN_OPTS) */
+#ifndef OPENSSL
+#undef  doOptModulus
+#define doOptModulus NULL
+#endif
+#ifndef OPENSSL
+#undef  optionNumericVal
+#define optionNumericVal NULL
+#endif
+#ifndef OPENSSL
+#undef  optionNumericVal
+#define optionNumericVal NULL
+#endif
+#ifdef TEST_NTP_KEYGEN_OPTS
+# define DOVERPROC optionVersionStderr
+#else
+# define DOVERPROC optionPrintVersion
+#endif /* TEST_NTP_KEYGEN_OPTS */
+
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ *
+ *  Define the Ntp_Keygen Option Descriptions.
+ */
+static tOptDesc optDesc[ OPTION_CT ] = {
+  {  /* entry idx, value */ 0, VALUE_OPT_CERTIFICATE,
+     /* equiv idx, value */ 0, VALUE_OPT_CERTIFICATE,
+     /* equivalenced to  */ NO_EQUIVALENT,
+     /* min, max, act ct */ 0, 1, 0,
+     /* opt state flags  */ CERTIFICATE_FLAGS, 0,
+     /* last opt argumnt */ NULL,
+     /* arg list/cookie  */ NULL,
+     /* must/cannot opts */ NULL, NULL,
+     /* option proc      */ NULL,
+     /* desc, NAME, name */ zCertificateText, zCertificate_NAME, zCertificate_Name,
+     /* disablement strs */ NULL, NULL },
+
+  {  /* entry idx, value */ 1, VALUE_OPT_DEBUG_LEVEL,
+     /* equiv idx, value */ 1, VALUE_OPT_DEBUG_LEVEL,
+     /* equivalenced to  */ NO_EQUIVALENT,
+     /* min, max, act ct */ 0, NOLIMIT, 0,
+     /* opt state flags  */ DEBUG_LEVEL_FLAGS, 0,
+     /* last opt argumnt */ NULL,
+     /* arg list/cookie  */ NULL,
+     /* must/cannot opts */ NULL, NULL,
+     /* option proc      */ NULL,
+     /* desc, NAME, name */ zDebug_LevelText, zDebug_Level_NAME, zDebug_Level_Name,
+     /* disablement strs */ NULL, NULL },
+
+  {  /* entry idx, value */ 2, VALUE_OPT_SET_DEBUG_LEVEL,
+     /* equiv idx, value */ 2, VALUE_OPT_SET_DEBUG_LEVEL,
+     /* equivalenced to  */ NO_EQUIVALENT,
+     /* min, max, act ct */ 0, NOLIMIT, 0,
+     /* opt state flags  */ SET_DEBUG_LEVEL_FLAGS, 0,
+     /* last opt argumnt */ NULL,
+     /* arg list/cookie  */ NULL,
+     /* must/cannot opts */ NULL, NULL,
+     /* option proc      */ SET_DEBUG_LEVEL_OPT_PROC,
+     /* desc, NAME, name */ zSet_Debug_LevelText, zSet_Debug_Level_NAME, zSet_Debug_Level_Name,
+     /* disablement strs */ NULL, NULL },
+
+  {  /* entry idx, value */ 3, VALUE_OPT_ID_KEY,
+     /* equiv idx, value */ 3, VALUE_OPT_ID_KEY,
+     /* equivalenced to  */ NO_EQUIVALENT,
+     /* min, max, act ct */ 0, 1, 0,
+     /* opt state flags  */ ID_KEY_FLAGS, 0,
+     /* last opt argumnt */ NULL,
+     /* arg list/cookie  */ NULL,
+     /* must/cannot opts */ NULL, NULL,
+     /* option proc      */ NULL,
+     /* desc, NAME, name */ zId_KeyText, zId_Key_NAME, zId_Key_Name,
+     /* disablement strs */ NULL, NULL },
+
+  {  /* entry idx, value */ 4, VALUE_OPT_GQ_PARAMS,
+     /* equiv idx, value */ 4, VALUE_OPT_GQ_PARAMS,
+     /* equivalenced to  */ NO_EQUIVALENT,
+     /* min, max, act ct */ 0, 1, 0,
+     /* opt state flags  */ GQ_PARAMS_FLAGS, 0,
+     /* last opt argumnt */ NULL,
+     /* arg list/cookie  */ NULL,
+     /* must/cannot opts */ NULL, NULL,
+     /* option proc      */ NULL,
+     /* desc, NAME, name */ zGq_ParamsText, zGq_Params_NAME, zGq_Params_Name,
+     /* disablement strs */ NULL, NULL },
+
+  {  /* entry idx, value */ 5, VALUE_OPT_GQ_KEYS,
+     /* equiv idx, value */ 5, VALUE_OPT_GQ_KEYS,
+     /* equivalenced to  */ NO_EQUIVALENT,
+     /* min, max, act ct */ 0, 1, 0,
+     /* opt state flags  */ GQ_KEYS_FLAGS, 0,
+     /* last opt argumnt */ NULL,
+     /* arg list/cookie  */ NULL,
+     /* must/cannot opts */ NULL, NULL,
+     /* option proc      */ NULL,
+     /* desc, NAME, name */ zGq_KeysText, zGq_Keys_NAME, zGq_Keys_Name,
+     /* disablement strs */ NULL, NULL },
+
+  {  /* entry idx, value */ 6, VALUE_OPT_HOST_KEY,
+     /* equiv idx, value */ 6, VALUE_OPT_HOST_KEY,
+     /* equivalenced to  */ NO_EQUIVALENT,
+     /* min, max, act ct */ 0, 1, 0,
+     /* opt state flags  */ HOST_KEY_FLAGS, 0,
+     /* last opt argumnt */ NULL,
+     /* arg list/cookie  */ NULL,
+     /* must/cannot opts */ NULL, NULL,
+     /* option proc      */ NULL,
+     /* desc, NAME, name */ zHost_KeyText, zHost_Key_NAME, zHost_Key_Name,
+     /* disablement strs */ NULL, NULL },
+
+  {  /* entry idx, value */ 7, VALUE_OPT_IFFKEY,
+     /* equiv idx, value */ 7, VALUE_OPT_IFFKEY,
+     /* equivalenced to  */ NO_EQUIVALENT,
+     /* min, max, act ct */ 0, 1, 0,
+     /* opt state flags  */ IFFKEY_FLAGS, 0,
+     /* last opt argumnt */ NULL,
+     /* arg list/cookie  */ NULL,
+     /* must/cannot opts */ NULL, NULL,
+     /* option proc      */ NULL,
+     /* desc, NAME, name */ zIffkeyText, zIffkey_NAME, zIffkey_Name,
+     /* disablement strs */ NULL, NULL },
+
+  {  /* entry idx, value */ 8, VALUE_OPT_ISSUER_NAME,
+     /* equiv idx, value */ 8, VALUE_OPT_ISSUER_NAME,
+     /* equivalenced to  */ NO_EQUIVALENT,
+     /* min, max, act ct */ 0, 1, 0,
+     /* opt state flags  */ ISSUER_NAME_FLAGS, 0,
+     /* last opt argumnt */ NULL,
+     /* arg list/cookie  */ NULL,
+     /* must/cannot opts */ NULL, NULL,
+     /* option proc      */ NULL,
+     /* desc, NAME, name */ zIssuer_NameText, zIssuer_Name_NAME, zIssuer_Name_Name,
+     /* disablement strs */ NULL, NULL },
+
+  {  /* entry idx, value */ 9, VALUE_OPT_MD5KEY,
+     /* equiv idx, value */ 9, VALUE_OPT_MD5KEY,
+     /* equivalenced to  */ NO_EQUIVALENT,
+     /* min, max, act ct */ 0, 1, 0,
+     /* opt state flags  */ MD5KEY_FLAGS, 0,
+     /* last opt argumnt */ NULL,
+     /* arg list/cookie  */ NULL,
+     /* must/cannot opts */ NULL, NULL,
+     /* option proc      */ NULL,
+     /* desc, NAME, name */ zMd5keyText, zMd5key_NAME, zMd5key_Name,
+     /* disablement strs */ NULL, NULL },
+
+  {  /* entry idx, value */ 10, VALUE_OPT_MODULUS,
+     /* equiv idx, value */ 10, VALUE_OPT_MODULUS,
+     /* equivalenced to  */ NO_EQUIVALENT,
+     /* min, max, act ct */ 0, 1, 0,
+     /* opt state flags  */ MODULUS_FLAGS, 0,
+     /* last opt argumnt */ NULL,
+     /* arg list/cookie  */ NULL,
+     /* must/cannot opts */ NULL, NULL,
+     /* option proc      */ doOptModulus,
+     /* desc, NAME, name */ zModulusText, zModulus_NAME, zModulus_Name,
+     /* disablement strs */ NULL, NULL },
+
+  {  /* entry idx, value */ 11, VALUE_OPT_PVT_CERT,
+     /* equiv idx, value */ 11, VALUE_OPT_PVT_CERT,
+     /* equivalenced to  */ NO_EQUIVALENT,
+     /* min, max, act ct */ 0, 1, 0,
+     /* opt state flags  */ PVT_CERT_FLAGS, 0,
+     /* last opt argumnt */ NULL,
+     /* arg list/cookie  */ NULL,
+     /* must/cannot opts */ NULL, NULL,
+     /* option proc      */ NULL,
+     /* desc, NAME, name */ zPvt_CertText, zPvt_Cert_NAME, zPvt_Cert_Name,
+     /* disablement strs */ NULL, NULL },
+
+  {  /* entry idx, value */ 12, VALUE_OPT_PVT_PASSWD,
+     /* equiv idx, value */ 12, VALUE_OPT_PVT_PASSWD,
+     /* equivalenced to  */ NO_EQUIVALENT,
+     /* min, max, act ct */ 0, 1, 0,
+     /* opt state flags  */ PVT_PASSWD_FLAGS, 0,
+     /* last opt argumnt */ NULL,
+     /* arg list/cookie  */ NULL,
+     /* must/cannot opts */ NULL, NULL,
+     /* option proc      */ NULL,
+     /* desc, NAME, name */ zPvt_PasswdText, zPvt_Passwd_NAME, zPvt_Passwd_Name,
+     /* disablement strs */ NULL, NULL },
+
+  {  /* entry idx, value */ 13, VALUE_OPT_GET_PVT_PASSWD,
+     /* equiv idx, value */ 13, VALUE_OPT_GET_PVT_PASSWD,
+     /* equivalenced to  */ NO_EQUIVALENT,
+     /* min, max, act ct */ 0, 1, 0,
+     /* opt state flags  */ GET_PVT_PASSWD_FLAGS, 0,
+     /* last opt argumnt */ NULL,
+     /* arg list/cookie  */ NULL,
+     /* must/cannot opts */ NULL, NULL,
+     /* option proc      */ NULL,
+     /* desc, NAME, name */ zGet_Pvt_PasswdText, zGet_Pvt_Passwd_NAME, zGet_Pvt_Passwd_Name,
+     /* disablement strs */ NULL, NULL },
+
+  {  /* entry idx, value */ 14, VALUE_OPT_SIGN_KEY,
+     /* equiv idx, value */ 14, VALUE_OPT_SIGN_KEY,
+     /* equivalenced to  */ NO_EQUIVALENT,
+     /* min, max, act ct */ 0, 1, 0,
+     /* opt state flags  */ SIGN_KEY_FLAGS, 0,
+     /* last opt argumnt */ NULL,
+     /* arg list/cookie  */ NULL,
+     /* must/cannot opts */ NULL, NULL,
+     /* option proc      */ NULL,
+     /* desc, NAME, name */ zSign_KeyText, zSign_Key_NAME, zSign_Key_Name,
+     /* disablement strs */ NULL, NULL },
+
+  {  /* entry idx, value */ 15, VALUE_OPT_SUBJECT_NAME,
+     /* equiv idx, value */ 15, VALUE_OPT_SUBJECT_NAME,
+     /* equivalenced to  */ NO_EQUIVALENT,
+     /* min, max, act ct */ 0, 1, 0,
+     /* opt state flags  */ SUBJECT_NAME_FLAGS, 0,
+     /* last opt argumnt */ NULL,
+     /* arg list/cookie  */ NULL,
+     /* must/cannot opts */ NULL, NULL,
+     /* option proc      */ NULL,
+     /* desc, NAME, name */ zSubject_NameText, zSubject_Name_NAME, zSubject_Name_Name,
+     /* disablement strs */ NULL, NULL },
+
+  {  /* entry idx, value */ 16, VALUE_OPT_TRUSTED_CERT,
+     /* equiv idx, value */ 16, VALUE_OPT_TRUSTED_CERT,
+     /* equivalenced to  */ NO_EQUIVALENT,
+     /* min, max, act ct */ 0, 1, 0,
+     /* opt state flags  */ TRUSTED_CERT_FLAGS, 0,
+     /* last opt argumnt */ NULL,
+     /* arg list/cookie  */ NULL,
+     /* must/cannot opts */ NULL, NULL,
+     /* option proc      */ NULL,
+     /* desc, NAME, name */ zTrusted_CertText, zTrusted_Cert_NAME, zTrusted_Cert_Name,
+     /* disablement strs */ NULL, NULL },
+
+  {  /* entry idx, value */ 17, VALUE_OPT_MV_PARAMS,
+     /* equiv idx, value */ 17, VALUE_OPT_MV_PARAMS,
+     /* equivalenced to  */ NO_EQUIVALENT,
+     /* min, max, act ct */ 0, 1, 0,
+     /* opt state flags  */ MV_PARAMS_FLAGS, 0,
+     /* last opt argumnt */ NULL,
+     /* arg list/cookie  */ NULL,
+     /* must/cannot opts */ NULL, NULL,
+     /* option proc      */ optionNumericVal,
+     /* desc, NAME, name */ zMv_ParamsText, zMv_Params_NAME, zMv_Params_Name,
+     /* disablement strs */ NULL, NULL },
+
+  {  /* entry idx, value */ 18, VALUE_OPT_MV_KEYS,
+     /* equiv idx, value */ 18, VALUE_OPT_MV_KEYS,
+     /* equivalenced to  */ NO_EQUIVALENT,
+     /* min, max, act ct */ 0, 1, 0,
+     /* opt state flags  */ MV_KEYS_FLAGS, 0,
+     /* last opt argumnt */ NULL,
+     /* arg list/cookie  */ NULL,
+     /* must/cannot opts */ NULL, NULL,
+     /* option proc      */ optionNumericVal,
+     /* desc, NAME, name */ zMv_KeysText, zMv_Keys_NAME, zMv_Keys_Name,
+     /* disablement strs */ NULL, NULL },
+
+  {  /* entry idx, value */ INDEX_OPT_VERSION, VALUE_OPT_VERSION,
+     /* equiv idx value  */ NO_EQUIVALENT, 0,
+     /* equivalenced to  */ NO_EQUIVALENT,
+     /* min, max, act ct */ 0, 1, 0,
+     /* opt state flags  */ OPTST_SET_ARGTYPE(OPARG_TYPE_STRING)
+                          | OPTST_ARG_OPTIONAL, 0,
+     /* last opt argumnt */ NULL,
+     /* arg list/cookie  */ NULL,
+     /* must/cannot opts */ NULL, NULL,
+     /* option proc      */ DOVERPROC,
+     /* desc, NAME, name */ zVersionText, NULL, zVersion_Name,
+     /* disablement strs */ NULL, NULL },
+
+  {  /* entry idx, value */ INDEX_OPT_HELP, VALUE_OPT_HELP,
+     /* equiv idx value  */ NO_EQUIVALENT, 0,
+     /* equivalenced to  */ NO_EQUIVALENT,
+     /* min, max, act ct */ 0, 1, 0,
+     /* opt state flags  */ OPTST_IMM, 0,
+     /* last opt argumnt */ NULL,
+     /* arg list/cookie  */ NULL,
+     /* must/cannot opts */ NULL, NULL,
+     /* option proc      */ doUsageOpt,
+     /* desc, NAME, name */ zHelpText, NULL, zHelp_Name,
+     /* disablement strs */ NULL, NULL },
+
+  {  /* entry idx, value */ INDEX_OPT_MORE_HELP, VALUE_OPT_MORE_HELP,
+     /* equiv idx value  */ NO_EQUIVALENT, 0,
+     /* equivalenced to  */ NO_EQUIVALENT,
+     /* min, max, act ct */ 0, 1, 0,
+     /* opt state flags  */ OPTST_IMM, 0,
+     /* last opt argumnt */ NULL,
+     /* arg list/cookie  */ NULL,
+     /* must/cannot opts */ NULL,  NULL,
+     /* option proc      */ optionPagedUsage,
+     /* desc, NAME, name */ zMore_HelpText, NULL, zMore_Help_Name,
+     /* disablement strs */ NULL, NULL },
+
+  {  /* entry idx, value */ INDEX_OPT_SAVE_OPTS, VALUE_OPT_SAVE_OPTS,
+     /* equiv idx value  */ NO_EQUIVALENT, 0,
+     /* equivalenced to  */ NO_EQUIVALENT,
+     /* min, max, act ct */ 0, 1, 0,
+     /* opt state flags  */ OPTST_SET_ARGTYPE(OPARG_TYPE_STRING)
+                          | OPTST_ARG_OPTIONAL, 0,
+     /* last opt argumnt */ NULL,
+     /* arg list/cookie  */ NULL,
+     /* must/cannot opts */ NULL,  NULL,
+     /* option proc      */ NULL,
+     /* desc, NAME, name */ zSave_OptsText, NULL, zSave_Opts_Name,
+     /* disablement strs */ NULL, NULL },
+
+  {  /* entry idx, value */ INDEX_OPT_LOAD_OPTS, VALUE_OPT_LOAD_OPTS,
+     /* equiv idx value  */ NO_EQUIVALENT, 0,
+     /* equivalenced to  */ NO_EQUIVALENT,
+     /* min, max, act ct */ 0, NOLIMIT, 0,
+     /* opt state flags  */ OPTST_DISABLE_IMM | \
+                       OPTST_SET_ARGTYPE(OPARG_TYPE_STRING), 0,
+     /* last opt argumnt */ NULL,
+     /* arg list/cookie  */ NULL,
+     /* must/cannot opts */ NULL, NULL,
+     /* option proc      */ optionLoadOpt,
+     /* desc, NAME, name */ zLoad_OptsText, zLoad_Opts_NAME, zLoad_Opts_Name,
+     /* disablement strs */ zNotLoad_Opts_Name, zNotLoad_Opts_Pfx }
+};
+
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ *
+ *  Define the Ntp_Keygen Option Environment
+ */
+tSCC   zPROGNAME[]   = "NTP_KEYGEN";
+tSCC   zUsageTitle[] =
+"ntp-keygen (ntp) - Create a NTP host key - Ver. 4.2.3p12\n\
+USAGE:  %s [ -<flag> [<val>] | --<name>[{=| }<val>] ]...\n";
+tSCC   zRcName[]     = ".ntprc";
+tSCC*  apzHomeList[] = {
+       "$HOME",
+       ".",
+       NULL };
+
+tSCC   zBugsAddr[]    = "http://bugs.ntp.isc.org, bugs@ntp.org";
+#define zExplain NULL
+tSCC    zDetail[]     = "\n\
+If there is no new host key, look for an existing one.\n\
+If one is not found, create it.\n";
+tSCC    zFullVersion[] = NTP_KEYGEN_FULL_VERSION;
+/* extracted from optcode near line 321 */
+
+#if defined(ENABLE_NLS)
+# define OPTPROC_BASE OPTPROC_TRANSLATE
+  static tOptionXlateProc translate_option_strings;
+#else
+# define OPTPROC_BASE OPTPROC_NONE
+# define translate_option_strings NULL
+#endif /* ENABLE_NLS */
+
+tOptions ntp_keygenOptions = {
+    OPTIONS_STRUCT_VERSION,
+    0, NULL,                    /* original argc + argv    */
+    ( OPTPROC_BASE
+    + OPTPROC_ERRSTOP
+    + OPTPROC_SHORTOPT
+    + OPTPROC_LONGOPT
+    + OPTPROC_NO_REQ_OPT
+    + OPTPROC_ENVIRON
+    + OPTPROC_NO_ARGS
+    + OPTPROC_HAS_IMMED ),
+    0, NULL,                    /* current option index, current option */
+    NULL,         NULL,         zPROGNAME,
+    zRcName,      zCopyright,   zCopyrightNotice,
+    zFullVersion, apzHomeList,  zUsageTitle,
+    zExplain,     zDetail,      optDesc,
+    zBugsAddr,                  /* address to send bugs to */
+    NULL, NULL,                 /* extensions/saved state  */
+    optionUsage,       /* usage procedure */
+    translate_option_strings,   /* translation procedure */
+    /*
+     *  Indexes to special options
+     */
+    { INDEX_OPT_MORE_HELP,
+      INDEX_OPT_SAVE_OPTS,
+      NO_EQUIVALENT /* index of '-#' option */,
+      NO_EQUIVALENT /* index of default opt */
+    },
+    OPTION_CT, 19 /* user option count */
+};
+
+/*
+ *  Create the static procedure(s) declared above.
+ */
+static void
+doUsageOpt(
+    tOptions*   pOptions,
+    tOptDesc*   pOptDesc )
+{
+    USAGE( EXIT_SUCCESS );
+}
+
+#if ! defined(TEST_NTP_KEYGEN_OPTS)
+
+/* * * * * * *
+ *
+ *   For the set-debug-level option.
+ */
+static void
+doOptSet_Debug_Level(
+    tOptions*   pOptions,
+    tOptDesc*   pOptDesc )
+{
+DESC(DEBUG_LEVEL).optOccCt = atoi( pOptDesc->pzLastArg );
+}
+
+#endif /* defined(TEST_NTP_KEYGEN_OPTS) */
+
+/* * * * * * *
+ *
+ *   For the modulus option, when OPENSSL is #define-d.
+ */
+#ifdef OPENSSL
+static void
+doOptModulus(
+    tOptions*   pOptions,
+    tOptDesc*   pOptDesc )
+{
+    static const struct {const int rmin, rmax;} rng[ 1 ] = {
+        { 256, 2048 } };
+    long val;
+    int ix;
+    const char* pzIndent = "\t\t\t\t  ";
+    extern FILE* option_usage_fp;
+
+    if (pOptDesc == NULL) /* usage is requesting range list
+                             option_usage_fp has already been set */
+        goto emit_ranges;
+
+    val = atoi( pOptDesc->pzLastArg );
+    for (ix = 0; ix < 1; ix++) {
+        if (val < rng[ix].rmin)
+            continue;  /* ranges need not be ordered. */
+        if (val == rng[ix].rmin)
+            goto valid_return;
+        if (rng[ix].rmax == INT_MIN)
+            continue;
+        if (val <= rng[ix].rmax)
+            goto valid_return;
+    }
+
+    option_usage_fp = stderr;
+    fprintf( stderr, _("%s error:  %s option value ``%s''is out of range.\n"),
+             pOptions->pzProgName, pOptDesc->pz_Name, pOptDesc->pzLastArg );
+    pzIndent = "\t";
+
+  emit_ranges:
+    fprintf( option_usage_fp, _("%sit must lie in the range: %d to %d\n"),
+             pzIndent, rng[0].rmin, rng[0].rmax );
+    if (pOptDesc == NULL)
+        return;
+
+    USAGE( EXIT_FAILURE );
+    /* NOTREACHED */
+    return;
+
+  valid_return:
+    pOptDesc->pzLastArg = (char*)val;
+}
+#endif /* defined OPENSSL */
+
+/* extracted from optmain.tpl near line 92 */
+
+#if defined(TEST_NTP_KEYGEN_OPTS) /* TEST MAIN PROCEDURE: */
+
+int
+main( int argc, char** argv )
+{
+    int res = EXIT_SUCCESS;
+    (void)optionProcess( &ntp_keygenOptions, argc, argv );
+    {
+        void optionPutShell( tOptions* );
+        optionPutShell( &ntp_keygenOptions );
+    }
+    return res;
+}
+#endif  /* defined TEST_NTP_KEYGEN_OPTS */
+/* extracted from optcode near line 418 */
+
+#if ENABLE_NLS
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+#include <autoopts/usage-txt.h>
+
+static char*
+AO_gettext( const char* pz )
+{
+    char* pzRes;
+    if (pz == NULL)
+        return NULL;
+    pzRes = _(pz);
+    if (pzRes == pz)
+        return pzRes;
+    pzRes = strdup( pzRes );
+    if (pzRes == NULL) {
+        fputs( _("No memory for duping translated strings\n"), stderr );
+        exit( EXIT_FAILURE );
+    }
+    return pzRes;
+}
+
+/*
+ *  This invokes the translation code (e.g. gettext(3)).
+ */
+static void
+translate_option_strings( void )
+{
+    /*
+     *  Guard against re-translation.  It won't work.  The strings will have
+     *  been changed by the first pass through this code.  One shot only.
+     */
+    if (option_usage_text.field_ct == 0)
+        return;
+    /*
+     *  Do the translations.  The first pointer follows the field count field.
+     *  The field count field is the size of a pointer.
+     */
+    {
+        char** ppz = (char**)(void*)&(option_usage_text);
+        int    ix  = option_usage_text.field_ct;
+
+        do {
+            ppz++;
+            *ppz = AO_gettext(*ppz);
+        } while (--ix > 0);
+    }
+    option_usage_text.field_ct = 0;
+
+    {
+        tOptDesc* pOD = ntp_keygenOptions.pOptDesc;
+        int       ix  = ntp_keygenOptions.optCt;
+
+        for (;;) {
+            pOD->pzText           = AO_gettext(pOD->pzText);
+            pOD->pz_NAME          = AO_gettext(pOD->pz_NAME);
+            pOD->pz_Name          = AO_gettext(pOD->pz_Name);
+            pOD->pz_DisableName   = AO_gettext(pOD->pz_DisableName);
+            pOD->pz_DisablePfx    = AO_gettext(pOD->pz_DisablePfx);
+            if (--ix <= 0)
+                break;
+            pOD++;
+        }
+    }
+    ntp_keygenOptions.pzCopyright   = AO_gettext(ntp_keygenOptions.pzCopyright);
+    ntp_keygenOptions.pzCopyNotice  = AO_gettext(ntp_keygenOptions.pzCopyNotice);
+    ntp_keygenOptions.pzFullVersion = AO_gettext(ntp_keygenOptions.pzFullVersion);
+    ntp_keygenOptions.pzUsageTitle  = AO_gettext(ntp_keygenOptions.pzUsageTitle);
+    ntp_keygenOptions.pzExplain     = AO_gettext(ntp_keygenOptions.pzExplain);
+    ntp_keygenOptions.pzDetail      = AO_gettext(ntp_keygenOptions.pzDetail);
+}
+
+#endif /* ENABLE_NLS */
+
+#ifdef  __cplusplus
+}
+#endif
diff --git a/util/ntp-keygen-opts.h b/util/ntp-keygen-opts.h
new file mode 100644 (file)
index 0000000..76d5c50
--- /dev/null
@@ -0,0 +1,206 @@
+/*   -*- buffer-read-only: t -*- vi: set ro:
+ *  
+ *  DO NOT EDIT THIS FILE   (ntp-keygen-opts.h)
+ *  
+ *  It has been AutoGen-ed  Tuesday June 27, 2006 at 10:16:55 PM EDT
+ *  From the definitions    ntp-keygen-opts.def
+ *  and the template file   options
+ */
+/*
+ *  This file contains the programmatic interface to the Automated
+ *  Options generated for the ntp-keygen program.
+ *  These macros are documented in the AutoGen info file in the
+ *  "AutoOpts" chapter.  Please refer to that doc for usage help.
+ */
+#ifndef AUTOOPTS_NTP_KEYGEN_OPTS_H_GUARD
+#define AUTOOPTS_NTP_KEYGEN_OPTS_H_GUARD
+
+/*
+ * ntp-keygen copyright 1970-2006 ntp.org - all rights reserved
+ *
+ * see html/copyright.html
+ */
+#include "config.h"
+#include <autoopts/options.h>
+
+/*
+ *  Ensure that the library used for compiling this generated header is at
+ *  least as new as the version current when the header template was released
+ *  (not counting patch version increments).  Also ensure that the oldest
+ *  tolerable version is at least as old as what was current when the header
+ *  template was released.
+ */
+#define AO_TEMPLATE_VERSION 110592
+#if (AO_TEMPLATE_VERSION < OPTIONS_MINIMUM_VERSION) \
+ || (AO_TEMPLATE_VERSION > OPTIONS_STRUCT_VERSION)
+# error option template version mismatches autoopts/options.h header
+#endif
+
+/*
+ *  Enumeration of each option:
+ */
+typedef enum {
+        INDEX_OPT_CERTIFICATE      =  0,
+        INDEX_OPT_DEBUG_LEVEL      =  1,
+        INDEX_OPT_SET_DEBUG_LEVEL  =  2,
+        INDEX_OPT_ID_KEY           =  3,
+        INDEX_OPT_GQ_PARAMS        =  4,
+        INDEX_OPT_GQ_KEYS          =  5,
+        INDEX_OPT_HOST_KEY         =  6,
+        INDEX_OPT_IFFKEY           =  7,
+        INDEX_OPT_ISSUER_NAME      =  8,
+        INDEX_OPT_MD5KEY           =  9,
+        INDEX_OPT_MODULUS          = 10,
+        INDEX_OPT_PVT_CERT         = 11,
+        INDEX_OPT_PVT_PASSWD       = 12,
+        INDEX_OPT_GET_PVT_PASSWD   = 13,
+        INDEX_OPT_SIGN_KEY         = 14,
+        INDEX_OPT_SUBJECT_NAME     = 15,
+        INDEX_OPT_TRUSTED_CERT     = 16,
+        INDEX_OPT_MV_PARAMS        = 17,
+        INDEX_OPT_MV_KEYS          = 18,
+        INDEX_OPT_VERSION          = 19,
+        INDEX_OPT_HELP             = 20,
+        INDEX_OPT_MORE_HELP        = 21,
+        INDEX_OPT_SAVE_OPTS        = 22,
+        INDEX_OPT_LOAD_OPTS        = 23
+} teOptIndex;
+
+#define OPTION_CT    24
+#define NTP_KEYGEN_VERSION       "4.2.3p12"
+#define NTP_KEYGEN_FULL_VERSION  "ntp-keygen (ntp) - Create a NTP host key - Ver. 4.2.3p12"
+
+/*
+ *  Interface defines for all options.  Replace "n" with
+ *  the UPPER_CASED option name (as in the teOptIndex
+ *  enumeration above).  e.g. HAVE_OPT( CERTIFICATE )
+ */
+#define        DESC(n) ntp_keygenOptions.pOptDesc[INDEX_OPT_ ## n]
+#define     HAVE_OPT(n) (! UNUSED_OPT(& DESC(n)))
+#define      OPT_ARG(n) (DESC(n).pzLastArg)
+#define    STATE_OPT(n) (DESC(n).fOptState & OPTST_SET_MASK)
+#define    COUNT_OPT(n) (DESC(n).optOccCt)
+#define    ISSEL_OPT(n) (SELECTED_OPT(&DESC(n)))
+#define ISUNUSED_OPT(n) (UNUSED_OPT(& DESC(n)))
+#define  ENABLED_OPT(n) (! DISABLED_OPT(& DESC(n)))
+#define  STACKCT_OPT(n) (((tArgList*)(DESC(n).optCookie))->useCt)
+#define STACKLST_OPT(n) (((tArgList*)(DESC(n).optCookie))->apzArgs)
+#define    CLEAR_OPT(n) STMTS( \
+                DESC(n).fOptState &= OPTST_PERSISTENT;   \
+                if ( (DESC(n).fOptState & OPTST_INITENABLED) == 0) \
+                    DESC(n).fOptState |= OPTST_DISABLED; \
+                DESC(n).optCookie = NULL )
+
+/*
+ *  Interface defines for specific options.
+ */
+#ifdef OPENSSL
+#define VALUE_OPT_CERTIFICATE    'c'
+#endif /* OPENSSL */
+#define VALUE_OPT_DEBUG_LEVEL    'd'
+#define VALUE_OPT_SET_DEBUG_LEVEL 'D'
+#ifdef OPENSSL
+#define VALUE_OPT_ID_KEY         'e'
+#endif /* OPENSSL */
+#ifdef OPENSSL
+#define VALUE_OPT_GQ_PARAMS      'G'
+#endif /* OPENSSL */
+#ifdef OPENSSL
+#define VALUE_OPT_GQ_KEYS        'g'
+#endif /* OPENSSL */
+#ifdef OPENSSL
+#define VALUE_OPT_HOST_KEY       'H'
+#endif /* OPENSSL */
+#ifdef OPENSSL
+#define VALUE_OPT_IFFKEY         'I'
+#endif /* OPENSSL */
+#ifdef OPENSSL
+#define VALUE_OPT_ISSUER_NAME    'i'
+#endif /* OPENSSL */
+#define VALUE_OPT_MD5KEY         'M'
+#ifdef OPENSSL
+#define VALUE_OPT_MODULUS        'm'
+#define OPT_VALUE_MODULUS        (*(unsigned long*)(&DESC(MODULUS).pzLastArg))
+#endif /* OPENSSL */
+#ifdef OPENSSL
+#define VALUE_OPT_PVT_CERT       'P'
+#endif /* OPENSSL */
+#ifdef OPENSSL
+#define VALUE_OPT_PVT_PASSWD     'p'
+#endif /* OPENSSL */
+#ifdef OPENSSL
+#define VALUE_OPT_GET_PVT_PASSWD 'q'
+#endif /* OPENSSL */
+#ifdef OPENSSL
+#define VALUE_OPT_SIGN_KEY       'S'
+#endif /* OPENSSL */
+#ifdef OPENSSL
+#define VALUE_OPT_SUBJECT_NAME   's'
+#endif /* OPENSSL */
+#ifdef OPENSSL
+#define VALUE_OPT_TRUSTED_CERT   'T'
+#endif /* OPENSSL */
+#ifdef OPENSSL
+#define VALUE_OPT_MV_PARAMS      'V'
+#define OPT_VALUE_MV_PARAMS      (*(unsigned long*)(&DESC(MV_PARAMS).pzLastArg))
+#endif /* OPENSSL */
+#ifdef OPENSSL
+#define VALUE_OPT_MV_KEYS        'v'
+#define OPT_VALUE_MV_KEYS        (*(unsigned long*)(&DESC(MV_KEYS).pzLastArg))
+#endif /* OPENSSL */
+
+#define VALUE_OPT_VERSION       'v'
+#define VALUE_OPT_SAVE_OPTS     '>'
+#define VALUE_OPT_LOAD_OPTS     '<'
+#define VALUE_OPT_HELP          '?'
+#define VALUE_OPT_MORE_HELP     '!'
+#define SET_OPT_SAVE_OPTS(a)   STMTS( \
+        DESC(SAVE_OPTS).fOptState &= OPTST_PERSISTENT; \
+        DESC(SAVE_OPTS).fOptState |= OPTST_SET; \
+        DESC(SAVE_OPTS).pzLastArg  = (const char*)(a) )
+/*
+ *  Interface defines not associated with particular options
+ */
+#define ERRSKIP_OPTERR  STMTS( ntp_keygenOptions.fOptSet &= ~OPTPROC_ERRSTOP )
+#define ERRSTOP_OPTERR  STMTS( ntp_keygenOptions.fOptSet |= OPTPROC_ERRSTOP )
+#define RESTART_OPT(n)  STMTS( \
+                ntp_keygenOptions.curOptIdx = (n); \
+                ntp_keygenOptions.pzCurOpt  = NULL )
+#define START_OPT       RESTART_OPT(1)
+#define USAGE(c)        (*ntp_keygenOptions.pUsageProc)( &ntp_keygenOptions, c )
+/* extracted from opthead near line 289 */
+
+/* * * * * *
+ *
+ *  Declare the ntp-keygen option descriptor.
+ */
+#ifdef  __cplusplus
+extern "C" {
+#endif
+
+extern tOptions   ntp_keygenOptions;
+
+#ifndef _
+#  if ENABLE_NLS
+#    include <stdio.h>
+     static inline char* aoGetsText( const char* pz ) {
+         if (pz == NULL) return NULL;
+         return (char*)gettext( pz );
+     }
+#    define _(s)  aoGetsText(s)
+#  else  /* ENABLE_NLS */
+#    define _(s)  s
+#  endif /* ENABLE_NLS */
+#endif
+
+#ifdef  __cplusplus
+}
+#endif
+#endif /* AUTOOPTS_NTP_KEYGEN_OPTS_H_GUARD */
+/*
+ * Local Variables:
+ * Mode: C
+ * c-file-style: "stroustrup"
+ * indent-tabs-mode: nil
+ * End:
+ * options.h ends here */
diff --git a/util/ntp-keygen-opts.menu b/util/ntp-keygen-opts.menu
new file mode 100644 (file)
index 0000000..bc5cfe9
--- /dev/null
@@ -0,0 +1 @@
+* ntp-keygen Invocation::          Invoking ntp-keygen
diff --git a/util/ntp-keygen-opts.texi b/util/ntp-keygen-opts.texi
new file mode 100644 (file)
index 0000000..fb72938
--- /dev/null
@@ -0,0 +1,362 @@
+@node ntp-keygen Invocation
+@section Invoking ntp-keygen
+@pindex ntp-keygen
+@cindex Create a NTP host key
+@ignore
+#  -*- buffer-read-only: t -*- vi: set ro:
+# 
+# DO NOT EDIT THIS FILE   (ntp-keygen-opts.texi)
+# 
+# It has been AutoGen-ed  Tuesday June 27, 2006 at 10:37:44 PM EDT
+# From the definitions    ntp-keygen-opts.def
+# and the template file   aginfo.tpl
+@end ignore
+This program has no explanation.
+
+If there is no new host key, look for an existing one.
+If one is not found, create it.
+
+This section was generated by @strong{AutoGen},
+the aginfo template and the option descriptions for the @command{ntp-keygen} program.  It documents the ntp-keygen usage text and option meanings.
+
+This software is released under a specialized copyright license.
+
+@menu
+* ntp-keygen usage::                  ntp-keygen usage help (-?)
+* ntp-keygen certificate::            certificate option (-c)
+* ntp-keygen debug-level::            debug-level option (-d)
+* ntp-keygen get-pvt-passwd::         get-pvt-passwd option (-q)
+* ntp-keygen gq-keys::                gq-keys option (-g)
+* ntp-keygen gq-params::              gq-params option (-G)
+* ntp-keygen host-key::               host-key option (-H)
+* ntp-keygen id-key::                 id-key option (-e)
+* ntp-keygen iffkey::                 iffkey option (-I)
+* ntp-keygen issuer-name::            issuer-name option (-i)
+* ntp-keygen md5key::                 md5key option (-M)
+* ntp-keygen modulus::                modulus option (-m)
+* ntp-keygen mv-keys::                mv-keys option (-v)
+* ntp-keygen mv-params::              mv-params option (-V)
+* ntp-keygen pvt-cert::               pvt-cert option (-P)
+* ntp-keygen pvt-passwd::             pvt-passwd option (-p)
+* ntp-keygen set-debug-level::        set-debug-level option (-D)
+* ntp-keygen sign-key::               sign-key option (-S)
+* ntp-keygen subject-name::           subject-name option (-s)
+* ntp-keygen trusted-cert::           trusted-cert option (-T)
+@end menu
+
+@node ntp-keygen usage
+@subsection ntp-keygen usage help (-?)
+@cindex ntp-keygen usage
+
+This is the automatically generated usage text for ntp-keygen:
+
+@exampleindent 0
+@example
+Using OpenSSL version 90704f
+ntp-keygen (ntp) - Create a NTP host key - Ver. 4.2.3p10
+USAGE:  ntp-keygen [ -<flag> [<val>] | --<name>[@{=| @}<val>] ]...
+  Flg Arg Option-Name    Description
+   -c Str certificate    certificate scheme
+   -d no  debug-level    Increase output debug message level
+                                - may appear multiple times
+   -D Str set-debug-level Set the output debug message level
+                                - may appear multiple times
+   -e no  id-key         Write identity keys
+   -G no  gq-params      Generate GQ parameters and keys
+   -g no  gq-keys        update GQ keys
+   -H no  host-key       generate RSA host key
+   -I no  iffkey         generate IFF parameters
+   -i no  issuer-name    set issuer name
+   -M no  md5key         generate MD5 keys
+   -m Num modulus        modulus
+                                  it must lie in the range: 256 to 2048
+   -P no  pvt-cert       generate PC private certificate
+   -p Str pvt-passwd     output private password
+   -q Str get-pvt-passwd input private password
+   -S Str sign-key       generate sign key (RSA or DSA)
+   -s Str subject-name   set subject name
+   -T no  trusted-cert   trusted certificate (TC scheme)
+   -V Num mv-params      generate <num> MV parameters
+   -v Num mv-keys        update <num> MV keys
+   -v opt version        Output version information and exit
+   -? no  help           Display usage information and exit
+   -! no  more-help      Extended usage information passed thru pager
+   -> opt save-opts      Save the option state to a config file
+   -< Str load-opts      Load options from a config file
+                                - disabled as --no-load-opts
+                                - may appear multiple times
+
+Options are specified by doubled hyphens and their name
+or by a single hyphen and the flag character.
+
+The following option preset mechanisms are supported:
+ - reading file /users/stenn/.ntprc
+ - reading file /deacon/backroom/ntp-dev-hms/util/.ntprc
+ - examining environment variables named NTP_KEYGEN_*
+
+If there is no new host key, look for an existing one.
+If one is not found, create it.
+
+please send bug reports to:  http://bugs.ntp.isc.org, bugs@@ntp.org
+@end example
+@exampleindent 4
+
+@node ntp-keygen certificate
+@subsection certificate option (-c)
+@cindex ntp-keygen-certificate
+
+This is the ``certificate scheme'' option.
+
+This option has some usage constraints.  It:
+@itemize @bullet
+@item
+must be compiled in by defining @code{OPENSSL} during the compilation.
+@end itemize
+
+Just some descriptive text.
+
+@node ntp-keygen debug-level
+@subsection debug-level option (-d)
+@cindex ntp-keygen-debug-level
+
+This is the ``increase output debug message level'' option.
+
+This option has some usage constraints.  It:
+@itemize @bullet
+@item
+may appear an unlimited number of times.
+@end itemize
+
+Increase the debugging message output level.
+
+@node ntp-keygen set-debug-level
+@subsection set-debug-level option (-D)
+@cindex ntp-keygen-set-debug-level
+
+This is the ``set the output debug message level'' option.
+
+This option has some usage constraints.  It:
+@itemize @bullet
+@item
+may appear an unlimited number of times.
+@end itemize
+
+Set the output debugging level.  Can be supplied multiple times,
+but each overrides the previous value(s).
+
+@node ntp-keygen id-key
+@subsection id-key option (-e)
+@cindex ntp-keygen-id-key
+
+This is the ``write identity keys'' option.
+
+This option has some usage constraints.  It:
+@itemize @bullet
+@item
+must be compiled in by defining @code{OPENSSL} during the compilation.
+@end itemize
+
+Just some descriptive text.
+
+@node ntp-keygen gq-params
+@subsection gq-params option (-G)
+@cindex ntp-keygen-gq-params
+
+This is the ``generate gq parameters and keys'' option.
+
+This option has some usage constraints.  It:
+@itemize @bullet
+@item
+must be compiled in by defining @code{OPENSSL} during the compilation.
+@end itemize
+
+Just some descriptive text.
+
+@node ntp-keygen gq-keys
+@subsection gq-keys option (-g)
+@cindex ntp-keygen-gq-keys
+
+This is the ``update gq keys'' option.
+
+This option has some usage constraints.  It:
+@itemize @bullet
+@item
+must be compiled in by defining @code{OPENSSL} during the compilation.
+@end itemize
+
+Just some descriptive text.
+
+@node ntp-keygen host-key
+@subsection host-key option (-H)
+@cindex ntp-keygen-host-key
+
+This is the ``generate rsa host key'' option.
+
+This option has some usage constraints.  It:
+@itemize @bullet
+@item
+must be compiled in by defining @code{OPENSSL} during the compilation.
+@end itemize
+
+Just some descriptive text.
+
+@node ntp-keygen iffkey
+@subsection iffkey option (-I)
+@cindex ntp-keygen-iffkey
+
+This is the ``generate iff parameters'' option.
+
+This option has some usage constraints.  It:
+@itemize @bullet
+@item
+must be compiled in by defining @code{OPENSSL} during the compilation.
+@end itemize
+
+Just some descriptive text.
+
+@node ntp-keygen issuer-name
+@subsection issuer-name option (-i)
+@cindex ntp-keygen-issuer-name
+
+This is the ``set issuer name'' option.
+
+This option has some usage constraints.  It:
+@itemize @bullet
+@item
+must be compiled in by defining @code{OPENSSL} during the compilation.
+@end itemize
+
+Just some descriptive text.
+
+@node ntp-keygen md5key
+@subsection md5key option (-M)
+@cindex ntp-keygen-md5key
+
+This is the ``generate md5 keys'' option.
+Just some descriptive text.
+
+@node ntp-keygen modulus
+@subsection modulus option (-m)
+@cindex ntp-keygen-modulus
+
+This is the ``modulus'' option.
+
+This option has some usage constraints.  It:
+@itemize @bullet
+@item
+must be compiled in by defining @code{OPENSSL} during the compilation.
+@end itemize
+
+Just some descriptive text.
+
+@node ntp-keygen pvt-cert
+@subsection pvt-cert option (-P)
+@cindex ntp-keygen-pvt-cert
+
+This is the ``generate pc private certificate'' option.
+
+This option has some usage constraints.  It:
+@itemize @bullet
+@item
+must be compiled in by defining @code{OPENSSL} during the compilation.
+@end itemize
+
+Just some descriptive text.
+
+@node ntp-keygen pvt-passwd
+@subsection pvt-passwd option (-p)
+@cindex ntp-keygen-pvt-passwd
+
+This is the ``output private password'' option.
+
+This option has some usage constraints.  It:
+@itemize @bullet
+@item
+must be compiled in by defining @code{OPENSSL} during the compilation.
+@end itemize
+
+Just some descriptive text.
+
+@node ntp-keygen get-pvt-passwd
+@subsection get-pvt-passwd option (-q)
+@cindex ntp-keygen-get-pvt-passwd
+
+This is the ``input private password'' option.
+
+This option has some usage constraints.  It:
+@itemize @bullet
+@item
+must be compiled in by defining @code{OPENSSL} during the compilation.
+@end itemize
+
+Just some descriptive text.
+
+@node ntp-keygen sign-key
+@subsection sign-key option (-S)
+@cindex ntp-keygen-sign-key
+
+This is the ``generate sign key (rsa or dsa)'' option.
+
+This option has some usage constraints.  It:
+@itemize @bullet
+@item
+must be compiled in by defining @code{OPENSSL} during the compilation.
+@end itemize
+
+Just some descriptive text.
+
+@node ntp-keygen subject-name
+@subsection subject-name option (-s)
+@cindex ntp-keygen-subject-name
+
+This is the ``set subject name'' option.
+
+This option has some usage constraints.  It:
+@itemize @bullet
+@item
+must be compiled in by defining @code{OPENSSL} during the compilation.
+@end itemize
+
+Just some descriptive text.
+
+@node ntp-keygen trusted-cert
+@subsection trusted-cert option (-T)
+@cindex ntp-keygen-trusted-cert
+
+This is the ``trusted certificate (tc scheme)'' option.
+
+This option has some usage constraints.  It:
+@itemize @bullet
+@item
+must be compiled in by defining @code{OPENSSL} during the compilation.
+@end itemize
+
+Just some descriptive text.
+
+@node ntp-keygen mv-params
+@subsection mv-params option (-V)
+@cindex ntp-keygen-mv-params
+
+This is the ``generate <num> mv parameters'' option.
+
+This option has some usage constraints.  It:
+@itemize @bullet
+@item
+must be compiled in by defining @code{OPENSSL} during the compilation.
+@end itemize
+
+Just some descriptive text.
+
+@node ntp-keygen mv-keys
+@subsection mv-keys option (-v)
+@cindex ntp-keygen-mv-keys
+
+This is the ``update <num> mv keys'' option.
+
+This option has some usage constraints.  It:
+@itemize @bullet
+@item
+must be compiled in by defining @code{OPENSSL} during the compilation.
+@end itemize
+
+Just some descriptive text.
diff --git a/util/ntp-keygen.1 b/util/ntp-keygen.1
new file mode 100644 (file)
index 0000000..7b0fe29
--- /dev/null
@@ -0,0 +1,176 @@
+.TH NTP-KEYGEN 1 2006-06-27 "" "Programmer's Manual"
+.\"  DO NOT EDIT THIS FILE   (ntp-keygen.1)
+.\"  
+.\"  It has been AutoGen-ed  Tuesday June 27, 2006 at 10:37:44 PM EDT
+.\"  From the definitions    ntp-keygen-opts.def
+.\"  and the template file   agman1.tpl
+.\"
+.SH NAME
+ntp-keygen \- Create a NTP host key
+.SH SYNOPSIS
+.B ntp-keygen
+.\" Mixture of short (flag) options and long options
+.RB [ -\fIflag\fP " [\fIvalue\fP]]... [" --\fIopt-name\fP " [[=| ]\fIvalue\fP]]..."
+.PP
+All arguments must be options.
+.SH "DESCRIPTION"
+This manual page documents, briefly, the \fBntp-keygen\fP command.
+If there is no new host key, look for an existing one.
+If one is not found, create it.
+.SH OPTIONS
+.TP
+.BR -c " \fIscheme\fP, " --certificate "=" \fIscheme\fP
+certificate scheme.
+.sp
+Just some descriptive text.
+.TP
+.BR -d ", " --debug-level
+Increase output debug message level.
+This option may appear an unlimited number of times.
+.sp
+Increase the debugging message output level.
+.TP
+.BR -D " \fIstring\fP, " --set-debug-level "=" \fIstring\fP
+Set the output debug message level.
+This option may appear an unlimited number of times.
+.sp
+Set the output debugging level.  Can be supplied multiple times,
+but each overrides the previous value(s).
+.TP
+.BR -e ", " --id-key
+Write identity keys.
+.sp
+Just some descriptive text.
+.TP
+.BR -G ", " --gq-params
+Generate GQ parameters and keys.
+.sp
+Just some descriptive text.
+.TP
+.BR -g ", " --gq-keys
+update GQ keys.
+.sp
+Just some descriptive text.
+.TP
+.BR -H ", " --host-key
+generate RSA host key.
+.sp
+Just some descriptive text.
+.TP
+.BR -I ", " --iffkey
+generate IFF parameters.
+.sp
+Just some descriptive text.
+.TP
+.BR -i ", " --issuer-name
+set issuer name.
+.sp
+Just some descriptive text.
+.TP
+.BR -M ", " --md5key
+generate MD5 keys.
+.sp
+Just some descriptive text.
+.TP
+.BR -m " \fImodulus\fP, " --modulus "=" \fImodulus\fP
+modulus.
+This option takes an integer number as its argument.
+The value of \fImodulus\fP is constrained to being:
+.in +4
+.nf
+.na
+in the range  256 through 2048
+.fi
+.in -4
+.sp
+Just some descriptive text.
+.TP
+.BR -P ", " --pvt-cert
+generate PC private certificate.
+.sp
+Just some descriptive text.
+.TP
+.BR -p " \fIpasswd\fP, " --pvt-passwd "=" \fIpasswd\fP
+output private password.
+.sp
+Just some descriptive text.
+.TP
+.BR -q " \fIpasswd\fP, " --get-pvt-passwd "=" \fIpasswd\fP
+input private password.
+.sp
+Just some descriptive text.
+.TP
+.BR -S " \fIsign\fP, " --sign-key "=" \fIsign\fP
+generate sign key (RSA or DSA).
+.sp
+Just some descriptive text.
+.TP
+.BR -s " \fIhost\fP, " --subject-name "=" \fIhost\fP
+set subject name.
+.sp
+Just some descriptive text.
+.TP
+.BR -T ", " --trusted-cert
+trusted certificate (TC scheme).
+.sp
+Just some descriptive text.
+.TP
+.BR -V " \fInum\fP, " --mv-params "=" \fInum\fP
+generate <num> MV parameters.
+This option takes an integer number as its argument.
+.sp
+Just some descriptive text.
+.TP
+.BR -v " \fInum\fP, " --mv-keys "=" \fInum\fP
+update <num> MV keys.
+This option takes an integer number as its argument.
+.sp
+Just some descriptive text.
+.TP
+.BR \-? , " \--help"
+Display usage information and exit.
+.TP
+.BR \-! , " \--more-help"
+Extended usage information passed thru pager.
+.TP
+.BR \-> " [\fIrcfile\fP]," " \--save-opts" "[=\fIrcfile\fP]"
+Save the option state to \fIrcfile\fP.  The default is the \fIlast\fP
+configuration file listed in the \fBOPTION PRESETS\fP section, below.
+.TP
+.BR \-< " \fIrcfile\fP," " \--load-opts" "=\fIrcfile\fP," " --no-load-opts"
+Load options from \fIrcfile\fP.
+The \fIno-load-opts\fP form will disable the loading
+of earlier RC/INI files.  \fI--no-load-opts\fP is handled early,
+out of order.
+.TP
+.BR \-v " [{\fIv|c|n\fP}]," " \--version" "[=\fI{v|c|n}\fP]"
+Output version of program and exit.  The default mode is `v', a simple
+version.  The `c' mode will print copyright information and `n' will
+print the full copyright notice.
+.SH OPTION PRESETS
+Any option that is not marked as \fInot presettable\fP may be preset
+by loading values from configuration ("RC" or ".INI") file(s) and values from
+environment variables named:
+.nf
+  \fBNTP_KEYGEN_<option-name>\fP or \fBNTP_KEYGEN\fP
+.fi
+.aj
+The environmental presets take precedence (are processed later than)
+the configuration files.
+The \fIhomerc\fP files are "\fI$HOME\fP", and "\fI.\fP".
+If any of these are directories, then the file \fI.ntprc\fP
+is searched for within those directories.
+.SH AUTHOR
+ntp.org
+.br
+Please send bug reports to:  http://bugs.ntp.isc.org, bugs@ntp.org
+
+.PP
+.nf
+.na
+see html/copyright.html
+.fi
+.ad
+.PP
+This manual page was \fIAutoGen\fP-erated from the \fBntp-keygen\fP
+option definitions.