*/
#define BULK_TRACK_SIZE 256
+/**
+ * How many characters do we use for matching of
+ * bulk components?
+ */
+#define COMP_TRACK_SIZE 32
+
/**
* How many characters can a date/time string
* be at most?
static unsigned int last_bulk_repeat;
/**
- * Component when the last bulk was logged.
+ * Component when the last bulk was logged. Will be 0-terminated.
*/
-static const char *last_bulk_comp;
+static char last_bulk_comp[COMP_TRACK_SIZE+1];
/**
* Running component.
*/
-static const char *component;
+static char *component;
/**
* Minimum log level.
*/
static unsigned int skip_log;
+/**
+ * File descriptor to use for "stderr", or NULL for none.
+ */
+static FILE *GNUNET_stderr;
+
/**
* Convert a textual description of a loglevel
* to the respective GNUNET_GE_KIND.
- * @returns GNUNET_GE_INVALID if log does not parse
+ *
+ * @param log loglevel to parse
+ * @return GNUNET_GE_INVALID if log does not parse
*/
static enum GNUNET_ErrorType
get_type (const char *log)
return GNUNET_ERROR_TYPE_INVALID;
}
+
/**
* Setup logging.
*
* @param comp default component to use
* @param loglevel what types of messages should be logged
+ * @param logfile which file to write log messages to (can be NULL)
+ * @return GNUNET_OK on success
*/
int
GNUNET_log_setup (const char *comp, const char *loglevel, const char *logfile)
{
FILE *altlog;
-
- component = comp;
+ int dirwarn;
+ char *fn;
+
+ GNUNET_free_non_null (component);
+ GNUNET_asprintf (&component,
+ "%s-%d",
+ comp,
+ getpid());
min_level = get_type (loglevel);
if (logfile == NULL)
return GNUNET_OK;
- altlog = fopen (logfile, "a");
+ fn = GNUNET_STRINGS_filename_expand (logfile);
+ dirwarn = (GNUNET_OK != GNUNET_DISK_directory_create_for_file (fn));
+ altlog = FOPEN (fn, "a");
if (altlog == NULL)
{
- GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_ERROR, "fopen", logfile);
+ GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_ERROR, "fopen", fn);
+ if (dirwarn)
+ GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
+ _("Failed to create or access directory for log file `%s'\n"),
+ fn);
+ GNUNET_free (fn);
return GNUNET_SYSERR;
}
- if (stderr != NULL)
- fclose (stderr);
- stderr = altlog;
+ GNUNET_free (fn);
+ if (GNUNET_stderr != NULL)
+ fclose (GNUNET_stderr);
+ GNUNET_stderr = altlog;
return GNUNET_OK;
}
GNUNET_free (pos);
}
+
+/**
+ * Actually output the log message.
+ *
+ * @param kind how severe was the issue
+ * @param comp component responsible
+ * @param datestr current date/time
+ * @param msg the actual message
+ */
static void
output_message (enum GNUNET_ErrorType kind,
const char *comp, const char *datestr, const char *msg)
{
struct CustomLogger *pos;
- if (stderr != NULL)
- fprintf (stderr, "%s %s %s %s", datestr, comp,
- GNUNET_error_type_to_string (kind), msg);
+ if (GNUNET_stderr != NULL)
+ {
+ fprintf (GNUNET_stderr, "%s %s %s %s", datestr, comp,
+ GNUNET_error_type_to_string (kind), msg);
+ fflush (GNUNET_stderr);
+ }
pos = loggers;
while (pos != NULL)
{
}
}
+
+/**
+ * Flush an existing bulk report to the output.
+ *
+ * @param datestr our current timestamp
+ */
static void
flush_bulk (const char *datestr)
{
* Ignore the next n calls to the log function.
*
* @param n number of log calls to ignore
+ * @param check_reset GNUNET_YES to assert that the log skip counter is currently zero
*/
void
-GNUNET_log_skip (unsigned int n)
+GNUNET_log_skip (unsigned int n, int check_reset)
{
- int ok;
-
if (n == 0)
{
+ int ok;
+
ok = (0 == skip_log);
skip_log = 0;
- GNUNET_assert (ok);
+ if (check_reset)
+ GNUNET_assert (ok);
}
- skip_log += n;
+ else
+ skip_log += n;
}
+/**
+ * Output a log message using the default mechanism.
+ *
+ * @param kind how severe was the issue
+ * @param comp component responsible
+ * @param message the actual message
+ * @param va arguments to the format string "message"
+ */
static void
mylog (enum GNUNET_ErrorType kind,
const char *comp, const char *message, va_list va)
last_bulk_repeat = 0;
last_bulk_kind = kind;
last_bulk_time = GNUNET_TIME_absolute_get ();
- last_bulk_comp = comp;
+ strncpy (last_bulk_comp, comp, sizeof (last_bulk_comp));
output_message (kind, comp, date, buf);
free (buf);
}
+/**
+ * Main log function.
+ *
+ * @param kind how serious is the error?
+ * @param message what is the message (format string)
+ * @param ... arguments for format string
+ */
void
GNUNET_log (enum GNUNET_ErrorType kind, const char *message, ...)
{
}
+/**
+ * Log function that specifies an alternative component.
+ * This function should be used by plugins.
+ *
+ * @param kind how serious is the error?
+ * @param comp component responsible for generating the message
+ * @param message what is the message (format string)
+ * @param ... arguments for format string
+ */
void
GNUNET_log_from (enum GNUNET_ErrorType kind,
const char *comp, const char *message, ...)
/**
- * Convert KIND to String
+ * Convert error type to string.
+ *
+ * @param kind type to convert
+ * @return string corresponding to the type
*/
const char *
GNUNET_error_type_to_string (enum GNUNET_ErrorType kind)
}
+/**
+ * Convert a hash to a string (for printing debug messages).
+ * This is one of the very few calls in the entire API that is
+ * NOT reentrant!
+ *
+ * @param hc the hash code
+ * @return string form; will be overwritten by next call to GNUNET_h2s.
+ */
+const char *
+GNUNET_h2s (const GNUNET_HashCode * hc)
+{
+ static struct GNUNET_CRYPTO_HashAsciiEncoded ret;
+ GNUNET_CRYPTO_hash_to_enc (hc, &ret);
+ ret.encoding[8] = '\0';
+ return (const char *) ret.encoding;
+}
+
+
/**
* Convert a peer identity to a string (for printing debug messages).
* This is one of the very few calls in the entire API that is
+/**
+ * Convert a "struct sockaddr*" (IPv4 or IPv6 address) to a string
+ * (for printing debug messages). This is one of the very few calls
+ * in the entire API that is NOT reentrant!
+ *
+ * @param addr the address
+ * @param addrlen the length of the address
+ * @return nicely formatted string for the address
+ * will be overwritten by next call to GNUNET_a2s.
+ */
+const char *
+GNUNET_a2s (const struct sockaddr *addr, socklen_t addrlen)
+{
+ static char buf[INET6_ADDRSTRLEN + 8];
+ static char b2[6];
+ const struct sockaddr_in *v4;
+ const struct sockaddr_in6 *v6;
+
+ if (addr == NULL)
+ return _("unknown address");
+ switch (addr->sa_family)
+ {
+ case AF_INET:
+ v4 = (const struct sockaddr_in *) addr;
+ inet_ntop (AF_INET, &v4->sin_addr, buf, INET_ADDRSTRLEN);
+ if (0 == ntohs (v4->sin_port))
+ return buf;
+ strcat (buf, ":");
+ sprintf (b2, "%u", ntohs (v4->sin_port));
+ strcat (buf, b2);
+ return buf;
+ case AF_INET6:
+ v6 = (const struct sockaddr_in6 *) addr;
+ buf[0] = '[';
+ inet_ntop (AF_INET6, &v6->sin6_addr, &buf[1], INET6_ADDRSTRLEN);
+ if (0 == ntohs (v6->sin6_port))
+ return &buf[1];
+ strcat (buf, "]:");
+ sprintf (b2, "%u", ntohs (v6->sin6_port));
+ strcat (buf, b2);
+ return buf;
+ default:
+ return _("invalid address");
+ }
+}
+
+
+/**
+ * Initializer
+ */
+void __attribute__ ((constructor)) GNUNET_util_cl_init ()
+{
+ GNUNET_stderr = stderr;
+}
+
/* end of common_logging.c */