Add httpd -v, fix ? in static URLs, and very start of CGI plumbing.
diff --git a/lib/lib.h b/lib/lib.h
index f7d723e..f27ed20 100644
--- a/lib/lib.h
+++ b/lib/lib.h
@@ -352,7 +352,7 @@
 void xsendto(int sockfd, void *buf, size_t len, struct sockaddr *dest);
 int xrecvwait(int fd, char *buf, int len, union socksaddr *sa, int timeout);
 char *escape_url(char *str, char *and);
-void unescape_url(char *str);
+char *unescape_url(char *str);
 
 // password.c
 int get_salt(char *salt, char * algo);
diff --git a/lib/net.c b/lib/net.c
index 8d3a677..533df28 100644
--- a/lib/net.c
+++ b/lib/net.c
@@ -197,18 +197,23 @@
 }
 
 // Convert %XX escapes to character (in place)
-void unescape_url(char *str)
+char *unescape_url(char *str)
 {
-  char *to;
+  char *to, *cut = strchr(str, '?');
   int i;
 
   for (to = str;;) {
     if (*str!='%' || !isxdigit(str[1]) || !isxdigit(str[2])) {
-      if (!(*to++ = *str++)) break;
+      if (str==cut) {
+        *to++ = 0;
+        str++;
+      } else if (!(*to++ = *str++)) break;
     } else {
       sscanf(++str, "%2x", &i);
       *to++ = i;
       str += 2;
     }
   }
+
+  return cut;
 }
diff --git a/toys/net/httpd.c b/toys/net/httpd.c
index f4dc464..2460dea 100644
--- a/toys/net/httpd.c
+++ b/toys/net/httpd.c
@@ -12,17 +12,22 @@
  * -ifv -p [IP:]PORT -u [USER][:GRP] -c CFGFILE
  * cgi: SERVER_PORT SERVER_NAME REMOTE_ADDR REMOTE_HOST REQUEST_METHOD
 
-USE_HTTPD(NEWTOY(httpd, ">1", TOYFLAG_USR|TOYFLAG_BIN))
+USE_HTTPD(NEWTOY(httpd, ">1v", TOYFLAG_USR|TOYFLAG_BIN))
 
 config HTTPD
   bool "httpd"
   default y
   help
-    usage: httpd [DIR]
+    usage: httpd [-e STR] [DIR]
 
     Serve contents of directory as static web pages.
+
+    -e	Escape STR as URL, printing result and exiting.
+    -d	Decode escaped STR, printing result and exiting.
+    -v	Verbose
 */
 
+#define FOR_httpd
 #include "toys.h"
 
 char *rfc1123(char *buf, time_t t)
@@ -32,23 +37,6 @@
   return buf;
 }
 
-// Stop: header time.
-void header_time(int stat, char *str, char *more)
-{
-  char buf[64];
-
-  xprintf("HTTP/1.1 %d %s\r\nServer: toybox httpd/%s\r\nDate: %s\r\n%s"
-    "Connection: close\r\n\r\n", stat, str, TOYBOX_VERSION,
-    rfc1123(buf, time(0)), more ? : "");
-}
-
-void error_time(int stat, char *str)
-{
-  header_time(stat, str, 0);
-  xprintf("<html><head><title>%d %s</title></head>"
-    "<body><h3>%d %s</h3></body></html>", stat, str, stat, str);
-}
-
 // She never told me...
 char *mime(char *file)
 {
@@ -80,6 +68,25 @@
   return toybuf;
 }
 
+// Stop: header time.
+static void header_time(int stat, char *str, char *more)
+{
+  char buf[64];
+
+  if (!more) more = "";
+  if (FLAG(v)) dprintf(2, "REPLY: %d %s\n%s\n", stat, str, more);
+  xprintf("HTTP/1.1 %d %s\r\nServer: toybox httpd/%s\r\nDate: %s\r\n%s"
+    "Connection: close\r\n\r\n", stat, str, TOYBOX_VERSION,
+    rfc1123(buf, time(0)), more);
+}
+
+static void error_time(int stat, char *str)
+{
+  header_time(stat, str, 0);
+  xprintf("<html><head><title>%d %s</title></head>"
+    "<body><h3>%d %s</h3></body></html>", stat, str, stat, str);
+}
+
 static int isunder(char *file, char *dir)
 {
   char *s1 = xabspath(dir, ABS_FILE), *s2 = xabspath(file, 0), *ss = s2;
@@ -95,8 +102,15 @@
 void handle(int infd, int outfd)
 {
   FILE *fp = fdopen(infd, "r");
-  char *s = xgetline(fp), *ss, *esc, *path, *word[3];
-  int i, fd;
+  char *s = xgetline(fp), *cut, *ss, *esc, *path, *word[3];
+  int i = sizeof(toybuf), fd;
+
+  if (!s) return;
+
+  if (!getsockname(0, (void *)&toybuf, &i)) {
+    if (FLAG(v))
+      dprintf(2, "Hello %s\n%s\n", ntop((void *)toybuf), s);
+  }
 
   // Split line into method/path/protocol
   for (i = 0, ss = s;;) {
@@ -110,6 +124,7 @@
   // Process additional http/1.1 lines
   while ((ss = xgetline(fp))) {
     i = *chomp(ss);
+    if (FLAG(v)) dprintf(2, "%s\n", ss);
 // TODO: any of
 //User-Agent: Wget/1.20.1 (linux-gnu) - do we want to log anything?
 //Accept: */* - 406 Too Snobbish
@@ -123,10 +138,11 @@
 
   if (!strcasecmp(word[0], "get")) {
     struct stat st;
+
     if (*(ss = word[1])!='/') error_time(400, "Bad Request");
     while (*ss=='/') ss++;
     if (!*ss) ss = "./";
-    else unescape_url(ss);
+    else cut = unescape_url(ss);
 
     // TODO domain.com:/path/to/blah domain2.com:/path/to/that
     if (!isunder(ss, ".") || stat(ss, &st)) error_time(404, "Not Found");