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