This source file includes following definitions.
- bump_verbosity
- pcmk__new_common_args
- free_common_args
- pcmk__build_arg_context
- pcmk__free_arg_context
- pcmk__add_main_args
- pcmk__add_arg_group
- string_replace
- pcmk__quote_cmdline
- pcmk__cmdline_preproc
- G_GNUC_PRINTF
1
2
3
4
5
6
7
8
9
10 #include <crm_internal.h>
11
12 #include <ctype.h>
13 #include <glib.h>
14
15 #include <crm/crm.h>
16 #include <crm/common/cmdline_internal.h>
17 #include <crm/common/strings_internal.h>
18 #include <crm/common/util.h>
19
20 static gboolean
21 bump_verbosity(const gchar *option_name, const gchar *optarg, gpointer data, GError **error) {
22 pcmk__common_args_t *common_args = (pcmk__common_args_t *) data;
23 common_args->verbosity++;
24 return TRUE;
25 }
26
27 pcmk__common_args_t *
28 pcmk__new_common_args(const char *summary)
29 {
30 pcmk__common_args_t *args = NULL;
31
32 args = calloc(1, sizeof(pcmk__common_args_t));
33 if (args == NULL) {
34 crm_exit(CRM_EX_OSERR);
35 }
36
37 args->summary = strdup(summary);
38 if (args->summary == NULL) {
39 free(args);
40 args = NULL;
41 crm_exit(CRM_EX_OSERR);
42 }
43
44 return args;
45 }
46
47 static void
48 free_common_args(gpointer data) {
49 pcmk__common_args_t *common_args = (pcmk__common_args_t *) data;
50
51 free(common_args->summary);
52 free(common_args->output_ty);
53 free(common_args->output_dest);
54
55 if (common_args->output_as_descr != NULL) {
56 free(common_args->output_as_descr);
57 }
58
59 free(common_args);
60 }
61
62 GOptionContext *
63 pcmk__build_arg_context(pcmk__common_args_t *common_args, const char *fmts,
64 GOptionGroup **output_group, const char *param_string) {
65 GOptionContext *context;
66 GOptionGroup *main_group;
67
68 GOptionEntry main_entries[3] = {
69 { "version", '$', 0, G_OPTION_ARG_NONE, &(common_args->version),
70 N_("Display software version and exit"),
71 NULL },
72 { "verbose", 'V', G_OPTION_FLAG_NO_ARG, G_OPTION_ARG_CALLBACK, bump_verbosity,
73 N_("Increase debug output (may be specified multiple times)"),
74 NULL },
75
76 { NULL }
77 };
78
79 main_group = g_option_group_new(NULL, "Application Options:", NULL, common_args, free_common_args);
80 g_option_group_add_entries(main_group, main_entries);
81
82 context = g_option_context_new(param_string);
83 g_option_context_set_summary(context, common_args->summary);
84 g_option_context_set_description(context,
85 "Report bugs to " PCMK__BUG_URL "\n");
86 g_option_context_set_main_group(context, main_group);
87
88 if (fmts != NULL) {
89 GOptionEntry output_entries[3] = {
90 { "output-as", 0, 0, G_OPTION_ARG_STRING, &(common_args->output_ty),
91 NULL,
92 N_("FORMAT") },
93 { "output-to", 0, 0, G_OPTION_ARG_STRING, &(common_args->output_dest),
94 N_( "Specify file name for output (or \"-\" for stdout)"), N_("DEST") },
95
96 { NULL }
97 };
98
99 if (*output_group == NULL) {
100 *output_group = g_option_group_new("output", N_("Output Options:"), N_("Show output help"), NULL, NULL);
101 }
102
103 common_args->output_as_descr = crm_strdup_printf("Specify output format as one of: %s", fmts);
104 output_entries[0].description = common_args->output_as_descr;
105 g_option_group_add_entries(*output_group, output_entries);
106 g_option_context_add_group(context, *output_group);
107 }
108
109
110
111 return context;
112 }
113
114 void
115 pcmk__free_arg_context(GOptionContext *context) {
116 if (context == NULL) {
117 return;
118 }
119
120 g_option_context_free(context);
121 }
122
123 void
124 pcmk__add_main_args(GOptionContext *context, const GOptionEntry entries[])
125 {
126 GOptionGroup *main_group = g_option_context_get_main_group(context);
127
128 g_option_group_add_entries(main_group, entries);
129 }
130
131 void
132 pcmk__add_arg_group(GOptionContext *context, const char *name,
133 const char *header, const char *desc,
134 const GOptionEntry entries[])
135 {
136 GOptionGroup *group = NULL;
137
138 group = g_option_group_new(name, header, desc, NULL, NULL);
139 g_option_group_add_entries(group, entries);
140 g_option_context_add_group(context, group);
141
142
143 }
144
145 static gchar *
146 string_replace(gchar *str, const gchar *sub, const gchar *repl)
147 {
148
149
150
151
152
153
154
155 gchar **split = g_strsplit(str, sub, 0);
156 gchar *retval = g_strjoinv(repl, split);
157
158 g_strfreev(split);
159 return retval;
160 }
161
162 gchar *
163 pcmk__quote_cmdline(gchar **argv)
164 {
165 GString *gs = NULL;
166
167 if (argv == NULL || argv[0] == NULL) {
168 return NULL;
169 }
170
171 gs = g_string_sized_new(100);
172
173 for (int i = 0; argv[i] != NULL; i++) {
174 if (i > 0) {
175 g_string_append_c(gs, ' ');
176 }
177
178 if (strchr(argv[i], ' ') == NULL) {
179
180 g_string_append(gs, argv[i]);
181 } else if (strchr(argv[i], '\'') == NULL) {
182
183 pcmk__g_strcat(gs, "'", argv[i], "'", NULL);
184 } else {
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203 gchar *repl = string_replace(argv[i], "'", "\\\'");
204 pcmk__g_strcat(gs, "'", repl, "'", NULL);
205 g_free(repl);
206 }
207 }
208
209 return g_string_free(gs, FALSE);
210 }
211
212 gchar **
213 pcmk__cmdline_preproc(char *const *argv, const char *special) {
214 GPtrArray *arr = NULL;
215 bool saw_dash_dash = false;
216 bool copy_option = false;
217
218 if (argv == NULL) {
219 return NULL;
220 }
221
222 if (g_get_prgname() == NULL && argv && *argv) {
223 gchar *basename = g_path_get_basename(*argv);
224
225 g_set_prgname(basename);
226 g_free(basename);
227 }
228
229 arr = g_ptr_array_new();
230
231 for (int i = 0; argv[i] != NULL; i++) {
232
233
234
235
236
237 if (saw_dash_dash == false && strcmp(argv[i], "--") == 0) {
238 saw_dash_dash = true;
239 }
240
241 if (saw_dash_dash == true) {
242 g_ptr_array_add(arr, g_strdup(argv[i]));
243 continue;
244 }
245
246 if (copy_option == true) {
247 g_ptr_array_add(arr, g_strdup(argv[i]));
248 copy_option = false;
249 continue;
250 }
251
252
253
254
255 if (pcmk__str_eq(argv[i], "-", pcmk__str_casei)) {
256 g_ptr_array_add(arr, g_strdup(argv[i]));
257 continue;
258 }
259
260
261
262
263 if (strcmp(argv[i], "-INFINITY") == 0) {
264 g_ptr_array_add(arr, g_strdup(argv[i]));
265 continue;
266 }
267
268
269
270
271 if (g_str_has_prefix(argv[i], "-") && !g_str_has_prefix(argv[i], "--")) {
272
273 const char *ch = argv[i]+1;
274
275
276
277
278
279
280 if (*ch != '\0' && *ch >= '1' && *ch <= '9') {
281 bool is_numeric = true;
282
283 while (*ch != '\0') {
284 if (!isdigit(*ch)) {
285 is_numeric = false;
286 break;
287 }
288
289 ch++;
290 }
291
292 if (is_numeric) {
293 g_ptr_array_add(arr, g_strdup_printf("%s", argv[i]));
294 continue;
295 } else {
296
297
298
299 ch = argv[i]+1;
300 }
301 }
302
303 while (*ch != '\0') {
304
305
306
307
308
309 if (special != NULL && strchr(special, *ch) != NULL) {
310
311
312
313 if (*(ch+1) != '\0') {
314 fprintf(stderr, "Deprecated argument format '-%c%s' used.\n", *ch, ch+1);
315 fprintf(stderr, "Please use '-%c %s' instead. "
316 "Support will be removed in a future release.\n",
317 *ch, ch+1);
318
319 g_ptr_array_add(arr, g_strdup_printf("-%c", *ch));
320 g_ptr_array_add(arr, g_strdup(ch+1));
321 break;
322
323
324
325
326
327 } else {
328 g_ptr_array_add(arr, g_strdup_printf("-%c", *ch));
329 copy_option = true;
330 ch++;
331 }
332
333
334 } else {
335 g_ptr_array_add(arr, g_strdup_printf("-%c", *ch));
336 ch++;
337 }
338 }
339
340
341
342
343
344 } else {
345 g_ptr_array_add(arr, g_strdup(argv[i]));
346 }
347 }
348
349 g_ptr_array_add(arr, NULL);
350
351 return (char **) g_ptr_array_free(arr, FALSE);
352 }
353
354 G_GNUC_PRINTF(3, 4)
355 gboolean
356 pcmk__force_args(GOptionContext *context, GError **error, const char *format, ...) {
357 int len = 0;
358 char *buf = NULL;
359 gchar **extra_args = NULL;
360 va_list ap;
361 gboolean retval = TRUE;
362
363 va_start(ap, format);
364 len = vasprintf(&buf, format, ap);
365 CRM_ASSERT(len > 0);
366 va_end(ap);
367
368 if (!g_shell_parse_argv(buf, NULL, &extra_args, error)) {
369 g_strfreev(extra_args);
370 free(buf);
371 return FALSE;
372 }
373
374 retval = g_option_context_parse_strv(context, &extra_args, error);
375
376 g_strfreev(extra_args);
377 free(buf);
378 return retval;
379 }