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