
Property changes on: src
___________________________________________________________________
Name: svn:ignore
   - commands-list.h
config.h
libdebconf.so*
libdebconfclient.so*
*.a
debconf
debconf-communicate
debconf-copydb
debconf-dumpdb
debconf-loadtemplate
dpkg-reconfigure
debconf.conf
cdebconf.conf-dist
*.opic
Makefile
*.o

   + commands-list.h
config.h
libdebconf.so*
libdebconfclient.so*
*.a
debconf
debconf-communicate
debconf-copydb
debconf-dumpdb
debconf-escape
debconf-loadtemplate
dpkg-reconfigure
debconf.conf
cdebconf.conf-dist
*.opic
Makefile
*.o


Index: src/Makefile.in
===================================================================
--- src/Makefile.in	(revision 50731)
+++ src/Makefile.in	(working copy)
@@ -13,7 +13,7 @@
 CLISONAME=$(CLILIB).$(MAJOR)
 DEBCONF=debconf
 TOOLS=debconf-loadtemplate debconf-copydb debconf-communicate \
-	debconf-dumpdb \
+	debconf-dumpdb debconf-escape \
 	dpkg-reconfigure #dpkg-preconfigure
 BIN=$(DEBCONF) $(TOOLS)
 
@@ -63,6 +63,7 @@
 	install -d -m 755 $(DESTDIR)${moddir}
 	install -m 755 debconf debconf-loadtemplate $(DESTDIR)${moddir}
 	install -m 755 debconf-copydb debconf-dumpdb $(DESTDIR)${moddir}
+	install -m 755 debconf-escape $(DESTDIR)${moddir}
 ifneq ($(TARGET),udeb)
 	install -m 755 debconf-communicate $(DESTDIR)${moddir}
 	install -m 755 dpkg-reconfigure $(DESTDIR)${moddir}
@@ -78,7 +79,7 @@
 	install -d -m 755 $(DESTDIR)${sbindir}
 	install -d -m 755 $(DESTDIR)${sharedir}
 	set -e; for p in debconf debconf-loadtemplate \
-			debconf-copydb debconf-dumpdb; do \
+			debconf-copydb debconf-dumpdb debconf-escape; do \
 		ln -sf ../lib/cdebconf/$$p $(DESTDIR)${bindir}; \
 	done
 	install -m 644 client/confmodule $(DESTDIR)${sharedir}
Index: src/commands.c
===================================================================
--- src/commands.c	(revision 50731)
+++ src/commands.c	(working copy)
@@ -127,9 +127,11 @@
             mod->frontend->capability |= DCF_CAPB_BACKUP;
         else if (strcmp(argv[i], "progresscancel") == 0)
             mod->frontend->capability |= DCF_CAPB_PROGRESSCANCEL;
+        else if (strcmp(argv[i], "escape") == 0)
+            mod->frontend->capability |= DCF_CAPB_ESCAPE;
     }
 
-    if (asprintf(&out, "%u multiselect backup progresscancel", CMDSTATUS_SUCCESS) == -1)
+    if (asprintf(&out, "%u multiselect backup progresscancel escape", CMDSTATUS_SUCCESS) == -1)
         DIE("Out of memory");
 
     plugin_state = NULL;
Index: src/frontend.h
===================================================================
--- src/frontend.h	(revision 50731)
+++ src/frontend.h	(working copy)
@@ -20,6 +20,7 @@
 
 #define DCF_CAPB_BACKUP		(1UL << 0)
 #define DCF_CAPB_PROGRESSCANCEL	(1UL << 1)
