logging config

This commit is contained in:
overflowerror 2019-03-13 16:01:38 +01:00
parent a9f91af3da
commit c67d7d6f78
7 changed files with 207 additions and 44 deletions

View file

@ -3,6 +3,7 @@
#include <errno.h>
#include <assert.h>
#include <stdlib.h>
#include <stdio.h>
#include "config.h"
#include "logging.h"
@ -33,6 +34,9 @@ void replaceOrAdd(void** array, int* length, void* old, void* new) {
}
struct config* config_parse(FILE* file) {
// logger is not yet set but we need error messages
setLogging(stdout, ERROR, true);
void* toFree[LENGTH_OF_TOFREE_ARRAY];
int toFreeLength = 0;
@ -45,9 +49,12 @@ struct config* config_parse(FILE* file) {
replaceOrAdd(toFree, &toFreeLength, NULL, config);
config->nrBinds = 0;
config->binds = NULL;
config->logging.accessLogfile = NULL;
config->logging.serverLogfile = NULL;
config->logging.serverVerbosity = CONFIG_DEFAULT_LOGLEVEL;
#define BIND (0)
#define ROOT (0)
#define BIND_VALUE (10)
#define BIND_BRACKETS_OPEN (11)
#define BIND_CONTENT (12)
@ -70,7 +77,15 @@ struct config* config_parse(FILE* file) {
#define TYPE_VALUE (1464)
#define INDEX_EQUALS (1465)
#define INDEX_VALUE (1466)
int state = BIND;
#define LOGGING_BRACKETS_OPEN (20)
#define LOGGING_CONTENT (21)
#define LOGGING_ACCESS_FILE_EQUALS (22)
#define LOGGING_ACCESS_FILE_VALUE (23)
#define LOGGING_SERVER_FILE_EQUALS (24)
#define LOGGING_SERVER_FILE_VALUE (25)
#define LOGGING_SERVER_VERBOSITY_EQUALS (26)
#define LOGGING_SERVER_VERBOSITY_VALUE (27)
int state = ROOT;
struct config_bind* currentBind = NULL;
struct config_site* currentSite = NULL;
@ -97,44 +112,46 @@ struct config* config_parse(FILE* file) {
char** tmpArray;
switch(state) {
case BIND:
if (strcmp(currentToken, "bind") != 0) {
error("config: Unexpected token '%s' on line %d. 'bind' expected", currentToken, currentLine);
case ROOT:
if (strcmp(currentToken, "bind") == 0) {
currentBind = malloc(sizeof(struct config_bind));
if (currentBind == NULL) {
error("config: couldn't allocate for bind struct: %s", strerror(errno));
freeEverything(toFree, toFreeLength);
return NULL;
}
replaceOrAdd(toFree, &toFreeLength, NULL, currentBind);
config->nrBinds++;
struct config_bind** tmpBind = realloc(config->binds, config->nrBinds * sizeof(struct config_bind*));
if (tmpBind == NULL) {
error("config: couldn't reallocate for bind array: %s", strerror(errno));
freeEverything(toFree, toFreeLength);
return NULL;
}
replaceOrAdd(toFree, &toFreeLength, config->binds, tmpBind);
config->binds = tmpBind;
config->binds[config->nrBinds - 1] = currentBind;
currentBind->nrSites = 0;
currentBind->sites = NULL;
currentBind->addr = NULL;
currentBind->port = NULL;
#ifdef SSL_SUPPORT
currentBind->ssl = NULL;
#endif
state = BIND_VALUE;
} else if (strcmp(currentToken, "logging") == 0) {
state = LOGGING_BRACKETS_OPEN;
} else {
error("config: Unexpected token '%s' on line %d.", currentToken, currentLine);
freeEverything(toFree, toFreeLength);
return NULL;
}
currentBind = malloc(sizeof(struct config_bind));
if (currentBind == NULL) {
error("config: couldn't allocate for bind struct: %s", strerror(errno));
freeEverything(toFree, toFreeLength);
return NULL;
}
replaceOrAdd(toFree, &toFreeLength, NULL, currentBind);
config->nrBinds++;
struct config_bind** tmpBind = realloc(config->binds, config->nrBinds * sizeof(struct config_bind*));
if (tmpBind == NULL) {
error("config: couldn't reallocate for bind array: %s", strerror(errno));
freeEverything(toFree, toFreeLength);
return NULL;
}
replaceOrAdd(toFree, &toFreeLength, config->binds, tmpBind);
config->binds = tmpBind;
config->binds[config->nrBinds - 1] = currentBind;
currentBind->nrSites = 0;
currentBind->sites = NULL;
currentBind->addr = NULL;
currentBind->port = NULL;
#ifdef SSL_SUPPORT
currentBind->ssl = NULL;
#endif
state = BIND_VALUE;
break;
case BIND_VALUE: ;
char* seperator = strstr(currentToken, ":");
@ -212,7 +229,7 @@ struct config* config_parse(FILE* file) {
state = SITE_BRACKETS_OPEN;
} else if (strcmp(currentToken, "}") == 0) {
state = BIND;
state = ROOT;
} else if (strcmp(currentToken, "ssl") == 0) {
#ifdef SSL_SUPPORT
if (currentBind->ssl != NULL) {
@ -502,6 +519,84 @@ struct config* config_parse(FILE* file) {
state = HANDLER_CONTENT;
break;
case LOGGING_BRACKETS_OPEN:
if (strcmp(currentToken, "{") != 0) {
error("config: Unexpected token '%s' on line %d. '{' expected", currentToken, currentLine);
freeEverything(toFree, toFreeLength);
return NULL;
}
state = LOGGING_CONTENT;
break;
case LOGGING_CONTENT:
if (strcmp(currentToken, "access") == 0) {
state = LOGGING_ACCESS_FILE_EQUALS;
} else if (strcmp(currentToken, "server") == 0) {
state = LOGGING_SERVER_FILE_EQUALS;
} else if (strcmp(currentToken, "verbosity") == 0) {
state = LOGGING_SERVER_VERBOSITY_EQUALS;
} else if (strcmp(currentToken, "}") == 0) {
state = ROOT;
} else {
error("config: Unknown property '%s' on line %d.", currentToken, currentLine);
freeEverything(toFree, toFreeLength);
return NULL;
}
break;
case LOGGING_ACCESS_FILE_EQUALS:
if (strcmp(currentToken, "=") != 0) {
error("config: Unexpected token '%s' on line %d. '=' expected", currentToken, currentLine);
freeEverything(toFree, toFreeLength);
return NULL;
}
state = LOGGING_ACCESS_FILE_VALUE;
break;
case LOGGING_ACCESS_FILE_VALUE:
config->logging.accessLogfile = strclone(currentToken);
if (config->logging.accessLogfile == NULL) {
error("config: error cloning access log file string");
freeEverything(toFree, toFreeLength);
return NULL;
}
state = LOGGING_CONTENT;
break;
case LOGGING_SERVER_FILE_EQUALS:
if (strcmp(currentToken, "=") != 0) {
error("config: Unexpected token '%s' on line %d. '=' expected", currentToken, currentLine);
freeEverything(toFree, toFreeLength);
return NULL;
}
state = LOGGING_SERVER_FILE_VALUE;
break;
case LOGGING_SERVER_FILE_VALUE:
config->logging.serverLogfile = strclone(currentToken);
if (config->logging.serverLogfile == NULL) {
error("config: error cloning server log file string");
freeEverything(toFree, toFreeLength);
return NULL;
}
state = LOGGING_CONTENT;
break;
case LOGGING_SERVER_VERBOSITY_EQUALS:
if (strcmp(currentToken, "=") != 0) {
error("config: Unexpected token '%s' on line %d. '=' expected", currentToken, currentLine);
freeEverything(toFree, toFreeLength);
return NULL;
}
state = LOGGING_SERVER_VERBOSITY_VALUE;
break;
case LOGGING_SERVER_VERBOSITY_VALUE:
config->logging.serverVerbosity = strtologlevel(currentToken);
if (config->logging.serverVerbosity == UNKNOWN) {
error("config: Unexpected token '%s' on line %d.", currentToken, currentLine);
freeEverything(toFree, toFreeLength);
return NULL;
}
state = LOGGING_CONTENT;
break;
default:
assert(false);
}
@ -516,7 +611,7 @@ struct config* config_parse(FILE* file) {
}
}
if (state != BIND) {
if (state != ROOT) {
error("config: unexpected EOF");
freeEverything(toFree, toFreeLength);
return NULL;
@ -582,6 +677,29 @@ struct networkingConfig config_getNetworkingConfig(struct config* config) {
return networkingConfig;
}
void config_setLogging(struct config* config) {
setLogging(stdout, config->logging.serverVerbosity, true);
if (config->logging.serverLogfile != NULL) {
FILE* file = fopen(config->logging.serverLogfile, "a");
if (file == NULL) {
error("config: failed to open server log file %s: %s", config->logging.serverLogfile, strerror(errno));
} else {
setLogging(file, config->logging.serverVerbosity, false);
}
}
if (config->logging.accessLogfile != NULL) {
FILE* file = fopen(config->logging.accessLogfile, "a");
if (file == NULL) {
error("config: failed to open access log file %s: %s", config->logging.accessLogfile, strerror(errno));
} else {
setLogging(file, HTTP_ACCESS, false);
}
}
}
struct handler config_getHandler(struct config* config, struct metaData metaData, const char* host, struct bind* bind) {
struct handler handler = {};

View file

@ -7,11 +7,14 @@
#include "misc.h"
#include "files.h"
#include "cgi.h"
#include "logging.h"
#ifdef SSL_SUPPORT
#include "ssl.h"
#endif
#define CONFIG_DEFAULT_LOGLEVEL (DEFAULT_LOGLEVEL)
struct config {
int nrBinds;
struct config_bind {
@ -39,6 +42,11 @@ struct config {
} **handlers;
} **sites;
} **binds;
struct config_logging {
char* accessLogfile;
char* serverLogfile;
loglevel_t serverVerbosity;
} logging;
};
/*
@ -59,6 +67,11 @@ bind [addr]:[port] {
}
}
}
logging {
access = file
server = file
verboseity = debug|info|warn|error
}
*/
@ -66,6 +79,7 @@ bind [addr]:[port] {
struct config* config_parse(FILE* file);
struct networkingConfig config_getNetworkingConfig(struct config* config);
void config_setLogging(struct config* config);
struct handler config_getHandler(struct config* config, struct metaData metaData, const char* host, struct bind* bind);
void config_destroy(struct config* config);

View file

@ -290,3 +290,20 @@ void critical(const char* format, ...) {
vlogging(CRITICAL, format, argptr);
va_end(argptr);
}
loglevel_t strtologlevel(const char* string) {
if (strcasecmp(string, "debug") == 0) {
return DEBUG;
} else if (strcasecmp(string, "info") == 0) {
return INFO;
} else if (strcasecmp(string, "warn") == 0) {
return WARN;
} else if (strcasecmp(string, "error") == 0) {
return ERROR;
} else if (strcasecmp(string, "critical") == 0) {
return CRITICAL;
} else {
return UNKNOWN;
}
}

View file

@ -7,6 +7,7 @@
typedef int loglevel_t;
#define UNKNOWN (-1)
#define DEBUG (0)
#define VERBOSE (1)
#define INFO (2)
@ -35,4 +36,6 @@ void warn(const char* format, ...);
void error(const char* format, ...);
void critical(const char* format, ...);
loglevel_t strtologlevel(const char* string);
#endif

View file

@ -269,6 +269,10 @@ void testConfig() {
checkString(config->binds[0]->sites[0]->handlers[0]->settings.fileSettings.documentRoot, "/var/www", "handler settings root check");
checkInt(config->binds[0]->sites[0]->handlers[0]->settings.fileSettings.indexfiles.number, 1, "handler settings index no");
checkString(config->binds[0]->sites[0]->handlers[0]->settings.fileSettings.indexfiles.files[0], "index.html", "handler settings index check");
checkString(config->logging.accessLogfile, "access.log", "access log file check");
checkString(config->logging.serverLogfile, "server.log", "server log file check");
printf("%s\n", config->logging.serverLogfile);
checkInt(config->logging.serverVerbosity, INFO, "server log verbosity check");
#ifdef SSL_SUPPORT
checkString(config->binds[1]->addr, "0.0.0.0", "bind addr check");
@ -306,15 +310,12 @@ void test(const char* name, void (*testFunction)()) {
}
int main(int argc, char** argv) {
/**test("logging", &testLogging);
test("config", &testConfig);
test("util", &testUtil);
test("linked lists", &testLinkedList);
test("signals", &testTimers);
test("headers", &testHeaders);*/
setLogging(stderr, DEFAULT_LOGLEVEL, true);
test("config", &testConfig);
test("headers", &testHeaders);
test("logging", &testLogging);
printf("\nOverall: %s\n", overall ? "OK" : "FAILED");

View file

@ -22,3 +22,8 @@ bind 0.0.0.0:443 {
}
}
}
logging {
access = access.log
server = server.log
verbosity = info
}

View file

@ -8,3 +8,8 @@ bind 0.0.0.0:80 {
}
}
}
logging {
access = access.log
server = server.log
verbosity = info
}