xref: /minix3/external/bsd/bind/dist/lib/isc/commandline.c (revision 00b67f09dd46474d133c95011a48590a8e8f94c7)
1*00b67f09SDavid van Moolenbroek /*	$NetBSD: commandline.c,v 1.5 2014/12/10 04:37:59 christos Exp $	*/
2*00b67f09SDavid van Moolenbroek 
3*00b67f09SDavid van Moolenbroek /*
4*00b67f09SDavid van Moolenbroek  * Portions Copyright (C) 2004, 2005, 2007, 2008, 2014  Internet Systems Consortium, Inc. ("ISC")
5*00b67f09SDavid van Moolenbroek  * Portions Copyright (C) 1999-2001  Internet Software Consortium.
6*00b67f09SDavid van Moolenbroek  *
7*00b67f09SDavid van Moolenbroek  * Permission to use, copy, modify, and/or distribute this software for any
8*00b67f09SDavid van Moolenbroek  * purpose with or without fee is hereby granted, provided that the above
9*00b67f09SDavid van Moolenbroek  * copyright notice and this permission notice appear in all copies.
10*00b67f09SDavid van Moolenbroek  *
11*00b67f09SDavid van Moolenbroek  * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
12*00b67f09SDavid van Moolenbroek  * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
13*00b67f09SDavid van Moolenbroek  * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
14*00b67f09SDavid van Moolenbroek  * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
15*00b67f09SDavid van Moolenbroek  * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
16*00b67f09SDavid van Moolenbroek  * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
17*00b67f09SDavid van Moolenbroek  * PERFORMANCE OF THIS SOFTWARE.
18*00b67f09SDavid van Moolenbroek  */
19*00b67f09SDavid van Moolenbroek 
20*00b67f09SDavid van Moolenbroek /*
21*00b67f09SDavid van Moolenbroek  * Copyright (c) 1987, 1993, 1994
22*00b67f09SDavid van Moolenbroek  *	The Regents of the University of California.  All rights reserved.
23*00b67f09SDavid van Moolenbroek  *
24*00b67f09SDavid van Moolenbroek  * Redistribution and use in source and binary forms, with or without
25*00b67f09SDavid van Moolenbroek  * modification, are permitted provided that the following conditions
26*00b67f09SDavid van Moolenbroek  * are met:
27*00b67f09SDavid van Moolenbroek  * 1. Redistributions of source code must retain the above copyright
28*00b67f09SDavid van Moolenbroek  *    notice, this list of conditions and the following disclaimer.
29*00b67f09SDavid van Moolenbroek  * 2. Redistributions in binary form must reproduce the above copyright
30*00b67f09SDavid van Moolenbroek  *    notice, this list of conditions and the following disclaimer in the
31*00b67f09SDavid van Moolenbroek  *    documentation and/or other materials provided with the distribution.
32*00b67f09SDavid van Moolenbroek  * 3. Neither the name of the University nor the names of its contributors
33*00b67f09SDavid van Moolenbroek  *    may be used to endorse or promote products derived from this software
34*00b67f09SDavid van Moolenbroek  *    without specific prior written permission.
35*00b67f09SDavid van Moolenbroek  *
36*00b67f09SDavid van Moolenbroek  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
37*00b67f09SDavid van Moolenbroek  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
38*00b67f09SDavid van Moolenbroek  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
39*00b67f09SDavid van Moolenbroek  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
40*00b67f09SDavid van Moolenbroek  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
41*00b67f09SDavid van Moolenbroek  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
42*00b67f09SDavid van Moolenbroek  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
43*00b67f09SDavid van Moolenbroek  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
44*00b67f09SDavid van Moolenbroek  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
45*00b67f09SDavid van Moolenbroek  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
46*00b67f09SDavid van Moolenbroek  * SUCH DAMAGE.
47*00b67f09SDavid van Moolenbroek  */
48*00b67f09SDavid van Moolenbroek 
49*00b67f09SDavid van Moolenbroek /* Id: commandline.c,v 1.22 2008/09/25 04:02:39 tbox Exp  */
50*00b67f09SDavid van Moolenbroek 
51*00b67f09SDavid van Moolenbroek /*! \file
52*00b67f09SDavid van Moolenbroek  * This file was adapted from the NetBSD project's source tree, RCS ID:
53*00b67f09SDavid van Moolenbroek  *    NetBSD: getopt.c,v 1.15 1999/09/20 04:39:37 lukem Exp
54*00b67f09SDavid van Moolenbroek  *
55*00b67f09SDavid van Moolenbroek  * The primary change has been to rename items to the ISC namespace
56*00b67f09SDavid van Moolenbroek  * and format in the ISC coding style.
57*00b67f09SDavid van Moolenbroek  */
58*00b67f09SDavid van Moolenbroek 
59*00b67f09SDavid van Moolenbroek /*
60*00b67f09SDavid van Moolenbroek  * \author Principal Authors: Computer Systems Research Group at UC Berkeley
61*00b67f09SDavid van Moolenbroek  * \author Principal ISC caretaker: DCL
62*00b67f09SDavid van Moolenbroek  */
63*00b67f09SDavid van Moolenbroek 
64*00b67f09SDavid van Moolenbroek #include <config.h>
65*00b67f09SDavid van Moolenbroek 
66*00b67f09SDavid van Moolenbroek #include <stdio.h>
67*00b67f09SDavid van Moolenbroek 
68*00b67f09SDavid van Moolenbroek #include <isc/commandline.h>
69*00b67f09SDavid van Moolenbroek #include <isc/msgs.h>
70*00b67f09SDavid van Moolenbroek #include <isc/string.h>
71*00b67f09SDavid van Moolenbroek #include <isc/util.h>
72*00b67f09SDavid van Moolenbroek 
73*00b67f09SDavid van Moolenbroek /*% Index into parent argv vector. */
74*00b67f09SDavid van Moolenbroek LIBISC_EXTERNAL_DATA int isc_commandline_index = 1;
75*00b67f09SDavid van Moolenbroek /*% Character checked for validity. */
76*00b67f09SDavid van Moolenbroek LIBISC_EXTERNAL_DATA int isc_commandline_option;
77*00b67f09SDavid van Moolenbroek /*% Argument associated with option. */
78*00b67f09SDavid van Moolenbroek LIBISC_EXTERNAL_DATA char *isc_commandline_argument;
79*00b67f09SDavid van Moolenbroek /*% For printing error messages. */
80*00b67f09SDavid van Moolenbroek LIBISC_EXTERNAL_DATA char *isc_commandline_progname;
81*00b67f09SDavid van Moolenbroek /*% Print error messages. */
82*00b67f09SDavid van Moolenbroek LIBISC_EXTERNAL_DATA isc_boolean_t isc_commandline_errprint = ISC_TRUE;
83*00b67f09SDavid van Moolenbroek /*% Reset processing. */
84*00b67f09SDavid van Moolenbroek LIBISC_EXTERNAL_DATA isc_boolean_t isc_commandline_reset = ISC_TRUE;
85*00b67f09SDavid van Moolenbroek 
86*00b67f09SDavid van Moolenbroek static char endopt = '\0';
87*00b67f09SDavid van Moolenbroek 
88*00b67f09SDavid van Moolenbroek #define	BADOPT	'?'
89*00b67f09SDavid van Moolenbroek #define	BADARG	':'
90*00b67f09SDavid van Moolenbroek #define ENDOPT  &endopt
91*00b67f09SDavid van Moolenbroek 
92*00b67f09SDavid van Moolenbroek /*!
93*00b67f09SDavid van Moolenbroek  * getopt --
94*00b67f09SDavid van Moolenbroek  *	Parse argc/argv argument vector.
95*00b67f09SDavid van Moolenbroek  */
96*00b67f09SDavid van Moolenbroek int
isc_commandline_parse(int argc,char * const * argv,const char * options)97*00b67f09SDavid van Moolenbroek isc_commandline_parse(int argc, char * const *argv, const char *options) {
98*00b67f09SDavid van Moolenbroek 	static char *place = ENDOPT;
99*00b67f09SDavid van Moolenbroek 	char *option;			/* Index into *options of option. */
100*00b67f09SDavid van Moolenbroek 
101*00b67f09SDavid van Moolenbroek 	REQUIRE(argc >= 0 && argv != NULL && options != NULL);
102*00b67f09SDavid van Moolenbroek 
103*00b67f09SDavid van Moolenbroek 	/*
104*00b67f09SDavid van Moolenbroek 	 * Update scanning pointer, either because a reset was requested or
105*00b67f09SDavid van Moolenbroek 	 * the previous argv was finished.
106*00b67f09SDavid van Moolenbroek 	 */
107*00b67f09SDavid van Moolenbroek 	if (isc_commandline_reset || *place == '\0') {
108*00b67f09SDavid van Moolenbroek 		if (isc_commandline_reset) {
109*00b67f09SDavid van Moolenbroek 			isc_commandline_index = 1;
110*00b67f09SDavid van Moolenbroek 			isc_commandline_reset = ISC_FALSE;
111*00b67f09SDavid van Moolenbroek 		}
112*00b67f09SDavid van Moolenbroek 
113*00b67f09SDavid van Moolenbroek 		if (isc_commandline_progname == NULL)
114*00b67f09SDavid van Moolenbroek 			isc_commandline_progname = argv[0];
115*00b67f09SDavid van Moolenbroek 
116*00b67f09SDavid van Moolenbroek 		if (isc_commandline_index >= argc ||
117*00b67f09SDavid van Moolenbroek 		    *(place = argv[isc_commandline_index]) != '-') {
118*00b67f09SDavid van Moolenbroek 			/*
119*00b67f09SDavid van Moolenbroek 			 * Index out of range or points to non-option.
120*00b67f09SDavid van Moolenbroek 			 */
121*00b67f09SDavid van Moolenbroek 			place = ENDOPT;
122*00b67f09SDavid van Moolenbroek 			return (-1);
123*00b67f09SDavid van Moolenbroek 		}
124*00b67f09SDavid van Moolenbroek 
125*00b67f09SDavid van Moolenbroek 		if (place[1] != '\0' && *++place == '-' && place[1] == '\0') {
126*00b67f09SDavid van Moolenbroek 			/*
127*00b67f09SDavid van Moolenbroek 			 * Found '--' to signal end of options.  Advance
128*00b67f09SDavid van Moolenbroek 			 * index to next argv, the first non-option.
129*00b67f09SDavid van Moolenbroek 			 */
130*00b67f09SDavid van Moolenbroek 			isc_commandline_index++;
131*00b67f09SDavid van Moolenbroek 			place = ENDOPT;
132*00b67f09SDavid van Moolenbroek 			return (-1);
133*00b67f09SDavid van Moolenbroek 		}
134*00b67f09SDavid van Moolenbroek 	}
135*00b67f09SDavid van Moolenbroek 
136*00b67f09SDavid van Moolenbroek 	isc_commandline_option = *place++;
137*00b67f09SDavid van Moolenbroek 	option = strchr(options, isc_commandline_option);
138*00b67f09SDavid van Moolenbroek 
139*00b67f09SDavid van Moolenbroek 	/*
140*00b67f09SDavid van Moolenbroek 	 * Ensure valid option has been passed as specified by options string.
141*00b67f09SDavid van Moolenbroek 	 * '-:' is never a valid command line option because it could not
142*00b67f09SDavid van Moolenbroek 	 * distinguish ':' from the argument specifier in the options string.
143*00b67f09SDavid van Moolenbroek 	 */
144*00b67f09SDavid van Moolenbroek 	if (isc_commandline_option == ':' || option == NULL) {
145*00b67f09SDavid van Moolenbroek 		if (*place == '\0')
146*00b67f09SDavid van Moolenbroek 			isc_commandline_index++;
147*00b67f09SDavid van Moolenbroek 
148*00b67f09SDavid van Moolenbroek 		if (isc_commandline_errprint && *options != ':')
149*00b67f09SDavid van Moolenbroek 			fprintf(stderr, "%s: %s -- %c\n",
150*00b67f09SDavid van Moolenbroek 				isc_commandline_progname,
151*00b67f09SDavid van Moolenbroek 				isc_msgcat_get(isc_msgcat,
152*00b67f09SDavid van Moolenbroek 					       ISC_MSGSET_COMMANDLINE,
153*00b67f09SDavid van Moolenbroek 					       ISC_MSG_ILLEGALOPT,
154*00b67f09SDavid van Moolenbroek 					       "illegal option"),
155*00b67f09SDavid van Moolenbroek 				isc_commandline_option);
156*00b67f09SDavid van Moolenbroek 
157*00b67f09SDavid van Moolenbroek 		return (BADOPT);
158*00b67f09SDavid van Moolenbroek 	}
159*00b67f09SDavid van Moolenbroek 
160*00b67f09SDavid van Moolenbroek 	if (*++option != ':') {
161*00b67f09SDavid van Moolenbroek 		/*
162*00b67f09SDavid van Moolenbroek 		 * Option does not take an argument.
163*00b67f09SDavid van Moolenbroek 		 */
164*00b67f09SDavid van Moolenbroek 		isc_commandline_argument = NULL;
165*00b67f09SDavid van Moolenbroek 
166*00b67f09SDavid van Moolenbroek 		/*
167*00b67f09SDavid van Moolenbroek 		 * Skip to next argv if at the end of the current argv.
168*00b67f09SDavid van Moolenbroek 		 */
169*00b67f09SDavid van Moolenbroek 		if (*place == '\0')
170*00b67f09SDavid van Moolenbroek 			++isc_commandline_index;
171*00b67f09SDavid van Moolenbroek 
172*00b67f09SDavid van Moolenbroek 	} else {
173*00b67f09SDavid van Moolenbroek 		/*
174*00b67f09SDavid van Moolenbroek 		 * Option needs an argument.
175*00b67f09SDavid van Moolenbroek 		 */
176*00b67f09SDavid van Moolenbroek 		if (*place != '\0')
177*00b67f09SDavid van Moolenbroek 			/*
178*00b67f09SDavid van Moolenbroek 			 * Option is in this argv, -D1 style.
179*00b67f09SDavid van Moolenbroek 			 */
180*00b67f09SDavid van Moolenbroek 			isc_commandline_argument = place;
181*00b67f09SDavid van Moolenbroek 
182*00b67f09SDavid van Moolenbroek 		else if (argc > ++isc_commandline_index)
183*00b67f09SDavid van Moolenbroek 			/*
184*00b67f09SDavid van Moolenbroek 			 * Option is next argv, -D 1 style.
185*00b67f09SDavid van Moolenbroek 			 */
186*00b67f09SDavid van Moolenbroek 			isc_commandline_argument = argv[isc_commandline_index];
187*00b67f09SDavid van Moolenbroek 
188*00b67f09SDavid van Moolenbroek 		else {
189*00b67f09SDavid van Moolenbroek 			/*
190*00b67f09SDavid van Moolenbroek 			 * Argument needed, but no more argv.
191*00b67f09SDavid van Moolenbroek 			 */
192*00b67f09SDavid van Moolenbroek 			place = ENDOPT;
193*00b67f09SDavid van Moolenbroek 
194*00b67f09SDavid van Moolenbroek 			/*
195*00b67f09SDavid van Moolenbroek 			 * Silent failure with "missing argument" return
196*00b67f09SDavid van Moolenbroek 			 * when ':' starts options string, per historical spec.
197*00b67f09SDavid van Moolenbroek 			 */
198*00b67f09SDavid van Moolenbroek 			if (*options == ':')
199*00b67f09SDavid van Moolenbroek 				return (BADARG);
200*00b67f09SDavid van Moolenbroek 
201*00b67f09SDavid van Moolenbroek 			if (isc_commandline_errprint)
202*00b67f09SDavid van Moolenbroek 				fprintf(stderr, "%s: %s -- %c\n",
203*00b67f09SDavid van Moolenbroek 					isc_commandline_progname,
204*00b67f09SDavid van Moolenbroek 					isc_msgcat_get(isc_msgcat,
205*00b67f09SDavid van Moolenbroek 						       ISC_MSGSET_COMMANDLINE,
206*00b67f09SDavid van Moolenbroek 						       ISC_MSG_OPTNEEDARG,
207*00b67f09SDavid van Moolenbroek 						       "option requires "
208*00b67f09SDavid van Moolenbroek 						       "an argument"),
209*00b67f09SDavid van Moolenbroek 					isc_commandline_option);
210*00b67f09SDavid van Moolenbroek 
211*00b67f09SDavid van Moolenbroek 			return (BADOPT);
212*00b67f09SDavid van Moolenbroek 		}
213*00b67f09SDavid van Moolenbroek 
214*00b67f09SDavid van Moolenbroek 		place = ENDOPT;
215*00b67f09SDavid van Moolenbroek 
216*00b67f09SDavid van Moolenbroek 		/*
217*00b67f09SDavid van Moolenbroek 		 * Point to argv that follows argument.
218*00b67f09SDavid van Moolenbroek 		 */
219*00b67f09SDavid van Moolenbroek 		isc_commandline_index++;
220*00b67f09SDavid van Moolenbroek 	}
221*00b67f09SDavid van Moolenbroek 
222*00b67f09SDavid van Moolenbroek 	return (isc_commandline_option);
223*00b67f09SDavid van Moolenbroek }
224