Add a framework for printing I/O transcripts; modify pop3d to use it.
* include/mailutils/stream.h (MU_STREAM_RDTHRU) (MU_STREAM_WRTHRU,MU_IOCTL_SET_TRANSPORT): New flags. (mu_xscript_stream_create, mu_iostream_create) (mu_dbgstream_create): New prototypes. * include/mailutils/sys/dbgstream.h: New header. * include/mailutils/sys/iostream.h: New header. * include/mailutils/sys/xscript-stream.h: New header. * include/mailutils/sys/Makefile.am (sysinclude_HEADERS): Add dbgstream.h, iostream.h and xscript-stream.h * mailbox/dbgstream.c: New file. * mailbox/iostream.c: New file. * mailbox/xscript-stream.c: New file. * mailbox/Makefile.am (libmailutils_la_SOURCES): Add dbgstream.c, iostream.c and xscript-stream.c * mailbox/filter_iconv.c (_icvt_ioctl): Simplify the declaration of ptrans. * mailbox/mapfile_stream.c (_mapfile_ioctl): Likewise. * mailbox/memory_stream.c (_memory_ioctl): Likewise. * mailbox/prog_stream.c (_prog_ioctl): Likewise. * mailbox/tcp.c (_tcp_ioctl): Likewise. * mailbox/fltstream.c (filter_ctl): Likewise. (filter_read_through, filter_write_through): New methods. (mu_filter_stream_create): Allow for use of MU_STREAM_RDTHRU and MU_STREAM_WRTHRU to create two-way filters (writing triggers filtering while reading is transparent or vice versa). * pop3d/extra.c (istream, ostream): Remove globals. (iostream): New variable. (real_istream, real_ostream): New variables. (pop3d_setio): Set transcript stream on top of the I/O one, if required. (pop3d_init_tls_server): Rewrite. Revert the meaning of the return code to match the usual convention (0 - success). (transcript): Removed. (pop3d_outf): Remove calls to transcript. * pop3d/pop3d.h (istream, ostream): Remove externs. (iostream): New extern. * pop3d/retr.c: Use iostream, instear of ostream. * pop3d/top.c: Likewise. * pop3d/stls.c: Update the call to pop3d_init_tls_server. * mailbox/stream_vprintf.c (mu_stream_vprintf): Fix return value to match the usual convention.
Showing
22 changed files
with
875 additions
and
80 deletions
... | @@ -47,6 +47,9 @@ enum mu_buffer_type | ... | @@ -47,6 +47,9 @@ enum mu_buffer_type |
47 | /* FIXME: This one affects only mailboxes */ | 47 | /* FIXME: This one affects only mailboxes */ |
48 | #define MU_STREAM_QACCESS 0x00000200 | 48 | #define MU_STREAM_QACCESS 0x00000200 |
49 | 49 | ||
50 | #define MU_STREAM_RDTHRU 0x00000400 | ||
51 | #define MU_STREAM_WRTHRU 0x00000800 | ||
52 | |||
50 | #define MU_STREAM_IRGRP 0x00001000 | 53 | #define MU_STREAM_IRGRP 0x00001000 |
51 | #define MU_STREAM_IWGRP 0x00002000 | 54 | #define MU_STREAM_IWGRP 0x00002000 |
52 | #define MU_STREAM_IROTH 0x00004000 | 55 | #define MU_STREAM_IROTH 0x00004000 |
... | @@ -59,6 +62,7 @@ enum mu_buffer_type | ... | @@ -59,6 +62,7 @@ enum mu_buffer_type |
59 | #define MU_IOCTL_SET_SEEK_LIMITS 4 | 62 | #define MU_IOCTL_SET_SEEK_LIMITS 4 |
60 | #define MU_IOCTL_ABRIDGE_SEEK MU_IOCTL_SET_SEEK_LIMITS | 63 | #define MU_IOCTL_ABRIDGE_SEEK MU_IOCTL_SET_SEEK_LIMITS |
61 | #define MU_IOCTL_GET_SEEK_LIMITS 5 | 64 | #define MU_IOCTL_GET_SEEK_LIMITS 5 |
65 | #define MU_IOCTL_SET_TRANSPORT 6 | ||
62 | 66 | ||
63 | void mu_stream_ref (mu_stream_t stream); | 67 | void mu_stream_ref (mu_stream_t stream); |
64 | void mu_stream_unref (mu_stream_t stream); | 68 | void mu_stream_unref (mu_stream_t stream); |
... | @@ -145,4 +149,12 @@ int mu_tcp_stream_create_with_source_host (mu_stream_t *stream, | ... | @@ -145,4 +149,12 @@ int mu_tcp_stream_create_with_source_host (mu_stream_t *stream, |
145 | int mu_tcp_stream_create (mu_stream_t *stream, const char *host, int port, | 149 | int mu_tcp_stream_create (mu_stream_t *stream, const char *host, int port, |
146 | int flags); | 150 | int flags); |
147 | 151 | ||
152 | int mu_xscript_stream_create(mu_stream_t *pref, mu_stream_t transport, | ||
153 | mu_stream_t logstr, | ||
154 | const char *prefix[]); | ||
155 | int mu_iostream_create (mu_stream_t *pref, mu_stream_t in, mu_stream_t out, | ||
156 | int flags); | ||
157 | int mu_dbgstream_create(mu_stream_t *pref, mu_debug_t debug, | ||
158 | mu_log_level_t level, int flags); | ||
159 | |||
148 | #endif | 160 | #endif | ... | ... |
... | @@ -19,10 +19,12 @@ | ... | @@ -19,10 +19,12 @@ |
19 | 19 | ||
20 | sysincludedir=$(pkgincludedir)/sys | 20 | sysincludedir=$(pkgincludedir)/sys |
21 | sysinclude_HEADERS = \ | 21 | sysinclude_HEADERS = \ |
22 | dbgstream.h\ | ||
22 | file_stream.h\ | 23 | file_stream.h\ |
23 | filter.h\ | 24 | filter.h\ |
24 | header_stream.h\ | 25 | header_stream.h\ |
25 | header.h\ | 26 | header.h\ |
27 | iostream.h\ | ||
26 | mapfile_stream.h\ | 28 | mapfile_stream.h\ |
27 | memory_stream.h\ | 29 | memory_stream.h\ |
28 | message_stream.h\ | 30 | message_stream.h\ |
... | @@ -36,4 +38,5 @@ sysinclude_HEADERS = \ | ... | @@ -36,4 +38,5 @@ sysinclude_HEADERS = \ |
36 | stream.h\ | 38 | stream.h\ |
37 | tls-stream.h\ | 39 | tls-stream.h\ |
38 | pop3.h\ | 40 | pop3.h\ |
39 | nntp.h | 41 | nntp.h\ |
42 | xscript-stream.h | ... | ... |
include/mailutils/sys/dbgstream.h
0 → 100644
1 | /* GNU Mailutils -- a suite of utilities for electronic mail | ||
2 | Copyright (C) 2010 Free Software Foundation, Inc. | ||
3 | |||
4 | This library is free software; you can redistribute it and/or modify | ||
5 | it under the terms of the GNU Lesser General Public License as published by | ||
6 | the Free Software Foundation; either version 3, or (at your option) | ||
7 | any later version. | ||
8 | |||
9 | This library is distributed in the hope that it will be useful, | ||
10 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
12 | GNU Lesser General Public License for more details. | ||
13 | |||
14 | You should have received a copy of the GNU Lesser General Public License | ||
15 | along with GNU Mailutils. If not, see <http://www.gnu.org/licenses/>. */ | ||
16 | |||
17 | #ifndef _MAILUTILS_SYS_DBGSTREAM_H | ||
18 | # define _MAILUTILS_SYS_DBGSTREAM_H | ||
19 | |||
20 | # include <mailutils/types.h> | ||
21 | # include <mailutils/stream.h> | ||
22 | # include <mailutils/sys/stream.h> | ||
23 | |||
24 | struct _mu_dbgstream | ||
25 | { | ||
26 | struct _mu_stream stream; | ||
27 | mu_debug_t debug; | ||
28 | mu_log_level_t level; | ||
29 | }; | ||
30 | |||
31 | #endif |
include/mailutils/sys/iostream.h
0 → 100644
1 | /* GNU Mailutils -- a suite of utilities for electronic mail | ||
2 | Copyright (C) 2010 Free Software Foundation, Inc. | ||
3 | |||
4 | This library is free software; you can redistribute it and/or modify | ||
5 | it under the terms of the GNU Lesser General Public License as published by | ||
6 | the Free Software Foundation; either version 3, or (at your option) | ||
7 | any later version. | ||
8 | |||
9 | This library is distributed in the hope that it will be useful, | ||
10 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
12 | GNU Lesser General Public License for more details. | ||
13 | |||
14 | You should have received a copy of the GNU Lesser General Public License | ||
15 | along with GNU Mailutils. If not, see <http://www.gnu.org/licenses/>. */ | ||
16 | |||
17 | #ifndef _MAILUTILS_SYS_IOSTREAM_H | ||
18 | # define _MAILUTILS_SYS_IOSTREAM_H | ||
19 | |||
20 | # include <mailutils/types.h> | ||
21 | # include <mailutils/stream.h> | ||
22 | # include <mailutils/sys/stream.h> | ||
23 | |||
24 | # define _MU_STREAM_INPUT 0 | ||
25 | # define _MU_STREAM_OUTPUT 1 | ||
26 | |||
27 | struct _mu_iostream | ||
28 | { | ||
29 | struct _mu_stream stream; | ||
30 | mu_stream_t transport[2]; | ||
31 | int last_err_str; | ||
32 | }; | ||
33 | |||
34 | #endif |
include/mailutils/sys/xscript-stream.h
0 → 100644
1 | /* GNU Mailutils -- a suite of utilities for electronic mail | ||
2 | Copyright (C) 2010 Free Software Foundation, Inc. | ||
3 | |||
4 | This library is free software; you can redistribute it and/or modify | ||
5 | it under the terms of the GNU Lesser General Public License as published by | ||
6 | the Free Software Foundation; either version 3, or (at your option) | ||
7 | any later version. | ||
8 | |||
9 | This library is distributed in the hope that it will be useful, | ||
10 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
12 | GNU Lesser General Public License for more details. | ||
13 | |||
14 | You should have received a copy of the GNU Lesser General Public License | ||
15 | along with GNU Mailutils. If not, see <http://www.gnu.org/licenses/>. */ | ||
16 | |||
17 | #ifndef _MAILUTILS_SYS_XSCRIPT_STREAM_H | ||
18 | # define _MAILUTILS_SYS_XSCRIPT_STREAM_H | ||
19 | |||
20 | # include <mailutils/types.h> | ||
21 | # include <mailutils/stream.h> | ||
22 | # include <mailutils/sys/stream.h> | ||
23 | |||
24 | struct _mu_xscript_stream | ||
25 | { | ||
26 | struct _mu_stream stream; | ||
27 | mu_stream_t transport; | ||
28 | mu_stream_t logstr; | ||
29 | int flags; | ||
30 | char *prefix[2]; | ||
31 | }; | ||
32 | |||
33 | #endif |
... | @@ -69,6 +69,7 @@ libmailutils_la_SOURCES = \ | ... | @@ -69,6 +69,7 @@ libmailutils_la_SOURCES = \ |
69 | daemon.c\ | 69 | daemon.c\ |
70 | date.c\ | 70 | date.c\ |
71 | dbgstderr.c\ | 71 | dbgstderr.c\ |
72 | dbgstream.c\ | ||
72 | dbgsyslog.c\ | 73 | dbgsyslog.c\ |
73 | debug.c\ | 74 | debug.c\ |
74 | diag.c\ | 75 | diag.c\ |
... | @@ -84,6 +85,7 @@ libmailutils_la_SOURCES = \ | ... | @@ -84,6 +85,7 @@ libmailutils_la_SOURCES = \ |
84 | gocs.c\ | 85 | gocs.c\ |
85 | hdritr.c\ | 86 | hdritr.c\ |
86 | header.c\ | 87 | header.c\ |
88 | iostream.c\ | ||
87 | iterator.c\ | 89 | iterator.c\ |
88 | ipsrv.c\ | 90 | ipsrv.c\ |
89 | kwd.c\ | 91 | kwd.c\ |
... | @@ -150,7 +152,8 @@ libmailutils_la_SOURCES = \ | ... | @@ -150,7 +152,8 @@ libmailutils_la_SOURCES = \ |
150 | vartab.c\ | 152 | vartab.c\ |
151 | vasnprintf.c\ | 153 | vasnprintf.c\ |
152 | version.c\ | 154 | version.c\ |
153 | wicket.c | 155 | wicket.c\ |
156 | xscript-stream.c | ||
154 | 157 | ||
155 | BUILT_SOURCES = parsedate.c muerrno.c cfg_parser.c cfg_parser.h cfg_lexer.c | 158 | BUILT_SOURCES = parsedate.c muerrno.c cfg_parser.c cfg_parser.h cfg_lexer.c |
156 | MOSTLYCLEANFILES= | 159 | MOSTLYCLEANFILES= | ... | ... |
mailbox/dbgstream.c
0 → 100644
1 | /* GNU Mailutils -- a suite of utilities for electronic mail | ||
2 | Copyright (C) 1999, 2000, 2001, 2002, 2004, | ||
3 | 2005, 2006, 2007, 2008, 2009, 2010 Free Software Foundation, Inc. | ||
4 | |||
5 | This library is free software; you can redistribute it and/or modify | ||
6 | it under the terms of the GNU Lesser General Public License as published by | ||
7 | the Free Software Foundation; either version 3, or (at your option) | ||
8 | any later version. | ||
9 | |||
10 | This library is distributed in the hope that it will be useful, | ||
11 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
13 | GNU Lesser General Public License for more details. | ||
14 | |||
15 | You should have received a copy of the GNU Lesser General Public License | ||
16 | along with GNU Mailutils. If not, see <http://www.gnu.org/licenses/>. */ | ||
17 | |||
18 | #ifdef HAVE_CONFIG_H | ||
19 | # include <config.h> | ||
20 | #endif | ||
21 | #include <stdlib.h> | ||
22 | #include <string.h> | ||
23 | #include <errno.h> | ||
24 | |||
25 | #include <mailutils/types.h> | ||
26 | #include <mailutils/alloc.h> | ||
27 | #include <mailutils/errno.h> | ||
28 | |||
29 | #include <mailutils/nls.h> | ||
30 | #include <mailutils/stream.h> | ||
31 | #include <mailutils/sys/stream.h> | ||
32 | #include <mailutils/sys/dbgstream.h> | ||
33 | #include <mailutils/debug.h> | ||
34 | |||
35 | static int | ||
36 | _dbg_write (struct _mu_stream *str, const char *buf, size_t size, | ||
37 | size_t *pnwrite) | ||
38 | { | ||
39 | struct _mu_dbgstream *sp = (struct _mu_dbgstream *)str; | ||
40 | if (pnwrite) | ||
41 | *pnwrite = size; | ||
42 | while (size > 0 && (buf[size-1] == '\n' || buf[size-1] == '\r')) | ||
43 | size--; | ||
44 | if (size) | ||
45 | mu_debug_printf (sp->debug, sp->level, "%.*s\n", size, buf); | ||
46 | return 0; | ||
47 | } | ||
48 | |||
49 | static int | ||
50 | _dbg_flush (struct _mu_stream *str) | ||
51 | { | ||
52 | struct _mu_dbgstream *sp = (struct _mu_dbgstream *)str; | ||
53 | mu_debug_printf (sp->debug, sp->level, "\n"); | ||
54 | return 0; | ||
55 | } | ||
56 | |||
57 | static void | ||
58 | _dbg_done (struct _mu_stream *str) | ||
59 | { | ||
60 | struct _mu_dbgstream *sp = (struct _mu_dbgstream *)str; | ||
61 | if (!(str->flags & MU_STREAM_NO_CLOSE)) | ||
62 | mu_debug_destroy (&sp->debug, NULL); | ||
63 | } | ||
64 | |||
65 | int | ||
66 | mu_dbgstream_create(mu_stream_t *pref, mu_debug_t debug, mu_log_level_t level, | ||
67 | int flags) | ||
68 | { | ||
69 | struct _mu_dbgstream *sp; | ||
70 | |||
71 | sp = (struct _mu_dbgstream *) | ||
72 | _mu_stream_create (sizeof (*sp), MU_STREAM_WRITE | | ||
73 | (flags & MU_STREAM_NO_CLOSE)); | ||
74 | if (!sp) | ||
75 | return ENOMEM; | ||
76 | sp->stream.write = _dbg_write; | ||
77 | sp->stream.flush = _dbg_flush; | ||
78 | sp->stream.done = _dbg_done; | ||
79 | |||
80 | sp->debug = debug; | ||
81 | sp->level = level; | ||
82 | mu_stream_set_buffer ((mu_stream_t) sp, mu_buffer_line, 1024); | ||
83 | *pref = (mu_stream_t) sp; | ||
84 | return 0; | ||
85 | } | ||
86 |
... | @@ -192,7 +192,7 @@ static int | ... | @@ -192,7 +192,7 @@ static int |
192 | fd_ioctl (struct _mu_stream *str, int code, void *ptr) | 192 | fd_ioctl (struct _mu_stream *str, int code, void *ptr) |
193 | { | 193 | { |
194 | struct _mu_file_stream *fstr = (struct _mu_file_stream *) str; | 194 | struct _mu_file_stream *fstr = (struct _mu_file_stream *) str; |
195 | mu_transport_t (*ptrans)[2]; | 195 | mu_transport_t *ptrans; |
196 | 196 | ||
197 | switch (code) | 197 | switch (code) |
198 | { | 198 | { |
... | @@ -200,8 +200,8 @@ fd_ioctl (struct _mu_stream *str, int code, void *ptr) | ... | @@ -200,8 +200,8 @@ fd_ioctl (struct _mu_stream *str, int code, void *ptr) |
200 | if (!ptr) | 200 | if (!ptr) |
201 | return EINVAL; | 201 | return EINVAL; |
202 | ptrans = ptr; | 202 | ptrans = ptr; |
203 | (*ptrans)[0] = (mu_transport_t) fstr->fd; | 203 | ptrans[0] = (mu_transport_t) fstr->fd; |
204 | (*ptrans)[1] = NULL; | 204 | ptrans[1] = NULL; |
205 | break; | 205 | break; |
206 | 206 | ||
207 | default: | 207 | default: | ... | ... |
... | @@ -390,7 +390,7 @@ static int | ... | @@ -390,7 +390,7 @@ static int |
390 | _icvt_ioctl (mu_stream_t stream, int code, void *ptr) | 390 | _icvt_ioctl (mu_stream_t stream, int code, void *ptr) |
391 | { | 391 | { |
392 | struct icvt_stream *s = (struct icvt_stream *)stream; | 392 | struct icvt_stream *s = (struct icvt_stream *)stream; |
393 | mu_transport_t (*ptrans)[2]; | 393 | mu_transport_t *ptrans; |
394 | 394 | ||
395 | switch (code) | 395 | switch (code) |
396 | { | 396 | { |
... | @@ -398,8 +398,8 @@ _icvt_ioctl (mu_stream_t stream, int code, void *ptr) | ... | @@ -398,8 +398,8 @@ _icvt_ioctl (mu_stream_t stream, int code, void *ptr) |
398 | if (!ptr) | 398 | if (!ptr) |
399 | return EINVAL; | 399 | return EINVAL; |
400 | ptrans = ptr; | 400 | ptrans = ptr; |
401 | (*ptrans)[0] = (mu_transport_t) s->transport; | 401 | ptrans[0] = (mu_transport_t) s->transport; |
402 | (*ptrans)[1] = NULL; | 402 | ptrans[1] = NULL; |
403 | break; | 403 | break; |
404 | 404 | ||
405 | default: | 405 | default: | ... | ... |
... | @@ -335,7 +335,7 @@ static int | ... | @@ -335,7 +335,7 @@ static int |
335 | filter_ctl (struct _mu_stream *stream, int op, void *ptr) | 335 | filter_ctl (struct _mu_stream *stream, int op, void *ptr) |
336 | { | 336 | { |
337 | struct _mu_filter_stream *fs = (struct _mu_filter_stream *)stream; | 337 | struct _mu_filter_stream *fs = (struct _mu_filter_stream *)stream; |
338 | mu_transport_t (*ptrans)[2]; | 338 | mu_transport_t *ptrans; |
339 | 339 | ||
340 | switch (op) | 340 | switch (op) |
341 | { | 341 | { |
... | @@ -343,8 +343,8 @@ filter_ctl (struct _mu_stream *stream, int op, void *ptr) | ... | @@ -343,8 +343,8 @@ filter_ctl (struct _mu_stream *stream, int op, void *ptr) |
343 | if (!ptr) | 343 | if (!ptr) |
344 | return EINVAL; | 344 | return EINVAL; |
345 | ptrans = ptr; | 345 | ptrans = ptr; |
346 | (*ptrans)[0] = (mu_transport_t) fs->transport; | 346 | ptrans[0] = (mu_transport_t) fs->transport; |
347 | (*ptrans)[1] = NULL; | 347 | ptrans[1] = NULL; |
348 | break; | 348 | break; |
349 | 349 | ||
350 | default: | 350 | default: |
... | @@ -390,6 +390,26 @@ filter_close (mu_stream_t stream) | ... | @@ -390,6 +390,26 @@ filter_close (mu_stream_t stream) |
390 | return mu_stream_close (fs->transport); | 390 | return mu_stream_close (fs->transport); |
391 | } | 391 | } |
392 | 392 | ||
393 | |||
394 | static int | ||
395 | filter_read_through (struct _mu_stream *stream, | ||
396 | char *buf, size_t bufsize, | ||
397 | size_t *pnread) | ||
398 | { | ||
399 | struct _mu_filter_stream *fs = (struct _mu_filter_stream *)stream; | ||
400 | return mu_stream_read (fs->transport, buf, bufsize, pnread); | ||
401 | } | ||
402 | |||
403 | static int | ||
404 | filter_write_through (struct _mu_stream *stream, | ||
405 | const char *buf, size_t bufsize, | ||
406 | size_t *pnwrite) | ||
407 | { | ||
408 | struct _mu_filter_stream *fs = (struct _mu_filter_stream *)stream; | ||
409 | return mu_stream_write (fs->transport, buf, bufsize, pnwrite); | ||
410 | } | ||
411 | |||
412 | |||
393 | int | 413 | int |
394 | mu_filter_stream_create (mu_stream_t *pflt, | 414 | mu_filter_stream_create (mu_stream_t *pflt, |
395 | mu_stream_t str, | 415 | mu_stream_t str, |
... | @@ -402,7 +422,14 @@ mu_filter_stream_create (mu_stream_t *pflt, | ... | @@ -402,7 +422,14 @@ mu_filter_stream_create (mu_stream_t *pflt, |
402 | 422 | ||
403 | if ((flags & MU_STREAM_RDWR) == MU_STREAM_RDWR | 423 | if ((flags & MU_STREAM_RDWR) == MU_STREAM_RDWR |
404 | || !(flags & MU_STREAM_RDWR) | 424 | || !(flags & MU_STREAM_RDWR) |
405 | || (flags & (MU_STREAM_WRITE|MU_STREAM_SEEK)) == (MU_STREAM_WRITE|MU_STREAM_SEEK)) | 425 | || (flags & (MU_STREAM_WRITE|MU_STREAM_SEEK)) == |
426 | (MU_STREAM_WRITE|MU_STREAM_SEEK) | ||
427 | || (flags & (MU_STREAM_RDTHRU|MU_STREAM_WRTHRU)) == | ||
428 | (MU_STREAM_RDTHRU|MU_STREAM_WRTHRU) | ||
429 | || (flags & (MU_STREAM_READ|MU_STREAM_RDTHRU)) == | ||
430 | (MU_STREAM_READ|MU_STREAM_RDTHRU) | ||
431 | || (flags & (MU_STREAM_WRITE|MU_STREAM_WRTHRU)) == | ||
432 | (MU_STREAM_WRITE|MU_STREAM_WRTHRU)) | ||
406 | return EINVAL; | 433 | return EINVAL; |
407 | 434 | ||
408 | fs = (struct _mu_filter_stream *) _mu_stream_create (sizeof (*fs), flags); | 435 | fs = (struct _mu_filter_stream *) _mu_stream_create (sizeof (*fs), flags); |
... | @@ -413,11 +440,21 @@ mu_filter_stream_create (mu_stream_t *pflt, | ... | @@ -413,11 +440,21 @@ mu_filter_stream_create (mu_stream_t *pflt, |
413 | { | 440 | { |
414 | fs->stream.read = filter_read; | 441 | fs->stream.read = filter_read; |
415 | fs->stream.flush = filter_rd_flush; | 442 | fs->stream.flush = filter_rd_flush; |
443 | if (flags & MU_STREAM_WRTHRU) | ||
444 | { | ||
445 | flags |= MU_STREAM_WRITE; | ||
446 | fs->stream.write = filter_write_through; | ||
447 | } | ||
416 | } | 448 | } |
417 | else | 449 | else |
418 | { | 450 | { |
419 | fs->stream.write = filter_write; | 451 | fs->stream.write = filter_write; |
420 | fs->stream.flush = filter_wr_flush; | 452 | fs->stream.flush = filter_wr_flush; |
453 | if (flags & MU_STREAM_RDTHRU) | ||
454 | { | ||
455 | flags |= MU_STREAM_READ; | ||
456 | fs->stream.read = filter_read_through; | ||
457 | } | ||
421 | } | 458 | } |
422 | fs->stream.done = filter_done; | 459 | fs->stream.done = filter_done; |
423 | fs->stream.close = filter_close; | 460 | fs->stream.close = filter_close; | ... | ... |
mailbox/iostream.c
0 → 100644
1 | /* GNU Mailutils -- a suite of utilities for electronic mail | ||
2 | Copyright (C) 2010 Free Software Foundation, Inc. | ||
3 | |||
4 | This library is free software; you can redistribute it and/or modify | ||
5 | it under the terms of the GNU Lesser General Public License as published by | ||
6 | the Free Software Foundation; either version 3, or (at your option) | ||
7 | any later version. | ||
8 | |||
9 | This library is distributed in the hope that it will be useful, | ||
10 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
12 | GNU Lesser General Public License for more details. | ||
13 | |||
14 | You should have received a copy of the GNU Lesser General Public License | ||
15 | along with GNU Mailutils. If not, see <http://www.gnu.org/licenses/>. */ | ||
16 | |||
17 | #ifdef HAVE_CONFIG_H | ||
18 | # include <config.h> | ||
19 | #endif | ||
20 | #include <stdlib.h> | ||
21 | #include <string.h> | ||
22 | #include <errno.h> | ||
23 | |||
24 | #include <mailutils/types.h> | ||
25 | #include <mailutils/alloc.h> | ||
26 | #include <mailutils/errno.h> | ||
27 | |||
28 | #include <mailutils/nls.h> | ||
29 | #include <mailutils/stream.h> | ||
30 | #include <mailutils/sys/stream.h> | ||
31 | #include <mailutils/sys/iostream.h> | ||
32 | |||
33 | static int | ||
34 | _iostream_read (struct _mu_stream *str, char *buf, size_t bufsize, | ||
35 | size_t *pnread) | ||
36 | { | ||
37 | struct _mu_iostream *sp = (struct _mu_iostream *)str; | ||
38 | int rc = mu_stream_read (sp->transport[_MU_STREAM_INPUT], buf, bufsize, | ||
39 | pnread); | ||
40 | if (rc) | ||
41 | sp->last_err_str = _MU_STREAM_INPUT; | ||
42 | return rc; | ||
43 | } | ||
44 | |||
45 | static int | ||
46 | _iostream_readdelim (struct _mu_stream *str, char *buf, size_t bufsize, | ||
47 | int delim, size_t *pnread) | ||
48 | { | ||
49 | struct _mu_iostream *sp = (struct _mu_iostream *)str; | ||
50 | int rc = mu_stream_readdelim (sp->transport[_MU_STREAM_INPUT], buf, | ||
51 | bufsize, delim, pnread); | ||
52 | if (rc) | ||
53 | sp->last_err_str = _MU_STREAM_INPUT; | ||
54 | return rc; | ||
55 | } | ||
56 | |||
57 | static int | ||
58 | _iostream_write (struct _mu_stream *str, const char *buf, size_t bufsize, | ||
59 | size_t *pnwrite) | ||
60 | { | ||
61 | struct _mu_iostream *sp = (struct _mu_iostream *)str; | ||
62 | int rc = mu_stream_write (sp->transport[_MU_STREAM_OUTPUT], buf, bufsize, | ||
63 | pnwrite); | ||
64 | if (rc) | ||
65 | sp->last_err_str = _MU_STREAM_OUTPUT; | ||
66 | return rc; | ||
67 | } | ||
68 | |||
69 | static int | ||
70 | _iostream_flush (struct _mu_stream *str) | ||
71 | { | ||
72 | struct _mu_iostream *sp = (struct _mu_iostream *)str; | ||
73 | int rc = mu_stream_flush (sp->transport[_MU_STREAM_INPUT]); | ||
74 | if (rc) | ||
75 | { | ||
76 | sp->last_err_str = _MU_STREAM_INPUT; | ||
77 | return rc; | ||
78 | } | ||
79 | if (sp->transport[_MU_STREAM_INPUT] != sp->transport[_MU_STREAM_OUTPUT]) | ||
80 | { | ||
81 | rc = mu_stream_flush (sp->transport[_MU_STREAM_OUTPUT]); | ||
82 | if (rc) | ||
83 | sp->last_err_str = _MU_STREAM_OUTPUT; | ||
84 | } | ||
85 | return rc; | ||
86 | } | ||
87 | |||
88 | static int | ||
89 | _iostream_open (struct _mu_stream *str) | ||
90 | { | ||
91 | struct _mu_iostream *sp = (struct _mu_iostream *)str; | ||
92 | int rc; | ||
93 | rc = mu_stream_open (sp->transport[_MU_STREAM_INPUT]); | ||
94 | if (rc) | ||
95 | { | ||
96 | sp->last_err_str = _MU_STREAM_INPUT; | ||
97 | return rc; | ||
98 | } | ||
99 | if (sp->transport[_MU_STREAM_INPUT] != sp->transport[_MU_STREAM_OUTPUT]) | ||
100 | { | ||
101 | rc = mu_stream_open (sp->transport[_MU_STREAM_OUTPUT]); | ||
102 | if (rc) | ||
103 | { | ||
104 | sp->last_err_str = _MU_STREAM_OUTPUT; | ||
105 | mu_stream_close (sp->transport[_MU_STREAM_INPUT]); | ||
106 | } | ||
107 | } | ||
108 | return rc; | ||
109 | } | ||
110 | |||
111 | static int | ||
112 | _iostream_close (struct _mu_stream *str) | ||
113 | { | ||
114 | struct _mu_iostream *sp = (struct _mu_iostream *)str; | ||
115 | if (sp->stream.flags & MU_STREAM_NO_CLOSE) | ||
116 | return 0; | ||
117 | mu_stream_close (sp->transport[_MU_STREAM_INPUT]); | ||
118 | if (sp->transport[_MU_STREAM_INPUT] != sp->transport[_MU_STREAM_OUTPUT]) | ||
119 | mu_stream_close (sp->transport[_MU_STREAM_OUTPUT]); | ||
120 | return 0; | ||
121 | } | ||
122 | |||
123 | static void | ||
124 | _iostream_done (struct _mu_stream *str) | ||
125 | { | ||
126 | struct _mu_iostream *sp = (struct _mu_iostream *)str; | ||
127 | mu_stream_unref (sp->transport[_MU_STREAM_INPUT]); | ||
128 | if (sp->transport[_MU_STREAM_INPUT] != sp->transport[_MU_STREAM_OUTPUT]) | ||
129 | mu_stream_unref (sp->transport[_MU_STREAM_OUTPUT]); | ||
130 | } | ||
131 | |||
132 | static int | ||
133 | _iostream_ctl (struct _mu_stream *str, int op, void *arg) | ||
134 | { | ||
135 | struct _mu_iostream *sp = (struct _mu_iostream *)str; | ||
136 | mu_transport_t *ptrans; | ||
137 | |||
138 | switch (op) | ||
139 | { | ||
140 | case MU_IOCTL_GET_TRANSPORT: | ||
141 | if (!arg) | ||
142 | return EINVAL; | ||
143 | ptrans = arg; | ||
144 | ptrans[0] = (mu_transport_t) sp->transport[_MU_STREAM_INPUT]; | ||
145 | ptrans[1] = (mu_transport_t) sp->transport[_MU_STREAM_OUTPUT]; | ||
146 | break; | ||
147 | |||
148 | case MU_IOCTL_SET_TRANSPORT: | ||
149 | if (!arg) | ||
150 | return EINVAL; | ||
151 | ptrans = arg; | ||
152 | sp->transport[_MU_STREAM_INPUT] = (mu_stream_t) ptrans[0]; | ||
153 | sp->transport[_MU_STREAM_OUTPUT] = (mu_stream_t) ptrans[1]; | ||
154 | break; | ||
155 | |||
156 | default: | ||
157 | return EINVAL; | ||
158 | } | ||
159 | return 0; | ||
160 | } | ||
161 | |||
162 | static int | ||
163 | _iostream_wait (struct _mu_stream *str, int *pflags, struct timeval *tvp) | ||
164 | { | ||
165 | struct _mu_iostream *sp = (struct _mu_iostream *)str; | ||
166 | int rc = EINVAL; | ||
167 | |||
168 | if (*pflags == MU_STREAM_READY_RD) | ||
169 | { | ||
170 | rc = mu_stream_wait (sp->transport[_MU_STREAM_INPUT], pflags, tvp); | ||
171 | if (rc) | ||
172 | sp->last_err_str = _MU_STREAM_INPUT; | ||
173 | } | ||
174 | else if (*pflags == MU_STREAM_READY_WR) | ||
175 | { | ||
176 | rc = mu_stream_wait (sp->transport[_MU_STREAM_OUTPUT], pflags, tvp); | ||
177 | if (rc) | ||
178 | sp->last_err_str = _MU_STREAM_OUTPUT; | ||
179 | } | ||
180 | return rc; | ||
181 | } | ||
182 | |||
183 | static int | ||
184 | _iostream_shutdown (struct _mu_stream *str, int how) | ||
185 | { | ||
186 | struct _mu_iostream *sp = (struct _mu_iostream *)str; | ||
187 | int rc = EINVAL; | ||
188 | switch (how) | ||
189 | { | ||
190 | case MU_STREAM_READ: | ||
191 | rc = mu_stream_shutdown (sp->transport[_MU_STREAM_INPUT], how); | ||
192 | if (rc) | ||
193 | sp->last_err_str = _MU_STREAM_INPUT; | ||
194 | break; | ||
195 | |||
196 | case MU_STREAM_WRITE: | ||
197 | rc = mu_stream_shutdown (sp->transport[_MU_STREAM_OUTPUT], how); | ||
198 | if (rc) | ||
199 | sp->last_err_str = _MU_STREAM_OUTPUT; | ||
200 | } | ||
201 | return rc; | ||
202 | } | ||
203 | |||
204 | static const char * | ||
205 | _iostream_error_string (struct _mu_stream *str, int rc) | ||
206 | { | ||
207 | struct _mu_iostream *sp = (struct _mu_iostream *)str; | ||
208 | mu_stream_t transport = sp->transport[sp->last_err_str]; | ||
209 | if (transport) | ||
210 | return mu_stream_strerror (transport, rc); | ||
211 | return mu_strerror (rc); | ||
212 | } | ||
213 | |||
214 | int | ||
215 | mu_iostream_create (mu_stream_t *pref, mu_stream_t in, mu_stream_t out, | ||
216 | int flags) | ||
217 | { | ||
218 | struct _mu_iostream *sp; | ||
219 | |||
220 | sp = (struct _mu_iostream *) | ||
221 | _mu_stream_create (sizeof (*sp), | ||
222 | MU_STREAM_READ | MU_STREAM_WRITE | | ||
223 | (flags & MU_STREAM_NO_CLOSE)); | ||
224 | if (!sp) | ||
225 | return ENOMEM; | ||
226 | |||
227 | sp->stream.read = _iostream_read; | ||
228 | sp->stream.readdelim = _iostream_readdelim; | ||
229 | sp->stream.write = _iostream_write; | ||
230 | sp->stream.flush = _iostream_flush; | ||
231 | sp->stream.open = _iostream_open; | ||
232 | sp->stream.close = _iostream_close; | ||
233 | sp->stream.done = _iostream_done; | ||
234 | sp->stream.ctl = _iostream_ctl; | ||
235 | sp->stream.wait = _iostream_wait; | ||
236 | sp->stream.shutdown = _iostream_shutdown; | ||
237 | sp->stream.error_string = _iostream_error_string; | ||
238 | |||
239 | mu_stream_ref (in); | ||
240 | sp->transport[_MU_STREAM_INPUT] = in; | ||
241 | mu_stream_ref (out); | ||
242 | sp->transport[_MU_STREAM_OUTPUT] = out; | ||
243 | |||
244 | mu_stream_set_buffer ((mu_stream_t) sp, mu_buffer_line, 1024); | ||
245 | *pref = (mu_stream_t) sp; | ||
246 | return 0; | ||
247 | } | ||
248 | |||
249 |
... | @@ -209,13 +209,13 @@ static int | ... | @@ -209,13 +209,13 @@ static int |
209 | _mapfile_ioctl (struct _mu_stream *str, int code, void *ptr) | 209 | _mapfile_ioctl (struct _mu_stream *str, int code, void *ptr) |
210 | { | 210 | { |
211 | struct _mu_mapfile_stream *mfs = (struct _mu_mapfile_stream *) str; | 211 | struct _mu_mapfile_stream *mfs = (struct _mu_mapfile_stream *) str; |
212 | mu_transport_t (*ptrans)[2]; | 212 | mu_transport_t ptrans[2]; |
213 | 213 | ||
214 | switch (code) | 214 | switch (code) |
215 | { | 215 | { |
216 | case MU_IOCTL_GET_TRANSPORT: | 216 | case MU_IOCTL_GET_TRANSPORT: |
217 | (*ptrans)[0] = (mu_transport_t) mfs->fd; | 217 | ptrans[0] = (mu_transport_t) mfs->fd; |
218 | (*ptrans)[1] = NULL; | 218 | ptrans[1] = NULL; |
219 | break; | 219 | break; |
220 | 220 | ||
221 | default: | 221 | default: | ... | ... |
... | @@ -147,7 +147,7 @@ static int | ... | @@ -147,7 +147,7 @@ static int |
147 | _memory_ioctl (struct _mu_stream *stream, int code, void *ptr) | 147 | _memory_ioctl (struct _mu_stream *stream, int code, void *ptr) |
148 | { | 148 | { |
149 | struct _mu_memory_stream *mfs = (struct _mu_memory_stream *) stream; | 149 | struct _mu_memory_stream *mfs = (struct _mu_memory_stream *) stream; |
150 | mu_transport_t (*ptrans)[2]; | 150 | mu_transport_t *ptrans; |
151 | 151 | ||
152 | switch (code) | 152 | switch (code) |
153 | { | 153 | { |
... | @@ -155,8 +155,8 @@ _memory_ioctl (struct _mu_stream *stream, int code, void *ptr) | ... | @@ -155,8 +155,8 @@ _memory_ioctl (struct _mu_stream *stream, int code, void *ptr) |
155 | if (!ptr) | 155 | if (!ptr) |
156 | return EINVAL; | 156 | return EINVAL; |
157 | ptrans = ptr; | 157 | ptrans = ptr; |
158 | (*ptrans)[0] = (mu_transport_t) mfs->ptr; | 158 | ptrans[0] = (mu_transport_t) mfs->ptr; |
159 | (*ptrans)[1] = NULL; | 159 | ptrans[1] = NULL; |
160 | break; | 160 | break; |
161 | 161 | ||
162 | default: | 162 | default: | ... | ... |
... | @@ -367,7 +367,7 @@ _prog_ioctl (struct _mu_stream *str, int code, void *ptr) | ... | @@ -367,7 +367,7 @@ _prog_ioctl (struct _mu_stream *str, int code, void *ptr) |
367 | { | 367 | { |
368 | struct _mu_prog_stream *fstr = (struct _mu_prog_stream *) str; | 368 | struct _mu_prog_stream *fstr = (struct _mu_prog_stream *) str; |
369 | mu_transport_t t[2]; | 369 | mu_transport_t t[2]; |
370 | mu_transport_t (*ptrans)[2]; | 370 | mu_transport_t *ptrans; |
371 | 371 | ||
372 | switch (code) | 372 | switch (code) |
373 | { | 373 | { |
... | @@ -375,9 +375,9 @@ _prog_ioctl (struct _mu_stream *str, int code, void *ptr) | ... | @@ -375,9 +375,9 @@ _prog_ioctl (struct _mu_stream *str, int code, void *ptr) |
375 | if (!ptr) | 375 | if (!ptr) |
376 | return EINVAL; | 376 | return EINVAL; |
377 | mu_stream_ioctl (fstr->in, MU_IOCTL_GET_TRANSPORT, t); | 377 | mu_stream_ioctl (fstr->in, MU_IOCTL_GET_TRANSPORT, t); |
378 | (*ptrans)[0] = t[0]; | 378 | ptrans[0] = t[0]; |
379 | mu_stream_ioctl (fstr->out, MU_IOCTL_GET_TRANSPORT, t); | 379 | mu_stream_ioctl (fstr->out, MU_IOCTL_GET_TRANSPORT, t); |
380 | (*ptrans)[1] = t[1]; | 380 | ptrans[1] = t[1]; |
381 | break; | 381 | break; |
382 | 382 | ||
383 | case MU_IOCTL_GET_STATUS: | 383 | case MU_IOCTL_GET_STATUS: | ... | ... |
... | @@ -37,6 +37,6 @@ mu_stream_vprintf (mu_stream_t str, const char *fmt, va_list ap) | ... | @@ -37,6 +37,6 @@ mu_stream_vprintf (mu_stream_t str, const char *fmt, va_list ap) |
37 | n = strlen (buf); | 37 | n = strlen (buf); |
38 | rc = mu_stream_write (str, buf, n, NULL); | 38 | rc = mu_stream_write (str, buf, n, NULL); |
39 | free (buf); | 39 | free (buf); |
40 | return rc == 0 ? n : -1; | 40 | return rc; |
41 | } | 41 | } |
42 | 42 | ... | ... |
... | @@ -196,7 +196,7 @@ static int | ... | @@ -196,7 +196,7 @@ static int |
196 | _tcp_ioctl (mu_stream_t stream, int code, void *ptr) | 196 | _tcp_ioctl (mu_stream_t stream, int code, void *ptr) |
197 | { | 197 | { |
198 | struct _tcp_instance *tcp = (struct _tcp_instance *)stream; | 198 | struct _tcp_instance *tcp = (struct _tcp_instance *)stream; |
199 | mu_transport_t (*ptrans)[2]; | 199 | mu_transport_t *ptrans; |
200 | 200 | ||
201 | switch (code) | 201 | switch (code) |
202 | { | 202 | { |
... | @@ -204,8 +204,8 @@ _tcp_ioctl (mu_stream_t stream, int code, void *ptr) | ... | @@ -204,8 +204,8 @@ _tcp_ioctl (mu_stream_t stream, int code, void *ptr) |
204 | if (!ptr) | 204 | if (!ptr) |
205 | return EINVAL; | 205 | return EINVAL; |
206 | ptrans = ptr; | 206 | ptrans = ptr; |
207 | (*ptrans)[0] = (mu_transport_t) tcp->fd; | 207 | ptrans[0] = (mu_transport_t) tcp->fd; |
208 | (*ptrans)[1] = NULL; | 208 | ptrans[1] = NULL; |
209 | break; | 209 | break; |
210 | 210 | ||
211 | default: | 211 | default: | ... | ... |
mailbox/xscript-stream.c
0 → 100644
1 | /* GNU Mailutils -- a suite of utilities for electronic mail | ||
2 | Copyright (C) 1999, 2000, 2001, 2002, 2004, | ||
3 | 2005, 2006, 2007, 2008, 2009, 2010 Free Software Foundation, Inc. | ||
4 | |||
5 | This library is free software; you can redistribute it and/or modify | ||
6 | it under the terms of the GNU Lesser General Public License as published by | ||
7 | the Free Software Foundation; either version 3, or (at your option) | ||
8 | any later version. | ||
9 | |||
10 | This library is distributed in the hope that it will be useful, | ||
11 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
13 | GNU Lesser General Public License for more details. | ||
14 | |||
15 | You should have received a copy of the GNU Lesser General Public License | ||
16 | along with GNU Mailutils. If not, see <http://www.gnu.org/licenses/>. */ | ||
17 | |||
18 | #ifdef HAVE_CONFIG_H | ||
19 | # include <config.h> | ||
20 | #endif | ||
21 | #include <stdlib.h> | ||
22 | #include <string.h> | ||
23 | #include <errno.h> | ||
24 | |||
25 | #include <mailutils/types.h> | ||
26 | #include <mailutils/alloc.h> | ||
27 | #include <mailutils/errno.h> | ||
28 | |||
29 | #include <mailutils/nls.h> | ||
30 | #include <mailutils/stream.h> | ||
31 | #include <mailutils/sys/stream.h> | ||
32 | #include <mailutils/sys/xscript-stream.h> | ||
33 | |||
34 | /* A "transcript stream" transparently writes data to and reads data from | ||
35 | an underlying transport stream, writing each lineful of data to a "log | ||
36 | stream". Writes to log stream are prefixed with a string indicating | ||
37 | direction of the data (read/write). Default prefixes are those used in | ||
38 | RFCs -- "S: ", for data written ("Server"), and "C: ", for data read | ||
39 | ("Client"). */ | ||
40 | |||
41 | #define TRANS_READ 0x1 | ||
42 | #define TRANS_WRITE 0x2 | ||
43 | #define FLAG_TO_PFX(c) ((c) - 1) | ||
44 | |||
45 | static void | ||
46 | print_transcript (struct _mu_xscript_stream *str, int flag, | ||
47 | const char *buf, size_t size) | ||
48 | { | ||
49 | while (size) | ||
50 | { | ||
51 | const char *p; | ||
52 | size_t len; | ||
53 | |||
54 | if (str->flags & flag) | ||
55 | { | ||
56 | mu_stream_write (str->logstr, | ||
57 | str->prefix[FLAG_TO_PFX(flag)], | ||
58 | strlen (str->prefix[FLAG_TO_PFX (flag)]), | ||
59 | NULL); | ||
60 | str->flags &= ~flag; | ||
61 | } | ||
62 | p = memchr (buf, '\n', size); | ||
63 | if (p) | ||
64 | { | ||
65 | len = p - buf; | ||
66 | if (p > buf && p[-1] == '\r') | ||
67 | len--; | ||
68 | mu_stream_write (str->logstr, buf, len, NULL); | ||
69 | mu_stream_write (str->logstr, "\n", 1, NULL); | ||
70 | str->flags |= flag; | ||
71 | |||
72 | len = p - buf + 1; | ||
73 | buf = p + 1; | ||
74 | size -= len; | ||
75 | } | ||
76 | else | ||
77 | { | ||
78 | mu_stream_write (str->logstr, buf, size, NULL); | ||
79 | break; | ||
80 | } | ||
81 | } | ||
82 | } | ||
83 | |||
84 | static int | ||
85 | _xscript_read (struct _mu_stream *str, char *buf, size_t bufsize, | ||
86 | size_t *pnread) | ||
87 | { | ||
88 | struct _mu_xscript_stream *sp = (struct _mu_xscript_stream *)str; | ||
89 | size_t nbytes; | ||
90 | int rc = mu_stream_read (sp->transport, buf, bufsize, &nbytes); | ||
91 | |||
92 | if (rc == 0) | ||
93 | { | ||
94 | print_transcript (sp, TRANS_READ, buf, nbytes); | ||
95 | if (pnread) | ||
96 | *pnread = nbytes; | ||
97 | } | ||
98 | return rc; | ||
99 | } | ||
100 | |||
101 | static int | ||
102 | _xscript_readdelim (struct _mu_stream *str, char *buf, size_t bufsize, | ||
103 | int delim, size_t *pnread) | ||
104 | { | ||
105 | struct _mu_xscript_stream *sp = (struct _mu_xscript_stream *)str; | ||
106 | size_t nread; | ||
107 | int rc = mu_stream_readdelim (sp->transport, buf, bufsize, delim, &nread); | ||
108 | if (rc == 0) | ||
109 | { | ||
110 | print_transcript (sp, TRANS_READ, buf, nread); | ||
111 | if (pnread) | ||
112 | *pnread = nread; | ||
113 | } | ||
114 | return rc; | ||
115 | } | ||
116 | |||
117 | static int | ||
118 | _xscript_write (struct _mu_stream *str, const char *buf, size_t bufsize, | ||
119 | size_t *pnwrite) | ||
120 | { | ||
121 | struct _mu_xscript_stream *sp = (struct _mu_xscript_stream *)str; | ||
122 | int rc = mu_stream_write (sp->transport, buf, bufsize, pnwrite); | ||
123 | |||
124 | if (rc == 0) | ||
125 | print_transcript (sp, TRANS_WRITE, buf, pnwrite ? *pnwrite : bufsize); | ||
126 | return rc; | ||
127 | } | ||
128 | |||
129 | static int | ||
130 | _xscript_flush (struct _mu_stream *str) | ||
131 | { | ||
132 | struct _mu_xscript_stream *sp = (struct _mu_xscript_stream *)str; | ||
133 | return mu_stream_flush (sp->transport); | ||
134 | } | ||
135 | |||
136 | static int | ||
137 | _xscript_open (struct _mu_stream *str) | ||
138 | { | ||
139 | struct _mu_xscript_stream *sp = (struct _mu_xscript_stream *)str; | ||
140 | return mu_stream_open (sp->transport); | ||
141 | } | ||
142 | |||
143 | static int | ||
144 | _xscript_close (struct _mu_stream *str) | ||
145 | { | ||
146 | struct _mu_xscript_stream *sp = (struct _mu_xscript_stream *)str; | ||
147 | if (sp->stream.flags & MU_STREAM_NO_CLOSE) | ||
148 | return 0; | ||
149 | return mu_stream_close (sp->transport); | ||
150 | } | ||
151 | |||
152 | static void | ||
153 | _xscript_done (struct _mu_stream *str) | ||
154 | { | ||
155 | struct _mu_xscript_stream *sp = (struct _mu_xscript_stream *)str; | ||
156 | free (sp->prefix[0]); | ||
157 | free (sp->prefix[1]); | ||
158 | mu_stream_unref (sp->transport); | ||
159 | mu_stream_unref (sp->logstr); | ||
160 | } | ||
161 | |||
162 | static int | ||
163 | _xscript_seek (struct _mu_stream *str, mu_off_t off, mu_off_t *ppos) | ||
164 | { | ||
165 | struct _mu_xscript_stream *sp = (struct _mu_xscript_stream *)str; | ||
166 | return mu_stream_seek (sp->transport, off, MU_SEEK_SET, ppos); | ||
167 | } | ||
168 | |||
169 | static int | ||
170 | _xscript_size (struct _mu_stream *str, mu_off_t *psize) | ||
171 | { | ||
172 | struct _mu_xscript_stream *sp = (struct _mu_xscript_stream *)str; | ||
173 | return mu_stream_size (sp->transport, psize); | ||
174 | } | ||
175 | |||
176 | static int | ||
177 | _xscript_ctl (struct _mu_stream *str, int op, void *arg) | ||
178 | { | ||
179 | struct _mu_xscript_stream *sp = (struct _mu_xscript_stream *)str; | ||
180 | mu_transport_t *ptrans; | ||
181 | |||
182 | switch (op) | ||
183 | { | ||
184 | case MU_IOCTL_GET_TRANSPORT: | ||
185 | if (!arg) | ||
186 | return EINVAL; | ||
187 | ptrans = arg; | ||
188 | ptrans[0] = (mu_transport_t) sp->transport; | ||
189 | ptrans[1] = (mu_transport_t) sp->logstr; | ||
190 | break; | ||
191 | |||
192 | case MU_IOCTL_SET_TRANSPORT: | ||
193 | if (!arg) | ||
194 | return EINVAL; | ||
195 | ptrans = arg; | ||
196 | if (ptrans[0]) | ||
197 | sp->transport = (mu_stream_t) ptrans[0]; | ||
198 | if (ptrans[1]) | ||
199 | sp->logstr = (mu_stream_t) ptrans[1]; | ||
200 | break; | ||
201 | |||
202 | default: | ||
203 | return mu_stream_ioctl (sp->transport, op, arg); | ||
204 | } | ||
205 | return 0; | ||
206 | } | ||
207 | |||
208 | static int | ||
209 | _xscript_wait (struct _mu_stream *str, int *pflags, struct timeval *tvp) | ||
210 | { | ||
211 | struct _mu_xscript_stream *sp = (struct _mu_xscript_stream *)str; | ||
212 | return mu_stream_wait (sp->transport, pflags, tvp); | ||
213 | } | ||
214 | |||
215 | static int | ||
216 | _xscript_truncate (struct _mu_stream *str, mu_off_t size) | ||
217 | { | ||
218 | struct _mu_xscript_stream *sp = (struct _mu_xscript_stream *)str; | ||
219 | return mu_stream_truncate (sp->transport, size); | ||
220 | } | ||
221 | |||
222 | static int | ||
223 | _xscript_shutdown (struct _mu_stream *str, int how) | ||
224 | { | ||
225 | struct _mu_xscript_stream *sp = (struct _mu_xscript_stream *)str; | ||
226 | return mu_stream_shutdown (sp->transport, how); | ||
227 | } | ||
228 | |||
229 | static const char * | ||
230 | _xscript_error_string (struct _mu_stream *str, int rc) | ||
231 | { | ||
232 | struct _mu_xscript_stream *sp = (struct _mu_xscript_stream *)str; | ||
233 | const char *p = mu_stream_strerror (sp->transport, rc); | ||
234 | if (!p) | ||
235 | p = mu_strerror (rc); | ||
236 | return p; | ||
237 | } | ||
238 | |||
239 | const char *default_prefix[2] = { | ||
240 | "C: ", "S: " | ||
241 | }; | ||
242 | |||
243 | int | ||
244 | mu_xscript_stream_create(mu_stream_t *pref, mu_stream_t transport, | ||
245 | mu_stream_t logstr, | ||
246 | const char *prefix[]) | ||
247 | { | ||
248 | int flags; | ||
249 | struct _mu_xscript_stream *sp; | ||
250 | |||
251 | mu_stream_get_flags (transport, &flags); | ||
252 | sp = (struct _mu_xscript_stream *) _mu_stream_create (sizeof (*sp), flags); | ||
253 | if (!sp) | ||
254 | return ENOMEM; | ||
255 | |||
256 | sp->stream.read = _xscript_read; | ||
257 | sp->stream.readdelim = _xscript_readdelim; | ||
258 | sp->stream.write = _xscript_write; | ||
259 | sp->stream.flush = _xscript_flush; | ||
260 | sp->stream.open = _xscript_open; | ||
261 | sp->stream.close = _xscript_close; | ||
262 | sp->stream.done = _xscript_done; | ||
263 | sp->stream.seek = _xscript_seek; | ||
264 | sp->stream.size = _xscript_size; | ||
265 | sp->stream.ctl = _xscript_ctl; | ||
266 | sp->stream.wait = _xscript_wait; | ||
267 | sp->stream.truncate = _xscript_truncate; | ||
268 | sp->stream.shutdown = _xscript_shutdown; | ||
269 | sp->stream.error_string = _xscript_error_string; | ||
270 | |||
271 | mu_stream_ref (transport); | ||
272 | sp->transport = transport; | ||
273 | mu_stream_ref (logstr); | ||
274 | sp->logstr = logstr; | ||
275 | |||
276 | sp->flags = TRANS_READ | TRANS_WRITE; | ||
277 | if (prefix) | ||
278 | { | ||
279 | sp->prefix[0] = strdup(prefix[0] ? prefix[0] : default_prefix[0]); | ||
280 | sp->prefix[1] = strdup(prefix[1] ? prefix[1] : default_prefix[1]); | ||
281 | } | ||
282 | else | ||
283 | { | ||
284 | sp->prefix[0] = strdup(default_prefix[0]); | ||
285 | sp->prefix[1] = strdup(default_prefix[1]); | ||
286 | } | ||
287 | |||
288 | if (sp->prefix[0] == NULL || sp->prefix[1] == 0) | ||
289 | { | ||
290 | free (sp->prefix[0]); | ||
291 | free (sp->prefix[1]); | ||
292 | free (sp); | ||
293 | return ENOMEM; | ||
294 | } | ||
295 | mu_stream_set_buffer ((mu_stream_t) sp, mu_buffer_line, 1024); | ||
296 | *pref = (mu_stream_t) sp; | ||
297 | return 0; | ||
298 | } | ||
299 | |||
300 |
... | @@ -20,7 +20,7 @@ | ... | @@ -20,7 +20,7 @@ |
20 | #include "pop3d.h" | 20 | #include "pop3d.h" |
21 | #include "mailutils/libargp.h" | 21 | #include "mailutils/libargp.h" |
22 | 22 | ||
23 | mu_stream_t istream, ostream; | 23 | mu_stream_t iostream; |
24 | 24 | ||
25 | void | 25 | void |
26 | pop3d_parse_command (char *cmd, char **pcmd, char **parg) | 26 | pop3d_parse_command (char *cmd, char **pcmd, char **parg) |
... | @@ -132,12 +132,12 @@ pop3d_abquit (int reason) | ... | @@ -132,12 +132,12 @@ pop3d_abquit (int reason) |
132 | FIXME: This is sorta kludge: we could use MU_IOCTL_GET_TRANSPORT call | 132 | FIXME: This is sorta kludge: we could use MU_IOCTL_GET_TRANSPORT call |
133 | to retrieve the bottom-level stream, if filter streams supported it. | 133 | to retrieve the bottom-level stream, if filter streams supported it. |
134 | */ | 134 | */ |
135 | static mu_stream_t real_ostream; | 135 | static mu_stream_t real_istream, real_ostream; |
136 | 136 | ||
137 | void | 137 | void |
138 | pop3d_setio (FILE *in, FILE *out) | 138 | pop3d_setio (FILE *in, FILE *out) |
139 | { | 139 | { |
140 | mu_stream_t str; | 140 | mu_stream_t str, istream, ostream; |
141 | 141 | ||
142 | if (!in) | 142 | if (!in) |
143 | pop3d_abquit (ERR_NO_IFILE); | 143 | pop3d_abquit (ERR_NO_IFILE); |
... | @@ -147,6 +147,7 @@ pop3d_setio (FILE *in, FILE *out) | ... | @@ -147,6 +147,7 @@ pop3d_setio (FILE *in, FILE *out) |
147 | if (mu_stdio_stream_create (&istream, fileno (in), | 147 | if (mu_stdio_stream_create (&istream, fileno (in), |
148 | MU_STREAM_READ | MU_STREAM_NO_CLOSE)) | 148 | MU_STREAM_READ | MU_STREAM_NO_CLOSE)) |
149 | pop3d_abquit (ERR_NO_IFILE); | 149 | pop3d_abquit (ERR_NO_IFILE); |
150 | real_istream = istream; | ||
150 | mu_stream_set_buffer (istream, mu_buffer_line, 1024); | 151 | mu_stream_set_buffer (istream, mu_buffer_line, 1024); |
151 | 152 | ||
152 | if (mu_stdio_stream_create (&str, fileno (out), | 153 | if (mu_stdio_stream_create (&str, fileno (out), |
... | @@ -157,6 +158,32 @@ pop3d_setio (FILE *in, FILE *out) | ... | @@ -157,6 +158,32 @@ pop3d_setio (FILE *in, FILE *out) |
157 | MU_STREAM_WRITE | MU_STREAM_NO_CLOSE)) | 158 | MU_STREAM_WRITE | MU_STREAM_NO_CLOSE)) |
158 | pop3d_abquit (ERR_NO_IFILE); | 159 | pop3d_abquit (ERR_NO_IFILE); |
159 | mu_stream_set_buffer (ostream, mu_buffer_line, 1024); | 160 | mu_stream_set_buffer (ostream, mu_buffer_line, 1024); |
161 | |||
162 | if (mu_iostream_create (&iostream, istream, ostream, 0)) | ||
163 | pop3d_abquit (ERR_FILE); | ||
164 | if (pop3d_transcript) | ||
165 | { | ||
166 | int rc; | ||
167 | mu_debug_t debug; | ||
168 | mu_stream_t dstr, xstr; | ||
169 | |||
170 | mu_diag_get_debug (&debug); | ||
171 | |||
172 | rc = mu_dbgstream_create (&dstr, debug, MU_DIAG_DEBUG, | ||
173 | MU_STREAM_NO_CLOSE); | ||
174 | if (rc) | ||
175 | mu_error (_("cannot create debug stream; transcript disabled: %s"), | ||
176 | mu_strerror (rc)); | ||
177 | else | ||
178 | { | ||
179 | rc = mu_xscript_stream_create (&xstr, iostream, dstr, NULL); | ||
180 | if (rc) | ||
181 | mu_error (_("cannot create transcript stream: %s"), | ||
182 | mu_strerror (rc)); | ||
183 | else | ||
184 | iostream = xstr; | ||
185 | } | ||
186 | } | ||
160 | } | 187 | } |
161 | 188 | ||
162 | #ifdef WITH_TLS | 189 | #ifdef WITH_TLS |
... | @@ -166,37 +193,44 @@ pop3d_init_tls_server () | ... | @@ -166,37 +193,44 @@ pop3d_init_tls_server () |
166 | mu_stream_t stream; | 193 | mu_stream_t stream; |
167 | int rc; | 194 | int rc; |
168 | 195 | ||
169 | rc = mu_tls_server_stream_create (&stream, istream, real_ostream, 0); | 196 | rc = mu_tls_server_stream_create (&stream, real_istream, real_ostream, |
197 | MU_STREAM_NO_CLOSE); | ||
170 | if (rc) | 198 | if (rc) |
171 | return 0; | 199 | return 1; |
172 | 200 | ||
173 | rc = mu_stream_open (stream); | 201 | rc = mu_stream_open (stream); |
174 | if (rc) | 202 | if (rc) |
175 | { | 203 | { |
176 | mu_diag_output (MU_DIAG_ERROR, _("cannot open TLS stream: %s"), | 204 | mu_diag_output (MU_DIAG_ERROR, _("cannot open TLS stream: %s"), |
177 | mu_stream_strerror (stream, rc)); | 205 | mu_stream_strerror (stream, rc)); |
178 | return 0; | 206 | mu_stream_destroy (&stream); |
207 | return 1; | ||
179 | } | 208 | } |
180 | 209 | ||
181 | istream = stream; | 210 | if (mu_filter_create (&stream, stream, "rfc822", MU_FILTER_ENCODE, |
182 | mu_stream_destroy (&ostream); | 211 | MU_STREAM_WRITE | MU_STREAM_RDTHRU | |
183 | if (mu_filter_create (&ostream, stream, "rfc822", MU_FILTER_ENCODE, | 212 | MU_STREAM_NO_CLOSE)) |
184 | MU_STREAM_WRITE | MU_STREAM_NO_CLOSE)) | ||
185 | pop3d_abquit (ERR_NO_IFILE); | 213 | pop3d_abquit (ERR_NO_IFILE); |
186 | mu_stream_set_buffer (ostream, mu_buffer_line, 1024); | 214 | |
187 | return 1; | 215 | if (pop3d_transcript) |
216 | { | ||
217 | mu_transport_t trans[2]; | ||
218 | |||
219 | trans[0] = (mu_transport_t) stream; | ||
220 | trans[1] = NULL; | ||
221 | mu_stream_ioctl (iostream, MU_IOCTL_SET_TRANSPORT, trans); | ||
222 | } | ||
223 | else | ||
224 | iostream = stream; | ||
225 | return 0; | ||
188 | } | 226 | } |
189 | #endif | 227 | #endif |
190 | 228 | ||
191 | void | 229 | void |
192 | pop3d_bye () | 230 | pop3d_bye () |
193 | { | 231 | { |
194 | if (istream == ostream) | 232 | mu_stream_close (iostream); |
195 | { | 233 | mu_stream_destroy (&iostream); |
196 | mu_stream_close (istream); | ||
197 | mu_stream_destroy (&istream); | ||
198 | } | ||
199 | /* There's no reason closing in/out streams otherwise */ | ||
200 | #ifdef WITH_TLS | 234 | #ifdef WITH_TLS |
201 | if (tls_available) | 235 | if (tls_available) |
202 | mu_deinit_tls_libs (); | 236 | mu_deinit_tls_libs (); |
... | @@ -206,53 +240,28 @@ pop3d_bye () | ... | @@ -206,53 +240,28 @@ pop3d_bye () |
206 | void | 240 | void |
207 | pop3d_flush_output () | 241 | pop3d_flush_output () |
208 | { | 242 | { |
209 | mu_stream_flush (ostream); | 243 | mu_stream_flush (iostream); |
210 | } | 244 | } |
211 | 245 | ||
212 | int | 246 | int |
213 | pop3d_is_master () | 247 | pop3d_is_master () |
214 | { | 248 | { |
215 | return ostream == NULL; | 249 | return iostream == NULL; |
216 | } | ||
217 | |||
218 | static void | ||
219 | transcript (const char *pfx, const char *buf) | ||
220 | { | ||
221 | if (pop3d_transcript) | ||
222 | { | ||
223 | int len = strlen (buf); | ||
224 | if (len > 0 && buf[len-1] == '\n') | ||
225 | { | ||
226 | len--; | ||
227 | if (len > 0 && buf[len-1] == '\r') | ||
228 | len--; | ||
229 | } | ||
230 | mu_diag_output (MU_DIAG_DEBUG, "%s: %-.*s", pfx, len, buf); | ||
231 | } | ||
232 | } | 250 | } |
233 | 251 | ||
234 | void | 252 | void |
235 | pop3d_outf (const char *fmt, ...) | 253 | pop3d_outf (const char *fmt, ...) |
236 | { | 254 | { |
237 | va_list ap; | 255 | va_list ap; |
238 | char *buf; | ||
239 | int rc; | 256 | int rc; |
240 | 257 | ||
241 | va_start (ap, fmt); | 258 | va_start (ap, fmt); |
242 | vasprintf (&buf, fmt, ap); | 259 | rc = mu_stream_vprintf (iostream, fmt, ap); |
243 | va_end (ap); | 260 | va_end (ap); |
244 | |||
245 | if (!buf) | ||
246 | pop3d_abquit (ERR_NO_MEM); | ||
247 | |||
248 | transcript ("sent", buf); | ||
249 | |||
250 | rc = mu_stream_write (ostream, buf, strlen (buf), NULL); | ||
251 | free (buf); | ||
252 | if (rc) | 261 | if (rc) |
253 | { | 262 | { |
254 | mu_diag_output (MU_DIAG_ERROR, _("Write failed: %s"), | 263 | mu_diag_output (MU_DIAG_ERROR, _("Write failed: %s"), |
255 | mu_stream_strerror (ostream, rc)); | 264 | mu_stream_strerror (iostream, rc)); |
256 | pop3d_abquit (ERR_IO); | 265 | pop3d_abquit (ERR_IO); |
257 | } | 266 | } |
258 | } | 267 | } |
... | @@ -265,13 +274,13 @@ pop3d_readline (char *buffer, size_t size) | ... | @@ -265,13 +274,13 @@ pop3d_readline (char *buffer, size_t size) |
265 | size_t nbytes; | 274 | size_t nbytes; |
266 | 275 | ||
267 | alarm (idle_timeout); | 276 | alarm (idle_timeout); |
268 | rc = mu_stream_readline (istream, buffer, size, &nbytes); | 277 | rc = mu_stream_readline (iostream, buffer, size, &nbytes); |
269 | alarm (0); | 278 | alarm (0); |
270 | 279 | ||
271 | if (rc) | 280 | if (rc) |
272 | { | 281 | { |
273 | mu_diag_output (MU_DIAG_ERROR, _("Read failed: %s"), | 282 | mu_diag_output (MU_DIAG_ERROR, _("Read failed: %s"), |
274 | mu_stream_strerror (ostream, rc)); | 283 | mu_stream_strerror (iostream, rc)); |
275 | pop3d_abquit (ERR_IO); | 284 | pop3d_abquit (ERR_IO); |
276 | } | 285 | } |
277 | else if (nbytes == 0) | 286 | else if (nbytes == 0) |
... | @@ -285,8 +294,6 @@ pop3d_readline (char *buffer, size_t size) | ... | @@ -285,8 +294,6 @@ pop3d_readline (char *buffer, size_t size) |
285 | pop3d_abquit (ERR_PROTO); | 294 | pop3d_abquit (ERR_PROTO); |
286 | } | 295 | } |
287 | 296 | ||
288 | transcript ("recv", buffer); | ||
289 | |||
290 | return buffer; | 297 | return buffer; |
291 | } | 298 | } |
292 | 299 | ... | ... |
... | @@ -189,7 +189,7 @@ struct pop3d_command | ... | @@ -189,7 +189,7 @@ struct pop3d_command |
189 | pop3d_command_handler_t handler; | 189 | pop3d_command_handler_t handler; |
190 | }; | 190 | }; |
191 | 191 | ||
192 | extern mu_stream_t istream, ostream; | 192 | extern mu_stream_t iostream; |
193 | extern mu_pop_server_t pop3srv; | 193 | extern mu_pop_server_t pop3srv; |
194 | extern mu_mailbox_t mbox; | 194 | extern mu_mailbox_t mbox; |
195 | extern int state; | 195 | extern int state; | ... | ... |
... | @@ -46,7 +46,7 @@ pop3d_retr (char *arg) | ... | @@ -46,7 +46,7 @@ pop3d_retr (char *arg) |
46 | return ERR_UNKNOWN; | 46 | return ERR_UNKNOWN; |
47 | 47 | ||
48 | pop3d_outf ("+OK\n"); | 48 | pop3d_outf ("+OK\n"); |
49 | mu_stream_copy (ostream, stream, 0); | 49 | mu_stream_copy (iostream, stream, 0); |
50 | mu_stream_destroy (&stream); | 50 | mu_stream_destroy (&stream); |
51 | 51 | ||
52 | if (!mu_attribute_is_read (attr)) | 52 | if (!mu_attribute_is_read (attr)) | ... | ... |
... | @@ -35,7 +35,7 @@ pop3d_stls (char *arg) | ... | @@ -35,7 +35,7 @@ pop3d_stls (char *arg) |
35 | pop3d_outf ("+OK Begin TLS negotiation\n"); | 35 | pop3d_outf ("+OK Begin TLS negotiation\n"); |
36 | pop3d_flush_output (); | 36 | pop3d_flush_output (); |
37 | 37 | ||
38 | tls_done = pop3d_init_tls_server (); | 38 | tls_done = pop3d_init_tls_server () == 0; |
39 | 39 | ||
40 | if (!tls_done) | 40 | if (!tls_done) |
41 | { | 41 | { | ... | ... |
... | @@ -62,7 +62,7 @@ pop3d_top (char *arg) | ... | @@ -62,7 +62,7 @@ pop3d_top (char *arg) |
62 | return ERR_UNKNOWN; | 62 | return ERR_UNKNOWN; |
63 | pop3d_outf ("+OK\n"); | 63 | pop3d_outf ("+OK\n"); |
64 | 64 | ||
65 | mu_stream_copy (ostream, stream, 0); | 65 | mu_stream_copy (iostream, stream, 0); |
66 | pop3d_outf ("\n"); | 66 | pop3d_outf ("\n"); |
67 | mu_stream_destroy (&stream); | 67 | mu_stream_destroy (&stream); |
68 | 68 | ... | ... |
-
Please register or sign in to post a comment