示例#1
0
static int
_iostream_close (struct _mu_stream *str)
{
  struct _mu_iostream *sp = (struct _mu_iostream *)str;
  mu_stream_close (sp->transport[_MU_STREAM_INPUT]);
  mu_stream_close (sp->transport[_MU_STREAM_OUTPUT]);
  return 0;
}
示例#2
0
int
main (int argc, char * argv [])
{
  int c;
  mu_stream_t in, out;
  int reread_option = 0;
  mu_off_t reread_off;
  int skip_option = 0;
  mu_off_t skip_off;
  
  while ((c = getopt (argc, argv, "hs:r:")) != EOF)
    switch (c)
      {
      case 'r':
	reread_option = 1;
	reread_off = strtoul (optarg, NULL, 10);
	break;

      case 's':
	skip_option = 1;
	skip_off = strtoul (optarg, NULL, 10);
	break;

      case 'h':
	printf ("usage: cat [-s off]\n");
	exit (0);

      default:
	exit (1);
      }
	

  MU_ASSERT (mu_stdio_stream_create (&in, MU_STDIN_FD, MU_STREAM_SEEK));
  MU_ASSERT (mu_stdio_stream_create (&out, MU_STDOUT_FD, 0));

  if (skip_option)
    {
      mu_stream_printf (out, "skipping to %lu:\n",
			(unsigned long) skip_off);
      MU_ASSERT (mu_stream_seek (in, skip_off, MU_SEEK_SET, NULL));
    }
  
  MU_ASSERT (mu_stream_copy (out, in, 0, NULL));

  if (reread_option)
    {
      mu_stream_printf (out, "rereading from %lu:\n",
			(unsigned long) reread_off);
      MU_ASSERT (mu_stream_seek (in, reread_off, MU_SEEK_SET, NULL));
      MU_ASSERT (mu_stream_copy (out, in, 0, NULL));
    }
  
  mu_stream_close (in);
  mu_stream_destroy (&in);
  mu_stream_close (out);
  mu_stream_destroy (&out);
  return 0;
}
示例#3
0
int
mu_message_save_attachment (mu_message_t msg, const char *filename,
			    mu_mime_io_buffer_t info)
{
  mu_stream_t istream;
  int ret;
  mu_header_t hdr;
  const char *fname = NULL;
  char *partname = NULL;

  if (msg == NULL)
    return EINVAL;

  if ((ret = _attachment_setup (&info, msg, &istream)) != 0)
    return ret;

  if (ret == 0 && (ret = mu_message_get_header (msg, &hdr)) == 0)
    {
      if (filename == NULL)
	{
	  ret = mu_message_aget_decoded_attachment_name (msg, info->charset,
							 &partname, NULL);
	  if (partname)
	    fname = partname;
	}
      else
	fname = filename;
      if (fname
	  && (ret = mu_file_stream_create (&info->fstream, fname,
				     MU_STREAM_WRITE | MU_STREAM_CREAT)) == 0)
	{
	  const char *content_encoding;

	  if (mu_header_sget_value (hdr, MU_HEADER_CONTENT_TRANSFER_ENCODING,
				    &content_encoding))
	    content_encoding = "7bit";
	  ret = mu_filter_create (&info->stream, istream, content_encoding,
				  MU_FILTER_DECODE,
				  MU_STREAM_READ);
	}
    }
  if (info->stream && istream)
    ret = mu_stream_copy (info->fstream, info->stream, 0, NULL);

  if (ret != EAGAIN && info)
    {
      mu_stream_close (info->fstream);
      mu_stream_destroy (&info->stream);
      mu_stream_destroy (&info->fstream);
    }

  mu_stream_destroy (&istream);
  _attachment_free (info, ret); /* FIXME: or 0? */
  
  /* Free fname if we allocated it. */
  if (partname)
    free (partname);

  return ret;
}
示例#4
0
/* Open the connection to the server. */
int
mu_nntp_connect (mu_nntp_t nntp)
{
  int status;

  /* Sanity checks.  */
  if (nntp == NULL)
    return EINVAL;

  /* A networking stack.  */
  if (nntp->carrier == NULL)
    return EINVAL;

  /* Enter the nntp state machine, and boogy  */
  switch (nntp->state)
    {
    default:
      /* FALLTHROUGH */
      /* If nntp was in an error state going through here should clear it.  */

    case MU_NNTP_NO_STATE:
      status = mu_nntp_disconnect (nntp);
      MU_NNTP_CHECK_EAGAIN (nntp, status);
      nntp->state = MU_NNTP_CONNECT;

    case MU_NNTP_CONNECT:
      /* Establish the connection.  */
      status = mu_stream_open (nntp->carrier);
      MU_NNTP_CHECK_EAGAIN (nntp, status);
      nntp->acknowledge = 0;
      nntp->state = MU_NNTP_GREETINGS;

    case MU_NNTP_GREETINGS:
      /* Get the greetings.  */
      {
	size_t len = 0;
	int code;
	status = mu_nntp_response (nntp, NULL, 0, &len);
	MU_NNTP_CHECK_EAGAIN (nntp, status);
	mu_nntp_debug_ack (nntp);
	/* 200 Service available, posting allowed */
	/* 201 Servie available, posting prohibited */
	code = mu_nntp_response_code(nntp);
	if (code != MU_NNTP_RESP_CODE_POSTING_ALLOWED && code != MU_NNTP_RESP_CODE_POSTING_PROHIBITED)
	  {
	    mu_stream_close (nntp->carrier);
	    nntp->state = MU_NNTP_NO_STATE;
	    return EACCES;
	  }
	nntp->state = MU_NNTP_NO_STATE;
      }
    } /* End AUTHORISATION state. */

  return status;
}
示例#5
0
static PyObject *
api_stream_close (PyObject *self, PyObject *args)
{
  int status;
  PyStream *py_stm;

  if (!PyArg_ParseTuple (args, "O!", &PyStreamType, &py_stm))
    return NULL;

  status = mu_stream_close (py_stm->stm);
  return _ro (PyInt_FromLong (status));
}
示例#6
0
文件: mbox.c 项目: ssvlab/esbmc-gpu
static int
mbox_close (mu_mailbox_t mailbox)
{
  mbox_data_t mud = mailbox->data;
  size_t i; 

  if (mud == NULL)
    return EINVAL;

  MU_DEBUG1 (mailbox->debug, MU_DEBUG_TRACE1,  "mbox_close (%s)\n", mud->name);

  /* Make sure that we do not hold any file locking.  */
  mu_locker_unlock (mailbox->locker);

  /* Alain: I'm not sure on the right approach especially if the client is
     working in disconnected mode, where it can mu_mailbox_close/mu_mailbox_open
     for each request, maybe we should keep them for a while.

     Sergey: No, it actually breaks reopening the mailbox. We should make
     sure that the sequence mu_mailbox_open();mu_mailbox_close() will catch all
     the changes that might have been done to the mailbox */
  
  mu_monitor_wrlock (mailbox->monitor);
  /* Before closing we need to remove all the messages
     - to reclaim the memory
     - to prepare for another scan.  */
  for (i = 0; i < mud->umessages_count; i++)
    {
      mbox_message_t mum = mud->umessages[i];
      /* Destroy the attach messages.  */
      if (mum)
	{
	  mu_message_destroy (&(mum->message), mum);
	  free (mum);
	}
    }
  if (mud->umessages)
    free (mud->umessages);
  mud->umessages = NULL;
  mud->messages_count = mud->umessages_count = 0;
  mud->size = 0;
  mud->uidvalidity = 0;
  mud->uidnext = 0;
  mu_monitor_unlock (mailbox->monitor);

  return mu_stream_close (mailbox->stream);
}
示例#7
0
static int
mu_port_close (SCM port)
{
  struct mu_port *mp = MU_PORT (port);
  scm_port *pt = SCM_PTAB_ENTRY (port);

  mu_port_flush (port);
  mu_stream_close (mp->stream);
  SCM_SETSTREAM (port, NULL);
		
  if (pt->read_buf != &pt->shortbuf)
    free (pt->read_buf);
  if (pt->write_buf != &pt->shortbuf)
    free (pt->write_buf);
  free (mp);
  return 0;
}
示例#8
0
void
mh_comp_draft (const char *formfile, const char *draftfile)
{
  char *s;

  if (mh_find_file (formfile, &s) == 0)
    {
      if (mh_file_copy (s, draftfile))
	exit (1);
      free (s);
    }
  else
    {
      /* I doubt if we need that: */
      int rc;
      mu_stream_t stream;
      
      if ((rc = mu_file_stream_create (&stream,
				       draftfile,
				       MU_STREAM_WRITE|MU_STREAM_CREAT)))
	{
	  mu_error (_("cannot open output file \"%s\": %s"),
		    draftfile, mu_strerror (rc));
	  exit (1);
	}
      
      rc = mu_stream_write (stream, 
			    default_format_str,
			    strlen (default_format_str), NULL);
      mu_stream_close (stream);
      mu_stream_destroy (&stream);
      
      if (rc)
	{
	  mu_error (_("error writing to \"%s\": %s"),
		    draftfile, mu_strerror (rc));
	  exit (1);
	}
    }
}
示例#9
0
static int
_iostream_open (struct _mu_stream *str)
{
  struct _mu_iostream *sp = (struct _mu_iostream *)str;
  int rc;
  rc = mu_stream_open (sp->transport[_MU_STREAM_INPUT]);
  if (rc)
    {
      sp->last_err_str = _MU_STREAM_INPUT;
      return rc;
    }
  if (sp->transport[_MU_STREAM_INPUT] != sp->transport[_MU_STREAM_OUTPUT])
    {
      rc = mu_stream_open (sp->transport[_MU_STREAM_OUTPUT]);
      if (rc)
	{
	  sp->last_err_str = _MU_STREAM_OUTPUT;
	  mu_stream_close (sp->transport[_MU_STREAM_INPUT]);
	}
    }
  return rc;
}
示例#10
0
int
main (int argc, char * argv [])
{
  mu_stream_t in, out, sock;
  pid_t pid;
  int status, c;

  while ((c = getopt (argc, argv, "v")) != EOF)
    switch (c)
      {
      case 'v':
	verbose++;
	break;

      case 'h':
	printf ("usage: musocio file\n");
	return 0;

      default:
	return 1;
      }

  argc -= optind;
  argv += optind;
  
  if (argc != 2)
    {
      mu_error ("usage: musocio file");
      return 1;
    }

  MU_ASSERT (mu_stdio_stream_create (&in, MU_STDIN_FD, 0));
  mu_stream_set_buffer (in, mu_buffer_line, 0);
  MU_ASSERT (mu_stdio_stream_create (&out, MU_STDOUT_FD, 0));
  mu_stream_set_buffer (out, mu_buffer_line, 0);
  MU_ASSERT (mu_socket_stream_create (&sock, argv[1], MU_STREAM_RDWR));
  mu_stream_set_buffer (sock, mu_buffer_line, 0);
  
  pid = fork ();
  if (pid == -1)
    {
      mu_error ("fork failed: %s", mu_strerror (errno));
      return 1;
    }

  if (pid == 0)
    {
      mu_stream_close (in);
      mu_stream_destroy (&in);
      ioloop ("reader", sock, out);
      exit (0);
    }

  ioloop ("writer", in, sock);

  mu_stream_close (in);
  mu_stream_destroy (&in);

  mu_stream_shutdown (sock, MU_STREAM_WRITE);
  waitpid (pid, &status, 0);

  mu_stream_close (sock);
  mu_stream_destroy (&sock);
  
  mu_stream_close (out);
  mu_stream_destroy (&out);
  return 0;
}
示例#11
0
int
main (int argc, char **argv)
{
  int i;
  char *host = NULL;
  char *infile = NULL;
  char *port = NULL;
  int tls = 0;
  int raw = 1;
  int flags = 0;
  mu_stream_t stream;
  mu_smtp_t smtp;
  mu_stream_t instr;
  char *from = NULL;
  mu_list_t rcpt_list = NULL;
  mu_list_t meth_list = NULL;
  mu_list_t skiphdr_list = NULL;
  struct mu_sockaddr *sa;
  struct mu_sockaddr_hints hints;
  
  mu_set_program_name (argv[0]);
  mu_stdstream_setup (MU_STDSTREAM_RESET_NONE);
  
  if (argc < 2)
    usage ();

  memset (&hints, 0, sizeof (hints)); 
  hints.flags = MU_AH_DETECT_FAMILY;
  hints.port = 25;
  hints.protocol = IPPROTO_TCP;
  hints.socktype = SOCK_STREAM;

  MU_ASSERT (mu_smtp_create (&smtp));

  for (i = 1; i < argc; i++)
    {
      if (strncmp (argv[i], "port=", 5) == 0)
	port = argv[i] + 5;
      else if (strncmp (argv[i], "family=", 7) == 0)
	{
	  hints.flags &= ~MU_AH_DETECT_FAMILY;
	  switch (argv[i][7])
	    {
	    case '4':
	      hints.family = AF_INET;
	      break;
	    case '6':
	      hints.family = AF_INET6;
	      break;
	    default:
	      mu_error ("invalid family name: %s", argv[i]+7);
	      exit (1);
	    }
	}
      else if (strncmp (argv[i], "trace=", 6) == 0)
	{
	  char *arg = argv[i] + 6;

	  if (mu_isdigit (arg[0]))
	    mu_smtp_trace (smtp, atoi (argv[i] + 6) ?
			   MU_SMTP_TRACE_SET : MU_SMTP_TRACE_CLR);
	  else
	    {
	      mu_smtp_trace (smtp, MU_SMTP_TRACE_SET);
	      if (strcmp (arg, "secure") == 0)
		mu_smtp_trace_mask (smtp, MU_SMTP_TRACE_SET,
				    MU_XSCRIPT_SECURE);
	      else if (strcmp (arg, "payload") == 0)
		mu_smtp_trace_mask (smtp, MU_SMTP_TRACE_SET,
				    MU_XSCRIPT_PAYLOAD);
	    }
	}
      else if (strncmp (argv[i], "tls=", 4) == 0)
	tls = atoi (argv[i] + 4);
      else if (strncmp (argv[i], "domain=", 7) == 0)
	MU_ASSERT (mu_smtp_set_param (smtp, MU_SMTP_PARAM_DOMAIN,
				      argv[i] + 7));
      else if (strncmp (argv[i], "user="******"pass="******"service=", 8) == 0)
	MU_ASSERT (mu_smtp_set_param (smtp, MU_SMTP_PARAM_SERVICE,
				      argv[i] + 8));
      else if (strncmp (argv[i], "realm=", 6) == 0)
	MU_ASSERT (mu_smtp_set_param (smtp, MU_SMTP_PARAM_REALM,
				      argv[i] + 6));
      else if (strncmp (argv[i], "host=", 5) == 0)
	MU_ASSERT (mu_smtp_set_param (smtp, MU_SMTP_PARAM_HOST,
				      argv[i] + 5));
      else if (strncmp (argv[i], "url=", 4) == 0)
	MU_ASSERT (mu_smtp_set_param (smtp, MU_SMTP_PARAM_URL,
				      argv[i] + 4));
      else if (strncmp (argv[i], "input=", 6) == 0)
	infile = argv[i] + 6;
      else if (strncmp (argv[i], "raw=", 4) == 0)
	raw = atoi (argv[i] + 4);
      else if (strncmp (argv[i], "rcpt=", 5) == 0)
	{
	  if (!rcpt_list)
	    MU_ASSERT (mu_list_create (&rcpt_list));
	  MU_ASSERT (mu_list_append (rcpt_list, argv[i] + 5));
	}
      else if (strncmp (argv[i], "from=", 5) == 0)
	from = argv[i] + 5;
      else if (strncmp (argv[i], "auth=", 5) == 0)
	update_list (&meth_list, argv[i] + 5);
      else if (strncmp (argv[i], "skiphdr=", 8) == 0)
	{
	  update_list (&skiphdr_list, argv[i] + 8);
	  raw = 0;
	}
      else if (host)
	{
	  mu_error ("server name already given: %s, new name %s?",
		    host, argv[i]);
	  exit (1);
	}
      else
	host = argv[i];
    }

  if (!host)
    usage ();

  if (!raw)
    flags = MU_STREAM_SEEK;
  if (infile)
    MU_ASSERT (mu_file_stream_create (&instr, infile, MU_STREAM_READ|flags));
  else
    MU_ASSERT (mu_stdio_stream_create (&instr, MU_STDIN_FD, flags));
  
  host = argv[1];

  MU_ASSERT (mu_sockaddr_from_node (&sa, host, port, &hints));

  MU_ASSERT (mu_tcp_stream_create_from_sa (&stream, sa, NULL, MU_STREAM_RDWR));
  
  mu_smtp_set_carrier (smtp, stream);
  mu_stream_unref (stream);
  
  if (!from)
    {
      from = getenv ("USER");
      if (!from)
	{
	  mu_error ("cannot determine sender name");
	  exit (1);
	}
    }

  if (raw && !rcpt_list)
    {
      mu_error ("no recipients");
      exit (1);
    }
  
  MU_ASSERT (mu_smtp_open (smtp));
  MU_ASSERT (mu_smtp_ehlo (smtp));

  if (tls && mu_smtp_capa_test (smtp, "STARTTLS", NULL) == 0)
    {
      MU_ASSERT (mu_smtp_starttls (smtp));
      MU_ASSERT (mu_smtp_ehlo (smtp));
    }

  if (meth_list)
    {
      int status;
      
      MU_ASSERT (mu_smtp_add_auth_mech_list (smtp, meth_list));
      status = mu_smtp_auth (smtp);
      switch (status)
	{
	case 0:
	  MU_ASSERT (mu_smtp_ehlo (smtp));
	  break;
	  
	case ENOSYS:
	case MU_ERR_NOENT:
	  /* Ok, skip it */
	  break;

	default:
	  mu_error ("authentication failed: %s", mu_strerror (status));
	  exit (1);
	}
    }
  
  MU_ASSERT (mu_smtp_mail_basic (smtp, from, NULL));
  mu_list_foreach (rcpt_list, send_rcpt_command, smtp);
  
  if (raw)
    {
      /* Raw sending mode: send from the stream directly */
      MU_ASSERT (mu_smtp_send_stream (smtp, instr));
    }
  else
    {
      /* Message (standard) sending mode: send a MU message. */

      mu_message_t msg;
      mu_stream_t ostr, bstr;
      mu_header_t hdr;
      mu_iterator_t itr;
      mu_body_t body;

      if (skiphdr_list)
	mu_list_set_comparator (skiphdr_list, headercmp);
      
      MU_ASSERT (mu_stream_to_message (instr, &msg));
      mu_stream_unref (instr);
      MU_ASSERT (mu_smtp_data (smtp, &ostr));
      MU_ASSERT (mu_message_get_header (msg, &hdr));
      MU_ASSERT (mu_header_get_iterator (hdr, &itr));
      for (mu_iterator_first (itr); !mu_iterator_is_done (itr);
	   mu_iterator_next (itr))
	{
	  const char *name;
	  void *value;

	  mu_iterator_current_kv (itr, (void*) &name, &value);
	  if (mu_list_locate (skiphdr_list, (void*) name, NULL) == 0)
	    continue;

	  mu_stream_printf (ostr, "%s: %s\n", name, (char*)value);
	}
      mu_iterator_destroy (&itr);
      MU_ASSERT (mu_stream_write (ostr, "\n", 1, NULL));
      
      MU_ASSERT (mu_message_get_body (msg, &body));
      MU_ASSERT (mu_body_get_streamref (body, &bstr));
      MU_ASSERT (mu_stream_copy (ostr, bstr, 0, NULL));
      mu_stream_destroy (&bstr);
      mu_stream_close (ostr);
      mu_stream_destroy (&ostr);
    }
  MU_ASSERT (mu_smtp_dot (smtp));
  MU_ASSERT (mu_smtp_quit (smtp));
  
  mu_smtp_destroy (&smtp);
  mu_stream_close (instr);
  mu_stream_destroy (&instr);
  return 0;
}
示例#12
0
static int
_streamref_close (struct _mu_stream *str)
{
  struct _mu_streamref *sp = (struct _mu_streamref *)str;
  return streamref_return (sp, mu_stream_close (sp->transport));
}
示例#13
0
/* Open the connection to the server. The server sends an affirmative greeting
   that may contain a timestamp for APOP.  */