+#define DCF_CAPB_ESCAPE		(1UL << 2)
 
 struct frontend_module {
     int (*initialize)(struct frontend *, struct configuration *);
Index: src/strutl.c
===================================================================
--- src/strutl.c	(revision 50731)
+++ src/strutl.c	(working copy)
@@ -327,15 +327,15 @@
 	int i = 0;
 	while (*p != 0 && i < maxlen-1)
 	{
-		/*  Debconf only escapes \n  */
+		/* Debconf only escapes \ and \n */
 		if (*p == '\\')
 		{
-			if (*(p+1) == 'n')
+			if (*(p+1) == '\\' || *(p+1) == 'n')
 			{
-				outbuf[i++] = '\n';
+				outbuf[i++] = (*(p+1) == '\\') ? '\\' : '\n';
 				p += 2;
 			}
-			else if (quote != 0 && (*(p+1) == '"' || *(p+1) == '\\'))
+			else if (quote != 0 && *(p+1) == '"')
 			{
 				outbuf[i++] = *(p+1);
 				p += 2;
@@ -355,15 +355,15 @@
 	int i = 0;
 	while (*p != 0 && i < maxlen-1)
 	{
-		/*  Debconf only escapes \n  */
-		if (*p == '\n')
+		/* Debconf only escapes \ and \n */
+		if (*p == '\\' || *p == '\n')
 		{
 			if (i + 2 >= maxlen) break;
 			outbuf[i++] = '\\';
-			outbuf[i++] = 'n';
+			outbuf[i++] = (*p == '\\') ? '\\' : 'n';
 			p++;
 		}
-		else if (quote != 0 && (*p == '"' || *p == '\\'))
+		else if (quote != 0 && *p == '"')
 		{
 			if (i + 2 >= maxlen) break;
 			outbuf[i++] = '\\';
Index: src/debconf-escape.c
===================================================================
--- src/debconf-escape.c	(revision 0)
+++ src/debconf-escape.c	(revision 0)
@@ -0,0 +1,130 @@
+/**
+ * @file debconf-escape.c
+ * @brief helper when working with debconf's escape capability
+ */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <getopt.h>
+
+static int escape = 0;
+static int unescape = 0;
+
+static struct option options[] = {
+    { "help", 0, 0, 'h' },
+    { "escape", 0, &escape, 'e' },
+    { "unescape", 0, &unescape, 'u' },
+    { 0, 0, 0, 0 },
+};
+
+static void help(FILE *f, const char *exename)
+{
+    fprintf(f, "%s -e|-u < input-text\n", exename);
+}
+
+static void parsecmdline(int argc, char **argv)
+{
+    int c;
+
+    while ((c = getopt_long(argc, argv, "eu", options, NULL)) != -1)
+    {
+        switch (c)
+        {
+            case 'h':
+                help(stdout, argv[0]);
+                exit(0);
+                break;
+            case 'e':
+                escape = 1;
+                break;
+            case 'u':
+                unescape = 1;
+                break;
+            default:
+                break;
+        }
+    }
+
+    if (optind > argc || escape == unescape)
+    {
+        help(stderr, argv[0]);
+        exit(1);
+    }
+}
+
+int main(int argc, char **argv)
+{
+    char buf[1024];
+    const char *p;
+    size_t r;
+
+    parsecmdline(argc, argv);
+
+    if (escape)
+    {
+        while (!feof(stdin) && !ferror(stdin))
+        {
+            r = fread(buf, sizeof(*buf), 1024, stdin);
+            for (p = buf; p < buf + r; ++p)
+            {
+                switch (*p)
+                {
+                    case '\\':
+                        fputs("\\\\", stdout);
+                        break;
+                    case '\n':
+                        fputs("\\n", stdout);
+                        break;
+                    default:
+                        fputc(*p, stdout);
+                        break;
+                }
+            }
+        }
+    }
+    else
+    {
+        while (!feof(stdin) && !ferror(stdin))
+        {
+            const char *pos, *backslash;
+            r = fread(buf, sizeof(*buf), 1024, stdin);
+            pos = buf;
+            while (r > 0)
+            {
+                backslash = memchr(pos, '\\', r);
+                if (!backslash)
+                {
+                    fwrite(pos, sizeof(*pos), r, stdout);
+                    break;
+                }
+                if (backslash - pos > 0)
+                    fwrite(pos, sizeof(*pos), backslash - pos, stdout);
+                if (backslash - pos == r - 1)
+                {
+                    fputc('\\', stdout);
+                    break;
+                }
+                else
+                {
+                    if (*(backslash + 1) == '\n')
+                        fputs("\\\n", stdout);
+                    else if (*(backslash + 1) == 'n')
+                        fputc('\n', stdout);
+                    else
+                        fputc(*(backslash + 1), stdout);
+                    r -= (backslash + 2 - pos);
+                    pos = backslash + 2;
+                }
+            }
+        }
+    }
+
+    if (ferror(stdin))
+    {
+        fprintf(stderr, "%s: error reading stdin\n", argv[0]);
+        return 1;
+    }
+
+    return 0;
+}
Index: src/strutl.h
===================================================================
--- src/strutl.h	(revision 50731)
+++ src/strutl.h	(working copy)
@@ -46,7 +46,7 @@
 int strgetargc(const char *inbuf);
 int strchoicesplit(const char *inbuf, char **argv, size_t maxnarg);
 int strchoicesplitsort(const char *origbuf, const char *transbuf, const char *listorder, char **oargv, char **targv, int *tindex, size_t maxnarg);
-int strcmdsplit(char *inbuf, char **argv, size_t maxnarg);
+int strcmdsplit(char *inbuf, char **argv, size_t maxnarg, int unescape);
 void strunescape(const char *inbuf, char *outbuf, const size_t maxlen, const int quote);
 void strescape(const char *inbuf, char *outbuf, const size_t maxlen, const int quote);
 char *unescapestr(const char *in);
