diff options
author | Tavian Barnes <tavianator@tavianator.com> | 2023-06-16 13:44:06 -0400 |
---|---|---|
committer | Tavian Barnes <tavianator@tavianator.com> | 2023-06-16 13:44:06 -0400 |
commit | d3f4340a460a023656151f220f5923ec8ccf9894 (patch) | |
tree | c004b4b319bf164a25cd72f6c6f5b7f19b927368 /src/bfstd.c | |
parent | a5550d478234efbb89d1c23ae3234bed626a47f6 (diff) | |
download | bfs-d3f4340a460a023656151f220f5923ec8ccf9894.tar.xz |
bfstd: New wordesc() function to shell-escape strings
Diffstat (limited to 'src/bfstd.c')
-rw-r--r-- | src/bfstd.c | 46 |
1 files changed, 46 insertions, 0 deletions
diff --git a/src/bfstd.c b/src/bfstd.c index 4e1175f..cfff426 100644 --- a/src/bfstd.c +++ b/src/bfstd.c @@ -544,3 +544,49 @@ size_t xstrwidth(const char *str) { return ret; } + +char *wordesc(const char *str) { + size_t len = strlen(str); + + if (strcspn(str, "|&;<>()$`\\\"' \t\n*?[#˜=%") == len) { + // Whole string is safe + // https://pubs.opengroup.org/onlinepubs/9699919799/utilities/V3_chap02.html#tag_18_02 + if (len > 0) { + return strdup(str); + } else { + return strdup("\"\""); + } + } else if (strcspn(str, "`$\\\"") == len) { + // Safe to double-quote the whole string + // https://pubs.opengroup.org/onlinepubs/9699919799/utilities/V3_chap02.html#tag_18_02_03 + char *ret = malloc(len + 3); + if (!ret) { + return NULL; + } + + char *cur = stpcpy(ret, "\""); + cur = stpcpy(cur, str); + cur = stpcpy(cur, "\""); + return ret; + } + + // Every ' is replaced with '\'', so at most a 3x growth + char *ret = malloc(3 * len + 3); + if (!ret) { + return NULL; + } + + char *cur = stpcpy(ret, "'"); + while (*str) { + size_t chunk = strcspn(str, "'"); + cur = stpncpy(cur, str, chunk); + str += chunk; + if (*str) { + cur = stpcpy(cur, "'\\''"); + ++str; + } + } + cur = stpcpy(cur, "'"); + + return ret; +} |