~siretart/lcd4linux/debian

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
}