2 * Copyright (c) 2018 Apple Inc. All rights reserved.
4 * @APPLE_LICENSE_HEADER_START@
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
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.
21 * @APPLE_LICENSE_HEADER_END@
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
33 * The user may define each subcommand taken by the utility as:
35 * static const struct option _template_opts[] = {
38 * .has_arg = required_argument,
43 * .has_arg = optional_argument,
54 * static const os_subcommand_option_t _template_required[] = {
56 * .osco_template = OS_SUBCOMMAND_OPTION_VERSION,
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.",
63 * OS_SUBCOMMAND_OPTION_TERMINATOR,
66 * static const os_subcommand_option_t _template_optional[] = {
68 * .osco_template = OS_SUBCOMMAND_OPTION_VERSION,
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.",
74 * OS_SUBCOMMAND_OPTION_TERMINATOR,
77 * static const os_subcommand_option_t _template_positional[] = {
79 * .osco_template = OS_SUBCOMMAND_OPTION_VERSION,
81 * .osco_option = NULL,
82 * .osco_argument_usage = "positional-baz",
83 * .osco_argument_human = "A baz specified by position.",
85 * OS_SUBCOMMAND_OPTION_TERMINATOR,
88 * static const os_subcommand_t _template_cmd = {
89 * .osc_template = OS_SUBCOMMAND_VERSION,
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,
100 * OS_SUBCOMMAND_REGISTER(_foo_cmd);
103 * When {@link os_subcommand_main} is called, the tool's "help" subcommand will
104 * display approximately the following:
107 * usage: tool <subcommand>
110 * foo foo a bar or maybe baz
111 * help Prints helpful information
114 * usage: tool foo [options] --bar=<thing-to-bar> <positional-baz>
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.
120 * positional-baz A baz specified by position.
123 * --baz[=thing-to-baz] The baz of which to propagate a foo.
125 #ifndef __DARWIN_CTL_H
126 #define __DARWIN_CTL_H
130 #include <os/linker_set.h>
131 #include <sys/cdefs.h>
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.
147 #define OS_SUBCOMMAND_REGISTER(_subcommand) \
148 LINKER_SET_ENTRY(__subcommands, _subcommand)
151 * @typedef os_subcommand_t
152 * The formal type name for the _os_subcommand structure.
154 DARWIN_API_AVAILABLE_20181020
155 typedef struct _os_subcommand os_subcommand_t
;
158 * @const OS_SUBCOMMAND_OPTION_VERSION
159 * The maximum version of the {@link os_subcommand_option_t} structure supported
160 * by the implementation.
162 #define OS_SUBCOMMAND_OPTION_VERSION ((os_struct_version_t)0)
165 * @typedef os_subcommand_option_flags_t
166 * Flags describing an option for a subcommand.
168 * @const OS_SUBCOMMAND_OPTION_FLAG_INIT
169 * No flags set. This value is suitable for initialization purposes.
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.
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.
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.
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
188 * "stdin|stdout|stderr"
190 * Without this flag, the implementation would print this string as a parameter
191 * name, i.e. in all caps:
193 * "<STDIN|STDOUT|STDERR>"
195 * With this flag, the string will be printed as it is given.
197 DARWIN_API_AVAILABLE_20181020
198 OS_CLOSED_ENUM(os_subcommand_option_flags
, uint64_t,
199 OS_SUBCOMMAND_OPTION_FLAG_INIT
= 0,
200 OS_SUBCOMMAND_OPTION_FLAG_TERMINATOR
= (1 << 0),
201 OS_SUBCOMMAND_OPTION_FLAG_OPTIONAL_POS
= (1 << 1),
202 OS_SUBCOMMAND_OPTION_FLAG_ENUM
= (1 << 2),
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
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.
213 * @field osco_version
214 * The version of the structure. Initialize to
215 * {@link OS_SUBCOMMAND_OPTION_VERSION}.
218 * A set of flags describing information about the option.
221 * A pointer to the option structure ingested by getopt_long(3) which
222 * corresponds to this option.
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
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
238 * --file=<FILE-PATH> The path to a file to take as input. This path must be
239 * absolute; relative paths are not supported.
241 DARWIN_API_AVAILABLE_20191015
242 typedef struct _os_subcommand_option
{
243 const os_struct_version_t osco_version
;
244 os_subcommand_option_flags_t osco_flags
;
245 const struct option
*osco_option
;
246 const char *osco_argument_usage
;
247 const char *osco_argument_human
;
248 } os_subcommand_option_t
;
251 * @const OS_SUBCOMMAND_OPTION_TERMINATOR
252 * A convenience terminator for an array of {@link os_subcommand_option_t}
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, \
264 * @const OS_SUBCOMMAND_GETOPT_TERMINATOR
265 * A convenience terminator for an array of getopt(3) option structures.
267 #define OS_SUBCOMMAND_GETOPT_TERMINATOR (struct option){ \
275 * @const OS_SUBCOMMAND_VERSION
276 * The maximum version of the {@link os_subcommand_t} structure supported by the
279 #define OS_SUBCOMMAND_VERSION ((os_struct_version_t)0)
282 * @enum os_subcommand_flags_t
283 * A type describing flags associated with a subcommand for a command line
286 * @const OS_SUBCOMMAND_FLAG_INIT
287 * No flags set. This value is suitable for initialization purposes.
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}.
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.
298 * @const OS_SUBCOMMAND_FLAG_HIDDEN
299 * This subcommand should not be displayed in the list of subcommands.
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}.
306 * This flag implies the behavior of {@link OS_SUBCOMMAND_FLAG_HIDDEN}.
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.
313 * If multiple subcommands in the same program set
314 * {@link OS_SUBCOMMAND_FLAG_MAIN}, the implementation's behavior is undefined.
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.
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.
326 * The implementation will conclude that the user is seeking help if
328 * - only one argument is provided to the subcommand, and
330 * any of the following
332 * - the argument is "-h"
333 * - the argument is "-help"
334 * - the argument is "--help"
335 * - the argument is "help"
337 DARWIN_API_AVAILABLE_20181020
338 OS_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),
343 OS_SUBCOMMAND_FLAG_MAIN
= (1 << 3),
344 OS_SUBCOMMAND_FLAG_HELPFUL
= (1 << 4),
345 OS_SUBCOMMAND_FLAG_HELPFUL_FIRST_OPTION
= (1 << 5),
349 * @typedef os_subcommand_invoke_t
350 * An type describing the invocation function for a subcommand.
353 * The descriptor for the command being invoked.
356 * The argument vector count.
359 * The argument vector. The first element of this array is the name of the
363 * An exit code, preferably from sysexits(3). Do not return a POSIX error code
364 * directly from this routine.
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.
372 DARWIN_API_AVAILABLE_20181020
373 typedef int (*os_subcommand_invoke_t
)(
374 const os_subcommand_t
*osc
,
380 * @struct os_subcommand_t
381 * A type describing a subcommand for a command line tool.
384 * The version of the structure. Initialize to {@link OS_SUBCOMMAND_VERSION}.
387 * The flags for the subcommand.
390 * The name of the subcommand. The second argument of user input will be matched
394 * A brief description of the subcommand. This description will be displayed
395 * next to the subcommand when the user lists all subcommands.
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.
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
410 * while ((ch = getopt_long(argc, argv, cmd->osc_optstring,
411 * cmd->osc_options, NULL)) != -1) {
417 * This pattern keeps the option string and option structs co-located in code.
420 * A pointer to an array of option structures describing the long options
421 * recognized by the subcommand. This array must be terminated by a NULL entry
422 * as expected by getopt_long(3).
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}.
429 * This array is consulted when printing usage information.
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}.
437 * This array is consulted when printing usage information.
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}.
445 * These options are expected to have their {@link osco_option} fields set to
448 * This array is consulted when printing usage information.
451 * A pointer to a function which returns information about the subcommand's
452 * individual options.
455 * The implementation for the subcommand.
457 DARWIN_API_AVAILABLE_20200401
458 struct _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
;
465 const os_subcommand_option_t
*osc_required
;
466 const os_subcommand_option_t
*osc_optional
;
467 const os_subcommand_option_t
*osc_positional
;
468 const os_subcommand_invoke_t osc_invoke
;
469 const char *const osc_long_desc
;
473 * @typedef os_subcommand_main_flags_t
474 * Flags modifying the behavior of {@link os_subcommand_main}.
476 * @const OS_SUBCOMMAND_MAIN_FLAG_INIT
477 * No flags set. This value is suitable for initialization purposes.
479 OS_CLOSED_OPTIONS(os_subcommand_main_flags
, uint64_t,
480 OS_SUBCOMMAND_MAIN_FLAG_INIT
,
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.
490 * The argument count supplied to main().
493 * The argument vector supplied to main().
496 * Flags modifying the behavior of the implementation.
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:
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
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.
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
522 * This routine implicitly implements a "help" subcommand.
524 DARWIN_API_AVAILABLE_20191015
525 OS_EXPORT OS_WARN_RESULT OS_NONNULL2
527 os_subcommand_main(int argc
, const char *argv
[],
528 os_subcommand_main_flags_t flags
);
531 * @function os_subcommand_fprintf
532 * Prints a message in the context of a subcommand to the given output stream.
535 * The subcommand which represents the context of the message.
538 * The stream to which the message shall be printed. If NULL, will be printed to
542 * A printf(3)-style format string.
545 * The arguments corresponding to {@link fmt}.
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).
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.
557 DARWIN_API_AVAILABLE_20191015
558 OS_EXPORT OS_NONNULL3
OS_FORMAT_PRINTF(3, 4)
560 os_subcommand_fprintf(const os_subcommand_t
*osc
, FILE *f
,
561 const char *fmt
, ...);
564 * @function os_subcommand_vfprintf
565 * Prints a message in the context of a subcommand to the given output stream.
568 * The subcommand which represents the context of the message.
571 * The stream to which the message shall be printed. If NULL, will be printed to
575 * A printf(3)-style format string.
578 * The argument list corresponding to {@link fmt}.
581 * See discussion for {@link os_subcommand_fprintf}.
583 DARWIN_API_AVAILABLE_20191015
584 OS_EXPORT OS_NONNULL3
586 os_subcommand_vfprintf(const os_subcommand_t
*osc
, FILE *f
,
587 const char *fmt
, va_list ap
);
591 #endif // __DARWIN_CTL_H