commit-mailutils
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[SCM] GNU Mailutils branch, master, updated. release-2.2-187-g3fb87f6


From: Sergey Poznyakoff
Subject: [SCM] GNU Mailutils branch, master, updated. release-2.2-187-g3fb87f6
Date: Thu, 11 Nov 2010 21:42:06 +0000

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 <address@hidden>
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 @@
address@hidden This is part of the GNU Mailutils manual.
address@hidden Copyright (C) 2010 Free Software Foundation, Inc.
address@hidden See file mailutils.texi for copying conditions.
address@hidden 
*******************************************************************
+
address@hidden Null stream
address@hidden null stream
address@hidden 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:
+
address@hidden {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:
+
address@hidden @code
address@hidden MU_STREAM_READ
+Stream is opened for reading.
address@hidden MU_STREAM_WRITE
+Stream is opened for writing.
address@hidden 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.
address@hidden deffn
+
+Writing to an instance of null stream and seeking in such streams
+always succeeds.  If the stream was created with the
address@hidden on, the reads from it normally behave as if
+it were connected to an endless source of zero bytes, i.e. each call
+to:
+
address@hidden
+  mu_stream_read (str, buf, size, &n);
address@hidden smallexample
+
address@hidden
+results in filling @var{buf} with @var{size} zeroes.  This is similar
+to reading from the system @file{/dev/zero} address@hidden 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}.
+
address@hidden {ioctl} MU_IOCTL_NULLSTREAM_SET_PATTERN
+Set the @dfn{pattern} for reads.  The argument is a pointer to
address@hidden mu_nullstream_pattern}, defined as:
+
address@hidden
address@hidden
+struct mu_nullstream_pattern
address@hidden
+  char *pattern;   /* Return pattern */          
+  size_t size;     /* Number of bytes in pattern */
address@hidden;
address@hidden group
address@hidden smallexample
+
+The @samp{pattern} member points to @samp{size} bytes of data which
+are returned cyclically at each read.  For example, suppose that
address@hidden is a null stream instance, and consider the following code:
+
address@hidden
+  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);
address@hidden smallexample
+
+Then, after the call to @code{mu_stream_read}, we will have:
+
address@hidden
address@hidden
+n @result{} 16
+buf @result{} "0123456701234567"
address@hidden group
address@hidden smallexample
+
+Similarly, the following code:
+
address@hidden
+  mu_stream_seek (str, 3, MU_SEEK_SET, NULL);
+  mu_stream_read (str, buf, sizeof (buf), &n);
address@hidden smallexample
+
address@hidden
+will yield:
+
address@hidden
address@hidden
+n @result{} 16
+buf @result{} "3456701234567012"
address@hidden group
address@hidden smallexample
+
+The default behavior corresponds to the following initialization:
+
address@hidden
address@hidden
+  pat.pattern = "";
+  pat.size = 1;
+  mu_stream_ioctl (str, MU_IOCTL_NULLSTREAM_SET_PATTERN, &pat);
address@hidden group  
address@hidden 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}:
+
address@hidden
address@hidden
+  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
address@hidden group  
address@hidden smallexample
address@hidden defvr
+
address@hidden {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:
+
address@hidden
+  int class = MU_CTYPE_DIGIT|MU_CTYPE_XLETR;
+  mu_stream_ioctl (str, MU_IOCTL_NULLSTREAM_SET_PATCLASS, &class);
address@hidden smallexample
+
address@hidden
+initializes the read pattern to the following string:
+
address@hidden
+0123456789ABCDEFabcdef
address@hidden smallexample
address@hidden defvr
+
+Two ioctls are provided to control the @dfn{size} of a null stream
+available to seek and read operations.
+
address@hidden {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:
+
address@hidden
address@hidden
+  mu_off_t limit = 32;
+  mu_stream_ioctl (str, MU_IOCTL_NULLSTREAM_SETSIZE, &limit);
address@hidden group  
address@hidden smallexample
address@hidden defvr
+
+Another way to set the null stream size is via the
address@hidden function:
+
address@hidden
+  mu_stream_truncate (str, 32);
address@hidden smallexample
+
+Setting the stream size to @samp{0} causes all subsequent reads from
+that stream to return @samp{EOF}.  The similar effect has the
address@hidden ioctl with the @samp{NULL} argument.
+
address@hidden {ioctl} MU_IOCTL_NULLSTREAM_CLRSIZE
+Cancel the size limitation imposed by a previous
address@hidden ioctl or a call to
address@hidden  Argument must be @samp{NULL}.
address@hidden defvr
+
address@hidden
+* null stream usage::
address@hidden menu
+
address@hidden null stream usage
address@hidden 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}:
+
address@hidden {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:
+
address@hidden @var
address@hidden mime_str
+A stream obtained from the MIME part.
+
address@hidden encoding
+Encoding type, as obtained from the @samp{Content-Transfer-Encoding}
+MIME header.
address@hidden table
+
address@hidden
+mu_off_t
+decoded_size (mu_stream_t mime_str, const char *encoding)
address@hidden
+  int rc;           /* Result code */
+  mu_stream_t fstr  /* Filter stream */
+  mu_stream_stat_buffer stat; /* Statistics buffer */
+  mu_stream_t null; /* Null stream */
address@hidden example
+
+First, create the filter stream for decoding the message part:
address@hidden
+  rc = mu_filter_create (&fstr, mime_str, encoding,
+                         MU_FILTER_DECODE, MU_STREAM_READ);
+  if (rc)
+    abort ();
address@hidden example
+
+Then, create an instance of the null stream which will act
+as a receiver:
+
address@hidden
+  mu_nullstream_create (&null, MU_STREAM_WRITE);
address@hidden 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:
+
address@hidden
+  mu_stream_set_stat (null, MU_STREAM_STAT_MASK (MU_STREAM_STAT_OUT),
+                      stat);
address@hidden 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}:
+
address@hidden
+  rc = mu_stream_copy (null, fstr, 0, NULL);
+  if (rc)
+    abort ();
address@hidden 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}:
+
address@hidden
+  mu_stream_destroy (&null);
+  mu_stream_destroy (&fstr);
+  return stat[MU_STREAM_STAT_OUT];
address@hidden  
address@hidden 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



reply via email to

[Prev in Thread] Current Thread [Next in Thread]