bundled getopt replaced with BSD-licensed one
authorVictor Kirhenshtein <victor@netxms.org>
Thu, 30 Jan 2014 09:54:36 +0000 (11:54 +0200)
committerVictor Kirhenshtein <victor@netxms.org>
Thu, 30 Jan 2014 18:57:13 +0000 (20:57 +0200)
include/netxms_getopt.h
src/libnetxms/getopt.c

index c0dbc52..8436ef6 100644 (file)
@@ -1,22 +1,79 @@
-/* Declarations for getopt.
-   Copyright (C) 1989, 1990, 1991, 1992, 1993 Free Software Foundation, Inc.
-
-   This program is free software; you can 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.
-
-   This program 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 this program; if not, write to the Free Software
-   Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
-
-#ifndef _GETOPT_H
-#define _GETOPT_H 1
+/*
+ * Copyright (c) 2014 Raden Solutions
+ *
+ * Custom header file for getopt implementation derived from NetBSD implementation
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+/*
+ * Copyright (c) 2002 Todd C. Miller <Todd.Miller@courtesan.com>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ * Sponsored in part by the Defense Advanced Research Projects
+ * Agency (DARPA) and Air Force Research Laboratory, Air Force
+ * Materiel Command, USAF, under agreement number F39502-99-1-0512.
+ */
+/*-
+ * Copyright (c) 2000 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Dieter Baron and Thomas Klausner.
+ *
+ * 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. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *        This product includes software developed by the NetBSD
+ *        Foundation, Inc. and its contributors.
+ * 4. Neither the name of The NetBSD Foundation nor the names of its
+ *    contributors may be used to endorse or promote products derived
+ *    from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``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 FOUNDATION OR CONTRIBUTORS
+ * 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.
+ */
+
+#ifndef _NETXMS_GETOPT_H
+#define _NETXMS_GETOPT_H
+
+#include <nms_util.h>
 
 #undef HAVE_GETOPT_LONG
 #define HAVE_GETOPT_LONG 1
 #undef HAVE_DECL_GETOPT_LONG
 #define HAVE_DECL_GETOPT_LONG 1
 
-#ifdef _WIN32
-#ifdef LIBNETXMS_EXPORTS
-#define GETOPT_EXPORTABLE __declspec(dllexport)
-#else
-#define GETOPT_EXPORTABLE __declspec(dllimport)
-#endif
-#else    /* _WIN32 */
-#define GETOPT_EXPORTABLE
+#if defined(_WIN32) && !defined(REPLACE_GETOPT)
+#define REPLACE_GETOPT
 #endif
 
 #ifdef __cplusplus
 extern "C" {
 #endif
 
-/* For communication from `getopt' to the caller.
-   When `getopt' finds an option that takes an argument,
-   the argument value is returned here.
-   Also, when `ordering' is RETURN_IN_ORDER,
-   each non-option ARGV-element is returned here.  */
-
-extern GETOPT_EXPORTABLE char *optarg;
-
-/* Index in ARGV of the next element to be scanned.
-   This is used for communication to and from the caller
-   and for communication between successive calls to `getopt'.
-
-   On entry to `getopt', zero means this is the first call; initialize.
-
-   When `getopt' returns EOF, this is the index of the first of the
-   non-option elements that the caller should itself scan.
-
-   Otherwise, `optind' communicates from one call to the next
-   how much of ARGV has been scanned so far.  */
-
-extern GETOPT_EXPORTABLE int optind;
-
-/* Callers store zero here to inhibit the error message `getopt' prints
-   for unrecognized options.  */
-
-extern GETOPT_EXPORTABLE int opterr;
-
-/* Set to an option character which was unrecognized.  */
-
-extern GETOPT_EXPORTABLE int optopt;
-
-/* Describe the long-named options requested by the application.
-   The LONG_OPTIONS argument to getopt_long or getopt_long_only is a vector
-   of `struct option' terminated by an element containing a name which is
-   zero.
-
-   The field `has_arg' is:
-   no_argument         (or 0) if the option does not take an argument,
-   required_argument   (or 1) if the option requires an argument,
-   optional_argument   (or 2) if the option takes an optional argument.
-
-   If the field `flag' is not NULL, it points to a variable that is set
-   to the value given in the field `val' when the option is found, but
-   left unchanged if the option is not found.
-
-   To have a long-named option do something other than set an `int' to
-   a compiled-in constant, such as set a value from `optarg', set the
-   option's `flag' field to zero and its `val' field to a nonzero
-   value (the equivalent single-letter option character, if there is
-   one).  For long options that have a zero `flag' field, `getopt'
-   returns the contents of the `val' field.  */
+extern LIBNETXMS_EXPORTABLE char *optarg;
+extern LIBNETXMS_EXPORTABLE int optind;
+extern LIBNETXMS_EXPORTABLE int opterr;
+extern LIBNETXMS_EXPORTABLE int optopt;
 
 struct option
 {
-#if    __STDC__
+#if __STDC__
   const char *name;
 #else
   char *name;
 #endif
-  /* has_arg can't be an enum because some compilers complain about
-     type mismatches in all the code that assumes it is an int.  */
   int has_arg;
   int *flag;
   int val;
 };
 
-/* Names for the values of the `has_arg' field of `struct option'.  */
+#define no_argument        0
+#define required_argument  1
+#define optional_argument  2
 
-#define        no_argument             0
-#define required_argument      1
-#define optional_argument      2
-
-extern int GETOPT_EXPORTABLE getopt (int argc, char *const *argv, const char *shortopts);
-extern int GETOPT_EXPORTABLE getopt_long (int argc, char *const *argv, const char *shortopts,
-                       const struct option *longopts, int *longind);
-extern int GETOPT_EXPORTABLE getopt_long_only (int argc, char *const *argv,
-                            const char *shortopts,
-                            const struct option *longopts, int *longind);
+#ifdef REPLACE_GETOPT
+int LIBNETXMS_EXPORTABLE nx_getopt(int nargc, char * const *nargv, const char *options);
+#define getopt nx_getopt
+#endif
 
-/* Internal only.  Users should not call this directly.  */
-extern int _getopt_internal (int argc, char *const *argv,
-                            const char *shortopts,
-                            const struct option *longopts, int *longind,
-                            int long_only);
+int LIBNETXMS_EXPORTABLE getopt_long(int nargc, char * const *nargv, const char *options, const struct option *long_options, int *idx);
+int LIBNETXMS_EXPORTABLE getopt_long_only(int nargc, char * const *nargv, const char *options, const struct option *long_options, int *idx);
 
 #ifdef __cplusplus
 }
 #endif
 
