summaryrefslogtreecommitdiffstats
path: root/lib/Utils/logging.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'lib/Utils/logging.cpp')
-rw-r--r--lib/Utils/logging.cpp119
1 files changed, 119 insertions, 0 deletions
diff --git a/lib/Utils/logging.cpp b/lib/Utils/logging.cpp
new file mode 100644
index 0000000..15104b8
--- /dev/null
+++ b/lib/Utils/logging.cpp
@@ -0,0 +1,119 @@
+/*
+ * Utility routines.
+ *
+ * Licensed under GPLv2, see file COPYING in this tarball for details.
+ */
+#include "abrtlib.h"
+#include <syslog.h>
+
+int xfunc_error_retval = EXIT_FAILURE;
+
+void xfunc_die(void)
+{
+ exit(xfunc_error_retval);
+}
+
+const char *msg_prefix = "";
+const char *msg_eol = "\n";
+int logmode = LOGMODE_STDIO;
+
+void verror_msg(const char *s, va_list p, const char* strerr)
+{
+ char *msg;
+ int prefix_len, strerr_len, msgeol_len, used;
+
+ if (!logmode)
+ return;
+
+ if (!s) /* nomsg[_and_die] uses NULL fmt */
+ s = ""; /* some libc don't like printf(NULL) */
+
+ used = vasprintf(&msg, s, p);
+ if (used < 0)
+ return;
+
+ /* This is ugly and costs +60 bytes compared to multiple
+ * fprintf's, but is guaranteed to do a single write.
+ * This is needed for e.g. when multiple children
+ * can produce log messages simultaneously. */
+
+ prefix_len = strlen(msg_prefix);
+ strerr_len = strerr ? strlen(strerr) : 0;
+ msgeol_len = strlen(msg_eol);
+ /* +3 is for ": " before strerr and for terminating NUL */
+ msg = (char*) xrealloc(msg, prefix_len + used + strerr_len + msgeol_len + 3);
+ /* TODO: maybe use writev instead of memmoving? Need full_writev? */
+ if (prefix_len) {
+ memmove(msg + prefix_len, msg, used);
+ used += prefix_len;
+ strcpy(msg, msg_prefix);
+ }
+ if (strerr) {
+ if (s[0]) { /* not perror_nomsg? */
+ msg[used++] = ':';
+ msg[used++] = ' ';
+ }
+ strcpy(&msg[used], strerr);
+ used += strerr_len;
+ }
+ strcpy(&msg[used], msg_eol);
+
+ if (logmode & LOGMODE_STDIO) {
+ fflush(stdout);
+ full_write(STDERR_FILENO, msg, used + msgeol_len);
+ }
+ if (logmode & LOGMODE_SYSLOG) {
+ syslog(LOG_ERR, "%s", msg + prefix_len);
+ }
+ free(msg);
+}
+
+void error_msg_and_die(const char *s, ...)
+{
+ va_list p;
+
+ va_start(p, s);
+ verror_msg(s, p, NULL);
+ va_end(p);
+ xfunc_die();
+}
+
+void error_msg(const char *s, ...)
+{
+ va_list p;
+
+ va_start(p, s);
+ verror_msg(s, p, NULL);
+ va_end(p);
+}
+
+void perror_msg_and_die(const char *s, ...)
+{
+ va_list p;
+
+ va_start(p, s);
+ /* Guard against "<error message>: Success" */
+ verror_msg(s, p, errno ? strerror(errno) : NULL);
+ va_end(p);
+ xfunc_die();
+}
+
+void perror_msg(const char *s, ...)
+{
+ va_list p;
+
+ va_start(p, s);
+ /* Guard against "<error message>: Success" */
+ verror_msg(s, p, errno ? strerror(errno) : NULL);
+ va_end(p);
+}
+
+void simple_perror_msg_and_die(const char *s)
+{
+ perror_msg_and_die("%s", s);
+}
+
+void simple_perror_msg(const char *s)
+{
+ perror_msg("%s", s);
+}