>From 9dd1afa561fa85377eed34126b17ee2ed2d896b3 Mon Sep 17 00:00:00 2001
From: Tamas TEVESZ <[email protected]>
Date: Tue, 12 Oct 2010 18:38:45 +0200
Subject: [PATCH] WINGs: Add wshellquote()

Transforms its argument so that the result is safe to pass to the shell
as an argument.

With very heavy inspirations from NetBSD's shquote(3),
http://cvsweb.netbsd.org/bsdweb.cgi/src/lib/libc/gen/shquote.c?annotate
http://man.netbsd.org/cgi-bin/man-cgi?shquote

Signed-off-by: Tamas TEVESZ <[email protected]>
---
 WINGs/WINGs/WUtil.h |    6 ++++
 WINGs/string.c      |   67 +++++++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 73 insertions(+), 0 deletions(-)

diff --git a/WINGs/WINGs/WUtil.h b/WINGs/WINGs/WUtil.h
index b78cc85..f3131c5 100644
--- a/WINGs/WINGs/WUtil.h
+++ b/WINGs/WINGs/WUtil.h
@@ -243,6 +243,12 @@ void wtokenfree(char **tokens, int count);
 
 char* wtrimspace(const char *s);
 
+/* transform `s' so that the result is safe to pass to the shell as an 
argument.
+ * returns a newly allocated string.
+ * with very heavy inspirations from NetBSD's shquote(3).
+ */
+char *wshellquote(const char *s);
+
 /* ---[ WINGs/wmisc.c ]--------------------------------------------------- */
 
 WMRange wmkrange(int start, int count);
diff --git a/WINGs/string.c b/WINGs/string.c
index d604fff..8629d77 100644
--- a/WINGs/string.c
+++ b/WINGs/string.c
@@ -352,3 +352,70 @@ wstrlcpy(char *dst, const char *src, size_t siz)
        return(s - src - 1);    /* count does not include NUL */
 }
 #endif /* HAVE_STRLCPY */
+
+/* transform `s' so that the result is safe to pass to the shell as an 
argument.
+ * returns a newly allocated string.
+ * with very heavy inspirations from NetBSD's shquote(3).
+ */
+char *wshellquote(const char *s)
+{
+       char *p, *r, *last, *ret;
+       size_t slen;
+       int needs_quoting;
+
+       if (!s)
+               return NULL;
+
+       needs_quoting = !*s;                    /* the empty string does need 
quoting */
+
+       /* do not quote if consists only of the following characters */
+       for (p = (char *)s; *p && !needs_quoting; p++) {
+               needs_quoting = !(isalnum(*p) || (*p == '+') || (*p == '/') ||
+                                (*p == '.') || (*p == ',') || (*p == '-'));
+       }
+
+       if (!needs_quoting)
+               return wstrdup(s);
+
+       for (slen = 0, p = (char *)s; *p; p++)          /* count space needed 
(worst case) */
+               slen += *p == '\'' ? 4 : 1;             /* every single ' 
becomes ''\' */
+
+       slen += 2 /* leading + trailing "'" */ + 1 /* NULL */;
+
+       ret = r = wmalloc(slen);
+       p = (char *)s;
+       last = p;
+
+       if (*p != '\'')                                 /* if string doesn't 
already begin with "'" */
+               *r++ ='\'';                             /* start putting it in 
quotes */
+
+       while (*p) {
+               last = p;
+               if (*p == '\'') {                       /* turn each ' into 
''\' */
+                       if (p != s)                     /* except if it's the 
first ', in which case */
+                               *r++ = '\'';            /* only escape it */
+                       *r++ = '\\';
+                       *r++ = '\'';
+                       while (*++p && *p == '\'') {    /* keep turning each 
consecutive 's into \' */
+                               *r++ = '\\';
+                               *r++ = '\'';
+                       }
+                       if (*p)                         /* if more input 
follows, terminate */
+                               *r++ = '\'';            /* what we have so far 
*/
+               } else {
+                       *r++ = *p++;
+               }
+       }
+
+       if (*last != '\'')                              /* if the last one 
isn't already a ' */
+               *r++ = '\'';                            /* terminate the whole 
shebang */
+
+       *r = '\0';
+
+       return ret;                                     /* technically, we lose 
(but not leak) a couple of */
+                                                       /* bytes (twice the 
number of consecutive 's in the */
+                                                       /* input or so), but 
since these are relatively rare */
+                                                       /* and short-lived 
strings, not sure if a trip to */
+                                                       /* wstrdup+wfree worths 
the gain. */
+}
+
-- 
1.7.0.4


