From 2a587639cbfb94f696d429dae3c7e26c7d55f4b0 Mon Sep 17 00:00:00 2001 From: Leonid Evdokimov Date: Sat, 9 Feb 2008 23:38:09 +0600 Subject: [PATCH] Added basic syslog support (everything is LOG_INFO) and console detaching. --- base.c | 64 ++++++++++++++++++++++++++++++++++++++++++---- log.c | 81 +++++++++++++++++++++++++++++++++++++++++++++++++++++----- log.h | 5 ++++ 3 files changed, 138 insertions(+), 12 deletions(-) diff --git a/base.c b/base.c index f2c8ee8..baeb24a 100644 --- a/base.c +++ b/base.c @@ -7,6 +7,7 @@ #include #include #include +#include #include "config.h" #if defined USE_IPTABLES # include @@ -33,6 +34,8 @@ typedef struct base_instance_t { char *group; char *redirector_name; redirector_subsys *redirector; + char *log_name; + bool daemon; } base_instance; static base_instance instance = { @@ -212,6 +215,8 @@ static parser_entry base_entries[] = { .key = "user", .type = pt_pchar, .addr = &instance.user }, { .key = "group", .type = pt_pchar, .addr = &instance.group }, { .key = "redirector", .type = pt_pchar, .addr = &instance.redirector_name }, + { .key = "log", .type = pt_pchar, .addr = &instance.log_name }, + { .key = "daemon", .type = pt_bool, .addr = &instance.daemon }, { } }; @@ -269,6 +274,7 @@ static int base_init() { uid_t uid; gid_t gid; + int devnull = -1; if (!instance.configured) { log_error("there is no configured instance of `base`, check config file"); @@ -296,6 +302,20 @@ static int base_init() gid = gr->gr_gid; } + if (log_preopen( + instance.log_name ? instance.log_name : instance.daemon ? "syslog:daemon" : "stderr" + ) < 0 ) { + goto fail; + } + + if (instance.daemon) { + devnull = open("/dev/null", O_RDWR); + if (devnull == -1) { + log_errno("open(\"/dev/null\", O_RDWR"); + goto fail; + } + } + if (instance.chroot) { if (chroot(instance.chroot) < 0) { log_errno("chroot(%s)", instance.chroot); @@ -303,6 +323,13 @@ static int base_init() } } + if (instance.daemon || instance.chroot) { + if (chdir("/") < 0) { + log_errno("chdir(\"/\")"); + goto fail; + } + } + if (instance.group) { if (setgid(gid) < 0) { log_errno("setgid(%i)", gid); @@ -317,14 +344,41 @@ static int base_init() } } -#if 0 - if (daemon(0, 0) < 0) { - log_errno("daemon()"); - goto fail; + if (instance.daemon) { + switch (fork()) { + case -1: // error + log_errno("fork()"); + goto fail; + case 0: // child + break; + default: // parent, pid is returned + exit(EXIT_SUCCESS); + } + } + + log_open(); // child has nothing to do with TTY + + if (instance.daemon) { + if (setsid() < 0) { + log_errno("setsid()"); + goto fail; + } + + int fds[] = { STDIN_FILENO, STDOUT_FILENO, STDERR_FILENO }; + int *pfd; + FOREACH(pfd, fds) + if (dup2(devnull, *pfd) < 0) { + log_errno("dup2(devnull, %i)", *pfd); + goto fail; + } + + close(devnull); + devnull = -1; } -#endif return 0; fail: + if (devnull != -1) + close(devnull); if (instance.redirector->fini) instance.redirector->fini(); return -1; diff --git a/log.c b/log.c index 7c1d0a2..df3d759 100644 --- a/log.c +++ b/log.c @@ -6,10 +6,83 @@ #include #include #include +#include "utils.h" #include "log.h" static const char *lowmem = ""; +typedef void (*log_func)(const char *file, int line, const char *func, const char *message, const char *appendix); + +static void stderr_msg(const char *file, int line, const char *func, const char *message, const char *appendix) +{ + struct timeval tv = { }; + gettimeofday(&tv, 0); + + if (appendix) + fprintf(stderr, "%lu.%6.6lu %s:%u %s(...) %s: %s\n", tv.tv_sec, tv.tv_usec, file, line, func, message, appendix); + else + fprintf(stderr, "%lu.%6.6lu %s:%u %s(...) %s\n", tv.tv_sec, tv.tv_usec, file, line, func, message); +} + +static void syslog_msg(const char *file, int line, const char *func, const char *message, const char *appendix) +{ + if (appendix) + syslog(LOG_INFO, "%s: %s\n", message, appendix); + else + syslog(LOG_INFO, "%s\n", message); +} + +static log_func log_msg = stderr_msg; +static log_func log_msg_next = NULL; + +int log_preopen(const char *dst) +{ + const char *syslog_prefix = "syslog:"; + if (strcmp(dst, "stderr") == 0) { + log_msg_next = stderr_msg; + } + else if (strncmp(dst, syslog_prefix, strlen(syslog_prefix)) == 0) { + const char *facility_name = dst + strlen(syslog_prefix); + int facility = -1; + struct { + char *name; int value; + } *ptpl, tpl[] = { + { "daemon", LOG_DAEMON }, + { "local0", LOG_LOCAL0 }, + { "local1", LOG_LOCAL1 }, + { "local2", LOG_LOCAL2 }, + { "local3", LOG_LOCAL3 }, + { "local4", LOG_LOCAL4 }, + { "local5", LOG_LOCAL5 }, + { "local6", LOG_LOCAL6 }, + { "local7", LOG_LOCAL7 }, + }; + FOREACH(ptpl, tpl) + if (strcmp(facility_name, ptpl->name) == 0) { + facility = ptpl->value; + break; + } + if (facility == -1) { + log_error("log_preopen(%s, ...): unknown syslog facility"); + return -1; + } + + openlog("redsocks", LOG_NDELAY | LOG_PID, facility); + log_msg_next = syslog_msg; + } + else { + log_error("log_preopen(%s, ...): unknown destination", dst); + return -1; + } + return 0; +} + +void log_open() +{ + log_msg = log_msg_next; + log_msg_next = NULL; +} + void _log_vwrite(const char *file, int line, const char *func, int do_errno, const char *fmt, va_list ap) { int saved_errno = errno; @@ -23,13 +96,7 @@ void _log_vwrite(const char *file, int line, const char *func, int do_errno, con else message = lowmem; - struct timeval tv = { }; - gettimeofday(&tv, 0); - - if (do_errno) - fprintf(stderr, "%lu.%6.6lu %s:%u %s(...) %s: %s\n", tv.tv_sec, tv.tv_usec, file, line, func, message, strerror(saved_errno)); - else - fprintf(stderr, "%lu.%6.6lu %s:%u %s(...) %s\n", tv.tv_sec, tv.tv_usec, file, line, func, message); + log_msg(file, line, func, message, do_errno ? strerror(saved_errno) : NULL); if (buff) evbuffer_free(buff); diff --git a/log.h b/log.h index 842cb0f..b3701b2 100644 --- a/log.h +++ b/log.h @@ -2,10 +2,15 @@ #define LOG_H_WED_JAN_24_18_21_27_2007 /* $Id$ */ #include +#include +#include #define log_errno(msg...) _log_write(__FILE__, __LINE__, __func__, 1, ## msg) #define log_error(msg...) _log_write(__FILE__, __LINE__, __func__, 0, ## msg) +int log_preopen(const char *dst); +void log_open(); + void _log_vwrite(const char *file, int line, const char *func, int do_errno, const char *fmt, va_list ap); void _log_write(const char *file, int line, const char *func, int do_errno, const char *fmt, ...);