From 181cec4348da40331b3e8ab365732c025ec149b2 Mon Sep 17 00:00:00 2001 From: Reinhard Tartler Date: Wed, 27 Apr 2011 19:24:15 +0200 Subject: Import upstream version 0.11.0~svn1143 --- plugin_fifo.c | 318 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 318 insertions(+) create mode 100644 plugin_fifo.c (limited to 'plugin_fifo.c') diff --git a/plugin_fifo.c b/plugin_fifo.c new file mode 100644 index 0000000..4166b05 --- /dev/null +++ b/plugin_fifo.c @@ -0,0 +1,318 @@ +/* $Id: plugin_fifo.c 1112 2010-02-14 02:47:49Z michael $ + * $URL: https://ssl.bulix.org/svn/lcd4linux/trunk/plugin_fifo.c $ + * + * Fifo plugin + * + * Copyright (C) 2008 Michael Vogt + * Copyright (C) 2010 Mattia Jona-Lasinio + * Copyright (C) 2004, 2005, 2006, 2007, 2008, 2010 The LCD4Linux Team + * + * This file is part of LCD4Linux. + * + * LCD4Linux is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * LCD4Linux is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ + +/* + * Configuration parameters: + * + * - FifoPath 'string' : use as the fifo complete file path + * If absent use /tmp/lcd4linux.fifo) + * + * - FifoBufSize num : if the plugin is unable to determine the display size then + * set the size of the internal buffer to characters + * otherwise use the display size (number of columns). + * If no display size is available and no FifoBufSize parameter + * is specified then arbitrarily set the internal buffer size + * to 80 characters. + */ + +#include "config.h" + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "debug.h" +#include "plugin.h" +#include "cfg.h" + +#ifdef WITH_DMALLOC +#include +#endif + +#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 == 0) { + info("[FIFO] Invalid '%s.FifoPath' entry from '%s'. " + "Assuming " string(FIFO_DEFAULT_PATH), fifosect, cfg_source()); + free(path); + path = strdup(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); + + 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); + if (sscanf(disp, "%dx%*d", &p->msglen) != 1) { + info("[FIFO] Could not determine the display size. " "Assuming " string(FIFO_DEFAULT_BUFSIZE)); + p->msglen = FIFO_DEFAULT_BUFSIZE; + } + free(disp); + } 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); + + 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); + + return (0); +} + + +static int makeFifo(struct FifoData *p) +{ + struct stat st; + + if (stat(p->path, &st) < 0) { + if (errno == ENOENT) { + if (mkfifo(p->path, 0666) == 0) { + p->created = 1; + + 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)); + + return (-1); + } + + if (!S_ISFIFO(st.st_mode)) { + error("\"%s\" already exists, but is not a FIFO", p->path); + + return (-1); + } + + return (0); +} + + +static void closeFifo(struct FifoData *p) +{ + 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; + } + + if (p->msg) { + free(p->msg); + p->msg = p->path = NULL; + p->msglen = -1; + } +} + + +static int openFifo(struct FifoData *p) +{ + 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 int startFifo(struct FifoData *p) +{ + int res; + + if ((res = confFifo(p))) + return (res); + + if ((res = makeFifo(p))) + return (res); + + if ((res = openFifo(p))) + return (res); + + /* ignore broken pipe */ + signal(SIGPIPE, SIG_IGN); + + return (res); +} + + +static void readFifo(struct FifoData *p) +{ + int bytes; + + bytes = read(p->input, p->msg, p->msglen); + if (bytes == 0) + return; + + 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"); + } +} + + +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; + } + + /* Store the result */ + SetResult(&result, R_STRING, s); +} + + +/* plugin initialization */ +int plugin_init_fifo(void) +{ + AddFunction("fifo::read", 0, runFifo); + + return (0); +} + + +void plugin_exit_fifo(void) +{ + closeFifo(&fd); +} -- cgit v1.2.3