summaryrefslogtreecommitdiff
path: root/package/heirloom-cpio/src/getopt.c
diff options
context:
space:
mode:
Diffstat (limited to 'package/heirloom-cpio/src/getopt.c')
-rw-r--r--package/heirloom-cpio/src/getopt.c141
1 files changed, 141 insertions, 0 deletions
diff --git a/package/heirloom-cpio/src/getopt.c b/package/heirloom-cpio/src/getopt.c
new file mode 100644
index 000000000..0a68ac8e9
--- /dev/null
+++ b/package/heirloom-cpio/src/getopt.c
@@ -0,0 +1,141 @@
+/*
+ * getopt() - command option parsing
+ *
+ * Gunnar Ritter, Freiburg i. Br., Germany, March 2002.
+ */
+
+/* Sccsid @(#)getopt.c 1.6 (gritter) 12/16/07 */
+
+#include <sys/types.h>
+#include <alloca.h>
+#include <string.h>
+#include "msgselect.h"
+
+/*
+ * One should not think that re-implementing this is necessary, but
+ *
+ * - Some libcs print weird messages.
+ *
+ * - GNU libc getopt() is totally brain-damaged, as it requires special
+ * care _not_ to reorder parameters and can't be told to work correctly
+ * with ':' as first optstring character at all.
+ */
+
+char *optarg = 0;
+int optind = 1;
+int opterr = 1;
+int optopt = 0;
+extern char *pfmt_label__;
+
+static void
+error(const char *s, int c)
+{
+ /*
+ * Avoid including <unistd.h>, in case its getopt() declaration
+ * conflicts.
+ */
+ extern ssize_t write(int, const void *, size_t);
+ const char *msg = 0;
+ char *buf, *bp;
+
+ if (pfmt_label__)
+ s = pfmt_label__;
+ switch (c) {
+ case '?':
+ msg = ": " msgselect("I","i") "llegal option -- ";
+ break;
+ case ':':
+ msg = ": " msgselect("O","o") "ption requires an argument -- ";
+ break;
+ }
+ bp = buf = alloca(strlen(s) + strlen(msg) + 2);
+ while (*s)
+ *bp++ = *s++;
+ while (*msg)
+ *bp++ = *msg++;
+ *bp++ = optopt;
+ *bp++ = '\n';
+ write(2, buf, bp - buf);
+}
+
+int
+getopt(int argc, char *const argv[], const char *optstring)
+{
+ int colon;
+ static const char *lastp;
+ const char *curp;
+
+ if (optstring[0] == ':') {
+ colon = 1;
+ optstring++;
+ } else
+ colon = 0;
+ if (lastp) {
+ curp = lastp;
+ lastp = 0;
+ } else {
+ if (optind >= argc || argv[optind] == 0 ||
+ argv[optind][0] != '-' ||
+ argv[optind][1] == '\0')
+ return -1;
+ if (argv[optind][1] == '-' && argv[optind][2] == '\0') {
+ optind++;
+ return -1;
+ }
+ curp = &argv[optind][1];
+ }
+ optopt = curp[0] & 0377;
+ while (optstring[0]) {
+ if (optstring[0] == ':') {
+ optstring++;
+ continue;
+ }
+ if ((optstring[0] & 0377) == optopt) {
+ if (optstring[1] == ':') {
+ if (curp[1] != '\0') {
+ optarg = (char *)&curp[1];
+ optind++;
+ } else {
+ if ((optind += 2) > argc) {
+ if (!colon && opterr)
+ error(argv[0], ':');
+ return colon ? ':' : '?';
+ }
+ optarg = argv[optind - 1];
+ }
+ } else {
+ if (curp[1] != '\0')
+ lastp = &curp[1];
+ else
+ optind++;
+ optarg = 0;
+ }
+ return optopt;
+ }
+ optstring++;
+ }
+ if (!colon && opterr)
+ error(argv[0], '?');
+ if (curp[1] != '\0')
+ lastp = &curp[1];
+ else
+ optind++;
+ optarg = 0;
+ return '?';
+}
+
+#ifdef __APPLE__
+/*
+ * Starting with Mac OS 10.5 Leopard, <unistd.h> turns getopt()
+ * into getopt$UNIX2003() by default. Consequently, this function
+ * is called instead of the one defined above. However, optind is
+ * still taken from this file, so in effect, options are not
+ * properly handled. Defining an own getopt$UNIX2003() function
+ * works around this issue.
+ */
+int
+getopt$UNIX2003(int argc, char *const argv[], const char *optstring)
+{
+ return getopt(argc, argv, optstring);
+}
+#endif /* __APPLE__ */