summaryrefslogtreecommitdiffstats
path: root/src/bfstd.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/bfstd.c')
-rw-r--r--src/bfstd.c46
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;
+}