[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[tyndur-devel] [PATCH 4/5] libc: wordexp.h
+ libc: wordexp.h hinzugefügt (mitsamt teilfunktionaler Implementierung)
Signed-off-by: Kevin Wolf <kevin@xxxxxxxxxx>
---
src/modules/include/wordexp.h | 48 +++++++
src/modules/lib/posix/wordexp.c | 309 ++++++++++++++++++++++++++++++++++++++++
2 files changed, 357 insertions(+)
create mode 100644 src/modules/include/wordexp.h
create mode 100644 src/modules/lib/posix/wordexp.c
diff --git a/src/modules/include/wordexp.h b/src/modules/include/wordexp.h
new file mode 100644
index 0000000..4a8cc7f
--- /dev/null
+++ b/src/modules/include/wordexp.h
@@ -0,0 +1,48 @@
+/*
+ * Copyright (c) 2016 Kevin Wolf
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * ``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 COPYRIGHT HOLDERS OR
+ * CONTRIBUTORS 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.
+ */
+
+#ifndef _WORDEXP_H_
+#define _WORDEXP_H_
+
+#include <stddef.h>
+
+typedef struct {
+ size_t we_wordc;
+ char** we_wordv;
+ size_t we_offs;
+} wordexp_t;
+
+enum {
+ WRDE_BADCHAR = 1,
+ WRDE_BADVAL,
+ WRDE_CMDSUB,
+ WRDE_NOSPACE,
+ WRDE_SYNTAX,
+};
+
+int wordexp(const char* word, wordexp_t* we, int flags);
+void wordfree(wordexp_t* we);
+
+#endif
diff --git a/src/modules/lib/posix/wordexp.c b/src/modules/lib/posix/wordexp.c
new file mode 100644
index 0000000..057b84d
--- /dev/null
+++ b/src/modules/lib/posix/wordexp.c
@@ -0,0 +1,309 @@
+/*
+ * Copyright (c) 2016 Kevin Wolf
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * ``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 COPYRIGHT HOLDERS OR
+ * CONTRIBUTORS 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 <wordexp.h>
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+#include <ctype.h>
+
+static void skip_quotes(char** s, char **out)
+{
+ char* p = *s;
+ enum {
+ UNQUOTED,
+ IN_SINGLE_QUOTE,
+ IN_DOUBE_QUOTE,
+ } state = UNQUOTED;
+
+ while (*p) {
+ switch (*p) {
+ case '"':
+ if (state == UNQUOTED) {
+ state = IN_DOUBE_QUOTE;
+ break;
+ } else if (state == IN_DOUBE_QUOTE) {
+ p++;
+ goto out;
+ }
+ goto normal_char;
+ case '\'':
+ if (state == UNQUOTED) {
+ state = IN_SINGLE_QUOTE;
+ break;
+ } else if (state == IN_SINGLE_QUOTE) {
+ p++;
+ goto out;
+ }
+ goto normal_char;
+ case '\\':
+ if (p[1]) {
+ p++;
+ if (out) {
+ *(*out)++ = *p;
+ }
+ }
+ break;
+ normal_char:
+ default:
+ if (state == UNQUOTED) {
+ goto out;
+ }
+ if (out) {
+ *(*out)++ = *p;
+ }
+ break;
+ }
+
+ p++;
+ }
+
+out:
+ *s = p;
+}
+
+static int name_length(const char* s)
+{
+ const char* start = s;
+
+ if (!*s || !(isalpha(*s) || *s == '_')) {
+ return 0;
+ }
+
+ while (*s && (isalnum(*s) || *s == '_')) {
+ s++;
+ }
+
+ return s - start;
+}
+
+static int buffer_replace(char** s, char** pos, size_t len, const char* value)
+{
+ size_t offset = *pos - *s;
+ size_t old_total_len = strlen(*s) + 1;
+ size_t new_len = strlen(value);
+ size_t new_total_len = old_total_len - len + new_len;
+ char* p = NULL;
+
+ if (len < new_len) {
+ p = realloc(*s, new_total_len);
+ if (p == NULL) {
+ return WRDE_NOSPACE;
+ }
+ memmove(p + offset + new_len,
+ p + offset + len,
+ old_total_len - (offset + len));
+ } else if (len > new_len) {
+ p = *s;
+ memmove(p + offset + new_len,
+ p + offset + len,
+ old_total_len - (offset + len));
+ p = realloc(*s, new_total_len);
+ if (p == NULL) {
+ return WRDE_NOSPACE;
+ }
+ }
+
+ memcpy(p + offset, value, new_len);
+ *s = p;
+ *pos = p + offset + new_len - 1;
+
+ return 0;
+}
+
+static int we_expand_parameter(char** s)
+{
+ char* p;
+ char* name;
+ const char* value;
+ size_t len;
+ int ret;
+
+ for (p = *s; *p; p++) {
+ if (*p == '\'' || *p == '\\') {
+ skip_quotes(&p, NULL);
+ if (*p == '\0') {
+ break;
+ }
+ }
+ if (*p != '$') {
+ continue;
+ }
+
+ len = name_length(p + 1);
+ if (len == 0) {
+ continue;
+ }
+
+ name = strndup(p + 1, len);
+ if (name == NULL) {
+ return WRDE_NOSPACE;
+ }
+
+ value = getenv(name);
+ if (value == NULL) {
+ value = "";
+ }
+
+ free(name);
+
+ ret = buffer_replace(s, &p, len + 1, value);
+ if (ret != 0) {
+ return ret;
+ }
+ }
+
+ return 0;
+}
+
+static int we_split_fields(char** s, wordexp_t* we)
+{
+ const char* ifs;
+ char* p;
+ int i;
+
+ if (**s == '\0') {
+ free(*s);
+ we->we_wordc = 0;
+ return 0;
+ }
+ we->we_wordc = 1;
+
+ ifs = getenv("IFS");
+ if (ifs == NULL) {
+ ifs = " \n\t";
+ }
+
+ for (p = *s; *p; p++) {
+ skip_quotes(&p, NULL);
+ if (*p == '\0') {
+ break;
+ }
+ if (strchr(ifs, *p)) {
+ we->we_wordc++;
+ }
+ }
+
+ we->we_wordv = calloc(we->we_wordc, sizeof(char*));
+ if (we->we_wordv == NULL) {
+ return WRDE_NOSPACE;
+ }
+
+ we->we_wordv[0] = *s;
+ for (p = *s, i = 0; *p; p++) {
+ skip_quotes(&p, NULL);
+ if (*p == '\0') {
+ break;
+ }
+ if (strchr(ifs, *p)) {
+ assert(i < we->we_wordc);
+ we->we_wordv[++i] = p + 1;
+ *p = '\0';
+ }
+ }
+
+ for (i = 0; i < we->we_wordc; i++) {
+ p = strdup(we->we_wordv[i]);
+ if (p == NULL) {
+ return WRDE_NOSPACE;
+ }
+ we->we_wordv[i] = p;
+ }
+
+ return 0;
+}
+
+static void we_str_remove_quotes(char** s)
+{
+ char *src;
+ char *out;
+
+ for (src = *s, out = *s; *src; src++, out++) {
+ skip_quotes(&src, &out);
+ if (*src == '\0') {
+ break;
+ }
+ if (src != out) {
+ *out = *src;
+ }
+ }
+
+ if (src != out) {
+ size_t len;
+ *out++ = '\0';
+ len = out - *s;
+ out = realloc(*s, len);
+ if (out != NULL) {
+ *s = out;
+ }
+ }
+}
+
+
+static void we_remove_quotes(wordexp_t* we)
+{
+ int i;
+
+ for (i = 0; i < we->we_wordc; i++) {
+ we_str_remove_quotes(&we->we_wordv[i]);
+ }
+}
+
+int wordexp(const char* word, wordexp_t* we, int flags)
+{
+ char *s;
+ int ret;
+
+ s = strdup(word);
+ if (s == NULL) {
+ return WRDE_NOSPACE;
+ }
+
+ ret = we_expand_parameter(&s);
+ if (ret != 0) {
+ free(s);
+ return ret;
+ }
+
+ ret = we_split_fields(&s, we);
+ if (ret != 0) {
+ free(s);
+ return ret;
+ }
+
+ we_remove_quotes(we);
+
+ return 0;
+}
+
+void wordfree(wordexp_t* we)
+{
+ int i;
+
+ for (i = 0; i < we->we_wordc; i++) {
+ free(we->we_wordv[i]);
+ }
+ free(we->we_wordv);
+}
--
2.1.4