int mu_iostream_create (mu_stream_t *pref, mu_stream_t in, mu_stream_t out) { struct _mu_iostream *sp; sp = (struct _mu_iostream *) _mu_stream_create (sizeof (*sp), MU_STREAM_READ | MU_STREAM_WRITE); if (!sp) return ENOMEM; sp->stream.flags |= _MU_STR_OPEN; sp->stream.read = _iostream_read; if (in->readdelim) sp->stream.readdelim = _iostream_readdelim; sp->stream.write = _iostream_write; sp->stream.flush = _iostream_flush; sp->stream.open = _iostream_open; sp->stream.close = _iostream_close; sp->stream.done = _iostream_done; sp->stream.ctl = _iostream_ctl; sp->stream.wait = _iostream_wait; sp->stream.shutdown = _iostream_shutdown; sp->stream.error_string = _iostream_error_string; mu_stream_ref (in); sp->transport[_MU_STREAM_INPUT] = in; mu_stream_ref (out); sp->transport[_MU_STREAM_OUTPUT] = out; mu_stream_set_buffer ((mu_stream_t) sp, mu_buffer_line, 0); *pref = (mu_stream_t) sp; return 0; }
int mu_streamref_create_abridged (mu_stream_t *pref, mu_stream_t str, mu_off_t start, mu_off_t end) { int rc; mu_off_t off; int flags; struct _mu_streamref *sp; rc = mu_stream_seek (str, 0, MU_SEEK_SET, &off);/*FIXME: SEEK_CUR?*/ if (rc) return rc; mu_stream_get_flags (str, &flags); sp = (struct _mu_streamref *) _mu_stream_create (sizeof (*sp), flags | _MU_STR_OPEN); if (!sp) return ENOMEM; mu_stream_ref (str); sp->stream.read = _streamref_read; if (str->readdelim) sp->stream.readdelim = _streamref_readdelim; sp->stream.write = _streamref_write; sp->stream.flush = _streamref_flush; sp->stream.open = _streamref_open; sp->stream.close = _streamref_close; sp->stream.done = _streamref_done; sp->stream.seek = _streamref_seek; sp->stream.size = _streamref_size; sp->stream.ctl = _streamref_ctl; sp->stream.wait = _streamref_wait; sp->stream.truncate = _streamref_truncate; sp->stream.shutdown = _streamref_shutdown; sp->stream.error_string = _streamref_error_string; sp->transport = str; sp->start = start; sp->end = end; if (off < start || off > end) off = start; sp->offset = off; *pref = (mu_stream_t) sp; mu_stream_set_buffer (*pref, mu_buffer_full, 0); return 0; }
static int set_strerr_flt () { mu_stream_t flt, trans[2]; int rc; rc = mu_stream_ioctl (mu_strerr, MU_IOCTL_TOPSTREAM, MU_IOCTL_OP_GET, trans); if (rc == 0) { char sessidstr[10]; char *argv[] = { "inline-comment", NULL, "-S", NULL }; snprintf (sessidstr, sizeof sessidstr, "%08lx:", mu_session_id); argv[1] = sessidstr; rc = mu_filter_create_args (&flt, trans[0], "inline-comment", 3, (const char **)argv, MU_FILTER_ENCODE, MU_STREAM_WRITE); mu_stream_unref (trans[0]); if (rc == 0) { mu_stream_set_buffer (flt, mu_buffer_line, 0); trans[0] = flt; trans[1] = NULL; rc = mu_stream_ioctl (mu_strerr, MU_IOCTL_TOPSTREAM, MU_IOCTL_OP_SET, trans); mu_stream_unref (trans[0]); if (rc) mu_error (_("%s failed: %s"), "MU_IOCTL_SET_STREAM", mu_stream_strerror (mu_strerr, rc)); } else mu_error (_("cannot create log filter stream: %s"), mu_strerror (rc)); } else { mu_error (_("%s failed: %s"), "MU_IOCTL_GET_STREAM", mu_stream_strerror (mu_strerr, rc)); } return rc; }
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; }
static int _pop_message_get_stream (struct _pop3_message *mpm, mu_stream_t *pstr) { int status; struct _pop3_mailbox *mpd = mpm->mpd; if (!(mpm->flags & _POP3_MSG_CACHED)) { mu_stream_t stream; mu_off_t size; status = mu_pop3_retr (mpd->pop3, mpm->num, &stream); if (status) return status; do { mu_stream_t flt; if (!mpd->cache) { status = mu_temp_file_stream_create (&mpd->cache, NULL, 0); if (status) /* FIXME: Try to recover first */ break; mu_stream_set_buffer (mpd->cache, mu_buffer_full, 8192); } status = mu_stream_size (mpd->cache, &mpm->offset); if (status) break; status = mu_filter_create (&flt, stream, "CRLF", MU_FILTER_DECODE, MU_STREAM_READ); if (status) break; status = mu_stream_copy (mpd->cache, flt, 0, &size); mu_stream_destroy (&flt); } while (0); if (status) { pop_stream_drain (stream); mu_stream_unref (stream); return status; } mu_stream_unref (stream); mpm->message_size = size; /* FIXME: Possible overflow. */ mpm->flags |= _POP3_MSG_CACHED | _POP3_MSG_SIZE; } return mu_streamref_create_abridged (pstr, mpd->cache, mpm->offset, mpm->offset + mpm->message_size - 1); }
static int pop_open (mu_mailbox_t mbox, int flags) { struct _pop3_mailbox *mpd = mbox->data; int status; mu_stream_t stream; struct mu_sockaddr *sa; struct mu_sockaddr_hints hints; /* Sanity checks. */ if (mpd == NULL) return EINVAL; mbox->flags = flags; memset (&hints, 0, sizeof (hints)); hints.flags = MU_AH_DETECT_FAMILY; hints.port = mpd->pops ? MU_POPS_PORT : MU_POP_PORT; hints.protocol = IPPROTO_TCP; hints.socktype = SOCK_STREAM; status = mu_sockaddr_from_url (&sa, mbox->url, &hints); if (status) return status; status = mu_tcp_stream_create_from_sa (&stream, sa, NULL, mbox->flags); if (status) { mu_sockaddr_free (sa); return status; } #ifdef WITH_TLS if (mpd->pops) { mu_stream_t newstr; status = mu_tls_client_stream_create (&newstr, stream, stream, 0); mu_stream_unref (stream); if (status) { mu_error ("pop_open: mu_tls_client_stream_create: %s", mu_strerror (status)); return status; } stream = newstr; } #endif /* WITH_TLS */ /* FIXME: How to configure buffer size? */ mu_stream_set_buffer (stream, mu_buffer_line, 0); status = mu_pop3_create (&mpd->pop3); if (status) { mu_stream_destroy (&stream); return status; } mu_pop3_set_carrier (mpd->pop3, stream); if (mu_debug_level_p (MU_DEBCAT_MAILBOX, MU_DEBUG_PROT)) mu_pop3_trace (mpd->pop3, MU_POP3_TRACE_SET); if (mu_debug_level_p (MU_DEBCAT_MAILBOX, MU_DEBUG_TRACE6)) mu_pop3_trace_mask (mpd->pop3, MU_POP3_TRACE_SET, MU_XSCRIPT_SECURE); if (mu_debug_level_p (MU_DEBCAT_MAILBOX, MU_DEBUG_TRACE7)) mu_pop3_trace_mask (mpd->pop3, MU_POP3_TRACE_SET, MU_XSCRIPT_PAYLOAD); do { status = mu_pop3_connect (mpd->pop3); if (status) break; status = mu_pop3_capa (mpd->pop3, 1, NULL); if (status == MU_ERR_REPLY) { mu_debug (MU_DEBCAT_MAILBOX, MU_DEBUG_ERROR, ("server rejected the CAPA command: %s", mu_pop3_strresp (mpd->pop3))); /* try to continue anyway */ } else if (status) return status; #ifdef WITH_TLS if (!mpd->pops && mu_url_sget_param (mbox->url, "notls", NULL) == MU_ERR_NOENT && mu_pop3_capa_test (mpd->pop3, "STLS", NULL) == 0) { status = mu_pop3_stls (mpd->pop3); if (status) break; } #endif status = mu_authority_authenticate (mbox->folder->authority); } while (0); if (status) mu_pop3_destroy (&mpd->pop3); return status; }
void io_setio (int ifd, int ofd, int tls) { mu_stream_t str, istream, ostream; if (ifd == -1) imap4d_bye (ERR_NO_IFILE); if (ofd == -1) imap4d_bye (ERR_NO_OFILE); if (mu_stdio_stream_create (&istream, ifd, MU_STREAM_READ)) imap4d_bye (ERR_STREAM_CREATE); mu_stream_set_buffer (istream, mu_buffer_line, 0); if (mu_stdio_stream_create (&ostream, ofd, MU_STREAM_WRITE)) imap4d_bye (ERR_STREAM_CREATE); mu_stream_set_buffer (ostream, mu_buffer_line, 0); /* Combine the two streams into an I/O one. */ #ifdef WITH_TLS if (tls) { int rc = mu_tls_server_stream_create (&str, istream, ostream, 0); if (rc) { mu_stream_unref (istream); mu_stream_unref (ostream); mu_error (_("failed to create TLS stream: %s"), mu_strerror (rc)); imap4d_bye (ERR_STREAM_CREATE); } } else #endif if (mu_iostream_create (&str, istream, ostream)) imap4d_bye (ERR_STREAM_CREATE); /* Convert all writes to CRLF form. There is no need to convert reads, as the code ignores extra \r anyway. */ if (mu_filter_create (&iostream, str, "CRLF", MU_FILTER_ENCODE, MU_STREAM_WRITE | MU_STREAM_RDTHRU)) imap4d_bye (ERR_STREAM_CREATE); /* Change buffering scheme: filter streams are fully buffered by default. */ mu_stream_set_buffer (iostream, mu_buffer_line, 0); if (imap4d_transcript) { int rc; mu_stream_t dstr, xstr; rc = mu_dbgstream_create (&dstr, MU_DIAG_DEBUG); if (rc) mu_error (_("cannot create debug stream; transcript disabled: %s"), mu_strerror (rc)); else { rc = mu_xscript_stream_create (&xstr, iostream, dstr, NULL); mu_stream_unref (dstr); if (rc) mu_error (_("cannot create transcript stream: %s"), mu_strerror (rc)); else { mu_stream_unref (iostream); iostream = xstr; } } } }
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; }