aboutsummaryrefslogtreecommitdiff
path: root/lib/compat/getopt_long.c
diff options
context:
space:
mode:
Diffstat (limited to 'lib/compat/getopt_long.c')
-rw-r--r--lib/compat/getopt_long.c72
1 files changed, 72 insertions, 0 deletions
diff --git a/lib/compat/getopt_long.c b/lib/compat/getopt_long.c
new file mode 100644
index 0000000..24f5864
--- /dev/null
+++ b/lib/compat/getopt_long.c
@@ -0,0 +1,72 @@
+/* SPDX-License-Identifier: GPL-3.0-or-later */
+/*
+ * getopt_long.c
+ *
+ * Copyright (C) 2019 David Oberhollenzer <goliath@infraroot.at>
+ */
+#include "config.h"
+#include "compat.h"
+
+#ifdef HAVE_GETOPT
+#include <unistd.h>
+#endif
+
+#include <stdio.h>
+#include <string.h>
+
+#ifndef HAVE_GETOPT_LONG
+int getopt_long(int argc, char *const argv[], const char *optstr,
+ const struct option *longopts, int *longindex)
+{
+ size_t i, len;
+ char *ptr;
+ (void)longindex;
+
+ if (optind >= argc || argv[optind][0] != '-' ||
+ argv[optind][1] != '-' || argv[optind][2] == '\0')
+ return getopt(argc, argv, optstr);
+
+ optarg = NULL;
+ ptr = argv[optind] + 2;
+
+ for (len = 0; ptr[len] != '\0' && ptr[len] != '='; ++len)
+ ;
+
+ for (i = 0; longopts[i].name != NULL; ++i) {
+ if (strncmp(longopts[i].name, ptr, len) != 0)
+ continue;
+
+ if (longopts[i].name[len] == '\0')
+ break;
+ }
+
+ if (longopts[i].name == NULL)
+ goto fail_unknown;
+
+ if (ptr[len] == '=') {
+ if (!longopts[i].has_arg)
+ goto fail_arg;
+
+ optarg = ptr + len + 1;
+ } else if (longopts[i].has_arg) {
+ if (++optind >= argc)
+ goto fail_no_arg;
+
+ optarg = argv[optind];
+ }
+
+ ++optind;
+ return longopts[i].val;
+fail_unknown:
+ fprintf(stderr, "%s: unknown option `--%s`\n", argv[0], ptr);
+ return '?';
+fail_arg:
+ fprintf(stderr, "%s: no argument expected for option `--%s`\n",
+ argv[0], ptr);
+ return '?';
+fail_no_arg:
+ fprintf(stderr, "%s: missing argument for option `--%s`\n",
+ argv[0], ptr);
+ return '?';
+}
+#endif