for (j = 0; j < 4; j++) {
unsigned octet;
- if ((*p < '0' || *p > '9') && (*p != '/' || j == 0) && *p != 0)
+ if ((*p < '0' || *p > '9') && (*p != '/' || j == 0) && *p != '\0')
return -auto_mask;
octet = 0;
while (*p >= '0' && *p <= '9') {
}
if (*p == '.')
p++;
- if (*p != '/' && *p != 0)
+ if (*p != '/' && *p != '\0')
auto_mask += 8;
*ip = ((*ip) << 8) | octet;
}
- if (*p != 0) {
+ if (*p != '\0') {
if (*p != endc)
return -auto_mask;
p++;
- if (*p == 0)
+ if (*p == '\0')
return -auto_mask;
}
*ep = p;
}
#endif
+/*
+ * Log the connection closure and exit.
+ */
+static void log_and_exit(void) ATTRIBUTE_NORETURN;
+static void log_and_exit(void)
+{
+ if (verbose > 2)
+ bb_error_msg("closed");
+ _exit(xfunc_error_retval);
+}
+
/*
* Create and send HTTP response headers.
* The arguments are combined and sent as one write operation. Note that
* responseNum - the result code to send.
* Return result of write().
*/
-static int sendHeaders(HttpResponseNum responseNum)
+static void send_headers(HttpResponseNum responseNum)
{
static const char RFC1123FMT[] ALIGN1 = "%a, %d %b %Y %H:%M:%S GMT";
len += sprintf(iobuf + len, "Last-Modified: %s\r\n%s %"OFF_FMT"d\r\n",
tmp_str, "Content-length:", ContentLength);
}
- strcat(iobuf, "\r\n");
- len += 2;
+ iobuf[len++] = '\r';
+ iobuf[len++] = '\n';
if (infoString) {
len += sprintf(iobuf + len,
"<HTML><HEAD><TITLE>%d %s</TITLE></HEAD>\n"
i = accepted_socket;
if (i == 0)
i++; /* write to fd #1 in inetd mode */
- return full_write(i, iobuf, len);
+ if (full_write(i, iobuf, len) != len) {
+ if (verbose > 1)
+ bb_perror_msg("error");
+ log_and_exit();
+ }
}
static void send_headers_and_exit(HttpResponseNum responseNum) ATTRIBUTE_NORETURN;
static void send_headers_and_exit(HttpResponseNum responseNum)
{
- sendHeaders(responseNum);
- _exit(0);
+ send_headers(responseNum);
+ log_and_exit();
}
/*
#else
pid = fork();
#endif
- if (pid < 0)
- _exit(0);
+ if (pid < 0) {
+ /* TODO: log perror? */
+ log_and_exit();
+ }
if (!pid) {
/* child process */
*script = '\0';
/* chdiring to script's dir */
if (chdir(fullpath) == 0) {
- /* Now run the program. If it fails,
- * use _exit() so no destructors
- * get called and make a mess. */
#if ENABLE_FEATURE_HTTPD_CONFIG_WITH_SCRIPT_INTERPR
char *interpr = NULL;
char *suffix = strrchr(purl, '.');
/* send to stdout
* (we are CGI here, our stdout is pumped to the net) */
accepted_socket = 1;
- sendHeaders(HTTP_NOT_FOUND);
- _exit(242);
+ send_headers_and_exit(HTTP_NOT_FOUND);
} /* end child */
/* parent process */
fprintf(stderr, "cgi read %d bytes: '%.*s'\n", count, count, rbuf);
} /* if (FD_ISSET(fromCgi.rd)) */
} /* while (1) */
- _exit(0);
+ log_and_exit();
}
#endif /* FEATURE_HTTPD_CGI */
send_headers_and_exit(HTTP_NOT_FOUND);
}
- sendHeaders(HTTP_OK);
+ send_headers(HTTP_OK);
fd = accepted_socket;
if (fd == 0)
fd++; /* write to fd #1 in inetd mode */
/* If you want to know about EPIPE below
* (happens if you abort downloads from local httpd): */
- /* signal(SIGPIPE, SIG_IGN); */
+ signal(SIGPIPE, SIG_IGN);
#if ENABLE_FEATURE_HTTPD_USE_SENDFILE
do {
goto fin;
}
} while (count > 0);
- _exit(0);
+ log_and_exit();
fallback:
#endif
#endif
if (count < 0 && verbose > 1)
bb_perror_msg("error");
- _exit(0);
+ log_and_exit();
}
static int checkPermIP(void)
{
- Htaccess_IP * cur;
+ Htaccess_IP *cur;
/* This could stand some work */
for (cur = ip_a_d; cur; cur = cur->next) {
sigaction(SIGALRM, &sa, NULL);
alarm(HEADER_READ_TIMEOUT);
- if (!get_line())
- _exit(0); /* EOF or error or empty line */
+ if (!get_line()) {
+ /* EOF or error or empty line */
+ send_headers_and_exit(HTTP_BAD_REQUEST);
+ }
/* Determine type of request (GET/POST) */
purl = strpbrk(iobuf, " \t");
if (prequest != request_GET) {
test = iobuf + sizeof("Content-length:") - 1;
if (!test[0])
- _exit(0);
+ send_headers_and_exit(HTTP_BAD_REQUEST);
errno = 0;
/* not using strtoul: it ignores leading minus! */
length = strtol(test, &test, 10);
/* so we check for negative or too large values in one go: */
/* (long -> ulong conv caused negatives to be seen as > INT_MAX) */
if (test[0] || errno || length > INT_MAX)
- _exit(0);
+ send_headers_and_exit(HTTP_BAD_REQUEST);
}
} else if (STRNCASECMP(iobuf, "Cookie:") == 0) {
cookie = strdup(skip_whitespace(iobuf + sizeof("Cookie:")-1));
} /* while extra header reading */
}
- /* We read everything, disable peer timeout */
+ /* We read headers, disable peer timeout */
alarm(0);
if (strcmp(bb_basename(url), httpd_conf) == 0 || ip_allowed == 0) {
} while (retval > 0 && read(accepted_socket, iobuf, sizeof(iobuf) > 0));
shutdown(accepted_socket, SHUT_RD);
close(accepted_socket);
- _exit(0);
+ log_and_exit();
#endif
}
#else
parse_conf(default_path_httpd_conf, FIRST_PARSE);
#endif
+ xfunc_error_retval = 0;
if (opt & OPT_INETD)
mini_httpd_inetd();
if (!(opt & OPT_FOREGROUND))
bb_daemonize(0); /* don't change current directory */
mini_httpd(server_socket); /* never returns */
#else
+ xfunc_error_retval = 0;
mini_httpd_inetd(); /* never returns */
/* return 0; */
#endif