aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSergey Poznyakoff <gray@gnu.org.ua>2010-06-11 10:13:59 +0300
committerSergey Poznyakoff <gray@gnu.org.ua>2010-06-11 10:23:40 +0300
commit7a0e63726f1722492f92cd92723f1be46a89e04f (patch)
tree84c2ea787894eb530e692e8fe4a32d8853f6abe1
parent972b32f76ffb55ca0244caa18109405facdf7209 (diff)
downloadsmap-7a0e63726f1722492f92cd92723f1be46a89e04f.tar.gz
smap-7a0e63726f1722492f92cd92723f1be46a89e04f.tar.bz2
Revamp stream support.
Use fully fledged I/O streams (based on my earlier implementation for Mailutils and Dico). Construct a sockmap stream which allows to do all interactions transparently as if it were a line-oriented protocol. Update everything accordingly. * include/smap/ostr.h: delete * lib/ostr.c: delete * lib/smapostr.c: delete * include/smap/printf.h: New file. * include/smap/stream.h: New file. * include/smap/streamdef.h: New file. * lib/asnprintf.c: New file. * lib/asprintf.c: New file. * lib/fileoutstr.c: New file. * lib/sockmapstr.c: New file. * lib/syslogstr.c: New file. * lib/stream.c: New file. * lib/stream_printf.c: New file. * lib/stream_vprintf.c: New file. * lib/vasnprintf.c: New file. * lib/xscript.c: New file. * include/smap/Makefile.am: Update. * lib/Makefile.am: Update. * include/smap/diag.h (smap_error_str) (smap_debug_str, smap_trace_str): Change type. * include/smap/module.h (smap_module)<smap_query>: Change type of ostr. * lib/debug.c: Rewrite for new stream subsystem. * lib/diag.c: Likewise. * lib/stderr.c: Likewise. * lib/syslog.c: Likewise. * modules/echo/echo.c: Likewise. * modules/guile/guile.c: Likewise. * modules/mailutils/mailutils.c: Likewise. * src/query.c: Likewise. * src/smapc.c: Likewise. * src/smapd.c: Likewise. * src/smapd.h: Likewise.
-rw-r--r--include/smap/Makefile.am4
-rw-r--r--include/smap/diag.h8
-rw-r--r--include/smap/module.h2
-rw-r--r--include/smap/ostr.h38
-rw-r--r--include/smap/printf.h26
-rw-r--r--include/smap/stream.h122
-rw-r--r--include/smap/streamdef.h73
-rw-r--r--lib/Makefile.am14
-rw-r--r--lib/asnprintf.c40
-rw-r--r--lib/asprintf.c41
-rw-r--r--lib/debug.c4
-rw-r--r--lib/diag.c14
-rw-r--r--lib/fileoutstr.c93
-rw-r--r--lib/ostr.c197
-rw-r--r--lib/sockmapstr.c477
-rw-r--r--lib/stderr.c42
-rw-r--r--lib/stream.c976
-rw-r--r--lib/stream_printf.c32
-rw-r--r--lib/stream_vprintf.c (renamed from lib/smapostr.c)42
-rw-r--r--lib/syslog.c22
-rw-r--r--lib/syslogstr.c82
-rw-r--r--lib/vasnprintf.c77
-rw-r--r--lib/xscript.c223
-rw-r--r--modules/echo/echo.c12
-rw-r--r--modules/guile/guile.c12
-rw-r--r--modules/mailutils/mailutils.c26
-rw-r--r--src/query.c6
-rw-r--r--src/smapc.c92
-rw-r--r--src/smapd.c137
-rw-r--r--src/smapd.h7
30 files changed, 2456 insertions, 485 deletions
diff --git a/include/smap/Makefile.am b/include/smap/Makefile.am
index 93c65f5..1f3fec6 100644
--- a/include/smap/Makefile.am
+++ b/include/smap/Makefile.am
@@ -15,11 +15,13 @@
# along with this program. If not, see <http://www.gnu.org/licenses/>.
pkginclude_HEADERS = \
- ostr.h\
wordsplit.h\
kwtab.h\
module.h\
diag.h\
parseopt.h\
+ printf.h\
+ stream.h\
+ streamdef.h\
url.h
diff --git a/include/smap/diag.h b/include/smap/diag.h
index 46bc5c9..a8d76d8 100644
--- a/include/smap/diag.h
+++ b/include/smap/diag.h
@@ -17,11 +17,11 @@
#ifndef __SMAP_DIAG_H
#define __SMAP_DIAG_H
-#include "smap/ostr.h"
+#include "smap/stream.h"
-extern smap_ostream_t smap_error_str;
-extern smap_ostream_t smap_debug_str;
-extern smap_ostream_t smap_trace_str;
+extern smap_stream_t smap_error_str;
+extern smap_stream_t smap_debug_str;
+extern smap_stream_t smap_trace_str;
void smap_verror(const char *fmt, va_list ap);
void smap_error(const char *fmt, ...);
diff --git a/include/smap/module.h b/include/smap/module.h
index 5375cd8..1c4a6eb 100644
--- a/include/smap/module.h
+++ b/include/smap/module.h
@@ -44,7 +44,7 @@ struct smap_module {
int (*smap_open) (smap_database_t hp);
int (*smap_close) (smap_database_t hp);
int (*smap_query)(smap_database_t dbp,
- smap_ostream_t ostr,
+ smap_stream_t ostr,
const char *map, const char *key,
struct smap_conninfo const *conninfo);
};
diff --git a/include/smap/ostr.h b/include/smap/ostr.h
deleted file mode 100644
index 63252c1..0000000
--- a/include/smap/ostr.h
+++ /dev/null
@@ -1,38 +0,0 @@
-/* This file is part of smf.
- Copyright (C) 2006, 2007, 2010 Sergey Poznyakoff
-
- This program 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 3, or (at your option)
- any later version.
-
- This program 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, see <http://www.gnu.org/licenses/>. */
-
-#ifndef __SMAP_OSTR_H
-#define __SMAP_OSTR_H
-
-/* ostr.c */
-#include <unistd.h>
-#include <stdio.h>
-#include <stdarg.h>
-
-typedef struct smap_output_stream *smap_ostream_t;
-int smap_ostream_write(smap_ostream_t str, const char *buf, size_t len);
-int smap_ostream_vprintf(smap_ostream_t str, const char *fmt, va_list ap);
-int smap_ostream_printf(smap_ostream_t str, const char *fmt, ...);
-int smap_ostream_flush(smap_ostream_t str);
-smap_ostream_t smap_ostream_create(void (*flush)(void *data, char *buf),
- void *data);
-void smap_ostream_free(smap_ostream_t str);
-void smap_ostream_destroy(smap_ostream_t *str);
-
-extern size_t smap_mapstr_debug_idx;
-extern smap_ostream_t smap_map_ostream_create(FILE *fp);
-
-#endif
diff --git a/include/smap/printf.h b/include/smap/printf.h
new file mode 100644
index 0000000..b4ea1bf
--- /dev/null
+++ b/include/smap/printf.h
@@ -0,0 +1,26 @@
+/* This file is part of smap.
+ Copyright (C) 2006, 2007, 2010 Sergey Poznyakoff
+
+ This program 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 3, or (at your option)
+ any later version.
+
+ This program 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, see <http://www.gnu.org/licenses/>. */
+
+#ifndef __SMAP_IO_H
+#define __SMAP_IO_H
+
+#include <stdarg.h>
+
+int smap_vasnprintf(char **pbuf, size_t *psize, const char *fmt, va_list ap);
+int smap_asnprintf(char **pbuf, size_t *psize, const char *fmt, ...);
+int smap_asprintf(char **pbuf, const char *fmt, ...);
+
+#endif
diff --git a/include/smap/stream.h b/include/smap/stream.h
new file mode 100644
index 0000000..bd801bc
--- /dev/null
+++ b/include/smap/stream.h
@@ -0,0 +1,122 @@
+/* This file is part of smap.
+ Copyright (C) 2009, 2010 Sergey Poznyakoff
+
+ This program 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 3, or (at your option)
+ any later version.
+
+ This program 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, see <http://www.gnu.org/licenses/>. */
+
+#ifndef __SMAP_STREAM_H
+#define __SMAP_STREAM_H
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdarg.h>
+
+enum smap_buffer_type {
+ smap_buffer_none,
+ smap_buffer_line,
+ smap_buffer_full
+};
+
+typedef struct _smap_transport *smap_transport_t;
+typedef struct _smap_stream *smap_stream_t;
+
+/* FIXME */
+typedef off_t smap_off_t;
+
+#define SMAP_SEEK_SET 0
+#define SMAP_SEEK_CUR 1
+#define SMAP_SEEK_END 2
+
+#define SMAP_STREAM_READ 0x00000001
+#define SMAP_STREAM_WRITE 0x00000002
+#define SMAP_STREAM_RDWR (SMAP_STREAM_READ|SMAP_STREAM_WRITE)
+#define SMAP_STREAM_SEEK 0x00000004
+#define SMAP_STREAM_APPEND 0x00000008
+#define SMAP_STREAM_CREAT 0x00000010
+#define SMAP_STREAM_NONBLOCK 0x00000020
+#define SMAP_STREAM_NO_CLOSE 0x00000040
+#define SMAP_STREAM_EXPBUF 0x00000080
+
+#define SMAP_IOCTL_GET_TRANSPORT 1
+#define SMAP_IOCTL_SET_TRANSPORT 2
+#define SMAP_IOCTL_SET_DEBUG_IDX 3
+#define SMAP_IOCTL_SET_DEBUG_PFX 4
+
+void smap_stream_ref(smap_stream_t stream);
+void smap_stream_unref(smap_stream_t stream);
+void smap_stream_destroy(smap_stream_t *pstream);
+int smap_stream_open(smap_stream_t stream);
+const char *smap_stream_strerror(smap_stream_t stream, int rc);
+int smap_stream_err(smap_stream_t stream);
+int smap_stream_last_error(smap_stream_t stream);
+void smap_stream_clearerr(smap_stream_t stream);
+int smap_stream_eof(smap_stream_t stream);
+int smap_stream_seek(smap_stream_t stream, smap_off_t offset, int whence,
+ smap_off_t *pres);
+int smap_stream_skip_input_bytes(smap_stream_t stream, smap_off_t count,
+ smap_off_t *pres);
+
+int smap_stream_set_buffer(smap_stream_t stream, enum smap_buffer_type type,
+ size_t size);
+int smap_stream_read(smap_stream_t stream, void *buf, size_t size,
+ size_t *pread);
+int smap_stream_readdelim(smap_stream_t stream, char *buf, size_t size,
+ int delim, size_t *pread);
+int smap_stream_readline(smap_stream_t stream, char *buf, size_t size,
+ size_t *pread);
+int smap_stream_getdelim(smap_stream_t stream, char **pbuf, size_t *psize,
+ int delim, size_t *pread);
+int smap_stream_getline(smap_stream_t stream, char **pbuf, size_t *psize,
+ size_t *pread);
+int smap_stream_write(smap_stream_t stream, const void *buf, size_t size,
+ size_t *pwrite);
+int smap_stream_writeline(smap_stream_t stream, const char *buf, size_t size);
+int smap_stream_flush(smap_stream_t stream);
+int smap_stream_close(smap_stream_t stream);
+int smap_stream_size(smap_stream_t stream, smap_off_t *psize);
+smap_off_t smap_stream_bytes_in(smap_stream_t stream);
+smap_off_t smap_stream_bytes_out(smap_stream_t stream);
+int smap_stream_ioctl(smap_stream_t stream, int code, void *ptr);
+int smap_stream_truncate(smap_stream_t stream, smap_off_t);
+int smap_stream_shutdown(smap_stream_t stream, int how);
+
+#define SMAP_STREAM_READY_RD 0x1
+#define SMAP_STREAM_READY_WR 0x2
+#define SMAP_STREAM_READY_EX 0x4
+struct timeval; /* Needed for the following declaration */
+
+int smap_stream_wait(smap_stream_t stream, int *pflags, struct timeval *);
+
+void smap_stream_get_flags(smap_stream_t stream, int *pflags);
+int smap_stream_set_flags(smap_stream_t stream, int fl);
+int smap_stream_clr_flags(smap_stream_t stream, int fl);
+
+int smap_stream_vprintf(smap_stream_t str, const char *fmt, va_list ap);
+int smap_stream_printf(smap_stream_t stream, const char *fmt, ...);
+
+
+int smap_fileout_stream_create (smap_stream_t *pstream, FILE *file,
+ const char *pfx, int pgopt);
+int smap_syslog_stream_create (smap_stream_t *pstream, int prio,
+ const char *pfx);
+
+int smap_sockmap_stream_create(smap_stream_t *pstream, int fd, int flags);
+int smap_sockmap_stream_create2(smap_stream_t *pstream, int fd[], int flags);
+
+int smap_transcript_stream_create(smap_stream_t *pstream,
+ smap_stream_t transport,
+ smap_stream_t logstr,
+ const char *prefix[]);
+
+
+#endif
diff --git a/include/smap/streamdef.h b/include/smap/streamdef.h
new file mode 100644
index 0000000..98ecac4
--- /dev/null
+++ b/include/smap/streamdef.h
@@ -0,0 +1,73 @@
+/* This file is part of smap.
+ Copyright (C) 2009, 2010 Sergey Poznyakoff
+
+ This program 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 3, or (at your option)
+ any later version.
+
+ This program 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, see <http://www.gnu.org/licenses/>. */
+
+#ifndef __SMAP_STREAMDEF_H
+#define __SMAP_STREAMDEF_H
+
+#define _SMAP_STR_DIRTY 0x01000 /* Buffer dirty */
+#define _SMAP_STR_WRT 0x02000 /* Unflushed write pending */
+#define _SMAP_STR_ERR 0x04000 /* Permanent error state */
+#define _SMAP_STR_EOF 0x08000 /* EOF encountered */
+#define _SMAP_STR_MORESPC 0x10000
+#define _SMAP_STR_INTERN_MASK 0xff000
+
+struct _smap_stream {
+ int ref_count;
+
+ enum smap_buffer_type buftype;
+ size_t bufsize;
+ char *buffer;
+ size_t level;
+ char *cur;
+
+ int flags;
+ smap_off_t offset;
+ smap_off_t bytes_in, bytes_out;
+
+ size_t size_hint;
+ int last_err;
+
+ int (*read)(struct _smap_stream *, char *, size_t, size_t *);
+ int (*readdelim)(struct _smap_stream *, char *, size_t, int, size_t *);
+ int (*write)(struct _smap_stream *, const char *, size_t, size_t *);
+ int (*flush)(struct _smap_stream *);
+ int (*open)(struct _smap_stream *);
+ int (*close)(struct _smap_stream *);
+ void (*done)(struct _smap_stream *);
+ int (*seek)(struct _smap_stream *, smap_off_t, smap_off_t *);
+ int (*size)(struct _smap_stream *, smap_off_t *);
+ int (*ctl)(struct _smap_stream *, int, void *);
+ int (*wait)(struct _smap_stream *, int *, struct timeval *);
+ int (*truncate)(struct _smap_stream *, smap_off_t);
+ int (*shutdown)(struct _smap_stream *, int);
+
+ const char *(*error_string)(struct _smap_stream *, int);
+
+};
+
+#define _stream_cleareof(s) ((s)->flags &= ~_SMAP_STR_EOF)
+#define _stream_advance_buffer(s,n) ((s)->cur += n, (s)->level -= n)
+#define _stream_buffer_offset(s) ((s)->cur - (s)->buffer)
+#define _stream_orig_level(s) ((s)->level + _stream_buffer_offset(s))
+
+smap_stream_t _smap_stream_create(size_t size, int flags);
+int smap_stream_read_unbuffered(smap_stream_t stream, void *buf, size_t size,
+ int full_read, size_t *pnread);
+int smap_stream_write_unbuffered(smap_stream_t stream,
+ const void *buf, size_t size,
+ int full_write, size_t *pnwritten);
+
+#endif
diff --git a/lib/Makefile.am b/lib/Makefile.am
index 49ca368..3c5d629 100644
--- a/lib/Makefile.am
+++ b/lib/Makefile.am
@@ -17,17 +17,25 @@
lib_LTLIBRARIES = libsmap.la
libsmap_la_SOURCES = \
+ asnprintf.c\
+ asprintf.c\
debug.c\
diag.c\
+ fileoutstr.c\
kwtab.c\
- ostr.c\
+ sockmapstr.c\
parseopt.c\
progname.c\
- smapostr.c\
stderr.c\
+ stream.c\
+ stream_printf.c\
+ stream_vprintf.c\
syslog.c\
+ syslogstr.c\
url.c\
- wordsplit.c
+ vasnprintf.c\
+ wordsplit.c\
+ xscript.c
libsmap_la_LDFLAGS = -version-info 0:0:0
diff --git a/lib/asnprintf.c b/lib/asnprintf.c
new file mode 100644
index 0000000..26d45c5
--- /dev/null
+++ b/lib/asnprintf.c
@@ -0,0 +1,40 @@
+/* This file is part of smap.
+ Copyright (C) 2009, 2010 Sergey Poznyakoff
+
+ This program 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 3, or (at your option)
+ any later version.
+
+ This program 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, see <http://www.gnu.org/licenses/>. */
+
+#if HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <stdlib.h>
+#include <stdarg.h>
+#include <stdio.h>
+#include <errno.h>
+#include <string.h>
+
+#include <smap/printf.h>
+
+int
+smap_asnprintf(char **pbuf, size_t *psize, const char *fmt, ...)
+{
+ int rc;
+ va_list ap;
+
+ va_start (ap, fmt);
+ rc = smap_vasnprintf(pbuf, psize, fmt, ap);
+ va_end (ap);
+ return rc;
+}
+
diff --git a/lib/asprintf.c b/lib/asprintf.c
new file mode 100644
index 0000000..8c30504
--- /dev/null
+++ b/lib/asprintf.c
@@ -0,0 +1,41 @@
+/* This file is part of smap.
+ Copyright (C) 2009, 2010 Sergey Poznyakoff
+
+ This program 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 3, or (at your option)
+ any later version.
+
+ This program 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, see <http://www.gnu.org/licenses/>. */
+
+#if HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <stdlib.h>
+#include <stdarg.h>
+#include <stdio.h>
+#include <errno.h>
+#include <string.h>
+
+#include <smap/printf.h>
+
+int
+smap_asprintf(char **pbuf, const char *fmt, ...)
+{
+ int rc;
+ va_list ap;
+ size_t size;
+
+ va_start (ap, fmt);
+ rc = smap_vasnprintf(pbuf, &size, fmt, ap);
+ va_end (ap);
+ return rc;
+}
+
diff --git a/lib/debug.c b/lib/debug.c
index 8cc0000..471efb2 100644
--- a/lib/debug.c
+++ b/lib/debug.c
@@ -108,8 +108,8 @@ smap_debug_printf(const char *fmt, ...)
{
va_list ap;
va_start(ap, fmt);
- smap_ostream_vprintf(smap_debug_str, fmt, ap);
- smap_ostream_write(smap_debug_str, "\n", 1);
+ smap_stream_vprintf(smap_debug_str, fmt, ap);
+ smap_stream_write(smap_debug_str, "\n", 1, NULL);
va_end(ap);
}
diff --git a/lib/diag.c b/lib/diag.c
index 786d06c..93df1c0 100644
--- a/lib/diag.c
+++ b/lib/diag.c
@@ -19,17 +19,17 @@
#endif
#include <stdlib.h>
#include <stdio.h>
-#include "smap/ostr.h"
+#include "smap/stream.h"
#include "smap/diag.h"
-smap_ostream_t smap_error_str;
-smap_ostream_t smap_debug_str;
-smap_ostream_t smap_trace_str;
+smap_stream_t smap_error_str;
+smap_stream_t smap_debug_str;
+smap_stream_t smap_trace_str;
void
smap_verror(const char *fmt, va_list ap)
{
- if (smap_ostream_vprintf(smap_error_str, fmt, ap) < 0) {
+ if (smap_stream_vprintf(smap_error_str, fmt, ap) < 0) {
vfprintf(stderr, fmt, ap);
fputc('\n', stderr);
fprintf(stderr,
@@ -37,8 +37,8 @@ smap_verror(const char *fmt, va_list ap)
"initialized, please report\n");
abort();
}
- smap_ostream_write(smap_error_str, "\n", 1);
- smap_ostream_flush(smap_error_str);
+ smap_stream_write(smap_error_str, "\n", 1, NULL);
+ smap_stream_flush(smap_error_str);
}
void
diff --git a/lib/fileoutstr.c b/lib/fileoutstr.c
new file mode 100644
index 0000000..884d075
--- /dev/null
+++ b/lib/fileoutstr.c
@@ -0,0 +1,93 @@
+/* This file is part of smap.
+ Copyright (C) 2006, 2007, 2010 Sergey Poznyakoff
+
+ This program 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 3, or (at your option)
+ any later version.
+
+ This program 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, see <http://www.gnu.org/licenses/>. */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+#include <stdio.h>
+#include <errno.h>
+#include <string.h>
+#include "smap/diag.h"
+#include "smap/stream.h"
+#include "smap/streamdef.h"
+
+struct fileout_stream {
+ struct _smap_stream base;
+ FILE *file;
+ char *pfx;
+ int pgopt;
+};
+
+static int
+_fileout_stream_write(struct _smap_stream *stream, const char *buf,
+ size_t size, size_t *pret)
+{
+ struct fileout_stream *str = (struct fileout_stream *)stream;
+ size_t n;
+
+ if (str->pgopt)
+ fprintf(str->file, "%s: ", smap_progname);
+ if (str->pfx)
+ fprintf(str->file, "%s: ", str->pfx);
+ n = fwrite(buf, 1, size, str->file);
+ *pret = n;
+ if (n != size)
+ return errno;
+ return 0;
+}
+
+static int
+_fileout_stream_flush(struct _smap_stream *stream)
+{
+ struct fileout_stream *str = (struct fileout_stream *)stream;
+ if (fflush(str->file))
+ return errno;
+ return 0;
+}
+
+static void
+_fileout_stream_destroy(struct _smap_stream *stream)
+{
+ struct fileout_stream *str = (struct fileout_stream *)stream;
+ free(str->pfx);
+}
+
+int
+smap_fileout_stream_create (smap_stream_t *pstream, FILE *file,
+ const char *pfx, int pgopt)
+{
+ struct fileout_stream *str =
+ (struct fileout_stream *)
+ _smap_stream_create(sizeof(*str), SMAP_STREAM_WRITE);
+ if (!str)
+ return ENOMEM;
+ if (pfx) {
+ str->pfx = strdup(pfx);
+ if (!str->pfx) {
+ free(str);
+ return ENOMEM;
+ }
+ } else
+ str->pfx = NULL;
+ str->file = file;
+ str->pgopt = pgopt;
+ str->base.write = _fileout_stream_write;
+ str->base.flush = _fileout_stream_flush;
+ str->base.done = _fileout_stream_destroy;
+ *pstream = (smap_stream_t) str;
+ smap_stream_set_buffer(*pstream, smap_buffer_line, 1024);
+ return 0;
+}
diff --git a/lib/ostr.c b/lib/ostr.c
deleted file mode 100644
index 91fb02e..0000000
--- a/lib/ostr.c
+++ /dev/null
@@ -1,197 +0,0 @@
-/* This file is part of smap.
- Copyright (C) 2006, 2007, 2010 Sergey Poznyakoff
-
- This program 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 3, or (at your option)
- any later version.
-
- This program 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, see <http://www.gnu.org/licenses/>. */
-
-#ifdef HAVE_CONFIG_H
-# include <config.h>
-#endif
-#include <stdlib.h>
-#include <stdio.h>
-#include <string.h>
-#include <errno.h>
-#include "smap/ostr.h"
-
-struct smap_output_stream {
- char *buf;
- size_t size;
- size_t level;
- void (*flush) (void *data, char *buf);
- void *data;
-};
-
-static int
-_chkbuf(struct smap_output_stream *str, size_t size)
-{
- if (str->level + size + 1 > str->size) {
- size_t newsize = str->level + size + 1;
- char *newbuf = realloc(str->buf, newsize);
- if (!newbuf)
- return -1;
- str->size = newsize;
- str->buf = newbuf;
- }
- return 0;
-}
-
-static void
-_flushbuf(struct smap_output_stream *str)
-{
- char *ptr = str->buf;
- size_t size = str->level;
-
- while (size) {
- size_t len;
- char *p = memchr(ptr, '\n', size);
- if (!p)
- break;
- *p++ = 0;
- str->flush(str->data, ptr);
- len = p - ptr;
- ptr += len;
- size -= len;
- }
- if (ptr > str->buf && size)
- memmove(str->buf, ptr, size);
- str->level = size;
-}
-
-int
-smap_ostream_write(smap_ostream_t str, const char *buf, size_t len)
-{
- if (!str) {
- errno = EINVAL;
- return -1;
- }
- if (_chkbuf(str, len))
- return -1;
- memcpy(str->buf + str->level, buf, len);
- str->level += len;
- _flushbuf(str);
- return 0;
-}
-
-int
-smap_ostream_vprintf(smap_ostream_t str, const char *fmt, va_list ap)
-{
- int n;
-
- if (!str) {
- errno = EINVAL;
- return -1;
- }
- if (!str->buf) {
- if (str->size == 0)
- str->size = 512; /* Initial allocation */
-
- str->buf = calloc(1, str->size);
- if (!str->buf)
- return -1;
- str->level = 0;
- }
-
- for (;;) {
- size_t buflen = str->size - str->level;
- n = vsnprintf(str->buf + str->level, buflen, fmt, ap);
-
- if (n < 0 || n >= buflen
- || !memchr (str->buf + str->level, '\0', n + 1)) {
- char *newbuf;
- size_t newlen = str->size * 2;
- if (newlen < str->size) {
- errno = ENOMEM;
- return -1;
- }
- newbuf = realloc(str->buf, newlen);
- if (!newbuf)
- return -1;
- str->size = newlen;
- str->buf = newbuf;
- } else {
- str->level += n;
- break;
- }
- }
- _flushbuf(str);
- return n;
-}
-
-int
-smap_ostream_printf(smap_ostream_t str, const char *fmt, ...)
-{
- va_list ap;
- int n;
-
- if (!str) {
- errno = EINVAL;
- return -1;
- }
- va_start(ap, fmt);
- n = smap_ostream_vprintf(str, fmt, ap);
- va_end(ap);
- return n;
-}
-
-int
-smap_ostream_flush(smap_ostream_t str)
-{
- if (!str) {
- errno = EINVAL;
- return -1;
- }
- _flushbuf(str);
- if (str->level) {
- str->buf[str->level] = 0;
- str->flush(str->data, str->buf);
- str->level = 0;
- }
- return 0;
-}
-
-smap_ostream_t
-smap_ostream_create(void (*flush)(void *data, char *buf), void *data)
-{
- struct smap_output_stream *str = calloc(1, sizeof(str[0]));
- if (!str)
- return NULL;
- str->flush = flush;
- str->data = data;
- str->size = 512;
- str->buf = malloc(str->size);
- if (!str->buf) {
- free(str);
- return NULL;
- }
- return str;
-}
-
-void
-smap_ostream_free(smap_ostream_t str)
-{
- if (!str)
- return;
- free(str->buf);
- free(str);
-}
-
-void
-smap_ostream_destroy(smap_ostream_t *str)
-{
- if (!str)
- return;
- if (*str) {
- smap_ostream_free(*str);
- *str = NULL;
- }
-}
diff --git a/lib/sockmapstr.c b/lib/sockmapstr.c
new file mode 100644
index 0000000..267dff0
--- /dev/null
+++ b/lib/sockmapstr.c
@@ -0,0 +1,477 @@
+/* This file is part of smap.
+ Copyright (C) 2006, 2007, 2010 Sergey Poznyakoff
+
+ This program 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 3, or (at your option)
+ any later version.
+
+ This program 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, see <http://www.gnu.org/licenses/>. */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <limits.h>
+#include <string.h>
+#include <errno.h>
+#include <unistd.h>
+#include "smap/diag.h"
+#include "smap/stream.h"
+#include "smap/streamdef.h"
+
+/* Bound on length of the string representing a size_t.
+ log10 (2.0) < 146/485; */
+#define SIZE_T_STRLEN_BOUND ((sizeof(size_t) * CHAR_BIT) * 146 / 485 + 1)
+
+
+struct sockmap_output_stream {
+ struct _smap_stream base;
+ int fd;
+ size_t bufsize;
+ char *buf;
+ int debug_idx;
+ char *debug_pfx;
+};
+
+static char *
+format_len(char *buf, size_t arg)
+{
+ char *p = buf + SIZE_T_STRLEN_BOUND;
+
+ *--p = 0;
+ while (arg) {
+ unsigned n = arg % 10;
+ *--p = '0' + n;
+ arg /= 10;
+ }
+ return p;
+}
+
+static int
+_sockmap_output_stream_write(struct _smap_stream *stream, const char *buf,
+ size_t len, size_t *pret)
+{
+ struct sockmap_output_stream *sp =
+ (struct sockmap_output_stream *)stream;
+ char nbuf[SIZE_T_STRLEN_BOUND+1], *p;
+ size_t size, n;
+
+ if (smap_trace_str) {
+ smap_stream_write(smap_trace_str, buf, len, NULL);
+ }
+ len--;
+ p = format_len(nbuf, len);
+ n = strlen(p);
+ size = n + 3 + len;
+ if (size > sp->bufsize) {
+ char *newbuf = realloc(sp->buf, size);
+ if (!newbuf)
+ return ENOMEM;
+ sp->buf = newbuf;
+ sp->bufsize = size;
+ }
+ memcpy(sp->buf, p, n);
+ sp->buf[n++] = ':';