-- 
[-]

mkdir /nonexistent
From 9dd1afa561fa85377eed34126b17ee2ed2d896b3 Mon Sep 17 00:00:00 2001
From: Tamas TEVESZ <[email protected]>
Date: Tue, 12 Oct 2010 18:38:45 +0200
Subject: [PATCH] WINGs: Add wshellquote()

Transforms its argument so that the result is safe to pass to the shell
as an argument.

With very heavy inspirations from NetBSD's shquote(3),
http://cvsweb.netbsd.org/bsdweb.cgi/src/lib/libc/gen/shquote.c?annotate
http://man.netbsd.org/cgi-bin/man-cgi?shquote

Signed-off-by: Tamas TEVESZ <[email protected]>
---
 WINGs/WINGs/WUtil.h |    6 ++++
 WINGs/string.c      |   67 +++++++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 73 insertions(+), 0 deletions(-)

diff --git a/WINGs/WINGs/WUtil.h b/WINGs/WINGs/WUtil.h
index b78cc85..f3131c5 100644
--- a/WINGs/WINGs/WUtil.h
+++ b/WINGs/WINGs/WUtil.h
@@ -243,6 +243,12 @@ void wtokenfree(char **tokens, int count);
 
 char* wtrimspace(const char *s);
 
+/* transform `s' so that the result is safe to pass to the shell as an argument.
+ * returns a newly allocated string.
+ * with very heavy inspirations from NetBSD's shquote(3).
+ */
+char *wshellquote(const char *s);
+
 /* ---[ WINGs/wmisc.c ]--------------------------------------------------- */
 
 WMRange wmkrange(int start, int count);
diff --git a/WINGs/string.c b/WINGs/string.c
index d604fff..8629d77 100644
--- a/WINGs/string.c
+++ b/WINGs/string.c
@@ -352,3 +352,70 @@ wstrlcpy(char *dst, const char *src, size_t siz)
 	return(s - src - 1);	/* count does not include NUL */
 }
 #endif /* HAVE_STRLCPY */
+
+/* transform `s' so that the result is safe to pass to the shell as an argument.
+ * returns a newly allocated string.
+ * with very heavy inspirations from NetBSD's shquote(3).
+ */
+char *wshellquote(const char *s)
+{
+	char *p, *r, *last, *ret;
+	size_t slen;
+	int needs_quoting;
+
+	if (!s)
+		return NULL;
+
+	needs_quoting = !*s;			/* the empty string does need quoting */
+
+	/* do not quote if consists only of the following characters */
+	for (p = (char *)s; *p && !needs_quoting; p++) {
+		needs_quoting = !(isalnum(*p) || (*p == '+') || (*p == '/') ||
+				 (*p == '.') || (*p == ',') || (*p == '-'));
+	}
+
+	if (!needs_quoting)
+		return wstrdup(s);
+
+	for (slen = 0, p = (char *)s; *p; p++)		/* count space needed (worst case) */
+		slen += *p == '\'' ? 4 : 1;		/* every single ' becomes ''\' */
+
+	slen += 2 /* leading + trailing "'" */ + 1 /* NULL */;
+
+	ret = r = wmalloc(slen);
+	p = (char *)s;
+	last = p;
+
+	if (*p != '\'')					/* if string doesn't already begin with "'" */
+		*r++ ='\'';				/* start putting it in quotes */
+
+	while (*p) {
+		last = p;
+		if (*p == '\'') {			/* turn each ' into ''\' */
+			if (p != s)			/* except if it's the first ', in which case */
+				*r++ = '\'';		/* only escape it */
+			*r++ = '\\';
+			*r++ = '\'';
+			while (*++p && *p == '\'') {	/* keep turning each consecutive 's into \' */
+				*r++ = '\\';
+				*r++ = '\'';
+			}
+			if (*p)				/* if more input follows, terminate */
+				*r++ = '\'';		/* what we have so far */
+		} else {
+			*r++ = *p++;
+		}
+	}
+
+	if (*last != '\'')				/* if the last one isn't already a ' */
+		*r++ = '\'';				/* terminate the whole shebang */
+
+	*r = '\0';
+
+	return ret;					/* technically, we lose (but not leak) a couple of */
+							/* bytes (twice the number of consecutive 's in the */
+							/* input or so), but since these are relatively rare */
+							/* and short-lived strings, not sure if a trip to */
+							/* wstrdup+wfree worths the gain. */
+}
+
-- 
1.7.0.4

Reply via email to