aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMike Frysinger <vapier@gentoo.org>2012-06-22 14:19:14 -0700
committerMike Frysinger <vapier@gentoo.org>2012-06-23 18:02:43 -0400
commit40abb498ca4a24495fe34e133379382ce8c3eaca (patch)
treea8779b17558a4c96eb2d5c56e82cee4743d408aa /libsbutil
parentuse m4_flatten to make multiline lists easier to handle (diff)
downloadsandbox-40abb498ca4a24495fe34e133379382ce8c3eaca.tar.gz
sandbox-40abb498ca4a24495fe34e133379382ce8c3eaca.tar.bz2
sandbox-40abb498ca4a24495fe34e133379382ce8c3eaca.zip
significantly overhaul output helpers
There are a few major points we want to hit here: - have all output from libsandbox go through portage helpers when we are in the portage environment so that output is properly logged - convert SB_E{info,warn,error} to sb_e{info,warn,error} to match style of other functions and cut down on confusion - move all abort/output helpers to libsbutil so it can be used in all source trees and not just by libsandbox - migrate all abort points to the centralized sb_ebort helper Unfortunately, it's not terribly easy to untangle these into separate patches, but hopefully this shouldn't be too messy as much of it is mechanical: move funcs between files, and change the name of funcs that get called. URL: http://bugs.gentoo.org/278761 Reported-by: Mounir Lamouri <volkmar@gentoo.org> Signed-off-by: Mike Frysinger <vapier@gentoo.org>
Diffstat (limited to 'libsbutil')
-rw-r--r--libsbutil/Makefile.am4
-rw-r--r--libsbutil/sb_backtrace.c15
-rw-r--r--libsbutil/sb_efuncs.c190
-rw-r--r--libsbutil/sb_memory.c37
-rw-r--r--libsbutil/sb_printf.c25
-rw-r--r--libsbutil/sb_proc.c31
-rw-r--r--libsbutil/sb_write_fd.c42
-rw-r--r--libsbutil/sbutil.h39
8 files changed, 321 insertions, 62 deletions
diff --git a/libsbutil/Makefile.am b/libsbutil/Makefile.am
index f1feca3..49a7d3b 100644
--- a/libsbutil/Makefile.am
+++ b/libsbutil/Makefile.am
@@ -20,11 +20,15 @@ libsbutil_la_SOURCES = \
get_tmp_dir.c \
is_env_on.c \
is_env_off.c \
+ sb_backtrace.c \
+ sb_efuncs.c \
sb_open.c \
sb_read.c \
sb_write.c \
+ sb_write_fd.c \
sb_close.c \
sb_printf.c \
+ sb_proc.c \
sb_memory.c \
include/rcscripts/rcutil.h \
include/rcscripts/util/str_list.h \
diff --git a/libsbutil/sb_backtrace.c b/libsbutil/sb_backtrace.c
new file mode 100644
index 0000000..e3d1ed7
--- /dev/null
+++ b/libsbutil/sb_backtrace.c
@@ -0,0 +1,15 @@
+/*
+ * sb_backtrace.c
+ *
+ * Need to keep in a dedicated file so libsandbox can override.
+ *
+ * Copyright 1999-2012 Gentoo Foundation
+ * Licensed under the GPL-2
+ */
+
+#include "headers.h"
+#include "sbutil.h"
+
+void __sb_dump_backtrace(void)
+{
+}
diff --git a/libsbutil/sb_efuncs.c b/libsbutil/sb_efuncs.c
new file mode 100644
index 0000000..248c2bd
--- /dev/null
+++ b/libsbutil/sb_efuncs.c
@@ -0,0 +1,190 @@
+/*
+ * sb_efuncs.c
+ *
+ * Helpers for doing pretty output.
+ *
+ * Copyright 1999-2012 Gentoo Foundation
+ * Licensed under the GPL-2
+ */
+
+#include "headers.h"
+#include "sbutil.h"
+
+static bool nocolor, init_color = false;
+void sb_efunc(const char *color, const char *hilight, const char *format, ...)
+{
+ save_errno();
+
+ int fd = STDERR_FILENO;
+
+ if (!init_color) {
+ nocolor = is_env_on(ENV_NOCOLOR);
+ init_color = true;
+ }
+
+ if (!nocolor)
+ sb_fdprintf(fd, "%s%s%s", color, hilight, COLOR_NORMAL);
+ else
+ sb_fdprintf(fd, "%s", hilight);
+
+ va_list args;
+ va_start(args, format);
+ sb_vfdprintf(fd, format, args);
+ va_end(args);
+
+ restore_errno();
+}
+
+const char *colors[] = {
+ "\033[0m",
+ "\033[32;01m",
+ "\033[33;01m",
+ "\033[31;01m",
+};
+__attribute__((constructor))
+static void sbio_init(void)
+{
+ if (is_env_on(ENV_NOCOLOR))
+ memset(colors, 0, sizeof(colors));
+}
+
+static bool try_portage_helpers = false;
+
+/*
+ * First try to use the helper programs from portage so that it can sanely
+ * log things itself, and so the output doesn't get consumed by something
+ * else #278761. If that fails, fall back to writing to /dev/tty. While
+ * this might annoy some people, using stderr will break tests that try to
+ * validate output #261957.
+ */
+static void sb_vefunc(const char *prog, const char *color, const char *format, va_list args)
+{
+ char shellcode[128];
+ FILE *fp;
+ sighandler_t oldsig;
+ bool is_pipe = false;
+
+ if (try_portage_helpers) {
+ /* If popen() fails, then writes to it will trigger SIGPIPE */
+ /* XXX: convert this to sigaction */
+ oldsig = signal(SIGPIPE, SIG_IGN);
+
+ sprintf(shellcode, "xargs %s 2>/dev/null", prog);
+ fp = sbio_popen(shellcode, "we");
+ is_pipe = true;
+ } else
+ fp = NULL;
+
+ if (!fp) {
+ do_tty:
+ is_pipe = false;
+ int fd = sbio_open(sbio_fallback_path, O_WRONLY|O_CLOEXEC, 0);
+ if (fd >= 0)
+ fp = fdopen(fd, "ae");
+ if (!fp)
+ fp = stderr;
+ }
+
+ sb_fprintf(fp, " %s*%s ", color, COLOR_NORMAL);
+ sb_vfprintf(fp, format, args);
+
+ if (is_pipe) {
+ int status = pclose(fp);
+ if (WEXITSTATUS(status))
+ goto do_tty;
+ } else if (fp != stderr)
+ fclose(fp);
+
+ if (try_portage_helpers)
+ signal(SIGPIPE, oldsig);
+}
+
+void sb_einfo(const char *format, ...)
+{
+ va_list args;
+ va_start(args, format);
+ sb_vefunc("einfo", COLOR_GREEN, format, args);
+ va_end(args);
+}
+
+void sb_debug_dyn(const char *format, ...)
+{
+ if (!is_env_on(ENV_SANDBOX_DEBUG))
+ return;
+
+ va_list args;
+ va_start(args, format);
+ sb_vefunc("einfo", COLOR_GREEN, format, args);
+ va_end(args);
+}
+
+void sb_ewarn(const char *format, ...)
+{
+ va_list args;
+ va_start(args, format);
+ sb_vefunc("ewarn", COLOR_YELLOW, format, args);
+ va_end(args);
+}
+
+void sb_eerror(const char *format, ...)
+{
+ va_list args;
+ va_start(args, format);
+ sb_vefunc("eerror", COLOR_RED, format, args);
+ va_end(args);
+}
+
+void sb_eqawarn(const char *format, ...)
+{
+ va_list args;
+ va_start(args, format);
+ sb_vefunc("eqawarn", COLOR_YELLOW, format, args);
+ va_end(args);
+}
+
+void sb_dump_backtrace(void)
+{
+#ifdef HAVE_BACKTRACE
+ void *funcs[10];
+ int num_funcs;
+ num_funcs = backtrace(funcs, ARRAY_SIZE(funcs));
+ backtrace_symbols_fd(funcs, num_funcs, STDERR_FILENO);
+#endif
+ __sb_dump_backtrace();
+}
+
+void __sb_ebort(const char *file, const char *func, size_t line_num, const char *format, ...)
+{
+ va_list args;
+
+ sb_eerror("%s:%s():%zu: failure (%s):\n", file, func, line_num, strerror(errno));
+
+ va_start(args, format);
+ sb_vefunc("eerror", COLOR_RED, format, args);
+ va_end(args);
+
+ sb_dump_backtrace();
+
+#ifndef NDEBUG
+ if (is_env_on("SANDBOX_GDB")) {
+ sb_einfo("attempting to autolaunch gdb; please wait ...\n\n");
+ pid_t crashed_pid = getpid();
+ switch (fork()) {
+ case -1: break;
+ case 0: {
+ char pid[10];
+ snprintf(pid, sizeof(pid), "%i", crashed_pid);
+ unsetenv(ENV_LD_PRELOAD);
+ /*sb_unwrapped_*/execlp("gdb", "gdb", "--quiet", "--pid", pid, "-ex", "bt full", NULL);
+ break;
+ }
+ default: {
+ int status;
+ wait(&status);
+ }
+ }
+ }
+#endif
+
+ abort();
+}
diff --git a/libsbutil/sb_memory.c b/libsbutil/sb_memory.c
index 40a4762..bdc054f 100644
--- a/libsbutil/sb_memory.c
+++ b/libsbutil/sb_memory.c
@@ -1,5 +1,5 @@
/*
- * debug.c
+ * sb_memory.c
*
* Simle debugging/logging macro's and functions.
*
@@ -16,11 +16,8 @@ __xcalloc(size_t nmemb, size_t size, const char *file, const char *func, size_t
{
void *ret = calloc(nmemb, size);
- if (ret == NULL) {
- SB_EERROR("calloc()", " %s:%s():%zu: calloc(%zu, %zu) failed: %s\n",
- file, func, line, nmemb, size, strerror(errno));
- abort();
- }
+ if (ret == NULL)
+ __sb_ebort(file, func, line, "calloc(%zu, %zu)\n", nmemb, size);
return ret;
}
@@ -30,11 +27,8 @@ __xmalloc(size_t size, const char *file, const char *func, size_t line)
{
void *ret = malloc(size);
- if (ret == NULL) {
- SB_EERROR("malloc()", " %s:%s():%zu: malloc(%zu) failed: %s\n",
- file, func, line, size, strerror(errno));
- abort();
- }
+ if (ret == NULL)
+ __sb_ebort(file, func, line, "malloc(%zu)\n", size);
return ret;
}
@@ -50,11 +44,8 @@ __xrealloc(void *ptr, size_t size, const char *file, const char *func, size_t li
{
void *ret = realloc(ptr, size);
- if (ret == NULL) {
- SB_EERROR("realloc()", " %s:%s():%zu: realloc(%p, %zu) failed: %s\n",
- file, func, line, ptr, size, strerror(errno));
- abort();
- }
+ if (ret == NULL)
+ __sb_ebort(file, func, line, "realloc(%p, %zu)\n", ptr, size);
return ret;
}
@@ -64,11 +55,8 @@ __xstrdup(const char *str, const char *file, const char *func, size_t line)
{
char *ret = strdup(str);
- if (ret == NULL) {
- SB_EERROR("strdup()", " %s:%s():%zu: strdup(%p) failed: %s\n",
- file, func, line, str, strerror(errno));
- abort();
- }
+ if (ret == NULL)
+ __sb_ebort(file, func, line, "strdup(%p)\n", str);
return ret;
}
@@ -94,11 +82,8 @@ __xstrndup(const char *str, size_t size, const char *file, const char *func, siz
{
char *ret = strndup(str, size);
- if (ret == NULL) {
- SB_EERROR("strndup()", " %s:%s():%zu: strndup(%p, %zu) failed: %s\n",
- file, func, line, str, size, strerror(errno));
- abort();
- }
+ if (ret == NULL)
+ __sb_ebort(file, func, line, "strndup(%p, %zu)\n", str, size);
return ret;
}
diff --git a/libsbutil/sb_printf.c b/libsbutil/sb_printf.c
index d3a27df..1ad9e23 100644
--- a/libsbutil/sb_printf.c
+++ b/libsbutil/sb_printf.c
@@ -187,28 +187,3 @@ void sb_printf(const char *format, ...)
sb_vfdprintf(STDERR_FILENO, format, args);
va_end(args);
}
-
-static bool nocolor, init_color = false;
-void sb_efunc(const char *color, const char *hilight, const char *format, ...)
-{
- save_errno();
-
- int fd = STDERR_FILENO;
-
- if (!init_color) {
- nocolor = is_env_on(ENV_NOCOLOR);
- init_color = true;
- }
-
- if (!nocolor)
- sb_fdprintf(fd, "%s%s%s", color, hilight, COLOR_NORMAL);
- else
- sb_fdprintf(fd, "%s", hilight);
-
- va_list args;
- va_start(args, format);
- sb_vfdprintf(fd, format, args);
- va_end(args);
-
- restore_errno();
-}
diff --git a/libsbutil/sb_proc.c b/libsbutil/sb_proc.c
new file mode 100644
index 0000000..c583d95
--- /dev/null
+++ b/libsbutil/sb_proc.c
@@ -0,0 +1,31 @@
+/*
+ * funcs for poking around /proc
+ *
+ * Copyright 1999-2012 Gentoo Foundation
+ * Licensed under the GPL-2
+ */
+
+#include "headers.h"
+#include "sbutil.h"
+
+const char sb_fd_dir[] =
+#if defined(SANDBOX_PROC_SELF_FD)
+ "/proc/self/fd"
+#elif defined(SANDBOX_DEV_FD)
+ "/dev/fd"
+#else
+# error "how do i access a proc's fd/ tree ?"
+#endif
+;
+
+const char *sb_get_cmdline(pid_t pid)
+{
+#if !defined(SANDBOX_PROC_1_CMDLINE) && !defined(SANDBOX_PROC_SELF_CMDLINE) && !defined(SANDBOX_PROC_dd_CMDLINE)
+# error "how do i access a proc's cmdline ?"
+#endif
+ static char path[256];
+ if (!pid)
+ pid = getpid();
+ sprintf(path, "/proc/%i/cmdline", pid);
+ return path;
+}
diff --git a/libsbutil/sb_write_fd.c b/libsbutil/sb_write_fd.c
new file mode 100644
index 0000000..f19d7de
--- /dev/null
+++ b/libsbutil/sb_write_fd.c
@@ -0,0 +1,42 @@
+/*
+ * helper for sucking up a file and writing it to a fd.
+ * good for copying the contents of small status files
+ * into a log file.
+ *
+ * Copyright 1999-2012 Gentoo Foundation
+ * Licensed under the GPL-2
+ */
+
+#include "headers.h"
+#include "sbutil.h"
+
+int sb_copy_file_to_fd(const char *file, int ofd)
+{
+ int ret = -1;
+
+ int ifd = sb_open(file, O_RDONLY|O_CLOEXEC, 0);
+ if (ifd == -1)
+ return ret;
+
+ size_t pagesz = getpagesize();
+ char *buf = xmalloc(pagesz);
+ while (1) {
+ size_t len = sb_read(ifd, buf, pagesz);
+ if (len == -1)
+ goto error;
+ else if (!len)
+ break;
+ size_t i;
+ for (i = 0; i < len; ++i)
+ if (!buf[i])
+ buf[i] = ' ';
+ if (sb_write(ofd, buf, len) != len)
+ goto error;
+ }
+
+ ret = 0;
+ error:
+ sb_close(ifd);
+ free(buf);
+ return ret;
+}
diff --git a/libsbutil/sbutil.h b/libsbutil/sbutil.h
index f45402e..f275514 100644
--- a/libsbutil/sbutil.h
+++ b/libsbutil/sbutil.h
@@ -42,8 +42,7 @@
#define ENV_SANDBOX_VERBOSE "SANDBOX_VERBOSE"
#define ENV_SANDBOX_DEBUG "SANDBOX_DEBUG"
-extern const char env_sandbox_testing[];
-#define ENV_SANDBOX_TESTING env_sandbox_testing
+#define ENV_SANDBOX_TESTING "__SANDBOX_TESTING"
#define ENV_SANDBOX_LIB "SANDBOX_LIB"
#define ENV_SANDBOX_BASHRC "SANDBOX_BASHRC"
@@ -67,15 +66,11 @@ extern const char env_sandbox_testing[];
#define SB_BUF_LEN 2048
-#define COLOR_NORMAL "\033[0m"
-#define COLOR_GREEN "\033[32;01m"
-#define COLOR_YELLOW "\033[33;01m"
-#define COLOR_RED "\033[31;01m"
-
-/* Gentoo style e* printing macro's */
-#define SB_EINFO(_hilight, _args...) sb_efunc(COLOR_GREEN, _hilight, _args)
-#define SB_EWARN(_hilight, _args...) sb_efunc(COLOR_YELLOW, _hilight, _args)
-#define SB_EERROR(_hilight, _args...) sb_efunc(COLOR_RED, _hilight, _args)
+extern const char *colors[];
+#define COLOR_NORMAL colors[0]
+#define COLOR_GREEN colors[1]
+#define COLOR_YELLOW colors[2]
+#define COLOR_RED colors[3]
char *get_sandbox_conf(void);
char *get_sandbox_confd(char *path);
@@ -87,19 +82,41 @@ int get_tmp_dir(char *path);
bool is_env_on (const char *);
bool is_env_off (const char *);
+/* proc helpers */
+extern const char sb_fd_dir[];
+#define sb_get_fd_dir() sb_fd_dir
+const char *sb_get_cmdline(pid_t pid);
+
/* libsandbox need to use a wrapper for open */
attribute_hidden extern int (*sbio_open)(const char *, int, mode_t);
+attribute_hidden extern FILE *(*sbio_popen)(const char *, const char *);
+extern const char sbio_fallback_path[];
/* Convenience functions to reliably open, read and write to a file */
int sb_open(const char *path, int flags, mode_t mode);
size_t sb_read(int fd, void *buf, size_t count);
size_t sb_write(int fd, const void *buf, size_t count);
int sb_close(int fd);
+int sb_copy_file_to_fd(const char *file, int ofd);
/* Reliable output */
__printf(1, 2) void sb_printf(const char *format, ...);
__printf(2, 3) void sb_fdprintf(int fd, const char *format, ...);
__printf(2, 0) void sb_vfdprintf(int fd, const char *format, va_list args);
__printf(3, 4) void sb_efunc(const char *color, const char *hilight, const char *format, ...);
+__printf(1, 2) void sb_einfo(const char *format, ...);
+__printf(1, 2) void sb_ewarn(const char *format, ...);
+__printf(1, 2) void sb_eerror(const char *format, ...);
+__printf(1, 2) void sb_eqawarn(const char *format, ...);
+__printf(1, 2) void sb_debug_dyn(const char *format, ...);
+__printf(4, 5) void __sb_ebort(const char *file, const char *func, size_t line_num, const char *format, ...) __noreturn;
+#define sb_ebort(format, ...) __sb_ebort(__FILE__, __func__, __LINE__, format, ## __VA_ARGS__)
+void sb_dump_backtrace(void);
+void __sb_dump_backtrace(void);
+#define sb_assert(cond) \
+ do { \
+ if (!(cond)) \
+ sb_ebort("assertion failure !(%s)\n", #cond); \
+ } while (0)
#define sb_fprintf(fp, ...) sb_fdprintf(fileno(fp), __VA_ARGS__)
#define sb_vfprintf(fp, ...) sb_vfdprintf(fileno(fp), __VA_ARGS__)