The more you use something them more you find about it, eh? And so we stumble upon another thttpd quirk that needs a shake-out. This time 'mercurial' throws up the challenge and thankfully it's a small enough challenge to match our skillz.

Although there's no reason for us to run 'mercurial' under 'thttpd', as it doesn't match our infrastructure (and in the end we simply run 'hg serv' rather than spawning CGI processes under an otherwise dead server) -- I became intrigued by the error and, after a little digging, it becomes apparent that 'thttpd's doing more than it's required to again. In this instance it's stripping the trailing '/' from the 'PATH_INFO' and, once again, it would be hard to say that there's anything wrong with that; however, "convention shall define" appears to be the dictat that computing is built upon and so, rather than digging into the 'mercurial' source to find out why it's doing what it's doing (surely it should be able to cope with URL path components independently of the literal string values) we simply check against apache with the following results.

# wget -O- http://my.server.rox/cgi/printenv.cgi/more/ \
        | grep PATH_INFO
PATH_INFO="/more/"

and so we simply strip the following two lines from 'libhttp.c'

static char*
expand_symlinks( char* path, char** restP, int no_symlink_check, int tildemapped )
[ ... ]
    if ( rest[restlen - 1] == '/' )
        rest[--restlen] = '\0';         /* trim trailing slash */
[ ... ]

which stops what 'thttpd' is calling 'rest' (i.e. PATH_INFO) being mangled.

It's probably also worth noting that, once again the intent of this is totally unknown and whilst it may make some sense to canonicalise (is that a word?) the PATH_INFO it doesn't deal with anything except the instance where we have a single trailing slash -- and that really doesn't make any sense.

One final note, should you really wish to run 'mercurial' under 'thttpd' using CGI, you'll probably need a further patch for the length of the GET request highlighted here here because, as best as I can tell, there's only 500 bytes allocated for it under 'thttpd' (well, that's not quite true but it probably won't grow fast enough to accommodate).

Here's a patch to try for that if you think you'll need it.

diff --git a/libhttpd.c b/libhttpd.c
index 73689be..7b252da 100644
--- a/libhttpd.c
+++ b/libhttpd.c
@@ -1663,7 +1661,7 @@ httpd_get_conn( httpd_server* hs, int listen_fd, httpd_conn* hc )
     if ( ! hc->initialized )
        {
        hc->read_size = 0;
-       httpd_realloc_str( &hc->read_buf, &hc->read_size, 500 );
+       httpd_realloc_str( &hc->read_buf, &hc->read_size, 16384 );
        hc->maxdecodedurl =
            hc->maxorigfilename = hc->maxexpnfilename = hc->maxencodings =
            hc->maxpathinfo = hc->maxquery = hc->maxaccept =

patch

diff --git a/libhttpd.c b/libhttpd.c
index 73689be..7b252da 100644
--- a/libhttpd.c
+++ b/libhttpd.c
@@ -1488,8 +1488,6 @@ expand_symlinks( char* path, char** restP, int no_symlink_check, int tildemapped
     restlen = strlen( path );
     httpd_realloc_str( &rest, &maxrest, restlen );
     (void) strcpy( rest, path );
-    if ( rest[restlen - 1] == '/' )
-       rest[--restlen] = '\0';         /* trim trailing slash */
     if ( ! tildemapped )
        /* Remove any leading slashes. */
        while ( rest[0] == '/' )