Use newer gengetopt which also frees memory

Taken from http://sourceforge.net/tracker/index.php?func=detail&aid=1811521&group_id=68956&atid=522957
diff --git a/ggsn/cmdline.c b/ggsn/cmdline.c
index d8eafe5..d83376f 100644
--- a/ggsn/cmdline.c
+++ b/ggsn/cmdline.c
@@ -1,5 +1,5 @@
 /*
-  File autogenerated by gengetopt version 2.8
+  File autogenerated by gengetopt version 2.17
   generated with the following command:
   gengetopt --conf-parser 
 
@@ -8,81 +8,84 @@
   we make no copyright claims on it.
 */
 
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
 /* If we use autoconf.  */
 #ifdef HAVE_CONFIG_H
 #include "config.h"
 #endif
-/* Check for configure's getopt check result.  */
-#ifndef HAVE_GETOPT_LONG
-#include "getopt.h"
-#else
-#include <getopt.h>
-#endif
 
-#ifndef HAVE_STRDUP
-#define strdup gengetopt_strdup
-#endif /* HAVE_STRDUP */
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "getopt.h"
 
 #include "cmdline.h"
 
+const char *gengetopt_args_info_purpose = "";
 
-void
-cmdline_parser_print_version (void)
-{
-  printf ("%s %s\n", PACKAGE, VERSION);
-}
+const char *gengetopt_args_info_usage = "Usage: " CMDLINE_PARSER_PACKAGE " [OPTIONS]...";
 
-void
-cmdline_parser_print_help (void)
+const char *gengetopt_args_info_help[] = {
+  "  -h, --help             Print help and exit",
+  "  -V, --version          Print version and exit",
+  "  -f, --fg               Run in foreground  (default=off)",
+  "  -d, --debug            Run in debug mode  (default=off)",
+  "  -c, --conf=STRING      Read configuration file  (default=`/etc/ggsn.conf')",
+  "      --pidfile=STRING   Filename of process id file  \n                           (default=`/var/run/ggsn.pid')",
+  "      --statedir=STRING  Directory of nonvolatile data  \n                           (default=`/var/lib/ggsn/')",
+  "  -l, --listen=STRING    Local interface",
+  "  -n, --net=STRING       Network  (default=`192.168.0.0/24')",
+  "      --ipup=STRING      Script to run after link-up",
+  "      --ipdown=STRING    Script to run after link-down",
+  "      --dynip=STRING     Dynamic IP address pool",
+  "      --statip=STRING    Static IP address pool",
+  "      --pcodns1=STRING   PCO DNS Server 1  (default=`0.0.0.0')",
+  "      --pcodns2=STRING   PCO DNS Server 2  (default=`0.0.0.0')",
+  "      --timelimit=INT    Exit after timelimit seconds  (default=`0')",
+  "  -a, --apn=STRING       Access point name  (default=`internet')",
+  "  -q, --qos=INT          Requested quality of service  (default=`0x0b921f')",
+    0
+};
+
+static
+void clear_given (struct gengetopt_args_info *args_info);
+static
+void clear_args (struct gengetopt_args_info *args_info);
+
+static int
+cmdline_parser_internal (int argc, char * const *argv, struct gengetopt_args_info *args_info, int override, int initialize, int check_required, const char *additional_error);
+
+struct line_list
 {
-  cmdline_parser_print_version ();
-  printf("\n"
-  "Usage: %s [OPTIONS]...\n", PACKAGE);
-  printf("   -h         --help             Print help and exit\n");
-  printf("   -V         --version          Print version and exit\n");
-  printf("   -f         --fg               Run in foreground (default=off)\n");
-  printf("   -d         --debug            Run in debug mode (default=off)\n");
-  printf("   -cSTRING   --conf=STRING      Read configuration file (default='/etc/ggsn.conf')\n");
-  printf("              --pidfile=STRING   Filename of process id file (default='/var/run/ggsn.pid')\n");
-  printf("              --statedir=STRING  Directory of nonvolatile data (default='/var/lib/ggsn/')\n");
-  printf("   -lSTRING   --listen=STRING    Local interface\n");
-  printf("   -nSTRING   --net=STRING       Network (default='192.168.0.0/24')\n");
-  printf("              --ipup=STRING      Script to run after link-up\n");
-  printf("              --ipdown=STRING    Script to run after link-down\n");
-  printf("              --dynip=STRING     Dynamic IP address pool\n");
-  printf("              --statip=STRING    Static IP address pool\n");
-  printf("              --pcodns1=STRING   PCO DNS Server 1 (default='0.0.0.0')\n");
-  printf("              --pcodns2=STRING   PCO DNS Server 2 (default='0.0.0.0')\n");
-  printf("              --timelimit=INT    Exit after timelimit seconds (default='0')\n");
-  printf("   -aSTRING   --apn=STRING       Access point name (default='internet')\n");
-  printf("   -qINT      --qos=INT          Requested quality of service (default='0x0b921f')\n");
+  char * string_arg;
+  struct line_list * next;
+};
+
+static struct line_list *cmd_line_list = 0;
+static struct line_list *cmd_line_list_tmp = 0;
+
+static void
+free_cmd_list(void)
+{
+  /* free the list of a previous call */
+  if (cmd_line_list)
+    {
+      while (cmd_line_list) {
+        cmd_line_list_tmp = cmd_line_list;
+        cmd_line_list = cmd_line_list->next;
+        free (cmd_line_list_tmp->string_arg);
+        free (cmd_line_list_tmp);
+      }
+    }
 }
 
 
-#ifndef HAVE_STRDUP
-/* gengetopt_strdup(): automatically generated from strdup.c. */
-/* strdup.c replacement of strdup, which is not standard */
 static char *
-gengetopt_strdup (const char *s)
-{
-  char *result = (char*)malloc(strlen(s) + 1);
-  if (result == (char*)0)
-    return (char*)0;
-  strcpy(result, s);
-  return result;
-}
-#endif /* HAVE_STRDUP */
+gengetopt_strdup (const char *s);
 
-int
-cmdline_parser (int argc, char * const *argv, struct gengetopt_args_info *args_info)
+static
+void clear_given (struct gengetopt_args_info *args_info)
 {
-  int c;	/* Character of the parsed option.  */
-  int missing_required_options = 0;
-
   args_info->help_given = 0 ;
   args_info->version_given = 0 ;
   args_info->fg_given = 0 ;
@@ -101,29 +104,431 @@
   args_info->timelimit_given = 0 ;
   args_info->apn_given = 0 ;
   args_info->qos_given = 0 ;
-#define clear_args() { \
-  args_info->fg_flag = 0;\
-  args_info->debug_flag = 0;\
-  args_info->conf_arg = strdup("/etc/ggsn.conf") ;\
-  args_info->pidfile_arg = strdup("/var/run/ggsn.pid") ;\
-  args_info->statedir_arg = strdup("/var/lib/ggsn/") ;\
-  args_info->listen_arg = NULL; \
-  args_info->net_arg = strdup("192.168.0.0/24") ;\
-  args_info->ipup_arg = NULL; \
-  args_info->ipdown_arg = NULL; \
-  args_info->dynip_arg = NULL; \
-  args_info->statip_arg = NULL; \
-  args_info->pcodns1_arg = strdup("0.0.0.0") ;\
-  args_info->pcodns2_arg = strdup("0.0.0.0") ;\
-  args_info->timelimit_arg = 0 ;\
-  args_info->apn_arg = strdup("internet") ;\
-  args_info->qos_arg = 0x0b921f ;\
 }
 
