const struct html_config *cfg)
{
char *line, *p, *q, *r, *z1, *z2, c1, c2;
- int auth_provided = 0, auth_correct = 0;
+ int auth_correct = 0;
unsigned long index;
char *document, *ret;
p = q;
}
if (p < q) {
- auth_provided = 1;
while (p < q && isspace((unsigned char)*p))
p++;
r = p;
if (!magic_access && !auth_correct) {
if (auth_string) {
ret = http_error("401", "Unauthorized",
- "WWW-Authenticate: Basic realm=\""PNAME"\"\r",
+ "WWW-Authenticate: Basic realm=\""PNAME"\"\r\n",
"\nYou must authenticate to view these pages.");
} else {
ret = http_error("403", "Forbidden", NULL,
"This is a restricted-access set of pages.");
}
} else {
+ char *q;
p = ctx->url;
p += strspn(p, "/?");
- index = strtoul(p, NULL, 10);
- document = html_query(ctx->t, index, cfg);
- if (document) {
- ret = http_success("text/html", 1, document);
- sfree(document);
- } else {
+ index = strtoul(p, &q, 10);
+ if (*q) {
ret = http_error("404", "Not Found", NULL,
- "Pathname index out of range.");
+ "This is not a valid pathname index.");
+ } else {
+ document = html_query(ctx->t, index, cfg, 1);
+ if (document) {
+ ret = http_success("text/html", 1, document);
+ sfree(document);
+ } else {
+ ret = http_error("404", "Not Found", NULL,
+ "Pathname index out of range.");
+ }
}
}
return ret;
while (fgets(linebuf, sizeof(linebuf), fp)) {
if (strlen(linebuf) >= 75 &&
!strncmp(linebuf+6, matchbuf, strlen(matchbuf))) {
+ fclose(fp);
return atoi(linebuf + 75);
}
}
+ fclose(fp);
}
return -1;
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;
- struct fd *f;
struct sockaddr_in addr;
socklen_t addrlen;
struct html_config cfg = *incfg;
fprintf(stderr, "socket(PF_INET): %s\n", strerror(errno));
exit(1);
}
+ memset(&addr, 0, sizeof(addr));
addr.sin_family = AF_INET;
if (!dcfg->address) {
+#ifdef RANDOM_LOCALHOST
+ unsigned long ipaddr;
srand(0L);
ipaddr = 0x7f000000;
ipaddr += (1 + rand() % 255) << 16;
ipaddr += (1 + rand() % 255) << 8;
ipaddr += (1 + rand() % 255);
addr.sin_addr.s_addr = htonl(ipaddr);
+#else
+ addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
+#endif
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);
+#ifdef RANDOM_LOCALHOST
+ 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);
+ }
+#endif
+ 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));
}
+ fflush(stdout);
/*
* Now construct an fd structure to hold it.
*/
- f = new_fdstruct(fd, FD_LISTENER);
-
- /*
- * Read from standard input, and treat EOF as a notification
- * to exit.
- */
- new_fdstruct(0, FD_CLIENT);
+ new_fdstruct(fd, FD_LISTENER);
+
+ if (dcfg->closeoneof) {
+ /*
+ * Read from standard input, and treat EOF as a notification
+ * to exit.
+ */
+ new_fdstruct(0, FD_CLIENT);
+ }
/*
* Now we're ready to run our main loop. Keep looping round on
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;