* 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 "agedu.h"
#include "alloc.h"
#include "html.h"
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;
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);
}
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));
}
/*
*/
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)
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;
}
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));