1 /*
2 * Original file name getopt.c Initial import into the c-ares source tree
3 * on 2007-04-11. Lifted from version 5.2 of the 'Open Mash' project with
4 * the modified BSD license, BSD license without the advertising clause.
5 *
6 */
7
8 /*
9 * getopt.c --
10 *
11 * Standard UNIX getopt function. Code is from BSD.
12 *
13 * Copyright (c) 1987-2001 The Regents of the University of California.
14 * All rights reserved.
15 *
16 * Redistribution and use in source and binary forms, with or without
17 * modification, are permitted provided that the following conditions are met:
18 *
19 * A. Redistributions of source code must retain the above copyright notice,
20 * this list of conditions and the following disclaimer.
21 * B. Redistributions in binary form must reproduce the above copyright notice,
22 * this list of conditions and the following disclaimer in the documentation
23 * and/or other materials provided with the distribution.
24 * C. Neither the names of the copyright holders nor the names of its
25 * contributors may be used to endorse or promote products derived from this
26 * software without specific prior written permission.
27 *
28 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS
29 * IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
30 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
31 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE
32 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
33 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
34 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
35 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
36 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
37 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
38 * POSSIBILITY OF SUCH DAMAGE.
39 *
40 * SPDX-License-Identifier: BSD-3-Clause
41 */
42
43 #include <stdio.h>
44 #include <stdlib.h>
45 #include <string.h>
46 #include "ares_getopt.h"
47
48 #define BADCH (int)'?'
49 #define BADARG (int)':'
50 #define EMSG ""
51
ares_getopt_init(ares_getopt_state_t * state,int nargc,const char * const * nargv)52 void ares_getopt_init(ares_getopt_state_t *state, int nargc,
53 const char * const *nargv)
54 {
55 memset(state, 0, sizeof(*state));
56 state->opterr = 1;
57 state->optind = 1;
58 state->place = EMSG;
59 state->argc = nargc;
60 state->argv = nargv;
61 }
62
63 /*
64 * ares_getopt --
65 * Parse argc/argv argument vector.
66 */
ares_getopt(ares_getopt_state_t * state,const char * ostr)67 int ares_getopt(ares_getopt_state_t *state, const char *ostr)
68 {
69 const char *oli; /* option letter list index */
70
71 /* update scanning pointer */
72 if (!*state->place) {
73 if (state->optind >= state->argc) {
74 return -1;
75 }
76 state->place = state->argv[state->optind];
77 if (*(state->place) != '-') {
78 return -1;
79 }
80 state->place++;
81
82 /* found "--" */
83 if (*(state->place) == '-') {
84 state->optind++;
85 return -1;
86 }
87
88 /* Found just - */
89 if (!*(state->place)) {
90 state->optopt = 0;
91 return BADCH;
92 }
93 }
94
95 /* option letter okay? */
96 state->optopt = *(state->place);
97 state->place++;
98 oli = strchr(ostr, state->optopt);
99
100 if (oli == NULL) {
101 if (!(*state->place)) {
102 ++state->optind;
103 }
104 if (state->opterr) {
105 (void)fprintf(stderr, "%s: illegal option -- %c\n", __FILE__,
106 state->optopt);
107 }
108 return BADCH;
109 }
110
111 /* don't need argument */
112 if (*++oli != ':') {
113 state->optarg = NULL;
114 if (!*state->place) {
115 ++state->optind;
116 }
117 } else {
118 /* need an argument */
119 if (*state->place) { /* no white space */
120 state->optarg = state->place;
121 } else if (state->argc <= ++state->optind) { /* no arg */
122 state->place = EMSG;
123 if (*ostr == ':') {
124 return BADARG;
125 }
126 if (state->opterr) {
127 (void)fprintf(stderr, "%s: option requires an argument -- %c\n",
128 __FILE__, state->optopt);
129 }
130 return BADARG;
131 } else { /* white space */
132 state->optarg = state->argv[state->optind];
133 }
134 state->place = EMSG;
135 ++state->optind;
136 }
137 return state->optopt; /* dump back option letter */
138 }
139