Initial check-in
[him-cellwriter] / src / singleinstance.c
diff --git a/src/singleinstance.c b/src/singleinstance.c
new file mode 100644 (file)
index 0000000..6dfdb89
--- /dev/null
@@ -0,0 +1,98 @@
+
+/*
+
+cellwriter -- a character recognition input method
+Copyright (C) 2007 Michael Levin <risujin@risujin.org>
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+
+*/
+
+#include "config.h"
+#include "common.h"
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <unistd.h>
+
+/*
+        Single-instance checks
+*/
+
+static SingleInstanceFunc on_dupe;
+static int fifo;
+static char *path;
+
+static gboolean check_dupe(void)
+{
+        ssize_t len;
+        char buf[2];
+
+        if (fifo <= 0 || !on_dupe)
+                return FALSE;
+        len = read(fifo, buf, 1);
+        buf[1] = 0;
+        if (len > 0)
+                on_dupe(buf);
+        return TRUE;
+}
+
+void single_instance_cleanup(void)
+{
+        if (fifo > 0)
+                close(fifo);
+        if (path && unlink(path) == -1)
+                log_errno("Failed to unlink program FIFO");
+}
+
+int single_instance_init(SingleInstanceFunc func, const char *str)
+{
+        on_dupe = func;
+        path = g_build_filename(g_get_home_dir(), "." PACKAGE, "fifo", NULL);
+
+        /* If we can open the program FIFO in write-only mode then we must
+           have a reader process already running. We send it a one-byte junk
+           message to wake it up and quit. */
+        if ((fifo = open(path, O_WRONLY | O_NONBLOCK)) > 0) {
+                write(fifo, str, 1);
+                close(fifo);
+                return TRUE;
+        }
+
+        /* The FIFO can be left over from a previous instance if the program
+           crashes or is killed */
+        if (g_file_test(path, G_FILE_TEST_EXISTS)) {
+                g_debug("Program FIFO exists but is not opened on "
+                        "read-only side, deleting\n");
+                single_instance_cleanup();
+        }
+
+        /* Otherwise, create a read-only FIFO and poll for input */
+        fifo = 0;
+        if (mkfifo(path, S_IRUSR | S_IWUSR)) {
+                log_errno("Failed to create program FIFO");
+                return FALSE;
+        }
+        if ((fifo = open(path, O_RDONLY | O_NONBLOCK)) == -1) {
+                log_errno("Failed to open FIFO for reading");
+                return FALSE;
+        }
+
+        /* Setup the polling function */
+        g_timeout_add_full(G_PRIORITY_DEFAULT_IDLE, 1000,
+                           (GSourceFunc)check_dupe, NULL, NULL);
+
+        return FALSE;
+}
+