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 (char *)""
51
ares_getopt_init(ares_getopt_state_t *state, int nargc, const char **nargv)52 void ares_getopt_init(ares_getopt_state_t *state, int nargc, const char **nargv)
53 {
54 memset(state, 0, sizeof(*state));
55 state->opterr = 1;
56 state->optind = 1;
57 state->place = EMSG;
58 state->argc = nargc;
59 state->argv = nargv;
60 }
61
62 /*
63 * ares_getopt --
64 * Parse argc/argv argument vector.
65 */
ares_getopt(ares_getopt_state_t *state, const char *ostr)66 int ares_getopt(ares_getopt_state_t *state, const char *ostr)
67 {
68 const char *oli; /* option letter list index */
69
70 /* update scanning pointer */
71 if (!*state->place) {
72 if (state->optind >= state->argc) {
73 return -1;
74 }
75 state->place = state->argv[state->optind];
76 if (*(state->place) != '-') {
77 return -1;
78 }
79 state->place++;
80
81 /* found "--" */
82 if (*(state->place) == '-') {
83 state->optind++;
84 return -1;
85 }
86
87 /* Found just - */
88 if (!*(state->place)) {
89 state->optopt = 0;
90 return BADCH;
91 }
92 }
93
94 /* option letter okay? */
95 state->optopt = *(state->place);
96 state->place++;
97 oli = strchr(ostr, state->optopt);
98
99 if (oli == NULL) {
100 if (!(*state->place)) {
101 ++state->optind;
102 }
103 if (state->opterr) {
104 (void)fprintf(stderr, "%s: illegal option -- %c\n", __FILE__,
105 state->optopt);
106 }
107 return BADCH;
108 }
109
110 /* don't need argument */
111 if (*++oli != ':') {
112 state->optarg = NULL;
113 if (!*state->place) {
114 ++state->optind;
115 }
116 } else {
117 /* need an argument */
118 if (*state->place) { /* no white space */
119 state->optarg = state->place;
120 } else if (state->argc <= ++state->optind) { /* no arg */
121 state->place = EMSG;
122 if (*ostr == ':') {
123 return BADARG;
124 }
125 if (state->opterr) {
126 (void)fprintf(stderr, "%s: option requires an argument -- %c\n",
127 __FILE__, state->optopt);
128 }
129 return BADARG;
130 } else { /* white space */
131 state->optarg = state->argv[state->optind];
132 }
133 state->place = EMSG;
134 ++state->optind;
135 }
136 return state->optopt; /* dump back option letter */
137 }
138