-#endif /* _GETOPT_H */
+#endif /* _NETXMS_GETOPT_H */
index 28502e5..71a7b0c 100644 (file)
@@ -1,25 +1,57 @@
-/* Getopt for GNU.
-   NOTE: getopt is now part of the C library, so if you don't know what
-   "Keep this file name-space clean" means, talk to roland@gnu.ai.mit.edu
-   before changing it!
-
-   Copyright (C) 1987, 88, 89, 90, 91, 92, 1993
-       Free Software Foundation, Inc.
-
-   This program is free software; you can 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.
-
-   This program 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 this program; if not, write to the Free Software
-   Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  
-*/
+/*
+ * Copyright (c) 2002 Todd C. Miller <Todd.Miller@courtesan.com>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ * Sponsored in part by the Defense Advanced Research Projects
+ * Agency (DARPA) and Air Force Research Laboratory, Air Force
+ * Materiel Command, USAF, under agreement number F39502-99-1-0512.
+ */
+/*-
+ * Copyright (c) 2000 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Dieter Baron and Thomas Klausner.
+ *
+ * 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. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *        This product includes software developed by the NetBSD
+ *        Foundation, Inc. and its contributors.
+ * 4. Neither the name of The NetBSD Foundation nor the names of its
+ *    contributors may be used to endorse or promote products derived
+ *    from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``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 FOUNDATION OR CONTRIBUTORS
+ * 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.
+ */
 
 #ifndef _WIN32
 #include <config.h>
 
 #if USE_BUNDLED_GETOPT || defined(_WIN32)
 
-#ifndef __STDC__
-#  ifndef const
-#    define const
-#  endif
-#endif
-
-/* This tells Alpha OSF/1 not to define a getopt prototype in <stdio.h>.  */
-#ifndef _NO_PROTO
-#define _NO_PROTO
-#endif
-
-#include <stdio.h>
-#include <string.h>
-
-/* Comment out all this code if we are using the GNU C Library, and are not
-   actually compiling the library itself.  This code is part of the GNU C
-   Library, but also included in many other GNU distributions.  Compiling
-   and linking in this code is a waste when using the GNU C library
-   (especially if it is a shared library).  Rather than having every GNU
-   program understand `configure --with-gnu-libc' and omit the object files,
-   it is simpler to just do this in the source for each such file.  */
-
-#if defined (_LIBC) || !defined (__GNU_LIBRARY__)
-
-
-/* This needs to come after some library #include
-   to get __GNU_LIBRARY__ defined.  */
-#ifdef __GNU_LIBRARY__
-/* Don't include stdlib.h for non-GNU C libraries because some of them
-   contain conflicting prototypes for getopt.  */
-#include <stdlib.h>
-#endif /* GNU C library.  */
-
-/* If GETOPT_COMPAT is defined, `+' as well as `--' can introduce a
-   long-named option.  Because this is not POSIX.2 compliant, it is
-   being phased out.  */
-/* #define GETOPT_COMPAT */
-
-/* This version of `getopt' appears to the caller like standard Unix `getopt'
-   but it behaves differently for the user, since it allows the user
-   to intersperse the options with the other arguments.
-
-   As `getopt' works, it permutes the elements of ARGV so that,
-   when it is done, all the options precede everything else.  Thus
-   all application programs are extended to handle flexible argument order.
-
-   Setting the environment variable POSIXLY_CORRECT disables permutation.
-   Then the behavior is completely standard.
-
-   GNU application programs can use a third alternative mode in which
-   they can distinguish the relative order of options and other arguments.  */
-
+#include "libnetxms.h"
 #include <netxms_getopt.h>
 
-/* For communication from `getopt' to the caller.
-   When `getopt' finds an option that takes an argument,
-   the argument value is returned here.
-   Also, when `ordering' is RETURN_IN_ORDER,
-   each non-option ARGV-element is returned here.  */
+#define GNU_COMPATIBLE          /* Be more compatible, configure's use us! */
 
-GETOPT_EXPORTABLE char *optarg = 0;
-
-/* Index in ARGV of the next element to be scanned.
-   This is used for communication to and from the caller
-   and for communication between successive calls to `getopt'.
-
-   On entry to `getopt', zero means this is the first call; initialize.
-
-   When `getopt' returns EOF, this is the index of the first of the
-   non-option elements that the caller should itself scan.
-
-   Otherwise, `optind' communicates from one call to the next
-   how much of ARGV has been scanned so far.  */
-
-/* XXX 1003.2 says this must be 1 before any call.  */
-GETOPT_EXPORTABLE int optind = 0;
-
-/* The next char to be scanned in the option-element
-   in which the last option character we returned was found.
-   This allows us to pick up the scan where we left off.
-
-   If this is zero, or a null string, it means resume the scan
-   by advancing to the next ARGV-element.  */
-
-static char *nextchar;
-
-/* Callers store zero here to inhibit the error message
-   for unrecognized options.  */
-
-GETOPT_EXPORTABLE int opterr = 1;
-
-/* Set to an option character which was unrecognized.
-   This must be initialized on some systems to avoid linking in the
-   system's own getopt implementation.  */
-
-#define BAD_OPTION '\0'
-GETOPT_EXPORTABLE int optopt = BAD_OPTION;
-
-/* Describe how to deal with options that follow non-option ARGV-elements.
-
-   If the caller did not specify anything,
-   the default is REQUIRE_ORDER if the environment variable
-   POSIXLY_CORRECT is defined, PERMUTE otherwise.
-
-   REQUIRE_ORDER means don't recognize them as options;
-   stop option processing when the first non-option is seen.
-   This is what Unix does.
-   This mode of operation is selected by either setting the environment
-   variable POSIXLY_CORRECT, or using `+' as the first character
-   of the list of option characters.
-
-   PERMUTE is the default.  We permute the contents of ARGV as we scan,
-   so that eventually all the non-options are at the end.  This allows options
-   to be given in any order, even with programs that were not written to
-   expect this.
+#ifdef REPLACE_GETOPT
+int     opterr = 1;             /* if error message should be printed */
+int     optind = 1;             /* index into parent argv vector */
+int     optopt = '?';           /* character checked for validity */
+int     optreset;               /* reset getopt */
+char    *optarg;                /* argument associated with option */
+#endif
 
