TODO list for agedu
===================
- - adjust the default web server address selection.
- + some systems (e.g. OS X) don't like us binding to random
- localhost addresses. So if that fails, try falling back to
- 127.0.0.1 proper (and a randomly selected port) before giving
- up.
- + since binding to port 80 isn't generally feasible, we should
- adjust the default behaviour when the user specifies --addr
- with no port: it should select port zero, and then print the
- port number on standard output. (Possibly also print the URL
- as usual, in that situation: translate INADDR_ANY to
- INADDR_LOOPBACK and then do the same as when we made the
- entire address up ourself.)
-
- we should munmap in all operating modes where we mmapped,
otherwise chaining them will run out of address space
\cw{agedu} should listen when running its web server. If you want
\cw{agedu} to listen for connections coming in from any source, you
should probably specify the special IP address \cw{0.0.0.0}. If the
-port number is omitted, it will be assumed to be 80 (for which
-\cw{agedu} will probably need to be running as a privileged user).
+port number is omitted, an arbitrary unused port will be chosen for
+you and displayed.
\lcont{
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));
}
/*
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;