Last active
January 19, 2022 04:32
-
-
Save ilyakurdyukov/db5e81b87a7be5ac38813104c111799f to your computer and use it in GitHub Desktop.
Helper function for escaping special characters from user-provided strings to be used in calls to system().
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#ifndef SAFESYS_H | |
#define SAFESYS_H | |
#include <stdlib.h> | |
#include <stdarg.h> | |
#ifndef SAFESYS_NOMEM | |
#include <errno.h> | |
#define SAFESYS_NOMEM ENOMEM | |
#endif | |
static int safesys(const char *format, ...) { | |
va_list va; size_t size = 0; | |
const char *next, *p, *f, *esc; | |
char *d, *cmd, c; int ret, nquot; | |
esc = "\t\n\r !\"#$&()*;<=>?[\\]^`{|}~"; | |
va_start(va, format); | |
f = format; | |
while ((c = *f++)) if (c == '%') { | |
p = next = va_arg(va, const char*); | |
nquot = 0; | |
while ((c = *p++)) | |
nquot = c == '\'' ? | |
size += nquot > 1 ? 3 : nquot + 1, 0 : | |
nquot + !!strchr(esc, c); | |
size += (nquot > 1 ? 2 : nquot) + (p - next) - 2; | |
} | |
va_end(va); | |
size += f - format; | |
cmd = malloc(size); | |
if (!cmd) return SAFESYS_NOMEM; | |
#define SAFESYS_COPY \ | |
if (nquot > 1) *d++ = '\''; \ | |
while (next < p - 1) { \ | |
c = *next++; \ | |
if (nquot == 1 && strchr(esc, c)) \ | |
*d++ = '\\', nquot = 0; \ | |
*d++ = c; \ | |
} \ | |
if (nquot > 1) *d++ = '\''; | |
d = cmd; | |
va_start(va, format); | |
f = format; | |
while ((c = *f++)) | |
if (c != '%') *d++ = c; | |
else { | |
p = next = va_arg(va, const char*); | |
nquot = 0; | |
while ((c = *p++)) | |
if (c == '\'') { | |
SAFESYS_COPY | |
nquot = 0; next++; | |
*d++ = '\\'; *d++ = '\''; | |
} else nquot += !!strchr(esc, c); | |
SAFESYS_COPY | |
} | |
va_end(va); | |
*d = 0; | |
puts(cmd); | |
ret = system(cmd); | |
free(cmd); | |
return ret; | |
} | |
#endif // SAFESYS_H |
You might wish to have the code simply return a malloced string that is "safe" and let the caller pass it to system() or popen()
This can be done very simply:
-static int safesys(const char *format, ...) {
+static char* cmdprintf(const char *format, ...) {
- if (!cmd) return SAFESYS_NOMEM;
+ if (!cmd) return cmd;
- puts(cmd);
- ret = system(cmd);
- free(cmd);
- return ret;
+ return cmd;
I just want to keep system() in this gist as an example.
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
mkiocccentry does not require double quotes escaping, because if one wants to use $FOO on the command line to invoke mkiocccentry, those variables will be expanded by the shell before mkiocccentry is run.