diff options
author | Joseph Hunkeler <jhunkeler@users.noreply.github.com> | 2024-06-20 15:10:56 -0400 |
---|---|---|
committer | GitHub <noreply@github.com> | 2024-06-20 15:10:56 -0400 |
commit | 931ee28eb9c5b5e3c2b0d3008f5f65d810dc9b0c (patch) | |
tree | 5dbcccffd509fa71a99c351ed4628ed0841e1e46 /src | |
parent | 11aa1d44d95da221073e512fbec3bbccc0f1a46b (diff) | |
download | stasis-931ee28eb9c5b5e3c2b0d3008f5f65d810dc9b0c.tar.gz |
Unit tests (#6)
* Initial commit of unit tests [WIP]
* Address shortcomings and bugs flushed out by unit tests
* Enable unit testing in CI workflow
* Enable verbose ctests
* Handle lack of __FILE_NAME__ define
* Only podman support `run --arch` argument
* Skip docker build testing if CI system cannot pull an image
* Remove errant call to puts()
* Identify local repo user
* Fix missing xmllint
* NULL terminate arrays
* Fix filename assignment in is_url mode
* Break loop when expected lines are exhausted
* strcmp_array expects NULL terminated array. Iterating by size in this case passes NULL to strcmp leading to an invalid read
* Remove debug printf statements
* Disable a few warnings for tests
* Workaround for ctest junit xml truncation
* Update checkout@v4
* Prevent false-positive result
* Return zero on error
* Fix strlist_remove function
* Value argument can be constant
* Fix test to match changes to startswith and endswith
* Add test_ini.c
* Fix redaction code to accept NULL pointers in array
* And let the caller specify the length of the array of strings to redact.
* Redactions now occur directly on authentication strings rather than their command line arguments
* Fix BUILD_TESTING_DEBUG
* Adds missing -D argument
Diffstat (limited to 'src')
-rw-r--r-- | src/artifactory.c | 15 | ||||
-rw-r--r-- | src/docker.c | 4 | ||||
-rw-r--r-- | src/ini.c | 2 | ||||
-rw-r--r-- | src/str.c | 154 | ||||
-rw-r--r-- | src/strlist.c | 239 | ||||
-rw-r--r-- | src/system.c | 54 | ||||
-rw-r--r-- | src/template.c | 54 | ||||
-rw-r--r-- | src/utils.c | 38 |
8 files changed, 362 insertions, 198 deletions
diff --git a/src/artifactory.c b/src/artifactory.c index 4772602..5678d64 100644 --- a/src/artifactory.c +++ b/src/artifactory.c @@ -229,16 +229,15 @@ int jfrog_cli(struct JFRT_Auth *auth, char *args) { } const char *redactable[] = { - "--access-token=", - "--ssh-key-path=", - "--ssh-passphrase=", - "--client-cert-key-path=", - "--client-cert-path=", - "--password=", - NULL, + auth->access_token, + auth->ssh_key_path, + auth->ssh_passphrase, + auth->client_cert_key_path, + auth->client_cert_path, + auth->password, }; snprintf(cmd, sizeof(cmd) - 1, "jf %s %s", args, auth_args); - redact_sensitive(redactable, cmd, cmd_redacted, sizeof(cmd_redacted) - 1); + redact_sensitive(redactable, sizeof(redactable) / sizeof (*redactable), cmd, cmd_redacted, sizeof(cmd_redacted) - 1); guard_free(auth_args); guard_strlist_free(&arg_map); 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]; @@ -16,7 +16,7 @@ void ini_section_init(struct INIFILE **ini) { (*ini)->section = calloc((*ini)->section_count + 1, sizeof(**(*ini)->section)); } -struct INISection *ini_section_search(struct INIFILE **ini, unsigned mode, char *value) { +struct INISection *ini_section_search(struct INIFILE **ini, unsigned mode, const char *value) { struct INISection *result = NULL; for (size_t i = 0; i < (*ini)->section_count; i++) { if ((*ini)->section[i]->key != NULL) { @@ -16,7 +16,7 @@ int num_chars(const char *sptr, int ch) { int startswith(const char *sptr, const char *pattern) { if (!sptr || !pattern) { - return -1; + return 0; } for (size_t i = 0; i < strlen(pattern); i++) { if (sptr[i] != pattern[i]) { @@ -26,10 +26,9 @@ int startswith(const char *sptr, const char *pattern) { return 1; } - int endswith(const char *sptr, const char *pattern) { if (!sptr || !pattern) { - return -1; + return 0; } ssize_t sptr_size = (ssize_t) strlen(sptr); ssize_t pattern_size = (ssize_t) strlen(pattern); @@ -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..bdacb5a 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,31 @@ 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) { - - retval = -1; - goto fatal; + 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 = strdup(tempfile); + long http_code = download(path, filename, NULL); + if (HTTP_ERROR(http_code)) { + retval = -1; + goto fatal; + } + } else { + filename = expandpath(path); + if (filename == NULL) { + retval = -1; + goto fatal; + } } data = file_readlines(filename, 0, 0, readerFn); @@ -96,17 +110,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) { - guard_free(filename); - } + guard_free(filename); if (path != NULL) { guard_free(path); } @@ -115,7 +130,7 @@ fatal: } /** - * Append the contents of a `StrList` to another `StrList` + * Append the contents of `pStrList2` to `pStrList1` * @param pStrList1 `StrList` * @param pStrList2 `StrList` */ @@ -200,16 +215,14 @@ void strlist_remove(struct StrList *pStrList, size_t index) { if (count == 0) { return; } - - for (size_t i = index; i < count; i++) { - char *next = pStrList->data[i + 1]; - pStrList->data[i] = next; - if (next == NULL) { - break; + if (pStrList->data[index] != NULL) { + for (size_t i = index; i < count; i++) { + pStrList->data[i] = pStrList->data[i + 1]; + } + if (pStrList->num_inuse) { + pStrList->num_inuse--; } } - - pStrList->num_inuse--; } /** @@ -227,13 +240,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 +331,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 +384,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 +404,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 +424,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 +444,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 +464,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 +484,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 +504,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 +524,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 +544,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 +564,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 +584,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 +604,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 +624,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..86622ad 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; } @@ -701,30 +707,26 @@ char *collapse_whitespace(char **s) { * @param maxlen maximum length of dest string * @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"); +int redact_sensitive(const char **to_redact, size_t to_redact_size, char *src, char *dest, size_t maxlen) { + 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); - } + for (size_t i = 0; i < to_redact_size; i++) { + if (to_redact[i] && 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; } |