tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

getopt_long.c (6304B)


      1 /*
      2 * Copyright (c) 1987, 1993, 1994, 1996
      3 *	The Regents of the University of California.  All rights reserved.
      4 *
      5 * Redistribution and use in source and binary forms, with or without
      6 * modification, are permitted provided that the following conditions
      7 * are met:
      8 * 1. Redistributions of source code must retain the above copyright
      9 *    notice, this list of conditions and the following disclaimer.
     10 * 2. Redistributions in binary form must reproduce the above copyright
     11 *    notice, this list of conditions and the following disclaimer in the
     12 *    documentation and/or other materials provided with the distribution.
     13 * 3. Neither the names of the copyright holders nor the names of its
     14 *    contributors may be used to endorse or promote products derived from
     15 *    this software without specific prior written permission.
     16 *
     17 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS 
     18 * IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
     19 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     20 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE
     21 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
     22 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
     23 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
     24 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
     25 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
     26 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
     27 * POSSIBILITY OF SUCH DAMAGE.
     28 */
     29 #include <assert.h>
     30 #include <errno.h>
     31 #include <stdio.h>
     32 #include <stdlib.h>
     33 #include <string.h>
     34 #include "getopt.h"
     35 
     36 extern int	  opterr;	/* if error message should be printed */
     37 extern int	  optind;	/* index into parent argv vector */
     38 extern int	  optopt;	/* character checked for validity */
     39 extern int	  optreset;	/* reset getopt */
     40 extern char *optarg;	/* argument associated with option */
     41 
     42 #define __P(x) x
     43 #define _DIAGASSERT(x) assert(x)
     44 
     45 static char * __progname __P((char *));
     46 int getopt_internal __P((int, char * const *, const char *));
     47 
     48 static char *
     49 __progname(nargv0)
     50 char * nargv0;
     51 {
     52 char * tmp;
     53 
     54 _DIAGASSERT(nargv0 != NULL);
     55 
     56 tmp = strrchr(nargv0, '/');
     57 if (tmp)
     58 	tmp++;
     59 else
     60 	tmp = nargv0;
     61 return(tmp);
     62 }
     63 
     64 #define	BADCH	(int)'?'
     65 #define	BADARG	(int)':'
     66 #define	EMSG	""
     67 
     68 /*
     69 * getopt --
     70 *	Parse argc/argv argument vector.
     71 */
     72 int
     73 getopt_internal(nargc, nargv, ostr)
     74 int nargc;
     75 char * const *nargv;
     76 const char *ostr;
     77 {
     78 static char *place = EMSG;		/* option letter processing */
     79 char *oli;				/* option letter list index */
     80 
     81 _DIAGASSERT(nargv != NULL);
     82 _DIAGASSERT(ostr != NULL);
     83 
     84 if (optreset || !*place) {		/* update scanning pointer */
     85 	optreset = 0;
     86 	if (optind >= nargc || *(place = nargv[optind]) != '-') {
     87 		place = EMSG;
     88 		return (-1);
     89 	}
     90 	if (place[1] && *++place == '-') {	/* found "--" */
     91 		/* ++optind; */
     92 		place = EMSG;
     93 		return (-2);
     94 	}
     95 }					/* option letter okay? */
     96 if ((optopt = (int)*place++) == (int)':' ||
     97     !(oli = strchr(ostr, optopt))) {
     98 	/*
     99 	 * if the user didn't specify '-' as an option,
    100 	 * assume it means -1.
    101 	 */
    102 	if (optopt == (int)'-')
    103 		return (-1);
    104 	if (!*place)
    105 		++optind;
    106 	if (opterr && *ostr != ':')
    107 		(void)fprintf(stderr,
    108 		    "%s: illegal option -- %c\n", __progname(nargv[0]), optopt);
    109 	return (BADCH);
    110 }
    111 if (*++oli != ':') {			/* don't need argument */
    112 	optarg = NULL;
    113 	if (!*place)
    114 		++optind;
    115 } else {				/* need an argument */
    116 	if (*place)			/* no white space */
    117 		optarg = place;
    118 	else if (nargc <= ++optind) {	/* no arg */
    119 		place = EMSG;
    120 		if ((opterr) && (*ostr != ':'))
    121 			(void)fprintf(stderr,
    122 			    "%s: option requires an argument -- %c\n",
    123 			    __progname(nargv[0]), optopt);
    124 		return (BADARG);
    125 	} else				/* white space */
    126 		optarg = nargv[optind];
    127 	place = EMSG;
    128 	++optind;
    129 }
    130 return (optopt);			/* dump back option letter */
    131 }
    132 
    133 #if 0
    134 /*
    135 * getopt --
    136 *	Parse argc/argv argument vector.
    137 */
    138 int
    139 getopt2(nargc, nargv, ostr)
    140 int nargc;
    141 char * const *nargv;
    142 const char *ostr;
    143 {
    144 int retval;
    145 
    146 if ((retval = getopt_internal(nargc, nargv, ostr)) == -2) {
    147 	retval = -1;
    148 	++optind; 
    149 }
    150 return(retval);
    151 }
    152 #endif
    153 
    154 /*
    155 * getopt_long --
    156 *	Parse argc/argv argument vector.
    157 */
    158 int
    159 getopt_long(nargc, nargv, options, long_options, index)
    160 int nargc;
    161 char ** nargv;
    162 const char * options;
    163 const struct option * long_options;
    164 int * index;
    165 {
    166 int retval;
    167 
    168 _DIAGASSERT(nargv != NULL);
    169 _DIAGASSERT(options != NULL);
    170 _DIAGASSERT(long_options != NULL);
    171 /* index may be NULL */
    172 
    173 if ((retval = getopt_internal(nargc, nargv, options)) == -2) {
    174 	char *current_argv = nargv[optind++] + 2, *has_equal;
    175 	int i, match = -1;
    176 	size_t current_argv_len;
    177 
    178 	if (*current_argv == '\0') {
    179 		return(-1);
    180 	}
    181 	if ((has_equal = strchr(current_argv, '=')) != NULL) {
    182 		current_argv_len = has_equal - current_argv;
    183 		has_equal++;
    184 	} else
    185 		current_argv_len = strlen(current_argv);
    186 
    187 	for (i = 0; long_options[i].name; i++) {
    188 		if (strncmp(current_argv, long_options[i].name, current_argv_len))
    189 			continue;
    190 
    191 		if (strlen(long_options[i].name) == current_argv_len) {
    192 			match = i;
    193 			break;
    194 		}
    195 		if (match == -1)
    196 			match = i;
    197 	}
    198 	if (match != -1) {
    199 		if (long_options[match].has_arg == required_argument ||
    200 		    long_options[match].has_arg == optional_argument) {
    201 			if (has_equal)
    202 				optarg = has_equal;
    203 			else
    204 				optarg = nargv[optind++];
    205 		}
    206 		if ((long_options[match].has_arg == required_argument)
    207 		    && (optarg == NULL)) {
    208 			/*
    209 			 * Missing argument, leading :
    210 			 * indicates no error should be generated
    211 			 */
    212 			if ((opterr) && (*options != ':'))
    213 				(void)fprintf(stderr,
    214 			      "%s: option requires an argument -- %s\n",
    215 			      __progname(nargv[0]), current_argv);
    216 			return (BADARG);
    217 		}
    218 	} else { /* No matching argument */
    219 		if ((opterr) && (*options != ':'))
    220 			(void)fprintf(stderr,
    221 			    "%s: illegal option -- %s\n", __progname(nargv[0]), current_argv);
    222 		return (BADCH);
    223 	}
    224 	if (long_options[match].flag) {
    225 		*long_options[match].flag = long_options[match].val;
    226 		retval = 0;
    227 	} else 
    228 		retval = long_options[match].val;
    229 	if (index)
    230 		*index = match;
    231 }
    232 return(retval);
    233 }