0.1.1
by Reinhard Tartler
Import upstream version 0.11.0~svn1143 |
1 |
/* $Id: plugin_fifo.c 1112 2010-02-14 02:47:49Z michael $
|
2 |
* $URL: https://ssl.bulix.org/svn/lcd4linux/trunk/plugin_fifo.c $
|
|
3 |
*
|
|
4 |
* Fifo plugin
|
|
5 |
*
|
|
6 |
* Copyright (C) 2008 Michael Vogt <michu@neophob.com>
|
|
7 |
* Copyright (C) 2010 Mattia Jona-Lasinio <mjona@users.sourceforge.net>
|
|
8 |
* Copyright (C) 2004, 2005, 2006, 2007, 2008, 2010 The LCD4Linux Team <lcd4linux-devel@users.sourceforge.net>
|
|
9 |
*
|
|
10 |
* This file is part of LCD4Linux.
|
|
11 |
*
|
|
12 |
* LCD4Linux is free software; you can redistribute it and/or modify
|
|
13 |
* it under the terms of the GNU General Public License as published by
|
|
14 |
* the Free Software Foundation; either version 2, or (at your option)
|
|
15 |
* any later version.
|
|
16 |
*
|
|
17 |
* LCD4Linux is distributed in the hope that it will be useful,
|
|
18 |
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
19 |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
20 |
* GNU General Public License for more details.
|
|
21 |
*
|
|
22 |
* You should have received a copy of the GNU General Public License
|
|
23 |
* along with this program; if not, write to the Free Software
|
|
24 |
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
|
25 |
*
|
|
26 |
*/
|
|
27 |
||
28 |
/*
|
|
29 |
* Configuration parameters:
|
|
30 |
*
|
|
31 |
* - FifoPath 'string' : use <string> as the fifo complete file path
|
|
32 |
* If absent use /tmp/lcd4linux.fifo)
|
|
33 |
*
|
|
34 |
* - FifoBufSize num : if the plugin is unable to determine the display size then
|
|
35 |
* set the size of the internal buffer to <num> characters
|
|
36 |
* otherwise use the display size (number of columns).
|
|
37 |
* If no display size is available and no FifoBufSize parameter
|
|
38 |
* is specified then arbitrarily set the internal buffer size
|
|
39 |
* to 80 characters.
|
|
40 |
*/
|
|
41 |
||
42 |
#include "config.h" |
|
43 |
||
44 |
#include <stdlib.h> |
|
45 |
#include <stdio.h> |
|
46 |
#include <string.h> |
|
47 |
#include <errno.h> |
|
48 |
#include <unistd.h> |
|
49 |
#include <fcntl.h> |
|
50 |
#include <sys/stat.h> |
|
51 |
#include <signal.h> |
|
52 |
||
53 |
#include "debug.h" |
|
54 |
#include "plugin.h" |
|
55 |
#include "cfg.h" |
|
56 |
||
57 |
#ifdef WITH_DMALLOC
|
|
58 |
#include <dmalloc.h> |
|
59 |
#endif
|
|
60 |
||
61 |
#define FIFO_MAXPATH 256
|
|
62 |
#define FIFO_DEFAULT_PATH /tmp/lcd4linux.fifo
|
|
63 |
#define FIFO_DEFAULT_BUFSIZE 80
|
|
64 |
#define str(s) #s
|
|
65 |
#define string(s) str(s)
|
|
66 |
||
67 |
struct FifoData { |
|
68 |
char *path; |
|
69 |
char *msg; |
|
70 |
int msglen; |
|
71 |
int input; |
|
72 |
int created; |
|
73 |
};
|
|
74 |
||
75 |
static struct FifoData fd = { |
|
76 |
.path = NULL, |
|
77 |
.msg = NULL, |
|
78 |
.msglen = -1, |
|
79 |
.input = -1, |
|
80 |
.created = -1, |
|
81 |
};
|
|
82 |
||
83 |
||
84 |
static int confFifo(struct FifoData *p) |
|
85 |
{
|
|
86 |
char *path, *disp, *sect, *fifosect = "Plugin:FIFO"; |
|
87 |
unsigned int pathlen; |
|
88 |
||
89 |
info("[FIFO] Reading config file '%s'", cfg_source()); |
|
90 |
||
91 |
path = cfg_get(fifosect, "FifoPath", string(FIFO_DEFAULT_PATH)); |
|
92 |
pathlen = strlen(path); |
|
93 |
if (pathlen == 0) { |
|
94 |
info("[FIFO] Invalid '%s.FifoPath' entry from '%s'. " |
|
95 |
"Assuming " string(FIFO_DEFAULT_PATH), fifosect, cfg_source()); |
|
96 |
free(path); |
|
97 |
path = strdup(string(FIFO_DEFAULT_PATH)); |
|
98 |
pathlen = strlen(path); |
|
99 |
}
|
|
100 |
if (pathlen > FIFO_MAXPATH) { |
|
101 |
error("[FIFO] Error: Too long '%s.FifoPath' entry from '%s'. " |
|
102 |
"(MAX " string(FIFO_MAXPATH) " chars)", fifosect, cfg_source()); |
|
103 |
free(path); |
|
104 |
return (-1); |
|
105 |
}
|
|
106 |
info("[FIFO] Read '%s.FifoPath' value is '%s'", fifosect, path); |
|
107 |
||
108 |
disp = cfg_get(NULL, "Display", NULL); |
|
109 |
if (disp == NULL) { |
|
110 |
error("[FIFO] Error: Could not get the Display name from '%s'", cfg_source()); |
|
111 |
free(path); |
|
112 |
return (-1); |
|
113 |
}
|
|
114 |
if ((sect = malloc(1 + strlen("Display:") + strlen(disp))) == NULL) { |
|
115 |
error("[FIFO] Error: Memory allocation failed"); |
|
116 |
free(disp); |
|
117 |
free(path); |
|
118 |
return (-1); |
|
119 |
}
|
|
120 |
strcpy(sect, "Display:"); |
|
121 |
strcat(sect, disp); |
|
122 |
info("[FIFO] Using display '%s'.", disp); |
|
123 |
free(disp); |
|
124 |
||
125 |
disp = cfg_get(sect, "Size", NULL); |
|
126 |
if (disp != NULL) { |
|
127 |
info("[FIFO] Getting the buffer size from '%s.Size'", sect); |
|
128 |
if (sscanf(disp, "%dx%*d", &p->msglen) != 1) { |
|
129 |
info("[FIFO] Could not determine the display size. " "Assuming " string(FIFO_DEFAULT_BUFSIZE)); |
|
130 |
p->msglen = FIFO_DEFAULT_BUFSIZE; |
|
131 |
}
|
|
132 |
free(disp); |
|
133 |
} else { |
|
134 |
info("[FIFO] Could not find a '%s.Size' entry.", sect); |
|
135 |
if (cfg_number(fifosect, "FifoBufSize", FIFO_DEFAULT_BUFSIZE, 0, -1, &p->msglen) > 0) { |
|
136 |
info("[FIFO] Getting the buffer size from '%s.FifoBufSize'", fifosect); |
|
137 |
} else { |
|
138 |
info("[FIFO] Could not find a valid '%s.FifoBufSize' entry. " |
|
139 |
"Assuming " string(FIFO_DEFAULT_BUFSIZE), fifosect); |
|
140 |
p->msglen = FIFO_DEFAULT_BUFSIZE; |
|
141 |
}
|
|
142 |
}
|
|
143 |
info("[FIFO] Read buffer size is '%d'", p->msglen); |
|
144 |
free(sect); |
|
145 |
||
146 |
if ((p->msg = malloc(2 + pathlen + p->msglen)) == NULL) { |
|
147 |
error("[FIFO] Error: Memory allocation failed"); |
|
148 |
free(path); |
|
149 |
return (-1); |
|
150 |
}
|
|
151 |
p->msg[0] = 0; |
|
152 |
p->path = p->msg + p->msglen + 1; |
|
153 |
strcpy(p->path, path); |
|
154 |
free(path); |
|
155 |
||
156 |
return (0); |
|
157 |
}
|
|
158 |
||
159 |
||
160 |
static int makeFifo(struct FifoData *p) |
|
161 |
{
|
|
162 |
struct stat st; |
|
163 |
||
164 |
if (stat(p->path, &st) < 0) { |
|
165 |
if (errno == ENOENT) { |
|
166 |
if (mkfifo(p->path, 0666) == 0) { |
|
167 |
p->created = 1; |
|
168 |
||
169 |
return (0); |
|
170 |
}
|
|
171 |
error("Couldn't create FIFO \"%s\": %s\n", p->path, strerror(errno)); |
|
172 |
||
173 |
return (-1); |
|
174 |
}
|
|
175 |
error("Failed to stat FIFO \"%s\": %s\n", p->path, strerror(errno)); |
|
176 |
||
177 |
return (-1); |
|
178 |
}
|
|
179 |
||
180 |
if (!S_ISFIFO(st.st_mode)) { |
|
181 |
error("\"%s\" already exists, but is not a FIFO", p->path); |
|
182 |
||
183 |
return (-1); |
|
184 |
}
|
|
185 |
||
186 |
return (0); |
|
187 |
}
|
|
188 |
||
189 |
||
190 |
static void closeFifo(struct FifoData *p) |
|
191 |
{
|
|
192 |
struct stat st; |
|
193 |
||
194 |
if (p->input >= 0) { |
|
195 |
close(p->input); |
|
196 |
p->input = -1; |
|
197 |
}
|
|
198 |
||
199 |
if ((p->created >= 0) && (stat(p->path, &st) == 0)) { |
|
200 |
debug("Removing FIFO \"%s\"\n", p->path); |
|
201 |
if (unlink(p->path) < 0) { |
|
202 |
error("Could not remove FIFO \"%s\": %s\n", p->path, strerror(errno)); |
|
203 |
||
204 |
return; |
|
205 |
}
|
|
206 |
p->created = -1; |
|
207 |
}
|
|
208 |
||
209 |
if (p->msg) { |
|
210 |
free(p->msg); |
|
211 |
p->msg = p->path = NULL; |
|
212 |
p->msglen = -1; |
|
213 |
}
|
|
214 |
}
|
|
215 |
||
216 |
||
217 |
static int openFifo(struct FifoData *p) |
|
218 |
{
|
|
219 |
if (p->created < 0) { |
|
220 |
error("Error: FIFO \"%s\" does not exist: %s\n", p->path, strerror(errno)); |
|
221 |
||
222 |
return (-1); |
|
223 |
}
|
|
224 |
||
225 |
if ((p->input = open(p->path, O_RDONLY | O_NONBLOCK)) < 0) { |
|
226 |
error("Could not open FIFO \"%s\" for reading: %s\n", p->path, strerror(errno)); |
|
227 |
closeFifo(p); |
|
228 |
||
229 |
return (-1); |
|
230 |
}
|
|
231 |
||
232 |
return (0); |
|
233 |
}
|
|
234 |
||
235 |
||
236 |
static int startFifo(struct FifoData *p) |
|
237 |
{
|
|
238 |
int res; |
|
239 |
||
240 |
if ((res = confFifo(p))) |
|
241 |
return (res); |
|
242 |
||
243 |
if ((res = makeFifo(p))) |
|
244 |
return (res); |
|
245 |
||
246 |
if ((res = openFifo(p))) |
|
247 |
return (res); |
|
248 |
||
249 |
/* ignore broken pipe */
|
|
250 |
signal(SIGPIPE, SIG_IGN); |
|
251 |
||
252 |
return (res); |
|
253 |
}
|
|
254 |
||
255 |
||
256 |
static void readFifo(struct FifoData *p) |
|
257 |
{
|
|
258 |
int bytes; |
|
259 |
||
260 |
bytes = read(p->input, p->msg, p->msglen); |
|
261 |
if (bytes == 0) |
|
262 |
return; |
|
263 |
||
264 |
if (bytes > 0) { |
|
265 |
p->msg[bytes] = 0; |
|
266 |
while (bytes--) |
|
267 |
if (p->msg[bytes] < 0x20) |
|
268 |
p->msg[bytes] = ' '; |
|
269 |
} else { |
|
270 |
error("[FIFO] Error %i: %s", errno, strerror(errno)); |
|
271 |
strcpy(p->msg, "ERROR"); |
|
272 |
}
|
|
273 |
}
|
|
274 |
||
275 |
||
276 |
static void runFifo(RESULT * result) |
|
277 |
{
|
|
278 |
static int state = 1; |
|
279 |
struct FifoData *p = &fd; |
|
280 |
char *s; |
|
281 |
||
282 |
switch (state) { |
|
283 |
case 1: |
|
284 |
/* Called for the first time. Set up everything. */
|
|
285 |
state = startFifo(p); |
|
286 |
s = ""; |
|
287 |
break; |
|
288 |
||
289 |
case 0: |
|
290 |
/* Init went fine. Now run in normal operation mode. */
|
|
291 |
readFifo(p); |
|
292 |
s = p->msg; |
|
293 |
break; |
|
294 |
||
295 |
default: |
|
296 |
/* There was an error somewhere in init. Do nothing. */
|
|
297 |
s = "ERROR"; |
|
298 |
break; |
|
299 |
}
|
|
300 |
||
301 |
/* Store the result */
|
|
302 |
SetResult(&result, R_STRING, s); |
|
303 |
}
|
|
304 |
||
305 |
||
306 |
/* plugin initialization */
|
|
307 |
int plugin_init_fifo(void) |
|
308 |
{
|
|
309 |
AddFunction("fifo::read", 0, runFifo); |
|
310 |
||
311 |
return (0); |
|
312 |
}
|
|
313 |
||
314 |
||
315 |
void plugin_exit_fifo(void) |
|
316 |
{
|
|
317 |
closeFifo(&fd); |
|
318 |
}
|