mirror of
https://github.com/sigmasternchen/CFloor
synced 2025-03-15 12:28:53 +00:00
logging config
This commit is contained in:
parent
a9f91af3da
commit
c67d7d6f78
7 changed files with 207 additions and 44 deletions
194
src/config.c
194
src/config.c
|
@ -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 = {};
|
||||
|
||||
|
|
14
src/config.h
14
src/config.h
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
13
src/test.c
13
src/test.c
|
@ -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");
|
||||
|
|
|
@ -22,3 +22,8 @@ bind 0.0.0.0:443 {
|
|||
}
|
||||
}
|
||||
}
|
||||
logging {
|
||||
access = access.log
|
||||
server = server.log
|
||||
verbosity = info
|
||||
}
|
||||
|
|
|
@ -8,3 +8,8 @@ bind 0.0.0.0:80 {
|
|||
}
|
||||
}
|
||||
}
|
||||
logging {
|
||||
access = access.log
|
||||
server = server.log
|
||||
verbosity = info
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue