This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "GNU Mailutils".
http://git.savannah.gnu.org/cgit/mailutils.git/commit/?id=3fb87f63f3dc9dbbcf3cecc2a9ef2c85bd007204 The branch, master has been updated via 3fb87f63f3dc9dbbcf3cecc2a9ef2c85bd007204 (commit) from c02201707fd4664252ba0e3fe93d3018ec816c89 (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- commit 3fb87f63f3dc9dbbcf3cecc2a9ef2c85bd007204 Author: Sergey Poznyakoff <g...@gnu.org.ua> Date: Thu Nov 11 23:40:01 2010 +0200 Document null streams * doc/texinfo/nullstream.texi: New file. * mh/mh_init.c (mh_real_install): Use mu_stream_t instead of FILE. * mh/mh_whatnow.c (_whatnow): Likewise. ----------------------------------------------------------------------- Summary of changes: doc/texinfo/nullstream.texi | 279 +++++++++++++++++++++++++++++++++++++++++++ mh/mh_init.c | 30 +++-- mh/mh_whatnow.c | 34 ++++-- 3 files changed, 320 insertions(+), 23 deletions(-) create mode 100644 doc/texinfo/nullstream.texi diff --git a/doc/texinfo/nullstream.texi b/doc/texinfo/nullstream.texi new file mode 100644 index 0000000..a140150 --- /dev/null +++ b/doc/texinfo/nullstream.texi @@ -0,0 +1,279 @@ +...@c This is part of the GNU Mailutils manual. +...@c Copyright (C) 2010 Free Software Foundation, Inc. +...@c See file mailutils.texi for copying conditions. +...@c ******************************************************************* + +...@section Null stream +...@cindex null stream +...@cindex stream, null + +A @dfn{null stream} is similar to the system @file{/dev/null} device. +It is not connected to any particular physical storage. Any data +written to such stream are irrevocably lost. Reading from such a +stream returns fixed data, depending on the mode of the stream. + +An instance of the null stream is created using the following function: + +...@deffn {stream function} int mu_nullstream_create (mu_stream_t *pstr, int mode) +Create an instance of the null stream and return it in the memory +location pointed to by @var{pstr}. The @var{mode} argument specifies +the access mode for this stream. It can be a binary @samp{or} of the +following values: + +...@table @code +...@item MU_STREAM_READ +Stream is opened for reading. +...@item MU_STREAM_WRITE +Stream is opened for writing. +...@end table + +The returned stream is always seekable, so the @code{MU_STREAM_SEEK} +mode is implied. + +Any other bits set in the @var{mode} argument are silently ignored. +...@end deffn + +Writing to an instance of null stream and seeking in such streams +always succeeds. If the stream was created with the +...@code{mu_stream_read} on, the reads from it normally behave as if +it were connected to an endless source of zero bytes, i.e. each call +to: + +...@smallexample + mu_stream_read (str, buf, size, &n); +...@end smallexample + +...@noindent +results in filling @var{buf} with @var{size} zeroes. This is similar +to reading from the system @file{/dev/zero} dev...@footnote{note that +the internal implementation of @dfn{null streams} has nothing to do +with @file{/dev/null}, or @file{/dev/zero}. We refer to these devices +only to illustrate the behavior of @dfn{null streams}.}. + +This is the default behavior when reading. It can be altered using +the following @dfn{ioctls}. + +...@defvr {ioctl} MU_IOCTL_NULLSTREAM_SET_PATTERN +Set the @dfn{pattern} for reads. The argument is a pointer to +...@dfn{struct mu_nullstream_pattern}, defined as: + +...@smallexample +...@group +struct mu_nullstream_pattern +...@{ + char *pattern; /* Return pattern */ + size_t size; /* Number of bytes in pattern */ +...@}; +...@end group +...@end smallexample + +The @samp{pattern} member points to @samp{size} bytes of data which +are returned cyclically at each read. For example, suppose that +...@var{str} is a null stream instance, and consider the following code: + +...@smallexample + struct mu_nullstream_pattern pat; + char buf[16]; + size_t n; + + pat.pattern = "01234567"; + pat.size = 8; + mu_stream_ioctl (str, MU_IOCTL_NULLSTREAM_SET_PATTERN, &pat); + + mu_stream_read (str, buf, sizeof (buf), &n); +...@end smallexample + +Then, after the call to @code{mu_stream_read}, we will have: + +...@smallexample +...@group +n @result{} 16 +buf @result{} "0123456701234567" +...@end group +...@end smallexample + +Similarly, the following code: + +...@smallexample + mu_stream_seek (str, 3, MU_SEEK_SET, NULL); + mu_stream_read (str, buf, sizeof (buf), &n); +...@end smallexample + +...@noindent +will yield: + +...@smallexample +...@group +n @result{} 16 +buf @result{} "3456701234567012" +...@end group +...@end smallexample + +The default behavior corresponds to the following initialization: + +...@smallexample +...@group + pat.pattern = ""; + pat.size = 1; + mu_stream_ioctl (str, MU_IOCTL_NULLSTREAM_SET_PATTERN, &pat); +...@end group +...@end smallexample + +Calling the @samp{MU_IOCTL_NULLSTREAM_SET_PATTERN} with a @samp{NULL} +argument causes all subsequent reads from that stream to return @samp{EOF}: + +...@smallexample +...@group + mu_stream_ioctl (str, MU_IOCTL_NULLSTREAM_SET_PATTERN, NULL); + @dots{} + rc = mu_stream_read (str, buf, sizeof (buf), &n); + + rc @result{} 0 + n @result{} 0 +...@end group +...@end smallexample +...@end defvr + +...@defvr {ioctl} MU_IOCTL_NULLSTREAM_SET_PATCLASS +Set read pattern in terms of @dfn{C character classes} +(@FIXME-pxref{C character classes}). Argument is a pointer +to an integer containing a bitwise @samp{OR} of the desired +character classes from @file{mailutils/cctype.h}. For example, +the following code: + +...@smallexample + int class = MU_CTYPE_DIGIT|MU_CTYPE_XLETR; + mu_stream_ioctl (str, MU_IOCTL_NULLSTREAM_SET_PATCLASS, &class); +...@end smallexample + +...@noindent +initializes the read pattern to the following string: + +...@smallexample +0123456789ABCDEFabcdef +...@end smallexample +...@end defvr + +Two ioctls are provided to control the @dfn{size} of a null stream +available to seek and read operations. + +...@defvr {ioctl} MU_IOCTL_NULLSTREAM_SETSIZE +Limit the addressable size of a null stream. Argument is a pointer +to @samp{mu_off_t} object specifying the new size. The example below +limits the stream size to 32 bytes: + +...@smallexample +...@group + mu_off_t limit = 32; + mu_stream_ioctl (str, MU_IOCTL_NULLSTREAM_SETSIZE, &limit); +...@end group +...@end smallexample +...@end defvr + +Another way to set the null stream size is via the +...@samp{mu_stream_truncate} function: + +...@smallexample + mu_stream_truncate (str, 32); +...@end smallexample + +Setting the stream size to @samp{0} causes all subsequent reads from +that stream to return @samp{EOF}. The similar effect has the +...@samp{mu_ioctl_nullstream_set_pattern} ioctl with the @samp{NULL} argument. + +...@defvr {ioctl} MU_IOCTL_NULLSTREAM_CLRSIZE +Cancel the size limitation imposed by a previous +...@samp{mu_ioctl_nullstream_setsize} ioctl or a call to +...@samp{mu_stream_truncate}. Argument must be @samp{NULL}. +...@end defvr + +...@menu +* null stream usage:: +...@end menu + +...@node null stream usage +...@subsection null stream usage + +Due to their nature, null streams are not among the most used stream +flavors. They are mainly useful for testing or measuring purposes. + +The @command{mhn} utility from GNU Mailutils MH suite gives a nice +example of using a null stream instance to compute the actual +(decoded) size of a part of a MIME message. In the example below +we present a simplified version of this code. It defines the +function @samp{decoded_size}: + +...@deffn {example function} mu_off_t decoded_size (mu_stream_t mime_str, @ + const char *encoding) +Return the size of the decoded input strem. Arguments are: + +...@table @var +...@item mime_str +A stream obtained from the MIME part. + +...@item encoding +Encoding type, as obtained from the @samp{Content-Transfer-Encoding} +MIME header. +...@end table + +...@example +mu_off_t +decoded_size (mu_stream_t mime_str, const char *encoding) +...@{ + int rc; /* Result code */ + mu_stream_t fstr /* Filter stream */ + mu_stream_stat_buffer stat; /* Statistics buffer */ + mu_stream_t null; /* Null stream */ +...@end example + +First, create the filter stream for decoding the message part: +...@example + rc = mu_filter_create (&fstr, mime_str, encoding, + MU_FILTER_DECODE, MU_STREAM_READ); + if (rc) + abort (); +...@end example + +Then, create an instance of the null stream which will act +as a receiver: + +...@example + mu_nullstream_create (&null, MU_STREAM_WRITE); +...@end example + +The data will be read from @var{fstr} and written to @var{null}. +Number of bytes written will give the decoded size of the message. +To get this number, attach the statistics buffer to the null +stream: + +...@example + mu_stream_set_stat (null, MU_STREAM_STAT_MASK (MU_STREAM_STAT_OUT), + stat); +...@end example + +The second argument instructs the stream to keep track of the +bytes output (i.e. written) to the stream. + +Now, copy the entire contents of @var{fstr} to @var{null}: + +...@example + rc = mu_stream_copy (null, fstr, 0, NULL); + if (rc) + abort (); +...@end example + +When done, destroy both streams (they are not needed any more), and +return the value of @samp{MU_STREAM_STAT_OUT} element from @var{stat}: + +...@example + mu_stream_destroy (&null); + mu_stream_destroy (&fstr); + return stat[MU_STREAM_STAT_OUT]; +...@} +...@end example + + + + + + diff --git a/mh/mh_init.c b/mh/mh_init.c index 016bf54..7b2098f 100644 --- a/mh/mh_init.c +++ b/mh/mh_init.c @@ -707,14 +707,21 @@ mh_real_install (char *name, int automode) char *home = mu_get_homedir (); char *mhdir; char *ctx; + mu_stream_t in; + int rc; FILE *fp; - + + rc = mu_stdio_stream_create (&in, MU_STDIN_FD, 0); + if (rc) + { + mu_error (_("cannot create input stream: %s"), mu_strerror (rc)); + exit (1); + } + mhdir = mh_safe_make_file_name (home, "Mail"); if (!automode) { - size_t n = 0; - /* TRANSLATORS: This is a question and will be followed by question mark on output. */ if (mh_getyn_interactive (_("Do you need help"))) @@ -725,7 +732,8 @@ mh_real_install (char *name, int automode) if (!mh_getyn_interactive (_("Do you want the standard MH path \"%s\""), mhdir)) { int local; - char *p; + char *p, *buf = NULL; + size_t size = 0; /* TRANSLATORS: This is a question and will be followed by question mark on output. */ @@ -734,16 +742,12 @@ mh_real_install (char *name, int automode) printf (_("What is the path? ")); else printf (_("What is the full path? ")); - if (getline (&p, &n, stdin) <= 0) - exit (1); - - n = strlen (p); - if (n == 0) + if (mu_stream_getline (in, &buf, &size, NULL)) exit (1); - - if (p[n-1] == '\n') - p[n-1] = 0; - + p = mu_str_stripws (buf); + if (p > buf) + memmove (buf, p, strlen (p) + 1); + free (mhdir); if (local) { diff --git a/mh/mh_whatnow.c b/mh/mh_whatnow.c index 6582fd8..9ba2195 100644 --- a/mh/mh_whatnow.c +++ b/mh/mh_whatnow.c @@ -323,37 +323,51 @@ static int _whatnow (struct mh_whatnow_env *wh, struct action_tab *tab) { int rc, status = 0; + mu_stream_t in; + char *line = NULL; + size_t size = 0; + struct mu_wordsplit ws; + int wsflags = MU_WRDSF_DEFFLAGS|MU_WRDSF_COMMENT; + + rc = mu_stdio_stream_create (&in, MU_STDIN_FD, 0); + if (rc) + { + mu_error (_("cannot create input stream: %s"), mu_strerror (rc)); + exit (1); + } do { - char *line = NULL; - size_t size = 0; - struct mu_wordsplit ws; handler_fp fun; printf ("%s ", wh->prompt); - getline (&line, &size, stdin); - if (!line) - continue; + fflush (stdout); + status = mu_stream_getline (in, &line, &size, NULL); + if (rc) + { + mu_error (_("cannot read input stream: %s"), mu_strerror (rc)); + break; + } ws.ws_comment = "#"; - rc = mu_wordsplit (line, &ws, MU_WRDSF_DEFFLAGS|MU_WRDSF_COMMENT); - free (line); + rc = mu_wordsplit (line, &ws, wsflags); if (rc) { mu_error (_("cannot split line `%s': %s"), line, mu_wordsplit_strerror (&ws)); break; } - + wsflags |= MU_WRDSF_REUSE; fun = func (tab, ws.ws_wordv[0]); if (fun) rc = fun (wh, ws.ws_wordc, ws.ws_wordv, &status); else rc = 0; - mu_wordsplit_free (&ws); } while (rc == 0); + if (wsflags & MU_WRDSF_REUSE) + mu_wordsplit_free (&ws); + free (line); return status; } hooks/post-receive -- GNU Mailutils _______________________________________________ Commit-mailutils mailing list Commit-mailutils@gnu.org http://lists.gnu.org/mailman/listinfo/commit-mailutils