hbase

heirloom base
git clone git://git.2f30.org/hbase
Log | Files | Refs | README

getopt.c (6585B)


      1 /*
      2  * CDDL HEADER START
      3  *
      4  * The contents of this file are subject to the terms of the
      5  * Common Development and Distribution License, Version 1.0 only
      6  * (the "License").  You may not use this file except in compliance
      7  * with the License.
      8  *
      9  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
     10  * or http://www.opensolaris.org/os/licensing.
     11  * See the License for the specific language governing permissions
     12  * and limitations under the License.
     13  *
     14  * When distributing Covered Code, include this CDDL HEADER in each
     15  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
     16  * If applicable, add the following below this CDDL HEADER, with the
     17  * fields enclosed by brackets "[]" replaced with your own identifying
     18  * information: Portions Copyright [yyyy] [name of copyright owner]
     19  *
     20  * CDDL HEADER END
     21  */
     22 /*
     23  * Copyright 2004 Sun Microsystems, Inc.  All rights reserved.
     24  * Use is subject to license terms.
     25  */
     26 /*
     27  * Portions Copyright (c) 2005 Gunnar Ritter, Freiburg i. Br., Germany
     28  *
     29  * Sccsid @(#)getopt.c	1.10 (gritter) 12/16/07
     30  */
     31 /* from OpenSolaris "getopt.c	1.23	05/06/08 SMI" */
     32 
     33 /*	Copyright (c) 1988 AT&T	*/
     34 /*	  All Rights Reserved  	*/
     35 
     36 
     37 /*
     38  * See getopt(3C) and SUS/XPG getopt() for function definition and
     39  * requirements.
     40  *
     41  * This actual implementation is a bit looser than the specification
     42  * as it allows any character other than ':' to be used as an option
     43  * character - The specification only guarantees the alnum characters
     44  * ([a-z][A-Z][0-9]).
     45  */
     46 
     47 #include <sys/types.h>
     48 #include <string.h>
     49 #include <stdio.h>
     50 
     51 extern ssize_t	write(int, const void *, size_t);
     52 
     53 char	*optarg = NULL;
     54 int	optind = 1;
     55 int	opterr = 1;
     56 int	optopt = 0;
     57 
     58 #define	ERR(s, c)	err(s, c, optstring, argv[0])
     59 static void
     60 err(const char *s, int c, const char *optstring, const char *argv0)
     61 {
     62 	char errbuf[256], *ep = errbuf;
     63 	const char	*cp;
     64 
     65 	if (opterr && optstring[0] != ':') {
     66 		for (cp = argv0; *cp && ep<&errbuf[sizeof errbuf]; cp++, ep++)
     67 			*ep = *cp;
     68 		for (cp = ": "; *cp && ep<&errbuf[sizeof errbuf]; cp++, ep++)
     69 			*ep = *cp;
     70 		for (cp = s; *cp && ep<&errbuf[sizeof errbuf]; cp++, ep++)
     71 			*ep = *cp;
     72 		for (cp = " -- "; *cp && ep<&errbuf[sizeof errbuf]; cp++, ep++)
     73 			*ep = *cp;
     74 		if (ep<&errbuf[sizeof errbuf])
     75 			*ep++ = c;
     76 		if (ep<&errbuf[sizeof errbuf])
     77 			*ep++ = '\n';
     78 		write(2, errbuf, ep - errbuf);
     79 	}
     80 }
     81 
     82 /*
     83  * getopt_sp is required to keep state between successive calls to getopt()
     84  * while extracting aggregated options (ie: -abcd). Hence, getopt() is not
     85  * thread safe or reentrant, but it really doesn't matter.
     86  *
     87  * So, why isn't this "static" you ask?  Because the historical Bourne
     88  * shell has actually latched on to this little piece of private data.
     89  */
     90 int getopt_sp = 1;
     91 
     92 /*
     93  * Determine if the specified character (c) is present in the string
     94  * (optstring) as a regular, single character option. If the option is found,
     95  * return a pointer into optstring pointing at the option character,
     96  * otherwise return null. The character ':' is not allowed.
     97  */
     98 static char *
     99 parse(const char *optstring, const char c)
    100 {
    101 	char *cp = (char *)optstring;
    102 
    103 	if (c == ':')
    104 		return (NULL);
    105 	do {
    106 		if (*cp == c)
    107 			return (cp);
    108 	} while (*cp++ != '\0');
    109 	return (NULL);
    110 }
    111 
    112 /*
    113  * External function entry point.
    114  */
    115 int
    116 getopt(int argc, char *const *argv, const char *optstring)
    117 {
    118 	char	c;
    119 	char	*cp;
    120 
    121 	/*
    122 	 * Has the end of the options been encountered?  The following
    123 	 * implements the SUS requirements:
    124 	 *
    125 	 * If, when getopt() is called:
    126 	 *	argv[optind]	is a null pointer
    127 	 *	*argv[optind]	is not the character '-'
    128 	 *	argv[optind]	points to the string "-"
    129 	 * getopt() returns -1 without changing optind. If
    130 	 *	argv[optind]	points to the string "--"
    131 	 * getopt() returns -1 after incrementing optind.
    132 	 */
    133 	if (getopt_sp == 1) {
    134 		if (optind >= argc || argv[optind][0] != '-' ||
    135 		    argv[optind] == NULL || argv[optind][1] == '\0')
    136 			return (EOF);
    137 		else if (strcmp(argv[optind], "--") == 0) {
    138 			optind++;
    139 			return (EOF);
    140 		}
    141 	}
    142 
    143 	/*
    144 	 * Getting this far indicates that an option has been encountered.
    145 	 * Note that the syntax of optstring applies special meanings to
    146 	 * the characters ':' and '(', so they are not permissible as
    147 	 * option letters. A special meaning is also applied to the ')'
    148 	 * character, but its meaning can be determined from context.
    149 	 * Note that the specification only requires that the alnum
    150 	 * characters be accepted.
    151 	 */
    152 	optopt = c = (unsigned char)argv[optind][getopt_sp];
    153 	optarg = NULL;
    154 	if ((cp = parse(optstring, c)) == NULL) {
    155 		/* LINTED: variable format specifier */
    156 		ERR("illegal option", c);
    157 		if (argv[optind][++getopt_sp] == '\0') {
    158 			optind++;
    159 			getopt_sp = 1;
    160 		}
    161 		return ('?');
    162 	}
    163 	optopt = c = *cp;
    164 
    165 	/*
    166 	 * A valid option has been identified.  If it should have an
    167 	 * option-argument, process that now.  SUS defines the setting
    168 	 * of optarg as follows:
    169 	 *
    170 	 *   1.	If the option was the last character in the string pointed to
    171 	 *	by an element of argv, then optarg contains the next element
    172 	 *	of argv, and optind is incremented by 2. If the resulting
    173 	 *	value of optind is not less than argc, this indicates a
    174 	 *	missing option-argument, and getopt() returns an error
    175 	 *	indication.
    176 	 *
    177 	 *   2.	Otherwise, optarg points to the string following the option
    178 	 *	character in that element of argv, and optind is incremented
    179 	 *	by 1.
    180 	 *
    181 	 * The second clause allows -abcd (where b requires an option-argument)
    182 	 * to be interpreted as "-a -b cd".
    183 	 */
    184 	if (*(cp + 1) == ':') {
    185 		/* The option takes an argument */
    186 		if (argv[optind][getopt_sp+1] != '\0') {
    187 			optarg = &argv[optind++][getopt_sp+1];
    188 		} else if (++optind >= argc) {
    189 			/* LINTED: variable format specifier */
    190 			ERR("option requires an argument", c);
    191 			getopt_sp = 1;
    192 			optarg = NULL;
    193 			return (optstring[0] == ':' ? ':' : '?');
    194 		} else
    195 			optarg = argv[optind++];
    196 		getopt_sp = 1;
    197 	} else {
    198 		/* The option does NOT take an argument */
    199 		if (argv[optind][++getopt_sp] == '\0') {
    200 			getopt_sp = 1;
    201 			optind++;
    202 		}
    203 		optarg = NULL;
    204 	}
    205 	return (c);
    206 } /* getopt() */
    207 
    208 #ifdef __APPLE__
    209 /*
    210  * Starting with Mac OS 10.5 Leopard, <unistd.h> turns getopt()
    211  * into getopt$UNIX2003() by default. Consequently, this function
    212  * is called instead of the one defined above. However, optind is
    213  * still taken from this file, so in effect, options are not
    214  * properly handled. Defining an own getopt$UNIX2003() function
    215  * works around this issue.
    216  */
    217 int
    218 getopt$UNIX2003(int argc, char *const argv[], const char *optstring)
    219 {
    220 	return getopt(argc, argv, optstring);
    221 }
    222 #endif	/* __APPLE__ */