int
mu_pop3_connect (mu_pop3_t pop3)
{
  int status;

  /* Sanity checks.  */
  if (pop3 == NULL)
    return EINVAL;

  /* A networking stack.  */
  if (pop3->carrier == NULL)
    return EINVAL;

  /* Enter the pop state machine, and boogy: AUTHORISATION State.  */
  switch (pop3->state)
    {
    default:
      /* FALLTHROUGH */
      /* If pop3 was in an error state going through here should clear it.  */

    case MU_POP3_NO_STATE:
      /* If the stream was previoulsy open this is sudden death:
         for many pop servers, it is important to let them time to remove any locks or move
         the .user.pop files.  This happen when we do close() and immediately open().
         For example, the user does not want to read the entire file, and wants to start
	 to read a new message, closing the connection and immediately
	 contacting the server again, and he'll end up having
	 "-ERR Mail Lock busy" or something similar. To prevent this race
	 condition we sleep 2 seconds.  You can see this behaviour in an
	 environment where QPopper(Qualcomm POP3 server) is use and the user as a big mailbox. */
      status = mu_pop3_disconnect (pop3);
      if (status != 0)
        mu_pop3_sleep (2);
      pop3->state = MU_POP3_CONNECT;

    case MU_POP3_CONNECT:
      /* Establish the connection.  */
      status = mu_stream_open (pop3->carrier);
      MU_POP3_CHECK_EAGAIN (pop3, status);
      pop3->acknowledge = 0;
      pop3->state = MU_POP3_GREETINGS;

    case MU_POP3_GREETINGS:
      /* Get the greetings.  */
      {
	size_t len = 0;
	char *right, *left;
	status = mu_pop3_response (pop3, NULL, 0, &len);
	MU_POP3_CHECK_EAGAIN (pop3, status);
	mu_pop3_debug_ack (pop3);
	if (mu_c_strncasecmp (pop3->ack.buf, "+OK", 3) != 0)
	  {
	    mu_stream_close (pop3->carrier);
	    pop3->state = MU_POP3_NO_STATE;
	    return EACCES;
	  }

	/* Get the timestamp.  */
	right = memchr (pop3->ack.buf, '<', len);
	if (right)
	  {
	    len = len - (right - pop3->ack.buf);
	    left = memchr (right, '>', len);
	    if (left)
	      {
		len = left - right + 1;
		pop3->timestamp = calloc (len + 1, 1);
		if (pop3->timestamp == NULL)
		  {
		    mu_stream_close (pop3->carrier);
		    MU_POP3_CHECK_ERROR (pop3, ENOMEM);
		  }
		memcpy (pop3->timestamp, right, len);
	      }
	  }
	pop3->state = MU_POP3_NO_STATE;
      }
    } /* End AUTHORISATION state. */

  return status;
}
示例#14
0
int
main (int argc, char * argv [])
{
  mu_stream_t in, out, flt;
  int i;
  int mode = MU_FILTER_ENCODE;
  int flags = MU_STREAM_READ;
  char *fltname;
  mu_off_t shift = 0;
  int newline_option = 0;
  size_t bufsize = 0;
  
  if (argc == 1)
    usage (NULL);
  if (argc < 4)
    usage ("not enough arguments");
  
  fltname = argv[1];

  if (strcmp (argv[2], "encode") == 0)
    mode = MU_FILTER_ENCODE;
  else if (strcmp (argv[2], "decode") == 0)
    mode = MU_FILTER_DECODE;
  else
    usage ("2nd arg is wrong");

  if (strcmp (argv[3], "read") == 0)
    flags = MU_STREAM_READ;
  else if (strcmp (argv[3], "write") == 0)
    flags = MU_STREAM_WRITE;
  else
    usage ("3rd arg is wrong");

  for (i = 4; i < argc; i++)
    {
      if (strncmp (argv[i], "shift=", 6) == 0)
	shift = strtoul (argv[i] + 6, NULL, 0);
      else if (strncmp (argv[i], "bufsize=", 8) == 0)
	bufsize = strtoul (argv[i] + 8, NULL, 0);
      else if (strcmp (argv[i], "verbose") == 0)
	verbose++;
      else if (strcmp (argv[i], "printable") == 0)
	printable++;
      else if (strcmp (argv[i], "nl") == 0)
	newline_option++;
      else if (strcmp (argv[i], "--") == 0)
	{
	  argv[i] = fltname;
	  break;
	}
      else
	usage ("wrong option");
    }

  argc -= i;
  argv += i;
  
  MU_ASSERT (mu_stdio_stream_create (&in, MU_STDIN_FD, 0));
  if (bufsize)
    mu_stream_set_buffer (in, mu_buffer_full, bufsize);
  MU_ASSERT (mu_stdio_stream_create (&out, MU_STDOUT_FD, 0));

  if (flags == MU_STREAM_READ)
    {
      MU_ASSERT (mu_filter_create_args (&flt, in, fltname,
					argc, (const char **)argv,
					mode,
					MU_STREAM_READ|MU_STREAM_SEEK));
      mu_stream_unref (in);
      if (bufsize)
	mu_stream_set_buffer (flt, mu_buffer_full, bufsize);
      if (shift)
	MU_ASSERT (mu_stream_seek (flt, shift, MU_SEEK_SET, NULL));
      c_copy (out, flt);
    }
  else
    {
      MU_ASSERT (mu_filter_create_args (&flt, out, fltname,
					argc, (const char **)argv,
					mode,
					MU_STREAM_WRITE));
      if (bufsize)
	mu_stream_set_buffer (flt, mu_buffer_full, bufsize);
      if (shift)
	MU_ASSERT (mu_stream_seek (in, shift, MU_SEEK_SET, NULL));
      c_copy (flt, in);

      mu_stream_close (in);
      mu_stream_destroy (&in);
    }

  mu_stream_close (flt);
  mu_stream_destroy (&flt);
  
  if (newline_option)
    mu_stream_write (out, "\n", 1, NULL);
    
  mu_stream_close (out);
  mu_stream_destroy (&out);
  
  if (verbose)
    {
      fprintf (stderr, "\nInput stream stats:\n");
      fprintf (stderr, "Bytes in: %lu\n",
	       (unsigned long) instat[MU_STREAM_STAT_IN]);
      fprintf (stderr, "Bytes out: %lu\n",
	       (unsigned long) instat[MU_STREAM_STAT_OUT]);
      fprintf (stderr, "Reads: %lu\n",
	       (unsigned long) instat[MU_STREAM_STAT_READS]);
      fprintf (stderr, "Seeks: %lu\n",
	       (unsigned long) instat[MU_STREAM_STAT_SEEKS]);

      fprintf (stderr, "\nOutput stream stats:\n");
      fprintf (stderr, "Bytes in: %lu\n",
	       (unsigned long) outstat[MU_STREAM_STAT_IN]);
      fprintf (stderr, "Bytes out: %lu\n",
	       (unsigned long) outstat[MU_STREAM_STAT_OUT]);
      fprintf (stderr, "Writes: %lu\n",
	       (unsigned long) outstat[MU_STREAM_STAT_WRITES]);
      fprintf (stderr, "Seeks: %lu\n",
	       (unsigned long) outstat[MU_STREAM_STAT_SEEKS]);
    }

  return 0;
}