All static memory allocations were turned into dynamical ones.

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
This commit is contained in:
mjona
2010-02-11 16:48:56 +00:00
parent b35fc3f8cb
commit 555ed9099a
+226 -154
View 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.
*
@@ -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)
typedef struct _FifoData {
char *path;
int input;
int created;
} FifoData;
struct FifoData {
char *path;
char *msg;
int msglen;
int input;
int created;
};
static char Section[] = "Plugin:FIFO";
static FifoData fd;
static char msg[FIFO_BUFFER_SIZE];
static char fifopath[1024];
static struct FifoData fd = {
.path = NULL,
.msg = NULL,
.msglen = -1,
.input = -1,
.created = -1,
};
static void configure_fifo(void)
static int confFifo(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);
}
char *path, *disp, *sect, *fifosect = "Plugin:FIFO";
unsigned int pathlen;
info("[FIFO] Reading config file '%s'", cfg_source());
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;
}
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();
}
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;
}
static int checkFifo(void)
{
struct stat st;
if (stat(fd.path, &st) < 0) {
if (errno == ENOENT) {
/* Path doesn't exist */
return makeFifo();
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);
}
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;
}
info("[FIFO] Read '%s.FifoPath' value is '%s'", fifosect, path);
static int openFifo(void)
{
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;
}
static void startFifo(void)
{
static int started = 0;
if (started)
return;
started = 1;
configure_fifo();
fd.path = fifopath;
fd.input = -1;
fd.created = 0;
openFifo();
/* ignore broken pipe */
signal(SIGPIPE, SIG_IGN);
memset(msg, 0, FIFO_BUFFER_SIZE);
}
static void fiforead(RESULT * result)
{
char buf[FIFO_BUFFER_SIZE];
unsigned int i;
int bytes = 1;
startFifo();
memset(buf, 0, FIFO_BUFFER_SIZE);
strcat(buf, "ERROR");
if (checkFifo() == 0) {
memset(buf, 0, FIFO_BUFFER_SIZE);
while (bytes > 0 && errno != EINTR) {
bytes = read(fd.input, buf, FIFO_BUFFER_SIZE);
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);
if (bytes < 0 || (errno > 0 && errno != EAGAIN)) {
error("[FIFO] Error %i: %s", errno, strerror(errno));
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 {
if (strlen(buf) > 0) {
strcpy(msg, buf);
}
for (i = 0; i < strlen(buf); i++) {
if (msg[i] < 0x20)
msg[i] = ' ';
}
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;
}
}
}
/* store result */
SetResult(&result, R_STRING, msg);
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);
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, fiforead);
return 0;
AddFunction("fifo::read", 0, runFifo);
return (0);
}
void plugin_exit_fifo(void)
{
/* close filedescriptors */
closeFifo();
closeFifo(&fd);
}