]> git.ipfire.org Git - thirdparty/strongswan.git/commitdiff
utils: Add a wait_sigint() function to wait for SIGINT or equivalent
authorMartin Willi <martin@revosec.ch>
Mon, 10 Mar 2014 11:12:47 +0000 (12:12 +0100)
committerMartin Willi <martin@revosec.ch>
Wed, 4 Jun 2014 13:53:11 +0000 (15:53 +0200)
src/libstrongswan/utils/utils.c
src/libstrongswan/utils/utils.h

index 0f12b58d7fd5940d93d164e558bd64c9e042bed8..8ef9a1f338002793ca15920fb1b8ff0924cd7626 100644 (file)
 #include <limits.h>
 #include <dirent.h>
 #include <time.h>
+#ifndef WIN32
+# include <signal.h>
+#endif
 
 #include <library.h>
 #include <utils/debug.h>
 #include <utils/chunk.h>
 #include <collections/enumerator.h>
 #include <threading/spinlock.h>
+#include <threading/mutex.h>
+#include <threading/condvar.h>
 
 ENUM(status_names, SUCCESS, NEED_MORE,
        "SUCCESS",
@@ -222,6 +227,84 @@ char* strreplace(const char *str, const char *search, const char *replace)
        return res;
 }
 
+#ifdef WIN32
+
+/**
+ * Flag to indicate signaled wait_sigint()
+ */
+static bool sigint_signaled = FALSE;
+
+/**
+ * Condvar to wait in wait_sigint()
+ */
+static condvar_t *sigint_cond;
+
+/**
+ * Mutex to check signaling()
+ */
+static mutex_t *sigint_mutex;
+
+/**
+ * Control handler to catch ^C
+ */
+static BOOL handler(DWORD dwCtrlType)
+{
+       switch (dwCtrlType)
+       {
+               case CTRL_C_EVENT:
+               case CTRL_BREAK_EVENT:
+               case CTRL_CLOSE_EVENT:
+                       sigint_mutex->lock(sigint_mutex);
+                       sigint_signaled = TRUE;
+                       sigint_cond->signal(sigint_cond);
+                       sigint_mutex->unlock(sigint_mutex);
+                       return TRUE;
+               default:
+                       return FALSE;
+       }
+}
+
+/**
+ * Windows variant
+ */
+void wait_sigint()
+{
+       SetConsoleCtrlHandler(handler, TRUE);
+
+       sigint_mutex = mutex_create(MUTEX_TYPE_DEFAULT);
+       sigint_cond = condvar_create(CONDVAR_TYPE_DEFAULT);
+
+       sigint_mutex->lock(sigint_mutex);
+       while (!sigint_signaled)
+       {
+               sigint_cond->wait(sigint_cond, sigint_mutex);
+       }
+       sigint_mutex->unlock(sigint_mutex);
+
+       sigint_mutex->destroy(sigint_mutex);
+       sigint_cond->destroy(sigint_cond);
+}
+
+#else /* !WIN32 */
+
+/**
+ * Unix variant
+ */
+void wait_sigint()
+{
+       sigset_t set;
+       int sig;
+
+       sigemptyset(&set);
+       sigaddset(&set, SIGINT);
+       sigaddset(&set, SIGTERM);
+
+       sigprocmask(SIG_BLOCK, &set, NULL);
+       sigwait(&set, &sig);
+}
+
+#endif
+
 /**
  * Described in header.
  */
index ac0841c49ef47d195e889e558d9fd49309adbafe..961ddb5835af410800e208c783639c035c63d809 100644 (file)
@@ -542,6 +542,11 @@ char *translate(char *str, const char *from, const char *to);
  */
 char *strreplace(const char *str, const char *search, const char *replace);
 
+/**
+ * Portable function to wait for SIGINT/SIGTERM (or equivalent).
+ */
+void wait_sigint();
+
 /**
  * Like dirname(3) returns the directory part of the given null-terminated
  * pathname, up to but not including the final '/' (or '.' if no '/' is found).