Why on earth was I creating the data file with x permission? Silly
[sgt/agedu] / httpd.c
diff --git a/httpd.c b/httpd.c
index d03e1c5..bbe82ab 100644 (file)
--- a/httpd.c
+++ b/httpd.c
@@ -2,25 +2,8 @@
  * httpd.c: implementation of httpd.h.
  */
 
-#define _GNU_SOURCE
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <errno.h>
-#include <assert.h>
-#include <unistd.h>
-#include <pwd.h>
-#include <ctype.h>
-#include <sys/types.h>
-#include <sys/wait.h>
-#include <fcntl.h>
-#include <sys/socket.h>
-#include <arpa/inet.h>
-#include <netinet/in.h>
-#include <syslog.h>
-
-#include "malloc.h"
+#include "agedu.h"
+#include "alloc.h"
 #include "html.h"
 #include "httpd.h"
 
@@ -66,7 +49,7 @@ static char *http_error(char *code, char *errmsg, char *extraheader,
 {
     return dupfmt("HTTP/1.1 %s %s\r\n"
                  "Date: %D\r\n"
-                 "Server: agedu\r\n"
+                 "Server: " PNAME "\r\n"
                  "Connection: close\r\n"
                  "%s"
                  "Content-Type: text/html; charset=US-ASCII\r\n"
@@ -87,7 +70,7 @@ static char *http_success(char *mimetype, int stuff_cr, char *document)
     return dupfmt("HTTP/1.1 200 OK\r\n"
                  "Date: %D\r\n"
                  "Expires: %D\r\n"
-                 "Server: agedu\r\n"
+                 "Server: " PNAME "\r\n"
                  "Connection: close\r\n"
                  "Content-Type: %s\r\n"
                  "\r\n"
@@ -186,7 +169,7 @@ char *got_data(struct connctx *ctx, char *data, int length,
            /* Restore the request to the way we received it. */
            *z2 = c2;
            *z1 = c1;
-           text = dupfmt("<code>agedu</code> received the HTTP request"
+           text = dupfmt("<code>" PNAME "</code> received the HTTP request"
                          " \"<code>%h</code>\", which contains no URL.",
                          line);
            ret = http_error("400", "Bad request", NULL, text);
@@ -277,10 +260,10 @@ char *got_data(struct connctx *ctx, char *data, int length,
        }
 
        if (!magic_access && !auth_correct) {
-           if (auth_string && !auth_provided) {
+           if (auth_string) {
                ret = http_error("401", "Unauthorized",
-                                "WWW-Authenticate: Basic realm=\"agedu\"\r\n",
-                                "Please authenticate to view these pages.");
+                                "WWW-Authenticate: Basic realm=\""PNAME"\"\r",
+                                "\nYou must authenticate to view these pages.");
            } else {
                ret = http_error("403", "Forbidden", NULL,
                                 "This is a restricted-access set of pages.");
@@ -420,7 +403,7 @@ static void base64_encode_atom(unsigned char *data, int n, char *out)
 void run_httpd(const void *t, int authmask, const struct httpd_config *dcfg,
               const struct html_config *incfg)
 {
-    int fd;
+    int fd, ret;
     int authtype;
     char *authstring = NULL;
     unsigned long ipaddr;
@@ -429,7 +412,7 @@ void run_httpd(const void *t, int authmask, const struct httpd_config *dcfg,
     socklen_t addrlen;
     struct html_config cfg = *incfg;
 
-    cfg.format = "%lu";
+    cfg.format = "%.0lu";
 
     /*
      * Establish the listening socket and retrieve its port
@@ -449,12 +432,24 @@ void run_httpd(const void *t, int authmask, const struct httpd_config *dcfg,
        ipaddr += (1 + rand() % 255);
        addr.sin_addr.s_addr = htonl(ipaddr);
        addr.sin_port = htons(0);
+       
     } else {
        addr.sin_addr.s_addr = inet_addr(dcfg->address);
-       addr.sin_port = dcfg->port ? htons(dcfg->port) : 80;
+       addr.sin_port = dcfg->port ? htons(dcfg->port) : 0;
     }
     addrlen = sizeof(addr);
-    if (bind(fd, (struct sockaddr *)&addr, addrlen) < 0) {
+    ret = bind(fd, (const struct sockaddr *)&addr, addrlen);
+    if (ret < 0 && errno == EADDRNOTAVAIL && !dcfg->address) {
+       /*
+        * Some systems don't like us binding to random weird
+        * localhost-space addresses. Try again with the official
+        * INADDR_LOOPBACK.
+        */
+       addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
+       addr.sin_port = htons(0);
+       ret = bind(fd, (const struct sockaddr *)&addr, addrlen);
+    }
+    if (ret < 0) {
        fprintf(stderr, "bind: %s\n", strerror(errno));
        exit(1);
     }
@@ -487,7 +482,7 @@ void run_httpd(const void *t, int authmask, const struct httpd_config *dcfg,
        if (dcfg->basicauthdata) {
            userpass = dcfg->basicauthdata;
        } else {
-           sprintf(username, "agedu");
+           strcpy(username, PNAME);
            rname = "/dev/urandom";
            fd = open(rname, O_RDONLY);
            if (fd < 0) {
@@ -551,16 +546,16 @@ void run_httpd(const void *t, int authmask, const struct httpd_config *dcfg,
        if (authmask != HTTPD_AUTH_NONE)
            printf("Web server is unauthenticated\n");
     } else {
-       fprintf(stderr, "agedu: authentication method not supported\n");
+       fprintf(stderr, PNAME ": authentication method not supported\n");
        exit(1);
     }
-    if (!dcfg->address) {
-       if (ntohs(addr.sin_port) == 80) {
-           printf("URL: http://%s/\n", inet_ntoa(addr.sin_addr));
-       } else {
-           printf("URL: http://%s:%d/\n",
-                  inet_ntoa(addr.sin_addr), ntohs(addr.sin_port));
-       }
+    if (ntohs(addr.sin_addr.s_addr) == INADDR_ANY) {
+       printf("Server port: %d\n", ntohs(addr.sin_port));
+    } else if (ntohs(addr.sin_port) == 80) {
+       printf("URL: http://%s/\n", inet_ntoa(addr.sin_addr));
+    } else {
+       printf("URL: http://%s:%d/\n",
+              inet_ntoa(addr.sin_addr), ntohs(addr.sin_port));
     }
 
     /*
@@ -580,7 +575,9 @@ void run_httpd(const void *t, int authmask, const struct httpd_config *dcfg,
      */
     while (1) {
        fd_set rfds, wfds;
-       int i, j, maxfd, ret;
+       int i, j;
+       SELECT_TYPE_ARG1 maxfd;
+       int ret;
 
 #define FD_SET_MAX(fd, set, max) \
         do { FD_SET((fd),(set)); (max) = ((max)<=(fd)?(fd)+1:(max)); } while(0)
@@ -604,6 +601,8 @@ void run_httpd(const void *t, int authmask, const struct httpd_config *dcfg,
 
            switch (fds[i].type) {
              case FD_CLIENT:
+               FD_SET_MAX(fds[i].fd, &rfds, maxfd);
+               break;
              case FD_LISTENER:
                FD_SET_MAX(fds[i].fd, &rfds, maxfd);
                break;
@@ -629,7 +628,9 @@ void run_httpd(const void *t, int authmask, const struct httpd_config *dcfg,
        }
        nfds = i;
 
-        ret = select(maxfd, &rfds, &wfds, NULL, NULL);
+        ret = select(maxfd, SELECT_TYPE_ARG234 &rfds,
+                    SELECT_TYPE_ARG234 &wfds, SELECT_TYPE_ARG234 NULL,
+                    SELECT_TYPE_ARG5 NULL);
        if (ret <= 0) {
            if (ret < 0 && (errno != EINTR)) {
                fprintf(stderr, "select: %s", strerror(errno));