Mercurial > ~mikael > mcabber > hg
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... */ |