comparison mcabber/mcabber/fifo_internal.c @ 2079:8da280d34b48

Rename FIFO module file name Module: fifo_module.c -> fifo.c Code: fifo.c -> fifo_internal.c Previous scheme didn't seem go well along with new autotools since they were expecting fifo_module.* object files.
author Mikael Berthe <mikael@lilotux.net>
date Sun, 29 Sep 2013 14:31:14 +0200
parents mcabber/mcabber/fifo.c@33483d3324cf
children 038c4d601011
comparison
equal deleted inserted replaced
2078:2a62243f6da9 2079:8da280d34b48
1 /*
2 * fifo_internal.c -- Read commands from a named pipe
3 *
4 * Copyright (C) 2008,2009 Mikael Berthe <mikael@lilotux.net>
5 * Copyright (C) 2009 Myhailo Danylenko <isbear@ukrpost.net>
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or (at
10 * your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307
20 * USA
21 */
22
23 #include <stdlib.h>
24 #include <glib.h>
25 #include <sys/types.h>
26 #include <sys/stat.h>
27 #include <fcntl.h>
28 #include <unistd.h>
29 #include <errno.h>
30 #include <fcntl.h>
31
32 #include "commands.h"
33 #include "logprint.h"
34 #include "utils.h"
35 #include "settings.h"
36 #include "main.h"
37
38 static char *fifo_name = NULL;
39 static GIOChannel *fifo_channel = NULL;
40
41 static const char *FIFO_ENV_NAME = "MCABBER_FIFO";
42
43 static gboolean attach_fifo(const char *name);
44
45 static guint fifo_callback(GIOChannel *channel,
46 GIOCondition condition,
47 gpointer data)
48 {
49 if (condition & (G_IO_IN|G_IO_PRI)) {
50 GIOStatus chstat;
51 gchar *buf;
52 gsize endpos;
53
54 chstat = g_io_channel_read_line(channel, &buf, NULL, &endpos, NULL);
55 if (chstat == G_IO_STATUS_ERROR || chstat == G_IO_STATUS_EOF) {
56 if (!attach_fifo(fifo_name))
57 scr_LogPrint(LPRINT_LOGNORM,
58 "Reopening fifo failed! Fifo will not work from now!");
59 return FALSE;
60 }
61 if (buf) {
62 guint logflag;
63 guint fifo_ignore = settings_opt_get_int("fifo_ignore");
64
65 if (endpos)
66 buf[endpos] = '\0';
67
68 if (settings_opt_get_int("fifo_hide_commands"))
69 logflag = LPRINT_LOG;
70 else
71 logflag = LPRINT_LOGNORM;
72 scr_LogPrint(logflag, "%s FIFO command: %s",
73 (fifo_ignore ? "Ignoring" : "Executing"), buf);
74 if (!fifo_ignore) {
75 if (process_command(buf, TRUE) == 255)
76 mcabber_set_terminate_ui();
77 }
78
79 g_free(buf);
80 }
81 } else if (condition & (G_IO_ERR|G_IO_NVAL|G_IO_HUP)) {
82 if (!attach_fifo(fifo_name))
83 scr_LogPrint(LPRINT_LOGNORM,
84 "Reopening fifo failed! Fifo will not work from now!");
85 return FALSE;
86 }
87 return TRUE;
88 }
89
90 static void fifo_destroy_callback(gpointer data)
91 {
92 GIOChannel *channel = (GIOChannel *)data;
93 g_io_channel_unref(channel);
94 channel = NULL;
95 }
96
97 static gboolean check_fifo(const char *name)
98 {
99 struct stat finfo;
100 if (stat(name, &finfo) == -1) {
101 /* some unknown error */
102 if (errno != ENOENT)
103 return FALSE;
104 /* fifo not yet exists */
105 if (mkfifo(name, S_IRUSR|S_IWUSR) != -1)
106 return check_fifo(name);
107 else
108 return FALSE;
109 }
110
111 /* file exists */
112 if (S_ISFIFO(finfo.st_mode))
113 return TRUE;
114 else
115 return FALSE;
116 }
117
118 static gboolean attach_fifo(const char *name)
119 {
120 GSource *source;
121 int fd = open (name, O_RDONLY|O_NONBLOCK);
122 if (fd == -1)
123 return FALSE;
124
125 if (fifo_channel)
126 g_io_channel_unref(fifo_channel);
127
128 fifo_channel = g_io_channel_unix_new(fd);
129
130 g_io_channel_set_flags(fifo_channel, G_IO_FLAG_NONBLOCK, NULL);
131 g_io_channel_set_encoding(fifo_channel, NULL, NULL);
132 g_io_channel_set_close_on_unref(fifo_channel, TRUE);
133
134 source = g_io_create_watch(fifo_channel,
135 G_IO_IN|G_IO_PRI|G_IO_ERR|G_IO_HUP|G_IO_NVAL);
136 g_source_set_callback(source, (GSourceFunc)fifo_callback,
137 (gpointer)fifo_channel,
138 (GDestroyNotify)fifo_destroy_callback);
139 g_source_attach(source, main_context);
140
141 return TRUE;
142 }
143
144 void fifo_deinit(void)
145 {
146 unsetenv(FIFO_ENV_NAME);
147
148 if (fifo_channel)
149 g_source_remove_by_user_data(fifo_channel);
150 /* channel itself should be destroyed by destruction callback */
151 /* destroy open fifo */
152 if (fifo_name) {
153 /* well, that may create fifo, and then unlink,
154 * but at least we will not destroy non-fifo data */
155 if (check_fifo(fifo_name))
156 unlink(fifo_name);
157 g_free(fifo_name);
158 fifo_name = NULL;
159 }
160 }
161
162 // fifo_init_internal(path)
163 // If path is NULL, reopen existing fifo, else open anew.
164 static int fifo_init_internal(const char *fifo_path)
165 {
166 if (fifo_path) {
167 fifo_deinit();
168 fifo_name = expand_filename(fifo_path);
169
170 if (!check_fifo(fifo_name)) {
171 scr_LogPrint(LPRINT_LOGNORM, "WARNING: Cannot create the FIFO. "
172 "%s already exists and is not a pipe", fifo_name);
173 g_free(fifo_name);
174 fifo_name = NULL;
175 return -1;
176 }
177 } else if (fifo_name)
178 g_source_remove_by_user_data(fifo_channel);
179 else
180 return -1;
181
182 if (!attach_fifo(fifo_name)) {
183 scr_LogPrint(LPRINT_LOGNORM, "Error: Cannot open fifo");
184 return -1;
185 }
186
187 setenv(FIFO_ENV_NAME, fifo_name, 1);
188
189 scr_LogPrint(LPRINT_LOGNORM, "FIFO initialized (%s)", fifo_path);
190 return 1;
191 }
192
193 static gchar *fifo_guard(const gchar *key, const gchar *new_value)
194 {
195 if (new_value)
196 fifo_init_internal(new_value);
197 else
198 fifo_deinit();
199 return g_strdup(new_value);
200 }
201
202 // Returns 1 in case of success, -1 on error
203 int fifo_init(void)
204 {
205 const char *path = settings_opt_get("fifo_name");
206 static gboolean guard_installed = FALSE;
207 if (!guard_installed)
208 if (!(guard_installed = settings_set_guard("fifo_name", fifo_guard)))
209 scr_LogPrint(LPRINT_DEBUG, "fifo: BUG: Cannot install option guard!");
210 if (path)
211 return fifo_init_internal(path);
212 return 1;
213 }
214
215 /* vim: set expandtab cindent cinoptions=>2\:2(0 sw=2 ts=2: For Vim users... */