diff options
author | Andrew Gregory <andrew.gregory.8@gmail.com> | 2019-06-09 18:54:02 +0200 |
---|---|---|
committer | Andrew Gregory <andrew.gregory.8@gmail.com> | 2019-10-12 03:49:38 +0200 |
commit | a2c4ad46751e4dcb85a739437d9331bf9282d9be (patch) | |
tree | bab6c048fb7eb2ffb37e4ba057a176d85990d650 | |
parent | a897599fa54813ea2a225271eacd9fb6e1a6762e (diff) | |
download | pacman-a2c4ad46751e4dcb85a739437d9331bf9282d9be.tar.gz pacman-a2c4ad46751e4dcb85a739437d9331bf9282d9be.tar.xz |
move wordsplit into common for sharing
Signed-off-by: Andrew Gregory <andrew.gregory.8@gmail.com>
-rw-r--r-- | lib/libalpm/hook.c | 119 | ||||
-rw-r--r-- | src/common/util-common.c | 112 | ||||
-rw-r--r-- | src/common/util-common.h | 3 |
3 files changed, 118 insertions, 116 deletions
diff --git a/lib/libalpm/hook.c b/lib/libalpm/hook.c index 6143ea0f..9d1aa215 100644 --- a/lib/libalpm/hook.c +++ b/lib/libalpm/hook.c @@ -17,7 +17,6 @@ * along with this program. If not, see <http://www.gnu.org/licenses/>. */ -#include <ctype.h> #include <dirent.h> #include <errno.h> #include <limits.h> @@ -71,23 +70,12 @@ static void _alpm_trigger_free(struct _alpm_trigger_t *trigger) } } -static void _alpm_wordsplit_free(char **ws) -{ - if(ws) { - char **c; - for(c = ws; *c; c++) { - free(*c); - } - free(ws); - } -} - static void _alpm_hook_free(struct _alpm_hook_t *hook) { if(hook) { free(hook->name); free(hook->desc); - _alpm_wordsplit_free(hook->cmd); + wordsplit_free(hook->cmd); alpm_list_free_inner(hook->triggers, (alpm_list_fn_free) _alpm_trigger_free); alpm_list_free(hook->triggers); alpm_list_free(hook->matches); @@ -158,107 +146,6 @@ static int _alpm_hook_validate(alpm_handle_t *handle, return ret; } -static char **_alpm_wordsplit(char *str) -{ - char *c = str, *end; - char **out = NULL, **outsave; - size_t count = 0; - - if(str == NULL) { - errno = EINVAL; - return NULL; - } - - for(c = str; isspace(*c); c++); - while(*c) { - size_t wordlen = 0; - - /* extend our array */ - outsave = out; - if((out = realloc(out, (count + 1) * sizeof(char*))) == NULL) { - out = outsave; - goto error; - } - - /* calculate word length and check for unbalanced quotes */ - for(end = c; *end && !isspace(*end); end++) { - if(*end == '\'' || *end == '"') { - char quote = *end; - while(*(++end) && *end != quote) { - if(*end == '\\' && *(end + 1) == quote) { - end++; - } - wordlen++; - } - if(*end != quote) { - errno = EINVAL; - goto error; - } - } else { - if(*end == '\\' && (end[1] == '\'' || end[1] == '"')) { - end++; /* skip the '\\' */ - } - wordlen++; - } - } - - if(wordlen == (size_t) (end - c)) { - /* no internal quotes or escapes, copy it the easy way */ - if((out[count++] = strndup(c, wordlen)) == NULL) { - goto error; - } - } else { - /* manually copy to remove quotes and escapes */ - char *dest = out[count++] = malloc(wordlen + 1); - if(dest == NULL) { goto error; } - while(c < end) { - if(*c == '\'' || *c == '"') { - char quote = *c; - /* we know there must be a matching end quote, - * no need to check for '\0' */ - for(c++; *c != quote; c++) { - if(*c == '\\' && *(c + 1) == quote) { - c++; - } - *(dest++) = *c; - } - c++; - } else { - if(*c == '\\' && (c[1] == '\'' || c[1] == '"')) { - c++; /* skip the '\\' */ - } - *(dest++) = *(c++); - } - } - *dest = '\0'; - } - - if(*end == '\0') { - break; - } else { - for(c = end + 1; isspace(*c); c++); - } - } - - outsave = out; - if((out = realloc(out, (count + 1) * sizeof(char*))) == NULL) { - out = outsave; - goto error; - } - - out[count++] = NULL; - - return out; - -error: - /* can't use wordsplit_free here because NULL has not been appended */ - while(count) { - free(out[--count]); - } - free(out); - return NULL; -} - static int _alpm_hook_parse_cb(const char *file, int line, const char *section, char *key, char *value, void *data) { @@ -347,9 +234,9 @@ static int _alpm_hook_parse_cb(const char *file, int line, } else if(strcmp(key, "Exec") == 0) { if(hook->cmd != NULL) { warning(_("hook %s line %d: overwriting previous definition of %s\n"), file, line, "Exec"); - _alpm_wordsplit_free(hook->cmd); + wordsplit_free(hook->cmd); } - if((hook->cmd = _alpm_wordsplit(value)) == NULL) { + if((hook->cmd = wordsplit(value)) == NULL) { if(errno == EINVAL) { error(_("hook %s line %d: invalid value %s\n"), file, line, value); } else { diff --git a/src/common/util-common.c b/src/common/util-common.c index 3aa0eac9..fd91ecec 100644 --- a/src/common/util-common.c +++ b/src/common/util-common.c @@ -197,3 +197,115 @@ char *strndup(const char *s, size_t n) return (char *)memcpy(new, s, len); } #endif + +void wordsplit_free(char **ws) +{ + if(ws) { + char **c; + for(c = ws; *c; c++) { + free(*c); + } + free(ws); + } +} + +char **wordsplit(const char *str) +{ + const char *c = str, *end; + char **out = NULL, **outsave; + size_t count = 0; + + if(str == NULL) { + errno = EINVAL; + return NULL; + } + + for(c = str; isspace(*c); c++); + while(*c) { + size_t wordlen = 0; + + /* extend our array */ + outsave = out; + if((out = realloc(out, (count + 1) * sizeof(char*))) == NULL) { + out = outsave; + goto error; + } + + /* calculate word length and check for unbalanced quotes */ + for(end = c; *end && !isspace(*end); end++) { + if(*end == '\'' || *end == '"') { + char quote = *end; + while(*(++end) && *end != quote) { + if(*end == '\\' && *(end + 1) == quote) { + end++; + } + wordlen++; + } + if(*end != quote) { + errno = EINVAL; + goto error; + } + } else { + if(*end == '\\' && (end[1] == '\'' || end[1] == '"')) { + end++; /* skip the '\\' */ + } + wordlen++; + } + } + + if(wordlen == (size_t) (end - c)) { + /* no internal quotes or escapes, copy it the easy way */ + if((out[count++] = strndup(c, wordlen)) == NULL) { + goto error; + } + } else { + /* manually copy to remove quotes and escapes */ + char *dest = out[count++] = malloc(wordlen + 1); + if(dest == NULL) { goto error; } + while(c < end) { + if(*c == '\'' || *c == '"') { + char quote = *c; + /* we know there must be a matching end quote, + * no need to check for '\0' */ + for(c++; *c != quote; c++) { + if(*c == '\\' && *(c + 1) == quote) { + c++; + } + *(dest++) = *c; + } + c++; + } else { + if(*c == '\\' && (c[1] == '\'' || c[1] == '"')) { + c++; /* skip the '\\' */ + } + *(dest++) = *(c++); + } + } + *dest = '\0'; + } + + if(*end == '\0') { + break; + } else { + for(c = end + 1; isspace(*c); c++); + } + } + + outsave = out; + if((out = realloc(out, (count + 1) * sizeof(char*))) == NULL) { + out = outsave; + goto error; + } + + out[count++] = NULL; + + return out; + +error: + /* can't use wordsplit_free here because NULL has not been appended */ + while(count) { + free(out[--count]); + } + free(out); + return NULL; +} diff --git a/src/common/util-common.h b/src/common/util-common.h index 3434e1eb..7ec588cc 100644 --- a/src/common/util-common.h +++ b/src/common/util-common.h @@ -30,6 +30,9 @@ int llstat(char *path, struct stat *buf); char *safe_fgets(char *s, int size, FILE *stream); +void wordsplit_free(char **ws); +char **wordsplit(const char *str); + size_t strtrim(char *str); #ifndef HAVE_STRNDUP |