]> git.saurik.com Git - apple/libc.git/blame - libdarwin/h/ctl.h
Libc-1439.100.3.tar.gz
[apple/libc.git] / libdarwin / h / ctl.h
CommitLineData
507116e3
A
1/*
2 * Copyright (c) 2018 Apple Inc. All rights reserved.
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. Please obtain a copy of the License at
10 * http://www.opensource.apple.com/apsl/ and read it before using this
11 * file.
12 *
13 * The Original Code and all software distributed under the License are
14 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
15 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
16 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
18 * Please see the License for the specific language governing rights and
19 * limitations under the License.
20 *
21 * @APPLE_LICENSE_HEADER_END@
22 */
23
24/*!
25 * @header
26 * Interfaces to implement subcommand-style command line utilities (e.g.
27 * launchctl(1)) and automatically generate usage output. The usage generated by
28 * these interfaces assumes a long option convention (cf. getopt_long(3)) and is
29 * loosely based on the docopt convention described at
30 *
31 * http://docopt.org
32 *
33 * The user may define each subcommand taken by the utility as:
34 *
e1ee4b85
A
35 * static const struct option _template_opts[] = {
36 * [0] = {
37 * .name = "bar",
38 * .has_arg = required_argument,
39 * .flag = NULL,
40 * .val = 'f',
41 * }, {
42 * .name = "baz",
43 * .has_arg = optional_argument,
44 * .flag = NULL,
45 * .val = 'b',
46 * }, {
47 * .name = NULL,
48 * .has_arg = 0,
49 * .flag = NULL,
50 * .val = 0,
51 * },
507116e3 52 * };
507116e3 53 *
e1ee4b85
A
54 * static const os_subcommand_option_t _template_required[] = {
55 * [0] = {
56 * .osco_template = OS_SUBCOMMAND_OPTION_VERSION,
57 * .osco_flags = 0,
58 * .osco_option = &_template_opts[0],
59 * .osco_argument_usage = "thing-to-bar",
60 * .osco_argument_human = "The thing to bar. May be specified as a "
61 * "bar that has a baz. This baz should have a shnaz.",
62 * },
63 * OS_SUBCOMMAND_OPTION_TERMINATOR,
507116e3 64 * };
507116e3 65 *
e1ee4b85
A
66 * static const os_subcommand_option_t _template_optional[] = {
67 * [0] = {
68 * .osco_template = OS_SUBCOMMAND_OPTION_VERSION,
69 * .osco_flags = 0,
70 * .osco_option = &_template_opts[1],
71 * .osco_argument_usage = "thing-to-baz",
72 * .osco_argument_human = "The baz of which to propagate a foo.",
73 * },
74 * OS_SUBCOMMAND_OPTION_TERMINATOR,
75 * };
76 *
77 * static const os_subcommand_option_t _template_positional[] = {
78 * [0] = {
79 * .osco_template = OS_SUBCOMMAND_OPTION_VERSION,
80 * .osco_flags = 0,
81 * .osco_option = NULL,
82 * .osco_argument_usage = "positional-baz",
83 * .osco_argument_human = "A baz specified by position.",
84 * },
85 * OS_SUBCOMMAND_OPTION_TERMINATOR,
86 * };
87 *
88 * static const os_subcommand_t _template_cmd = {
89 * .osc_template = OS_SUBCOMMAND_VERSION,
90 * .osc_flags = 0,
91 * .osc_name = "foo",
92 * .osc_desc = "foo a bar or maybe baz",
93 * .osc_optstring = "f:b:",
94 * .osc_options = _foo_opts,
95 * .osc_required = _foo_required,
96 * .osc_optional = _foo_optional,
97 * .osc_positional = _template_positional,
98 * .osc_invoke = &_foo_invoke,
507116e3 99 * }
e1ee4b85
A
100 * OS_SUBCOMMAND_REGISTER(_foo_cmd);
101 * };
507116e3
A
102 *
103 * When {@link os_subcommand_main} is called, the tool's "help" subcommand will
104 * display approximately the following:
105 *
106 * $ tool help
e1ee4b85 107 * usage: tool <subcommand>
507116e3
A
108 *
109 * subcommands:
e1ee4b85
A
110 * foo foo a bar or maybe baz
111 * help Prints helpful information
507116e3
A
112 *
113 * $ tool help foo
e1ee4b85
A
114 * usage: tool foo [options] --bar=<thing-to-bar> <positional-baz>
115 *
116 * required options:
117 * --bar=<thing-to-bar> The thing to bar. May be specified as a bar that
118 * has a baz. This baz should have a shnaz.
119 *
120 * positional-baz A baz specified by position.
121 *
122 * optional options:
123 * --baz[=thing-to-baz] The baz of which to propagate a foo.
507116e3
A
124 */
125#ifndef __DARWIN_CTL_H
126#define __DARWIN_CTL_H
127
128#include <os/base.h>
129#include <os/api.h>
507116e3 130#include <os/linker_set.h>
507116e3
A
131#include <sys/cdefs.h>
132#include <stdio.h>
133#include <getopt.h>
134
e1ee4b85
A
135#if DARWIN_TAPI
136#include "tapi.h"
137#endif
138
507116e3
A
139__BEGIN_DECLS;
140
141/*!
142 * @define OS_SUBCOMMAND_REGISTER
143 * Registers a {@link os_subcommand_t} with the runtime. Subcommands may only be
144 * declared as part of the main executable image -- subcommands declared in
145 * dynamic libraries or bundles will not be recognized.
146 */
147#define OS_SUBCOMMAND_REGISTER(_subcommand) \
148 LINKER_SET_ENTRY(__subcommands, _subcommand)
149
150/*!
151 * @typedef os_subcommand_t
152 * The formal type name for the _os_subcommand structure.
153 */
154DARWIN_API_AVAILABLE_20181020
155typedef struct _os_subcommand os_subcommand_t;
156
157/*!
158 * @const OS_SUBCOMMAND_OPTION_VERSION
159 * The maximum version of the {@link os_subcommand_option_t} structure supported
160 * by the implementation.
161 */
162#define OS_SUBCOMMAND_OPTION_VERSION ((os_struct_version_t)0)
163
507116e3
A
164/*!
165 * @typedef os_subcommand_option_flags_t
166 * Flags describing an option for a subcommand.
167 *
168 * @const OS_SUBCOMMAND_OPTION_FLAG_INIT
169 * No flags set. This value is suitable for initialization purposes.
170 *
e1ee4b85
A
171 * @const OS_SUBCOMMAND_OPTION_FLAG_TERMINATOR
172 * The option terminates an array of {@link os_subcommand_option_t} structures
173 * and does not contain any useful information.
174 *
175 * @const OS_SUBCOMMAND_OPTION_FLAG_OPTIONAL_POS
176 * The option is a positional option (that is, not identified by a long or short
177 * flag) and is not required for the subcommand to execute successfully.
a9aaacca
A
178 *
179 * @const OS_SUBCOMMAND_OPTION_FLAG_ENUM
180 * The option has an explicitly-defined list of valid inputs that are enumerated
181 * in the option's {@link osco_argument_usage} field. When printing usage
182 * information for this option, the implementation will not transform the string
183 * in this field in any way.
184 *
185 * For example, an option named "--stream" might have three valid inputs:
186 * "stdin", "stdout", and "stderr", and the usage string may be specified as
187 *
188 * "stdin|stdout|stderr"
189 *
190 * Without this flag, the implementation would print this string as a parameter
191 * name, i.e. in all caps:
192 *
193 * "<STDIN|STDOUT|STDERR>"
194 *
195 * With this flag, the string will be printed as it is given.
507116e3
A
196 */
197DARWIN_API_AVAILABLE_20181020
198OS_CLOSED_ENUM(os_subcommand_option_flags, uint64_t,
199 OS_SUBCOMMAND_OPTION_FLAG_INIT = 0,
e1ee4b85
A
200 OS_SUBCOMMAND_OPTION_FLAG_TERMINATOR = (1 << 0),
201 OS_SUBCOMMAND_OPTION_FLAG_OPTIONAL_POS = (1 << 1),
a9aaacca 202 OS_SUBCOMMAND_OPTION_FLAG_ENUM = (1 << 2),
507116e3
A
203);
204
205/*!
206 * @typedef os_subcommand_option_t
207 * A structure describing human-readable information about a particular option
208 * taken by a subcommand. This structure is to be returned when the
e1ee4b85
A
209 * implementation invokes a {@link os_subcommand_option_info_t} function to
210 * query about a command's options individually. This is done when the
211 * implementation is synthesizing a usage string.
507116e3
A
212 *
213 * @field osco_version
214 * The version of the structure. Initialize to
215 * {@link OS_SUBCOMMAND_OPTION_VERSION}.
216 *
217 * @field osco_flags
e1ee4b85
A
218 * A set of flags describing information about the option.
219 *
220 * @field osco_option
221 * A pointer to the option structure ingested by getopt_long(3) which
222 * corresponds to this option.
507116e3 223 *
e1ee4b85
A
224 * @field osco_argument_usage
225 * The short-form name of the argument given to the option, appropriate for
226 * display in a usage specifier. For example, if the subcommand takes a "--file"
227 * option with a required argument, this might be the string "FILE-PATH", and
228 * the resulting usage specifier would be
229 *
230 * --file=<FILE-PATH>
231 *
232 * @field osco_argument_human
233 * The long-form description of the argument given to the option. Extending the
234 * above example, this might be the string "The path to a file to take as input.
235 * This path must be absolute; relative paths are not supported." and the
236 * resulting usage specifier would be
237 *
238 * --file=<FILE-PATH> The path to a file to take as input. This path must be
239 * absolute; relative paths are not supported.
507116e3 240 */
e1ee4b85 241DARWIN_API_AVAILABLE_20191015
507116e3
A
242typedef struct _os_subcommand_option {
243 const os_struct_version_t osco_version;
244 os_subcommand_option_flags_t osco_flags;
e1ee4b85
A
245 const struct option *osco_option;
246 const char *osco_argument_usage;
247 const char *osco_argument_human;
507116e3
A
248} os_subcommand_option_t;
249
250/*!
e1ee4b85
A
251 * @const OS_SUBCOMMAND_OPTION_TERMINATOR
252 * A convenience terminator for an array of {@link os_subcommand_option_t}
253 * structures.
507116e3 254 */
e1ee4b85
A
255#define OS_SUBCOMMAND_OPTION_TERMINATOR (os_subcommand_option_t){ \
256 .osco_version = OS_SUBCOMMAND_OPTION_VERSION, \
257 .osco_flags = OS_SUBCOMMAND_OPTION_FLAG_TERMINATOR, \
258 .osco_option = NULL, \
259 .osco_argument_usage = NULL, \
260 .osco_argument_human = NULL, \
261}
262
263/*!
264* @const OS_SUBCOMMAND_GETOPT_TERMINATOR
265* A convenience terminator for an array of getopt(3) option structures.
266*/
267#define OS_SUBCOMMAND_GETOPT_TERMINATOR (struct option){ \
268 .name = NULL, \
269 .has_arg = 0, \
270 .flag = NULL, \
271 .val = 0, \
272}
507116e3
A
273
274/*!
275 * @const OS_SUBCOMMAND_VERSION
276 * The maximum version of the {@link os_subcommand_t} structure supported by the
277 * implementation.
278 */
279#define OS_SUBCOMMAND_VERSION ((os_struct_version_t)0)
280
281/*!
282 * @enum os_subcommand_flags_t
283 * A type describing flags associated with a subcommand for a command line
284 * utility.
285 *
286 * @const OS_SUBCOMMAND_FLAG_INIT
287 * No flags set. This value is suitable for initialization purposes.
288 *
289 * @const OS_SUBCOMMAND_FLAG_REQUIRE_ROOT
290 * This subcommand requires the user to be root. If the user is not root, the
291 * {@link os_subcommand_dispatch} routine will return {@EX_PERM}.
292 *
293 * @const OS_SUBCOMMAND_FLAG_TTYONLY
294 * This subcommand may only be invoked via a terminal interface, i.e. it should
295 * not be invoked by scripts. Use this option to emphasize that a command's
296 * output is human-readably only and should not be parsed.
297 *
298 * @const OS_SUBCOMMAND_FLAG_HIDDEN
299 * This subcommand should not be displayed in the list of subcommands.
e1ee4b85
A
300 *
301 * @const OS_SUBCOMMAND_FLAG_MAIN
302 * This subcommand is the "main" subcommand. Designating a main subcommand
303 * allows the program to specify and parse global options using an
304 * {@link os_subcommand_t} object and {@link os_subcommand_main}.
305 *
306 * This flag implies the behavior of {@link OS_SUBCOMMAND_FLAG_HIDDEN}.
307 *
308 * If the program specifies a main subcommand, that subcommand's invocation
309 * routine is unconditionally called before calling the subcommand invocation,
310 * if the user provided a subcommand. The invocation function for the main
311 * subcommand should not exit on success and should instead return 0.
312 *
313 * If multiple subcommands in the same program set
314 * {@link OS_SUBCOMMAND_FLAG_MAIN}, the implementation's behavior is undefined.
a9aaacca
A
315 *
316 * @const OS_SUBCOMMAND_FLAG_HELPFUL
317 * When invoked with no arguments, this subcommand will print usage information
318 * to stdout and exit with status zero.
319 *
320 * @const OS_SUBCOMMAND_FLAG_HELPFUL_FIRST_OPTION
321 * Allow the implementation to detect whether the user is attempting to print
322 * usage information for the given subcommand. If the implementation concludes
323 * that the user is seeking help, it will print the subcommand's usage
324 * information to stdout and exit with status 0.
325 *
326 * The implementation will conclude that the user is seeking help if
327 *
328 * - only one argument is provided to the subcommand, and
329 *
330 * any of the following
331 *
332 * - the argument is "-h"
333 * - the argument is "-help"
334 * - the argument is "--help"
335 * - the argument is "help"
507116e3
A
336 */
337DARWIN_API_AVAILABLE_20181020
338OS_CLOSED_OPTIONS(os_subcommand_flags, uint64_t,
339 OS_SUBCOMMAND_FLAG_INIT,
340 OS_SUBCOMMAND_FLAG_REQUIRE_ROOT = (1 << 0),
341 OS_SUBCOMMAND_FLAG_TTYONLY = (1 << 1),
342 OS_SUBCOMMAND_FLAG_HIDDEN = (1 << 2),
e1ee4b85 343 OS_SUBCOMMAND_FLAG_MAIN = (1 << 3),
a9aaacca
A
344 OS_SUBCOMMAND_FLAG_HELPFUL = (1 << 4),
345 OS_SUBCOMMAND_FLAG_HELPFUL_FIRST_OPTION = (1 << 5),
507116e3
A
346);
347
348/*!
349 * @typedef os_subcommand_invoke_t
350 * An type describing the invocation function for a subcommand.
351 *
352 * @param osc
353 * The descriptor for the command being invoked.
354 *
355 * @param argc
356 * The argument vector count.
357 *
358 * @param argv
359 * The argument vector. The first element of this array is the name of the
360 * subcommand.
361 *
362 * @result
e1ee4b85
A
363 * An exit code, preferably from sysexits(3). Do not return a POSIX error code
364 * directly from this routine.
507116e3
A
365 *
366 * @discussion
e1ee4b85
A
367 * You may exit directly on success or failure from this routine if desired. If
368 * the routine is the invocation for a main subcommand, then on success, the
369 * routine should return zero to the caller rather than exiting so that the
370 * implementation may continue parsing the command line arguments.
507116e3
A
371 */
372DARWIN_API_AVAILABLE_20181020
373typedef int (*os_subcommand_invoke_t)(
e1ee4b85
A
374 const os_subcommand_t *osc,
375 int argc,
376 const char *argv[]
377);
507116e3
A
378
379/*!
380 * @struct os_subcommand_t
381 * A type describing a subcommand for a command line tool.
382 *
383 * @field osc_version
384 * The version of the structure. Initialize to {@link OS_SUBCOMMAND_VERSION}.
385 *
386 * @field osc_flags
387 * The flags for the subcommand.
388 *
389 * @field osc_name
390 * The name of the subcommand. The second argument of user input will be matched
391 * against this name.
392 *
393 * @field osc_desc
394 * A brief description of the subcommand. This description will be displayed
395 * next to the subcommand when the user lists all subcommands.
396 *
a9aaacca
A
397 * @field osc_long_desc
398 * A long description of the subcommand. This description will be displayed
399 * when the user invokes help on the subcommand. If it's NULL the brief
400 * description from osc_desc will be displayed.
401 *
507116e3
A
402 * @field osc_optstring
403 * The option string associated with the subcommand. The implementation does not
404 * recognize this string directly; the intent of storing it here is to provide a
405 * convenient place to access the string for the implementation function.
406 * Combined with the {@link osc_options} field, this enables the following
407 * pattern:
408 *
409 * int ch = 0;
410 * while ((ch = getopt_long(argc, argv, cmd->osc_optstring,
411 * cmd->osc_options, NULL)) != -1) {
412 * switch (ch) {
413 * // process option
414 * }
415 * }
416 *
417 * This pattern keeps the option string and option structs co-located in code.
418 *
419 * @field osc_options
420 * A pointer to an array of option structures describing the long options
e1ee4b85
A
421 * recognized by the subcommand. This array must be terminated by a NULL entry
422 * as expected by getopt_long(3).
423 *
424 * @field osc_required
425 * A pointer to an array of subcommand option descriptors. The options described
426 * in this array are required for the subcommand to execute successfully. This
427 * array should be terminated with {@link OS_SUBCOMMAND_OPTION_TERMINATOR}.
428 *
429 * This array is consulted when printing usage information.
430 *
431 * @field osc_optional
432 * A pointer to an array of subcommand option descriptors. The options described
433 * in this array are parsed by the subcommand but not required for it to execute
434 * successfully. This array should be terminated with
435 * {@link OS_SUBCOMMAND_OPTION_TERMINATOR}.
436 *
437 * This array is consulted when printing usage information.
438 *
439 * @field osc_positional
440 * A pointer to an array of subcommand option descriptors. The options described
441 * in this array are expected to follow the required and optional arguments in
442 * the command line invocation, in the order given in this array. This array
443 * should be terminated with {@link OS_SUBCOMMAND_OPTION_TERMINATOR}.
444 *
445 * These options are expected to have their {@link osco_option} fields set to
446 * NULL.
447 *
448 * This array is consulted when printing usage information.
507116e3
A
449 *
450 * @field osc_info
451 * A pointer to a function which returns information about the subcommand's
452 * individual options.
453 *
454 * @field osc_invoke
455 * The implementation for the subcommand.
456 */
a9aaacca 457DARWIN_API_AVAILABLE_20200401
507116e3
A
458struct _os_subcommand {
459 const os_struct_version_t osc_version;
460 const os_subcommand_flags_t osc_flags;
461 const char *const osc_name;
462 const char *const osc_desc;
463 const char *osc_optstring;
464 const struct option *osc_options;
e1ee4b85
A
465 const os_subcommand_option_t *osc_required;
466 const os_subcommand_option_t *osc_optional;
467 const os_subcommand_option_t *osc_positional;
507116e3 468 const os_subcommand_invoke_t osc_invoke;
a9aaacca 469 const char *const osc_long_desc;
507116e3
A
470};
471
e1ee4b85
A
472/*!
473 * @typedef os_subcommand_main_flags_t
474 * Flags modifying the behavior of {@link os_subcommand_main}.
475 *
476 * @const OS_SUBCOMMAND_MAIN_FLAG_INIT
477 * No flags set. This value is suitable for initialization purposes.
478 */
479OS_CLOSED_OPTIONS(os_subcommand_main_flags, uint64_t,
480 OS_SUBCOMMAND_MAIN_FLAG_INIT,
481);
482
507116e3
A
483/*!
484 * @function os_subcommand_main
485 * Dispatches the subcommand appropriate for the given arguments. All
486 * subcommands will be implicitly discovered by virtue of their delcarations
487 * with the OS_SUBCOMMAND_REGISTER attribute.
488 *
489 * @param argc
490 * The argument count supplied to main().
491 *
492 * @param argv
493 * The argument vector supplied to main().
494 *
e1ee4b85
A
495 * @param flags
496 * Flags modifying the behavior of the implementation.
497 *
507116e3
A
498 * @result
499 * The exit status from the subcommand's invocation function or an exit status
500 * from the implementation indicating that the subcommand could not be
501 * dispatched. Exit codes that can be returned by the implementation are:
502 *
503 * [EX_USAGE] The subcommand was invoked with improper syntax. Usage
504 * has been printed to stderr.
505 * [EX_USAGE] The subcommand specified is not recognized.
506 * [EX_PERM] The command required root privileges, and the caller is
507 * not running as root.
508 * [EX_UNAVAILABLE] The command specified that it may only run within
509 * the context of a tty(3), and either stdin or stdout are
510 * not a tty(3).
511 *
512 * @discussion
513 * In general, the code returned by this routine should immediately be passed to
514 * exit(3). The reason this routine does not implicitly exit is to allow for the
515 * caller to process multiple subcommand invocations as a batch.
516 *
517 * The caller should not print anything after this routine has returned -- the
518 * expectation is that all relevant information has already been conveyed to the
519 * user either by the implementation or from one of the subcommand invocation
520 * routines.
521 *
522 * This routine implicitly implements a "help" subcommand.
523 */
e1ee4b85 524DARWIN_API_AVAILABLE_20191015
507116e3
A
525OS_EXPORT OS_WARN_RESULT OS_NONNULL2
526int
e1ee4b85
A
527os_subcommand_main(int argc, const char *argv[],
528 os_subcommand_main_flags_t flags);
529
530/*!
531 * @function os_subcommand_fprintf
532 * Prints a message in the context of a subcommand to the given output stream.
533 *
534 * @param osc
535 * The subcommand which represents the context of the message.
536 *
537 * @param f
538 * The stream to which the message shall be printed. If NULL, will be printed to
539 * stderr(4).
540 *
541 * @param fmt
542 * A printf(3)-style format string.
543 *
544 * @param ...
545 * The arguments corresponding to {@link fmt}.
546 *
547 * @discussion
548 * This routine provides a uniform method for printing messages in the context
549 * of a subcommand. It will ensure that the message is prefixed appropriately
550 * (e.g. with the program name and/or subcommand name).
551 *
552 * This routine should be used for printing messages intended for humans to
553 * read; the implementation makes no guarantees about the output format's
554 * stability. If any output is intended to be machine-parseable, it should be
555 * written with fprintf(3) et al.
556 */
557DARWIN_API_AVAILABLE_20191015
558OS_EXPORT OS_NONNULL3 OS_FORMAT_PRINTF(3, 4)
559void
560os_subcommand_fprintf(const os_subcommand_t *osc, FILE *f,
561 const char *fmt, ...);
562
563/*!
564 * @function os_subcommand_vfprintf
565 * Prints a message in the context of a subcommand to the given output stream.
566 *
567 * @param osc
568 * The subcommand which represents the context of the message.
569 *
570 * @param f
571 * The stream to which the message shall be printed. If NULL, will be printed to
572 * stderr(4).
573 *
574 * @param fmt
575 * A printf(3)-style format string.
576 *
577 * @param ap
578 * The argument list corresponding to {@link fmt}.
579 *
580 * @discussion
581 * See discussion for {@link os_subcommand_fprintf}.
582 */
583DARWIN_API_AVAILABLE_20191015
584OS_EXPORT OS_NONNULL3
585void
586os_subcommand_vfprintf(const os_subcommand_t *osc, FILE *f,
587 const char *fmt, va_list ap);
507116e3
A
588
589__END_DECLS;
590
591#endif // __DARWIN_CTL_H