[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[PATCH] Add a portable implementation of getline to src/common.
From: |
Christopher Brannon |
Subject: |
[PATCH] Add a portable implementation of getline to src/common. |
Date: |
Tue, 28 Sep 2010 13:38:42 -0500 |
This patch adds our own implementation of getline, named spd_getline.
The function uses GLib's allocation routines.
We now use it in the server and modules.
This function was taken from OpenTTS and subsequently modified.
---
include/spd_utils.h | 29 ++++++++++
src/common/Makefile.am | 5 +-
src/common/spd_getline.c | 132 ++++++++++++++++++++++++++++++++++++++++++++
src/modules/dummy.c | 5 --
src/modules/module_main.c | 10 +--
src/modules/module_utils.c | 57 ++-----------------
src/server/module.c | 9 +--
src/server/output.c | 47 +---------------
8 files changed, 177 insertions(+), 117 deletions(-)
create mode 100644 include/spd_utils.h
create mode 100644 src/common/spd_getline.c
diff --git a/include/spd_utils.h b/include/spd_utils.h
new file mode 100644
index 0000000..458a0d0
--- /dev/null
+++ b/include/spd_utils.h
@@ -0,0 +1,29 @@
+/*
+ * spd_utils.h - prototypes for utility functions used
+ * in the Speech Dispatcher server and modules.
+ *
+ * Copyright (C) 2010 Brailcom, o.p.s.
+ *
+ * This 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.
+ *
+ * This software 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 package; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+#ifndef SPD_UTILS_H
+#define SPD_UTILS_H
+#include <stdio.h>
+#include <stddef.h>
+
+ssize_t spd_getline(char **lineptr, size_t * n, FILE * f);
+#endif /* SPD_UTILS_H */
diff --git a/src/common/Makefile.am b/src/common/Makefile.am
index f80f9b4..24623d6 100644
--- a/src/common/Makefile.am
+++ b/src/common/Makefile.am
@@ -2,5 +2,6 @@
noinst_LTLIBRARIES = libcommon.la
libcommon_la_CFLAGS = $(ERROR_CFLAGS)
-libcommon_la_CPPFLAGS = "-I$(top_srcdir)/include/"
-libcommon_la_SOURCES = fdsetconv.c
+libcommon_la_CPPFLAGS = "-I$(top_srcdir)/include/" $(GLIB_CFLAGS)
+libcommon_la_LIBADD = $(GLIB_LIBS)
+libcommon_la_SOURCES = fdsetconv.c getline.c
diff --git a/src/common/spd_getline.c b/src/common/spd_getline.c
new file mode 100644
index 0000000..d81591f
--- /dev/null
+++ b/src/common/spd_getline.c
@@ -0,0 +1,132 @@
+/*
+ * spd_getline.c - portable implementation of getline
+ *
+ * Copyright (C) 2010 Brailcom, o.p.s.
+ *
+ * This 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.
+ *
+ * This software 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 package; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+
+#if HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <limits.h>
+#include <glib.h>
+#include <spd_utils.h>
+
+#define INITIAL_BUF_SIZE 120
+#define GETLINE_FAILURE -1
+
+/*
+ * A portable implementation of getline.
+ * Originally provided by Willie Walker, and modified by Chris Brannon.
+ *
+ * Note: `*lineptr' must be a valid argument that could be passed to the
+ * `g_free()' glib function, i.e. it must be g_malloc'ed, not malloc'ed.
+ * In all other respects, this function behaves just like the POSIX version
+ * of getline.
+ */
+
+ssize_t
+spd_getline (char **lineptr, size_t * n, FILE * f)
+{
+ char ch;
+ ssize_t buf_pos = 0;
+ ssize_t needed = 2; /* Always buf_pos + 2 (see below). */
+ size_t new_length = 0;
+ char *temp;
+
+ if ((n == NULL) || (lineptr == NULL) || (f == NULL))
+ {
+ errno = EINVAL;
+ return GETLINE_FAILURE;
+ }
+
+ if (errno != 0)
+ errno = 0;
+
+ if ((*lineptr == NULL) || (*n == 0))
+ {
+ *n = INITIAL_BUF_SIZE;
+ *lineptr = g_malloc (*n * sizeof (char));
+
+ if (*lineptr == NULL)
+ {
+ *n = 0;
+ return GETLINE_FAILURE; /* Out of memory. */
+ }
+ }
+
+ /*
+ * For each iteration of this loop, the following holds.
+ * We have read buf_pos bytes of the line. The buffer contains buf_pos
+ * bytes, not including the trailing null byte at the end of the string.
+ * When we read another character, we want to store it, and we also need
+ * enough room for a null byte. So we need to realloc as soon as our
+ * capacity becomes less than buf_pos + 2.
+ * Hence the variable "needed" which always equals buf_pos + 2.
+ */
+
+ while ((ch = getc (f)) != EOF)
+ {
+ if (errno != 0)
+ return GETLINE_FAILURE;
+
+ if (needed > *n)
+ {
+ new_length = *n * 2;
+ if (new_length <= *n)
+ { /* Overflow. */
+ errno = ENOMEM;
+ /* We couldn't store the character, */
+ /* so put it back on the stream. */
+ ungetc (ch, f);
+ return GETLINE_FAILURE;
+ }
+ temp = (char *) g_realloc (*lineptr, new_length * sizeof (char));
+ if (temp == NULL)
+ {
+ ungetc (ch, f);
+ return GETLINE_FAILURE;
+ }
+ *n = new_length;
+ *lineptr = temp;
+ }
+ (*lineptr)[buf_pos++] = ch;
+
+ if (ch == '\n')
+ break;
+
+ if (needed == SSIZE_MAX)
+ {
+ /* We'll overflow ssize_t on the next round. */
+ errno = ENOMEM;
+ return GETLINE_FAILURE;
+ }
+ needed++;
+ }
+ (*lineptr)[buf_pos] = '\0';
+
+ if (buf_pos == 0)
+ {
+ buf_pos = GETLINE_FAILURE;
+ }
+ return buf_pos;
+}
diff --git a/src/modules/dummy.c b/src/modules/dummy.c
index 58bb565..c9948ac 100644
--- a/src/modules/dummy.c
+++ b/src/modules/dummy.c
@@ -40,11 +40,6 @@
//#define Debug 0
-#if !(defined(__GLIBC__) && defined(_GNU_SOURCE))
-/* Added by Willie Walker - getline is a gcc-ism */
-ssize_t getline (char **lineptr, size_t *n, FILE *f);
-#endif
-
/* Thread and process control */
static int dummy_speaking = 0;
diff --git a/src/modules/module_main.c b/src/modules/module_main.c
index 82a3220..30c3f38 100644
--- a/src/modules/module_main.c
+++ b/src/modules/module_main.c
@@ -32,13 +32,9 @@
#include <glib.h>
#include <dotconf.h>
+#include <spd_utils.h>
#include "module_utils.h"
-#if !(defined(__GLIBC__) && defined(_GNU_SOURCE))
-/* Added by Willie Walker - getline is a gcc-ism */
-ssize_t getline (char **lineptr, size_t *n, FILE *f);
-#endif
-
#define PROCESS_CMD(command, function) \
if (!strcmp(cmd_buf, #command"\n")){ \
char *msg; \
@@ -122,7 +118,7 @@ main(int argc, char *argv[])
ret_init = module_init(&status_info);
cmd_buf = NULL; n=0;
- ret = getline(&cmd_buf, &n, stdin);
+ ret = spd_getline(&cmd_buf, &n, stdin);
if (ret == -1){
DBG("Broken pipe when reading INIT, exiting... \n");
module_close(2);
@@ -152,7 +148,7 @@ main(int argc, char *argv[])
while(1){
cmd_buf = NULL; n=0;
- ret = getline(&cmd_buf, &n, stdin);
+ ret = spd_getline(&cmd_buf, &n, stdin);
if (ret == -1){
DBG("Broken pipe, exiting... \n");
module_close(2);
diff --git a/src/modules/module_utils.c b/src/modules/module_utils.c
index 11cbaa2..76b308c 100644
--- a/src/modules/module_utils.c
+++ b/src/modules/module_utils.c
@@ -26,60 +26,13 @@
#endif
#include <fdsetconv.h>
+#include <spd_utils.h>
#include "module_utils.h"
static char* module_audio_pars[10];
extern char* module_index_mark;
-#if !(defined(__GLIBC__) && defined(_GNU_SOURCE))
-/* Added by Willie Walker - getline is a gcc-ism */
-#define BUFFER_LEN 256
-ssize_t getline (char **lineptr, size_t *n, FILE *f)
-{
- char ch;
- size_t m = 0;
- ssize_t buf_len = 0;
- char * buf = NULL;
- char * p = NULL;
-
- if (errno != 0) {
- DBG("getline: errno came in as %d!!!\n", errno);
- errno = 0;
- }
- while ( (ch = getc(f)) !=EOF )
- {
- if (errno != 0)
- return -1;
- if ( m++ >= buf_len )
- {
- buf_len += BUFFER_LEN;
- buf = (char *) g_realloc(buf, buf_len + 1);
- if ( buf == NULL )
- {
- DBG("buf==NULL");
- return -1;
- }
- p = buf + buf_len - BUFFER_LEN;
- }
- *p = ch;
- p++;
- if ( ch == '\n' )
- break;
- }
- if ( m == 0 )
- {
- DBG("getline: m=%d!",m);
- return -1;
- } else {
- *p = '\0';
- *lineptr = buf;
- *n = m;
- return m;
- }
-}
-#endif /* !(defined(__GLIBC__) && defined(_GNU_SOURCE)) */
-
char*
do_message(EMessageType msgtype)
{
@@ -97,7 +50,7 @@ do_message(EMessageType msgtype)
while(1){
cur_line = NULL;
n = 0;
- ret = getline(&cur_line, &n, stdin);
+ ret = spd_getline(&cur_line, &n, stdin);
nlines++;
if (ret == -1) return g_strdup("401 ERROR INTERNAL");
@@ -222,7 +175,7 @@ do_set(void)
while(1){
line = NULL; n = 0;
- ret = getline(&line, &n, stdin);
+ ret = spd_getline(&line, &n, stdin);
if (ret == -1){ err=1; break; }
if (!strcmp(line, ".\n")){
g_free(line);
@@ -279,7 +232,7 @@ do_audio(void)
while(1){
line = NULL; n = 0;
- ret = getline(&line, &n, stdin);
+ ret = spd_getline(&line, &n, stdin);
if (ret == -1){ err=1; break; }
if (!strcmp(line, ".\n")){
g_free(line);
@@ -341,7 +294,7 @@ do_loglevel(void)
while(1){
line = NULL; n = 0;
- ret = getline(&line, &n, stdin);
+ ret = spd_getline(&line, &n, stdin);
if (ret == -1){ err=1; break; }
if (!strcmp(line, ".\n")){
g_free(line);
diff --git a/src/server/module.c b/src/server/module.c
index 187d575..d0d4d06 100644
--- a/src/server/module.c
+++ b/src/server/module.c
@@ -30,14 +30,9 @@
#include <sys/stat.h>
#include <stdio.h>
#include "speechd.h"
+#include <spd_utils.h>
#include "output.h"
-#if !(defined(__GLIBC__) && defined(_GNU_SOURCE))
-/* Added by Willie Walker - TEMP_FAILURE_RETRY, strndup, and getline
- * are gcc-isms
- */
-ssize_t getline (char **lineptr, size_t *n, FILE *f);
-#endif
void
destroy_module(OutputModule *module)
@@ -181,7 +176,7 @@ load_output_module(char* mod_name, char* mod_prog, char*
mod_cfgfile, char* mod_
reply = g_string_new("\n---------------\n");
f = fdopen(dup(module->pipe_out[0]), "r");
while(1){
- ret = getline(&rep_line, &n, f);
+ ret = spd_getline(&rep_line, &n, f);
if (ret <= 0){
MSG(1, "ERROR: Bad syntax from output module %s 1",
module->name);
return NULL;
diff --git a/src/server/output.c b/src/server/output.c
index 7f00f58..3802f83 100644
--- a/src/server/output.c
+++ b/src/server/output.c
@@ -26,6 +26,7 @@
#endif
#include <fdsetconv.h>
+#include <spd_utils.h>
#include "output.h"
#include "parse.h"
@@ -47,7 +48,7 @@ safe_write(int fd, const void *buf, size_t count) {
#endif /* TEMP_FAILURE_RETRY */
#if !(defined(__GLIBC__) && defined(_GNU_SOURCE))
-/* Added by Willie Walker - strndup, and getline are gcc-isms
+/* Added by Willie Walker - strndup is a gcc-ism
*/
char *strndup ( const char *s, size_t n)
{
@@ -67,48 +68,6 @@ char *strndup ( const char *s, size_t n)
return p;
}
-
-#define BUFFER_LEN 256
-ssize_t getline (char **lineptr, size_t *n, FILE *f)
-{
- char ch;
- size_t m = 0;
- ssize_t buf_len = 0;
- char * buf = NULL;
- char * p = NULL;
-
- if (errno != 0) {
- errno = 0;
- }
- while ( (ch = getc(f)) !=EOF )
- {
- if (errno != 0)
- return -1;
- if ( m++ >= buf_len )
- {
- buf_len += BUFFER_LEN;
- buf = (char *) g_realloc(buf, buf_len + 1);
- if ( buf == NULL )
- {
- return -1;
- }
- p = buf + buf_len - BUFFER_LEN;
- }
- *p = ch;
- p++;
- if ( ch == '\n' )
- break;
- }
- if ( m == 0 )
- {
- return -1;
- } else {
- *p = '\0';
- *lineptr = buf;
- *n = m;
- return m;
- }
-}
#endif /* !(defined(__GLIBC__) && defined(_GNU_SOURCE)) */
void
@@ -227,7 +186,7 @@ output_read_reply(OutputModule *output)
/* Wait for activity on the socket, when there is some,
read all the message line by line */
do{
- bytes = getline(&line, &N, output->stream_out);
+ bytes = spd_getline(&line, &N, output->stream_out);
if (bytes == -1){
MSG(2, "Error: Broken pipe to module.");
output->working = 0;
--
1.7.3