-   RETURN_IN_ORDER is an option available to programs that were written
-   to expect options and other ARGV-elements in any order and that care about
-   the ordering of the two.  We describe each non-option ARGV-element
-   as if it were the argument of an option with character code 1.
-   Using `-' as the first character of the list of option characters
-   selects this mode of operation.
+#define PRINT_ERROR     ((opterr) && (*options != ':'))
 
-   The special argument `--' forces an end of option-scanning regardless
-   of the value of `ordering'.  In the case of RETURN_IN_ORDER, only
-   `--' can cause `getopt' to return EOF with `optind' != ARGC.  */
+#define FLAG_PERMUTE    0x01    /* permute non-options to the end of argv */
+#define FLAG_ALLARGS    0x02    /* treat non-options as args to option "-1" */
+#define FLAG_LONGONLY   0x04    /* operate as getopt_long_only */
 
-static enum
-{
-  REQUIRE_ORDER, PERMUTE, RETURN_IN_ORDER
-} ordering;
-
-#ifdef __GNU_LIBRARY__
-/* We want to avoid inclusion of string.h with non-GNU libraries
-   because there are many ways it can cause trouble.
-   On some systems, it contains special magic macros that don't work
-   in GCC.  */
-#include <string.h>
-#define        my_index        strchr
-#define        my_strlen       strlen
-#else
+/* return values */
+#define BADCH           (int)'?'
+#define BADARG          ((*options == ':') ? (int)':' : (int)'?')
+#define INORDER         (int)1
 
-/* Avoid depending on library functions or files
-   whose names are inconsistent.  */
+#define EMSG            ""
 
-#if __STDC__ || defined(PROTO)
-extern char *getenv(const char *name);
-extern int  strcmp (const char *s1, const char *s2);
-extern int  strncmp(const char *s1, const char *s2, int n);
+#ifdef GNU_COMPATIBLE
+#define NO_PREFIX       (-1)
+#define D_PREFIX        0
+#define DD_PREFIX       1
+#define W_PREFIX        2
+#endif
 
-static int my_strlen(const char *s);
-static char *my_index (const char *str, int chr);
+static int getopt_internal(int, char * const *, const char *,
+                           const struct option *, int *, int);
+static int parse_long_options(char * const *, const char *,
+                              const struct option *, int *, int, int);
+static int gcd(int, int);
+static void permute_args(int, int, int, char * const *);
+
+static char *place = EMSG; /* option letter processing */
+
+/* XXX: set optreset to 1 rather than these two */
+static int nonopt_start = -1; /* first non option argument (for permute) */
+static int nonopt_end = -1;   /* first option after non options (for permute) */
+
+/* Error messages */
+static const char recargchar[] = "option requires an argument -- %c";
+static const char illoptchar[] = "illegal option -- %c"; /* From P1003.2 */
+#ifdef GNU_COMPATIBLE
+static int dash_prefix = NO_PREFIX;
+static const char gnuoptchar[] = "invalid option -- %c";
+
+static const char recargstring[] = "option `%s%s' requires an argument";
+static const char ambig[] = "option `%s%.*s' is ambiguous";
+static const char noarg[] = "option `%s%.*s' doesn't allow an argument";
+static const char illoptstring[] = "unrecognized option `%s%s'";
 #else
-extern char *getenv ();
+static const char recargstring[] = "option requires an argument -- %s";
+static const char ambig[] = "ambiguous option -- %.*s";
+static const char noarg[] = "option doesn't take an argument -- %.*s";
+static const char illoptstring[] = "unknown option -- %s";
 #endif
 
+/*
+ * Compute the greatest common divisor of a and b.
+ */
 static int
-my_strlen (str)
-     const char *str;
+gcd(int a, int b)
 {
-  int n = 0;
-  while (*str++)
-    n++;
-  return n;
+        int c;
+
+        c = a % b;
+        while (c != 0) {
+                a = b;
+                b = c;
+                c = a % b;
+        }
+
+        return (b);
 }
 
-static char *
-my_index (str, chr)
-     const char *str;
-     int chr;
+/*
+ * Exchange the block from nonopt_start to nonopt_end with the block
+ * from nonopt_end to opt_end (keeping the same order of arguments
+ * in each block).
+ */
+static void
+permute_args(int panonopt_start, int panonopt_end, int opt_end,
+        char * const *nargv)
 {
-  while (*str)
-    {
-      if (*str == chr)
-       return (char *) str;
-      str++;
-    }
-  return 0;
+        int cstart, cyclelen, i, j, ncycle, nnonopts, nopts, pos;
+        char *swap;
+
+        /*
+         * compute lengths of blocks and number and size of cycles
+         */
+        nnonopts = panonopt_end - panonopt_start;
+        nopts = opt_end - panonopt_end;
+        ncycle = gcd(nnonopts, nopts);
+        cyclelen = (opt_end - panonopt_start) / ncycle;
+
+        for (i = 0; i < ncycle; i++) {
+                cstart = panonopt_end+i;
+                pos = cstart;
+                for (j = 0; j < cyclelen; j++) {
+                        if (pos >= panonopt_end)
+                                pos -= nnonopts;
+                        else
+                                pos += nopts;
+                        swap = nargv[pos];
+                        /* LINTED const cast */
+                        ((char **) nargv)[pos] = nargv[cstart];
+                        /* LINTED const cast */
+                        ((char **)nargv)[cstart] = swap;
+                }
+        }
 }
 
