Radish alpha
H
rad:z3QDZAW2FAfuLvihrhiyDC9fAD8G9
HardenedBSD Package Manager
Radicle
Git
Use tokeniser from libedit to convert a string to argv
Baptiste Daroussin committed 12 years ago
commit 5d4df0c235fff3e65c67d3d4b139c833a0b88126
parent 53a0267
6 files changed +23 -334
modified external/Makefile
@@ -1,4 +1,4 @@
-
SUBDIR=	sqlite str2argv
+
SUBDIR=	sqlite

.if !exists(/usr/include/bsdyml.h)
SUBDIR+= libyaml
deleted external/str2argv/Makefile
@@ -1,6 +0,0 @@
-
LIB=	str2argv
-
SRCS=	str2argv.c
-
WARNS=	6
-
INTERNALLIB=
-

-
.include <bsd.lib.mk>
deleted external/str2argv/str2argv.c
@@ -1,257 +0,0 @@
-
/*
-
 * Copyright (c) 2010, 2011, 2012 Ryan Flannery <ryan.flannery@gmail.com>
-
 *
-
 * Permission to use, copy, modify, and distribute this software for any
-
 * purpose with or without fee is hereby granted, provided that the above
-
 * copyright notice and this permission notice appear in all copies.
-
 *
-
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
-
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
-
 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
-
 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
-
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
-
 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
-
 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
-
 */
-

-
#include "str2argv.h"
-

-
/* initialize empty argc/argv struct */
-
static void
-
argv_init(int *argc, char ***argv)
-
{
-
   if ((*argv = calloc(ARGV_MAX_ENTRIES, sizeof(char*))) == NULL)
-
      err(1, "argv_init: argv calloc fail");
-

-
   if (((*argv)[0] = calloc(ARGV_MAX_TOKEN_LEN, sizeof(char))) == NULL)
-
      err(1, "argv_init: argv[i] calloc fail");
-

-
   bzero((*argv)[0], ARGV_MAX_TOKEN_LEN * sizeof(char));
-
   *argc = 0;
-
}
-

-
/* free all memory in an arc/argv */
-
void
-
argv_free(int *argc, char ***argv)
-
{
-
   int i;
-

-
   for (i = 0; i <= *argc; i++)
-
      free((*argv)[i]);
-

-
   free(*argv);
-
   *argc = 0;
-
}
-

-
/* add a character to the end of the current entry in an argc/argv */
-
static void
-
argv_addch(int argc, char **argv, int c)
-
{
-
   int n;
-

-
   n = strlen(argv[argc]);
-
   if (n == ARGV_MAX_TOKEN_LEN - 1)
-
      errx(1, "argv_addch: reached max token length (%d)", ARGV_MAX_TOKEN_LEN);
-

-
   argv[argc][n] = c;
-
}
-

-
/* complete the current entry in the argc/argv and setup the next one */
-
static void
-
argv_finish_token(int *argc, char ***argv)
-
{
-
   if (*argc == ARGV_MAX_ENTRIES - 1)
-
      errx(1, "argv_finish_token: reached max argv entries(%d)", ARGV_MAX_ENTRIES);
-

-
   if (strlen((*argv)[*argc]) == 0)
-
      return;
-

-
   *argc = *argc + 1;
-
   if (((*argv)[*argc] = calloc(ARGV_MAX_TOKEN_LEN, sizeof(char))) == NULL)
-
      err(1, "argv_finish_token: failed to calloc argv[i]");
-

-
   bzero((*argv)[*argc], ARGV_MAX_TOKEN_LEN * sizeof(char));
-
}
-

-
/*
-
 * Main parser used for converting a string (str) to an argc/argv style
-
 * parameter list.  This handles escape sequences and quoting.  Possibly
-
 * correctly.  :D
-
 * The argc/argv parameters passed are over-written.  After they have been
-
 * built by this function, the caller should use argv_free() on them to
-
 * free() all associated memory.
-
 * If the parsing goes correctly, 0 is returned.  Otherwise, 1 is returned
-
 * and the errmsg parameter is set to some appropriate error message and
-
 * both argc/argv are set to 0/NULL.
-
 */
-
int
-
str2argv(char *str, int *argc, char ***argv, const char **errmsg)
-
{
-
   bool in_token;
-
   bool in_container;
-
   bool escaped;
-
   char container_start;
-
   char c;
-
   int  len;
-
   int  i;
-

-
   const char *ERRORS[2] = {
-
      "Unmatched quotes",
-
      "Unused/Dangling escape sequence"
-
   };
-
   *errmsg = NULL;
-

-
   container_start = 0;
-
   in_token = false;
-
   in_container = false;
-
   escaped = false;
-

-
   len = strlen(str);
-

-
   argv_init(argc, argv);
-
   for (i = 0; i < len; i++) {
-
      c = str[i];
-

-
      switch (c) {
-
         /* handle whitespace */
-
         case ' ':
-
         case '\t':
-
         case '\n':
-
            if (!in_token)
-
               continue;
-

-
            if (in_container) {
-
               argv_addch(*argc, *argv, c);
-
               continue;
-
            }
-

-
            if (escaped) {
-
               escaped = false;
-
               argv_addch(*argc, *argv, c);
-
               continue;
-
            }
-

-
            /* if reached here, we're at end of token */
-
            in_token = false;
-
            argv_finish_token(argc, argv);
-
            break;
-

-
         /* handle quotes */
-
         case '\'':
-
         case '\"':
-

-
            if (escaped) {
-
               argv_addch(*argc, *argv, c);
-
               escaped = false;
-
               continue;
-
            }
-

-
            if (!in_token) {
-
               in_token = true;
-
               in_container = true;
-
               container_start = c;
-
               continue;
-
            }
-

-
            if (in_token && !in_container) {
-
               in_container = true;
-
               container_start = c;
-
               continue;
-
            }
-

-
            if (in_container) {
-
               if (c == container_start) {
-
                  in_container = false;
-
                  in_token = false;
-
                  argv_finish_token(argc, argv);
-
                  continue;
-
               } else {
-
                  argv_addch(*argc, *argv, c);
-
                  continue;
-
               }
-
            }
-

-
            *errmsg = ERRORS[0];
-
            argv_free(argc, argv);
-
            return 1;
-

-
         case '\\':
-
            if (in_container && str[i+1] != container_start) {
-
               argv_addch(*argc, *argv, c);
-
               continue;
-
            }
-

-
            if (escaped) {
-
               escaped = false;
-
               argv_addch(*argc, *argv, c);
-
               continue;
-
            }
-

-
            escaped = true;
-
            break;
-

-
         default:
-
            if (!in_token)
-
               in_token = true;
-

-
            if (escaped)
-
               escaped = false;
-

-
            argv_addch(*argc, *argv, c);
-
      }
-
   }
-
   argv_finish_token(argc, argv);
-

-
   if (in_container) {
-
      argv_free(argc, argv);
-
      *errmsg = ERRORS[0];
-
      return 1;
-
   }
-

-
   if (escaped) {
-
      argv_free(argc, argv);
-
      *errmsg = ERRORS[1];
-
      return 1;
-
   }
-

-
   (*argv)[*argc] = NULL;/*XXX*/
-

-
   return 0;
-
}
-

-
char *
-
argv2str(int argc, char *argv[])
-
{
-
   char *result;
-
   int   len;
-
   int   off;
-
   int   i;
-

-
   /* handle empty case */
-
   if (0 >= argc)
-
      return NULL;
-

-
   /* determine length of resulting string */
-
   len = 0;
-
   for (i = 0; i < argc; i++) {
-
      len += strlen(argv[i]) + 1;
-
      if (strstr(argv[i], " ") != NULL)
-
         len += 2;
-
   }
-

-
   /* allocate result */
-
   if ((result = calloc(len, sizeof(char))) == NULL)
-
      err(1, "argv2str: calloc failed");
-
   bzero(result, len);
-

-
   /* build result */
-
   off = 0;
-
   for (i = 0; i < argc; i++) {
-
      if (strstr(argv[i], " ") == NULL)
-
         off += snprintf(result + off, len, "%s ", argv[i]);
-
      else
-
         off += snprintf(result + off, len, "\'%s\' ", argv[i]);
-
   }
-

-
   return result;
-
}
deleted external/str2argv/str2argv.h
@@ -1,55 +0,0 @@
-
/*
-
 * Copyright (c) 2010, 2011 Ryan Flannery <ryan.flannery@gmail.com>
-
 *
-
 * Permission to use, copy, modify, and distribute this software for any
-
 * purpose with or without fee is hereby granted, provided that the above
-
 * copyright notice and this permission notice appear in all copies.
-
 *
-
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
-
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
-
 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
-
 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
-
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
-
 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
-
 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
-
 */
-

-
#ifndef STR2ARGV_H
-
#define STR2ARGV_H
-

