X-Git-Url: https://diplodocus.org/git/nmh/blobdiff_plain/c703902741e0f7ce55f87e48ef0d00901195f1bc..ac1e36dc09f4092f4e9fa9ed66003bb585f790ed:/sbr/arglist.c diff --git a/sbr/arglist.c b/sbr/arglist.c index 1f85b7b2..cd88b86b 100644 --- a/sbr/arglist.c +++ b/sbr/arglist.c @@ -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 @@ -25,10 +23,10 @@ * * - 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(char **) * (MAXARGS + 5))); /* * The simple case - no spaces or shell metacharacters @@ -61,33 +59,33 @@ 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); @@ -110,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) @@ -123,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; + + mh_xfree(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); +}