-  clear_args();
+static
+void clear_args (struct gengetopt_args_info *args_info)
+{
+  args_info->fg_flag = 0;
+  args_info->debug_flag = 0;
+  args_info->conf_arg = gengetopt_strdup ("/etc/ggsn.conf");
+  args_info->conf_orig = NULL;
+  args_info->pidfile_arg = gengetopt_strdup ("/var/run/ggsn.pid");
+  args_info->pidfile_orig = NULL;
+  args_info->statedir_arg = gengetopt_strdup ("/var/lib/ggsn/");
+  args_info->statedir_orig = NULL;
+  args_info->listen_arg = NULL;
+  args_info->listen_orig = NULL;
+  args_info->net_arg = gengetopt_strdup ("192.168.0.0/24");
+  args_info->net_orig = NULL;
+  args_info->ipup_arg = NULL;
+  args_info->ipup_orig = NULL;
+  args_info->ipdown_arg = NULL;
+  args_info->ipdown_orig = NULL;
+  args_info->dynip_arg = NULL;
+  args_info->dynip_orig = NULL;
+  args_info->statip_arg = NULL;
+  args_info->statip_orig = NULL;
+  args_info->pcodns1_arg = gengetopt_strdup ("0.0.0.0");
+  args_info->pcodns1_orig = NULL;
+  args_info->pcodns2_arg = gengetopt_strdup ("0.0.0.0");
+  args_info->pcodns2_orig = NULL;
+  args_info->timelimit_arg = 0;
+  args_info->timelimit_orig = NULL;
+  args_info->apn_arg = gengetopt_strdup ("internet");
+  args_info->apn_orig = NULL;
+  args_info->qos_arg = 0x0b921f;
+  args_info->qos_orig = NULL;
+  
+}
+
+static
+void init_args_info(struct gengetopt_args_info *args_info)
+{
+  args_info->help_help = gengetopt_args_info_help[0] ;
+  args_info->version_help = gengetopt_args_info_help[1] ;
+  args_info->fg_help = gengetopt_args_info_help[2] ;
+  args_info->debug_help = gengetopt_args_info_help[3] ;
+  args_info->conf_help = gengetopt_args_info_help[4] ;
+  args_info->pidfile_help = gengetopt_args_info_help[5] ;
+  args_info->statedir_help = gengetopt_args_info_help[6] ;
+  args_info->listen_help = gengetopt_args_info_help[7] ;
+  args_info->net_help = gengetopt_args_info_help[8] ;
+  args_info->ipup_help = gengetopt_args_info_help[9] ;
+  args_info->ipdown_help = gengetopt_args_info_help[10] ;
+  args_info->dynip_help = gengetopt_args_info_help[11] ;
+  args_info->statip_help = gengetopt_args_info_help[12] ;
+  args_info->pcodns1_help = gengetopt_args_info_help[13] ;
+  args_info->pcodns2_help = gengetopt_args_info_help[14] ;
+  args_info->timelimit_help = gengetopt_args_info_help[15] ;
+  args_info->apn_help = gengetopt_args_info_help[16] ;
+  args_info->qos_help = gengetopt_args_info_help[17] ;
+  
+}
+
+void
+cmdline_parser_print_version (void)
+{
+  printf ("%s %s\n", CMDLINE_PARSER_PACKAGE, CMDLINE_PARSER_VERSION);
+}
+
+void
+cmdline_parser_print_help (void)
+{
+  int i = 0;
+  cmdline_parser_print_version ();
+
+  if (strlen(gengetopt_args_info_purpose) > 0)
+    printf("\n%s\n", gengetopt_args_info_purpose);
+
+  printf("\n%s\n\n", gengetopt_args_info_usage);
+  while (gengetopt_args_info_help[i])
+    printf("%s\n", gengetopt_args_info_help[i++]);
+}
+
+void
+cmdline_parser_init (struct gengetopt_args_info *args_info)
+{
+  clear_given (args_info);
+  clear_args (args_info);
+  init_args_info (args_info);
+}
+
+static void
+cmdline_parser_release (struct gengetopt_args_info *args_info)
+{
+  
+  if (args_info->conf_arg)
+    {
+      free (args_info->conf_arg); /* free previous argument */
+      args_info->conf_arg = 0;
+    }
+  if (args_info->conf_orig)
+    {
+      free (args_info->conf_orig); /* free previous argument */
+      args_info->conf_orig = 0;
+    }
+  if (args_info->pidfile_arg)
+    {
+      free (args_info->pidfile_arg); /* free previous argument */
+      args_info->pidfile_arg = 0;
+    }
+  if (args_info->pidfile_orig)
+    {
+      free (args_info->pidfile_orig); /* free previous argument */
+      args_info->pidfile_orig = 0;
+    }
+  if (args_info->statedir_arg)
+    {
+      free (args_info->statedir_arg); /* free previous argument */
+      args_info->statedir_arg = 0;
+    }
+  if (args_info->statedir_orig)
+    {
+      free (args_info->statedir_orig); /* free previous argument */
+      args_info->statedir_orig = 0;
+    }
+  if (args_info->listen_arg)
+    {
+      free (args_info->listen_arg); /* free previous argument */
+      args_info->listen_arg = 0;
+    }
+  if (args_info->listen_orig)
+    {
+      free (args_info->listen_orig); /* free previous argument */
+      args_info->listen_orig = 0;
+    }
+  if (args_info->net_arg)
+    {
+      free (args_info->net_arg); /* free previous argument */
+      args_info->net_arg = 0;
+    }
+  if (args_info->net_orig)
+    {
+      free (args_info->net_orig); /* free previous argument */
+      args_info->net_orig = 0;
+    }
+  if (args_info->ipup_arg)
+    {
+      free (args_info->ipup_arg); /* free previous argument */
+      args_info->ipup_arg = 0;
+    }
+  if (args_info->ipup_orig)
+    {
+      free (args_info->ipup_orig); /* free previous argument */
+      args_info->ipup_orig = 0;
+    }
+  if (args_info->ipdown_arg)
+    {
+      free (args_info->ipdown_arg); /* free previous argument */
+      args_info->ipdown_arg = 0;
+    }
+  if (args_info->ipdown_orig)
+    {
+      free (args_info->ipdown_orig); /* free previous argument */
+      args_info->ipdown_orig = 0;
+    }
+  if (args_info->dynip_arg)
+    {
+      free (args_info->dynip_arg); /* free previous argument */
+      args_info->dynip_arg = 0;
+    }
+  if (args_info->dynip_orig)
+    {
+      free (args_info->dynip_orig); /* free previous argument */
+      args_info->dynip_orig = 0;
+    }
+  if (args_info->statip_arg)
+    {
+      free (args_info->statip_arg); /* free previous argument */
+      args_info->statip_arg = 0;
+    }
+  if (args_info->statip_orig)
+    {
+      free (args_info->statip_orig); /* free previous argument */
+      args_info->statip_orig = 0;
+    }
+  if (args_info->pcodns1_arg)
+    {
+      free (args_info->pcodns1_arg); /* free previous argument */
+      args_info->pcodns1_arg = 0;
+    }
+  if (args_info->pcodns1_orig)
+    {
+      free (args_info->pcodns1_orig); /* free previous argument */
+      args_info->pcodns1_orig = 0;
+    }
+  if (args_info->pcodns2_arg)
+    {
+      free (args_info->pcodns2_arg); /* free previous argument */
+      args_info->pcodns2_arg = 0;
+    }
+  if (args_info->pcodns2_orig)
+    {
+      free (args_info->pcodns2_orig); /* free previous argument */
+      args_info->pcodns2_orig = 0;
+    }
+  if (args_info->timelimit_orig)
+    {
+      free (args_info->timelimit_orig); /* free previous argument */
+      args_info->timelimit_orig = 0;
+    }
+  if (args_info->apn_arg)
+    {
+      free (args_info->apn_arg); /* free previous argument */
+      args_info->apn_arg = 0;
+    }
+  if (args_info->apn_orig)
+    {
+      free (args_info->apn_orig); /* free previous argument */
+      args_info->apn_orig = 0;
+    }
+  if (args_info->qos_orig)
+    {
+      free (args_info->qos_orig); /* free previous argument */
+      args_info->qos_orig = 0;
+    }
+  
+  clear_given (args_info);
+}
+
+int
+cmdline_parser_file_save(const char *filename, struct gengetopt_args_info *args_info)
+{
+  FILE *outfile;
+  int i = 0;
+
+  outfile = fopen(filename, "w");
+
+  if (!outfile)
+    {
+      fprintf (stderr, "%s: cannot open file for writing: %s\n", CMDLINE_PARSER_PACKAGE, filename);
+      return EXIT_FAILURE;
+    }
+
+  if (args_info->help_given) {
+    fprintf(outfile, "%s\n", "help");
+  }
+  if (args_info->version_given) {
+    fprintf(outfile, "%s\n", "version");
+  }
+  if (args_info->fg_given) {
+    fprintf(outfile, "%s\n", "fg");
+  }
+  if (args_info->debug_given) {
+    fprintf(outfile, "%s\n", "debug");
+  }
+  if (args_info->conf_given) {
+    if (args_info->conf_orig) {
+      fprintf(outfile, "%s=\"%s\"\n", "conf", args_info->conf_orig);
+    } else {
+      fprintf(outfile, "%s\n", "conf");
+    }
+  }
+  if (args_info->pidfile_given) {
+    if (args_info->pidfile_orig) {
+      fprintf(outfile, "%s=\"%s\"\n", "pidfile", args_info->pidfile_orig);
+    } else {
+      fprintf(outfile, "%s\n", "pidfile");
+    }
+  }
+  if (args_info->statedir_given) {
+    if (args_info->statedir_orig) {
+      fprintf(outfile, "%s=\"%s\"\n", "statedir", args_info->statedir_orig);
+    } else {
+      fprintf(outfile, "%s\n", "statedir");
+    }
+  }
+  if (args_info->listen_given) {
+    if (args_info->listen_orig) {
+      fprintf(outfile, "%s=\"%s\"\n", "listen", args_info->listen_orig);
+    } else {
+      fprintf(outfile, "%s\n", "listen");
+    }
+  }
+  if (args_info->net_given) {
+    if (args_info->net_orig) {
+      fprintf(outfile, "%s=\"%s\"\n", "net", args_info->net_orig);
+    } else {
+      fprintf(outfile, "%s\n", "net");
+    }
+  }
+  if (args_info->ipup_given) {
+    if (args_info->ipup_orig) {
+      fprintf(outfile, "%s=\"%s\"\n", "ipup", args_info->ipup_orig);
+    } else {
+      fprintf(outfile, "%s\n", "ipup");
+    }
+  }
+  if (args_info->ipdown_given) {
+    if (args_info->ipdown_orig) {
+      fprintf(outfile, "%s=\"%s\"\n", "ipdown", args_info->ipdown_orig);
+    } else {
+      fprintf(outfile, "%s\n", "ipdown");
+    }
+  }
+  if (args_info->dynip_given) {
+    if (args_info->dynip_orig) {
+      fprintf(outfile, "%s=\"%s\"\n", "dynip", args_info->dynip_orig);
+    } else {
+      fprintf(outfile, "%s\n", "dynip");
+    }
+  }
+  if (args_info->statip_given) {
+    if (args_info->statip_orig) {
+      fprintf(outfile, "%s=\"%s\"\n", "statip", args_info->statip_orig);
+    } else {
+      fprintf(outfile, "%s\n", "statip");
+    }
+  }
+  if (args_info->pcodns1_given) {
+    if (args_info->pcodns1_orig) {
+      fprintf(outfile, "%s=\"%s\"\n", "pcodns1", args_info->pcodns1_orig);
+    } else {
+      fprintf(outfile, "%s\n", "pcodns1");
+    }
+  }
+  if (args_info->pcodns2_given) {
+    if (args_info->pcodns2_orig) {
+      fprintf(outfile, "%s=\"%s\"\n", "pcodns2", args_info->pcodns2_orig);
+    } else {
+      fprintf(outfile, "%s\n", "pcodns2");
+    }
+  }
+  if (args_info->timelimit_given) {
+    if (args_info->timelimit_orig) {
+      fprintf(outfile, "%s=\"%s\"\n", "timelimit", args_info->timelimit_orig);
+    } else {
+      fprintf(outfile, "%s\n", "timelimit");
+    }
+  }
+  if (args_info->apn_given) {
+    if (args_info->apn_orig) {
+      fprintf(outfile, "%s=\"%s\"\n", "apn", args_info->apn_orig);
+    } else {
+      fprintf(outfile, "%s\n", "apn");
+    }
+  }
+  if (args_info->qos_given) {
+    if (args_info->qos_orig) {
+      fprintf(outfile, "%s=\"%s\"\n", "qos", args_info->qos_orig);
+    } else {
+      fprintf(outfile, "%s\n", "qos");
+    }
+  }
+  
+  fclose (outfile);
+
+  i = EXIT_SUCCESS;
+  return i;
+}
+
+void
+cmdline_parser_free (struct gengetopt_args_info *args_info)
+{
+  cmdline_parser_release (args_info);
+}
+
+
+/* gengetopt_strdup() */
+/* strdup.c replacement of strdup, which is not standard */
+char *
+gengetopt_strdup (const char *s)
+{
+  char *result = NULL;
+  if (!s)
+    return result;
+
+  result = (char*)malloc(strlen(s) + 1);
+  if (result == (char*)0)
+    return (char*)0;
+  strcpy(result, s);
+  return result;
+}
+
+int
+cmdline_parser (int argc, char * const *argv, struct gengetopt_args_info *args_info)
+{
+  return cmdline_parser2 (argc, argv, args_info, 0, 1, 1);
+}
+
+int
+cmdline_parser2 (int argc, char * const *argv, struct gengetopt_args_info *args_info, int override, int initialize, int check_required)
+{
+  int result;
+
+  result = cmdline_parser_internal (argc, argv, args_info, override, initialize, check_required, NULL);
+
+  if (result == EXIT_FAILURE)
+    {
+      cmdline_parser_free (args_info);
+      exit (EXIT_FAILURE);
+    }
+  
+  return result;
+}
+
+int
+cmdline_parser_required (struct gengetopt_args_info *args_info, const char *prog_name)
+{
+  return EXIT_SUCCESS;
+}
+
+int
+cmdline_parser_internal (int argc, char * const *argv, struct gengetopt_args_info *args_info, int override, int initialize, int check_required, const char *additional_error)
+{
+  int c;	/* Character of the parsed option.  */
+
+  int error = 0;
+  struct gengetopt_args_info local_args_info;
+
+  if (initialize)
+    cmdline_parser_init (args_info);
+
+  cmdline_parser_init (&local_args_info);
 
   optarg = 0;
-  optind = 1;
+  optind = 0;
   opterr = 1;
   optopt = '?';
 
@@ -131,6 +536,7 @@
     {
       int option_index = 0;
       char *stop_char;
+
       static struct option long_options[] = {
         { "help",	0, NULL, 'h' },
         { "version",	0, NULL, 'V' },
@@ -153,6 +559,7 @@
         { NULL,	0, NULL, 0 }
       };
 
+      stop_char = 0;
       c = getopt_long (argc, argv, "hVfdc:l:n:a:q:", long_options, &option_index);
 
       if (c == -1) break;	/* Exit from `while (1)' loop.  */
@@ -160,90 +567,131 @@
       switch (c)
         {
         case 'h':	/* Print help and exit.  */
-          clear_args ();
           cmdline_parser_print_help ();
+          cmdline_parser_free (&local_args_info);
           exit (EXIT_SUCCESS);
 
         case 'V':	/* Print version and exit.  */
-          clear_args ();
           cmdline_parser_print_version ();
+          cmdline_parser_free (&local_args_info);
           exit (EXIT_SUCCESS);
 
         case 'f':	/* Run in foreground.  */
-          if (args_info->fg_given)
+          if (local_args_info.fg_given)
             {
-              fprintf (stderr, "%s: `--fg' (`-f') option given more than once\n", PACKAGE);
-              clear_args ();
-              exit (EXIT_FAILURE);
+              fprintf (stderr, "%s: `--fg' (`-f') option given more than once%s\n", argv[0], (additional_error ? additional_error : ""));
+              goto failure;
             }
+          if (args_info->fg_given && ! override)
+            continue;
+          local_args_info.fg_given = 1;
           args_info->fg_given = 1;
           args_info->fg_flag = !(args_info->fg_flag);
           break;
 
         case 'd':	/* Run in debug mode.  */
-          if (args_info->debug_given)
+          if (local_args_info.debug_given)
             {
-              fprintf (stderr, "%s: `--debug' (`-d') option given more than once\n", PACKAGE);
-              clear_args ();
-              exit (EXIT_FAILURE);
+              fprintf (stderr, "%s: `--debug' (`-d') option given more than once%s\n", argv[0], (additional_error ? additional_error : ""));
+              goto failure;
             }
+          if (args_info->debug_given && ! override)
+            continue;
+          local_args_info.debug_given = 1;
           args_info->debug_given = 1;
           args_info->debug_flag = !(args_info->debug_flag);
           break;
 
         case 'c':	/* Read configuration file.  */
-          if (args_info->conf_given)
+          if (local_args_info.conf_given)
             {
-              fprintf (stderr, "%s: `--conf' (`-c') option given more than once\n", PACKAGE);
-              clear_args ();
-              exit (EXIT_FAILURE);
+              fprintf (stderr, "%s: `--conf' (`-c') option given more than once%s\n", argv[0], (additional_error ? additional_error : ""));
+              goto failure;
             }
+          if (args_info->conf_given && ! override)
+            continue;
+          local_args_info.conf_given = 1;
           args_info->conf_given = 1;
-          args_info->conf_arg = strdup (optarg);
+          if (args_info->conf_arg)
+            free (args_info->conf_arg); /* free previous string */
+          args_info->conf_arg = gengetopt_strdup (optarg);
+          if (args_info->conf_orig)
+            free (args_info->conf_orig); /* free previous string */
+          args_info->conf_orig = gengetopt_strdup (optarg);
           break;
 
         case 'l':	/* Local interface.  */
-          if (args_info->listen_given)
+          if (local_args_info.listen_given)
             {
-              fprintf (stderr, "%s: `--listen' (`-l') option given more than once\n", PACKAGE);
-              clear_args ();
-              exit (EXIT_FAILURE);
+              fprintf (stderr, "%s: `--listen' (`-l') option given more than once%s\n", argv[0], (additional_error ? additional_error : ""));
+              goto failure;
             }
+          if (args_info->listen_given && ! override)
+            continue;
+          local_args_info.listen_given = 1;
           args_info->listen_given = 1;
-          args_info->listen_arg = strdup (optarg);
+          if (args_info->listen_arg)
+            free (args_info->listen_arg); /* free previous string */
+          args_info->listen_arg = gengetopt_strdup (optarg);
+          if (args_info->listen_orig)
+            free (args_info->listen_orig); /* free previous string */
+          args_info->listen_orig = gengetopt_strdup (optarg);
           break;
 
         case 'n':	/* Network.  */
-          if (args_info->net_given)
+          if (local_args_info.net_given)
             {
-              fprintf (stderr, "%s: `--net' (`-n') option given more than once\n", PACKAGE);
-              clear_args ();
-              exit (EXIT_FAILURE);
+              fprintf (stderr, "%s: `--net' (`-n') option given more than once%s\n", argv[0], (additional_error ? additional_error : ""));
+              goto failure;
             }
+          if (args_info->net_given && ! override)
+            continue;
+          local_args_info.net_given = 1;
           args_info->net_given = 1;
-          args_info->net_arg = strdup (optarg);
+          if (args_info->net_arg)
+            free (args_info->net_arg); /* free previous string */
+          args_info->net_arg = gengetopt_strdup (optarg);
+          if (args_info->net_orig)
+            free (args_info->net_orig); /* free previous string */
+          args_info->net_orig = gengetopt_strdup (optarg);
           break;
 
         case 'a':	/* Access point name.  */
-          if (args_info->apn_given)
+          if (local_args_info.apn_given)
             {
-              fprintf (stderr, "%s: `--apn' (`-a') option given more than once\n", PACKAGE);
-              clear_args ();
-              exit (EXIT_FAILURE);
+              fprintf (stderr, "%s: `--apn' (`-a') option given more than once%s\n", argv[0], (additional_error ? additional_error : ""));
+              goto failure;
             }
+          if (args_info->apn_given && ! override)
+            continue;
+          local_args_info.apn_given = 1;
           args_info->apn_given = 1;
-          args_info->apn_arg = strdup (optarg);
+          if (args_info->apn_arg)
+            free (args_info->apn_arg); /* free previous string */
+          args_info->apn_arg = gengetopt_strdup (optarg);
+          if (args_info->apn_orig)
+            free (args_info->apn_orig); /* free previous string */
+          args_info->apn_orig = gengetopt_strdup (optarg);
           break;
 
         case 'q':	/* Requested quality of service.  */
-          if (args_info->qos_given)
+          if (local_args_info.qos_given)
             {
-              fprintf (stderr, "%s: `--qos' (`-q') option given more than once\n", PACKAGE);
-              clear_args ();
-              exit (EXIT_FAILURE);
+              fprintf (stderr, "%s: `--qos' (`-q') option given more than once%s\n", argv[0], (additional_error ? additional_error : ""));
+              goto failure;
             }
+          if (args_info->qos_given && ! override)
+            continue;
+          local_args_info.qos_given = 1;
           args_info->qos_given = 1;
-          args_info->qos_arg = strtol (optarg,&stop_char,0);
+          args_info->qos_arg = strtol (optarg, &stop_char, 0);
+          if (!(stop_char && *stop_char == '\0')) {
+            fprintf(stderr, "%s: invalid numeric value: %s\n", argv[0], optarg);
+            goto failure;
+          }
+          if (args_info->qos_orig)
+            free (args_info->qos_orig); /* free previous string */
+          args_info->qos_orig = gengetopt_strdup (optarg);
           break;
 
 
@@ -251,444 +699,374 @@
           /* Filename of process id file.  */
           if (strcmp (long_options[option_index].name, "pidfile") == 0)
           {
-            if (args_info->pidfile_given)
+            if (local_args_info.pidfile_given)
               {
-                fprintf (stderr, "%s: `--pidfile' option given more than once\n", PACKAGE);
-                clear_args ();
-                exit (EXIT_FAILURE);
+                fprintf (stderr, "%s: `--pidfile' option given more than once%s\n", argv[0], (additional_error ? additional_error : ""));
+                goto failure;
               }
+            if (args_info->pidfile_given && ! override)
+              continue;
+            local_args_info.pidfile_given = 1;
             args_info->pidfile_given = 1;
-            args_info->pidfile_arg = strdup (optarg);
-            break;
+            if (args_info->pidfile_arg)
+              free (args_info->pidfile_arg); /* free previous string */
+            args_info->pidfile_arg = gengetopt_strdup (optarg);
+            if (args_info->pidfile_orig)
+              free (args_info->pidfile_orig); /* free previous string */
+            args_info->pidfile_orig = gengetopt_strdup (optarg);
           }
           /* Directory of nonvolatile data.  */
           else if (strcmp (long_options[option_index].name, "statedir") == 0)
           {
-            if (args_info->statedir_given)
+            if (local_args_info.statedir_given)
               {
-                fprintf (stderr, "%s: `--statedir' option given more than once\n", PACKAGE);
-                clear_args ();
-                exit (EXIT_FAILURE);
+                fprintf (stderr, "%s: `--statedir' option given more than once%s\n", argv[0], (additional_error ? additional_error : ""));
+                goto failure;
               }
+            if (args_info->statedir_given && ! override)
+              continue;
+            local_args_info.statedir_given = 1;
             args_info->statedir_given = 1;
-            args_info->statedir_arg = strdup (optarg);
-            break;
+            if (args_info->statedir_arg)
+              free (args_info->statedir_arg); /* free previous string */
+            args_info->statedir_arg = gengetopt_strdup (optarg);
+            if (args_info->statedir_orig)
+              free (args_info->statedir_orig); /* free previous string */
+            args_info->statedir_orig = gengetopt_strdup (optarg);
           }
           /* Script to run after link-up.  */
           else if (strcmp (long_options[option_index].name, "ipup") == 0)
           {
-            if (args_info->ipup_given)
+            if (local_args_info.ipup_given)
               {
-                fprintf (stderr, "%s: `--ipup' option given more than once\n", PACKAGE);
-                clear_args ();
-                exit (EXIT_FAILURE);
+                fprintf (stderr, "%s: `--ipup' option given more than once%s\n", argv[0], (additional_error ? additional_error : ""));
+                goto failure;
               }
+            if (args_info->ipup_given && ! override)
+              continue;
+            local_args_info.ipup_given = 1;
             args_info->ipup_given = 1;
-            args_info->ipup_arg = strdup (optarg);
-            break;
+            if (args_info->ipup_arg)
+              free (args_info->ipup_arg); /* free previous string */
+            args_info->ipup_arg = gengetopt_strdup (optarg);
+            if (args_info->ipup_orig)
+              free (args_info->ipup_orig); /* free previous string */
+            args_info->ipup_orig = gengetopt_strdup (optarg);
           }
           /* Script to run after link-down.  */
           else if (strcmp (long_options[option_index].name, "ipdown") == 0)
           {
-            if (args_info->ipdown_given)
+            if (local_args_info.ipdown_given)
               {
-                fprintf (stderr, "%s: `--ipdown' option given more than once\n", PACKAGE);
-                clear_args ();
-                exit (EXIT_FAILURE);
+                fprintf (stderr, "%s: `--ipdown' option given more than once%s\n", argv[0], (additional_error ? additional_error : ""));
+                goto failure;
               }
+            if (args_info->ipdown_given && ! override)
+              continue;
+            local_args_info.ipdown_given = 1;
             args_info->ipdown_given = 1;
-            args_info->ipdown_arg = strdup (optarg);
-            break;
+            if (args_info->ipdown_arg)
+              free (args_info->ipdown_arg); /* free previous string */
+            args_info->ipdown_arg = gengetopt_strdup (optarg);
+            if (args_info->ipdown_orig)
+              free (args_info->ipdown_orig); /* free previous string */
+            args_info->ipdown_orig = gengetopt_strdup (optarg);
           }
           /* Dynamic IP address pool.  */
           else if (strcmp (long_options[option_index].name, "dynip") == 0)
           {
-            if (args_info->dynip_given)
+            if (local_args_info.dynip_given)
               {
-                fprintf (stderr, "%s: `--dynip' option given more than once\n", PACKAGE);
-                clear_args ();
-                exit (EXIT_FAILURE);
+                fprintf (stderr, "%s: `--dynip' option given more than once%s\n", argv[0], (additional_error ? additional_error : ""));
+                goto failure;
               }
+            if (args_info->dynip_given && ! override)
+              continue;
+            local_args_info.dynip_given = 1;
             args_info->dynip_given = 1;
-            args_info->dynip_arg = strdup (optarg);
-            break;
+            if (args_info->dynip_arg)
+              free (args_info->dynip_arg); /* free previous string */
+            args_info->dynip_arg = gengetopt_strdup (optarg);
+            if (args_info->dynip_orig)
+              free (args_info->dynip_orig); /* free previous string */
+            args_info->dynip_orig = gengetopt_strdup (optarg);
           }
           /* Static IP address pool.  */
           else if (strcmp (long_options[option_index].name, "statip") == 0)
           {
-            if (args_info->statip_given)
+            if (local_args_info.statip_given)
               {
-                fprintf (stderr, "%s: `--statip' option given more than once\n", PACKAGE);
-                clear_args ();
-                exit (EXIT_FAILURE);
+                fprintf (stderr, "%s: `--statip' option given more than once%s\n", argv[0], (additional_error ? additional_error : ""));
+                goto failure;
               }
+            if (args_info->statip_given && ! override)
+              continue;
+            local_args_info.statip_given = 1;
             args_info->statip_given = 1;
-            args_info->statip_arg = strdup (optarg);
-            break;
+            if (args_info->statip_arg)
+              free (args_info->statip_arg); /* free previous string */
+            args_info->statip_arg = gengetopt_strdup (optarg);
+            if (args_info->statip_orig)
+              free (args_info->statip_orig); /* free previous string */
+            args_info->statip_orig = gengetopt_strdup (optarg);
           }
           /* PCO DNS Server 1.  */
           else if (strcmp (long_options[option_index].name, "pcodns1") == 0)
           {
-            if (args_info->pcodns1_given)
+            if (local_args_info.pcodns1_given)
               {
-                fprintf (stderr, "%s: `--pcodns1' option given more than once\n", PACKAGE);
-                clear_args ();
-                exit (EXIT_FAILURE);
+                fprintf (stderr, "%s: `--pcodns1' option given more than once%s\n", argv[0], (additional_error ? additional_error : ""));
+                goto failure;
               }
+            if (args_info->pcodns1_given && ! override)
+              continue;
+            local_args_info.pcodns1_given = 1;
             args_info->pcodns1_given = 1;
-            args_info->pcodns1_arg = strdup (optarg);
-            break;
+            if (args_info->pcodns1_arg)
+              free (args_info->pcodns1_arg); /* free previous string */
+            args_info->pcodns1_arg = gengetopt_strdup (optarg);
+            if (args_info->pcodns1_orig)
+              free (args_info->pcodns1_orig); /* free previous string */
+            args_info->pcodns1_orig = gengetopt_strdup (optarg);
           }
           /* PCO DNS Server 2.  */
           else if (strcmp (long_options[option_index].name, "pcodns2") == 0)
           {
-            if (args_info->pcodns2_given)
+            if (local_args_info.pcodns2_given)
               {
-                fprintf (stderr, "%s: `--pcodns2' option given more than once\n", PACKAGE);
-                clear_args ();
-                exit (EXIT_FAILURE);
+                fprintf (stderr, "%s: `--pcodns2' option given more than once%s\n", argv[0], (additional_error ? additional_error : ""));
+                goto failure;
               }
+            if (args_info->pcodns2_given && ! override)
+              continue;
+            local_args_info.pcodns2_given = 1;
             args_info->pcodns2_given = 1;
-            args_info->pcodns2_arg = strdup (optarg);
-            break;
+            if (args_info->pcodns2_arg)
+              free (args_info->pcodns2_arg); /* free previous string */
+            args_info->pcodns2_arg = gengetopt_strdup (optarg);
+            if (args_info->pcodns2_orig)
+              free (args_info->pcodns2_orig); /* free previous string */
+            args_info->pcodns2_orig = gengetopt_strdup (optarg);
           }
           /* Exit after timelimit seconds.  */
           else if (strcmp (long_options[option_index].name, "timelimit") == 0)
           {
-            if (args_info->timelimit_given)
+            if (local_args_info.timelimit_given)
               {
-                fprintf (stderr, "%s: `--timelimit' option given more than once\n", PACKAGE);
-                clear_args ();
-                exit (EXIT_FAILURE);
+                fprintf (stderr, "%s: `--timelimit' option given more than once%s\n", argv[0], (additional_error ? additional_error : ""));
+                goto failure;
               }
+            if (args_info->timelimit_given && ! override)
+              continue;
+            local_args_info.timelimit_given = 1;
             args_info->timelimit_given = 1;
-            args_info->timelimit_arg = strtol (optarg,&stop_char,0);
-            break;
+            args_info->timelimit_arg = strtol (optarg, &stop_char, 0);
+            if (!(stop_char && *stop_char == '\0')) {
+              fprintf(stderr, "%s: invalid numeric value: %s\n", argv[0], optarg);
+              goto failure;
+            }
+            if (args_info->timelimit_orig)
+              free (args_info->timelimit_orig); /* free previous string */
+            args_info->timelimit_orig = gengetopt_strdup (optarg);
           }
-
+          
+          break;
         case '?':	/* Invalid option.  */
           /* `getopt_long' already printed an error message.  */
-          exit (EXIT_FAILURE);
+          goto failure;
 
         default:	/* bug: option not considered.  */
-          fprintf (stderr, "%s: option unknown: %c\n", PACKAGE, c);
+          fprintf (stderr, "%s: option unknown: %c%s\n", CMDLINE_PARSER_PACKAGE, c, (additional_error ? additional_error : ""));
           abort ();
         } /* switch */
     } /* while */
 
 
-  if ( missing_required_options )
-    exit (EXIT_FAILURE);
+
+
+  cmdline_parser_release (&local_args_info);
+
+  if ( error )
+    return (EXIT_FAILURE);
 
   return 0;
+
+failure:
+  
+  cmdline_parser_release (&local_args_info);
+  return (EXIT_FAILURE);
 }
 
