cmd: bail if out of memory while printing syntax
[openafs.git] / src / cmd / cmd.c
index f97e558..10b2b1b 100644 (file)
@@ -171,11 +171,12 @@ ParmHelpString(struct cmd_parmdesc *aparm)
     if (aparm->type == CMD_FLAG) {
        return strdup("");
     } else {
-       asprintf(&str, " %s<%s>%s%s",
-                aparm->type == CMD_SINGLE_OR_FLAG?"[":"",
-                aparm->help?aparm->help:"arg",
-                aparm->type == CMD_LIST?"+":"",
-                aparm->type == CMD_SINGLE_OR_FLAG?"]":"");
+       if (asprintf(&str, " %s<%s>%s%s",
+                    aparm->type == CMD_SINGLE_OR_FLAG?"[":"",
+                    aparm->help?aparm->help:"arg",
+                    aparm->type == CMD_LIST?"+":"",
+                    aparm->type == CMD_SINGLE_OR_FLAG?"]":"") < 0)
+           return NULL;
        return str;
     }
 }
@@ -201,18 +202,14 @@ PrintSyntax(struct cmd_syndesc *as)
 
     /* now print usage, from syntax table */
     if (noOpcodes)
-       asprintf(&str, "Usage: %s", as->a0name);
+       len = printf("Usage: %s", as->a0name);
     else {
        if (!strcmp(as->name, initcmd_opcode))
-           asprintf(&str, "Usage: %s[%s]", NName(as->a0name, " "), as->name);
+           len = printf("Usage: %s[%s]", NName(as->a0name, " "), as->name);
        else
-           asprintf(&str, "Usage: %s%s", NName(as->a0name, " "), as->name);
+           len = printf("Usage: %s%s", NName(as->a0name, " "), as->name);
     }
 
