summaryrefslogtreecommitdiffstats
path: root/usr.sbin/afs/src/lib/cmd/cmd.c
diff options
context:
space:
mode:
authorart <art@openbsd.org>2000-09-11 14:40:26 +0000
committerart <art@openbsd.org>2000-09-11 14:40:26 +0000
commit2caf32899aba1af6b57e8ce1e682a74cda4f7160 (patch)
treee4f7aefca7feb82ab6a6b4488de1458b9b0f59f9 /usr.sbin/afs/src/lib/cmd/cmd.c
parentNew xfs from Arla between 0.34.2 and current in arla cvs. (diff)
downloadwireguard-openbsd-2caf32899aba1af6b57e8ce1e682a74cda4f7160.tar.xz
wireguard-openbsd-2caf32899aba1af6b57e8ce1e682a74cda4f7160.zip
New Arla userland from Arla between 0.34.2 and current in arla cvs.
Too many new features and fixes to mention here.
Diffstat (limited to 'usr.sbin/afs/src/lib/cmd/cmd.c')
-rw-r--r--usr.sbin/afs/src/lib/cmd/cmd.c1016
1 files changed, 1016 insertions, 0 deletions
diff --git a/usr.sbin/afs/src/lib/cmd/cmd.c b/usr.sbin/afs/src/lib/cmd/cmd.c
new file mode 100644
index 00000000000..41da62309d9
--- /dev/null
+++ b/usr.sbin/afs/src/lib/cmd/cmd.c
@@ -0,0 +1,1016 @@
+/*
+ * Copyright (c) 2000 Kungliga Tekniska Högskolan
+ * (Royal Institute of Technology, Stockholm, Sweden).
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * 3. Neither the name of the Institute nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <sys/types.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <time.h>
+#include <strings.h>
+#include <assert.h>
+#include <ctype.h>
+#include <err.h>
+
+#include <cmd.h>
+
+#ifdef RCSID
+RCSID("$Id: cmd.c,v 1.1 2000/09/11 14:40:55 art Exp $");
+#endif
+
+static struct cmd_syndesc *cmd_cmds = NULL;
+static struct cmd_syndesc **cmd_lastcmd = &cmd_cmds;
+static int _cmd_init = 0;
+
+static int (*before_proc) (void *rock) = NULL;
+static void *before_rock = NULL;
+static int (*after_proc) (void *rock) = NULL;
+static void *after_rock = NULL;
+
+static void
+cmd_PrintSyntaxManDoc (const char *commandname);
+
+
+static struct cmd_syndesc *
+new_cmd (const char *name, const char *help_str, struct cmd_syndesc *alias)
+{
+ struct cmd_syndesc *ts;
+
+ ts = malloc (sizeof(*ts));
+ if (ts == NULL)
+ return NULL;
+ memset (ts, 0, sizeof (*ts));
+
+ if (name) {
+ ts->name = strdup (name);
+ if (ts->name == NULL) {
+ free (ts);
+ return NULL;
+ }
+ }
+ if (help_str) {
+ ts->help = strdup (help_str);
+ if (ts->help == NULL) {
+ free (ts->name);
+ free (ts);
+ return NULL;
+ }
+ }
+ if (alias) {
+ ts->aliasOf = alias;
+ ts->nextAlias = alias->nextAlias;
+ alias->nextAlias = ts;
+ ts->flags |= CMD_ALIAS;
+ }
+ if (ts->name == NULL) {
+ assert (cmd_cmds == NULL || cmd_cmds->name != NULL);
+ ts->next = cmd_cmds;
+ if (&cmd_cmds == cmd_lastcmd)
+ cmd_lastcmd = &ts->next;
+ cmd_cmds = ts;
+ } else {
+ *cmd_lastcmd = ts;
+ cmd_lastcmd = &ts->next;
+ }
+ return ts;
+}
+
+/*
+ *
+ */
+
+static int
+find_command (struct cmd_syndesc *cmd_cmds, const char *func,
+ struct cmd_syndesc **ret)
+{
+ struct cmd_syndesc *partial_match = NULL;
+ struct cmd_syndesc *ts;
+ int partial_len = strlen (func);
+
+ for (ts = cmd_cmds; ts; ts = ts->next) {
+ if (ts->name == NULL)
+ continue;
+ if (strcasecmp (ts->name, func) == 0) {
+ if (ts->aliasOf)
+ ts = ts->aliasOf;
+ *ret = ts;
+ return 0;
+ }
+ if (strncasecmp (ts->name, func, partial_len) == 0) {
+ if (partial_match)
+ return CMD_AMBIG;
+ partial_match = ts;
+ }
+ }
+ if (partial_match) {
+ if (partial_match->aliasOf)
+ partial_match = partial_match->aliasOf;
+ *ret = partial_match;
+ return 0;
+ }
+ return CMD_UNKNOWNCMD;
+}
+
+/*
+ *
+ */
+
+static void
+print_usage (const char *name, struct cmd_syndesc *ts)
+{
+ int i;
+
+ if (getenv ("CMD_MANDOC") != NULL) {
+ cmd_PrintSyntaxManDoc(__progname); /* XXX */
+ return;
+ }
+
+ printf ("%s", name);
+ if (ts->name)
+ printf (" %s", ts->name);
+
+ for (i = 0; i < CMD_MAXPARMS ; i++) {
+ char *help = ts->parms[i].help;
+ char *name = ts->parms[i].name;
+ if (help == NULL)
+ help = "arg";
+ if ((ts->parms[i].flags & CMD_HIDE) == CMD_HIDE || name == NULL)
+ continue;
+ printf (" ");
+ if ((ts->parms[i].flags & CMD_OPTIONAL) == CMD_OPTIONAL)
+ printf ("[");
+ switch (ts->parms[i].type) {
+ case CMD_FLAG:
+ printf ("%s", name);
+ break;
+ case CMD_SINGLE:
+ printf ("%s <%s>", name, help);
+ break;
+ case CMD_LIST:
+ printf ("%s <%s>+", name, help);
+ break;
+ default:
+ abort();
+ }
+ if ((ts->parms[i].flags & CMD_OPTIONAL) == CMD_OPTIONAL)
+ printf ("]");
+ }
+ if (ts->name == NULL)
+ printf (" command");
+ printf ("\n");
+}
+
+/*
+ *
+ */
+
+static int
+cmd_internal_help (struct cmd_syndesc *t, void *ptr)
+{
+ struct cmd_syndesc *ts;
+ char *help;
+
+ if (getenv ("CMD_MANDOC") != NULL) {
+ cmd_PrintSyntaxManDoc(__progname); /* XXX */
+ return 0;
+ }
+
+ if (t->parms[0].items == NULL) {
+
+ for (ts = cmd_cmds; ts; ts = ts->next) {
+ if (ts->name == NULL && cmd_cmds == ts)
+ continue;
+ if ((ts->flags & CMD_HIDDEN) == CMD_HIDDEN)
+ continue;
+ if (ts->aliasOf)
+ continue;
+ if (ts->help)
+ help = ts->help;
+ else
+ help = "";
+
+ printf ("%-10s %s\n", ts->name, help);
+ }
+ } else {
+ char *cmd = t->parms[0].items->data;
+ struct cmd_syndesc *ts;
+ int ret;
+
+ ret = find_command (cmd_cmds, cmd, &ts);
+ if (ret)
+ return ret;
+ print_usage (__progname, ts); /* XXX */
+ }
+ return 0;
+}
+
+/*
+ *
+ */
+
+static int
+cmd_internal_apropos (struct cmd_syndesc *t, void *ptr)
+{
+ struct cmd_syndesc *ts;
+ char *cmd, *help;
+
+ cmd = t->parms[0].items->data;
+
+ for (ts = cmd_cmds; ts; ts = ts->next) {
+ if (ts->name == NULL && cmd_cmds == ts)
+ continue;
+ if (ts->help)
+ help = ts->help;
+ else
+ help = "";
+ if (strstr(ts->name, cmd))
+ printf ("%-10s %s\n", ts->name, help);
+ }
+ return 0;
+}
+
+/*
+ * Create a new command with `name' that will run the function `main'
+ * with the `rock'. When help is choose `help_str' will be displayed.
+ */
+
+struct cmd_syndesc *
+cmd_CreateSyntax (const char *name, cmd_proc main, void *rock,
+ const char *help_str)
+{
+ struct cmd_syndesc *ts;
+
+ ts = new_cmd (name, help_str, NULL);
+
+ ts->proc = main;
+ ts->rock = rock;
+
+ cmd_Seek (ts, CMD_HELPPARM);
+ cmd_AddParm (ts, "-help", CMD_FLAG, CMD_OPTIONAL, "get detailed help");
+ cmd_Seek (ts, 0);
+
+ return ts;
+}
+
+/*
+ *
+ */
+
+int
+cmd_SetBeforeProc (int (*proc) (void *), void *rock)
+{
+ before_proc = proc;
+ before_rock = rock;
+ return 0;
+}
+
+/*
+ *
+ */
+
+int
+cmd_SetAfterProc (int (*proc) (void *rock), void *rock)
+{
+ after_proc = proc;
+ after_rock = rock;
+ return 0;
+}
+
+/*
+ * Allocate a new parameter to `ts' with name `cmd' of `type' and with
+ * `flags'. When help is needed show `help_str'.
+ */
+
+void
+cmd_AddParm (struct cmd_syndesc *ts, const char *name,
+ cmd_parmdesc_type type, cmd_parmdesc_flags flags,
+ const char *help_str)
+{
+ struct cmd_parmdesc *p = &ts->parms[ts->nParams];;
+
+ memset (p, 0, sizeof(*p));
+
+ if (ts->nParams > CMD_HELPPARM)
+ abort();
+
+ p->name = strdup (name);
+ if (p->name == NULL)
+ return;
+ p->help = strdup(help_str);
+ if (p->help == NULL) {
+ free (p->name);
+ return;
+ }
+ ts->nParams++;
+
+ p->type = type;
+ p->flags = flags;
+}
+
+/*
+ *
+ */
+
+int
+cmd_CreateAlias (struct cmd_syndesc *orignal, const char *name)
+{
+ struct cmd_syndesc *ts;
+ ts = new_cmd (name, NULL, orignal);
+ if (ts == NULL)
+ return CMD_INTERALERROR;
+ return 0;
+}
+
+/*
+ *
+ */
+
+int
+cmd_Seek (struct cmd_syndesc *ts, int pos)
+{
+ if (pos > CMD_HELPPARM || pos < 0)
+ return CMD_EXCESSPARMS;
+ ts->nParams = pos;
+ return 0;
+}
+
+/*
+ *
+ */
+
+void
+cmd_FreeArgv (char **argv)
+{
+ return;
+}
+
+/*
+ *
+ */
+
+#define CMD_IS_CMD(str) (str[0] == '-' && !isdigit(str[1]))
+
+/*
+ *
+ */
+
+static struct cmd_parmdesc *
+find_next_param (struct cmd_syndesc *ts, int *curval)
+{
+ int i;
+ for (i = *curval; i < CMD_MAXPARMS ; i++) {
+ if ((ts->parms[i].flags & CMD_EXPANDS) == CMD_EXPANDS)
+ break;
+ if (ts->parms[i].name == NULL)
+ continue;
+ if (ts->parms[i].items != NULL)
+ continue;
+ break;
+ }
+ if (i >= CMD_MAXPARMS)
+ return NULL;
+ *curval = i;
+ return &ts->parms[i];
+}
+
+/*
+ *
+ */
+
+static int
+find_next_name (struct cmd_syndesc *ts, const char *name,
+ struct cmd_parmdesc **ret)
+{
+ struct cmd_parmdesc *partial_match = NULL;
+ int i, partial_len = strlen(name);
+
+ for (i = 0; i < CMD_MAXPARMS; i++) {
+ if (ts->parms[i].name == NULL)
+ continue;
+ if (strcasecmp (name, ts->parms[i].name) == 0) {
+ *ret = &ts->parms[i];
+ return 0;
+ }
+ if (strncasecmp (name, ts->parms[i].name, partial_len) == 0) {
+ if (partial_match)
+ return CMD_AMBIG;
+ partial_match = &ts->parms[i];
+ }
+ }
+ if (partial_match) {
+ *ret = partial_match;
+ return 0;
+ }
+ return CMD_UNKNOWNSWITCH;
+}
+
+/*
+ *
+ */
+
+static struct cmd_item *
+new_items (struct cmd_parmdesc *p)
+{
+ struct cmd_item *i;
+ i = malloc (sizeof (*i));
+ if (i == NULL)
+ err (1, "new_items");
+ i->next = p->items;
+ p->items = i;
+ return i;
+}
+
+/*
+ *
+ */
+
+static int
+parse_options (int argc, char **argv, int *optind, struct cmd_syndesc *ts,
+ int failp)
+{
+ struct cmd_parmdesc *p;
+ int i, ret;
+
+ for (i = 0; i < CMD_MAXPARMS; i++) {
+ if (ts->parms[i].name)
+ break;
+ }
+ if (i == CMD_MAXPARMS)
+ return 0;
+
+
+ for (i = 0; i < argc; i++) {
+ ret = find_next_name (ts, argv[i], &p);
+ if (ret) {
+ if (failp)
+ return ret;
+ break;
+ }
+ switch (p->type) {
+ case CMD_FLAG:
+ assert (p->items == NULL);
+ p->items = new_items (p);
+ p->items->data = p;
+ break;
+ case CMD_SINGLE:
+ assert (p->items == NULL);
+ if (i == argc - 1)
+ return CMD_TOOFEW;
+ i++;
+ p->items = new_items (p);
+ p->items->data = argv[i];
+ break;
+ case CMD_LIST:
+ if (i == argc - 1)
+ return CMD_TOOFEW;
+ i++;
+ while (i < argc) {
+ p->items = new_items (p);
+ p->items->data = argv[i];
+ if (i >= argc - 1 || CMD_IS_CMD(argv[i+1]))
+ break;
+ i++;
+ }
+ break;
+ default:
+ abort();
+ }
+ }
+ if (argc < i)
+ i = argc;
+ *optind = i;
+ return 0;
+}
+
+/*
+ *
+ */
+
+static int
+parse_magic_options (int argc, char **argv, int *optind,
+ struct cmd_syndesc *ts)
+{
+ struct cmd_parmdesc *p;
+ int i, curval = 0;
+
+ for (i = 0; i < argc; i++) {
+ if (CMD_IS_CMD(argv[i]))
+ break;
+ p = find_next_param (ts, &curval);
+ if (p == NULL)
+ break;
+ if (p->type == CMD_FLAG) {
+#if 0
+ assert (p->items == NULL);
+ p->items = new_items (p);
+ p->items->data = p;
+#else
+ break;
+#endif
+ } else if (p->type == CMD_SINGLE) {
+ assert (p->items == NULL);
+ p->items = new_items (p);
+ p->items->data = argv[i];
+ } else if (p->type == CMD_LIST) {
+ while (i < argc) {
+ p->items = new_items (p);
+ p->items->data = argv[i];
+ if ((i >= argc - 1 || CMD_IS_CMD(argv[i+1]))
+ || (p->flags & CMD_EXPANDS) == 0)
+ break;
+ i++;
+ }
+ } else {
+#if 0
+ abort();
+#else
+ break;
+#endif
+ }
+ }
+ if (argc < i)
+ i = argc;
+ *optind = i;
+ return 0;
+}
+
+/*
+ *
+ */
+
+static struct cmd_parmdesc *
+req_argumentp (struct cmd_syndesc *ts)
+{
+ int i;
+
+ for (i = 0; i < CMD_MAXPARMS; i++) {
+ if (ts->parms[i].name == NULL)
+ continue;
+ if ((ts->parms[i].flags & CMD_OPTIONAL) == 0
+ && ts->parms[i].items == NULL)
+ return &ts->parms[i];
+ }
+ return NULL;
+}
+
+/*
+ *
+ */
+
+int
+cmd_ParseLine (const char *line, char **argv, int *n, int maxn)
+{
+ return 0;
+}
+
+/*
+ *
+ */
+
+static int
+call_proc (const char *programname, struct cmd_syndesc *ts)
+{
+ struct cmd_parmdesc *p;
+ int ret;
+
+ if (ts->parms[CMD_HELPPARM].items) {
+ print_usage (programname, ts);
+ return 0;
+ }
+
+ p = req_argumentp (ts);
+ if (p) {
+ print_usage (programname, ts);
+ fprintf (stderr, "missing argument: %s\n", &p->name[1]);
+ return CMD_USAGE;
+ }
+
+ if (before_proc)
+ (*before_proc) (before_rock);
+
+ ret = (*ts->proc) (ts, ts->rock);
+
+ if (after_proc)
+ (*after_proc) (before_rock);
+ return ret;
+}
+
+/*
+ *
+ */
+
+int
+cmd_Dispatch (int argc, char **argv)
+{
+ struct cmd_syndesc *ts;
+ int optind = 0;
+ int ret;
+ char *programname = argv[0];
+
+ argc -= 1;
+ argv += 1;
+
+ if (!_cmd_init) {
+ if (cmd_cmds->next != NULL || cmd_cmds->proc == NULL) {
+ ts = cmd_CreateSyntax ("help", cmd_internal_help, NULL, "help");
+ cmd_AddParm (ts, "-cmd", CMD_SINGLE, CMD_OPTIONAL, "command");
+ ts = cmd_CreateSyntax ("apropos", cmd_internal_apropos,
+ NULL, "apropos");
+ cmd_AddParm (ts, "-cmd", CMD_SINGLE, CMD_REQUIRED, "command");
+ }
+ if (cmd_cmds->name)
+ ts = cmd_CreateSyntax ("main", NULL, NULL, NULL);
+ _cmd_init = 1;
+ }
+
+ if (cmd_cmds->next == NULL && cmd_cmds->proc) {
+ ret = parse_magic_options (argc, argv, &optind, ts);
+ if (ret)
+ return ret;
+
+ argv += optind;
+ argc -= optind;
+ optind = 0;
+ }
+ ret = parse_options (argc, argv, &optind, cmd_cmds, 0);
+ if (ret)
+ errx (1, "main parse failed");
+ if (cmd_cmds->next == NULL && cmd_cmds->proc) {
+ return call_proc (programname, cmd_cmds);
+ } else {
+ struct cmd_parmdesc *p;
+
+ if (cmd_cmds->parms[CMD_HELPPARM].items) {
+ print_usage (programname, cmd_cmds);
+ return 0;
+ }
+
+ p = req_argumentp (cmd_cmds);
+ if (p) {
+ fprintf (stderr, "missing argument: %s\n", &p->name[1]);
+ return CMD_USAGE;
+ }
+ }
+
+ argv += optind;
+ argc -= optind;
+
+ if (argc <= 0) {
+ print_usage (programname, ts);
+ return CMD_USAGE;
+ }
+
+ ret = find_command (cmd_cmds, argv[0], &ts);
+ if (ret)
+ return ret;
+
+ argv += 1;
+ argc -= 1;
+ optind = 0;
+
+ ret = parse_magic_options (argc, argv, &optind, ts);
+ if (ret)
+ return ret;
+
+ argv += optind;
+ argc -= optind;
+ optind = 0;
+
+ ret = parse_options (argc, argv, &optind, ts, 1);
+ if (ret)
+ return ret;
+
+ argv += optind;
+ argc -= optind;
+
+ if (argc != 0) {
+ print_usage (programname, ts);
+ return CMD_USAGE;
+ }
+
+ return call_proc (programname, ts);
+}
+
+
+static void
+cmd_PrintParams (struct cmd_syndesc *ts)
+{
+ int i;
+
+ for (i = 0; i < CMD_MAXPARMS ; i++) {
+ char *help = ts->parms[i].help;
+ if (ts->parms[i].name == NULL)
+ continue;
+ if (help == NULL)
+ help = "arg";
+ if ((ts->parms[i].flags & CMD_HIDE) == CMD_HIDE)
+ continue;
+ if ((ts->parms[i].flags & CMD_OPTIONAL) == CMD_OPTIONAL)
+ printf (".Op ");
+ else
+ printf (".");
+ switch (ts->parms[i].type) {
+ case CMD_FLAG:
+ printf ("Cm %s\n", ts->parms[i].name);
+ break;
+ case CMD_SINGLE:
+ printf ("Cm %s Ar %s\n", ts->parms[i].name, help);
+ break;
+ case CMD_LIST:
+ printf ("Cm %s Ar %s ...\n", ts->parms[i].name, help);
+ break;
+ default: abort(); break;
+ }
+ }
+#if 0
+ for (i = 0; i < CMD_MAXPARMS ; i++) {
+ if (ts->parms[i].name == NULL)
+ continue;
+ printf ("\tflag: %s\n", ts->parms[i].name);
+ printf ("\t\thelp: %s\n", ts->parms[i].help);
+ printf ("\t\tflags: ");
+ if ((ts->parms[i].flags & CMD_REQUIRED) == CMD_REQUIRED)
+ printf ("required");
+ if ((ts->parms[i].flags & CMD_EXPANDS) == CMD_EXPANDS)
+ printf ("expands");
+ if ((ts->parms[i].flags & CMD_PROCESSED) == CMD_PROCESSED)
+ printf ("processed");
+ printf ("\n");
+ }
+#endif
+}
+
+/*
+ *
+ */
+
+static int
+cmd_ExtraText (const char *cmd, const char *sectionname,
+ const char *class, const char *name, int withcr)
+{
+ char *fn, *section;
+ char buf[1024];
+ FILE *f;
+ int len, searching = 1;
+
+ asprintf (&fn, "%s.ctx", cmd);
+ f = fopen (fn, "r");
+ if (f == NULL) {
+ free (fn);
+ if (getenv ("srcdir")) {
+ asprintf (&fn, "%s/%s.ctx", getenv("srcdir"), cmd);
+ f = fopen (fn, "r");
+ }
+ if (f == NULL)
+ return 0;
+ }
+ len = asprintf (&section, "%%%s %s", class, name);
+
+ while (fgets (buf, sizeof(buf), f) != NULL) {
+ buf[strlen(buf)-1] = '\0';
+
+ if (buf[0] == '#')
+ continue;
+
+ if (searching) {
+ if (strncasecmp (buf, section, len) == 0) {
+ searching = 0;
+ if (sectionname)
+ printf ("%s", sectionname);
+ }
+ } else {
+ char *p = buf;
+ if (buf[0] == '%') {
+ break;
+ }
+ while (isspace (*p)) p++;
+ if (*p == '\0')
+ continue;
+ printf ("%s%s", p, withcr ? "\n" : "");
+ }
+ }
+ fclose (f);
+ return searching;
+}
+
+static void
+cmd_PrintSyntaxManDoc (const char *commandname)
+{
+ char timestr[64], cmd[64];
+ time_t t;
+ struct cmd_syndesc *ts;
+
+ printf(".\\\" Things to fix:\n");
+ printf(".\\\" * use better macros for arguments (like .Pa for files)\n");
+ printf(".\\\"\n");
+
+ t = time(NULL);
+ strftime(timestr, sizeof(timestr), "%B %e, %Y", localtime(&t));
+ strlcpy(cmd, commandname, sizeof(cmd));
+ cmd[sizeof(cmd)-1] = '\0';
+/* XXX-libroken strupr(cmd);*/
+
+ printf(".Dd %s\n", timestr);
+ printf(".Dt %s ", cmd);
+ if (cmd_ExtraText (commandname, NULL, "name", "section", 0))
+ printf("SECTION");
+ printf ("\n");
+ if (cmd_ExtraText (commandname, ".Os ", "name", "OS", 0))
+ printf(".Os OPERATING_SYSTEM");
+ printf ("\n");
+ printf(".Sh NAME\n");
+ printf(".Nm %s\n", commandname);
+ if (cmd_ExtraText (commandname, ".Nd ", "name", "description", 1))
+ printf(".Nd in search of a description\n");
+ printf(".Sh SYNOPSIS\n");
+ printf(".Nm\n");
+ if (cmd_cmds->name == NULL)
+ cmd_PrintParams (cmd_cmds);
+ if (cmd_cmds->next)
+ printf (".Cm command\n.Op ...");
+ printf ("\n");
+ printf(".Sh DESCRIPTION\n");
+
+ cmd_ExtraText (commandname, NULL, "section", "description", 1);
+
+ if (cmd_cmds->name == NULL && cmd_cmds->next == NULL) {
+ printf (".Pp\n");
+ if (cmd_ExtraText (commandname, NULL, "command", "_main", 1))
+ printf ("Tell someone to add some helptext "
+ "here to the .ctx file\n");
+ } else {
+ printf (".Bl -tag -width Ds\n");
+
+ for (ts = cmd_cmds; ts; ts = ts->next) {
+ struct cmd_syndesc *t = ts->nextAlias;
+
+ if (ts->name == NULL && cmd_cmds == ts)
+ continue;
+ if ((ts->flags & CMD_HIDDEN) == CMD_HIDDEN)
+ continue;
+ if (ts->aliasOf)
+ continue;
+
+ printf (".It %s", ts->name);
+
+ if (t) {
+ while (t) {
+ printf (", %s", t->name);
+ t = t->nextAlias;
+ }
+ }
+ printf ("\n.Pp\n");
+ printf (".Nm \"%s %s\"\n", commandname, ts->name);
+ cmd_PrintParams (ts);
+ printf (".Pp\n");
+ if (strcmp (ts->name, "help") == 0) {
+ printf ("List all commands, or if\n"
+ ".Ar command\n"
+ "is given as an argument, help for that command.\n");
+ } else if (strcmp (ts->name, "apropos") == 0) {
+ printf ("List all command that have the argument\n.Ar command\n"
+ "as a subtring in themself.");
+ } else {
+ if (cmd_ExtraText (commandname, NULL, "command", ts->name, 1))
+ printf ("Tell someone to add some helptext "
+ "here to the .ctx file\n");
+ }
+ }
+ printf(".El\n");
+ }
+
+ cmd_ExtraText (commandname, ".Sh ERRORS\n", "section", "errors", 1);
+ cmd_ExtraText (commandname, ".Sh SEE ALSO\n", "section", "see also", 1);
+ cmd_ExtraText (commandname, ".Sh HISTORY\n", "section", "history", 1);
+ cmd_ExtraText (commandname, ".Sh AUTHORS\n", "section", "authors", 1);
+ cmd_ExtraText (commandname, ".Sh BUGS\n", "section", "bugs", 1);
+}
+
+/*
+ *
+ */
+
+void
+cmd_PrintSyntax (const char *commandname)
+{
+ const char *name;
+ struct cmd_syndesc *ts;
+ int i;
+
+ name = strrchr (commandname, '/');
+ if (name == NULL)
+ name = commandname;
+ else
+ name++;
+
+ if (getenv ("CMD_MANDOC") != NULL) {
+ cmd_PrintSyntaxManDoc(name);
+ return;
+ }
+
+ for (ts = cmd_cmds; ts; ts = ts->next) {
+ struct cmd_syndesc *t = ts->nextAlias;
+
+ if (ts->name == NULL && cmd_cmds == ts)
+ printf ("exec-file: %s\n", name);
+ else
+ printf ("command: %s - %s\n", ts->name, ts->help);
+ printf ("\tflags: ");
+ if ((ts->flags & CMD_ALIAS) == CMD_ALIAS)
+ printf (" alias");
+ if ((ts->flags & CMD_HIDDEN) == CMD_HIDDEN)
+ printf (" hidden");
+ printf ("\n");
+ if (ts->aliasOf)
+ continue;
+ if (t) {
+ printf ("\taliases:");
+ while (t) {
+ printf (" %s", t->name);
+ t = t->nextAlias;
+ }
+ printf ("\n");
+ }
+ for (i = 0; i < CMD_MAXPARMS ; i++) {
+ if (ts->parms[i].name == NULL)
+ continue;
+ printf ("\tflag: %s\n", ts->parms[i].name);
+ switch (ts->parms[i].type) {
+ case CMD_FLAG: printf ("\t\ttype: flag\n"); break;
+ case CMD_SINGLE: printf ("\t\ttype: single\n"); break;
+ case CMD_LIST: printf ("\t\ttype: list\n"); break;
+ default: abort(); break;
+ }
+ printf ("\t\thelp: %s\n", ts->parms[i].help);
+ printf ("\t\tflags: ");
+ if ((ts->parms[i].flags & CMD_REQUIRED) == CMD_REQUIRED)
+ printf ("required");
+ if ((ts->parms[i].flags & CMD_OPTIONAL) == CMD_OPTIONAL)
+ printf ("optional");
+ if ((ts->parms[i].flags & CMD_EXPANDS) == CMD_EXPANDS)
+ printf ("expands");
+ if ((ts->parms[i].flags & CMD_HIDE) == CMD_HIDE)
+ printf ("hide");
+ if ((ts->parms[i].flags & CMD_PROCESSED) == CMD_PROCESSED)
+ printf ("processed");
+ printf ("\n");
+ }
+ }
+}
+
+/*
+ *
+ */
+
+static const char *cmd_errors[] = {
+ "cmd - Excess parameters",
+ "cmd - Internal error",
+ "cmd - Notlist",
+ "cmd - Too many",
+ "cmd - Usage",
+ "cmd - Unknown command",
+ "cmd - Unknown switch",
+ "cmd - Ambigous",
+ "cmd - Too few arguments",
+ "cmd - Too many arguments"
+};
+
+const char *
+cmd_number2str(int error)
+{
+ if (error < CMD_EXCESSPARMS || error > CMD_TOOBIG)
+ return NULL;
+ return cmd_errors[error - CMD_EXCESSPARMS];
+}