commit 20967f0e8a0e974e401bf1d64bb12f13d6435a7a
parent 39cd852a98148cf21f1cbc448195137e88285b4a
Author: conrad <conrad@9c49b5d1-7df3-0310-bce2-b7278e68f44c>
Date: Tue, 12 Feb 2008 04:37:54 +0000
Expand the argument array to handle combined single-letter arguments, eg. so
"xsel -ao" is equivalent to "xsel -a -o".
Patch by Christopher Wellons, adapted to preserve argument order and avoid
potential memory leaks with multiple groups of arguments.
git-svn-id: http://svn.kfish.org/xsel/trunk@208 9c49b5d1-7df3-0310-bce2-b7278e68f44c
Diffstat:
M | xsel.c | | | 81 | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
1 file changed, 81 insertions(+), 0 deletions(-)
diff --git a/xsel.c b/xsel.c
@@ -90,6 +90,9 @@ static int current_alloc = 0;
static long timeout = 0;
static struct itimerval timer;
+static int saved_argc;
+static char ** saved_argv;
+
/*
* usage ()
*
@@ -1801,6 +1804,81 @@ exchange_selections (void)
set_selection_pair__daemon (text2, text1);
}
+/*
+ * free_saved_argv ()
+ *
+ * atexit function for freeing argv, after it has been relocated to the
+ * heap.
+ */
+static void
+free_saved_argv (void)
+{
+ int i;
+
+ for (i=0; i < saved_argc; i++) {
+ free (saved_argv[i]);
+ }
+ free (saved_argv);
+}
+
+/*
+ * expand_argv (&argc, &argv)
+ *
+ * Explodes single letter options so that the argument parser can see
+ * all of them. Relocates argv and all arguments to the heap.
+ */
+static void
+expand_argv(int * argc, char **argv[])
+{
+ int i, new_i, arglen, new_argc = *argc;
+ char ** new_argv;
+ char * arg;
+
+ /* Calculate new argc */
+ for (i = 0; i < *argc; i++) {
+ arglen = strlen((*argv)[i]);
+ /* An option we need to expand? */
+ if ((arglen > 2) && (*argv)[i][0] == '-' && (*argv)[i][1] != '-')
+ new_argc += arglen-2;
+ }
+
+ /* Allocate new_argv */
+ new_argv = xs_malloc (new_argc * sizeof(char *));
+
+ /* Copy args into new argv */
+ for (i = 0, new_i = 0; i < *argc; i++) {
+ arglen = strlen((*argv)[i]);
+
+ /* An option we need to expand? */
+ if ((arglen > 2)
+ && (*argv)[i][0] == '-' && (*argv)[i][1] != '-') {
+ /* Make each letter a new argument. */
+
+ char * c = ((*argv)[i] + 1);
+
+ while (*c != '\0') {
+ arg = xs_malloc(sizeof(char) * 3);
+ arg[0] = '-';
+ arg[1] = *c;
+ arg[2] = '\0';
+ new_argv[new_i++] = arg;
+ c++;
+ }
+ } else {
+ /* Simply copy the argument pointer to new_argv */
+ new_argv[new_i++] = strdup ((*argv)[i]);
+ }
+ }
+
+ /* Set the expected return values */
+ *argc = new_argc;
+ *argv = new_argv;
+
+ /* Save the new argc, argv values and free them on exit */
+ saved_argc = new_argc;
+ saved_argv = new_argv;
+ atexit (free_saved_argv);
+}
/*
* main (argc, argv)
@@ -1855,6 +1933,9 @@ main(int argc, char *argv[])
#define OPT(s) (strcmp (argv[i], (s)) == 0)
+ /* Expand argv array before parsing to uncombine arguments. */
+ expand_argv(&argc, &argv);
+
/* Parse options; modify behaviour according to user-specified options */
for (i=1; i < argc; i++) {
if (OPT("--help") || OPT("-h")) {