1 /*
2 * GetOpt functions
3 *
4 * Copyright (C) 2012-2021, Joachim Metz <joachim.metz@gmail.com>
5 *
6 * Refer to AUTHORS for acknowledgements.
7 *
8 * This program is free software: you can redistribute it and/or modify
9 * it under the terms of the GNU Lesser General Public License as published by
10 * the Free Software Foundation, either version 3 of the License, or
11 * (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU Lesser General Public License
19 * along with this program. If not, see <https://www.gnu.org/licenses/>.
20 */
21
22 #include <common.h>
23 #include <narrow_string.h>
24 #include <system_string.h>
25 #include <types.h>
26 #include <wide_string.h>
27
28 #if defined( HAVE_STDLIB_H ) || defined( WINAPI )
29 #include <stdlib.h>
30 #endif
31
32 #include "modi_test_getopt.h"
33 #include "modi_test_libcnotify.h"
34
35 #if !defined( HAVE_GETOPT )
36
37 /* The option index
38 * Start with argument 1 (argument 0 is the program name)
39 */
40 int optind = 1;
41
42 /* The current option argument
43 */
44 system_character_t *optarg = NULL;
45
46 /* Value to indicate the current option
47 */
48 system_integer_t optopt = 0;
49
50 /* The next option in a group
51 */
52 system_character_t *next_option = NULL;
53
54 /* Get the program options
55 * Function for platforms that do not have the getopt function
56 * Returns the option character processed, or -1 on error,
57 * ? if the option was not in the options string, : if the option argument was missing
58 */
modi_test_getopt(int argument_count,system_character_t * const argument_values[],const system_character_t * options_string)59 system_integer_t modi_test_getopt(
60 int argument_count,
61 system_character_t * const argument_values[],
62 const system_character_t *options_string )
63 {
64 system_character_t *argument_value = NULL;
65 system_character_t *option_value = NULL;
66 static char *function = "modi_test_getopt";
67 size_t options_string_length = 0;
68
69 if( next_option != NULL )
70 {
71 argument_value = next_option;
72 next_option = NULL;
73 }
74 else if( optind >= argument_count )
75 {
76 return( (system_integer_t) -1 );
77 }
78 else
79 {
80 argument_value = argument_values[ optind ];
81
82 /* Check if the argument value is not an empty string
83 */
84 if( *argument_value == (system_character_t) '\0' )
85 {
86 return( (system_integer_t) -1 );
87 }
88 /* Check if the first character is a option marker '-'
89 */
90 if( *argument_value != (system_character_t) '-' )
91 {
92 return( (system_integer_t) -1 );
93 }
94 argument_value++;
95
96 /* Check if long options are provided '--'
97 */
98 if( *argument_value == (system_character_t) '-' )
99 {
100 optind++;
101
102 return( (system_integer_t) -1 );
103 }
104 }
105 options_string_length = system_string_length(
106 options_string );
107
108 optopt = *argument_value;
109 option_value = system_string_search_character(
110 options_string,
111 optopt,
112 options_string_length );
113
114 argument_value++;
115
116 /* Check if an argument was specified or that the option was not found
117 * in the option string
118 */
119 if( ( optopt == (system_integer_t) ':' )
120 || ( option_value == NULL ) )
121 {
122 if( *argument_value == (system_character_t) '\0' )
123 {
124 optind++;
125 }
126 if( ( *options_string != (system_character_t) ':' )
127 && ( optopt != (system_integer_t) '?' ) )
128 {
129 libcnotify_printf(
130 "%s: no such option: %" PRIc_SYSTEM ".\n",
131 function,
132 optopt );
133 }
134 return( (system_integer_t) '?' );
135 }
136 option_value++;
137
138 /* Check if no option argument is required
139 */
140 if( *option_value != (system_character_t) ':' )
141 {
142 optarg = NULL;
143
144 if( *argument_value == (system_character_t) '\0' )
145 {
146 optind++;
147 }
148 else
149 {
150 /* Multiple options are grouped
151 */
152 next_option = argument_value;
153 }
154 }
155 /* Check if the argument is right after the option flag with no space in between
156 */
157 else if( *argument_value != (system_character_t) '\0' )
158 {
159 optarg = argument_value;
160
161 optind++;
162 }
163 else
164 {
165 optind++;
166
167 /* Check if the argument was provided as the next argument value
168 */
169 if( argument_count <= optind )
170 {
171 if( *option_value == ':' )
172 {
173 return( (system_integer_t) ':' );
174 }
175 libcnotify_printf(
176 "%s: option: %" PRIc_SYSTEM " requires an argument.\n",
177 function,
178 optopt );
179
180 return( (system_integer_t) '?' );
181 }
182 optarg = argument_values[ optind ];
183
184 optind++;
185 }
186 return( optopt );
187 }
188
189 #endif /* !defined( HAVE_GETOPT ) */
190
191