-#define CONFIGPARSERBUFSIZE 1024
+#ifndef CONFIG_FILE_LINE_SIZE
+#define CONFIG_FILE_LINE_SIZE 2048
+#endif
+#define ADDITIONAL_ERROR " in configuration file "
+
+#define CONFIG_FILE_LINE_BUFFER_SIZE (CONFIG_FILE_LINE_SIZE+3)
+/* 3 is for "--" and "=" */
+
+char my_argv[CONFIG_FILE_LINE_BUFFER_SIZE+1];
 
 int
-cmdline_parser_configfile (char * const filename, struct gengetopt_args_info *args_info, int override)
+cmdline_parser_configfile (char * const filename, struct gengetopt_args_info *args_info, int override, int initialize, int check_required)
 {
   FILE* file;
-  char linebuf[CONFIGPARSERBUFSIZE];
+  char linebuf[CONFIG_FILE_LINE_SIZE];
   int line_num = 0;
-  int len;
-  int fnum;
-  char fopt[CONFIGPARSERBUFSIZE], farg[CONFIGPARSERBUFSIZE];
-  char *stop_char;
+  int i, result, equal;
+  char *fopt, *farg;
+  char *str_index;
+  size_t len, next_token;
+  char delimiter;
+  int my_argc = 0;
+  char **my_argv_arg;
+  char *additional_error;
+
+  /* store the program name */
+  cmd_line_list_tmp = (struct line_list *) malloc (sizeof (struct line_list));
+  cmd_line_list_tmp->next = cmd_line_list;
+  cmd_line_list = cmd_line_list_tmp;
+  cmd_line_list->string_arg = gengetopt_strdup (CMDLINE_PARSER_PACKAGE);
 
   if ((file = fopen(filename, "r")) == NULL)
     {
       fprintf (stderr, "%s: Error opening configuration file '%s'\n",
-               PACKAGE, filename);
-      exit (EXIT_FAILURE);
+               CMDLINE_PARSER_PACKAGE, filename);
+      result = EXIT_FAILURE;
+      goto conf_failure;
     }
 
