From a1d1f456a1fbf44bfa5c6a9d041023ac498b0c46 Mon Sep 17 00:00:00 2001
From: Theo Buehler <theo@math.ethz.ch>
Date: Thu, 14 Jan 2016 10:06:34 +0100
Subject: [PATCH] Add pledge(2) support for OpenBSD

pledges for i3:
"stdio rpath unix" for talking to the i3 socket usually in /tmp
"proc exec" for executing programs
"wpath cpath" are needed for the restart-in-place functionality

To make this work, @semarie pointed out that it is sufficient to ensure
that we get physical_mem_bytes only once, namely in init_logging().

pledges for i3-msg:
"stdio rpath unix" are needed for talking to the i3-socket

pledges for i3-nagbar
"rpath getpw" to find the home directory
"wpath cpath" to write the script
"proc exec" to execute the script
---
 i3-msg/main.c    |  4 ++++
 i3-nagbar/main.c |  5 +++++
 src/log.c        | 21 ++++++++++++---------
 src/main.c       |  5 +++++
 4 files changed, 26 insertions(+), 9 deletions(-)

diff --git a/i3-msg/main.c b/i3-msg/main.c
index e4a0628c..36691cae 100644
--- a/i3-msg/main.c
+++ b/i3-msg/main.c
@@ -119,6 +119,10 @@ static yajl_callbacks reply_callbacks = {
 };
 
 int main(int argc, char *argv[]) {
+#if defined(__OpenBSD__)
+    if (pledge("stdio rpath unix", NULL) == -1)
+        err(EXIT_FAILURE, "pledge");
+#endif
     char *env_socket_path = getenv("I3SOCK");
     if (env_socket_path)
         socket_path = sstrdup(env_socket_path);
diff --git a/i3-nagbar/main.c b/i3-nagbar/main.c
index 38740774..674fcb7d 100644
--- a/i3-nagbar/main.c
+++ b/i3-nagbar/main.c
@@ -470,6 +470,11 @@ int main(int argc, char *argv[]) {
     font = load_font(pattern, true);
     set_font(&font);
 
+#if defined(__OpenBSD__)
+    if (pledge("stdio rpath wpath cpath getpw proc exec", NULL) == -1)
+        err(EXIT_FAILURE, "pledge");
+#endif
+
     xcb_rectangle_t win_pos = get_window_position();
 
     xcb_cursor_t cursor;
diff --git a/src/log.c b/src/log.c
index b7ad072f..e8a08b53 100644
--- a/src/log.c
+++ b/src/log.c
@@ -58,6 +58,8 @@ static char *loglastwrap;
 static int logbuffer_size;
 /* File descriptor for shm_open. */
 static int logbuffer_shm;
+/* Size (in bytes) of physical memory */
+static long long physical_mem_bytes;
 
 /*
  * Writes the offsets for the next write and for the last wrap to the
@@ -89,6 +91,16 @@ void init_logging(void) {
             }
         }
     }
+    if (physical_mem_bytes == 0) {
+#if defined(__APPLE__)
+        int mib[2] = {CTL_HW, HW_MEMSIZE};
+        size_t length = sizeof(long long);
+        sysctl(mib, 2, &physical_mem_bytes, &length, NULL, 0);
+#else
+        physical_mem_bytes = (long long)sysconf(_SC_PHYS_PAGES) *
+                             sysconf(_SC_PAGESIZE);
+#endif
+    }
     /* Start SHM logging if shmlog_size is > 0. shmlog_size is SHMLOG_SIZE by
      * default on development versions, and 0 on release versions. If it is
      * not > 0, the user has turned it off, so let's close the logbuffer. */
@@ -108,15 +120,6 @@ void open_logbuffer(void) {
          * For 512 MiB of RAM this will lead to a 5 MiB log buffer.
          * At the moment (2011-12-10), no testcase leads to an i3 log
          * of more than ~ 600 KiB. */
-    long long physical_mem_bytes;
-#if defined(__APPLE__)
-    int mib[2] = {CTL_HW, HW_MEMSIZE};
-    size_t length = sizeof(long long);
-    sysctl(mib, 2, &physical_mem_bytes, &length, NULL, 0);
-#else
-    physical_mem_bytes = (long long)sysconf(_SC_PHYS_PAGES) *
-                         sysconf(_SC_PAGESIZE);
-#endif
     logbuffer_size = min(physical_mem_bytes * 0.01, shmlog_size);
 #if defined(__FreeBSD__)
     sasprintf(&shmlogname, "/tmp/i3-log-%d", getpid());
diff --git a/src/main.c b/src/main.c
index 78835e08..b2ce17d8 100644
--- a/src/main.c
+++ b/src/main.c
@@ -802,6 +802,11 @@ int main(int argc, char *argv[]) {
         xcb_free_pixmap(conn, pixmap);
     }
 
+#if defined(__OpenBSD__)
+    if (pledge("stdio rpath wpath cpath proc exec unix", NULL) == -1)
+        err(EXIT_FAILURE, "pledge");
+#endif
+
     struct sigaction action;
 
     action.sa_sigaction = handle_signal;