Restyle and add printflike.

This commit is contained in:
Emil Mikulic 2011-01-15 18:37:15 +11:00
parent 8d11e14d11
commit 1fa02dc545

View File

@ -75,6 +75,15 @@ static const int debug = 1;
#define O_EXLOCK O_EXCL #define O_EXLOCK O_EXCL
#endif #endif
#ifdef __GNUC__
/* [->] borrowed from FreeBSD's src/sys/sys/cdefs.h,v 1.102.2.2.2.1 */
#define __printflike(fmtarg, firstvararg) \
__attribute__((__format__(__printf__, fmtarg, firstvararg)))
/* [<-] */
#else
#define __printflike(fmtarg, firstvararg)
#endif
/* [->] borrowed from FreeBSD's src/sys/sys/systm.h,v 1.276.2.7.4.1 */ /* [->] borrowed from FreeBSD's src/sys/sys/systm.h,v 1.276.2.7.4.1 */
#ifndef CTASSERT /* Allow lint to override */ #ifndef CTASSERT /* Allow lint to override */
#define CTASSERT(x) _CTASSERT(x, __LINE__) #define CTASSERT(x) _CTASSERT(x, __LINE__)
@ -91,49 +100,45 @@ CTASSERT(sizeof(unsigned long long) >= sizeof(off_t));
/* err - prints "error: format: strerror(errno)" to stderr and exit()s with /* err - prints "error: format: strerror(errno)" to stderr and exit()s with
* the given code. * the given code.
*/ */
static void static void err(const int code, const char *format, ...) __printflike(2, 3);
err(const int code, const char *format, ...) static void err(const int code, const char *format, ...) {
{ va_list va;
va_list va;
va_start(va, format); va_start(va, format);
fprintf(stderr, "error: "); fprintf(stderr, "error: ");
vfprintf(stderr, format, va); vfprintf(stderr, format, va);
fprintf(stderr, ": %s\n", strerror(errno)); fprintf(stderr, ": %s\n", strerror(errno));
va_end(va); va_end(va);
exit(code); exit(code);
} }
/* errx - err without the strerror */ /* errx - err() without the strerror */
static void static void errx(const int code, const char *format, ...) __printflike(2, 3);
errx(const int code, const char *format, ...) static void errx(const int code, const char *format, ...) {
{ va_list va;
va_list va;
va_start(va, format); va_start(va, format);
fprintf(stderr, "error: "); fprintf(stderr, "error: ");
vfprintf(stderr, format, va); vfprintf(stderr, format, va);
fprintf(stderr, "\n"); fprintf(stderr, "\n");
va_end(va); va_end(va);
exit(code); exit(code);
} }
/* warn - err without the exit */ /* warn - err() without the exit */
static void static void warn(const char *format, ...) __printflike(1, 2);
warn(const char *format, ...) static void warn(const char *format, ...) {
{ va_list va;
va_list va;
va_start(va, format); va_start(va, format);
fprintf(stderr, "warning: "); fprintf(stderr, "warning: ");
vfprintf(stderr, format, va); vfprintf(stderr, format, va);
fprintf(stderr, ": %s\n", strerror(errno)); fprintf(stderr, ": %s\n", strerror(errno));
va_end(va); va_end(va);
} }
#endif #endif
/* --------------------------------------------------------------------------- /* [->] LIST_* macros taken from FreeBSD's src/sys/sys/queue.h,v 1.56
* LIST_* macros taken from FreeBSD's src/sys/sys/queue.h,v 1.56
* Copyright (c) 1991, 1993 * Copyright (c) 1991, 1993
* The Regents of the University of California. All rights reserved. * The Regents of the University of California. All rights reserved.
* *
@ -184,15 +189,12 @@ struct { \
(elm)->field.le_prev; \ (elm)->field.le_prev; \
*(elm)->field.le_prev = LIST_NEXT((elm), field); \ *(elm)->field.le_prev = LIST_NEXT((elm), field); \
} while (0) } while (0)
/* ------------------------------------------------------------------------ */ /* [<-] */
LIST_HEAD(conn_list_head, connection) connlist = LIST_HEAD(conn_list_head, connection) connlist =
LIST_HEAD_INITIALIZER(conn_list_head); LIST_HEAD_INITIALIZER(conn_list_head);
struct connection struct connection {
{
LIST_ENTRY(connection) entries; LIST_ENTRY(connection) entries;
int socket; int socket;
@ -203,7 +205,7 @@ struct connection
SEND_HEADER, /* sending generated header */ SEND_HEADER, /* sending generated header */
SEND_REPLY, /* sending reply */ SEND_REPLY, /* sending reply */
DONE /* connection closed, need to remove from queue */ DONE /* connection closed, need to remove from queue */
} state; } state;
/* char request[request_length+1] is null-terminated */ /* char request[request_length+1] is null-terminated */
char *request; char *request;
@ -251,8 +253,6 @@ static time_t now;
*/ */
#define MAX_REQUEST_LENGTH 4000 #define MAX_REQUEST_LENGTH 4000
/* Defaults can be overridden on the command-line */ /* Defaults can be overridden on the command-line */
static in_addr_t bindaddr = INADDR_ANY; static in_addr_t bindaddr = INADDR_ANY;
static unsigned short bindport = 80; static unsigned short bindport = 80;
@ -299,8 +299,6 @@ static const char *default_extension_map[] = {
static const char default_mimetype[] = "application/octet-stream"; static const char default_mimetype[] = "application/octet-stream";
/* Connection or Keep-Alive field, depending on conn_close. */ /* Connection or Keep-Alive field, depending on conn_close. */
#define keep_alive(conn) ((conn)->conn_close ? \ #define keep_alive(conn) ((conn)->conn_close ? \
"Connection: close\r\n" : keep_alive_field) "Connection: close\r\n" : keep_alive_field)
@ -310,59 +308,40 @@ static void poll_recv_request(struct connection *conn);
static void poll_send_header(struct connection *conn); static void poll_send_header(struct connection *conn);
static void poll_send_reply(struct connection *conn); static void poll_send_reply(struct connection *conn);
/* close() that dies on error. */
static void xclose(const int fd) {
/* --------------------------------------------------------------------------- if (close(fd) == -1)
* close that dies on error. err(1, "close()");
*/
static void xclose(const int fd)
{
if (close(fd) == -1) err(1, "close()");
} }
/* malloc that dies if it can't allocate. */
static void *xmalloc(const size_t size) {
/* ---------------------------------------------------------------------------
* malloc that errx()s if it can't allocate.
*/
static void *xmalloc(const size_t size)
{
void *ptr = malloc(size); void *ptr = malloc(size);
if (ptr == NULL) errx(1, "can't allocate %u bytes", size); if (ptr == NULL)
errx(1, "can't allocate %u bytes", size);
return ptr; return ptr;
} }
/* realloc() that dies if it can't reallocate. */
static void *xrealloc(void *original, const size_t size) {
/* ---------------------------------------------------------------------------
* realloc() that errx()s if it can't allocate.
*/
static void *xrealloc(void *original, const size_t size)
{
void *ptr = realloc(original, size); void *ptr = realloc(original, size);
if (ptr == NULL) errx(1, "can't reallocate %u bytes", size); if (ptr == NULL)
errx(1, "can't reallocate %u bytes", size);
return ptr; return ptr;
} }
/* strdup() that dies if it can't allocate.
* Implement this ourselves since regular strdup() isn't C89.
/* ---------------------------------------------------------------------------
* strdup() that errx()s if it can't allocate. Do this by hand since strdup()
* isn't C89.
*/ */
static char *xstrdup(const char *src) static char *xstrdup(const char *src) {
{
size_t len = strlen(src) + 1; size_t len = strlen(src) + 1;
char *dest = xmalloc(len); char *dest = xmalloc(len);
memcpy(dest, src, len); memcpy(dest, src, len);
return dest; return dest;
} }
#ifdef __sun /* unimpressed by Solaris */ #ifdef __sun /* unimpressed by Solaris */
static int vasprintf(char **strp, const char *fmt, va_list ap) static int vasprintf(char **strp, const char *fmt, va_list ap) {
{
char tmp; char tmp;
int result = vsnprintf(&tmp, 1, fmt, ap); int result = vsnprintf(&tmp, 1, fmt, ap);
*strp = xmalloc(result+1); *strp = xmalloc(result+1);
@ -371,25 +350,20 @@ static int vasprintf(char **strp, const char *fmt, va_list ap)
} }
#endif #endif
/* vasprintf() that dies if it fails. */
/* ---------------------------------------------------------------------------
* vasprintf() that errx()s if it fails.
*/
static unsigned int xvasprintf(char **ret, const char *format, va_list ap) static unsigned int xvasprintf(char **ret, const char *format, va_list ap)
{ __printflike(2,0);
static unsigned int xvasprintf(char **ret, const char *format, va_list ap) {
int len = vasprintf(ret, format, ap); int len = vasprintf(ret, format, ap);
if (ret == NULL || len == -1) errx(1, "out of memory in vasprintf()"); if (ret == NULL || len == -1)
errx(1, "out of memory in vasprintf()");
return (unsigned int)len; return (unsigned int)len;
} }
/* asprintf() that dies if it fails. */
/* ---------------------------------------------------------------------------
* asprintf() that errx()s if it fails.
*/
static unsigned int xasprintf(char **ret, const char *format, ...) static unsigned int xasprintf(char **ret, const char *format, ...)
{ __printflike(2,3);
static unsigned int xasprintf(char **ret, const char *format, ...) {
va_list va; va_list va;
unsigned int len; unsigned int len;
@ -399,24 +373,17 @@ static unsigned int xasprintf(char **ret, const char *format, ...)
return len; return len;
} }
/* Append buffer code. A somewhat efficient string buffer with pool-based
/* ---------------------------------------------------------------------------
* Append buffer code. A somewhat efficient string buffer with pool-based
* reallocation. * reallocation.
*/ */
#define APBUF_INIT 4096 #define APBUF_INIT 4096
#define APBUF_GROW APBUF_INIT #define APBUF_GROW APBUF_INIT
struct apbuf struct apbuf {
{
size_t length, pool; size_t length, pool;
char *str; char *str;
}; };
static struct apbuf *make_apbuf(void) {
static struct apbuf *make_apbuf(void)
{
struct apbuf *buf = xmalloc(sizeof(struct apbuf)); struct apbuf *buf = xmalloc(sizeof(struct apbuf));
buf->length = 0; buf->length = 0;
buf->pool = APBUF_INIT; buf->pool = APBUF_INIT;
@ -426,9 +393,10 @@ static struct apbuf *make_apbuf(void)
/* Append s (of length len) to buf. */ /* Append s (of length len) to buf. */
static void appendl(struct apbuf *buf, const char *s, const size_t len) { static void appendl(struct apbuf *buf, const char *s, const size_t len) {
if (buf->pool < buf->length + len) { size_t need = buf->length + len;
if (buf->pool < need) {
/* pool has dried up */ /* pool has dried up */
while (buf->pool < buf->length + len) while (buf->pool < need)
buf->pool += APBUF_GROW; buf->pool += APBUF_GROW;
buf->str = xrealloc(buf->str, buf->pool); buf->str = xrealloc(buf->str, buf->pool);
} }
@ -446,7 +414,8 @@ static void append(struct apbuf *buf, const char *s) {
#endif #endif
static void appendf(struct apbuf *buf, const char *format, ...) static void appendf(struct apbuf *buf, const char *format, ...)
{ __printflike(2, 3);
static void appendf(struct apbuf *buf, const char *format, ...) {
char *tmp; char *tmp;
va_list va; va_list va;
size_t len; size_t len;
@ -454,19 +423,12 @@ static void appendf(struct apbuf *buf, const char *format, ...)
va_start(va, format); va_start(va, format);
len = xvasprintf(&tmp, format, va); len = xvasprintf(&tmp, format, va);
va_end(va); va_end(va);
appendl(buf, tmp, len); appendl(buf, tmp, len);
free(tmp); free(tmp);
} }
/* Make the specified socket non-blocking. */
static void nonblock_socket(const int sock) {
/* ---------------------------------------------------------------------------
* Make the specified socket non-blocking.
*/
static void
nonblock_socket(const int sock)
{
int flags = fcntl(sock, F_GETFL, NULL); int flags = fcntl(sock, F_GETFL, NULL);
if (flags == -1) if (flags == -1)
@ -476,14 +438,9 @@ nonblock_socket(const int sock)
err(1, "fcntl() to set O_NONBLOCK"); err(1, "fcntl() to set O_NONBLOCK");
} }
/* Split string out of src with range [left:right-1] */
/* ---------------------------------------------------------------------------
* Split string out of src with range [left:right-1]
*/
static char *split_string(const char *src, static char *split_string(const char *src,
const size_t left, const size_t right) const size_t left, const size_t right) {
{
char *dest; char *dest;
assert(left <= right); assert(left <= right);
assert(left < strlen(src)); /* [left means must be smaller */ assert(left < strlen(src)); /* [left means must be smaller */
@ -495,47 +452,35 @@ static char *split_string(const char *src,
return dest; return dest;
} }
/* Consolidate slashes in-place by shifting parts of the string over repeated
/* ---------------------------------------------------------------------------
* Consolidate slashes in-place by shifting parts of the string over repeated
* slashes. * slashes.
*/ */
static void consolidate_slashes(char *s) static void consolidate_slashes(char *s) {
{
size_t left = 0, right = 0; size_t left = 0, right = 0;
int saw_slash = 0; int saw_slash = 0;
assert(s != NULL); assert(s != NULL);
while (s[right] != '\0') {
while (s[right] != '\0') if (saw_slash) {
{ if (s[right] == '/')
if (saw_slash) right++;
{ else {
if (s[right] == '/') right++;
else
{
saw_slash = 0; saw_slash = 0;
s[left++] = s[right++]; s[left++] = s[right++];
} }
} } else {
else if (s[right] == '/')
{ saw_slash++;
if (s[right] == '/') saw_slash++;
s[left++] = s[right++]; s[left++] = s[right++];
} }
} }
s[left] = '\0'; s[left] = '\0';
} }
/* Resolve /./ and /../ in a URI, in-place. Returns NULL if the URI is
/* ---------------------------------------------------------------------------
* Resolve /./ and /../ in a URI, in-place. Returns NULL if the URI is
* invalid/unsafe, or the original buffer if successful. * invalid/unsafe, or the original buffer if successful.
*/ */
static char *make_safe_uri(char *uri) static char *make_safe_uri(char *uri) {
{
struct { struct {
char *start; char *start;
size_t len; size_t len;
@ -545,7 +490,8 @@ static char *make_safe_uri(char *uri)
int ends_in_slash; int ends_in_slash;
assert(uri != NULL); assert(uri != NULL);
if (uri[0] != '/') return NULL; if (uri[0] != '/')
return NULL;
consolidate_slashes(uri); consolidate_slashes(uri);
urilen = strlen(uri); urilen = strlen(uri);
if (urilen > 0) if (urilen > 0)
@ -555,7 +501,8 @@ static char *make_safe_uri(char *uri)
/* count the slashes */ /* count the slashes */
for (i=0, num_slashes=0; i<urilen; i++) for (i=0, num_slashes=0; i<urilen; i++)
if (uri[i] == '/') num_slashes++; if (uri[i] == '/')
num_slashes++;
/* make an array for the URI elements */ /* make an array for the URI elements */
chunks = xmalloc(sizeof(*chunks) * num_slashes); chunks = xmalloc(sizeof(*chunks) * num_slashes);
@ -602,32 +549,29 @@ static char *make_safe_uri(char *uri)
} }
free(chunks); free(chunks);
if ((num_chunks == 0) || ends_in_slash) uri[pos++] = '/'; if ((num_chunks == 0) || ends_in_slash)
uri[pos++] = '/';
assert(pos <= urilen); assert(pos <= urilen);
uri[pos] = '\0'; uri[pos] = '\0';
return uri; return uri;
} }
/* Associates an extension with a mimetype in the mime_map. Entries are in
/* ---------------------------------------------------------------------------
* Associates an extension with a mimetype in the mime_map. Entries are in
* unsorted order. Makes copies of extension and mimetype strings. * unsorted order. Makes copies of extension and mimetype strings.
*/ */
static void add_mime_mapping(const char *extension, const char *mimetype) static void add_mime_mapping(const char *extension, const char *mimetype) {
{
size_t i; size_t i;
assert(strlen(extension) > 0); assert(strlen(extension) > 0);
assert(strlen(mimetype) > 0); assert(strlen(mimetype) > 0);
/* update longest_ext */ /* update longest_ext */
i = strlen(extension); i = strlen(extension);
if (i > longest_ext) longest_ext = i; if (i > longest_ext)
longest_ext = i;
/* look through list and replace an existing entry if possible */ /* look through list and replace an existing entry if possible */
for (i=0; i<mime_map_size; i++) for (i=0; i<mime_map_size; i++)
if (strcmp(mime_map[i].extension, extension) == 0) if (strcmp(mime_map[i].extension, extension) == 0) {
{
free(mime_map[i].mimetype); free(mime_map[i].mimetype);
mime_map[i].mimetype = xstrdup(mimetype); mime_map[i].mimetype = xstrdup(mimetype);
return; return;
@ -641,26 +585,19 @@ static void add_mime_mapping(const char *extension, const char *mimetype)
mime_map[mime_map_size-1].mimetype = xstrdup(mimetype); mime_map[mime_map_size-1].mimetype = xstrdup(mimetype);
} }
/* qsort() the mime_map. The map must be sorted before it can be
* binary-searched.
/* ---------------------------------------------------------------------------
* qsort() the mime_map. The map must be sorted before it can be searched
* through.
*/ */
static int mime_mapping_cmp(const void *a, const void *b) static int mime_mapping_cmp(const void *a, const void *b) {
{
return strcmp( ((const struct mime_mapping *)a)->extension, return strcmp( ((const struct mime_mapping *)a)->extension,
((const struct mime_mapping *)b)->extension ); ((const struct mime_mapping *)b)->extension );
} }
static void sort_mime_map(void) static void sort_mime_map(void) {
{
qsort(mime_map, mime_map_size, sizeof(struct mime_mapping), qsort(mime_map, mime_map_size, sizeof(struct mime_mapping),
mime_mapping_cmp); mime_mapping_cmp);
} }
/* --------------------------------------------------------------------------- /* ---------------------------------------------------------------------------
* Parses a mime.types line and adds the parsed data to the mime_map. * Parses a mime.types line and adds the parsed data to the mime_map.
*/ */