-#endif                         /* GNU C library.  */
-
-/* Handle permutation of arguments.  */
-
-/* Describe the part of ARGV that contains non-options that have
-   been skipped.  `first_nonopt' is the index in ARGV of the first of them;
-   `last_nonopt' is the index after the last of them.  */
-
-static int first_nonopt;
-static int last_nonopt;
-
-/* Exchange two adjacent subsequences of ARGV.
-   One subsequence is elements [first_nonopt,last_nonopt)
-   which contains all the non-options that have been skipped so far.
-   The other is elements [last_nonopt,optind), which contains all
-   the options processed since those non-options were skipped.
-
-   `first_nonopt' and `last_nonopt' are relocated so that they describe
-   the new indices of the non-options in ARGV after they are moved.
-
-   To perform the swap, we first reverse the order of all elements. So
-   all options now come before all non options, but they are in the
-   wrong order. So we put back the options and non options in original
-   order by reversing them again. For example:
-       original input:      a b c -x -y
-       reverse all:         -y -x c b a
-       reverse options:     -x -y c b a
-       reverse non options: -x -y a b c
-*/
-
-#if __STDC__ || defined(PROTO)
-static void exchange (char **argv);
-#endif
-
-static void
-exchange (argv)
-     char **argv;
+/*
+ * parse_long_options --
+ *      Parse long options in argc/argv argument vector.
+ * Returns -1 if short_too is set and the option does not match long_options.
+ */
+static int
+parse_long_options(char * const *nargv, const char *options,
+        const struct option *long_options, int *idx, int short_too, int flags)
 {
-  char *temp, **first, **last;
-
-  /* Reverse all the elements [first_nonopt, optind) */
-  first = &argv[first_nonopt];
-  last  = &argv[optind-1];
-  while (first < last) {
-    temp = *first; *first = *last; *last = temp; first++; last--;
-  }
-  /* Put back the options in order */
-  first = &argv[first_nonopt];
-  first_nonopt += (optind - last_nonopt);
-  last  = &argv[first_nonopt - 1];
-  while (first < last) {
-    temp = *first; *first = *last; *last = temp; first++; last--;
-  }
-
-  /* Put back the non options in order */
-  first = &argv[first_nonopt];
-  last_nonopt = optind;
-  last  = &argv[last_nonopt-1];
-  while (first < last) {
-    temp = *first; *first = *last; *last = temp; first++; last--;
-  }
+        char *current_argv, *has_equal;
+#ifdef GNU_COMPATIBLE
+        char *current_dash;
+#endif
+        size_t current_argv_len;
+        int i, match, exact_match, second_partial_match;
+
+        current_argv = place;
+#ifdef GNU_COMPATIBLE
+        switch (dash_prefix) {
+                case D_PREFIX:
+                        current_dash = "-";
+                        break;
+                case DD_PREFIX:
+                        current_dash = "--";
+                        break;
+                case W_PREFIX:
+                        current_dash = "-W ";
+                        break;
+                default:
+                        current_dash = "";
+                        break;
+        }
+#endif
+        match = -1;
+        exact_match = 0;
+        second_partial_match = 0;
+
+        optind++;
+
+        if ((has_equal = strchr(current_argv, '=')) != NULL) {
+                /* argument found (--option=arg) */
+                current_argv_len = has_equal - current_argv;
+                has_equal++;
+        } else
+                current_argv_len = strlen(current_argv);
+
+        for (i = 0; long_options[i].name; i++) {
+                /* find matching long option */
+                if (strncmp(current_argv, long_options[i].name,
+                    current_argv_len))
+                        continue;
+
+                if (strlen(long_options[i].name) == current_argv_len) {
+                        /* exact match */
+                        match = i;
+                        exact_match = 1;
+                        break;
+                }
+                /*
+                 * If this is a known short option, don't allow
+                 * a partial match of a single character.
+                 */
+                if (short_too && current_argv_len == 1)
+                        continue;
+
+                if (match == -1)        /* first partial match */
+                        match = i;
+                else if ((flags & FLAG_LONGONLY) ||
+                         long_options[i].has_arg !=
+                             long_options[match].has_arg ||
+                         long_options[i].flag != long_options[match].flag ||
+                         long_options[i].val != long_options[match].val)
+                        second_partial_match = 1;
+        }
+        if (!exact_match && second_partial_match) {
+                /* ambiguous abbreviation */
+                if (PRINT_ERROR)
+                        printf(ambig,
+#ifdef GNU_COMPATIBLE
+                             current_dash,
+#endif
+                             (int)current_argv_len,
+                             current_argv);
+                optopt = 0;
+                return (BADCH);
+        }
+        if (match != -1) {              /* option found */
+                if (long_options[match].has_arg == no_argument
+                    && has_equal) {
+                        if (PRINT_ERROR)
+                                printf(noarg,
+#ifdef GNU_COMPATIBLE
+                                     current_dash,
+#endif
+                                     (int)current_argv_len,
+                                     current_argv);
+                        /*
+                         * XXX: GNU sets optopt to val regardless of flag
+                         */
+                        if (long_options[match].flag == NULL)
+                                optopt = long_options[match].val;
+                        else
+                                optopt = 0;
+#ifdef GNU_COMPATIBLE
+                        return (BADCH);
+#else
+                        return (BADARG);
+#endif
+                }
+                if (long_options[match].has_arg == required_argument ||
+                    long_options[match].has_arg == optional_argument) {
+                        if (has_equal)
+                                optarg = has_equal;
+                        else if (long_options[match].has_arg ==
+                            required_argument) {
+                                /*
+                                 * optional argument doesn't use next nargv
+                                 */
+                                optarg = nargv[optind++];
+                        }
+                }
+                if ((long_options[match].has_arg == required_argument)
+                    && (optarg == NULL)) {
+                        /*
+                         * Missing argument; leading ':' indicates no error
+                         * should be generated.
+                         */
+                        if (PRINT_ERROR)
+                                printf(recargstring,
+#ifdef GNU_COMPATIBLE
+                                    current_dash,
+#endif
+                                    current_argv);
+                        /*
+                         * XXX: GNU sets optopt to val regardless of flag
+                         */
+                        if (long_options[match].flag == NULL)
+                                optopt = long_options[match].val;
+                        else
+                                optopt = 0;
+                        --optind;
+                        return (BADARG);
+                }
+        } else {                        /* unknown option */
+                if (short_too) {
+                        --optind;
+                        return (-1);
+                }
+                if (PRINT_ERROR)
+                        printf(illoptstring,
+#ifdef GNU_COMPATIBLE
+                              current_dash,
+#endif
+                              current_argv);
+                optopt = 0;
+                return (BADCH);
+        }
+        if (idx)
+                *idx = match;
+        if (long_options[match].flag) {
+                *long_options[match].flag = long_options[match].val;
+                return (0);
+        } else
+                return (long_options[match].val);
 }
 
