#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#include "sh-quote.h"
#include <string.h>
#include "strpbrk.h"
#include "xalloc.h"
#define SHELL_SPECIAL_CHARS "\t\n !\"#$&'()*;<=>?[\\]`{|}~"
size_t
shell_quote_length (const char *string)
{
if (string[0] == '\0')
return 2;
else if (strpbrk (string, SHELL_SPECIAL_CHARS) == NULL)
return strlen (string);
else
{
char qchar = '\0';
size_t length = 0;
for (; *string != '\0'; string++)
{
char c = *string;
char q = (c == '\'' ? '"' : '\'');
if (qchar != q)
{
if (qchar)
length++;
qchar = q;
length++;
}
length++;
}
if (qchar)
length++;
return length;
}
}
char *
shell_quote_copy (char *p, const char *string)
{
if (string[0] == '\0')
{
memcpy (p, "''", 2);
return p + 2;
}
else if (strpbrk (string, SHELL_SPECIAL_CHARS) == NULL)
{
memcpy (p, string, strlen (string));
return p + strlen (string);
}
else
{
char qchar = '\0';
for (; *string != '\0'; string++)
{
char c = *string;
char q = (c == '\'' ? '"' : '\'');
if (qchar != q)
{
if (qchar)
*p++ = qchar;
qchar = q;
*p++ = qchar;
}
*p++ = c;
}
if (qchar)
*p++ = qchar;
return p;
}
}
char *
shell_quote (const char *string)
{
size_t length = shell_quote_length (string);
char *quoted = (char *) xmalloc (length + 1);
char *p = shell_quote_copy (quoted, string);
*p = '\0';
return quoted;
}
char *
shell_quote_argv (char **argv)
{
if (*argv != NULL)
{
char **argp;
size_t length;
char *command;
char *p;
length = 0;
for (argp = argv; ; )
{
length += shell_quote_length (*argp) + 1;
argp++;
if (*argp == NULL)
break;
}
command = (char *) xmalloc (length);
p = command;
for (argp = argv; ; )
{
p = shell_quote_copy (p, *argp);
argp++;
if (*argp == NULL)
break;
*p++ = ' ';
}
*p = '\0';
return command;
}
else
return xstrdup ("");
}