aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--plugin_fifo.c328
1 files changed, 200 insertions, 128 deletions
diff --git a/plugin_fifo.c b/plugin_fifo.c
index 165cb32..0d4a7d1 100644
--- a/plugin_fifo.c
+++ b/plugin_fifo.c
@@ -4,7 +4,8 @@
* plugin template
*
* Copyright (C) 2008 Michael Vogt <michu@neophob.com>
- * Copyright (C) 2004, 2005, 2006, 2007, 2008 The LCD4Linux Team <lcd4linux-devel@users.sourceforge.net>
+ * Copyright (C) 2010 Mattia Jona-Lasinio <mjona@users.sourceforge.net>
+ * Copyright (C) 2004, 2005, 2006, 2007, 2008, 2010 The LCD4Linux Team <lcd4linux-devel@users.sourceforge.net>
*
* This file is part of LCD4Linux.
*
@@ -24,19 +25,12 @@
*
*/
-/*
- * Quick fifo hack for lcd4linux
- *
- * most code is ripped ...
- *
- */
-
/* define the include files you need */
#include "config.h"
#include <stdlib.h>
+#include <stdio.h>
#include <string.h>
-#include <ctype.h>
#include <errno.h>
#include <unistd.h>
#include <fcntl.h>
@@ -52,173 +46,251 @@
#include <dmalloc.h>
#endif
-#define FIFO_BUFFER_SIZE 80
+#define FIFO_MAXPATH 256
+#define FIFO_DEFAULT_PATH /tmp/lcd4linux.fifo
+#define FIFO_DEFAULT_BUFSIZE 80
+#define str(s) #s
+#define string(s) str(s)
+
+struct FifoData {
+ char *path;
+ char *msg;
+ int msglen;
+ int input;
+ int created;
+};
+
+static struct FifoData fd = {
+ .path = NULL,
+ .msg = NULL,
+ .msglen = -1,
+ .input = -1,
+ .created = -1,
+};
+
+
+static int confFifo(struct FifoData *p)
+{
+ char *path, *disp, *sect, *fifosect = "Plugin:FIFO";
+ unsigned int pathlen;
+
+ info("[FIFO] Reading config file '%s'", cfg_source());
+
+ path = cfg_get(fifosect, "FifoPath", string(FIFO_DEFAULT_PATH));
+ pathlen = strlen(path);
+ if (pathlen > FIFO_MAXPATH) {
+ error("[FIFO] Error: Too long '%s.FifoPath' entry from '%s'. "
+ "(MAX "string(FIFO_MAXPATH)" chars)", fifosect, cfg_source());
+ free(path);
+ return (-1);
+ }
+ info("[FIFO] Read '%s.FifoPath' value is '%s'", fifosect, path);
-typedef struct _FifoData {
- char *path;
- int input;
- int created;
-} FifoData;
+ disp = cfg_get(NULL, "Display", NULL);
+ if (disp == NULL) {
+ error("[FIFO] Error: Could not get the Display name from '%s'.", cfg_source());
+ free(path);
+ return (-1);
+ }
+ if ((sect = malloc(1+strlen("Display:")+strlen(disp))) == NULL) {
+ error("[FIFO] Error: Memory allocation failed");
+ free(disp);
+ free(path);
+ return (-1);
+ }
+ strcpy(sect, "Display:");
+ strcat(sect, disp);
+ info("[FIFO] Using display '%s'.", disp);
+ free(disp);
+
+ disp = cfg_get(sect, "Size", NULL);
+ if (disp != NULL) {
+ info("[FIFO] Getting the buffer size from '%s.Size'.", sect);
+ sscanf(disp, "%dx%*d", &p->msglen);
+ } else {
+ info("[FIFO] Could not find a '%s.Size' entry.", sect);
+ if (cfg_number(fifosect, "FifoBufSize", FIFO_DEFAULT_BUFSIZE, 0, -1, &p->msglen) > 0) {
+ info("[FIFO] Getting the buffer size from '%s.FifoBufSize'.", fifosect);
+ } else {
+ info("[FIFO] Could not find a valid '%s.FifoBufSize' entry. "
+ "Assuming "string(FIFO_DEFAULT_BUFSIZE)".", fifosect);
+ p->msglen = FIFO_DEFAULT_BUFSIZE;
+ }
+ }
+ info("[FIFO] Read buffer size is '%d'", p->msglen);
+ free(sect);
+ free(disp);
+
+ if ((p->msg = malloc(2+pathlen+p->msglen)) == NULL) {
+ error("[FIFO] Error: Memory allocation failed");
+ free(path);
+ return (-1);
+ }
+ p->msg[0] = 0;
+ p->path = p->msg+p->msglen+1;
+ strcpy(p->path, path);
+ free(path);
-static char Section[] = "Plugin:FIFO";
-static FifoData fd;
-static char msg[FIFO_BUFFER_SIZE];
-static char fifopath[1024];
+ return (0);
+}
-static void configure_fifo(void)
+static int makeFifo(struct FifoData *p)
{
- char *s;
- memset(fifopath, 0, 1024);
- s = cfg_get(Section, "fifopath", "/tmp/lcd4linux.fifo");
- if (*s == '\0') {
- info("[FIFO] empty '%s.fifopath' entry from %s, assuming '/tmp/lcd4linux.fifo'", Section, cfg_source());
- strcpy(fifopath, "/tmp/lcd4linux.fifo");
- } else {
- strcpy(fifopath, s);
- info("[FIFO] read '%s.fifopath', value is '%s'", Section, fifopath);
- }
- free(s);
-}
+ struct stat st;
+ if (stat(p->path, &st) < 0) {
+ if (errno == ENOENT) {
+ if (mkfifo(p->path, 0666) == 0) {
+ p->created = 1;
-static void removeFifo(void)
-{
- debug("Removing FIFO \"%s\"\n", fd.path);
- if (unlink(fd.path) < 0) {
- error("Could not remove FIFO \"%s\": %s\n", fd.path, strerror(errno));
- return;
- }
- fd.created = 0;
-}
+ return (0);
+ }
+ error("Couldn't create FIFO \"%s\": %s\n", p->path, strerror(errno));
+ return (-1);
+ }
+ error("Failed to stat FIFO \"%s\": %s\n", p->path, strerror(errno));
-static void closeFifo(void)
-{
- struct stat st;
- if (fd.input >= 0) {
- close(fd.input);
- fd.input = -1;
- }
- if (fd.created && (stat(fd.path, &st) == 0))
- removeFifo();
-}
+ return (-1);
+ }
-static int makeFifo(void)
-{
- if (mkfifo(fd.path, 0666) < 0) {
- error("Couldn't create FIFO \"%s\": %s\n", fd.path, strerror(errno));
- return -1;
- }
- /* clear errno */
- errno = 0;
- fd.created = 1;
- return 0;
+ if (! S_ISFIFO(st.st_mode)) {
+ error("\"%s\" already exists, but is not a FIFO", p->path);
+
+ return (-1);
+ }
+
+ return (0);
}
-static int checkFifo(void)
+static void closeFifo(struct FifoData *p)
{
- struct stat st;
- if (stat(fd.path, &st) < 0) {
- if (errno == ENOENT) {
+ struct stat st;
+
+ if (p->input >= 0) {
+ close(p->input);
+ p->input = -1;
+ }
+
+ if ((p->created >= 0) && (stat(p->path, &st) == 0)) {
+ debug("Removing FIFO \"%s\"\n", p->path);
+ if (unlink(p->path) < 0) {
+ error("Could not remove FIFO \"%s\": %s\n", p->path, strerror(errno));
+
+ return;
+ }
+ p->created = -1;
+ }
- /* Path doesn't exist */
- return makeFifo();
+ if (p->msg) {
+ free(p->msg);
+ p->msg = p->path = NULL;
+ p->msglen = -1;
}
- error("Failed to stat FIFO \"%s\": %s\n", fd.path, strerror(errno));
- return -1;
- }
- if (!S_ISFIFO(st.st_mode)) {
- error("\"%s\" already exists, but is not a FIFO\n", fd.path);
- return -1;
- }
- return 0;
}
-static int openFifo(void)
+static int openFifo(struct FifoData *p)
{
- if (checkFifo() < 0)
- return -1;
- fd.input = open(fd.path, O_RDONLY | O_NONBLOCK);
- if (fd.input < 0) {
- error("Could not open FIFO \"%s\" for reading: %s\n", fd.path, strerror(errno));
- closeFifo();
- return -1;
- }
- return 0;
+ if (p->created < 0) {
+ error("Error: FIFO \"%s\" does not exist: %s\n", p->path, strerror(errno));
+
+ return (-1);
+ }
+
+ if ((p->input = open(p->path, O_RDONLY | O_NONBLOCK)) < 0) {
+ error("Could not open FIFO \"%s\" for reading: %s\n", p->path, strerror(errno));
+ closeFifo(p);
+
+ return (-1);
+ }
+
+ return (0);
}
-static void startFifo(void)
+static int startFifo(struct FifoData *p)
{
- static int started = 0;
-
- if (started)
- return;
+ int res;
- started = 1;
+ if ((res = confFifo(p)))
+ return (res);
- configure_fifo();
- fd.path = fifopath;
- fd.input = -1;
- fd.created = 0;
- openFifo();
+ if ((res = makeFifo(p)))
+ return (res);
- /* ignore broken pipe */
- signal(SIGPIPE, SIG_IGN);
+ if ((res = openFifo(p)))
+ return (res);
- memset(msg, 0, FIFO_BUFFER_SIZE);
+ /* ignore broken pipe */
+ signal(SIGPIPE, SIG_IGN);
+ return (res);
}
-static void fiforead(RESULT * result)
+static void readFifo(struct FifoData *p)
{
- char buf[FIFO_BUFFER_SIZE];
- unsigned int i;
- int bytes = 1;
+ int bytes;
- startFifo();
+ bytes = read(p->input, p->msg, p->msglen);
+ if (bytes == 0)
+ return;
- memset(buf, 0, FIFO_BUFFER_SIZE);
- strcat(buf, "ERROR");
+ if (bytes > 0) {
+ p->msg[bytes] = 0;
+ while (bytes--)
+ if (p->msg[bytes] < 0x20)
+ p->msg[bytes] = ' ';
+ } else {
+ error("[FIFO] Error %i: %s", errno, strerror(errno));
+ strcpy(p->msg, "ERROR");
+ }
+}
- if (checkFifo() == 0) {
- memset(buf, 0, FIFO_BUFFER_SIZE);
- while (bytes > 0 && errno != EINTR) {
- bytes = read(fd.input, buf, FIFO_BUFFER_SIZE);
+static void runFifo(RESULT *result)
+{
+ static int state = 1;
+ struct FifoData *p = &fd;
+ char *s;
+
+ switch (state) {
+ case 1:
+ /* Called for the first time. Set up everything. */
+ state = startFifo(p);
+ s = "";
+ break;
+
+ case 0:
+ /* Init went fine. Now run in normal operation mode. */
+ readFifo(p);
+ s = p->msg;
+ break;
+
+ default:
+ /* There was an error somewhere in init. Do nothing. */
+ s = "ERROR";
+ break;
}
- if (bytes < 0 || (errno > 0 && errno != EAGAIN)) {
- error("[FIFO] Error %i: %s", errno, strerror(errno));
- } else {
- if (strlen(buf) > 0) {
- strcpy(msg, buf);
- }
- for (i = 0; i < strlen(buf); i++) {
- if (msg[i] < 0x20)
- msg[i] = ' ';
- }
- }
- }
- /* store result */
- SetResult(&result, R_STRING, msg);
+ /* Store the result */
+ SetResult(&result, R_STRING, s);
}
/* plugin initialization */
int plugin_init_fifo(void)
{
- AddFunction("fifo::read", 0, fiforead);
- return 0;
+ AddFunction("fifo::read", 0, runFifo);
+
+ return (0);
}
void plugin_exit_fifo(void)
{
- /* close filedescriptors */
- closeFifo();
+ closeFifo(&fd);
}