diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..0c6994b --- /dev/null +++ b/.gitignore @@ -0,0 +1,3 @@ +*.log +*.o +webdis diff --git a/Makefile b/Makefile index 055fed7..ecb4072 100644 --- a/Makefile +++ b/Makefile @@ -2,7 +2,8 @@ OUT=webdis HIREDIS_OBJ=hiredis/hiredis.o hiredis/sds.o hiredis/net.o hiredis/async.o hiredis/dict.o JANSSON_OBJ=jansson/src/dump.o jansson/src/error.o jansson/src/hashtable.o jansson/src/load.o jansson/src/strbuffer.o jansson/src/utf.o jansson/src/value.o jansson/src/variadic.o FORMAT_OBJS=formats/json.o formats/raw.o formats/common.o formats/custom-type.o -OBJS=webdis.o conf.o $(FORMAT_OBJS) cmd.o server.o $(HIREDIS_OBJ) $(JANSSON_OBJ) libb64/cencode.o acl.o md5/md5.o +OBJS=webdis.o conf.o $(FORMAT_OBJS) cmd.o slog.o server.o $(HIREDIS_OBJ) $(JANSSON_OBJ) libb64/cencode.o acl.o md5/md5.o + CFLAGS=-O3 -Wall -Wextra -I. -Ijansson/src LDFLAGS=-levent diff --git a/conf.c b/conf.c index 839192d..c15ec5c 100644 --- a/conf.c +++ b/conf.c @@ -32,6 +32,8 @@ conf_read(const char *filename) { conf->http_port = 7379; conf->user = getuid(); conf->group = getgid(); + conf->logfile = "webdis.log"; + conf->verbosity = WEBDIS_VERBOSE; j = json_load_file(filename, 0, &error); if(!j) { @@ -66,6 +68,10 @@ conf_read(const char *filename) { if((g = getgrnam(json_string_value(jtmp)))) { conf->group = g->gr_gid; } + } else if(strcmp(json_object_iter_key(kv),"logfile") == 0 && json_typeof(jtmp) == JSON_STRING){ + conf->logfile = strdup(json_string_value(jtmp)); + } else if(strcmp(json_object_iter_key(kv),"verbosity") == 0 && json_typeof(jtmp) == JSON_INTEGER){ + conf->verbosity = (short)json_integer_value(jtmp); } } diff --git a/conf.h b/conf.h index d700fe8..dc43875 100644 --- a/conf.h +++ b/conf.h @@ -1,8 +1,16 @@ #ifndef CONF_H #define CONF_H +#define WEBDIS_VERBOSE 0 +#define WEBDIS_QUIET 1 +#define WEBDIS_SILENT 2 + #include +typedef enum { + WARNING = 0 +} log_level; + struct conf { /* connection to Redis */ @@ -20,6 +28,10 @@ struct conf { /* user/group */ uid_t user; gid_t group; + + /* Logging */ + char *logfile; + log_level verbosity; }; struct conf * diff --git a/server.c b/server.c index 152de71..e41af3a 100644 --- a/server.c +++ b/server.c @@ -1,6 +1,7 @@ #include "server.h" #include "conf.h" #include "cmd.h" +#include "slog.h" #include #include @@ -116,7 +117,6 @@ on_flash_request(struct evhttp_request *rq, void *ctx) { void on_request(struct evhttp_request *rq, void *ctx) { - const char *uri = evhttp_request_uri(rq); struct server *s = ctx; int ret; @@ -127,13 +127,16 @@ on_request(struct evhttp_request *rq, void *ctx) { return; } + /* check that the command can be executed */ switch(rq->type) { case EVHTTP_REQ_GET: + webdis_log(s,1,uri); ret = cmd_run(s, rq, 1+uri, strlen(uri)-1); break; case EVHTTP_REQ_POST: + webdis_log(s,1,uri); ret = cmd_run(s, rq, (const char*)EVBUFFER_DATA(rq->input_buffer), EVBUFFER_LENGTH(rq->input_buffer)); @@ -141,11 +144,13 @@ on_request(struct evhttp_request *rq, void *ctx) { default: printf("405\n"); + webdis_log(s,1,"405"); evhttp_send_reply(rq, 405, "Method Not Allowed", NULL); return; } if(ret < 0) { + slog(s->cfg->logfile,2, uri); evhttp_send_reply(rq, 403, "Forbidden", NULL); } } @@ -159,11 +164,13 @@ server_start(struct server *s) { #endif /* start http server */ + slog(s->cfg->logfile,1,"Starting HTTP Server"); evhttp_bind_socket(s->http, s->cfg->http_host, s->cfg->http_port); evhttp_set_cb(s->http, "/crossdomain.xml", on_flash_request, s); evhttp_set_gencb(s->http, on_request, s); /* drop privileges */ + slog(s->cfg->logfile,1,"Dropping Privileges"); setuid(s->cfg->user); setgid(s->cfg->group); @@ -174,3 +181,9 @@ server_start(struct server *s) { event_base_dispatch(s->base); } +void +webdis_log(struct server *s, int level, const char *body){ + if(level > (int)s->cfg->verbosity){ + slog(s->cfg->logfile,level,body); + } +} diff --git a/server.h b/server.h index 998c9a0..a4f9528 100644 --- a/server.h +++ b/server.h @@ -31,5 +31,8 @@ server_copy(const struct server *s); void server_start(struct server *s); +void +webdis_log(struct server *s, int level, const char *body); + #endif diff --git a/slog.c b/slog.c new file mode 100644 index 0000000..c9ea1e9 --- /dev/null +++ b/slog.c @@ -0,0 +1,27 @@ +/* A slog is a simple log. Basically extracted from antirez/redis. */ +#include +#include +#include +#include +#include +#include + +void slog(const char *logfile, int level, const char *body) { + const char *c = ".-*#"; + time_t now = time(NULL); + FILE *fp; + char buf[64]; + char msg[1024]; + + snprintf(msg, sizeof(msg), "%s", body); + + fp = (logfile == NULL) ? stdout : fopen(logfile,"a"); + if (!fp) return; + + strftime(buf,sizeof(buf),"%d %b %H:%M:%S",localtime(&now)); + fprintf(fp,"[%d] %s %c %s\n",(int)getpid(),buf,c[level],msg); + fprintf(stdout,"[%d] %s %c %s\n",(int)getpid(),buf,c[level],msg); + fflush(fp); + + if (logfile) fclose(fp); +} diff --git a/slog.h b/slog.h new file mode 100644 index 0000000..8cd2099 --- /dev/null +++ b/slog.h @@ -0,0 +1,6 @@ +#ifndef SLOG_H +#define SLOG_H + +void slog(const char *logfile, int level, const char *body); + +#endif diff --git a/webdis.json b/webdis.json index 611c3f5..0e2e4e1 100644 --- a/webdis.json +++ b/webdis.json @@ -16,5 +16,7 @@ "http_basic_auth": "user:password", "enabled": ["DEBUG"] } - ] + ], + "verbosity": 0, + "logfile": "webdis.log" }