-
#include <err.h>
-
#include <stdbool.h>
-
#include <stdio.h>
-
#include <stdlib.h>
-
#include <string.h>
-

-

-
/* hard limits on the size of an argv and each entry/token w/in an argv */
-
#define ARGV_MAX_ENTRIES    255
-
#define ARGV_MAX_TOKEN_LEN  255
-

-
/*
-
 * Given a string (str), it parses it taking into account escape sequence (\),
-
 * quoting, etc., and builds an argc/argv style set of parameters that are
-
 * suitable for passing to any of the cmd_* or ecmd_* functions.
-
 *
-
 * This has been tricky for me.  It no doubt has bugs.
-
 * str2argv.c contains a small driver program that can be used for testing.
-
 * The Makefile contains the necessary build target "test_str2argv"
-
 */
-
int str2argv(char *str, int *argc, char ***argv, const char **errmsg);
-

-
/*
-
 * After the above function is used to build an argc/argv set of parameters,
-
 * this function should be used to free() all of the allocated memory.
-
 */
-
void argv_free(int *argc, char ***argv);
-

-
/*
-
 * This is used to un-tokenize an argv array.  Given argc/argv, this
-
 * constructs a string containing all of the tokens in order, with a single
-
 * space between each.  Tokens with multiple words are quoted.
-
 */
-
char *argv2str(int argc, char *argv[]);
-

-
#endif
modified pkg/Makefile
@@ -56,11 +56,9 @@ DEBUG_FLAGS+= -pg
.endif

CFLAGS+=	-I../libpkg \
-
		-I${.CURDIR}/../external/uthash \
-
		-I${.CURDIR}/../external/str2argv
+
		-I${.CURDIR}/../external/uthash
LDADD+=		-L../libpkg \
-
		-L../external/str2argv \
-
		-lstr2argv \
+
		-ledit \
		-lpkg \
		-larchive \
		-lutil \
modified pkg/main.c
@@ -31,9 +31,11 @@
#include <sys/jail.h>
#include <sys/stat.h>
#include <sys/queue.h>
+
#include <sys/sbuf.h>

#include <assert.h>
#include <err.h>
+
#include <histedit.h>
#include <inttypes.h>
#include <stdio.h>
#include <stdlib.h>
@@ -43,7 +45,6 @@
#ifndef NO_LIBJAIL
#include <jail.h>
#endif
-
#include <str2argv.h>

#include <pkg.h>

@@ -510,10 +511,12 @@ main(int argc, char **argv)
	const char *conffile = NULL;
	const char *reposdir = NULL;
	struct pkg_config_kv *alias = NULL;
-
	const char *alias_value, *errmsg;
+
	const char *alias_value;
	char **newargv;
	int newargc;
-
	char *oldcmd, *newcmd;
+
	Tokenizer *t = NULL;
+
	struct sbuf *newcmd;
+
	int j;

	/* Set stdout unbuffered */
	setvbuf(stdout, NULL, _IONBF, 0);
@@ -648,13 +651,19 @@ main(int argc, char **argv)
				continue;
			argv++;
			argc--;
-
			oldcmd = argv2str(argc, argv);
-
			asprintf(&newcmd, "%s %s", alias_value, oldcmd);
-
			free(oldcmd);
-
			if (str2argv(newcmd, &newargc, &newargv, &errmsg) != 0)
-
				errx(EX_CONFIG, "Invalid alias: %s", errmsg);
-
			free(newcmd);
-

+
			newcmd = sbuf_new_auto();
+
			sbuf_cat(newcmd, alias_value);
+
			for (j = 0; j < argc; j++) {
+
				if (strspn(argv[j], " \t\n") > 0)
+
					sbuf_printf(newcmd, " \"%s\" ", argv[j]);
+
				else
+
					sbuf_printf(newcmd, " %s ", argv[j]);
+
			}
+
			sbuf_done(newcmd);
+
			t = tok_init(NULL);
+
			if (tok_str(t, sbuf_data(newcmd), &newargc, (const char ***)&newargv) != 0)
+
				errx(EX_CONFIG, "Invalid alias: %s", alias_value);
+
			sbuf_delete(newcmd);
			break;
		}
	}
@@ -713,7 +722,7 @@ main(int argc, char **argv)
	}

	if (alias != NULL)
-
		argv_free(&newargc, &newargv);
+
		tok_end(t);

	if (ret == EX_OK && newpkgversion)
		execvp(getprogname(), cmdargv);