diff options
-rw-r--r-- | include/str.h | 27 | ||||
-rw-r--r-- | include/strlist.h | 8 | ||||
-rw-r--r-- | include/system.h | 2 | ||||
-rw-r--r-- | include/template.h | 2 | ||||
-rw-r--r-- | src/docker.c | 4 | ||||
-rw-r--r-- | src/str.c | 150 | ||||
-rw-r--r-- | src/strlist.c | 232 | ||||
-rw-r--r-- | src/system.c | 54 | ||||
-rw-r--r-- | src/template.c | 54 | ||||
-rw-r--r-- | src/utils.c | 34 |
10 files changed, 362 insertions, 205 deletions
diff --git a/include/str.h b/include/str.h index 8018cc0..895b8cc 100644 --- a/include/str.h +++ b/include/str.h @@ -51,33 +51,6 @@ int endswith(const char *sptr, const char *pattern); void strchrdel(char *sptr, const char *chars); /** - * Find the integer offset of the first occurrence of `ch` in `sptr` - * - * ~~~{.c} - * char buffer[255]; - * char string[] = "abc=123"; - * long int separator_offset = strchroff(string, '='); - * for (long int i = 0; i < separator_offset); i++) { - * buffer[i] = string[i]; - * } - * ~~~ - * - * @param sptr string to scan - * @param ch character to find - * @return offset to character in string, or 0 on failure - */ -long int strchroff(const char *sptr, int ch); - -/** - * This function scans `sptr` from right to left removing any matches to `suffix` - * from the string. - * - * @param sptr string to be modified - * @param suffix string to be removed from `sptr` - */ -void strdelsuffix(char *sptr, const char *suffix); - -/** * Split a string by every delimiter in `delim` string. * * Callee should free memory using `GENERIC_ARRAY_FREE()` diff --git a/include/strlist.h b/include/strlist.h index 2d3c3cf..3f35e23 100644 --- a/include/strlist.h +++ b/include/strlist.h @@ -44,4 +44,12 @@ struct StrList *strlist_copy(struct StrList *pStrList); int strlist_cmp(struct StrList *a, struct StrList *b); void strlist_free(struct StrList **pStrList); +#define STRLIST_E_SUCCESS 0 +#define STRLIST_E_OUT_OF_RANGE 1 +#define STRLIST_E_INVALID_VALUE 2 +#define STRLIST_E_UNKNOWN 3 +extern int strlist_errno; +const char *strlist_get_error(int flag); + + #endif //OMC_STRLIST_H diff --git a/include/system.h b/include/system.h index 7428355..94d5a36 100644 --- a/include/system.h +++ b/include/system.h @@ -14,6 +14,8 @@ #include <sys/wait.h> #include <sys/stat.h> +#define OMC_SHELL_SAFE_RESTRICT ";&|()" + struct Process { // Write stdout stream to file char f_stdout[PATH_MAX]; diff --git a/include/template.h b/include/template.h index a242a08..362eb3d 100644 --- a/include/template.h +++ b/include/template.h @@ -42,7 +42,7 @@ int tpl_render_to_file(char *str, const char *filename); struct tplfunc_frame *tpl_getfunc(char *key); struct tplfunc_frame; -typedef int tplfunc(struct tplfunc_frame *frame); +typedef int tplfunc(struct tplfunc_frame *frame, void *result); struct tplfunc_frame { char *key; tplfunc *func; diff --git a/src/docker.c b/src/docker.c index f8c9c11..308fbc7 100644 --- a/src/docker.c +++ b/src/docker.c @@ -28,7 +28,7 @@ int docker_script(const char *image, char *data, unsigned flags) { char buffer[OMC_BUFSIZ]; memset(cmd, 0, sizeof(cmd)); - snprintf(cmd, sizeof(cmd) - 1, "docker run --rm -i %s /bin/bash -", image); + snprintf(cmd, sizeof(cmd) - 1, "docker run --rm -i %s /bin/sh -", image); outfile = popen(cmd, "w"); if (!outfile) { @@ -103,7 +103,7 @@ static int docker_exists() { return false; } -char *docker_ident() { +static char *docker_ident() { FILE *fp = NULL; char *tempfile = NULL; char line[PATH_MAX]; @@ -26,7 +26,6 @@ int startswith(const char *sptr, const char *pattern) { return 1; } - int endswith(const char *sptr, const char *pattern) { if (!sptr || !pattern) { return -1; @@ -61,64 +60,10 @@ void strchrdel(char *sptr, const char *chars) { return; } - while (*sptr != '\0') { - for (int i = 0; chars[i] != '\0'; i++) { - if (*sptr == chars[i]) { - memmove(sptr, sptr + 1, strlen(sptr)); - } - } - sptr++; - } -} - - -long int strchroff(const char *sptr, int ch) { - char *orig = strdup(sptr); - char *tmp = orig; - long int result = 0; - - int found = 0; - size_t i = 0; - - while (*tmp != '\0') { - if (*tmp == ch) { - found = 1; - break; - } - tmp++; - i++; - } - - if (found == 0 && i == strlen(sptr)) { - return -1; - } - - result = tmp - orig; - guard_free(orig); - - return result; -} - -void strdelsuffix(char *sptr, const char *suffix) { - if (!sptr || !suffix) { - return; - } - size_t sptr_len = strlen(sptr); - size_t suffix_len = strlen(suffix); - intptr_t target_offset = sptr_len - suffix_len; - - // Prevent access to memory below input string - if (target_offset < 0) { - return; - } - - // Create a pointer to - char *target = sptr + target_offset; - if (!strcmp(target, suffix)) { - // Purge the suffix - memset(target, '\0', suffix_len); - // Recursive call continues removing suffix until it is gone - strip(sptr); + for (size_t i = 0; i < strlen(chars); i++) { + char ch[2] = {0}; + strncpy(ch, &chars[i], 1); + replace_text(sptr, ch, "", 0); } } @@ -141,7 +86,7 @@ char** split(char *_sptr, const char* delim, size_t max) if (max && i > max) { break; } - split_alloc = num_chars(sptr, delim[i]); + split_alloc += num_chars(sptr, delim[i]); } // Preallocate enough records based on the number of delimiters @@ -158,27 +103,35 @@ char** split(char *_sptr, const char* delim, size_t max) } // Separate the string into individual parts and store them in the result array - int i = 0; - size_t x = max; char *token = NULL; char *sptr_tmp = sptr; - while((token = strsep(&sptr_tmp, delim)) != NULL) { - result[i] = calloc(OMC_BUFSIZ, sizeof(char)); - if (x < max) { - strcat(result[i], strstr(orig, delim) + 1); + size_t pos = 0; + size_t i; + for (i = 0; (token = strsep(&sptr_tmp, delim)) != NULL; i++) { + // When max is zero, record all tokens + if (max > 0 && i == max) { + // Maximum number of splits occurred. + // Record position in string + pos = token - sptr; break; - } else { - if (!result[i]) { - return NULL; - } - strcpy(result[i], token); } - i++; - if (x > 0) { - --x; + result[i] = calloc(OMC_BUFSIZ, sizeof(char)); + if (!result[i]) { + return NULL; } - //memcpy(result[i], token, strlen(token) + 1); // copy the string contents into the record + strcpy(result[i], token); } + + // pos is non-zero when maximum split is reached + if (pos) { + // append the remaining string contents to array + result[i] = calloc(OMC_BUFSIZ, sizeof(char)); + if (!result[i]) { + return NULL; + } + strcpy(result[i], &orig[pos]); + } + guard_free(sptr); return result; } @@ -244,8 +197,9 @@ char *join_ex(char *separator, ...) { if (tmp == NULL) { perror("join_ex realloc failed"); return NULL; + } else if (tmp != argv) { + argv = tmp; } - argv = tmp; size += strlen(current) + separator_len; argv[argc] = strdup(current); } @@ -275,43 +229,37 @@ char *substring_between(char *sptr, const char *delims) { // Ensure we have enough delimiters to continue size_t delim_count = strlen(delims); - if (delim_count != 2) { + if (delim_count < 2 || delim_count % 2) { return NULL; } + char delim_open[255] = {0}; + strncpy(delim_open, delims, delim_count / 2); + + char delim_close[255] = {0}; + strcpy(delim_close, &delims[delim_count / 2]); + // Create pointers to the delimiters - char *start = strchr(sptr, delims[0]); + char *start = strstr(sptr, delim_open); if (start == NULL || strlen(start) == 0) { return NULL; } - char *end = strchr(start + 1, delims[1]); + char *end = strstr(start + 1, delim_close); if (end == NULL) { return NULL; } - start++; // ignore leading delimiter + start += delim_count / 2; // ignore leading delimiter // Get length of the substring - size_t length = strlen(start); + size_t length = strlen(start) - strlen(end); if (!length) { return NULL; } - char *result = (char *)calloc(length + 1, sizeof(char)); - if (!result) { - return NULL; - } - - // Copy the contents of the substring to the result - char *tmp = result; - while (start != end) { - *tmp = *start; - tmp++; - start++; - } - - return result; + // Return the contents of the substring + return strndup(start, length); } /* @@ -476,19 +424,16 @@ char *strip(char *sptr) { size_t len = strlen(sptr); if (len == 0) { return sptr; - } - else if (len == 1 && (isblank(*sptr) || isspace(*sptr))) { + } else if (len == 1 && (isblank(*sptr) || isspace(*sptr))) { *sptr = '\0'; return sptr; - } - for (size_t i = len; i != 0; --i) { + } for (size_t i = len; i != 0; --i) { if (sptr[i] == '\0') { continue; } if (isspace(sptr[i]) || isblank(sptr[i])) { sptr[i] = '\0'; - } - else { + } else { break; } } @@ -665,6 +610,9 @@ int strcmp_array(const char **a, const char **b) { } int isdigit_s(const char *s) { + if (!s || !strlen(s)) { + return 0; // nothing to do, fail + } for (size_t i = 0; s[i] != '\0'; i++) { if (isdigit(s[i]) == 0) { return 0; // non-digit found, fail diff --git a/src/strlist.c b/src/strlist.c index d54ed06..bd88c46 100644 --- a/src/strlist.c +++ b/src/strlist.c @@ -3,7 +3,6 @@ * @file strlist.c */ #include "strlist.h" -//#include "url.h" #include "utils.h" /** @@ -71,6 +70,7 @@ int strlist_append_file(struct StrList *pStrList, char *_path, ReaderFn *readerF char *path = NULL; char *filename = NULL; char **data = NULL; + int is_url = strstr(_path, "://") != NULL; if (readerFn == NULL) { readerFn = reader_strlist_append_file; @@ -78,17 +78,32 @@ int strlist_append_file(struct StrList *pStrList, char *_path, ReaderFn *readerF path = strdup(_path); if (path == NULL) { - retval = -1; goto fatal; } - filename = expandpath(path); - - if (filename == NULL) { + if (is_url) { + int fd; + char tempfile[PATH_MAX] = {0}; + strcpy(tempfile, "/tmp/.remote_file.XXXXXX"); + if ((fd = mkstemp(tempfile)) < 0) { + retval = -1; + goto fatal; + } + close(fd); + filename = tempfile; + long http_code = download(path, filename, NULL); + if (HTTP_ERROR(http_code)) { + retval = -1; + goto fatal; + } - retval = -1; - goto fatal; + } else { + filename = expandpath(path); + if (filename == NULL) { + retval = -1; + goto fatal; + } } data = file_readlines(filename, 0, 0, readerFn); @@ -96,15 +111,18 @@ int strlist_append_file(struct StrList *pStrList, char *_path, ReaderFn *readerF retval = 1; goto fatal; } - for (size_t record = 0; data[record] != NULL; record++) { strlist_append(&pStrList, data[record]); guard_free(data[record]); } + if (is_url) { + // remove temporary data + remove(filename); + } guard_free(data); fatal: - if (filename != NULL) { + if (!is_url && filename != NULL) { guard_free(filename); } if (path != NULL) { @@ -115,7 +133,7 @@ fatal: } /** - * Append the contents of a `StrList` to another `StrList` + * Append the contents of `pStrList2` to `pStrList1` * @param pStrList1 `StrList` * @param pStrList2 `StrList` */ @@ -203,13 +221,17 @@ void strlist_remove(struct StrList *pStrList, size_t index) { for (size_t i = index; i < count; i++) { char *next = pStrList->data[i + 1]; - pStrList->data[i] = next; if (next == NULL) { break; } + pStrList->data[i] = next; + count = strlist_count(pStrList); + pStrList->data[count - 1] = NULL; + } + if (pStrList->num_inuse) { + guard_free(pStrList->data[pStrList->num_inuse]); + pStrList->num_inuse--; } - - pStrList->num_inuse--; } /** @@ -227,13 +249,10 @@ int strlist_cmp(struct StrList *a, struct StrList *b) { return -2; } - if (a->num_alloc != b->num_alloc) { + if (a->num_alloc != b->num_alloc || a->num_inuse != b->num_inuse) { return 1; } - if (a->num_inuse != b->num_inuse) { - return 1; - } for (size_t i = 0; i < strlist_count(a); i++) { if (strcmp(strlist_item(a, i), strlist_item(b, i)) != 0) { @@ -321,6 +340,29 @@ void strlist_set(struct StrList **pStrList, size_t index, char *value) { } } +const char *strlist_error_msgs[] = { + "success", + "index out of range", + "invalid value for type", + "unknown error", +}; +int strlist_errno = 0; + +void strlist_set_error(int flag) { + strlist_errno = flag; +} + +const char *strlist_get_error(int flag) { + if (flag < STRLIST_E_SUCCESS || flag > STRLIST_E_UNKNOWN) { + return strlist_error_msgs[STRLIST_E_UNKNOWN]; + } + return strlist_error_msgs[flag]; +} + +void strlist_clear_error() { + strlist_errno = STRLIST_E_SUCCESS; +} + /** * Retrieve data from a `StrList` * @param pStrList @@ -351,7 +393,17 @@ char *strlist_item_as_str(struct StrList *pStrList, size_t index) { * @return `char` */ char strlist_item_as_char(struct StrList *pStrList, size_t index) { - return (char) strtol(strlist_item(pStrList, index), NULL, 10); + char *error_p; + char result; + + strlist_clear_error(); + result = (char) strtol(strlist_item(pStrList, index), &error_p, 10); + if (!result && error_p && *error_p != 0) { + strlist_set_error(STRLIST_E_INVALID_VALUE); + return 0; + } + error_p = NULL; + return result; } /** @@ -361,7 +413,17 @@ char strlist_item_as_char(struct StrList *pStrList, size_t index) { * @return `unsigned char` */ unsigned char strlist_item_as_uchar(struct StrList *pStrList, size_t index) { - return (unsigned char) strtol(strlist_item(pStrList, index), NULL, 10); + char *error_p; + unsigned char result; + + strlist_clear_error(); + result = (unsigned char) strtoul(strlist_item(pStrList, index), &error_p, 10); + if (!result && error_p && *error_p != 0) { + strlist_set_error(STRLIST_E_INVALID_VALUE); + return 0; + } + error_p = NULL; + return result; } /** @@ -371,7 +433,17 @@ unsigned char strlist_item_as_uchar(struct StrList *pStrList, size_t index) { * @return `short` */ short strlist_item_as_short(struct StrList *pStrList, size_t index) { - return (short)strtol(strlist_item(pStrList, index), NULL, 10); + char *error_p; + short result; + + strlist_clear_error(); + result = (short) strtol(strlist_item(pStrList, index), &error_p, 10); + if (!result && error_p && *error_p != 0) { + strlist_set_error(STRLIST_E_INVALID_VALUE); + return 0; + } + error_p = NULL; + return result; } /** @@ -381,7 +453,17 @@ short strlist_item_as_short(struct StrList *pStrList, size_t index) { * @return `unsigned short` */ unsigned short strlist_item_as_ushort(struct StrList *pStrList, size_t index) { - return (unsigned short)strtoul(strlist_item(pStrList, index), NULL, 10); + char *error_p; + unsigned short result; + + strlist_clear_error(); + result = (unsigned short) strtoul(strlist_item(pStrList, index), &error_p, 10); + if (!result && error_p && *error_p != 0) { + strlist_set_error(STRLIST_E_INVALID_VALUE); + return 0; + } + error_p = NULL; + return result; } /** @@ -391,7 +473,17 @@ unsigned short strlist_item_as_ushort(struct StrList *pStrList, size_t index) { * @return `int` */ int strlist_item_as_int(struct StrList *pStrList, size_t index) { - return (int)strtol(strlist_item(pStrList, index), NULL, 10); + char *error_p; + int result; + + strlist_clear_error(); + result = (int) strtol(strlist_item(pStrList, index), &error_p, 10); + if (!result && error_p && *error_p != 0) { + strlist_set_error(STRLIST_E_INVALID_VALUE); + return 0; + } + error_p = NULL; + return result; } /** @@ -401,7 +493,17 @@ int strlist_item_as_int(struct StrList *pStrList, size_t index) { * @return `unsigned int` */ unsigned int strlist_item_as_uint(struct StrList *pStrList, size_t index) { - return (unsigned int)strtoul(strlist_item(pStrList, index), NULL, 10); + char *error_p; + unsigned int result; + + strlist_clear_error(); + result = (unsigned int) strtoul(strlist_item(pStrList, index), &error_p, 10); + if (!result && error_p && *error_p != 0) { + strlist_set_error(STRLIST_E_INVALID_VALUE); + return 0; + } + error_p = NULL; + return result; } /** @@ -411,7 +513,17 @@ unsigned int strlist_item_as_uint(struct StrList *pStrList, size_t index) { * @return `long` */ long strlist_item_as_long(struct StrList *pStrList, size_t index) { - return strtol(strlist_item(pStrList, index), NULL, 10); + char *error_p; + long result; + + strlist_clear_error(); + result = (long) strtol(strlist_item(pStrList, index), &error_p, 10); + if (!result && error_p && *error_p != 0) { + strlist_set_error(STRLIST_E_INVALID_VALUE); + return 0; + } + error_p = NULL; + return result; } /** @@ -421,7 +533,17 @@ long strlist_item_as_long(struct StrList *pStrList, size_t index) { * @return `unsigned long` */ unsigned long strlist_item_as_ulong(struct StrList *pStrList, size_t index) { - return strtoul(strlist_item(pStrList, index), NULL, 10); + char *error_p; + unsigned long result; + + strlist_clear_error(); + result = (unsigned long) strtoul(strlist_item(pStrList, index), &error_p, 10); + if (!result && error_p && *error_p != 0) { + strlist_set_error(STRLIST_E_INVALID_VALUE); + return 0; + } + error_p = NULL; + return result; } /** @@ -431,7 +553,17 @@ unsigned long strlist_item_as_ulong(struct StrList *pStrList, size_t index) { * @return `long long` */ long long strlist_item_as_long_long(struct StrList *pStrList, size_t index) { - return strtoll(strlist_item(pStrList, index), NULL, 10); + char *error_p; + long long result; + + strlist_clear_error(); + result = (long long) strtoll(strlist_item(pStrList, index), &error_p, 10); + if (!result && error_p && *error_p != 0) { + strlist_set_error(STRLIST_E_INVALID_VALUE); + return 0; + } + error_p = NULL; + return result; } /** @@ -441,7 +573,17 @@ long long strlist_item_as_long_long(struct StrList *pStrList, size_t index) { * @return `unsigned long long` */ unsigned long long strlist_item_as_ulong_long(struct StrList *pStrList, size_t index) { - return strtoull(strlist_item(pStrList, index), NULL, 10); + char *error_p; + unsigned long long result; + + strlist_clear_error(); + result = (unsigned long long) strtol(strlist_item(pStrList, index), &error_p, 10); + if (!result && error_p && *error_p != 0) { + strlist_set_error(STRLIST_E_INVALID_VALUE); + return 0; + } + error_p = NULL; + return result; } /** @@ -451,7 +593,17 @@ unsigned long long strlist_item_as_ulong_long(struct StrList *pStrList, size_t i * @return `float` */ float strlist_item_as_float(struct StrList *pStrList, size_t index) { - return (float)atof(strlist_item(pStrList, index)); + char *error_p; + float result; + + strlist_clear_error(); + result = (float) strtof(strlist_item(pStrList, index), &error_p); + if (!result && error_p && *error_p != 0) { + strlist_set_error(STRLIST_E_INVALID_VALUE); + return 0; + } + error_p = NULL; + return result; } /** @@ -461,7 +613,17 @@ float strlist_item_as_float(struct StrList *pStrList, size_t index) { * @return `double` */ double strlist_item_as_double(struct StrList *pStrList, size_t index) { - return atof(strlist_item(pStrList, index)); + char *error_p; + double result; + + strlist_clear_error(); + result = (double) strtod(strlist_item(pStrList, index), &error_p); + if (!result && error_p && *error_p != 0) { + strlist_set_error(STRLIST_E_INVALID_VALUE); + return 0; + } + error_p = NULL; + return result; } /** @@ -471,7 +633,17 @@ double strlist_item_as_double(struct StrList *pStrList, size_t index) { * @return `long double` */ long double strlist_item_as_long_double(struct StrList *pStrList, size_t index) { - return (long double)atof(strlist_item(pStrList, index)); + char *error_p; + long double result; + + strlist_clear_error(); + result = (long double) strtold(strlist_item(pStrList, index), &error_p); + if (!result && error_p && *error_p != 0) { + strlist_set_error(STRLIST_E_INVALID_VALUE); + return 0; + } + error_p = NULL; + return result; } /** diff --git a/src/system.c b/src/system.c index ca2da97..d5e77ce 100644 --- a/src/system.c +++ b/src/system.c @@ -1,11 +1,8 @@ -// -// Created by jhunk on 10/4/23. -// - #include "system.h" #include "omc.h" int shell(struct Process *proc, char *args) { + struct Process selfproc; FILE *fp_out = NULL; FILE *fp_err = NULL; pid_t pid; @@ -13,6 +10,18 @@ int shell(struct Process *proc, char *args) { status = 0; errno = 0; + if (!proc) { + // provide our own proc structure + // albeit not accessible to the user + memset(&selfproc, 0, sizeof(selfproc)); + proc = &selfproc; + } + + if (!args) { + proc->returncode = -1; + return -1; + } + FILE *tp = NULL; char *t_name; t_name = xmkstemp(&tp, "w"); @@ -31,22 +40,20 @@ int shell(struct Process *proc, char *args) { exit(1); } else if (pid == 0) { int retval; - if (proc != NULL) { - if (strlen(proc->f_stdout)) { - fp_out = freopen(proc->f_stdout, "w+", stdout); - } + if (strlen(proc->f_stdout)) { + fp_out = freopen(proc->f_stdout, "w+", stdout); + } - if (strlen(proc->f_stderr)) { - fp_err = freopen(proc->f_stderr, "w+", stderr); - } + if (strlen(proc->f_stderr)) { + fp_err = freopen(proc->f_stderr, "w+", stderr); + } - if (proc->redirect_stderr) { - if (fp_err) { - fclose(fp_err); - fclose(stderr); - } - dup2(fileno(stdout), fileno(stderr)); + if (proc->redirect_stderr) { + if (fp_err) { + fclose(fp_err); + fclose(stderr); } + dup2(fileno(stdout), fileno(stderr)); } retval = execl("/bin/bash", "bash", "-c", t_name, (char *) NULL); @@ -54,7 +61,7 @@ int shell(struct Process *proc, char *args) { remove(t_name); } - if (proc != NULL && strlen(proc->f_stdout)) { + if (strlen(proc->f_stdout)) { if (fp_out != NULL) { fflush(fp_out); fclose(fp_out); @@ -62,7 +69,7 @@ int shell(struct Process *proc, char *args) { fflush(stdout); fclose(stdout); } - if (proc != NULL && strlen(proc->f_stderr)) { + if (strlen(proc->f_stderr)) { if (fp_err) { fflush(fp_err); fclose(fp_err); @@ -89,10 +96,7 @@ int shell(struct Process *proc, char *args) { remove(t_name); } - if (proc != NULL) { - proc->returncode = status; - } - + proc->returncode = status; guard_free(t_name); return WEXITSTATUS(status); } @@ -102,7 +106,7 @@ int shell_safe(struct Process *proc, char *args) { char buf[1024] = {0}; int result; - char *invalid_ch = strpbrk(args, ";&|()"); + char *invalid_ch = strpbrk(args, OMC_SHELL_SAFE_RESTRICT); if (invalid_ch) { args = NULL; } @@ -168,6 +172,6 @@ char *shell_output(const char *command, int *status) { strcat(result, line); memset(line, 0, sizeof(line)); } - pclose(pp); + *status = pclose(pp); return result; }
\ No newline at end of file diff --git a/src/template.c b/src/template.c index 6101338..0a57232 100644 --- a/src/template.c +++ b/src/template.c @@ -16,9 +16,14 @@ struct tpl_item { }; struct tpl_item *tpl_pool[1024] = {0}; unsigned tpl_pool_used = 0; +struct tplfunc_frame *tpl_pool_func[1024] = {0}; unsigned tpl_pool_func_used = 0; -struct tplfunc_frame *tpl_pool_func[1024] = {0}; +extern void tpl_reset() { + tpl_free(); + tpl_pool_used = 0; + tpl_pool_func_used = 0; +} void tpl_register_func(char *key, struct tplfunc_frame *frame) { (void) key; // TODO: placeholder @@ -86,6 +91,10 @@ void tpl_free() { } guard_free(item); } + for (unsigned i = 0; i < tpl_pool_func_used; i++) { + struct tplfunc_frame *item = tpl_pool_func[i]; + guard_free(item); + } } char *tpl_getval(char *key) { @@ -167,7 +176,9 @@ char *tpl_render(char *str) { size_t key_len = 0; while (isalnum(pos[off]) || pos[off] != '}') { if (isspace(pos[off]) || isblank(pos[off])) { - break; + // skip whitespace in key + off++; + continue; } key[key_len] = pos[off]; key_len++; @@ -205,7 +216,44 @@ char *tpl_render(char *str) { char *env_val = getenv(key); value = strdup(env_val ? env_val : ""); } else if (do_func) { // {{ func:NAME(a, ...) }} - // TODO + char func_name_temp[OMC_NAME_MAX] = {0}; + strcpy(func_name_temp, type_stop + 1); + char *param_begin = strchr(func_name_temp, '('); + if (!param_begin) { + fprintf(stderr, "offset %zu: function name must be followed by a '('\n", off); + guard_free(output); + return NULL; + } + *param_begin = 0; + param_begin++; + char *param_end = strrchr(param_begin, ')'); + if (!param_end) { + fprintf(stderr, "offset %zu: function arguments must be closed with a ')'\n", off); + guard_free(output); + return NULL; + } + *param_end = 0; + char *k = func_name_temp; + char **params = split(param_begin, ",", 0); + int params_count; + for (params_count = 0; params[params_count] != NULL; params_count++); + + struct tplfunc_frame *frame = tpl_getfunc(k); + if (params_count > frame->argc) { + fprintf(stderr, "offset %zu: Too many arguments for function: %s()\n", off, frame->key); + value = strdup(""); + } else { + for (size_t p = 0; p < sizeof(frame->argv) / sizeof(*frame->argv) && params[p] != NULL; p++) { + lstrip(params[p]); + strip(params[p]); + frame->argv[p].t_char_ptr = params[p]; + } + char func_result[100]; + char *fres = func_result; + frame->func(frame, fres); + value = strdup(fres); + } + GENERIC_ARRAY_FREE(params); } else { // Read replacement value value = strdup(tpl_getval(key) ? tpl_getval(key) : ""); diff --git a/src/utils.c b/src/utils.c index 7cc3e6e..7b77020 100644 --- a/src/utils.c +++ b/src/utils.c @@ -6,9 +6,15 @@ const ssize_t dirstack_max = sizeof(dirstack) / sizeof(dirstack[0]); ssize_t dirstack_len = 0; int pushd(const char *path) { + if (access(path, F_OK)) { + // the requested path doesn't exist. + return -1; + } if (dirstack_len + 1 > dirstack_max) { + // the stack is full return -1; } + dirstack[dirstack_len] = realpath(".", NULL); dirstack_len++; return chdir(path); @@ -151,7 +157,7 @@ char *path_dirname(char *path) { if (!pos) { return "."; } - *path = '\0'; + *pos = '\0'; return path; } @@ -702,29 +708,25 @@ char *collapse_whitespace(char **s) { * @return 0 on success, -1 on error */ int redact_sensitive(const char **to_redact, char *src, char *dest, size_t maxlen) { - char **parts = split(src, " ", 0); - if (!parts) { - fprintf(stderr, "Unable to split source string\n"); + const char *redacted = "***REDACTED***"; + + char *tmp = calloc(strlen(redacted) + strlen(src) + 1, sizeof(*tmp)); + if (!tmp) { return -1; } + strcpy(tmp, src); for (size_t i = 0; to_redact[i] != NULL; i++) { - for (size_t p = 0; parts[p] != NULL; p++) { - if (strstr(parts[p], to_redact[i])) { - replace_text(parts[p], to_redact[i], "***REDACTED***", REPLACE_TRUNCATE_AFTER_MATCH); - } + if (strstr(tmp, to_redact[i])) { + replace_text(tmp, to_redact[i], redacted, 0); + break; } } - char *dest_tmp = join(parts, " "); - if (!dest_tmp) { - fprintf(stderr, "Unable to join message array\n"); - return -1; - } - strncpy(dest, dest_tmp, maxlen); + memset(dest, 0, maxlen); + strncpy(dest, tmp, maxlen - 1); + guard_free(tmp); - GENERIC_ARRAY_FREE(parts); - guard_free(dest_tmp); return 0; } |