Commit 1e4c4488 1e4c44886b7dd9d9995f60ae038e04b08ecbd786 by Sergey Poznyakoff

Initialize standard I/O streams statically.

This allows programmers to use them right away, much like their stdio
counterparts.  The mu_stdstream_setup and friends can be used to
re-initialize them, should the need be.

* include/mailutils/sys/file_stream.h
(_MU_FILE_STREAM_STATIC_FILENAME): New flag.
(_mu_file_stream_setup): New proto.
* include/mailutils/sys/logstream.h (_mu_log_stream_setup): New proto.
* include/mailutils/sys/stream.h (_MU_STR_EVENT_BOOTSTRAP): New event
code.
(_mu_stream) <destroy>: New method.
* libmailutils/stdstream/basestr.c: Define the three standard streams
statically, use bootstrap event to initialize them.
* libmailutils/stdstream/strerr.c (mu_stdstream_strerr_create): Accept
tag==NULL.
* libmailutils/stream/file_stream.c (fd_done): Do not free filename if
_MU_FILE_STREAM_STATIC_FILENAME is set.
(_mu_file_stream_setup): New function.
* libmailutils/stream/logstream.c (NEXT): Check size before advancing
buffer pointer.
(_mu_log_stream_setup): New function.
* libmailutils/stream/stream.c (_bootstrap_event): New macro.
(mu_stream_destroy): If .destroy is defined, use it instead of free(2).
(mu_stream_open,mu_stream_seek,mu_stream_set_buffer)
(mu_stream_read,mu_stream_readdelim,mu_stream_getdelim)
(mu_stream_write,mu_stream_size,mu_stream_wait)
(mu_stream_truncate,mu_stream_shutdown): Call _bootstrap_event at the
beginning.
* libmailutils/tests/.gitignore: Add strin, strout.
* libmailutils/tests/Makefile.am (noinst_PROGRAMS): Add strin, strout.
(TESTSUITE_AT): Add stdstream tests.
* libmailutils/tests/testsuite.at: Include stdstream tests.
* libmailutils/tests/strerr.at: New test case.
* libmailutils/tests/strin.at: Likewise.
* libmailutils/tests/strout.at: Likewise.
* libmailutils/tests/strin.c: New test program.
* libmailutils/tests/strout.c: Likewise.
1 parent c42e6194
......@@ -24,6 +24,7 @@
#define _MU_FILE_STREAM_TEMP 0x01
#define _MU_FILE_STREAM_ECHO_OFF 0x02
#define _MU_FILE_STREAM_FD_BORROWED 0x04
#define _MU_FILE_STREAM_STATIC_FILENAME 0x08
struct _mu_file_stream
{
......@@ -36,5 +37,6 @@ struct _mu_file_stream
int _mu_file_stream_create (struct _mu_file_stream **pstream, size_t size,
const char *filename, int fd, int flags);
void _mu_file_stream_setup (struct _mu_file_stream *str);
#endif
......
......@@ -33,4 +33,6 @@ struct _mu_log_stream
struct mu_locus locus; /* Location */
};
void _mu_log_stream_setup (struct _mu_log_stream *sp, mu_stream_t transport);
#endif
......
......@@ -30,6 +30,7 @@
#define _MU_STR_EVENT_FILLBUF 2
#define _MU_STR_EVENT_FLUSHBUF 3
#define _MU_STR_EVENT_CLOSE 4
#define _MU_STR_EVENT_BOOTSTRAP 5
#define _MU_STR_EVMASK(n) (1<<(n))
......@@ -58,6 +59,7 @@ struct _mu_stream
int (*open) (struct _mu_stream *);
int (*close) (struct _mu_stream *);
void (*done) (struct _mu_stream *);
void (*destroy) (struct _mu_stream *);
int (*seek) (struct _mu_stream *, mu_off_t, mu_off_t *);
int (*size) (struct _mu_stream *, mu_off_t *);
int (*ctl) (struct _mu_stream *, int, int, void *);
......
......@@ -28,10 +28,127 @@
#include <mailutils/stream.h>
#include <mailutils/stdstream.h>
#include <mailutils/util.h>
#include <mailutils/io.h>
#include <mailutils/filter.h>
#include <mailutils/sys/stream.h>
#include <mailutils/sys/file_stream.h>
#include <mailutils/sys/logstream.h>
mu_stream_t mu_strin;
mu_stream_t mu_strout;
mu_stream_t mu_strerr;
static void stdstream_flushall_setup (void);
/* This event callback bootstraps standard I/O streams mu_strin and
mu_strout. It is invoked when the stream core emits the bootstrap
event for the stream. */
static void
std_bootstrap (struct _mu_stream *str, int code,
unsigned long lval, void *pval)
{
struct _mu_file_stream *fstr = (struct _mu_file_stream *) str;
_mu_file_stream_setup (fstr);
str->event_cb = NULL;
str->event_mask = 0;
str->event_cb_data = 0;
fstr->stream.flags |= _MU_STR_OPEN;
mu_stream_set_buffer ((mu_stream_t) fstr, mu_buffer_line, 0);
stdstream_flushall_setup ();
}
/* This event callback bootstraps standard error stream (mu_strerr).
It is invoked when the stream core emits the bootstrap event for
the stream. */
static void
std_log_bootstrap (struct _mu_stream *str, int code,
unsigned long lval, void *pval)
{
struct _mu_log_stream *logstr = (struct _mu_log_stream *) str;
int yes = 1;
mu_stream_t errstr, transport;
int rc;
rc = mu_stdio_stream_create (&errstr, MU_STDERR_FD, 0);
if (rc)
{
fprintf (stderr, "%s: cannot open error stream: %s\n",
mu_program_name ? mu_program_name : "<unknown>",
mu_strerror (rc));
abort ();
}
/* Make sure 2 is not closed when errstr is destroyed. */
mu_stream_ioctl (errstr, MU_IOCTL_FD, MU_IOCTL_FD_SET_BORROW, &yes);
if (!mu_program_name)
transport = errstr;
else
{
char *fltargs[3] = { "INLINE-COMMENT", };
mu_asprintf (&fltargs[1], "%s: ", mu_program_name);
fltargs[2] = NULL;
rc = mu_filter_create_args (&transport, errstr,
"INLINE-COMMENT",
2, (const char**)fltargs,
MU_FILTER_ENCODE, MU_STREAM_WRITE);
mu_stream_unref (errstr);
free (fltargs[1]);
if (rc)
{
fprintf (stderr,
"%s: cannot open output filter stream: %s",
mu_program_name ? mu_program_name : "<unknown>",
mu_strerror (rc));
abort ();
}
mu_stream_set_buffer (transport, mu_buffer_line, 0);
}
str->event_cb = NULL;
str->event_mask = 0;
str->event_cb_data = 0;
_mu_log_stream_setup (logstr, transport);
stdstream_flushall_setup ();
}
/* The noop destroy function is necessary to prevent stream core from
freeing the stream on mu_stream_unref. */
static void
bootstrap_destroy (struct _mu_stream *str)
{
/* Nothing */
}
/* Standard I/O streams: */
static struct _mu_file_stream stdstream[2] = {
{ { ref_count: 1,
buftype: mu_buffer_none,
flags: MU_STREAM_READ,
destroy: bootstrap_destroy,
event_cb: std_bootstrap,
event_mask: _MU_STR_EVMASK (_MU_STR_EVENT_BOOTSTRAP)
}, fd: MU_STDIN_FD, filename: "<stdin>",
flags: _MU_FILE_STREAM_FD_BORROWED|_MU_FILE_STREAM_STATIC_FILENAME },
{ { ref_count: 1,
buftype: mu_buffer_none,
flags: MU_STREAM_WRITE,
event_cb: std_bootstrap,
event_mask: _MU_STR_EVMASK (_MU_STR_EVENT_BOOTSTRAP)
}, fd: MU_STDOUT_FD, filename: "<stdout>",
flags: _MU_FILE_STREAM_FD_BORROWED|_MU_FILE_STREAM_STATIC_FILENAME }
};
/* Standard error stream: */
static struct _mu_log_stream default_strerr = {
{ ref_count: 1,
buftype: mu_buffer_none,
flags: MU_STREAM_WRITE,
destroy: bootstrap_destroy,
event_cb: std_log_bootstrap,
event_mask: _MU_STR_EVMASK (_MU_STR_EVENT_BOOTSTRAP)
}
};
/* Pointers to these: */
mu_stream_t mu_strin = (mu_stream_t) &stdstream[MU_STDIN_FD];
mu_stream_t mu_strout = (mu_stream_t) &stdstream[MU_STDOUT_FD];
mu_stream_t mu_strerr = (mu_stream_t) &default_strerr;
static void
stdstream_flushall (void *data MU_ARG_UNUSED)
......@@ -41,7 +158,17 @@ stdstream_flushall (void *data MU_ARG_UNUSED)
mu_stream_flush (mu_strerr);
}
static int stdstream_flushall_setup = 0;
static void
stdstream_flushall_setup (void)
{
static int _setup = 0;
if (!_setup)
{
mu_onexit (stdstream_flushall, NULL);
_setup = 1;
}
}
void
mu_stdstream_setup (int flags)
......@@ -120,11 +247,7 @@ mu_stdstream_setup (int flags)
abort ();
}
if (!stdstream_flushall_setup)
{
mu_onexit (stdstream_flushall, NULL);
stdstream_flushall_setup = 1;
}
stdstream_flushall_setup ();
}
int
......
......@@ -50,7 +50,7 @@ mu_stdstream_strerr_create (mu_stream_t *plogger, int type, int facility,
if (rc)
{
fprintf (stderr, _("%s: cannot open error stream: %s\n"),
tag, mu_strerror (rc));
tag ? tag : "<unknown>", mu_strerror (rc));
return MU_ERR_FAILURE;
}
/* Make sure 2 is not closed when str is destroyed.
......@@ -74,7 +74,7 @@ mu_stdstream_strerr_create (mu_stream_t *plogger, int type, int facility,
{
fprintf (stderr,
_("%s: cannot open output filter stream: %s"),
tag, mu_strerror (rc));
tag ? tag : "<unknown>", mu_strerror (rc));
return MU_ERR_FAILURE;
}
mu_stream_set_buffer (transport, mu_buffer_line, 0);
......@@ -88,14 +88,14 @@ mu_stdstream_strerr_create (mu_stream_t *plogger, int type, int facility,
if (rc)
{
fprintf (stderr, _("%s: cannot create syslog stream: %s\n"),
tag, mu_strerror (rc));
tag ? tag : "<unknown>", mu_strerror (rc));
return MU_ERR_FAILURE;
}
break;
default:
fprintf (stderr, _("%s: cannot create error stream: %s\n"),
tag, mu_strerror (EINVAL));
tag ? tag : "<unknown>", mu_strerror (EINVAL));
return EINVAL;
}
......@@ -104,7 +104,7 @@ mu_stdstream_strerr_create (mu_stream_t *plogger, int type, int facility,
if (rc)
{
fprintf (stderr, _("%s: cannot open logger stream: %s\n"),
tag , mu_strerror (rc));
tag ? tag : "<unknown>", mu_strerror (rc));
return MU_ERR_FAILURE;
}
return 0;
......
......@@ -153,7 +153,7 @@ fd_done (struct _mu_stream *str)
struct _mu_file_stream *fstr = (struct _mu_file_stream *) str;
if (fstr->fd != -1)
fd_close (str);
if (fstr->filename)
if (fstr->filename && !(fstr->flags & _MU_FILE_STREAM_STATIC_FILENAME))
free (fstr->filename);
if (fstr->echo_state)
free (fstr->echo_state);
......@@ -312,15 +312,9 @@ fd_truncate (mu_stream_t stream, mu_off_t size)
return 0;
}
int
_mu_file_stream_create (struct _mu_file_stream **pstream, size_t size,
const char *filename, int fd, int flags)
void
_mu_file_stream_setup (struct _mu_file_stream *str)
{
struct _mu_file_stream *str =
(struct _mu_file_stream *) _mu_stream_create (size, flags);
if (!str)
return ENOMEM;
str->stream.read = fd_read;
str->stream.write = fd_write;
str->stream.open = fd_open;
......@@ -331,6 +325,18 @@ _mu_file_stream_create (struct _mu_file_stream **pstream, size_t size,
str->stream.ctl = fd_ioctl;
str->stream.wait = fd_wait;
str->stream.truncate = fd_truncate;
}
int
_mu_file_stream_create (struct _mu_file_stream **pstream, size_t size,
const char *filename, int fd, int flags)
{
struct _mu_file_stream *str =
(struct _mu_file_stream *) _mu_stream_create (size, flags);
if (!str)
return ENOMEM;
_mu_file_stream_setup (str);
if (filename)
str->filename = mu_strdup (filename);
......
......@@ -103,7 +103,7 @@ _log_write (struct _mu_stream *str, const char *buf, size_t size,
int rc;
int escape_error = 0;
#define NEXT do { buf++; size--; if (size == 0) return EINVAL; } while (0)
#define NEXT do { if (size == 0) return EINVAL; buf++; size--; } while (0)
#define READNUM(n) do { \
unsigned __x = 0; \
if (*buf != '<') \
......@@ -470,17 +470,11 @@ _log_ctl (struct _mu_stream *str, int code, int opcode, void *arg)
return 0;
}
int
mu_log_stream_create (mu_stream_t *pstr, mu_stream_t transport)
void
_mu_log_stream_setup (struct _mu_log_stream *sp, mu_stream_t transport)
{
struct _mu_log_stream *sp;
mu_stream_t stream;
int rc;
sp = (struct _mu_log_stream *)
_mu_stream_create (sizeof (*sp), MU_STREAM_WRITE);
if (!sp)
return ENOMEM;
sp->base.write = _log_write;
sp->base.flush = _log_flush;
sp->base.close = _log_close;
......@@ -494,13 +488,21 @@ mu_log_stream_create (mu_stream_t *pstr, mu_stream_t transport)
stream = (mu_stream_t) sp;
mu_stream_set_buffer (stream, mu_buffer_line, 0);
rc = mu_stream_open (stream);
if (rc)
mu_stream_destroy (&stream);
else
*pstr = stream;
}
return rc;
int
mu_log_stream_create (mu_stream_t *pstr, mu_stream_t transport)
{
struct _mu_log_stream *sp;
sp = (struct _mu_log_stream *)
_mu_stream_create (sizeof (*sp), MU_STREAM_WRITE);
if (!sp)
return ENOMEM;
_mu_log_stream_setup (sp, transport);
*pstr = (mu_stream_t) sp;
return 0;
}
......
......@@ -46,6 +46,19 @@ size_t mu_stream_default_buffer_size = MU_STREAM_DEFBUFSIZ;
} \
while (0)
#define _bootstrap_event(stream) \
do \
{ \
if ((stream)->event_cb && \
((stream)->event_mask & _MU_STR_EVMASK(_MU_STR_EVENT_BOOTSTRAP))) \
{ \
(stream)->event_cb (stream, _MU_STR_EVENT_BOOTSTRAP, 0, NULL); \
(stream)->event_mask &= ~_MU_STR_EVMASK(_MU_STR_EVENT_BOOTSTRAP); \
} \
} \
while (0)
#define _stream_stat_incr(s, k, n) \
(((s)->statmask & MU_STREAM_STAT_MASK(k)) ? ((s)->statbuf[k] += n) : 0)
......@@ -292,6 +305,9 @@ mu_stream_destroy (mu_stream_t *pstream)
mu_stream_close (str);
if (str->done)
str->done (str);
if (str->destroy)
str->destroy (str);
else
free (str);
*pstream = NULL;
}
......@@ -336,6 +352,7 @@ mu_stream_open (mu_stream_t stream)
if (stream->flags & _MU_STR_OPEN)
return MU_ERR_OPEN;
_bootstrap_event (stream);
if (stream->open)
{
if ((rc = stream->open (stream)))
......@@ -399,6 +416,7 @@ mu_stream_seek (mu_stream_t stream, mu_off_t offset, int whence,
int rc;
mu_off_t size;
_bootstrap_event (stream);
if (!(stream->flags & _MU_STR_OPEN))
{
if (stream->open)
......@@ -551,6 +569,8 @@ int
mu_stream_set_buffer (mu_stream_t stream, enum mu_buffer_type type,
size_t size)
{
_bootstrap_event (stream);
if (size == 0)
size = mu_stream_default_buffer_size;
......@@ -717,6 +737,8 @@ _stream_write_unbuffered (mu_stream_t stream,
int
mu_stream_read (mu_stream_t stream, void *buf, size_t size, size_t *pread)
{
_bootstrap_event (stream);
if (!(stream->flags & _MU_STR_OPEN))
{
if (stream->open)
......@@ -857,6 +879,8 @@ mu_stream_readdelim (mu_stream_t stream, char *buf, size_t size,
{
int rc;
_bootstrap_event (stream);
if (size == 0)
return EINVAL;
......@@ -905,6 +929,8 @@ mu_stream_getdelim (mu_stream_t stream, char **pbuf, size_t *psize,
size_t n = *psize;
size_t cur_len = 0;
_bootstrap_event (stream);
if (!(stream->flags & _MU_STR_OPEN))
{
if (stream->open)
......@@ -996,6 +1022,8 @@ mu_stream_write (mu_stream_t stream, const void *buf, size_t size,
{
int rc = 0;
_bootstrap_event (stream);
if (!(stream->flags & _MU_STR_OPEN))
{
if (stream->open)
......@@ -1063,6 +1091,7 @@ mu_stream_flush (mu_stream_t stream)
if (!stream)
return EINVAL;
_bootstrap_event (stream);
if (!(stream->flags & _MU_STR_OPEN))
{
if (stream->open)
......@@ -1105,6 +1134,7 @@ mu_stream_size (mu_stream_t stream, mu_off_t *psize)
int rc;
mu_off_t size;
_bootstrap_event (stream);
if (!(stream->flags & _MU_STR_OPEN))
{
if (stream->open)
......@@ -1126,6 +1156,7 @@ mu_stream_size (mu_stream_t stream, mu_off_t *psize)
int
mu_stream_ioctl (mu_stream_t stream, int family, int opcode, void *ptr)
{
_bootstrap_event (stream);
if (stream->ctl == NULL)
return ENOSYS;
return stream->ctl (stream, family, opcode, ptr);
......@@ -1138,6 +1169,7 @@ mu_stream_wait (mu_stream_t stream, int *pflags, struct timeval *tvp)
if (stream == NULL)
return EINVAL;
_bootstrap_event (stream);
#if 0
/* NOTE: Sometimes mu_stream_wait is called after a failed mu_stream_open.
In particular, this is needed for a TCP stream opened with a
......@@ -1181,6 +1213,8 @@ mu_stream_wait (mu_stream_t stream, int *pflags, struct timeval *tvp)
int
mu_stream_truncate (mu_stream_t stream, mu_off_t size)
{
_bootstrap_event (stream);
if (!(stream->flags & _MU_STR_OPEN))
{
if (stream->open)
......@@ -1204,6 +1238,8 @@ mu_stream_shutdown (mu_stream_t stream, int how)
{
int rc;
_bootstrap_event (stream);
if (!(stream->flags & _MU_STR_OPEN))
{
if (stream->open)
......
......@@ -18,6 +18,8 @@ mailcap
prop
scantime
strftime
strin
strout
url-comp
url-parse
wicket
......
......@@ -53,6 +53,8 @@ noinst_PROGRAMS = \
prop\
scantime\
strftime\
strin\
strout\
tempfile\
url-comp\
url-parse\
......@@ -85,6 +87,9 @@ TESTSUITE_AT = \
prop.at\
scantime.at\
strftime.at\
strerr.at\
strin.at\
strout.at\
testsuite.at\
url.at\
url-comp.at\
......
# This file is part of GNU Mailutils. -*- Autotest -*-
# Copyright (C) 2011 Free Software Foundation, Inc.
#
# GNU Mailutils 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.
#
# GNU Mailutils 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 GNU Mailutils. If not, see <http://www.gnu.org/licenses/>.
AT_SETUP([strerr])
AT_KEYWORDS([stdstream])
AT_CHECK([
strout -err now is the time for all good men
],
[0],
[],
[strout: now
strout: is
strout: the
strout: time
strout: for
strout: all
strout: good
strout: men
])
AT_CLEANUP
# This file is part of GNU Mailutils. -*- Autotest -*-
# Copyright (C) 2011 Free Software Foundation, Inc.
#
# GNU Mailutils 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.
#
# GNU Mailutils 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 GNU Mailutils. If not, see <http://www.gnu.org/licenses/>.
AT_SETUP([strin])
AT_KEYWORDS([stdstream])
AT_DATA([input],
[Omnis enim res, quae dando non deficit,
dum habetur et non datur, nondum habetur,
quomodo habenda est.
])
AT_CHECK([
strin < input
],
[0],
[Omnis enim res, quae dando non deficit,
dum habetur et non datur, nondum habetur,
quomodo habenda est.
])
AT_CLEANUP
/* GNU Mailutils -- a suite of utilities for electronic mail
Copyright (C) 2011 Free Software Foundation, Inc.
GNU Mailutils 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.
GNU Mailutils 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 GNU Mailutils. 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 <mailutils/stream.h>
#include <mailutils/stdstream.h>
#include <mailutils/diag.h>
#include <mailutils/errno.h>
int
main (int argc, char **argv)
{
int i, rc;
int echo_state = 0;
size_t n;
char buf[80];
for (i = 1; i < argc; i++)
{
char *arg = argv[i];
if (arg[0] == '-')
{
if (strcmp (arg, "-noecho") == 0)
{
MU_ASSERT (mu_stream_ioctl (mu_strin, MU_IOCTL_ECHO,
MU_IOCTL_OP_SET,
&echo_state));
echo_state = 1;
}
else
{
fprintf (stderr, "usage: %s [-noecho]\n", argv[0]);
return 1;
}
}
}
while ((rc = mu_stream_read (mu_strin, buf, sizeof (buf), &n) == 0) &&
n > 0)
fwrite (buf, 1, n, stdout);
if (echo_state)
MU_ASSERT (mu_stream_ioctl (mu_strin, MU_IOCTL_ECHO, MU_IOCTL_OP_SET,
&echo_state));
return 0;
}
# This file is part of GNU Mailutils. -*- Autotest -*-
# Copyright (C) 2011 Free Software Foundation, Inc.
#
# GNU Mailutils 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.
#
# GNU Mailutils 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 GNU Mailutils. If not, see <http://www.gnu.org/licenses/>.
AT_SETUP([strout])
AT_KEYWORDS([stdstream])
AT_CHECK([
strout now is the time for all good men
],
[0],
[now
is
the
time
for
all
good
men
])
AT_CLEANUP
/* GNU Mailutils -- a suite of utilities for electronic mail
Copyright (C) 2011 Free Software Foundation, Inc.
GNU Mailutils 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.
GNU Mailutils 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 GNU Mailutils. 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 <mailutils/stream.h>
#include <mailutils/stdstream.h>
#include <mailutils/diag.h>
int
main (int argc, char **argv)
{
mu_stream_t str = mu_strout;
int i;
if (argc == 1)
{
fprintf (stderr, "usage: %s: word|option [word|option...]\n", argv[0]);
fprintf (stderr, "options are: -out, -err, -reset\n");
return 1;
}
mu_set_program_name (argv[0]);
for (i = 1; i < argc; i++)
{
char *arg = argv[i];
if (arg[0] == '-')
{
if (strcmp (arg, "-out") == 0)
str = mu_strout;
else if (strcmp (arg, "-err") == 0)
str = mu_strerr;
else if (strcmp (arg, "-reset") == 0)
{
if (str == mu_strout)
{
mu_stdstream_setup (MU_STDSTREAM_RESET_STROUT);
str = mu_strout;
}
else
{
mu_stdstream_setup (MU_STDSTREAM_RESET_STRERR);
str = mu_strerr;
}
}
else
{
fprintf (stderr, "%s: unrecognized option %s\n", argv[0], arg);
return 1;
}
}
else
mu_stream_printf (str, "%s\n", arg);
}
return 0;
}
......@@ -54,6 +54,11 @@ AT_CLEANUP
AT_INIT
AT_BANNER([Standard streams])
m4_include([strin.at])
m4_include([strout.at])
m4_include([strerr.at])
m4_include([list.at])
m4_include([address.at])
m4_include([wordsplit.at])
......