Merge branch 'fixes'
[gitweb.git] / quote.c
diff --git a/quote.c b/quote.c
index 5e6fda311c5f5fdaa20b7e9d64e46c13b7d9cce8..9d5d0bcb0f0e32b95e27d32efe6d725479d28f76 100644 (file)
--- a/quote.c
+++ b/quote.c
@@ -2,40 +2,52 @@
 #include "quote.h"
 
 /* Help to copy the thing properly quoted for the shell safety.
- * any single quote is replaced with '\'', and the caller is
- * expected to enclose the result within a single quote pair.
+ * any single quote is replaced with '\'', any exclamation point
+ * is replaced with '\!', and the whole thing is enclosed in a
  *
  * E.g.
  *  original     sq_quote     result
  *  name     ==> name      ==> 'name'
  *  a b      ==> a b       ==> 'a b'
  *  a'b      ==> a'\''b    ==> 'a'\''b'
+ *  a!b      ==> a'\!'b    ==> 'a'\!'b'
  */
-char *sq_quote(const char *src)
-{
-       static char *buf = NULL;
-       int cnt, c;
-       const char *cp;
-       char *bp;
+#define EMIT(x) ( (++len < n) && (*bp++ = (x)) )
 
-       /* count bytes needed to store the quoted string. */
-       for (cnt = 3, cp = src; *cp; cnt++, cp++)
-               if (*cp == '\'')
-                       cnt += 3;
+size_t sq_quote_buf(char *dst, size_t n, const char *src)
+{
+       char c;
+       char *bp = dst;
+       size_t len = 0;
 
-       buf = xmalloc(cnt);
-       bp = buf;
-       *bp++ = '\'';
+       EMIT('\'');
        while ((c = *src++)) {
-               if (c != '\'')
-                       *bp++ = c;
-               else {
-                       bp = strcpy(bp, "'\\''");
-                       bp += 4;
+               if (c == '\'' || c == '!') {
+                       EMIT('\'');
+                       EMIT('\\');
+                       EMIT(c);
+                       EMIT('\'');
+               } else {
+                       EMIT(c);
                }
        }
-       *bp++ = '\'';
-       *bp = 0;
+       EMIT('\'');
+
+       if ( n )
+               *bp = 0;
+
+       return len;
+}
+
+char *sq_quote(const char *src)
+{
+       char *buf;
+       size_t cnt;
+
+       cnt = sq_quote_buf(NULL, 0, src) + 1;
+       buf = xmalloc(cnt);
+       sq_quote_buf(buf, cnt, src);
+
        return buf;
 }