]> git.saurik.com Git - apple/libc.git/blobdiff - libdarwin/ctl.c
Libc-1439.100.3.tar.gz
[apple/libc.git] / libdarwin / ctl.c
index 8015ba3e314cf774af5b9f9291c256ce59af4bf4..28daa35ef84b661dc1d57bd598d177fac1e80166 100755 (executable)
 
 #pragma mark Definitions
 #define CTL_OUTPUT_WIDTH (80)
-#define CTL_OUTPUT_OPTARG_PAD (28)
-#define CTL_OUTPUT_LIST_PAD (4)
+#define CTL_OUTPUT_OPTARG_INDENT (32)
+#define CTL_OUTPUT_OPTARG_OVERFLOW (CTL_OUTPUT_OPTARG_INDENT - 4)
 #define SUBCOMMAND_LINKER_SET "__subcommands"
 
+#define OS_SUBCOMMAND_OPTIONS_FOREACH(_osco_i, _osc, _which, _i) \
+               while (((_osco_i) = &osc->osc_ ## _which[(_i)]) && \
+                       ((_i) += 1, 1) && \
+                       !((_osco_i)->osco_flags & OS_SUBCOMMAND_OPTION_FLAG_TERMINATOR))
+
+#pragma mark Types
+OS_ENUM(os_subcommand_option_spec_fmt, uint64_t,
+       OS_SUBCOMMAND_OPTION_SPEC_SHORT,
+       OS_SUBCOMMAND_OPTION_SPEC_LONG,
+       OS_SUBCOMMAND_OPTION_SPEC_COMBINED,
+);
+
+#pragma mark Forward Declarations
+static void _print_header(
+               FILE *f,
+               const char *hdr,
+               bool *already_done);
+static const os_subcommand_t *_os_subcommand_find(
+               const char *name);
+static void _os_subcommand_print_usage(
+               const os_subcommand_t *osc,
+               FILE *f);
+static void _os_subcommand_print_help_line(
+               const os_subcommand_t *osc,
+               FILE *f);
+static void _print_subcommand_list(
+               const os_subcommand_t *osc,
+               FILE *f);
+
 #pragma mark Module Globals
-static const os_subcommand_t _help_cmd;
+static const os_subcommand_t __help_cmd;
+static const os_subcommand_t *_help_cmd = &__help_cmd;
+
+static const os_subcommand_t __main_cmd;
+static const os_subcommand_t *_main_cmd = &__main_cmd;
+static const os_subcommand_t *_internal_main_cmd = &__main_cmd;
+
+static struct ttysize __ttys = {
+       .ts_lines = 24,
+       .ts_cols = CTL_OUTPUT_WIDTH,
+};
+
+static const struct ttysize *_ttys = &__ttys;
+
+#pragma mark Module Private
+static void
+_init_column_count(void)
+{
+       const char *columns_env = NULL;
+       char *end = NULL;
+       struct ttysize ttys = {
+               .ts_lines = 24,
+               .ts_cols = CTL_OUTPUT_WIDTH,
+       };
+       int ret = -1;
+
+       columns_env = getenv("COLUMNS");
+       if (columns_env) {
+               unsigned short cols = -1;
+
+               cols = strtoul(columns_env, &end, 0);
+               if (end != columns_env && end[0] != 0) {
+                       ttys.ts_lines = cols;
+               }
+       } else {
+               ret = ioctl(0, TIOCGSIZE, &ttys);
+               if (ret) {
+                       ttys.ts_lines = 24;
+                       ttys.ts_cols = CTL_OUTPUT_WIDTH;
+               }
+       }
+
+       __ttys = ttys;
+}
+
+static void
+_stoupper(char *str)
+{
+       size_t i = 0;
+       size_t len = strlen(str);
+
+       for (i = 0; i < len; i++) {
+               char *cp = &str[i];
+               *cp = ___toupper(*cp);
+       }
+}
+
+#pragma mark Main Subcommand
+static int _main_invoke(const os_subcommand_t *osc,
+       int argc,
+       const char *argv[]);
+
+static const os_subcommand_option_t _main_positional[] = {
+       [0] = {
+               .osco_version = OS_SUBCOMMAND_OPTION_VERSION,
+               .osco_flags = 0,
+               .osco_option = NULL,
+               .osco_argument_usage = "subcommand",
+               .osco_argument_human = "The subcommand to invoke",
+       },
+       OS_SUBCOMMAND_OPTION_TERMINATOR,
+};
+
+static const os_subcommand_t __main_cmd = {
+       .osc_version = OS_SUBCOMMAND_VERSION,
+       .osc_flags = OS_SUBCOMMAND_FLAG_MAIN,
+       .osc_name = "_main",
+       .osc_desc = "main command",
+       .osc_optstring = NULL,
+       .osc_options = NULL,
+       .osc_required = NULL,
+       .osc_optional = NULL,
+       .osc_positional = _main_positional,
+       .osc_invoke = &_main_invoke,
+};
+
+static int
+_main_invoke(const os_subcommand_t *osc, int argc, const char *argv[])
+{
+       return 0;
+}
+
+#pragma mark Help Subcommand
+static int _help_invoke(const os_subcommand_t *osc,
+       int argc,
+       const char *argv[]);
+
+static const os_subcommand_option_t _help_positional[] = {
+       [0] = {
+               .osco_version = OS_SUBCOMMAND_OPTION_VERSION,
+               .osco_flags = 0,
+               .osco_option = NULL,
+               .osco_argument_usage = "SUBCOMMAND",
+               .osco_argument_human = "The subcommand to query for help",
+       },
+       OS_SUBCOMMAND_OPTION_TERMINATOR,
+};
+
+static const os_subcommand_t __help_cmd = {
+       .osc_version = OS_SUBCOMMAND_VERSION,
+       .osc_flags = 0,
+       .osc_name = "help",
+       .osc_desc = "prints helpful information",
+       .osc_optstring = NULL,
+       .osc_options = NULL,
+       .osc_required = NULL,
+       .osc_optional = NULL,
+       .osc_positional = _help_positional,
+       .osc_invoke = &_help_invoke,
+};
+
+static int
+_help_invoke(const os_subcommand_t *osc, int argc, const char *argv[])
+{
+       int xit = -1;
+       const char *cmdname = NULL;
+       const os_subcommand_t *target = NULL;
+       FILE *f = stdout;
+
+       if (argc > 1) {
+               cmdname = argv[1];
+       }
+
+       // Print usage information for the requested subcommand.
+       target = _os_subcommand_find(cmdname);
+       if (!target) {
+               // If it's a bogus subcommand, just print top-level usage.
+               fprintf(stderr, "unrecognized subcommand: %s\n", cmdname);
+               target = _main_cmd;
+               xit = EX_UNAVAILABLE;
+       } else {
+               xit = 0;
+       }
+
+       if (xit) {
+               f = stderr;
+       }
+
+       _os_subcommand_print_usage(target, f);
+
+       if (target == _main_cmd) {
+               _print_subcommand_list(_help_cmd, f);
+       }
+
+       return xit;
+}
+
+#pragma mark Utilities
+static void
+_print_header(FILE *f, const char *hdr, bool *already_done)
+{
+       if (already_done && *already_done) {
+               return;
+       }
+
+       crfprintf_np(f, "");
+       crfprintf_np(f, "%s:", hdr);
+       crfprintf_np(f, "");
+
+       if (already_done) {
+               *already_done = true;
+       }
+}
 
 #pragma mark Module Routines
 static char *
-_os_subcommand_copy_optarg_usage(const os_subcommand_t *osc,
-               const struct option *opt, os_subcommand_optarg_format_t format,
-               os_subcommand_option_t *scopt)
+_os_subcommand_copy_option_spec_short(const os_subcommand_t *osc,
+               const os_subcommand_option_t *osco)
 {
+       const struct option *opt = osco->osco_option;
        char optbuff[64] = "";
        char argbuff[64] = "";
        char *final = NULL;
        int ret = -1;
 
-       snprintf(optbuff, sizeof(optbuff), "--%s", opt->name);
+       if (opt) {
+               snprintf(optbuff, sizeof(optbuff), "-%c", opt->val);
+
+               switch (opt->has_arg) {
+               case no_argument:
+                       break;
+               case optional_argument:
+                       snprintf(argbuff, sizeof(argbuff), "[%s]",
+                                       osco->osco_argument_usage);
+                       break;
+               case required_argument:
+                       snprintf(argbuff, sizeof(argbuff), "<%s>",
+                                       osco->osco_argument_usage);
+                       break;
+               default:
+                       __builtin_unreachable();
+               }
 
-       if (osc->osc_info) {
-               osc->osc_info(osc, format, opt, scopt);
+               if (!(osco->osco_flags & OS_SUBCOMMAND_OPTION_FLAG_ENUM)) {
+                       _stoupper(argbuff);
+               }
+       } else {
+               snprintf(optbuff, sizeof(optbuff), "%s", osco->osco_argument_usage);
+               if (!(osco->osco_flags & OS_SUBCOMMAND_OPTION_FLAG_ENUM)) {
+                       _stoupper(optbuff);
+               }
        }
 
-       switch (opt->has_arg) {
-       case no_argument:
-               break;
-       case optional_argument:
-               snprintf(argbuff, sizeof(argbuff), "[=%s]", scopt->osco_argdesc);
-               break;
-       case required_argument:
-               snprintf(argbuff, sizeof(argbuff), "=<%s>", scopt->osco_argdesc);
-               break;
-       default:
-               __builtin_unreachable();
+       ret = asprintf(&final, "%s%s", optbuff, argbuff);
+       if (ret < 0) {
+               os_assert_zero(ret);
+       }
+
+       return final;
+}
+
+static char *
+_os_subcommand_copy_option_spec_long(const os_subcommand_t *osc,
+               const os_subcommand_option_t *osco)
+{
+       const struct option *opt = osco->osco_option;
+       char optbuff[64] = "";
+       char argbuff[64] = "";
+       char *final = NULL;
+       int ret = -1;
+
+       if (opt) {
+               snprintf(optbuff, sizeof(optbuff), "--%s", opt->name);
+
+               switch (opt->has_arg) {
+               case no_argument:
+                       break;
+               case optional_argument:
+                       snprintf(argbuff, sizeof(argbuff), "[=%s]",
+                                       osco->osco_argument_usage);
+                       break;
+               case required_argument:
+                       snprintf(argbuff, sizeof(argbuff), "=<%s>",
+                                       osco->osco_argument_usage);
+                       break;
+               default:
+                       __builtin_unreachable();
+               }
+
+               if (!(osco->osco_flags & OS_SUBCOMMAND_OPTION_FLAG_ENUM)) {
+                       _stoupper(argbuff);
+               }
+       } else {
+               snprintf(optbuff, sizeof(optbuff), "%s", osco->osco_argument_usage);
+               if (!(osco->osco_flags & OS_SUBCOMMAND_OPTION_FLAG_ENUM)) {
+                       _stoupper(optbuff);
+               }
        }
 
        ret = asprintf(&final, "%s%s", optbuff, argbuff);
@@ -47,243 +303,433 @@ _os_subcommand_copy_optarg_usage(const os_subcommand_t *osc,
        return final;
 }
 
-static void
-_os_subcommand_print_optarg_usage(const os_subcommand_t *osc,
-               const struct option *opt, FILE *f)
+static char *
+_os_subcommand_copy_option_spec(const os_subcommand_t *osc,
+               const os_subcommand_option_t *osco, os_subcommand_option_spec_fmt_t fmt)
 {
-       os_subcommand_option_t scopt = {
-               .osco_flags = 0,
-               .osco_argdesc = opt->name,
-       };
-       char *__os_free usage = NULL;
-       char *braces[2] = {
-               "",
-               "",
-       };
+       int ret = -1;
+       char *spec = NULL;
+       char *__os_free spec_old = NULL;
+
+       switch (fmt) {
+       case OS_SUBCOMMAND_OPTION_SPEC_SHORT:
+               _os_subcommand_copy_option_spec_short(osc, osco);
+               break;
+       case OS_SUBCOMMAND_OPTION_SPEC_LONG:
+               _os_subcommand_copy_option_spec_long(osc, osco);
+               break;
+       case OS_SUBCOMMAND_OPTION_SPEC_COMBINED:
+               spec = _os_subcommand_copy_option_spec_long(osc, osco);
+               if (osco->osco_option) {
+                       spec_old = spec;
+
+                       ret = asprintf(&spec, "-%c | %s", osco->osco_option->val, spec);
+                       if (ret < 0) {
+                               os_assert_zero(ret);
+                       }
+               }
 
-       usage = _os_subcommand_copy_optarg_usage(osc, opt,
-                       OS_SUBCOMMAND_OPTARG_USAGE, &scopt);
-       if (scopt.osco_flags & OS_SUBCOMMAND_OPTION_FLAG_OPTIONAL) {
-               braces[0] = "[";
-               braces[1] = "]";
+               break;
+       default:
+               __builtin_unreachable();
        }
 
-       fprintf(f, " %s%s%s", braces[0], usage, braces[1]);
+       return spec;
 }
 
-static void
-_os_subcommand_print_usage(const os_subcommand_t *osc, FILE *f)
+static char *
+_os_subcommand_copy_usage_line(const os_subcommand_t *osc)
 {
-       const struct option *opts = osc->osc_options;
-       const struct option *curopt = NULL;
+       char *usage_line = NULL;
        size_t i = 0;
+       const os_subcommand_option_t *osco_i = NULL;
+       const char *optional_spec = "";
+       char subcmd_name[64];
+       int ret = -1;
 
-       fprintf(f, "usage: %s %s", getprogname(), osc->osc_name);
+       // The usage line does not enumerate all possible optional options, just the
+       // required options. If there are optional options, then display that but
+       // otherwise leave them to be described by more extensive usage information.
+       if (osc->osc_optional) {
+               optional_spec = " [options]";
+       }
 
-       while ((curopt = &opts[i]) && curopt->name) {
-               _os_subcommand_print_optarg_usage(osc, curopt, f);
-               i++;
+       if (osc == _main_cmd) {
+               strlcpy(subcmd_name, "", sizeof(subcmd_name));
+       } else {
+               snprintf(subcmd_name, sizeof(subcmd_name), " %s", osc->osc_name);
        }
 
-       fprintf(f, "\n");
+       ret = asprintf(&usage_line, "%s%s%s",
+                       getprogname(), subcmd_name, optional_spec);
+       if (ret < 0) {
+               os_assert_zero(ret);
+       }
+
+       i = 0;
+       OS_SUBCOMMAND_OPTIONS_FOREACH(osco_i, osc, required, i) {
+               char *__os_free usage_line_old = NULL;
+               char *__os_free osco_spec = NULL;
+
+               usage_line_old = usage_line;
+
+               osco_spec = _os_subcommand_copy_option_spec_long(osc, osco_i);
+               ret = asprintf(&usage_line, "%s %s", usage_line, osco_spec);
+               if (ret < 0) {
+                       os_assert_zero(ret);
+               }
+       }
+
+       i = 0;
+       OS_SUBCOMMAND_OPTIONS_FOREACH(osco_i, osc, positional, i) {
+               char *__os_free usage_line_old = NULL;
+               char *__os_free osco_spec = NULL;
+               const char *braces[] = {
+                       "<",
+                       ">",
+               };
+
+               if (osco_i->osco_flags & OS_SUBCOMMAND_OPTION_FLAG_OPTIONAL_POS) {
+                       braces[0] = "[";
+                       braces[1] = "]";
+               }
+
+               usage_line_old = usage_line;
+
+               osco_spec = _os_subcommand_copy_option_spec_long(osc, osco_i);
+               ret = asprintf(&usage_line, "%s %s%s%s",
+                               usage_line, braces[0], osco_spec, braces[1]);
+               if (ret < 0) {
+                       os_assert_zero(ret);
+               }
+       }
+
+       if (osc == _main_cmd && osc != _internal_main_cmd) {
+               // Always include the positional subcommand when printing usage for the
+               // main subcommand. We do not expect it to be specified in a user-
+               // provided main subcommand.
+               const os_subcommand_option_t *subopt = &_main_positional[0];
+               char *__os_free usage_line_old = NULL;
+               char *__os_free osco_spec = NULL;
+
+               usage_line_old = usage_line;
+
+               osco_spec = _os_subcommand_copy_option_spec_long(osc, subopt);
+               ret = asprintf(&usage_line, "%s <%s>", usage_line, osco_spec);
+               if (ret < 0) {
+                       os_assert_zero(ret);
+               }
+       }
+
+       return usage_line;
 }
 
 static void
-_os_subcommand_print_optarg_human(const os_subcommand_t *osc,
-               const struct option *opt, FILE *f)
+_os_subcommand_print_option_usage(const os_subcommand_t *osc,
+               const os_subcommand_option_t *osco, FILE *f)
 {
-       os_subcommand_option_t scopt = {
-               .osco_flags = 0,
-               .osco_argdesc = opt->name,
-       };
-       char *__os_free usage = NULL;
-       char *__os_free human = NULL;
+       char *__os_free opt_spec = NULL;
+       ssize_t initpad = -CTL_OUTPUT_OPTARG_INDENT;
+
+       opt_spec = _os_subcommand_copy_option_spec(osc, osco,
+                       OS_SUBCOMMAND_OPTION_SPEC_COMBINED);
+       fprintf(f, "    %-24s    ", opt_spec);
 
-       usage = _os_subcommand_copy_optarg_usage(osc, opt,
-                       OS_SUBCOMMAND_OPTARG_USAGE, &scopt);
-       fprintf(f, "    %-24s", usage);
+       // If the usage specifier is long, start the description on the next line.
+       if (strlen(opt_spec) >= CTL_OUTPUT_OPTARG_OVERFLOW) {
+               initpad = CTL_OUTPUT_OPTARG_INDENT;
+               crfprintf_np(f, "");
+       }
 
-       human = _os_subcommand_copy_optarg_usage(osc, opt,
-                       OS_SUBCOMMAND_OPTARG_HUMAN, &scopt);
-       wfprintf_np(f, -CTL_OUTPUT_OPTARG_PAD, CTL_OUTPUT_OPTARG_PAD,
-                       CTL_OUTPUT_WIDTH, "%s", scopt.osco_argdesc);
+       wfprintf_np(f, initpad, CTL_OUTPUT_OPTARG_INDENT, _ttys->ts_cols, "%s",
+                       osco->osco_argument_human);
 }
 
 static void
-_os_subcommand_print_human(const os_subcommand_t *osc, FILE *f)
+_os_subcommand_print_help_line(const os_subcommand_t *osc, FILE *f)
 {
-       const struct option *opts = osc->osc_options;
-       const struct option *curopt = NULL;
-       size_t i = 0;
+       ssize_t initpad = -CTL_OUTPUT_OPTARG_INDENT;
 
-       _os_subcommand_print_usage(osc, f);
+       fprintf(f, "    %-24s    ", osc->osc_name);
 
-       while ((curopt = &opts[i]) && curopt->name) {
-               _os_subcommand_print_optarg_human(osc, curopt, f);
-               i++;
+       // If the usage specifier is long, start the description on the next line.
+       if (strlen(osc->osc_name) >= CTL_OUTPUT_OPTARG_OVERFLOW) {
+               initpad = CTL_OUTPUT_OPTARG_INDENT;
+               crfprintf_np(f, "");
        }
+
+       wfprintf_np(f, initpad, CTL_OUTPUT_OPTARG_INDENT, _ttys->ts_cols, "%s",
+                       osc->osc_desc);
 }
 
 static void
-_os_subcommand_print_list(const os_subcommand_t *osc, FILE *f)
+_os_subcommand_print_usage(const os_subcommand_t *osc, FILE *f)
 {
-       wfprintf_np(f, CTL_OUTPUT_LIST_PAD, 0, 0, "%-24s %s",
-                       osc->osc_name, osc->osc_desc);
-}
+       size_t i = 0;
+       const os_subcommand_option_t *osco_i = NULL;
+       char *__os_free usage_line = NULL;
+       bool header_printed = false;
 
-static const os_subcommand_t *
-_os_subcommand_find(const char *name)
-{
-       const os_subcommand_t **oscip = NULL;
+       usage_line = _os_subcommand_copy_usage_line(osc);
 
-       if (strcmp(_help_cmd.osc_name, name) == 0) {
-               return &_help_cmd;
+       wfprintf_np(f, 0, 4, _ttys->ts_cols, "USAGE:");
+       crfprintf_np(f, "");
+       wfprintf_np(f, 4, 4, _ttys->ts_cols, "%s", usage_line);
+
+       if (osc->osc_long_desc) {
+               // The long description gets printed in its own paragraph.
+               _print_header(f, "DESCRIPTION", NULL);
+               wfprintf_np(f, 4, 4, _ttys->ts_cols, "%s", osc->osc_long_desc);
+       } else if (osc->osc_desc) {
+               // The short description gets printed on the same line.
+               crfprintf_np(f, "");
+               wfprintf_np(f, 0, 4, _ttys->ts_cols, "DESCRIPTION: %s",
+                               osc->osc_desc);
        }
 
-       LINKER_SET_FOREACH(oscip, const os_subcommand_t **, SUBCOMMAND_LINKER_SET) {
-               const os_subcommand_t *osci = *oscip;
+       if (osc->osc_required || osc->osc_positional || osc == _main_cmd) {
+               i = 0;
+               OS_SUBCOMMAND_OPTIONS_FOREACH(osco_i, osc, required, i) {
+                       _print_header(f, "REQUIRED", &header_printed);
+                       _os_subcommand_print_option_usage(osc, osco_i, f);
+               }
 
-               if (strcmp(osci->osc_name, name) == 0) {
-                       return osci;
+               i = 0;
+               OS_SUBCOMMAND_OPTIONS_FOREACH(osco_i, osc, positional, i) {
+                       _print_header(f, "REQUIRED", &header_printed);
+
+                       if (osco_i->osco_flags & OS_SUBCOMMAND_OPTION_FLAG_OPTIONAL_POS) {
+                               continue;
+                       }
+
+                       _os_subcommand_print_option_usage(osc, osco_i, f);
+               }
+
+               if (osc == _main_cmd && osc != _internal_main_cmd) {
+                       // We do not expect the user's main command to specify that a
+                       // subcommand must follow, so always defer to ours.
+                       _print_header(f, "REQUIRED", &header_printed);
+                       _os_subcommand_print_option_usage(osc, &_main_positional[0], f);
                }
        }
 
-       return NULL;
+       header_printed = false;
+
+       if (osc->osc_optional || osc->osc_positional) {
+               i = 0;
+               OS_SUBCOMMAND_OPTIONS_FOREACH(osco_i, osc, optional, i) {
+                       _print_header(f, "OPTIONAL", &header_printed);
+                       _os_subcommand_print_option_usage(osc, osco_i, f);
+               }
+
+               i = 0;
+               OS_SUBCOMMAND_OPTIONS_FOREACH(osco_i, osc, positional, i) {
+                       if (osco_i->osco_flags & OS_SUBCOMMAND_OPTION_FLAG_OPTIONAL_POS) {
+                               _print_header(f, "OPTIONAL", &header_printed);
+                               _os_subcommand_print_option_usage(osc, osco_i, f);
+                       }
+               }
+       }
 }
 
-#pragma mark Default Usage
-static void
-_usage_default(FILE *f)
+static const os_subcommand_t *
+_os_subcommand_find(const char *name)
 {
        const os_subcommand_t **oscip = NULL;
 
-       crfprintf_np(f, "usage: %s <subcommand> [...] | help [subcommand]",
-                       getprogname());
-       crfprintf_np(f, "");
+       if (!name) {
+               return _main_cmd;
+       }
+
+       if (strcmp(_help_cmd->osc_name, name) == 0) {
+               return &__help_cmd;
+       }
 
-       crfprintf_np(f, "subcommands:");
        LINKER_SET_FOREACH(oscip, const os_subcommand_t **, SUBCOMMAND_LINKER_SET) {
                const os_subcommand_t *osci = *oscip;
-               _os_subcommand_print_list(osci, f);
+
+               if (osci->osc_flags & OS_SUBCOMMAND_FLAG_MAIN) {
+                       // The main subcommand cannot be invoked directly.
+                       continue;
+               }
+
+               if (strcmp(osci->osc_name, name) == 0) {
+                       return osci;
+               }
        }
 
-       _os_subcommand_print_list(&_help_cmd, f);
+       return NULL;
 }
 
 static int
-_usage(FILE *f)
+_os_subcommand_be_helpful(const os_subcommand_t *osc,
+               int argc, const char *argv[])
 {
-       _usage_default(f);
-       return EX_USAGE;
-}
+       int res = 0;
 
-#pragma mark Help Subcommand
-static int _help_invoke(const os_subcommand_t *osc,
-       int argc,
-       const char *argv[]
-);
+       if (osc->osc_flags & OS_SUBCOMMAND_FLAG_HELPFUL) {
+               if (argc == 1) {
+                       _os_subcommand_print_usage(osc, stdout);
+                       res = 1;
+                       goto __out;
+               }
+       }
 
-static const os_subcommand_t _help_cmd = {
-       .osc_version = OS_SUBCOMMAND_VERSION,
-       .osc_flags = 0,
-       .osc_name = "help",
-       .osc_desc = "prints helpful information",
-       .osc_optstring = NULL,
-       .osc_options = NULL,
-       .osc_info = NULL,
-       .osc_invoke = &_help_invoke,
-};
+       if (osc->osc_flags & OS_SUBCOMMAND_FLAG_HELPFUL_FIRST_OPTION) {
+               if (argc == 2 && (strcmp(argv[1], "help") == 0 ||
+                               strcmp(argv[1], "-h") == 0 ||
+                               strcmp(argv[1], "-help") == 0 ||
+                               strcmp(argv[1], "--help") == 0)) {
+                       _os_subcommand_print_usage(osc, stdout);
+                       res = 1;
+                       goto __out;
+               }
+       }
 
-static void
-_help_print_subcommand(const os_subcommand_t *osc, FILE *f)
-{
-       wfprintf_np(f, 4, 4, 76, "%-16s%s", osc->osc_name, osc->osc_desc);
+__out:
+       return res;
 }
 
 static void
-_help_print_all(FILE *f)
+_print_subcommand_list(const os_subcommand_t *osc, FILE *f)
 {
        const os_subcommand_t **oscip = NULL;
+       bool header_printed = false;
 
-       _usage_default(f);
-       crfprintf_np(f, "");
-
-       crfprintf_np(f, "subcommands:");
-       LINKER_SET_FOREACH(oscip, const os_subcommand_t **, SUBCOMMAND_LINKER_SET) {
+       LINKER_SET_FOREACH(oscip, const os_subcommand_t **,
+                       SUBCOMMAND_LINKER_SET) {
                const os_subcommand_t *osci = *oscip;
-               if (osci->osc_flags & OS_SUBCOMMAND_FLAG_HIDDEN) {
-                       continue;
-               }
-               _help_print_subcommand(osci, f);
-       }
-}
 
-static int
-_help_invoke(const os_subcommand_t *osc, int argc, const char *argv[])
-{
-       const os_subcommand_t *target = NULL;
+               _print_header(f, "SUBCOMMANDS", &header_printed);
 
-       if (argc == 1) {
-               _help_print_all(stdout);
-       } else {
-               target = _os_subcommand_find(argv[1]);
-               if (!target) {
-                       crfprintf_np(stderr, "unrecognized subcommand: %s", argv[1]);
-                       _usage_default(stderr);
-                       return EX_USAGE;
+               if ((osci->osc_flags & OS_SUBCOMMAND_FLAG_MAIN) ||
+                               (osci->osc_flags & OS_SUBCOMMAND_FLAG_HIDDEN)) {
+                       continue;
                }
 
-               _os_subcommand_print_human(target, stdout);
+               _os_subcommand_print_help_line(osci, f);
        }
 
-       return 0;
+       // Print the help subcommand last.
+       _os_subcommand_print_help_line(osc, f);
 }
 
 #pragma mark API
 int
-os_subcommand_main(int argc, const char *argv[])
+os_subcommand_main(int argc, const char *argv[],
+               os_subcommand_main_flags_t flags)
 {
-       int exitcode = -1;
+       int xit = -1;
        const char *cmdname = NULL;
-       const os_subcommand_t *osci = NULL;
+       const os_subcommand_t *osc = NULL;
+       const os_subcommand_t **oscip = NULL;
+
+       _init_column_count();
+
+       // Find the main subcommand if any exists. Otherwise we'll just use our pre-
+       // canned main subcommand.
+       LINKER_SET_FOREACH(oscip, const os_subcommand_t **, SUBCOMMAND_LINKER_SET) {
+               osc = *oscip;
+               if (osc->osc_flags & OS_SUBCOMMAND_FLAG_MAIN) {
+                       _main_cmd = osc;
+                       break;
+               }
+       }
+
+       osc = NULL;
 
-       if (argc < 2) {
-               exitcode = _usage(stderr);
+       // See if we just need to print help for the main command.
+       if (_os_subcommand_be_helpful(_main_cmd, argc, argv)) {
+               _print_subcommand_list(_help_cmd, stdout);
+               xit = 0;
+               goto __out;
+       }
+
+       // Invoke the main subcommand to snarf any global options. Our default
+       // implementation does nothing and just returns 0.
+       xit = _main_cmd->osc_invoke(_main_cmd, argc, argv);
+       if (xit) {
                goto __out;
        }
 
        // Advance argument pointer and make the subcommand argv[0].
-       argc -= 1;
-       argv += 1;
+       argc -= optind;
+       argv += optind;
        cmdname = argv[0];
 
-       osci = _os_subcommand_find(cmdname);
-       if (osci) {
-               if (osci->osc_flags & OS_SUBCOMMAND_FLAG_REQUIRE_ROOT) {
+       if (argc < 1) {
+               os_subcommand_fprintf(NULL, stderr, "please provide a subcommand");
+               xit = EX_USAGE;
+               goto __out;
+       }
+
+       osc = _os_subcommand_find(cmdname);
+       if (osc) {
+               if (osc->osc_flags & OS_SUBCOMMAND_FLAG_REQUIRE_ROOT) {
                        if (geteuid()) {
-                               crfprintf_np(stderr, "subcommand requires root: %s", cmdname);
-                               exitcode = EX_NOPERM;
+                               os_subcommand_fprintf(osc, stderr,
+                                               "subcommand requires root: %s",
+                                               cmdname);
+                               xit = EX_NOPERM;
                                goto __out;
                        }
                }
 
-               if (osci->osc_flags & OS_SUBCOMMAND_FLAG_TTYONLY) {
+               if (osc->osc_flags & OS_SUBCOMMAND_FLAG_TTYONLY) {
                        if (!isatty(STDOUT_FILENO) || !isatty(STDIN_FILENO)) {
-                               crfprintf_np(stderr, "subcommand requires a tty: %s", cmdname);
-                               exitcode = EX_UNAVAILABLE;
+                               os_subcommand_fprintf(osc, stderr,
+                                               "subcommand requires a tty: %s",
+                                               cmdname);
+                               xit = EX_UNAVAILABLE;
                                goto __out;
                        }
                }
 
-               exitcode = osci->osc_invoke(osci, argc, argv);
-               if (exitcode == EX_USAGE) {
-                       _os_subcommand_print_usage(osci, stderr);
+               if (_os_subcommand_be_helpful(osc, argc, argv)) {
+                       xit = 0;
+                       goto __out;
                }
+
+               xit = osc->osc_invoke(osc, argc, argv);
        } else {
-               crfprintf_np(stderr, "unrecognized subcommand: %s", cmdname);
-               exitcode = _usage(stderr);
+               os_subcommand_fprintf(NULL, stderr, "unknown subcommand: %s", cmdname);
+               xit = EX_USAGE;
        }
 
 __out:
-       return exitcode;
+       if (xit == EX_USAGE) {
+               if (!osc) {
+                       // If we couldn't find the subcommand, then print the list of known
+                       // subcommands.
+                       _print_subcommand_list(_help_cmd, stderr);
+               } else {
+                       _os_subcommand_print_usage(osc, stderr);
+               }
+       }
+
+       return xit;
+}
+
+void
+os_subcommand_fprintf(const os_subcommand_t *osc, FILE *f,
+               const char *fmt, ...)
+{
+       va_list ap;
+
+       va_start(ap, fmt);
+       vcrfprintf_np(f, fmt, ap);
+       va_end(ap);
+}
+
+void
+os_subcommand_vfprintf(const os_subcommand_t *osc, FILE *f,
+               const char *fmt, va_list ap)
+{
+       if (!osc || (osc->osc_flags & OS_SUBCOMMAND_FLAG_MAIN)) {
+               fprintf(f, "%s: ", getprogname());
+       } else {
+               fprintf(f, "%s-%s: ", getprogname(), osc->osc_name);
+       }
+
+       vcrfprintf_np(f, fmt, ap);
 }