summaryrefslogtreecommitdiff
path: root/tools/cpio/src/getopt.c
diff options
context:
space:
mode:
authorWaldemar Brodkorb <wbx@openadk.org>2010-07-29 15:25:12 +0200
committerWaldemar Brodkorb <wbx@openadk.org>2010-07-29 15:25:12 +0200
commitfd6481d82ff407139157e53df28563d40bb3ad3b (patch)
treeed2ae9e08c31d1eed424793272a60c25cdec6c00 /tools/cpio/src/getopt.c
parent14804005d5b33beb6f52d4a72034acb00c00eb90 (diff)
add a cpio implementation to tools directory
cpio utility is a mess in point of portability. For example NetBSD cpio implementation does not support userid and groupid changes for the archive. This feature is required for initramfs filesystem targets. This cpio is from the Heirloom project. Fix needed rebuild of tools, when changing targets.
Diffstat (limited to 'tools/cpio/src/getopt.c')
-rw-r--r--tools/cpio/src/getopt.c141
1 files changed, 141 insertions, 0 deletions
diff --git a/tools/cpio/src/getopt.c b/tools/cpio/src/getopt.c
new file mode 100644
index 000000000..0a68ac8e9
--- /dev/null
+++ b/tools/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__ */