From 1c273e0db8c0188d1bf2a9d2ff660f3fed67dd7b Mon Sep 17 00:00:00 2001
From: Fredrik Tolf <fredrik@dolda2000.com>
Date: Mon, 4 Oct 2010 09:43:41 +0200
Subject: [PATCH] sendfile: Allow file forcing and X-Ash-File-less operation.

---
 doc/sendfile.doc | 15 +++++++++++++--
 src/sendfile.c   | 26 ++++++++++++++++----------
 2 files changed, 29 insertions(+), 12 deletions(-)

diff --git a/doc/sendfile.doc b/doc/sendfile.doc
index 2d30436..3c31929 100644
--- a/doc/sendfile.doc
+++ b/doc/sendfile.doc
@@ -7,19 +7,25 @@ sendfile - Static file handler for ashd(7)
 
 SYNOPSIS
 --------
-*sendfile* [*-c* 'CONTENT-TYPE'] 'METHOD' 'URL' 'REST'
+*sendfile* [*-c* 'CONTENT-TYPE'] [*-f* 'FILE'] 'METHOD' 'URL' 'REST'
 
 DESCRIPTION
 -----------
 
 *sendfile* serves static files by sending them exactly as they are to
 clients. It needs to be called with the `X-Ash-File` header added to
-the request, as *dirplex*(1) does.
+the request, as *dirplex*(1) does, unless the *-f* option is given.
 
 *sendfile* is a transient handler, as defined in *ashd*(7), and the
 'METHOD', 'URL' and 'REST' arguments will normally be added by the
 parent handler.
 
+Normally, *sendfile* will serve the file named by the `X-Ash-File`
+header, and fail with a 404 error in case the rest string is not
+empty. However, if the *-f* argument is given, the given 'FILE' will
+always be served instead, and the `X-Ash-File` header and any rest
+string is ignored.
+
 If a MIME-type is not explicitly specified, *sendfile* uses
 *libmagic*(3) to determine the MIME-type automatically. If *sendfile*
 is compiled with support for filesystem attributes (see *attr*(5) if
@@ -43,6 +49,11 @@ OPTIONS
 	Sends 'CONTENT-TYPE' as the file's MIME-type instead of trying
 	to auto-detect the file type.
 
+*-f* 'FILE'::
+
+	Ignore the `X-Ash-File` header and force 'FILE' to be served
+	instead. Any remaining rest string is also ignored.
+
 AUTHOR
 ------
 Fredrik Tolf <fredrik@dolda2000.com>
diff --git a/src/sendfile.c b/src/sendfile.c
index 7124c25..f148196 100644
--- a/src/sendfile.c
+++ b/src/sendfile.c
@@ -141,11 +141,6 @@ static void checkcache(char *file, struct stat *sb)
     }
 }
 
-static void usage(void)
-{
-    flog(LOG_ERR, "usage: sendfile [-c CONTENT-TYPE] METHOD URL REST");
-}
-
 static void sendwhole(int fd, struct stat *sb, const char *contype, int head)
 {
     printf("HTTP/1.1 200 OK\n");
@@ -227,21 +222,32 @@ error:
     sendwhole(fd, sb, contype, head);
 }
 
+static void usage(void)
+{
+    flog(LOG_ERR, "usage: sendfile [-c CONTENT-TYPE] [-f FILE] METHOD URL REST");
+}
+
 int main(int argc, char **argv)
 {
     int c;
     char *file, *hdr;
     struct stat sb;
-    int fd, ishead;
+    int fd, ishead, ignrest;
     const char *contype;
     
     setlocale(LC_ALL, "");
     contype = NULL;
-    while((c = getopt(argc, argv, "c:")) >= 0) {
+    file = NULL;
+    ignrest = 0;
+    while((c = getopt(argc, argv, "c:f:")) >= 0) {
 	switch(c) {
 	case 'c':
 	    contype = optarg;
 	    break;
+	case 'f':
+	    file = optarg;
+	    ignrest = 1;
+	    break;
 	default:
 	    usage();
 	    exit(1);
@@ -252,11 +258,11 @@ int main(int argc, char **argv)
 	usage();
 	exit(1);
     }
-    if((file = getenv("REQ_X_ASH_FILE")) == NULL) {
-	flog(LOG_ERR, "sendfile: needs to be called with the X-Ash-File header");
+    if((file == NULL) && ((file = getenv("REQ_X_ASH_FILE")) == NULL)) {
+	flog(LOG_ERR, "sendfile: needs to be called with either the X-Ash-File header or the -f option");
 	exit(1);
     }
-    if(*argv[optind + 2]) {
+    if(!ignrest && *argv[optind + 2]) {
 	simpleerror(1, 404, "Not Found", "The requested URL has no corresponding resource.");
 	exit(0);
     }
-- 
2.11.0