From c74b749c65c33cd63de498f3484187fb2af2a195 Mon Sep 17 00:00:00 2001 From: William Pitcock Date: Thu, 3 May 2012 18:59:14 +0000 Subject: [PATCH] Add code for spliting strings into argc/argv using shell quoting rules. --- Makefile | 2 +- argvsplit.c | 110 ++++++++++++++++++++++++++++++++++++++++++++++++++++ pkg.h | 3 ++ 3 files changed, 114 insertions(+), 1 deletion(-) create mode 100644 argvsplit.c diff --git a/Makefile b/Makefile index fe628e0..8ac6467 100644 --- a/Makefile +++ b/Makefile @@ -1,5 +1,5 @@ PROG = pkgconf${PROG_SUFFIX} -SRCS = main.c parse.c pkg.c bsdstubs.c getopt_long.c +SRCS = main.c parse.c pkg.c bsdstubs.c getopt_long.c argvsplit.c include buildsys.mk diff --git a/argvsplit.c b/argvsplit.c new file mode 100644 index 0000000..c99b27a --- /dev/null +++ b/argvsplit.c @@ -0,0 +1,110 @@ +/* + * argvsplit.c + * argv_split() routine + * + * Copyright (c) 2012 William Pitcock . + * + * Permission to use, copy, modify, and/or 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. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include "config.h" +#include "pkg.h" + +int argv_split(const char *src, int *argc, char ***argv) +{ + char *buf = malloc(strlen(src) + 1); + const char *src_iter; + char *dst_iter; + int argc_count = 0; + int argv_size = 5; + char quote = 0; + + src_iter = src; + dst_iter = buf; + + bzero(buf, strlen(src) + 1); + + *argv = calloc(sizeof (void *), argv_size); + (*argv)[argc_count] = dst_iter; + + while (*src_iter) + { + if (quote == *src_iter) + quote = 0; + else if (quote) + { + if (*src_iter == '\\') + { + src_iter++; + if (!*src_iter) + { + free(*argv); + free(buf); + return -1; + } + + if (*src_iter != quote) + *dst_iter++ = '\\'; + } + *dst_iter++ = *src_iter; + } + else if (isspace(*src_iter)) + { + if (*(src_iter - 2) != '-' && (*argv)[argc_count] != NULL) + { + argc_count++, dst_iter++; + + if (argc_count == argv_size) + { + argv_size += 5; + *argv = realloc(*argv, sizeof(void *) * argv_size); + } + + (*argv)[argc_count] = dst_iter; + } + } + else switch(*src_iter) + { + case '"': + case '\'': + quote = *src_iter; + break; + + case '\\': + src_iter++; + + if (!*src_iter) + { + free(argv); + free(buf); + return -1; + } + default: + *dst_iter++ = *src_iter; + break; + } + + src_iter++; + } + + if (strlen((*argv)[argc_count])) { + argc_count++; + } + + *argc = argc_count; + return 0; +} diff --git a/pkg.h b/pkg.h index 1564df4..a83950e 100644 --- a/pkg.h +++ b/pkg.h @@ -121,4 +121,7 @@ char *tuple_find(pkg_tuple_t *head, const char *key); pkg_dependency_t *parse_deplist(pkg_t *pkg, const char *depends); pkg_dependency_t *pkg_dependency_append(pkg_dependency_t *head, pkg_dependency_t *tail); +/* argvsplit.c */ +int argv_split(const char *src, int *argc, char ***argv); + #endif