Commit 814b9791 814b97914c8ac0177af4688e934511912733c314 by Sergey Poznyakoff

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.
1 parent cab81060
...@@ -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
......
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
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
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=
......
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;
......
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:
......
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
......