-  while ((fgets(linebuf, CONFIGPARSERBUFSIZE, file)) != NULL)
+  while ((fgets(linebuf, CONFIG_FILE_LINE_SIZE, file)) != NULL)
     {
       ++line_num;
+      my_argv[0] = '\0';
       len = strlen(linebuf);
-      if (len == CONFIGPARSERBUFSIZE-1)
+      if (len > (CONFIG_FILE_LINE_BUFFER_SIZE-1))
         {
-          fprintf (stderr, "%s: Line longer than %d characters found in configuration file '%s'\n",
-                   PACKAGE, CONFIGPARSERBUFSIZE, filename);
-          exit (EXIT_FAILURE);
+          fprintf (stderr, "%s:%s:%d: Line too long in configuration file\n",
+                   CMDLINE_PARSER_PACKAGE, filename, line_num);
+          result = EXIT_FAILURE;
+          goto conf_failure;
         }
 
-      if (linebuf[0] == '#')
-        continue; /* Line was a comment */
-    
-      /* Get the option */
-      if ((fnum = sscanf(linebuf, "%s %s", fopt, farg)) > 0)
-        {
-          if (!strcmp(fopt, "help"))
-            {
-              if (override || !args_info->help_given)
-                {
-                  args_info->help_given = 1;
-                  
-                }
-              continue;
-            }
-          if (!strcmp(fopt, "version"))
-            {
-              if (override || !args_info->version_given)
-                {
-                  args_info->version_given = 1;
-                  
-                }
-              continue;
-            }
-          if (!strcmp(fopt, "fg"))
-            {
-              if (override || !args_info->fg_given)
-                {
-                  args_info->fg_given = 1;
-                  args_info->fg_flag = !(args_info->fg_flag);
-                }
-              continue;
-            }
-          if (!strcmp(fopt, "debug"))
-            {
-              if (override || !args_info->debug_given)
-                {
-                  args_info->debug_given = 1;
-                  args_info->debug_flag = !(args_info->debug_flag);
-                }
-              continue;
-            }
-          if (!strcmp(fopt, "conf"))
-            {
-              if (override || !args_info->conf_given)
-                {
-                  args_info->conf_given = 1;
-                  if (fnum == 2)
-                    args_info->conf_arg = strdup (farg);
-                  else
-                    {
-                      fprintf (stderr, "%s:%d: required <option_name> <option_val>\n",
-                               filename, line_num);
-                      exit (EXIT_FAILURE);
-                    }
-                }
-              continue;
-            }
-          if (!strcmp(fopt, "pidfile"))
-            {
-              if (override || !args_info->pidfile_given)
-                {
-                  args_info->pidfile_given = 1;
-                  if (fnum == 2)
-                    args_info->pidfile_arg = strdup (farg);
-                  else
-                    {
-                      fprintf (stderr, "%s:%d: required <option_name> <option_val>\n",
-                               filename, line_num);
-                      exit (EXIT_FAILURE);
-                    }
-                }
-              continue;
-            }
-          if (!strcmp(fopt, "statedir"))
-            {
-              if (override || !args_info->statedir_given)
-                {
-                  args_info->statedir_given = 1;
-                  if (fnum == 2)
-                    args_info->statedir_arg = strdup (farg);
-                  else
-                    {
-                      fprintf (stderr, "%s:%d: required <option_name> <option_val>\n",
-                               filename, line_num);
-                      exit (EXIT_FAILURE);
-                    }
-                }
-              continue;
-            }
-          if (!strcmp(fopt, "listen"))
-            {
-              if (override || !args_info->listen_given)
-                {
-                  args_info->listen_given = 1;
-                  if (fnum == 2)
-                    args_info->listen_arg = strdup (farg);
-                  else
-                    {
-                      fprintf (stderr, "%s:%d: required <option_name> <option_val>\n",
-                               filename, line_num);
-                      exit (EXIT_FAILURE);
-                    }
-                }
-              continue;
-            }
-          if (!strcmp(fopt, "net"))
-            {
-              if (override || !args_info->net_given)
-                {
-                  args_info->net_given = 1;
-                  if (fnum == 2)
-                    args_info->net_arg = strdup (farg);
-                  else
-                    {
-                      fprintf (stderr, "%s:%d: required <option_name> <option_val>\n",
-                               filename, line_num);
-                      exit (EXIT_FAILURE);
-                    }
-                }
-              continue;
-            }
-          if (!strcmp(fopt, "ipup"))
-            {
-              if (override || !args_info->ipup_given)
-                {
-                  args_info->ipup_given = 1;
-                  if (fnum == 2)
-                    args_info->ipup_arg = strdup (farg);
-                  else
-                    {
-                      fprintf (stderr, "%s:%d: required <option_name> <option_val>\n",
-                               filename, line_num);
-                      exit (EXIT_FAILURE);
-                    }
-                }
-              continue;
-            }
-          if (!strcmp(fopt, "ipdown"))
-            {
-              if (override || !args_info->ipdown_given)
-                {
-                  args_info->ipdown_given = 1;
-                  if (fnum == 2)
-                    args_info->ipdown_arg = strdup (farg);
-                  else
-                    {
-                      fprintf (stderr, "%s:%d: required <option_name> <option_val>\n",
-                               filename, line_num);
-                      exit (EXIT_FAILURE);
-                    }
-                }
-              continue;
-            }
-          if (!strcmp(fopt, "dynip"))
-            {
-              if (override || !args_info->dynip_given)
-                {
-                  args_info->dynip_given = 1;
-                  if (fnum == 2)
-                    args_info->dynip_arg = strdup (farg);
-                  else
-                    {
-                      fprintf (stderr, "%s:%d: required <option_name> <option_val>\n",
-                               filename, line_num);
-                      exit (EXIT_FAILURE);
-                    }
-                }
-              continue;
-            }
-          if (!strcmp(fopt, "statip"))
-            {
-              if (override || !args_info->statip_given)
-                {
-                  args_info->statip_given = 1;
-                  if (fnum == 2)
-                    args_info->statip_arg = strdup (farg);
-                  else
-                    {
-                      fprintf (stderr, "%s:%d: required <option_name> <option_val>\n",
-                               filename, line_num);
-                      exit (EXIT_FAILURE);
-                    }
-                }
-              continue;
-            }
-          if (!strcmp(fopt, "pcodns1"))
-            {
-              if (override || !args_info->pcodns1_given)
-                {
-                  args_info->pcodns1_given = 1;
-                  if (fnum == 2)
-                    args_info->pcodns1_arg = strdup (farg);
-                  else
-                    {
-                      fprintf (stderr, "%s:%d: required <option_name> <option_val>\n",
-                               filename, line_num);
-                      exit (EXIT_FAILURE);
-                    }
-                }
-              continue;
-            }
-          if (!strcmp(fopt, "pcodns2"))
-            {
-              if (override || !args_info->pcodns2_given)
-                {
-                  args_info->pcodns2_given = 1;
-                  if (fnum == 2)
-                    args_info->pcodns2_arg = strdup (farg);
-                  else
-                    {
-                      fprintf (stderr, "%s:%d: required <option_name> <option_val>\n",
-                               filename, line_num);
-                      exit (EXIT_FAILURE);
-                    }
-                }
-              continue;
-            }
-          if (!strcmp(fopt, "timelimit"))
-            {
-              if (override || !args_info->timelimit_given)
-                {
-                  args_info->timelimit_given = 1;
-                  if (fnum == 2)
-                    args_info->timelimit_arg = strtol (farg,&stop_char,0);
-                  else
-                    {
-                      fprintf (stderr, "%s:%d: required <option_name> <option_val>\n",
-                               filename, line_num);
-                      exit (EXIT_FAILURE);
-                    }
-                }
-              continue;
-            }
-          if (!strcmp(fopt, "apn"))
-            {
-              if (override || !args_info->apn_given)
-                {
-                  args_info->apn_given = 1;
-                  if (fnum == 2)
-                    args_info->apn_arg = strdup (farg);
-                  else
-                    {
-                      fprintf (stderr, "%s:%d: required <option_name> <option_val>\n",
-                               filename, line_num);
-                      exit (EXIT_FAILURE);
-                    }
-                }
-              continue;
-            }
-          if (!strcmp(fopt, "qos"))
-            {
-              if (override || !args_info->qos_given)
-                {
-                  args_info->qos_given = 1;
-                  if (fnum == 2)
-                    args_info->qos_arg = strtol (farg,&stop_char,0);
-                  else
-                    {
-                      fprintf (stderr, "%s:%d: required <option_name> <option_val>\n",
-                               filename, line_num);
-                      exit (EXIT_FAILURE);
-                    }
-                }
-              continue;
-            }
-          
+      /* find first non-whitespace character in the line */
+      next_token = strspn ( linebuf, " \t\r\n");
+      str_index  = linebuf + next_token;
 
-          /* Tried all known options. This one is unknown! */
-          fprintf (stderr, "%s: Unknown option '%s' found in %s\n",
-                   PACKAGE, fopt, filename);
-          exit (EXIT_FAILURE);
+      if ( str_index[0] == '\0' || str_index[0] == '#')
+        continue; /* empty line or comment line is skipped */
+
+      fopt = str_index;
+
+      /* truncate fopt at the end of the first non-valid character */
+      next_token = strcspn (fopt, " \t\r\n=");
+
+      if (fopt[next_token] == '\0') /* the line is over */
+        {
+          farg  = NULL;
+          equal = 0;
+          goto noarg;
         }
+
+      /* remember if equal sign is present */
+      equal = (fopt[next_token] == '=');
+      fopt[next_token++] = '\0';
+
+      /* advance pointers to the next token after the end of fopt */
+      next_token += strspn (fopt + next_token, " \t\r\n");
+      /* check for the presence of equal sign, and if so, skip it */
+      if ( !equal )
+        if ((equal = (fopt[next_token] == '=')))
+          {
+            next_token++;
+            next_token += strspn (fopt + next_token, " \t\r\n");
+          }
+      str_index  += next_token;
+
+      /* find argument */
+      farg = str_index;
+      if ( farg[0] == '\"' || farg[0] == '\'' )
+        { /* quoted argument */
+          str_index = strchr (++farg, str_index[0] ); /* skip opening quote */
+          if (! str_index)
+            {
+              fprintf
+                (stderr,
+                 "%s:%s:%d: unterminated string in configuration file\n",
+                 CMDLINE_PARSER_PACKAGE, filename, line_num);
+              result = EXIT_FAILURE;
+              goto conf_failure;
+            }
+        }
+      else
+        { /* read up the remaining part up to a delimiter */
+          next_token = strcspn (farg, " \t\r\n#\'\"");
+          str_index += next_token;
+        }
+
+      /* truncate farg at the delimiter and store it for further check */
+      delimiter = *str_index, *str_index++ = '\0';
+
+      /* everything but comment is illegal at the end of line */
+      if (delimiter != '\0' && delimiter != '#')
+        {
+          str_index += strspn(str_index, " \t\r\n");
+          if (*str_index != '\0' && *str_index != '#')
+            {
+              fprintf
+                (stderr,
+                 "%s:%s:%d: malformed string in configuration file\n",
+                 CMDLINE_PARSER_PACKAGE, filename, line_num);
+              result = EXIT_FAILURE;
+              goto conf_failure;
+            }
+        }
+
+    noarg:
+      ++my_argc;
+      len = strlen(fopt);
+
+      strcat (my_argv, len > 1 ? "--" : "-");
+      strcat (my_argv, fopt);
+      if (len > 1 && ((farg &&*farg) || equal))
+          strcat (my_argv, "=");
+      if (farg && *farg)
+          strcat (my_argv, farg);
+
+      cmd_line_list_tmp = (struct line_list *) malloc (sizeof (struct line_list));
+      cmd_line_list_tmp->next = cmd_line_list;
+      cmd_line_list = cmd_line_list_tmp;
+      cmd_line_list->string_arg = gengetopt_strdup(my_argv);
     } /* while */
-  fclose(file); /* No error checking on close */
 
-  return 0;
+  ++my_argc; /* for program name */
+  my_argv_arg = (char **) malloc((my_argc+1) * sizeof(char *));
+  cmd_line_list_tmp = cmd_line_list;
+  for (i = my_argc - 1; i >= 0; --i) {
+    my_argv_arg[i] = cmd_line_list_tmp->string_arg;
+    cmd_line_list_tmp = cmd_line_list_tmp->next;
+  }
+  my_argv_arg[my_argc] = 0;
+
+  additional_error = (char *)malloc(strlen(filename) + strlen(ADDITIONAL_ERROR) + 1);
+  strcpy (additional_error, ADDITIONAL_ERROR);
+  strcat (additional_error, filename);
+  result =
+    cmdline_parser_internal (my_argc, my_argv_arg, args_info, override, initialize, check_required, additional_error);
+
+  free (additional_error);
+  free (my_argv_arg);
+
+conf_failure:
+  if (file)
+    fclose(file);
+
+  free_cmd_list();
+  if (result == EXIT_FAILURE)
+    {
+      cmdline_parser_free (args_info);
+      exit (EXIT_FAILURE);
+    }
+  
+  return result;
 }
