From fd6481d82ff407139157e53df28563d40bb3ad3b Mon Sep 17 00:00:00 2001 From: Waldemar Brodkorb Date: Thu, 29 Jul 2010 15:25:12 +0200 Subject: 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. --- tools/cpio/src/getopt.c | 141 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 141 insertions(+) create mode 100644 tools/cpio/src/getopt.c (limited to 'tools/cpio/src/getopt.c') 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 +#include +#include +#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 , 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, 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__ */ -- cgit v1.2.3