-/* Scan elements of ARGV (whose length is ARGC) for option characters
-   given in OPTSTRING.
-
-   If an element of ARGV starts with '-', and is not exactly "-" or "--",
-   then it is an option element.  The characters of this element
-   (aside from the initial '-') are option characters.  If `getopt'
-   is called repeatedly, it returns successively each of the option characters
-   from each of the option elements.
-
-   If `getopt' finds another option character, it returns that character,
-   updating `optind' and `nextchar' so that the next call to `getopt' can
-   resume the scan with the following option character or ARGV-element.
-
-   If there are no more option characters, `getopt' returns `EOF'.
-   Then `optind' is the index in ARGV of the first ARGV-element
-   that is not an option.  (The ARGV-elements have been permuted
-   so that those that are not options now come last.)
-
-   OPTSTRING is a string containing the legitimate option characters.
-   If an option character is seen that is not listed in OPTSTRING,
-   return BAD_OPTION after printing an error message.  If you set `opterr' to
-   zero, the error message is suppressed but we still return BAD_OPTION.
-
-   If a char in OPTSTRING is followed by a colon, that means it wants an arg,
-   so the following text in the same ARGV-element, or the text of the following
-   ARGV-element, is returned in `optarg'.  Two colons mean an option that
-   wants an optional arg; if there is text in the current ARGV-element,
-   it is returned in `optarg', otherwise `optarg' is set to zero.
-
-   If OPTSTRING starts with `-' or `+', it requests different methods of
-   handling the non-option ARGV-elements.
-   See the comments about RETURN_IN_ORDER and REQUIRE_ORDER, above.
-
-   Long-named options begin with `--' instead of `-'.
-   Their names may be abbreviated as long as the abbreviation is unique
-   or is an exact match for some defined option.  If they have an
-   argument, it follows the option name in the same ARGV-element, separated
-   from the option name by a `=', or else the in next ARGV-element.
-   When `getopt' finds a long-named option, it returns 0 if that option's
-   `flag' field is nonzero, the value of the option's `val' field
-   if the `flag' field is zero.
-
-   The elements of ARGV aren't really const, because we permute them.
-   But we pretend they're const in the prototype to be compatible
-   with other systems.
-
-   LONGOPTS is a vector of `struct option' terminated by an
-   element containing a name which is zero.
-
-   LONGIND returns the index in LONGOPT of the long-named option found.
-   It is only valid when a long-named option has been found by the most
-   recent call.
-
-   If LONG_ONLY is nonzero, '-' as well as '--' can introduce
-   long-named options.  */
-
-int
-_getopt_internal (argc, argv, optstring, longopts, longind, long_only)
-     int argc;
-     char *const *argv;
-     const char *optstring;
-     const struct option *longopts;
-     int *longind;
-     int long_only;
+/*
+ * getopt_internal --
+ *      Parse argc/argv argument vector.  Called by user level routines.
+ */
+static int
+getopt_internal(int nargc, char * const *nargv, const char *options,
+        const struct option *long_options, int *idx, int flags)
 {
-  int option_index;
-
-  optarg = 0;
-
-  /* Initialize the internal data when the first call is made.
-     Start processing options with ARGV-element 1 (since ARGV-element 0
-     is the program name); the sequence of previously skipped
-     non-option ARGV-elements is empty.  */
-
-  if (optind == 0)
-    {
-      first_nonopt = last_nonopt = optind = 1;
-
-      nextchar = NULL;
-
-      /* Determine how to handle the ordering of options and nonoptions.  */
-
-      if (optstring[0] == '-')
-       {
-         ordering = RETURN_IN_ORDER;
-         ++optstring;
-       }
-      else if (optstring[0] == '+')
-       {
-         ordering = REQUIRE_ORDER;
-         ++optstring;
-       }
-      else if (getenv ("POSIXLY_CORRECT") != NULL)
-       ordering = REQUIRE_ORDER;
-      else
-       ordering = PERMUTE;
-    }
-
-  if (nextchar == NULL || *nextchar == '\0')
-    {
-      if (ordering == PERMUTE)
-       {
-         /* If we have just processed some options following some non-options,
-            exchange them so that the options come first.  */
-
-         if (first_nonopt != last_nonopt && last_nonopt != optind)
-           exchange ((char **) argv);
-         else if (last_nonopt != optind)
-           first_nonopt = optind;
-
-         /* Now skip any additional non-options
-            and extend the range of non-options previously skipped.  */
-
-         while (optind < argc
-                && (argv[optind][0] != '-' || argv[optind][1] == '\0')
-#ifdef GETOPT_COMPAT
-                && (longopts == NULL
-                    || argv[optind][0] != '+' || argv[optind][1] == '\0')
-#endif                         /* GETOPT_COMPAT */
-                )
-           optind++;
-         last_nonopt = optind;
-       }
-
-      /* Special ARGV-element `--' means premature end of options.
-        Skip it like a null option,
-        then exchange with previous non-options as if it were an option,
-        then skip everything else like a non-option.  */
-
-      if (optind != argc && !strcmp (argv[optind], "--"))
-       {
-         optind++;
-
-         if (first_nonopt != last_nonopt && last_nonopt != optind)
-           exchange ((char **) argv);
-         else if (first_nonopt == last_nonopt)
-           first_nonopt = optind;
-         last_nonopt = argc;
-
-         optind = argc;
-       }
-
-      /* If we have done all the ARGV-elements, stop the scan
-        and back over any non-options that we skipped and permuted.  */
-
-      if (optind == argc)
-       {
-         /* Set the next-arg-index to point at the non-options
-            that we previously skipped, so the caller will digest them.  */
-         if (first_nonopt != last_nonopt)
-           optind = first_nonopt;
-         return EOF;
-       }
-
-      /* If we have come to a non-option and did not permute it,
-        either stop the scan or describe it to the caller and pass it by.  */
-
-      if ((argv[optind][0] != '-' || argv[optind][1] == '\0')
-#ifdef GETOPT_COMPAT
-         && (longopts == NULL
-             || argv[optind][0] != '+' || argv[optind][1] == '\0')
-#endif                         /* GETOPT_COMPAT */
-         )
-       {
-         if (ordering == REQUIRE_ORDER)
-           return EOF;
-         optarg = argv[optind++];
-         return 1;
-       }
-
-      /* We have found another option-ARGV-element.
-        Start decoding its characters.  */
-
-      nextchar = (argv[optind] + 1
-                 + (longopts != NULL && argv[optind][1] == '-'));
-    }
-
-  if (longopts != NULL
-      && ((argv[optind][0] == '-'
-          && (argv[optind][1] == '-' || long_only))
-#ifdef GETOPT_COMPAT
-         || argv[optind][0] == '+'
-#endif                         /* GETOPT_COMPAT */
-         ))
-    {
-      const struct option *p;
-      char *s = nextchar;
-      int exact = 0;
-      int ambig = 0;
-      const struct option *pfound = NULL;
-      int indfound = 0;
-
-      while (*s && *s != '=')
-       s++;
-
-      /* Test all options for either exact match or abbreviated matches.  */
-      for (p = longopts, option_index = 0; p->name;
-          p++, option_index++)
-       if (!strncmp (p->name, nextchar, s - nextchar))
-         {
-           if (s - nextchar == my_strlen (p->name))
-             {
-               /* Exact match found.  */
-               pfound = p;
-               indfound = option_index;
-               exact = 1;
-               break;
-             }
-           else if (pfound == NULL)
-             {
-               /* First nonexact match found.  */
-               pfound = p;
-               indfound = option_index;
-             }
-           else
-             /* Second nonexact match found.  */
-             ambig = 1;
-         }
-
-      if (ambig && !exact)
-       {
-         if (opterr)
-           fprintf (stderr, "%s: option `%s' is ambiguous\n",
-                    argv[0], argv[optind]);
-         nextchar += my_strlen (nextchar);
-         optind++;
-         return BAD_OPTION;
-       }
-
-      if (pfound != NULL)
-       {
-         option_index = indfound;
-         optind++;
-         if (*s)
-           {
-             /* Don't test has_arg with >, because some C compilers don't
-                allow it to be used on enums.  */
-             if (pfound->has_arg)
-               optarg = s + 1;
-             else
-               {
-                 if (opterr)
-                   {
-                     if (argv[optind - 1][1] == '-')
-                       /* --option */
-                       fprintf (stderr,
-                                "%s: option `--%s' doesn't allow an argument\n",
-                                argv[0], pfound->name);
-                     else
-                       /* +option or -option */
-                       fprintf (stderr,
-                            "%s: option `%c%s' doesn't allow an argument\n",
-                            argv[0], argv[optind - 1][0], pfound->name);
-                   }
-                 nextchar += my_strlen (nextchar);
-                 return BAD_OPTION;
-               }
-           }
-         else if (pfound->has_arg == 1)
-           {
-             if (optind < argc)
-               optarg = argv[optind++];
-             else
-               {
-                 if (opterr)
-                   fprintf (stderr, "%s: option `%s' requires an argument\n",
-                            argv[0], argv[optind - 1]);
-                 nextchar += my_strlen (nextchar);
-                 return optstring[0] == ':' ? ':' : BAD_OPTION;
-               }
-           }
-         nextchar += my_strlen (nextchar);
-         if (longind != NULL)
-           *longind = option_index;
-         if (pfound->flag)
-           {
-             *(pfound->flag) = pfound->val;
-             return 0;
-           }
-         return pfound->val;
-       }
-      /* Can't find it as a long option.  If this is not getopt_long_only,
-        or the option starts with '--' or is not a valid short
-        option, then it's an error.
-        Otherwise interpret it as a short option.  */
-      if (!long_only || argv[optind][1] == '-'
-#ifdef GETOPT_COMPAT
-         || argv[optind][0] == '+'
-#endif                         /* GETOPT_COMPAT */
-         || my_index (optstring, *nextchar) == NULL)
-       {
-         if (opterr)
-           {
-             if (argv[optind][1] == '-')
-               /* --option */
-               fprintf (stderr, "%s: unrecognized option `--%s'\n",
-                        argv[0], nextchar);
-             else
-               /* +option or -option */
-               fprintf (stderr, "%s: unrecognized option `%c%s'\n",
-                        argv[0], argv[optind][0], nextchar);
-           }
-         nextchar = (char *) "";
-         optind++;
-         return BAD_OPTION;
-       }
-    }
-
-  /* Look at and handle the next option-character.  */
-
-  {
-    char c = *nextchar++;
-    char *temp = my_index (optstring, c);
-
-    /* Increment `optind' when we start to process its last character.  */
-    if (*nextchar == '\0')
-      ++optind;
-
-    if (temp == NULL || c == ':')
-      {
-       if (opterr)
-         {
-#if 0
-           if (c < 040 || c >= 0177)
-             fprintf (stderr, "%s: unrecognized option, character code 0%o\n",
-                      argv[0], c);
-           else
-             fprintf (stderr, "%s: unrecognized option `-%c'\n", argv[0], c);
+        char *oli;                              /* option letter list index */
+        int optchar, short_too;
+        int posixly_correct;    /* no static, can be changed on the fly */
+
+        if (options == NULL)
+                return (-1);
+
+        /*
+         * Disable GNU extensions if POSIXLY_CORRECT is set or options
+         * string begins with a '+'.
+         */
+        posixly_correct = (getenv("POSIXLY_CORRECT") != NULL);
+#ifdef GNU_COMPATIBLE
+        if (*options == '-')
+                flags |= FLAG_ALLARGS;
+        else if (posixly_correct || *options == '+')
+                flags &= ~FLAG_PERMUTE;
+#else
+        if (posixly_correct || *options == '+')
+                flags &= ~FLAG_PERMUTE;
+        else if (*options == '-')
+                flags |= FLAG_ALLARGS;
+#endif
+        if (*options == '+' || *options == '-')
+                options++;
+
+        /*
+         * XXX Some GNU programs (like cvs) set optind to 0 instead of
+         * XXX using optreset.  Work around this braindamage.
+         */
+        if (optind == 0)
+                optind = optreset = 1;
+
+        optarg = NULL;
+        if (optreset)
+                nonopt_start = nonopt_end = -1;
+start:
+        if (optreset || !*place) {              /* update scanning pointer */
+                optreset = 0;
+                if (optind >= nargc) {          /* end of argument vector */
+                        place = EMSG;
+                        if (nonopt_end != -1) {
+                                /* do permutation, if we have to */
+                                permute_args(nonopt_start, nonopt_end,
+                                    optind, nargv);
+                                optind -= nonopt_end - nonopt_start;
+                        }
+                        else if (nonopt_start != -1) {
+                                /*
+                                 * If we skipped non-options, set optind
+                                 * to the first of them.
+                                 */
+                                optind = nonopt_start;
+                        }
+                        nonopt_start = nonopt_end = -1;
+                        return (-1);
+                }
+                if (*(place = nargv[optind]) != '-' ||
+#ifdef GNU_COMPATIBLE
+                    place[1] == '\0') {
 #else
-           /* 1003.2 specifies the format of this message.  */
-           fprintf (stderr, "%s: illegal option -- %c\n", argv[0], c);
+                    (place[1] == '\0' && strchr(options, '-') == NULL)) {
 #endif
-         }
-       optopt = c;
-       return BAD_OPTION;
-      }
-    if (temp[1] == ':')
-      {
-       if (temp[2] == ':')
-         {
-           /* This is an option that accepts an argument optionally.  */
-           if (*nextchar != '\0')
-             {
-               optarg = nextchar;
-               optind++;
-             }
-           else
-             optarg = 0;
-           nextchar = NULL;
-         }
-       else
-         {
-           /* This is an option that requires an argument.  */
-           if (*nextchar != '\0')
-             {
-               optarg = nextchar;
-               /* If we end this ARGV-element by taking the rest as an arg,
-                  we must advance to the next element now.  */
-               optind++;
-             }
-           else if (optind == argc)
-             {
-               if (opterr)
-                 {
-#if 0
-                   fprintf (stderr, "%s: option `-%c' requires an argument\n",
-                            argv[0], c);
+                        place = EMSG;           /* found non-option */
+                        if (flags & FLAG_ALLARGS) {
+                                /*
+                                 * GNU extension:
+                                 * return non-option as argument to option 1
+                                 */
+                                optarg = nargv[optind++];
+                                return (INORDER);
+                        }
+                        if (!(flags & FLAG_PERMUTE)) {
+                                /*
+                                 * If no permutation wanted, stop parsing
+                                 * at first non-option.
+                                 */
+                                return (-1);
+                        }
+                        /* do permutation */
+                        if (nonopt_start == -1)
+                                nonopt_start = optind;
+                        else if (nonopt_end != -1) {
+                                permute_args(nonopt_start, nonopt_end,
+                                    optind, nargv);
+                                nonopt_start = optind -
+                                    (nonopt_end - nonopt_start);
+                                nonopt_end = -1;
+                        }
+                        optind++;
+                        /* process next argument */
+                        goto start;
+                }
+                if (nonopt_start != -1 && nonopt_end == -1)
+                        nonopt_end = optind;
+
+                /*
+                 * If we have "-" do nothing, if "--" we are done.
+                 */
+                if (place[1] != '\0' && *++place == '-' && place[1] == '\0') {
+                        optind++;
+                        place = EMSG;
+                        /*
+                         * We found an option (--), so if we skipped
+                         * non-options, we have to permute.
+                         */
+                        if (nonopt_end != -1) {
+                                permute_args(nonopt_start, nonopt_end,
+                                    optind, nargv);
+                                optind -= nonopt_end - nonopt_start;
+                        }
+                        nonopt_start = nonopt_end = -1;
+                        return (-1);
+                }
+        }
+
+        /*
+         * Check long options if:
+         *  1) we were passed some
+         *  2) the arg is not just "-"
+         *  3) either the arg starts with -- we are getopt_long_only()
+         */
+        if (long_options != NULL && place != nargv[optind] &&
+            (*place == '-' || (flags & FLAG_LONGONLY))) {
+                short_too = 0;
+#ifdef GNU_COMPATIBLE
+                dash_prefix = D_PREFIX;
+#endif
+                if (*place == '-') {
+                        place++;                /* --foo long option */
+#ifdef GNU_COMPATIBLE
+                        dash_prefix = DD_PREFIX;
+#endif
+                } else if (*place != ':' && strchr(options, *place) != NULL)
+                        short_too = 1;          /* could be short option too */
+
+                optchar = parse_long_options(nargv, options, long_options,
+                    idx, short_too, flags);
+                if (optchar != -1) {
+                        place = EMSG;
+                        return (optchar);
+                }
+        }
+
+        if ((optchar = (int)*place++) == (int)':' ||
+            (optchar == (int)'-' && *place != '\0') ||
+            (oli = strchr(options, optchar)) == NULL) {
+                /*
+                 * If the user specified "-" and  '-' isn't listed in
+                 * options, return -1 (non-option) as per POSIX.
+                 * Otherwise, it is an unknown option character (or ':').
+                 */
+                if (optchar == (int)'-' && *place == '\0')
+                        return (-1);
+                if (!*place)
+                        ++optind;
+#ifdef GNU_COMPATIBLE
+                if (PRINT_ERROR)
+                        printf(posixly_correct ? illoptchar : gnuoptchar,
+                              optchar);
 #else
-                   /* 1003.2 specifies the format of this message.  */
-                   fprintf (stderr, "%s: option requires an argument -- %c\n",
-                            argv[0], c);
+                if (PRINT_ERROR)
+                        printf(illoptchar, optchar);
+#endif
+                optopt = optchar;
+                return (BADCH);
+        }
+        if (long_options != NULL && optchar == 'W' && oli[1] == ';') {
+                /* -W long-option */
+                if (*place)                     /* no space */
+                        /* NOTHING */;
+                else if (++optind >= nargc) {   /* no arg */
+                        place = EMSG;
+                        if (PRINT_ERROR)
+                                printf(recargchar, optchar);
+                        optopt = optchar;
+                        return (BADARG);
+                } else                          /* white space */
+                        place = nargv[optind];
+#ifdef GNU_COMPATIBLE
+                dash_prefix = W_PREFIX;
 #endif
-                 }
-               optopt = c;
-               if (optstring[0] == ':')
-                 c = ':';
-               else
-                 c = BAD_OPTION;
-             }
-           else
-             /* We already incremented `optind' once;
-                increment it again when taking next ARGV-elt as argument.  */
-             optarg = argv[optind++];
-           nextchar = NULL;
-         }
-      }
-    return c;
-  }
+                optchar = parse_long_options(nargv, options, long_options,
+                    idx, 0, flags);
+                place = EMSG;
+                return (optchar);
+        }
+        if (*++oli != ':') {                    /* doesn't take argument */
+                if (!*place)
+                        ++optind;
+        } else {                                /* takes (optional) argument */
+                optarg = NULL;
+                if (*place)                     /* no white space */
+                        optarg = place;
+                else if (oli[1] != ':') {       /* arg not optional */
+                        if (++optind >= nargc) {        /* no arg */
+                                place = EMSG;
+                                if (PRINT_ERROR)
+                                        printf(recargchar, optchar);
+                                optopt = optchar;
+                                return (BADARG);
+                        } else
+                                optarg = nargv[optind];
+                }
+                place = EMSG;
+                ++optind;
+        }
+        /* dump back option letter */
+        return (optchar);
 }
 
