{"thread":{"id":"2060","subject":"[PATCH 1/3] Enhanced sq_quote()","startedAt":"2005-10-10T20:49:34Z","lastAt":"2005-10-10T20:49:34Z","messageCount":1,"participants":["H. Peter Anvin"],"isPatch":true,"patchVersion":1,"patchTotal":3},"messages":[{"id":"9922","messageId":"434AD3DE.6040300@zytor.com","threadId":"2060","inReplyTo":null,"subject":"[PATCH 1/3] Enhanced sq_quote()","fromName":"H. Peter Anvin","fromEmail":"hpa@zytor.com","sentAt":"2005-10-10T20:49:34Z","receivedAt":"2005-10-10T20:49:34Z","isPatch":true,"sender":{"key":"hpa@zytor.com","avatar":null},"body":"\n\nCreate function to sq_quote into a buffer\nHandle !'s for csh-based shells\n\nSigned-off-by: H. Peter Anvin <hpa@zytor.com>\n\n---\ncommit cc114823f72bd8d912abf7f7a7515853c554a9f3\ntree 9766b638ae175b9206855f2613e07507ed51fbca\nparent d5b0c9ea178dab3599674ccff50645c0464b8c31\nauthor Peter Anvin <hpa@tazenda.sc.orionmulti.com> Mon, 10 Oct 2005 12:21:35 -0700\ncommitter Peter Anvin <hpa@tazenda.sc.orionmulti.com> Mon, 10 Oct 2005 12:21:35 -0700\n\n quote.c |   56 ++++++++++++++++++++++++++++++++++----------------------\n quote.h |   11 +++++++++--\n 2 files changed, 43 insertions(+), 24 deletions(-)\n\ndiff --git a/quote.c b/quote.c\nindex 5e6fda3..9d5d0bc 100644\n--- a/quote.c\n+++ b/quote.c\n@@ -2,40 +2,52 @@\n #include \"quote.h\"\n \n /* Help to copy the thing properly quoted for the shell safety.\n- * any single quote is replaced with '\\'', and the caller is\n- * expected to enclose the result within a single quote pair.\n+ * any single quote is replaced with '\\'', any exclamation point\n+ * is replaced with '\\!', and the whole thing is enclosed in a\n  *\n  * E.g.\n  *  original     sq_quote     result\n  *  name     ==> name      ==> 'name'\n  *  a b      ==> a b       ==> 'a b'\n  *  a'b      ==> a'\\''b    ==> 'a'\\''b'\n+ *  a!b      ==> a'\\!'b    ==> 'a'\\!'b'\n  */\n-char *sq_quote(const char *src)\n+#define EMIT(x) ( (++len < n) && (*bp++ = (x)) )\n+\n+size_t sq_quote_buf(char *dst, size_t n, const char *src)\n {\n-\tstatic char *buf = NULL;\n-\tint cnt, c;\n-\tconst char *cp;\n-\tchar *bp;\n-\n-\t/* count bytes needed to store the quoted string. */\n-\tfor (cnt = 3, cp = src; *cp; cnt++, cp++)\n-\t\tif (*cp == '\\'')\n-\t\t\tcnt += 3;\n+\tchar c;\n+\tchar *bp = dst;\n+\tsize_t len = 0;\n \n-\tbuf = xmalloc(cnt);\n-\tbp = buf;\n-\t*bp++ = '\\'';\n+\tEMIT('\\'');\n \twhile ((c = *src++)) {\n-\t\tif (c != '\\'')\n-\t\t\t*bp++ = c;\n-\t\telse {\n-\t\t\tbp = strcpy(bp, \"'\\\\''\");\n-\t\t\tbp += 4;\n+\t\tif (c == '\\'' || c == '!') {\n+\t\t\tEMIT('\\'');\n+\t\t\tEMIT('\\\\');\n+\t\t\tEMIT(c);\n+\t\t\tEMIT('\\'');\n+\t\t} else {\n+\t\t\tEMIT(c);\n \t\t}\n \t}\n-\t*bp++ = '\\'';\n-\t*bp = 0;\n+\tEMIT('\\'');\n+\n+\tif ( n )\n+\t\t*bp = 0;\n+\n+\treturn len;\n+}\n+\n+char *sq_quote(const char *src)\n+{\n+\tchar *buf;\n+\tsize_t cnt;\n+\n+\tcnt = sq_quote_buf(NULL, 0, src) + 1;\n+\tbuf = xmalloc(cnt);\n+\tsq_quote_buf(buf, cnt, src);\n+\n \treturn buf;\n }\n \ndiff --git a/quote.h b/quote.h\nindex c8cfb3a..50ce1df 100644\n--- a/quote.h\n+++ b/quote.h\n@@ -1,10 +1,12 @@\n #ifndef QUOTE_H\n #define QUOTE_H\n \n+#include <stddef.h>\n \n /* Help to copy the thing properly quoted for the shell safety.\n- * any single quote is replaced with '\\'', and the whole thing\n- * is enclosed in a single quote pair.\n+ * any single quote is replaced with '\\'', any exclamation point\n+ * is replaced with '\\!', and the whole thing is enclosed in a\n+ * single quote pair.\n  *\n  * For example, if you are passing the result to system() as an\n  * argument:\n@@ -19,8 +21,13 @@\n  *\n  * Note that the above examples leak memory!  Remember to free result from\n  * sq_quote() in a real application.\n+ *\n+ * sq_quote_buf() writes to an existing buffer of specified size; it\n+ * will return the number of characters that would have been written\n+ * excluding the final null regardless of the buffer size.\n  */\n \n char *sq_quote(const char *src);\n+size_t sq_quote_buf(char *dst, size_t n, const char *src);\n \n #endif\n"}]}