diff --git a/ggsn/cmdline.h b/ggsn/cmdline.h
index f083dbe..d9e3086 100644
--- a/ggsn/cmdline.h
+++ b/ggsn/cmdline.h
@@ -1,42 +1,78 @@
 /* cmdline.h */
 
-/* File autogenerated by gengetopt version 2.8  */
+/* File autogenerated by gengetopt version 2.17  */
 
-#ifndef _cmdline_h
-#define _cmdline_h
+#ifndef CMDLINE_H
+#define CMDLINE_H
+
+/* If we use autoconf.  */
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
 
 #ifdef __cplusplus
 extern "C" {
 #endif /* __cplusplus */
 
-/* Don't define PACKAGE and VERSION if we use automake.  */
-#ifndef PACKAGE
-#define PACKAGE ""
+#ifndef CMDLINE_PARSER_PACKAGE
+#define CMDLINE_PARSER_PACKAGE PACKAGE
 #endif
 
-#ifndef VERSION
-#define VERSION ""
+#ifndef CMDLINE_PARSER_VERSION
+#define CMDLINE_PARSER_VERSION VERSION
 #endif
 
 struct gengetopt_args_info
 {
+  const char *help_help; /* Print help and exit help description.  */
+  const char *version_help; /* Print version and exit help description.  */
   int fg_flag;	/* Run in foreground (default=off).  */
+  const char *fg_help; /* Run in foreground help description.  */
   int debug_flag;	/* Run in debug mode (default=off).  */
+  const char *debug_help; /* Run in debug mode help description.  */
   char * conf_arg;	/* Read configuration file (default='/etc/ggsn.conf').  */
+  char * conf_orig;	/* Read configuration file original value given at command line.  */
+  const char *conf_help; /* Read configuration file help description.  */
   char * pidfile_arg;	/* Filename of process id file (default='/var/run/ggsn.pid').  */
+  char * pidfile_orig;	/* Filename of process id file original value given at command line.  */
+  const char *pidfile_help; /* Filename of process id file help description.  */
   char * statedir_arg;	/* Directory of nonvolatile data (default='/var/lib/ggsn/').  */
+  char * statedir_orig;	/* Directory of nonvolatile data original value given at command line.  */
+  const char *statedir_help; /* Directory of nonvolatile data help description.  */
   char * listen_arg;	/* Local interface.  */
+  char * listen_orig;	/* Local interface original value given at command line.  */
+  const char *listen_help; /* Local interface help description.  */
   char * net_arg;	/* Network (default='192.168.0.0/24').  */
+  char * net_orig;	/* Network original value given at command line.  */
+  const char *net_help; /* Network help description.  */
   char * ipup_arg;	/* Script to run after link-up.  */
+  char * ipup_orig;	/* Script to run after link-up original value given at command line.  */
+  const char *ipup_help; /* Script to run after link-up help description.  */
   char * ipdown_arg;	/* Script to run after link-down.  */
+  char * ipdown_orig;	/* Script to run after link-down original value given at command line.  */
+  const char *ipdown_help; /* Script to run after link-down help description.  */
   char * dynip_arg;	/* Dynamic IP address pool.  */
+  char * dynip_orig;	/* Dynamic IP address pool original value given at command line.  */
+  const char *dynip_help; /* Dynamic IP address pool help description.  */
   char * statip_arg;	/* Static IP address pool.  */
+  char * statip_orig;	/* Static IP address pool original value given at command line.  */
+  const char *statip_help; /* Static IP address pool help description.  */
   char * pcodns1_arg;	/* PCO DNS Server 1 (default='0.0.0.0').  */
+  char * pcodns1_orig;	/* PCO DNS Server 1 original value given at command line.  */
+  const char *pcodns1_help; /* PCO DNS Server 1 help description.  */
   char * pcodns2_arg;	/* PCO DNS Server 2 (default='0.0.0.0').  */
+  char * pcodns2_orig;	/* PCO DNS Server 2 original value given at command line.  */
+  const char *pcodns2_help; /* PCO DNS Server 2 help description.  */
   int timelimit_arg;	/* Exit after timelimit seconds (default='0').  */
+  char * timelimit_orig;	/* Exit after timelimit seconds original value given at command line.  */
+  const char *timelimit_help; /* Exit after timelimit seconds help description.  */
   char * apn_arg;	/* Access point name (default='internet').  */
+  char * apn_orig;	/* Access point name original value given at command line.  */
+  const char *apn_help; /* Access point name help description.  */
   int qos_arg;	/* Requested quality of service (default='0x0b921f').  */
-
+  char * qos_orig;	/* Requested quality of service original value given at command line.  */
+  const char *qos_help; /* Requested quality of service help description.  */
+  
   int help_given ;	/* Whether help was given.  */
   int version_given ;	/* Whether version was given.  */
   int fg_given ;	/* Whether fg was given.  */
@@ -58,14 +94,33 @@
 
 } ;
 
-int cmdline_parser (int argc, char * const *argv, struct gengetopt_args_info *args_info);
+extern const char *gengetopt_args_info_purpose;
+extern const char *gengetopt_args_info_usage;
+extern const char *gengetopt_args_info_help[];
+
+int cmdline_parser (int argc, char * const *argv,
+  struct gengetopt_args_info *args_info);
+int cmdline_parser2 (int argc, char * const *argv,
+  struct gengetopt_args_info *args_info,
+  int override, int initialize, int check_required);
+int cmdline_parser_file_save(const char *filename,
+  struct gengetopt_args_info *args_info);
 
 void cmdline_parser_print_help(void);
 void cmdline_parser_print_version(void);
 
-int cmdline_parser_configfile (char * const filename, struct gengetopt_args_info *args_info, int override);
+void cmdline_parser_init (struct gengetopt_args_info *args_info);
+void cmdline_parser_free (struct gengetopt_args_info *args_info);
+
+int cmdline_parser_configfile (char * const filename,
+  struct gengetopt_args_info *args_info,
+  int override, int initialize, int check_required);
+
+int cmdline_parser_required (struct gengetopt_args_info *args_info,
+  const char *prog_name);
+
 
 #ifdef __cplusplus
 }
 #endif /* __cplusplus */
-#endif /* _cmdline_h */
+#endif /* CMDLINE_H */
diff --git a/ggsn/ggsn.c b/ggsn/ggsn.c
index 5f120f3..52a2022 100644
--- a/ggsn/ggsn.c
+++ b/ggsn/ggsn.c
@@ -261,7 +261,7 @@
 
   /* Try out our new parser */
   
-  if (cmdline_parser_configfile (args_info.conf_arg, &args_info, 0) != 0)
+  if (cmdline_parser_configfile (args_info.conf_arg, &args_info, 0, 0, 0) != 0)
     exit(1);
   if (args_info.debug_flag) {
     printf("cmdline_parser_configfile\n");
@@ -532,6 +532,7 @@
     
   }
 
+  cmdline_parser_free(&args_info);
   ippool_free(ippool);
   gtp_free(gsn);
   tun_free(tun);