-    len = strlen(str);
-    printf("%s", str);
-    free(str);
-
     for (i = 0; i < CMD_MAXPARMS; i++) {
        tp = &as->parms[i];
        if (tp->type == 0)
@@ -223,6 +220,10 @@ PrintSyntax(struct cmd_syndesc *as)
        /* The parameter name is the real name, plus any aliases */
        if (!tp->aliases) {
            name = strdup(tp->name);
+           if (!name) {
+               fprintf(stderr, "Out of memory.\n");
+               return;
+           }
        } else {
            size_t namelen;
            struct cmd_item *alias;
@@ -231,6 +232,10 @@ PrintSyntax(struct cmd_syndesc *as)
                namelen+=strlen(alias->data) + 3;
 
            name = malloc(namelen);
+           if (!name) {
+               fprintf(stderr, "Out of memory.\n");
+               return;
+           }
            strlcpy(name, tp->name, namelen);
 
            for (alias = tp->aliases; alias != NULL; alias = alias->next) {
@@ -242,6 +247,11 @@ PrintSyntax(struct cmd_syndesc *as)
        /* Work out if we can fit what we want to on this line, or if we need to
         * start a new one */
        str = ParmHelpString(tp);
+       if (!str) {
+           fprintf(stderr, "Out of memory.\n");
+           free(name);
+           return;
+       }
        xtralen = 1 + strlen(name) + strlen(str) +
                  ((tp->flags & CMD_OPTIONAL)? 2: 0);
 
@@ -360,11 +370,35 @@ HelpProc(struct cmd_syndesc *as, void *arock)
     int code = 0;
 
     if (as->parms[0].items == 0) {
-       printf("%sCommands are:\n", NName(as->a0name, ": "));
+       struct cmd_syndesc *initcmd = NULL;
+       int count = 0;
+
+       /*
+        * Print the usage of the initcmd command when it is the only
+        * non-hidden, explicit command, otherwise, list the all the commands.
+        */
        for (ts = allSyntax; ts; ts = ts->next) {
-           if ((ts->flags & CMD_ALIAS) || (ts->flags & CMD_HIDDEN))
+           if (ts->flags & (CMD_ALIAS | CMD_HIDDEN | CMD_IMPLICIT)) {
+               continue; /* skip aliases, hidden, and implied commands */
+           }
+           if (strcmp(ts->name, initcmd_opcode) == 0) {
+               initcmd = ts; /* save the initcmd */
                continue;
-           printf("%-15s %s\n", ts->name, (ts->help ? ts->help : ""));
+           }
+           count++;
+       }
+       if (initcmd && count == 0) {
+           initcmd->a0name = as->a0name;
+           PrintAliases(initcmd);
+           PrintSyntax(initcmd);
+           PrintFlagHelp(initcmd);
+       } else {
+           printf("%sCommands are:\n", NName(as->a0name, ": "));
+           for (ts = allSyntax; ts; ts = ts->next) {
+               if ((ts->flags & CMD_ALIAS) || (ts->flags & CMD_HIDDEN))
+                   continue;
+               printf("%-15s %s\n", ts->name, (ts->help ? ts->help : ""));
+           }
        }
     } else {
        /* print out individual help topics */
@@ -442,7 +476,7 @@ SortSyntax(struct cmd_syndesc *as)
  * \param[in] aname  name used to invoke the command
  * \param[in] aproc  procedure to be called when command is invoked
  * \param[in] arock  opaque data pointer to be passed to aproc
- * \param[in] aflags command option flags (CMD_HIDDEN)
+ * \param[in] aflags command option flags
  * \param[in] ahelp  help string to display for this command
  *
  * \return a pointer to the cmd_syndesc or NULL if error.
@@ -459,7 +493,7 @@ cmd_CreateSyntax(char *aname,
        return NULL;
 
     /* Allow only valid cmd flags. */
-    if (aflags & ~CMD_HIDDEN) {
+    if (aflags & ~(CMD_HIDDEN | CMD_IMPLICIT)) {
        return NULL;
     }
 
@@ -766,20 +800,20 @@ initSyntax(void)
     struct cmd_syndesc *ts;
 
     if (!noOpcodes) {
-       ts = cmd_CreateSyntax("help", HelpProc, NULL, 0,
+       ts = cmd_CreateSyntax("help", HelpProc, NULL, CMD_IMPLICIT,
                              "get help on commands");
        cmd_AddParm(ts, "-topic", CMD_LIST, CMD_OPTIONAL, "help string");
 
-       ts = cmd_CreateSyntax("apropos", AproposProc, NULL, 0,
+       ts = cmd_CreateSyntax("apropos", AproposProc, NULL, CMD_IMPLICIT,
                              "search by help text");
        cmd_AddParm(ts, "-topic", CMD_SINGLE, CMD_REQUIRED, "help string");
 
-       cmd_CreateSyntax("version", VersionProc, NULL, 0,
+       cmd_CreateSyntax("version", VersionProc, NULL, CMD_IMPLICIT,
                         "show version");
-       cmd_CreateSyntax("-version", VersionProc, NULL, CMD_HIDDEN, NULL);
-       cmd_CreateSyntax("-help", HelpProc, NULL, CMD_HIDDEN, NULL);
-       cmd_CreateSyntax("--version", VersionProc, NULL, CMD_HIDDEN, NULL);
-       cmd_CreateSyntax("--help", HelpProc, NULL, CMD_HIDDEN, NULL);
+       cmd_CreateSyntax("-version", VersionProc, NULL, (CMD_HIDDEN | CMD_IMPLICIT), NULL);
+       cmd_CreateSyntax("-help", HelpProc, NULL, (CMD_HIDDEN | CMD_IMPLICIT), NULL);
+       cmd_CreateSyntax("--version", VersionProc, NULL, (CMD_HIDDEN | CMD_IMPLICIT), NULL);
+       cmd_CreateSyntax("--help", HelpProc, NULL, (CMD_HIDDEN | CMD_IMPLICIT), NULL);
     }
 }
 
@@ -1272,7 +1306,8 @@ _get_file_string(struct cmd_syndesc *syn, int pos, const char **str)
 
     /* First, try the command_subcommand form */
     if (syn->name != NULL && commandName != NULL) {
-       asprintf(&section, "%s_%s", commandName, syn->name);
+       if (asprintf(&section, "%s_%s", commandName, syn->name) < 0)
+           return ENOMEM;
        *str = cmd_RawConfigGetString(globalConfig, NULL, section,
                                      optionName, NULL);
        free(section);