Initial check-in
[him-cellwriter] / src / singleinstance.c
1
2 /*
3
4 cellwriter -- a character recognition input method
5 Copyright (C) 2007 Michael Levin <risujin@risujin.org>
6
7 This program is free software; you can redistribute it and/or
8 modify it under the terms of the GNU General Public License
9 as published by the Free Software Foundation; either version 2
10 of the License, or (at your option) any later version.
11
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15 GNU General Public License for more details.
16
17 You should have received a copy of the GNU General Public License
18 along with this program; if not, write to the Free Software
19 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
20
21 */
22
23 #include "config.h"
24 #include "common.h"
25 #include <sys/stat.h>
26 #include <fcntl.h>
27 #include <unistd.h>
28
29 /*
30         Single-instance checks
31 */
32
33 static SingleInstanceFunc on_dupe;
34 static int fifo;
35 static char *path;
36
37 static gboolean check_dupe(void)
38 {
39         ssize_t len;
40         char buf[2];
41
42         if (fifo <= 0 || !on_dupe)
43                 return FALSE;
44         len = read(fifo, buf, 1);
45         buf[1] = 0;
46         if (len > 0)
47                 on_dupe(buf);
48         return TRUE;
49 }
50
51 void single_instance_cleanup(void)
52 {
53         if (fifo > 0)
54                 close(fifo);
55         if (path && unlink(path) == -1)
56                 log_errno("Failed to unlink program FIFO");
57 }
58
59 int single_instance_init(SingleInstanceFunc func, const char *str)
60 {
61         on_dupe = func;
62         path = g_build_filename(g_get_home_dir(), "." PACKAGE, "fifo", NULL);
63
64         /* If we can open the program FIFO in write-only mode then we must
65            have a reader process already running. We send it a one-byte junk
66            message to wake it up and quit. */
67         if ((fifo = open(path, O_WRONLY | O_NONBLOCK)) > 0) {
68                 write(fifo, str, 1);
69                 close(fifo);
70                 return TRUE;
71         }
72
73         /* The FIFO can be left over from a previous instance if the program
74            crashes or is killed */
75         if (g_file_test(path, G_FILE_TEST_EXISTS)) {
76                 g_debug("Program FIFO exists but is not opened on "
77                         "read-only side, deleting\n");
78                 single_instance_cleanup();
79         }
80
81         /* Otherwise, create a read-only FIFO and poll for input */
82         fifo = 0;
83         if (mkfifo(path, S_IRUSR | S_IWUSR)) {
84                 log_errno("Failed to create program FIFO");
85                 return FALSE;
86         }
87         if ((fifo = open(path, O_RDONLY | O_NONBLOCK)) == -1) {
88                 log_errno("Failed to open FIFO for reading");
89                 return FALSE;
90         }
91
92         /* Setup the polling function */
93         g_timeout_add_full(G_PRIORITY_DEFAULT_IDLE, 1000,
94                            (GSourceFunc)check_dupe, NULL, NULL);
95
96         return FALSE;
97 }
98