commit 00b0e16d70d9075c4363a2edaa16efe387d52ddd Author: David Goulet dgoulet@ev0ke.net Date: Sun Jun 2 16:18:51 2013 -0400
Reengineer logging and remove old show_msg
Signed-off-by: David Goulet dgoulet@ev0ke.net --- src/common/config-file.c | 127 ++++++++++++++-------------- src/common/defaults.h | 9 ++ src/common/log.c | 211 ++++++++++++++++++++++++++++++++-------------- src/common/log.h | 94 +++++++++++++++++---- 4 files changed, 299 insertions(+), 142 deletions(-)
diff --git a/src/common/config-file.c b/src/common/config-file.c index ad7b683..47f6a09 100644 --- a/src/common/config-file.c +++ b/src/common/config-file.c @@ -58,9 +58,8 @@ static int check_server(struct config_server_entry *server) static int handle_endpath(struct config_parsed *config, int lineno, int nowords) {
if (nowords != 1) { - show_msg(MSGERR, "Badly formed path close statement on line " - "%d in configuration file (should look like " - ""}")\n", lineno); + ERR("Badly formed path close statement on line %d in configuration" + "file (should look like "}")\n", lineno); } else { currentcontext = &(config->default_server); } @@ -112,7 +111,7 @@ int make_config_network_entry(char *value, struct config_network_entry **ent) { exit(1); }
- show_msg(MSGDEBUG, "New network entry for %s going to 0x%08x\n", ip, *ent); + DBG("New network entry for %s going to 0x%08x\n", ip, *ent);
if (!start_port) (*ent)->start_port = 0; @@ -174,46 +173,46 @@ static int handle_reaches(int lineno, char *value) { rc = make_config_network_entry(value, &ent); switch(rc) { case 1: - show_msg(MSGERR, "Local network specification (%s) is not validly " + ERR("Local network specification (%s) is not validly " "constructed in reach statement on line " "%d in configuration " "file\n", value, lineno); return(0); break; case 2: - show_msg(MSGERR, "IP in reach statement " + ERR("IP in reach statement " "network specification (%s) is not valid on line " "%d in configuration file\n", value, lineno); return(0); break; case 3: - show_msg(MSGERR, "SUBNET in reach statement " + ERR("SUBNET in reach statement " "network specification (%s) is not valid on " "line %d in configuration file\n", value, lineno); return(0); break; case 4: - show_msg(MSGERR, "IP (%s) & ", inet_ntoa(ent->local_ip)); - show_msg(MSGERR, "SUBNET (%s) != IP on line %d in " + ERR("IP (%s) & ", inet_ntoa(ent->local_ip)); + ERR("SUBNET (%s) != IP on line %d in " "configuration file, ignored\n", inet_ntoa(ent->local_net), lineno); return(0); break; case 5: - show_msg(MSGERR, "Start port in reach statement " + ERR("Start port in reach statement " "network specification (%s) is not valid on line " "%d in configuration file\n", value, lineno); return(0); break; case 6: - show_msg(MSGERR, "End port in reach statement " + ERR("End port in reach statement " "network specification (%s) is not valid on line " "%d in configuration file\n", value, lineno); return(0); break; case 7: - show_msg(MSGERR, "End port in reach statement " + ERR("End port in reach statement " "network specification (%s) is less than the start " "port on line %d in configuration file\n", value, lineno); @@ -239,11 +238,11 @@ static int handle_server(struct config_parsed *config, int lineno, char *value) currentcontext->address = strdup(ip); else { if (currentcontext == &(config->default_server)) - show_msg(MSGERR, "Only one default SOCKS server " + ERR("Only one default SOCKS server " "may be specified at line %d in " "configuration file\n", lineno); else - show_msg(MSGERR, "Only one SOCKS server may be specified " + ERR("Only one SOCKS server may be specified " "per path on line %d in configuration " "file. (Path begins on line %d)\n", lineno, currentcontext->lineno); @@ -256,11 +255,11 @@ static int handle_port(struct config_parsed *config, int lineno, char *value) {
if (currentcontext->port != 0) { if (currentcontext == &(config->default_server)) - show_msg(MSGERR, "Server port may only be specified " + ERR("Server port may only be specified " "once for default server, at line %d " "in configuration file\n", lineno); else - show_msg(MSGERR, "Server port may only be specified " + ERR("Server port may only be specified " "once per path on line %d in configuration " "file. (Path begins on line %d)\n", lineno, currentcontext->lineno); @@ -269,7 +268,7 @@ static int handle_port(struct config_parsed *config, int lineno, char *value) { currentcontext->port = (unsigned short int) (strtol(value, (char **)NULL, 10)); if ((errno != 0) || (currentcontext->port == 0)) { - show_msg(MSGERR, "Invalid server port number " + ERR("Invalid server port number " "specified in configuration file " "(%s) on line %d\n", value, lineno); currentcontext->port = 0; @@ -283,11 +282,11 @@ static int handle_username(struct config_parsed *config, int lineno, char *value
if (currentcontext->username != NULL) { if (currentcontext == &(config->default_server)) - show_msg(MSGERR, "Default username may only be specified " + ERR("Default username may only be specified " "once for default server, at line %d " "in configuration file\n", lineno); else - show_msg(MSGERR, "Default username may only be specified " + ERR("Default username may only be specified " "once per path on line %d in configuration " "file. (Path begins on line %d)\n", lineno, currentcontext->lineno); @@ -302,11 +301,11 @@ static int handle_password(struct config_parsed *config, int lineno, char *value
if (currentcontext->password != NULL) { if (currentcontext == &(config->default_server)) - show_msg(MSGERR, "Default password may only be specified " + ERR("Default password may only be specified " "once for default server, at line %d " "in configuration file\n", lineno); else - show_msg(MSGERR, "Default password may only be specified " + ERR("Default password may only be specified " "once per path on line %d in configuration " "file. (Path begins on line %d)\n", lineno, currentcontext->lineno); @@ -321,11 +320,11 @@ static int handle_type(struct config_parsed *config, int lineno, char *value) {
if (currentcontext->type != 0) { if (currentcontext == &(config->default_server)) - show_msg(MSGERR, "Server type may only be specified " + ERR("Server type may only be specified " "once for default server, at line %d " "in configuration file\n", lineno); else - show_msg(MSGERR, "Server type may only be specified " + ERR("Server type may only be specified " "once per path on line %d in configuration " "file. (Path begins on line %d)\n", lineno, currentcontext->lineno); @@ -334,7 +333,7 @@ static int handle_type(struct config_parsed *config, int lineno, char *value) { currentcontext->type = (int) strtol(value, (char **)NULL, 10); if ((errno != 0) || (currentcontext->type == 0) || ((currentcontext->type != 4) && (currentcontext->type != 5))) { - show_msg(MSGERR, "Invalid server type (%s) " + ERR("Invalid server type (%s) " "specified in configuration file " "on line %d, only 4 or 5 may be " "specified\n", value, lineno); @@ -363,7 +362,7 @@ static int handle_tordns_enabled(struct config_parsed *config, int lineno, { int val = handle_flag(value); if(val == -1) { - show_msg(MSGERR, "Invalid value %s supplied for tordns_enabled at " + ERR("Invalid value %s supplied for tordns_enabled at " "line %d in config file, IGNORED\n", value, lineno); } else { config->tordns_enabled = val; @@ -377,15 +376,15 @@ static int handle_tordns_cache_size(struct config_parsed *config, char *endptr; long size = strtol(value, &endptr, 10); if(*endptr != '\0') { - show_msg(MSGERR, "Error parsing integer value for " + ERR("Error parsing integer value for " "tordns_cache_size (%s), using default %d\n", value, config->tordns_cache_size); } else if(size < 128) { - show_msg(MSGERR, "The value supplied for tordns_cache_size (%d) " + ERR("The value supplied for tordns_cache_size (%d) " "is too small (<128), using default %d\n", size, config->tordns_cache_size); } else if(size > 4096) { - show_msg(MSGERR, "The value supplied for tordns_cache_range (%d) " + ERR("The value supplied for tordns_cache_range (%d) " "is too large (>4096), using default %d\n", size, config->tordns_cache_size); } else { @@ -399,13 +398,13 @@ static int handle_path(struct config_parsed *config, int lineno, int nowords, ch struct config_server_entry *newserver;
if ((nowords != 2) || (strcmp(words[1], "{"))) { - show_msg(MSGERR, "Badly formed path open statement on line %d " + ERR("Badly formed path open statement on line %d " "in configuration file (should look like " ""path {")\n", lineno); } else if (currentcontext != &(config->default_server)) { /* You cannot nest path statements so check that */ /* the current context is default_server */ - show_msg(MSGERR, "Path statements cannot be nested on line %d " + ERR("Path statements cannot be nested on line %d " "in configuration file\n", lineno); } else { /* Open up a new config_server_entry, put it on the list */ @@ -414,7 +413,7 @@ static int handle_path(struct config_parsed *config, int lineno, int nowords, ch exit(-1);
/* Initialize the structure */ - show_msg(MSGDEBUG, "New server structure from line %d in configuration file going " + DBG("New server structure from line %d in configuration file going " "to 0x%08x\n", lineno, newserver); memset(newserver, 0x0, sizeof(*newserver)); newserver->next = config->paths; @@ -431,7 +430,7 @@ static int handle_local(struct config_parsed *config, int lineno, const char *va struct config_network_entry *ent;
if (currentcontext != &(config->default_server)) { - show_msg(MSGERR, "Local networks cannot be specified in path " + ERR("Local networks cannot be specified in path " "block at line %d in configuration file. " "(Path block started at line %d)\n", lineno, currentcontext->lineno); @@ -441,34 +440,34 @@ static int handle_local(struct config_parsed *config, int lineno, const char *va rc = make_config_network_entry((char *)value, &ent); switch(rc) { case 1: - show_msg(MSGERR, "Local network specification (%s) is not validly " + ERR("Local network specification (%s) is not validly " "constructed on line %d in configuration " "file\n", value, lineno); return(0); break; case 2: - show_msg(MSGERR, "IP for local " + ERR("IP for local " "network specification (%s) is not valid on line " "%d in configuration file\n", value, lineno); return(0); break; case 3: - show_msg(MSGERR, "SUBNET for " + ERR("SUBNET for " "local network specification (%s) is not valid on " "line %d in configuration file\n", value, lineno); return(0); break; case 4: - show_msg(MSGERR, "IP (%s) & ", inet_ntoa(ent->local_ip)); - show_msg(MSGERR, "SUBNET (%s) != IP on line %d in " + ERR("IP (%s) & ", inet_ntoa(ent->local_ip)); + ERR("SUBNET (%s) != IP on line %d in " "configuration file, ignored\n", inet_ntoa(ent->local_net), lineno); return(0); case 5: case 6: case 7: - show_msg(MSGERR, "Port specification is invalid and " + ERR("Port specification is invalid and " "not allowed in local network specification " "(%s) on line %d in configuration file\n", value, lineno); @@ -477,7 +476,7 @@ static int handle_local(struct config_parsed *config, int lineno, const char *va }
if (ent->start_port || ent->end_port) { - show_msg(MSGERR, "Port specification is " + ERR("Port specification is " "not allowed in local network specification " "(%s) on line %d in configuration file\n", value, lineno); @@ -498,13 +497,13 @@ static int handle_tordns_deadpool_range(struct config_parsed *config, int lineno struct config_network_entry *ent;
if (config->tordns_deadpool_range != NULL) { - show_msg(MSGERR, "Only one 'deadpool' entry permitted, found a " + ERR("Only one 'deadpool' entry permitted, found a " "second at line %d in configuration file.\n"); return(0); }
if (currentcontext != &(config->default_server)) { - show_msg(MSGERR, "Deadpool cannot be specified in path " + ERR("Deadpool cannot be specified in path " "block at line %d in configuration file. " "(Path block started at line %d)\n", lineno, currentcontext->lineno); @@ -516,34 +515,34 @@ static int handle_tordns_deadpool_range(struct config_parsed *config, int lineno a generic whinge() function or something */ switch(rc) { case 1: - show_msg(MSGERR, "The deadpool specification (%s) is not validly " + ERR("The deadpool specification (%s) is not validly " "constructed on line %d in configuration " "file\n", value, lineno); return(0); break; case 2: - show_msg(MSGERR, "IP for deadpool " + ERR("IP for deadpool " "network specification (%s) is not valid on line " "%d in configuration file\n", value, lineno); return(0); break; case 3: - show_msg(MSGERR, "SUBNET for " + ERR("SUBNET for " "deadpool network specification (%s) is not valid on " "line %d in configuration file\n", value, lineno); return(0); break; case 4: - show_msg(MSGERR, "IP (%s) & ", inet_ntoa(ent->local_ip)); - show_msg(MSGERR, "SUBNET (%s) != IP on line %d in " + ERR("IP (%s) & ", inet_ntoa(ent->local_ip)); + ERR("SUBNET (%s) != IP on line %d in " "configuration file, ignored\n", inet_ntoa(ent->local_net), lineno); return(0); case 5: case 6: case 7: - show_msg(MSGERR, "Port specification is invalid and " + ERR("Port specification is invalid and " "not allowed in deadpool specification " "(%s) on line %d in configuration file\n", value, lineno); @@ -551,7 +550,7 @@ static int handle_tordns_deadpool_range(struct config_parsed *config, int lineno break; } if (ent->start_port || ent->end_port) { - show_msg(MSGERR, "Port specification is " + ERR("Port specification is " "not allowed in deadpool specification " "(%s) on line %d in configuration file\n", value, lineno); @@ -590,7 +589,7 @@ static int handle_line(struct config_parsed *config, char *line, int lineno) } else { /* Has to be a pair */ if ((nowords != 3) || (strcmp(words[1], "="))) { - show_msg(MSGERR, "Malformed configuration pair " + ERR("Malformed configuration pair " "on line %d in configuration " "file, "%s"\n", lineno, savedline); } else if (!strcmp(words[0], "reaches")) { @@ -614,7 +613,7 @@ static int handle_line(struct config_parsed *config, char *line, int lineno) } else if (!strcmp(words[0], "tordns_cache_size")) { handle_tordns_cache_size(config, words[2]); } else { - show_msg(MSGERR, "Invalid pair type (%s) specified " + ERR("Invalid pair type (%s) specified " "on line %d in configuration file, " ""%s"\n", words[0], lineno, savedline); @@ -629,31 +628,31 @@ int is_local(struct config_parsed *config, struct in_addr *testip) { struct config_network_entry *ent; char buf[16]; inet_ntop(AF_INET, testip, buf, sizeof(buf)); - show_msg(MSGDEBUG, "checking if address: %s is local" + DBG("checking if address: %s is local" "\n", buf);
for (ent = (config->local_nets); ent != NULL; ent = ent -> next) { inet_ntop(AF_INET, &ent->local_net, buf, sizeof(buf)); - show_msg(MSGDEBUG, "local_net addr: %s" + DBG("local_net addr: %s" "\n", buf); inet_ntop(AF_INET, &ent->local_ip, buf, sizeof(buf)); - show_msg(MSGDEBUG, "local_ip addr: %s" + DBG("local_ip addr: %s" "\n", buf); - show_msg(MSGDEBUG, "result testip->s_addr & ent->local_net.s_addr : %i" + DBG("result testip->s_addr & ent->local_net.s_addr : %i" "\n", testip->s_addr & ent->local_net.s_addr); - show_msg(MSGDEBUG, "result ent->local_ip.s_addr & ent->local_net.s_addr : %i" + DBG("result ent->local_ip.s_addr & ent->local_net.s_addr : %i" "\n", ent->local_ip.s_addr & ent->local_net.s_addr); - show_msg(MSGDEBUG, "result ent->local_ip.s_addr : %i" + DBG("result ent->local_ip.s_addr : %i" "\n", ent->local_ip.s_addr); if ((testip->s_addr & ent->local_net.s_addr) == (ent->local_ip.s_addr & ent->local_net.s_addr)) { - show_msg(MSGDEBUG, "address: %s is local" + DBG("address: %s is local" "\n", buf); return(0); @@ -661,7 +660,7 @@ int is_local(struct config_parsed *config, struct in_addr *testip) { }
inet_ntop(AF_INET, testip, buf, sizeof(buf)); - show_msg(MSGDEBUG, "address: %s is not local" + DBG("address: %s is not local" "\n", buf); return(1); @@ -673,24 +672,24 @@ int pick_server(struct config_parsed *config, struct config_server_entry **ent, struct config_network_entry *net; char ipbuf[64];
- show_msg(MSGDEBUG, "Picking appropriate server for %s\n", inet_ntoa(*ip)); + DBG("Picking appropriate server for %s\n", inet_ntoa(*ip)); *ent = (config->paths); while (*ent != NULL) { /* Go through all the servers looking for one */ /* with a path to this network */ - show_msg(MSGDEBUG, "Checking SOCKS server %s\n", + DBG("Checking SOCKS server %s\n", ((*ent)->address ? (*ent)->address : "(No Address)")); net = (*ent)->reachnets; while (net != NULL) { strcpy(ipbuf, inet_ntoa(net->local_ip)); - show_msg(MSGDEBUG, "Server can reach %s/%s\n", + DBG("Server can reach %s/%s\n", ipbuf, inet_ntoa(net->local_net)); if (((ip->s_addr & net->local_net.s_addr) == (net->local_ip.s_addr & net->local_net.s_addr)) && (!net->start_port || ((net->start_port <= port) && (net->end_port >= port)))) { - show_msg(MSGDEBUG, "This server can reach target\n"); + DBG("This server can reach target\n"); /* Found the net, return */ return(0); } @@ -734,13 +733,13 @@ int config_file_read(const char *filename, struct config_parsed *config) /* Insure null termination */ line[sizeof(line) - 1] = (char) 0; filename = line; - show_msg(MSGDEBUG, "Configuration file not provided by TORSOCKS_CONF_FILE " + DBG("Configuration file not provided by TORSOCKS_CONF_FILE " "environment variable, attempting to use defaults in %s.\n", filename); }
/* If there is no configuration file use reasonable defaults for Tor */ if ((conf = fopen(filename, "r")) == NULL) { - show_msg(MSGERR, "Could not open socks configuration file " + ERR("Could not open socks configuration file " "(%s) errno (%d), assuming sensible defaults for Tor.\n", filename, errno); memset(&(config->default_server), 0x0, sizeof(config->default_server)); check_server(&(config->default_server)); diff --git a/src/common/defaults.h b/src/common/defaults.h index c13db66..6e11e83 100644 --- a/src/common/defaults.h +++ b/src/common/defaults.h @@ -18,8 +18,17 @@ #ifndef TORSOCKS_DEFAULTS_H #define TORSOCKS_DEFAULTS_H
+#include "log.h" + #define DEFAULT_TOR_PORT 9050 #define DEFAULT_TOR_ADDRESS "127.0.0.1" #define DEFAULT_TOR_SOCKS 5
+/* Logging defaults. */ +#define DEFAULT_LOG_LEVEL_ENV "TORSOCKS_LOG_LEVEL" +#define DEFAULT_LOG_TIME_ENV "TORSOCKS_LOG_TIME" +#define DEFAULT_LOG_FILEPATH_ENV "TORSOCKS_LOG_FILE_PATH" +#define DEFAULT_LOG_TIME_STATUS LOG_TIME_ADD +#define DEFAULT_LOG_LEVEL MSGWARN + #endif /* TORSOCKS_DEFAULTS_H */ diff --git a/src/common/log.c b/src/common/log.c index 29888c0..e415721 100644 --- a/src/common/log.c +++ b/src/common/log.c @@ -1,7 +1,5 @@ /* - * Copyright (C) 2000-2008 - Shaun Clowes delius@progsoc.org - * 2008-2011 - Robert Hogan robert@roberthogan.net - * 2013 - David Goulet dgoulet@ev0ke.net + * Copyright (C) 2013 - David Goulet dgoulet@ev0ke.net * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License, version 2 only, as @@ -17,91 +15,180 @@ * Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */
+#include <assert.h> #include <errno.h> #include <stdarg.h> #include <stdio.h> +#include <stdlib.h> #include <string.h> -#include <sys/types.h> #include <time.h> #include <unistd.h>
+#include "defaults.h" +#include "macros.h"
-#include "log.h" - -/* Set logging options, the options are as follows: */ -/* level - This sets the logging threshold, messages with */ -/* a higher level (i.e lower importance) will not be */ -/* output. For example, if the threshold is set to */ -/* MSGWARN a call to log a message of level MSGDEBUG */ -/* would be ignored. This can be set to -1 to disable */ -/* messages entirely */ -/* filename - This is a filename to which the messages should */ -/* be logged instead of to standard error */ -/* timestamp - This indicates that messages should be prefixed */ -/* with timestamps (and the process id) */ -void set_log_options(int level, char *filename, int timestamp) +static struct log_config { + FILE *fp; + char *filepath; + /* Add time or not to the log entry. */ + enum log_time_status time_status; +} logconfig; + +/* + * The default logging level is to only log error messages. + */ +int tsocks_loglevel = DEFAULT_LOG_LEVEL; + +/* + * Add a special formatted timestamp at the beginning of the given buffer. + * + * On success, return the number of bytes written else, return 0. + */ +static size_t add_time_to_log(char *buf, size_t len) { - loglevel = level; - if (loglevel < MSGERR) - loglevel = MSGNONE; + time_t now; + const struct tm *tm;
- if (filename) { - strncpy(logfilename, filename, sizeof(logfilename)); - logfilename[sizeof(logfilename) - 1] = '\0'; - } + assert(buf);
- logstamp = timestamp; + /* Get time stamp. */ + time(&now); + tm = localtime(&now); + return strftime(buf, len, "[%b %d %H:%M:%S] ", tm); }
-void show_msg(int level, const char *fmt, ...) +/* + * Log function taking a format and variable number of arguments fitting the + * given format. + */ +static void _log_write(char *buf, size_t len) { + int ret; + + assert(buf); + assert(logconfig.fp); + + /* Make sure buffer is NULL terminated. */ + buf[len - 1] = '\0'; + + ret = fprintf(logconfig.fp, "%s", buf); + if (ret < 0) { + fprintf(stderr, "[tsocks] logging failed. Stopping logging.\n"); + log_destroy(); + goto end; + } + + /* + * On a write failure we stop the logging but a flush failure is not that + * critical. + */ + (void) fflush(logconfig.fp); + +end: + return; +} + +/* + * Log messages using the logconfig configuration. + */ +ATTR_HIDDEN +void log_print(const char *fmt, ...) +{ + int ret; + size_t written = 0; va_list ap; - int saveerr; - extern char *torsocks_progname; - char timestring[20]; - time_t timestamp; - - if ((loglevel == MSGNONE) || (level > loglevel)) - return; - - if (!logfile) { - if (logfilename[0]) { - logfile = fopen(logfilename, "a"); - if (logfile == NULL) { - logfile = stderr; - show_msg(MSGERR, "Could not open log file, %s, %s\n", - logfilename, strerror(errno)); - } - } else - logfile = stderr; - } + /* This is a hard limit for the size of the line. */ + char buf[4096];
- if (logstamp) { - timestamp = time(NULL); - strftime(timestring, sizeof(timestring), "%H:%M:%S", - localtime(×tamp)); - fprintf(logfile, "%s ", timestring); + assert(fmt); + + if (!logconfig.fp) { + goto end; }
- fputs(torsocks_progname, logfile); + memset(buf, 0, sizeof(buf)); + va_start(ap, fmt);
- if (logstamp) { - fprintf(logfile, "(%d)", getpid()); + if (logconfig.time_status == LOG_TIME_ADD) { + written = add_time_to_log(buf, sizeof(buf)); }
- fputs(": ", logfile); + ret = vsnprintf(buf + written, sizeof(buf) - written, fmt, ap); + if (ret < 0) { + perror("[tsocks] vsnprintf log"); + goto error; + }
- va_start(ap, fmt); + _log_write(buf, sizeof(buf)); + +error: + va_end(ap); +end: + return; +} + +/* + * Initialize logconfig. + * + * Return 0 on success or else a negative errno value. + */ +ATTR_HIDDEN +int log_init(int level, const char *filepath, enum log_time_status t_status) +{ + int ret = 0;
- /* Save errno */ - saveerr = errno; + /* Reset logconfig. Useful if this is call multiple times. */ + memset(&logconfig, 0, sizeof(logconfig));
- vfprintf(logfile, fmt, ap); + if (level < MSGNONE || level > MSGDEBUG) { + fprintf(stderr, "[tsocks] Unknown loglevel %d\n", level); + ret = -ENOENT; + goto error; + }
- fflush(logfile); + if (filepath) { + logconfig.fp = fopen(filepath, "a"); + if (!logconfig.fp) { + fprintf(stderr, "[tsocks] Unable to open log file %s\n", filepath); + ret = -errno; + goto error; + } + + logconfig.filepath = strdup(filepath); + if (!logconfig.filepath) { + perror("[tsocks] log init strdup"); + ret = -errno; + fclose(logconfig.fp); + goto error; + } + } else { + /* The default output is stderr if no filepath is given. */ + fileno(stderr); + if (errno != EBADF) { + logconfig.fp = stderr; + } + }
- errno = saveerr; + tsocks_loglevel = level; + logconfig.time_status = t_status;
- va_end(ap); +error: + return ret; }
+/* + * Cleanup the logconfig data structure. + */ +ATTR_HIDDEN +void log_destroy(void) +{ + free(logconfig.filepath); + if (logconfig.fp) { + int ret; + + ret = fclose(logconfig.fp); + if (ret) { + perror("[tsocks] fclose log destroy"); + } + } +} diff --git a/src/common/log.h b/src/common/log.h index fd141a0..a60618b 100644 --- a/src/common/log.h +++ b/src/common/log.h @@ -20,21 +20,83 @@ #ifndef TORSOCKS_LOG_H #define TORSOCKS_LOG_H
-#define MSGNONE -1 -#define MSGERR 0 -#define MSGWARN 1 -#define MSGTEST 2 -#define MSGNOTICE 3 -#define MSGDEBUG 3 - -int loglevel = MSGERR; /* The default logging level is to only log - error messages */ -char logfilename[256]; /* Name of file to which log messages should - be redirected */ -FILE *logfile; /* File to which messages should be logged */ -int logstamp; /* Timestamp (and pid stamp) messages */ - -void set_log_options(int level, char *filename, int timestamp); -void show_msg(int level, const char *fmt, ...); +#include <sys/types.h> +#include <unistd.h> + +#include "compat.h" + +/* Stringify the expansion of a define */ +#define XSTR(d) STR(d) +#define STR(s) #s + +#define MSGNONE 0x1 +#define MSGERR 0x2 +#define MSGWARN 0x3 +#define MSGNOTICE 0x4 +#define MSGDEBUG 0x5 + +/* + * Used during logging initialization whether or not to add the time or + * suppress it from a log entry. + */ +enum log_time_status { + LOG_TIME_NONE = 0, + LOG_TIME_ADD = 1, +}; + +extern int tsocks_loglevel; + +void log_print(const char *fmt, ...); +int log_init(int level, const char *filepath, enum log_time_status t_status); +void log_destroy(void); + +#define __tsocks_print(level, fmt, args...) \ + do { \ + if (level != MSGNONE && level <= tsocks_loglevel) { \ + log_print(fmt, ## args); \ + } \ + } while (0) + +#define _ERRMSG(msg, type, fmt, args...) __tsocks_print(type, msg \ + " torsocks[%ld]: " fmt " (in %s() at " __FILE__ ":" XSTR(__LINE__) ")\n", \ + (long) getpid(), ## args, __func__) + +#define MSG(fmt, args...) __tsocks_print(MSGNOTICE, fmt "\n", ## args) +#define ERR(fmt, args...) _ERRMSG("ERROR", MSGERR, fmt, ## args) +#define WARN(fmt, args...) _ERRMSG("Warning", MSGWARN, fmt, ## args) +#define DBG(fmt, args...) _ERRMSG("DEBUG", MSGDEBUG, fmt, ## args) + +/* + * Local wrapper used by the PERROR() call below. Should NOT be used outside of + * this scope. + */ +#define _PERROR(fmt, args...) _ERRMSG("PERROR", MSGERR, fmt, ## args) + +#if !defined(__linux__) || ((_POSIX_C_SOURCE >= 200112L || _XOPEN_SOURCE >= 600) && !defined(_GNU_SOURCE)) + +/* + * Version using XSI strerror_r. + */ +#define PERROR(call, args...) \ + do { \ + char buf[200]; \ + strerror_r(errno, buf, sizeof(buf)); \ + _PERROR(call ": %s", ## args, buf); \ + } while(0); + +#else /* _POSIX_C_SOURCE */ + +/* + * Version using GNU strerror_r, for linux with appropriate defines. + */ +#define PERROR(call, args...) \ + do { \ + char *buf; \ + char tmp[200]; \ + buf = strerror_r(errno, tmp, sizeof(tmp)); \ + _PERROR(call ": %s", ## args, buf); \ + } while(0); + +#endif /* _POSIX_C_SOURCE */
#endif /* TORSOCKS_LOG_H */
tor-commits@lists.torproject.org