]> diplodocus.org Git - nmh/blobdiff - sbr/arglist.c
new.c: Order two return statements to match comment.
[nmh] / sbr / arglist.c
index 20bf84c7496bd40d6577cf263bb842e95c3fe2e2..59d311b210d1b1a8ade66885bfccb2554fb26ffe 100644 (file)
@@ -1,6 +1,4 @@
-
-/*
- * arglist.c -- Routines for handling argument lists for execvp() and friends
+/* arglist.c -- Routines for handling argument lists for execvp() and friends
  *
  * This code is Copyright (c) 2013, by the authors of nmh.  See the
  * COPYRIGHT file in the root directory of the nmh distribution for
  *
  * - If there are no spaces or shell metacharacters in "command", then
  *   take it as-is.
- * - If there are spaces in command, space-split command string and
- *   append an argument list to it.
+ * - If there are spaces in command, space-split command string.
  * - If we have shell metacharacters, run the command using
- *   /bin/sh -c 'command "${@}"'.
+ *   /bin/sh -c 'command "$@"'.  In this case, any additional arguments
+ *   appended to the arglist will be expanded by "$@".
  *
  * In all cases additional arguments can be added to the argv[] array.
  */
@@ -52,7 +50,7 @@ argsplit(char *command, char **file, int *argp)
        }
     }
 
-    argvarray = (char **) mh_xmalloc((sizeof(char **) * MAXARGS));
+    argvarray = (char **)mh_xmalloc(sizeof *argvarray * (MAXARGS + 5));
 
     /*
      * The simple case - no spaces or shell metacharacters
@@ -61,35 +59,36 @@ argsplit(char *command, char **file, int *argp)
     if (!space && !metachar) {
        argvarray[0] = getcpy(r1bindex(command, '/'));
        argvarray[1] = NULL;
-       *file = getcpy(command);
+       *file = mh_xstrdup(command);
        if (argp)
            *argp = 1;
        return argvarray;
     }
 
     /*
-     * Spaces, but no shell metacharacters; space-split into seperate
+     * Spaces, but no shell metacharacters; space-split into separate
      * arguments
      */
 
     if (space && !metachar) {
        char **split;
-       p = getcpy(command);
+       p = mh_xstrdup(command);
        split = brkstring(p, " \t", NULL);
        if (split[0] == NULL) {
            adios(NULL, "Invalid blank command found");
        }
-       argvarray[0] = getcpy(r1bindex(split[0], '/'));
+       argvarray[0] = mh_xstrdup(r1bindex(split[0], '/'));
        for (i = 1; split[i] != NULL; i++) {
            if (i > MAXARGS) {
                adios(NULL, "Command exceeded argument limit");
            }
-           argvarray[i] = getcpy(split[i]);
+           argvarray[i] = mh_xstrdup(split[i]);
        }
        argvarray[i] = NULL;
-       *file = getcpy(split[0]);
+       *file = mh_xstrdup(split[0]);
        if (argp)
            *argp = i;
+       free(p);
        return argvarray;
     }
 
@@ -109,12 +108,12 @@ argsplit(char *command, char **file, int *argp)
      *   So we put in a dummy argument (we just use /bin/sh)
      */
 
-    *file = getcpy("/bin/sh");
-    argvarray[0] = getcpy("sh");
-    argvarray[1] = getcpy("-c");
-    argvarray[2] = getcpy(command);
+    *file = mh_xstrdup("/bin/sh");
+    argvarray[0] = mh_xstrdup("sh");
+    argvarray[1] = mh_xstrdup("-c");
+    argvarray[2] = mh_xstrdup(command);
     argvarray[2] = add(" \"$@\"", argvarray[2]);
-    argvarray[3] = getcpy("/bin/sh");
+    argvarray[3] = mh_xstrdup("/bin/sh");
     argvarray[4] = NULL;
 
     if (argp)
@@ -122,3 +121,99 @@ argsplit(char *command, char **file, int *argp)
 
     return argvarray;
 }
+
+/*
+ * Free our argument array
+ */
+
+void
+arglist_free(char *command, char **argvarray)
+{
+    int i;
+
+    free(command);
+
+    if (argvarray != NULL) {
+       for (i = 0; argvarray[i] != NULL; i++)
+           free(argvarray[i]);
+       free(argvarray);
+    }
+}
+
+/*
+ * Similar in functionality to argsplit, but is designed to deal with
+ * a msgs_array.
+ */
+
+void
+argsplit_msgarg(struct msgs_array *msgs, char *command, char **program)
+{
+    int argp, i;
+    char **vec;
+
+    vec = argsplit(command, program, &argp);
+
+    /*
+     * As usual, there is lousy memory management in nmh.  Nothing ever
+     * free's the msgs_array, and a lot of the arguments are allocated
+     * from static memory.  I could have app_msgarg() allocate new
+     * memory for each pointer, but for now I decided to stick with
+     * the existing interface; maybe that will be revisited later.
+     * So we'll just copy over our pointers and free the pointer list
+     * (not the actual pointers themselves).  Note that we don't
+     * include a trailing NULL, since we are expecting the application
+     * to take care of that.
+     */
+
+    for (i = 0; i < argp; i++) {
+       app_msgarg(msgs, vec[i]);
+    }
+
+    free(vec);
+}
+
+/*
+ * Insert a arglist vector into the beginning of an struct msgs array
+ *
+ * Uses by some programs (e.g., show) who want to decide which proc
+ * to use after the argument vector has been constructed
+ */
+
+#ifndef MAXMSGS
+#define MAXMSGS 256
+#endif
+
+void
+argsplit_insert(struct msgs_array *msgs, char *command, char **program)
+{
+    int argp, i;
+    char **vec;
+
+    vec = argsplit(command, program, &argp);
+
+    /*
+     * Okay, we want to shuffle all of our arguments down so we have room
+     * for argp number of arguments.  This means we need to know about
+     * msgs_array internals.  If that changes, we need to change this
+     * code here.
+     */
+
+    if (msgs->size + argp >= msgs->max) {
+        msgs->max += max(MAXMSGS, argp);
+        msgs->msgs = mh_xrealloc(msgs->msgs, msgs->max * sizeof(*msgs->msgs));
+    }
+
+    for (i = msgs->size - 1; i >= 0; i--)
+       msgs->msgs[i + argp] = msgs->msgs[i];
+
+    msgs->size += argp;
+
+    /*
+     * Now fill in the arguments at the beginning of the vector.
+     */
+
+    for (i = 0; i < argp; i++)
+       msgs->msgs[i] = vec[i];
+
+    free(vec);
+}