aboutsummaryrefslogtreecommitdiffstats
path: root/error.c
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--error.c63
1 files changed, 55 insertions, 8 deletions
diff --git a/error.c b/error.c
index 4c8a1ff..5408c07 100644
--- a/error.c
+++ b/error.c
@@ -19,6 +19,31 @@
*/
#include "wavemon.h"
#include <stdarg.h>
+#if HAVE_LIBCAP
+#include <sys/capability.h>
+
+static bool has_capability(cap_value_t cap)
+{
+ cap_t cap_proc = cap_get_proc();
+ cap_flag_value_t cur_val;
+
+ if (cap_get_flag(cap_proc, cap, CAP_EFFECTIVE, &cur_val))
+ err_sys("cap_get_flag(CAP_EFFECTIVE)");
+ cap_free(cap_proc);
+
+ return cur_val == CAP_SET;
+}
+
+bool has_net_admin_capability(void)
+{
+ return has_capability(CAP_NET_ADMIN);
+}
+#else /* !HAVE_LIBCAP */
+bool has_net_admin_capability(void)
+{
+ return geteuid() == 0;
+}
+#endif
/*
* For displaying warning messages that are unrelated to system calls,
@@ -34,6 +59,34 @@ void err_msg(const char *format, ...)
sleep(WARN_DISPLAY_DELAY);
}
+/**
+ * terminate_all_processes - terminate wavemon and reset screen
+ * @fmt: printf-like format string
+ * @strerr: set to non-0 if termination is due to failed system call
+ * @ap: argument list for @fmt
+ */
+static void terminate_all_processes(const char *fmt, int strerr, va_list ap)
+{
+ int saved_errno = strerr ? errno : 0;
+ /*
+ * wavemon runs in its own process group. Block TERM in this process,
+ * but send to all others (parent or child), which by default do not
+ * block TERM.
+ */
+ xsignal(SIGTERM, SIG_IGN);
+ endwin();
+ kill(0, SIGTERM);
+ reset_shell_mode();
+ if (saved_errno) {
+ errno = saved_errno;
+ vwarn(fmt, ap);
+ } else {
+ vwarnx(fmt, ap);
+ }
+ va_end(ap);
+ exit(EXIT_FAILURE);
+}
+
/*
* Abort on fatal error unrelated to system call.
*/
@@ -41,11 +94,8 @@ void err_quit(const char *format, ...)
{
va_list argp;
- endwin();
-
va_start(argp, format);
- verrx(EXIT_FAILURE, format, argp);
- va_end(argp);
+ terminate_all_processes(format, false, argp);
}
/*
@@ -55,9 +105,6 @@ void err_sys(const char *format, ...)
{
va_list argp;
- endwin();
-
va_start(argp, format);
- verr(EXIT_FAILURE, format, argp);
- va_end(argp);
+ terminate_all_processes(format, true, argp);
}