@code{#include <mailutils/stream.h>}

@deftypefun int stream_create (stream_t *@var{pstream}, int @var{flags}, void *@var{owner})
@table @code
@item MU_STREAM_READ
@findex MU_STREAM_READ
The stream is open read only.
@item MU_STREAM_WRITE
@findex MU_STREAM_WRITE
The stream is open write only.
@item MU_STREAM_RDWR
@findex MU_STREAM_RDWR
The stream is open read and write.
@item MU_STREAM_APPEND
@findex MU_STREAM_APPEND
The stream is open in append mode for writing.
@item MU_STREAM_CREAT
@findex MU_STREAM_CREAT
The stream is created.
@item MU_STREAM_NONBLOCK
@findex MU_STREAM_NONBLOCK
The stream is set non blocking.
@item MU_STREAM_NO_CHECK
@findex MU_STREAM_NO_CHECK
Stream is destroyed without checking for the owner.
@end table
@end deftypefun

@deftypefun void stream_destroy (stream_t *@var{pstream}, void *@var{owner})
@end deftypefun

@deftypefun int stream_open (stream_t @var{stream}, const char *@var{name}, int@var{port}, int @var{flag})
@end deftypefun

@deftypefun int stream_close (stream_t @var{stream})
@end deftypefun

@deftypefun int stream_get_fd (stream_t @var{stream}, int *@var{pfd})
@end deftypefun

@deftypefun int stream_read (stream_t @var{stream}, char *@var{buffer}, size_t @var{buflen}, off_t @var{offset}, size_t *@var{pwriten})
@end deftypefun

@deftypefun int stream_readline (stream_t @var{stream}, char *@var{buffer}, size_t @var{buflen}, off_t @var{offset}, size_t *@var{pwriten})
@end deftypefun

@deftypefun int stream_size (stream_t @var{stream}, off_t *@var{psize})
@end deftypefun

@deftypefun int stream_truncate (stream_t @var{stream}, off_t @var{size})
@end deftypefun

@deftypefun int stream_write (stream_t @var{stream}, const char *@var{buffer}, size_t @var{buflen}, off_t @var{offset}, size_t *@var{pwriten})
@end deftypefun

@deftypefun int stream_flush (stream_t @var{stream})
@end deftypefun

@deftypefun int stream_get_flags (stream_t @var{stream}, int *@var{pflags})
@end deftypefun

@deftypefun int stream_get_state (stream_t @var{stream}, int *@var{pstate})
@table @code
@item MU_STREAM_STATE_OPEN
Last action was @code{stream_open}.
@item MU_STREAM_STATE_READ
Last action was @code{stream_read} or @code{stream_readline}.
@item MU_STREAM_STATE_WRITE
Last action was @code{stream_write}.
@item MU_STREAM_STATE_CLOSE
Last action was @code{stream_close}.
@end table
@end deftypefun

@deftypefun int file_stream_create (stream_t *@var{pstream})
@end deftypefun

@deftypefun int mapfile_stream_create (stream_t *@var{pstream})
@end deftypefun

@deftypefun int encoder_stream_create (stream_t *@var{pstream}, stream_t @var{iostream}, const char *@var{encoding})
@end deftypefun

@deftypefun int decoder_stream_create (stream_t *@var{pstream}, stream_t @var{iostream}, const char *@var{encoding})
@end deftypefun

@deftypefun int tcp_stream_create (stream_t *@var{pstream})
@end deftypefun


An example using @code{tcp_stream_create} to make a simple web client:
@example
#include <stdlib.h>
#include <stdio.h>
#include <errno.h>
#include <string.h>
#include <unistd.h>
#include <sys/select.h>

#include <mailutils/io.h>

const char *wbuf = "GET / HTTP/1.0\r\n\r\n";
char rbuf[1024];

int
main(int argc, char **argv)
@{
  int ret, off = 0, fd;
  stream_t stream;
  size_t nb;
  fd_set fds;

  argc = argc, argv = argv;

  ret = tcp_stream_create (&stream);
  if (ret != 0)
    @{
       fprintf (stderr, "tcp_stream_create: %s\n",
                mailutils_error(ret));
       exit (EXIT_FAILURE);
    @}

connect_again:
  ret = stream_open (stream, "www.netscape.com", 80,
                     MU_STREAM_NONBLOCK);
  if (ret != 0)
    @{
       if (ret == MU_ERROR_EAGAIN)
         @{
             ret = stream_get_fd(stream, &fd);
             if (ret != 0)
               @{
                   fprintf (stderr, "stream_get_fd: %s\n",
                            mailutils_error(ret));
                   exit (EXIT_FAILURE);
               @}
               FD_ZERO (&fds);
               FD_SET (fd, &fds);
               select (fd+1, NULL, &fds, NULL, NULL);
               goto connect_again;
          @}
          fprintf (stderr, "stream_open: %s\n", mailutils_error (ret));
          exit (EXIT_FAILURE);
    @}

    ret = stream_get_fd (stream, &fd);
    if (ret != 0)
      @{
         fprintf(stderr, "stream_get_fd: %s\n", strerror(ret));
         exit (EXIT_FAILURE);
      @}

write_again:
    ret = stream_write (stream, wbuf + off, strlen (wbuf), 0, &nb);
    if (ret != 0 )
      @{
         if (ret == EAGAIN)
           @{
              FD_ZERO (&fds);
              FD_SET (fd, &fds);
              select (fd + 1, NULL, &fds, NULL, NULL);
              off += nb;
              goto write_again;
           @}
         fprintf (stderr, "stream_write: %s\n", strerror(ret));
         exit (EXIT_FAILURE)
      @}

      if (nb != strlen (wbuf))
        @{
           fprintf(stderr, "stream_write: %s\n", "nb != wbuf length");
           exit (EXIT_FAILURE);
        @}

      do
        @{
read_again:
           ret = stream_read (stream, rbuf, sizeof (rbuf), 0, &nb);
           if (ret != 0)
             @{
                if (ret == EAGAIN)
                  @{
                     FD_ZERO (&fds);
                     FD_SET (fd, &fds);
                     select (fd + 1, &fds, NULL, NULL, NULL);
                     goto read_again;
                   @}
                 fprintf (stderr, "stream_read: %s\n", strerror(ret));
                 exit(EXIT_FAILURE);
              @}
              write (2, rbuf, nb);
         @} while (nb);

         ret = stream_close (stream);
         if (ret!= 0)
           @{
              fprintf (stderr, "stream_close: %s\n", strerror(ret));
              exit (EXIT_FAILURE);
           @}

         stream_destroy (&stream, NULL);
         exit (EXIT_SUCCESS);
@}
@end example