-int
-GETOPT_EXPORTABLE getopt (argc, argv, optstring)
-     int argc;
-     char *const *argv;
-     const char *optstring;
+#ifdef REPLACE_GETOPT
+/*
+ * getopt --
+ *      Parse argc/argv argument vector.
+ *
+ * [eventually this will replace the BSD getopt]
+ */
+int LIBNETXMS_EXPORTABLE
+nx_getopt(int nargc, char * const *nargv, const char *options)
 {
-  return _getopt_internal (argc, argv, optstring,
-                          (const struct option *) 0,
-                          (int *) 0,
-                          0);
-}
 
-int
-GETOPT_EXPORTABLE getopt_long (argc, argv, options, long_options, opt_index)
-     int argc;
-     char *const *argv;
-     const char *options;
-     const struct option *long_options;
-     int *opt_index;
+        /*
+         * We don't pass FLAG_PERMUTE to getopt_internal() since
+         * the BSD getopt(3) (unlike GNU) has never done this.
+         *
+         * Furthermore, since many privileged programs call getopt()
+         * before dropping privileges it makes sense to keep things
+         * as simple (and bug-free) as possible.
+         */
+        return (getopt_internal(nargc, nargv, options, NULL, NULL, 0));
+}
+#endif /* REPLACE_GETOPT */
+
+/*
+ * getopt_long --
+ *      Parse argc/argv argument vector.
+ */
+int LIBNETXMS_EXPORTABLE
+getopt_long(int nargc, char * const *nargv, const char *options, const struct option *long_options, int *idx)
 {
-  return _getopt_internal (argc, argv, options, long_options, opt_index, 0);
+
+        return (getopt_internal(nargc, nargv, options, long_options, idx,
+            FLAG_PERMUTE));
 }
 
-#endif /* _LIBC or not __GNU_LIBRARY__.  */
+/*
+ * getopt_long_only --
+ *      Parse argc/argv argument vector.
+ */
+int LIBNETXMS_EXPORTABLE
+getopt_long_only(int nargc, char * const *nargv, const char *options, const struct option *long_options, int *idx)
+{
+
+        return (getopt_internal(nargc, nargv, options, long_options, idx,
+            FLAG_PERMUTE|FLAG_LONGONLY));
+}
 
 #endif   /* _WIN32 */