Skip to content

Instantly share code, notes, and snippets.

@lichray
Created April 13, 2012 06:18
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save lichray/2374329 to your computer and use it in GitHub Desktop.
Save lichray/2374329 to your computer and use it in GitHub Desktop.
Reliably quote a string as a single argument for /bin/sh.
#include <sys/param.h>
#include <sys/wait.h>
#include <ctype.h>
#include <paths.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
/*
* Reliably quote a string as a single argument for /bin/sh.
* The logic comes from python's pipes.quote().
*/
char *
quote(char *str)
{
char *p, *t;
size_t i = 0, n = 0;
int unsafe = 0;
for (p = str; *p != '\0'; p++, i++) {
if (*p == '\'')
n++;
if (unsafe)
continue;
if (isascii(*p)) {
if (isalnum(*p))
continue;
switch (*p) {
case '%': case '+': case ',': case '-': case '.':
case '/': case ':': case '=': case '@': case '_':
continue;
}
}
unsafe = 1;
}
if (!unsafe)
t = strdup(str);
#define SQT "'\\''"
else if ((p = t = malloc(i + n * (sizeof(SQT) - 2) + 3)) != NULL) {
*p++ = '\'';
for (; *str != '\0'; str++) {
if (*str == '\'') {
(void)strncpy(p, SQT, sizeof(SQT) - 1);
p += sizeof(SQT) - 1;
} else
*p++ = *str;
}
*p++ = '\'';
*p = '\0';
}
return t;
}
/*
* An example program, touch a file for each of your input lines.
* No error checking -- don't blame me for that.
*/
int main(void) {
char buf[MAXPATHLEN];
int pid;
int st = 0;
while (1) {
char *p, *t;
fgets(buf, sizeof(buf), stdin);
t = strchr(buf, '\n');
if (t == NULL)
return WEXITSTATUS(st);
*t = '\0';
p = quote(buf);
pid = fork();
if (pid) {
free(p);
waitpid(pid, &st, 0);
} else {
char *cmd;
asprintf(&cmd, "touch %s", p);
puts(cmd);
execl(_PATH_BSHELL, "sh", "-c", cmd, NULL);
free(cmd);
_exit(127);
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment