summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--FEATURES1
-rw-r--r--hittpd.c52
2 files changed, 48 insertions, 5 deletions
diff --git a/FEATURES b/FEATURES
index 5524dd8..13b23c6 100644
--- a/FEATURES
+++ b/FEATURES
@@ -13,6 +13,7 @@ Features of hittpd:
 - ~user directories
 - NCSA compatible log format
 - Connection timeouts
+- inetd(8)/s6-tcpserver mode with -i
 - Portable code
 - MIT licensed
 - less than 3kloc total
diff --git a/hittpd.c b/hittpd.c
index 2404e47..79e6de6 100644
--- a/hittpd.c
+++ b/hittpd.c
@@ -104,6 +104,7 @@ int show_index = 1;
 int only_public = 0;
 int reuse_port = 0;
 const char *custom_mimetypes = "";
+int inetd = 0;
 
 static int
 on_url(http_parser *p, const char *s, size_t l)
@@ -332,7 +333,7 @@ send_response(http_parser *p, int status, const char *msg,
 		return;
 	}
 
-	write(data->fd, buf, len);
+	write(inetd ? 1 : data->fd, buf, len);
 	accesslog(p, status);
 }
 
@@ -826,7 +827,7 @@ void
 write_client(int i)
 {
 	struct conn_data *data = &datas[i];
-	int sockfd = client[i].fd;
+	int sockfd = inetd ? 1 : client[i].fd;
 	ssize_t w = 0;
 
 	if (data->stream_fd >= 0) {
@@ -880,7 +881,7 @@ void
 read_client(int i)
 {
 	struct conn_data *data = &datas[i];
-	int sockfd = client[i].fd;
+	int sockfd = inetd ? 0 : client[i].fd;
 	ssize_t n;
 	char buf[1024];
 
@@ -933,9 +934,10 @@ main(int argc, char *argv[])
 	char *uds = 0;
 
 	int c;
-	while ((c = getopt(argc, argv, "h:m:p:qu:IHM:PRV")) != -1)
+	while ((c = getopt(argc, argv, "h:im:p:qu:IHM:PRV")) != -1)
 		switch (c) {
 		case 'h': host = optarg; break;
+		case 'i': inetd = 1; quiet = 1; break;
 		case 'm': custom_mimetypes = optarg; break;
 		case 'p': port = optarg; break;
 		case 'u': uds = optarg; break;
@@ -950,7 +952,7 @@ main(int argc, char *argv[])
 			fprintf(stderr,
 			    "Usage: %s [-h HOST] [-p PORT] [-u SOCKET] "
 			    "[-m :.ext=mime/type:...] [-M DEFAULT_MIMETYPE] "
-			    "[-IHPRVq] [DIRECTORY]\n", argv[0]);
+			    "[-iIHPRVq] [DIRECTORY]\n", argv[0]);
 			exit(1);
 		}
 
@@ -970,6 +972,46 @@ main(int argc, char *argv[])
 	int nready;
 	int r = 0;
 
+	if (inetd) {
+		accept_client(1, 0);
+		accept_client(2, 1);
+
+		client[1].fd = 0;
+		client[1].events = POLLRDNORM;
+
+		while (!stop) {
+			client[2].fd = (datas[1].state == SENDING) ? 1 : -1;
+			client[2].events = POLLWRNORM;
+
+			if (client[1].fd < 0)
+				break;
+
+			nready = poll(client + 1, 2, TIMEOUT*1000);
+
+			if (nready < 0) {
+				if (errno == EINTR) {
+					continue;   // and stop maybe
+				} else {
+					perror("poll");
+					exit(111);
+				}
+			}
+
+			if (nready == 0 || (client[1].revents & POLLNVAL))
+				break;
+
+			now = time(0);
+			httpdate(now, timestamp);
+
+			if (client[1].revents & (POLLRDNORM | POLLHUP | POLLERR))
+				read_client(1);
+			if (client[2].revents & POLLWRNORM)
+				write_client(1);
+		}
+
+		return 0;
+	}
+
 	if (uds) {
 		struct sockaddr_un addr = { 0 };
 		addr.sun_family = AF_UNIX;