diff options
-rw-r--r-- | plugin_fifo.c | 328 |
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); } |