]> git.webhop.me Git - lcd4linux.git/commitdiff
All static memory allocations were turned into dynamical ones.
authormjona <mjona@3ae390bd-cb1e-0410-b409-cd5a39f66f1f>
Thu, 11 Feb 2010 16:48:56 +0000 (16:48 +0000)
committermjona <mjona@3ae390bd-cb1e-0410-b409-cd5a39f66f1f>
Thu, 11 Feb 2010 16:48:56 +0000 (16:48 +0000)
Improved configuration parameters:
- FifoPath to specify the fifo path (if absent, a built in replacement is used)
- FifoBufSize to specify the size of the internal buffer (this parameter is optional as
the plugin will try to match the number of display columns; if it fails and
no FifoBufSize parameter is supplied then a built in replacement is used)
Simplified and rationalized init and exit functions:
most global variables have been localized.
Fixed several off-by-one overflows memory bugs.

git-svn-id: https://ssl.bulix.org/svn/lcd4linux/trunk@1108 3ae390bd-cb1e-0410-b409-cd5a39f66f1f

plugin_fifo.c

index 165cb3241003f9210f2cd67e4a83ed61ce8cf434..0d4a7d104078615ed38f0ae4f48a3015ae58babc 100644 (file)
@@ -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.
  *
  *
  */
 
-/* 
- * 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>
 #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);
 }