Commit 29d2e390 29d2e3904c897c01191072db85985b93f9ea1704 by Sergey Poznyakoff

Implement an ioctl for replace bottom-level transport layers in a stream chain.

* include/mailutils/stream.h (MU_IOCTL_SWAP_STREAM): New ioctl op.
(mu_stream_seterr): New function.
* include/mailutils/sys/stream.h (_MU_SWAP_FIRST_ONLY)
(_MU_SWAP_IOCTL_MUST_SUCCEED): New defines.
(_mu_stream_swap_streams): New proto.
* mailbox/amd.c (amd_body_stream_read): Always update *pnread.
* mailbox/errors (MU_ERR_NO_TRANSPORT): New error code.

* mailbox/stream.c (_stream_seterror): Rename to mu_stream_seterr,
remove static qualifier. All uses updated.
(_mu_stream_swap_streams): New function.

* mailbox/filter_iconv.c (_icvt_ioctl): Implement MU_IOCTL_SWAP_STREAM.
* mailbox/iostream.c (_iostream_ctl): Likewise.
* mailbox/xscript-stream.c (_xscript_ctl): Likewise.

* pop3d/extra.c (real_istream, real_ostream): Remove statics.
(pop3d_init_tls_server): Use MU_IOCTL_SWAP_STREAM to replace
bottom-level transport layers without recreating the entire stream
chain.
1 parent baea3184
...@@ -32,8 +32,6 @@ enum mu_buffer_type ...@@ -32,8 +32,6 @@ enum mu_buffer_type
32 #define MU_SEEK_CUR 1 32 #define MU_SEEK_CUR 1
33 #define MU_SEEK_END 2 33 #define MU_SEEK_END 2
34 34
35 #define MU_STREAM_NO_CHECK 0 /* for backward compatibility */
36
37 #define MU_STREAM_READ 0x00000001 35 #define MU_STREAM_READ 0x00000001
38 #define MU_STREAM_WRITE 0x00000002 36 #define MU_STREAM_WRITE 0x00000002
39 #define MU_STREAM_RDWR (MU_STREAM_READ|MU_STREAM_WRITE) 37 #define MU_STREAM_RDWR (MU_STREAM_READ|MU_STREAM_WRITE)
...@@ -63,6 +61,7 @@ enum mu_buffer_type ...@@ -63,6 +61,7 @@ enum mu_buffer_type
63 #define MU_IOCTL_ABRIDGE_SEEK MU_IOCTL_SET_SEEK_LIMITS 61 #define MU_IOCTL_ABRIDGE_SEEK MU_IOCTL_SET_SEEK_LIMITS
64 #define MU_IOCTL_GET_SEEK_LIMITS 5 62 #define MU_IOCTL_GET_SEEK_LIMITS 5
65 #define MU_IOCTL_SET_TRANSPORT 6 63 #define MU_IOCTL_SET_TRANSPORT 6
64 #define MU_IOCTL_SWAP_STREAM 7
66 65
67 void mu_stream_ref (mu_stream_t stream); 66 void mu_stream_ref (mu_stream_t stream);
68 void mu_stream_unref (mu_stream_t stream); 67 void mu_stream_unref (mu_stream_t stream);
...@@ -72,6 +71,8 @@ const char *mu_stream_strerror (mu_stream_t stream, int rc); ...@@ -72,6 +71,8 @@ const char *mu_stream_strerror (mu_stream_t stream, int rc);
72 int mu_stream_err (mu_stream_t stream); 71 int mu_stream_err (mu_stream_t stream);
73 int mu_stream_last_error (mu_stream_t stream); 72 int mu_stream_last_error (mu_stream_t stream);
74 void mu_stream_clearerr (mu_stream_t stream); 73 void mu_stream_clearerr (mu_stream_t stream);
74 int mu_stream_seterr (struct _mu_stream *stream, int code, int perm);
75
75 int mu_stream_eof (mu_stream_t stream); 76 int mu_stream_eof (mu_stream_t stream);
76 int mu_stream_seek (mu_stream_t stream, mu_off_t offset, int whence, 77 int mu_stream_seek (mu_stream_t stream, mu_off_t offset, int whence,
77 mu_off_t *pres); 78 mu_off_t *pres);
......
...@@ -65,4 +65,11 @@ int mu_stream_write_unbuffered (mu_stream_t stream, ...@@ -65,4 +65,11 @@ int mu_stream_write_unbuffered (mu_stream_t stream,
65 const void *buf, size_t size, 65 const void *buf, size_t size,
66 int full_write, size_t *pnwritten); 66 int full_write, size_t *pnwritten);
67 67
68 #define _MU_SWAP_FIRST_ONLY 0x01
69 #define _MU_SWAP_IOCTL_MUST_SUCCEED 0x02
70
71 int _mu_stream_swap_streams (mu_stream_t stream, mu_stream_t *curtrans,
72 mu_stream_t *newtrans, int flags);
73
74
68 #endif 75 #endif
......
...@@ -679,7 +679,7 @@ _mu_tls_stream_create (mu_stream_t *pstream, ...@@ -679,7 +679,7 @@ _mu_tls_stream_create (mu_stream_t *pstream,
679 free (sp); 679 free (sp);
680 return rc; 680 return rc;
681 } 681 }
682 682
683 rc = _mu_tls_io_stream_create (&sp->transport[1], strout, 683 rc = _mu_tls_io_stream_create (&sp->transport[1], strout,
684 MU_STREAM_WRITE | autoclose, sp); 684 MU_STREAM_WRITE | autoclose, sp);
685 if (rc) 685 if (rc)
...@@ -688,7 +688,7 @@ _mu_tls_stream_create (mu_stream_t *pstream, ...@@ -688,7 +688,7 @@ _mu_tls_stream_create (mu_stream_t *pstream,
688 free (sp->transport[0]); 688 free (sp->transport[0]);
689 return rc; 689 return rc;
690 } 690 }
691 691
692 mu_stream_set_buffer ((mu_stream_t) sp, mu_buffer_line, 1024); 692 mu_stream_set_buffer ((mu_stream_t) sp, mu_buffer_line, 1024);
693 *pstream = (mu_stream_t) sp; 693 *pstream = (mu_stream_t) sp;
694 return 0; 694 return 0;
......
...@@ -1604,8 +1604,7 @@ amd_body_stream_read (mu_stream_t is, char *buffer, size_t buflen, ...@@ -1604,8 +1604,7 @@ amd_body_stream_read (mu_stream_t is, char *buffer, size_t buflen,
1604 1604
1605 if (buffer == NULL || buflen == 0) 1605 if (buffer == NULL || buflen == 0)
1606 { 1606 {
1607 if (pnread) 1607 *pnread = nread;
1608 *pnread = nread;
1609 return 0; 1608 return 0;
1610 } 1609 }
1611 1610
...@@ -1626,11 +1625,11 @@ amd_body_stream_read (mu_stream_t is, char *buffer, size_t buflen, ...@@ -1626,11 +1625,11 @@ amd_body_stream_read (mu_stream_t is, char *buffer, size_t buflen,
1626 { 1625 {
1627 status = mu_stream_read (mhm->stream, buffer, nread, &nread); 1626 status = mu_stream_read (mhm->stream, buffer, nread, &nread);
1628 amdstr->off += nread; 1627 amdstr->off += nread;
1629 if (pnread)
1630 *pnread = nread;
1631 } 1628 }
1632 } 1629 }
1633 1630
1631 *pnread = nread;
1632
1634 mu_monitor_unlock (mhm->amd->mailbox->monitor); 1633 mu_monitor_unlock (mhm->amd->mailbox->monitor);
1635 #ifdef WITH_PTHREAD 1634 #ifdef WITH_PTHREAD
1636 pthread_cleanup_pop (0); 1635 pthread_cleanup_pop (0);
......
...@@ -83,3 +83,5 @@ MU_ERR_NO_INTERFACE _("No such interface") ...@@ -83,3 +83,5 @@ MU_ERR_NO_INTERFACE _("No such interface")
83 MU_ERR_BADOP _("Inappropriate operation for this mode") 83 MU_ERR_BADOP _("Inappropriate operation for this mode")
84 MU_ERR_BAD_FILENAME _("Badly formed file or directory name") 84 MU_ERR_BAD_FILENAME _("Badly formed file or directory name")
85 MU_ERR_READ _("Read error") 85 MU_ERR_READ _("Read error")
86
87 MU_ERR_NO_TRANSPORT _("Transport stream not set")
......
...@@ -400,6 +400,9 @@ _icvt_ioctl (mu_stream_t stream, int code, void *ptr) ...@@ -400,6 +400,9 @@ _icvt_ioctl (mu_stream_t stream, int code, void *ptr)
400 ptrans[1] = NULL; 400 ptrans[1] = NULL;
401 break; 401 break;
402 402
403 case MU_IOCTL_SWAP_STREAM:
404 return mu_stream_ioctl (s->transport, code, ptr);
405
403 default: 406 default:
404 return EINVAL; 407 return EINVAL;
405 } 408 }
......
...@@ -148,6 +148,11 @@ _iostream_ctl (struct _mu_stream *str, int op, void *arg) ...@@ -148,6 +148,11 @@ _iostream_ctl (struct _mu_stream *str, int op, void *arg)
148 sp->transport[_MU_STREAM_INPUT] = (mu_stream_t) ptrans[0]; 148 sp->transport[_MU_STREAM_INPUT] = (mu_stream_t) ptrans[0];
149 sp->transport[_MU_STREAM_OUTPUT] = (mu_stream_t) ptrans[1]; 149 sp->transport[_MU_STREAM_OUTPUT] = (mu_stream_t) ptrans[1];
150 break; 150 break;
151
152 case MU_IOCTL_SWAP_STREAM:
153 if (!arg)
154 return EINVAL;
155 return _mu_stream_swap_streams (str, sp->transport, arg, 0);
151 156
152 default: 157 default:
153 return EINVAL; 158 return EINVAL;
......
...@@ -32,8 +32,8 @@ ...@@ -32,8 +32,8 @@
32 #include <mailutils/stream.h> 32 #include <mailutils/stream.h>
33 #include <mailutils/sys/stream.h> 33 #include <mailutils/sys/stream.h>
34 34
35 static int 35 int
36 _stream_seterror (struct _mu_stream *stream, int code, int perm) 36 mu_stream_seterr (struct _mu_stream *stream, int code, int perm)
37 { 37 {
38 stream->last_err = code; 38 stream->last_err = code;
39 switch (code) 39 switch (code)
...@@ -236,7 +236,7 @@ mu_stream_open (mu_stream_t stream) ...@@ -236,7 +236,7 @@ mu_stream_open (mu_stream_t stream)
236 int rc; 236 int rc;
237 237
238 if (stream->open && (rc = stream->open (stream))) 238 if (stream->open && (rc = stream->open (stream)))
239 return _stream_seterror (stream, rc, 1); 239 return mu_stream_seterr (stream, rc, 1);
240 stream->bytes_in = stream->bytes_out = 0; 240 stream->bytes_in = stream->bytes_out = 0;
241 return 0; 241 return 0;
242 } 242 }
...@@ -286,10 +286,10 @@ mu_stream_seek (mu_stream_t stream, mu_off_t offset, int whence, ...@@ -286,10 +286,10 @@ mu_stream_seek (mu_stream_t stream, mu_off_t offset, int whence,
286 mu_off_t size; 286 mu_off_t size;
287 287
288 if (!stream->seek) 288 if (!stream->seek)
289 return _stream_seterror (stream, ENOSYS, 0); 289 return mu_stream_seterr (stream, ENOSYS, 0);
290 290
291 if (!(stream->flags & MU_STREAM_SEEK)) 291 if (!(stream->flags & MU_STREAM_SEEK))
292 return _stream_seterror (stream, EACCES, 1); 292 return mu_stream_seterr (stream, EACCES, 1);
293 293
294 switch (whence) 294 switch (whence)
295 { 295 {
...@@ -308,12 +308,12 @@ mu_stream_seek (mu_stream_t stream, mu_off_t offset, int whence, ...@@ -308,12 +308,12 @@ mu_stream_seek (mu_stream_t stream, mu_off_t offset, int whence,
308 case MU_SEEK_END: 308 case MU_SEEK_END:
309 rc = mu_stream_size (stream, &size); 309 rc = mu_stream_size (stream, &size);
310 if (rc) 310 if (rc)
311 return _stream_seterror (stream, rc, 1); 311 return mu_stream_seterr (stream, rc, 1);
312 offset += size; 312 offset += size;
313 break; 313 break;
314 314
315 default: 315 default:
316 return _stream_seterror (stream, EINVAL, 1); 316 return mu_stream_seterr (stream, EINVAL, 1);
317 } 317 }
318 318
319 if (stream->buftype == mu_buffer_none 319 if (stream->buftype == mu_buffer_none
...@@ -326,7 +326,7 @@ mu_stream_seek (mu_stream_t stream, mu_off_t offset, int whence, ...@@ -326,7 +326,7 @@ mu_stream_seek (mu_stream_t stream, mu_off_t offset, int whence,
326 if (rc == ESPIPE) 326 if (rc == ESPIPE)
327 return rc; 327 return rc;
328 if (rc) 328 if (rc)
329 return _stream_seterror (stream, rc, 1); 329 return mu_stream_seterr (stream, rc, 1);
330 _stream_cleareof (stream); 330 _stream_cleareof (stream);
331 } 331 }
332 332
...@@ -352,7 +352,7 @@ mu_stream_skip_input_bytes (mu_stream_t stream, mu_off_t count, mu_off_t *pres) ...@@ -352,7 +352,7 @@ mu_stream_skip_input_bytes (mu_stream_t stream, mu_off_t count, mu_off_t *pres)
352 int rc; 352 int rc;
353 353
354 if (!(stream->flags & MU_STREAM_READ)) 354 if (!(stream->flags & MU_STREAM_READ))
355 return _stream_seterror (stream, EACCES, 1); 355 return mu_stream_seterr (stream, EACCES, 1);
356 356
357 if (stream->buftype == mu_buffer_none) 357 if (stream->buftype == mu_buffer_none)
358 { 358 {
...@@ -426,7 +426,7 @@ mu_stream_set_buffer (mu_stream_t stream, enum mu_buffer_type type, ...@@ -426,7 +426,7 @@ mu_stream_set_buffer (mu_stream_t stream, enum mu_buffer_type type,
426 if (stream->buffer == NULL) 426 if (stream->buffer == NULL)
427 { 427 {
428 stream->buftype = mu_buffer_none; 428 stream->buftype = mu_buffer_none;
429 return _stream_seterror (stream, ENOMEM, 1); 429 return mu_stream_seterr (stream, ENOMEM, 1);
430 } 430 }
431 stream->bufsize = size; 431 stream->bufsize = size;
432 stream->cur = stream->buffer; 432 stream->cur = stream->buffer;
...@@ -444,10 +444,10 @@ mu_stream_read_unbuffered (mu_stream_t stream, void *buf, size_t size, ...@@ -444,10 +444,10 @@ mu_stream_read_unbuffered (mu_stream_t stream, void *buf, size_t size,
444 size_t nread; 444 size_t nread;
445 445
446 if (!stream->read) 446 if (!stream->read)
447 return _stream_seterror (stream, ENOSYS, 0); 447 return mu_stream_seterr (stream, ENOSYS, 0);
448 448
449 if (!(stream->flags & MU_STREAM_READ)) 449 if (!(stream->flags & MU_STREAM_READ))
450 return _stream_seterror (stream, EACCES, 1); 450 return mu_stream_seterr (stream, EACCES, 1);
451 451
452 if (stream->flags & _MU_STR_ERR) 452 if (stream->flags & _MU_STR_ERR)
453 return stream->last_err; 453 return stream->last_err;
...@@ -479,7 +479,7 @@ mu_stream_read_unbuffered (mu_stream_t stream, void *buf, size_t size, ...@@ -479,7 +479,7 @@ mu_stream_read_unbuffered (mu_stream_t stream, void *buf, size_t size,
479 479
480 } 480 }
481 if (size && rc) 481 if (size && rc)
482 rc = _stream_seterror (stream, rc, 0); 482 rc = mu_stream_seterr (stream, rc, 0);
483 } 483 }
484 else 484 else
485 { 485 {
...@@ -490,7 +490,7 @@ mu_stream_read_unbuffered (mu_stream_t stream, void *buf, size_t size, ...@@ -490,7 +490,7 @@ mu_stream_read_unbuffered (mu_stream_t stream, void *buf, size_t size,
490 stream->flags |= _MU_STR_EOF; 490 stream->flags |= _MU_STR_EOF;
491 stream->bytes_in += nread; 491 stream->bytes_in += nread;
492 } 492 }
493 _stream_seterror (stream, rc, rc != 0); 493 mu_stream_seterr (stream, rc, rc != 0);
494 } 494 }
495 stream->offset += nread; 495 stream->offset += nread;
496 if (pnread) 496 if (pnread)
...@@ -509,10 +509,10 @@ mu_stream_write_unbuffered (mu_stream_t stream, ...@@ -509,10 +509,10 @@ mu_stream_write_unbuffered (mu_stream_t stream,
509 size_t nwritten; 509 size_t nwritten;
510 510
511 if (!stream->write) 511 if (!stream->write)
512 return _stream_seterror (stream, ENOSYS, 0); 512 return mu_stream_seterr (stream, ENOSYS, 0);
513 513
514 if (!(stream->flags & MU_STREAM_WRITE)) 514 if (!(stream->flags & MU_STREAM_WRITE))
515 return _stream_seterror (stream, EACCES, 1); 515 return mu_stream_seterr (stream, EACCES, 1);
516 516
517 if (stream->flags & _MU_STR_ERR) 517 if (stream->flags & _MU_STR_ERR)
518 return stream->last_err; 518 return stream->last_err;
...@@ -555,7 +555,7 @@ mu_stream_write_unbuffered (mu_stream_t stream, ...@@ -555,7 +555,7 @@ mu_stream_write_unbuffered (mu_stream_t stream,
555 stream->offset += nwritten; 555 stream->offset += nwritten;
556 if (pnwritten) 556 if (pnwritten)
557 *pnwritten = nwritten; 557 *pnwritten = nwritten;
558 _stream_seterror (stream, rc, rc != 0); 558 mu_stream_seterr (stream, rc, rc != 0);
559 return rc; 559 return rc;
560 } 560 }
561 561
...@@ -861,9 +861,9 @@ mu_stream_size (mu_stream_t stream, mu_off_t *psize) ...@@ -861,9 +861,9 @@ mu_stream_size (mu_stream_t stream, mu_off_t *psize)
861 int rc; 861 int rc;
862 862
863 if (!stream->size) 863 if (!stream->size)
864 return _stream_seterror (stream, ENOSYS, 0); 864 return mu_stream_seterr (stream, ENOSYS, 0);
865 rc = stream->size (stream, psize); 865 rc = stream->size (stream, psize);
866 return _stream_seterror (stream, rc, rc != 0); 866 return mu_stream_seterr (stream, rc, rc != 0);
867 } 867 }
868 868
869 mu_off_t 869 mu_off_t
...@@ -948,8 +948,88 @@ mu_stream_clr_flags (mu_stream_t stream, int fl) ...@@ -948,8 +948,88 @@ mu_stream_clr_flags (mu_stream_t stream, int fl)
948 return 0; 948 return 0;
949 } 949 }
950 950
951 static void
952 swapstr (mu_stream_t stream, mu_stream_t *curstr, mu_stream_t *newstr)
953 {
954 mu_stream_t tmp;
955
956 tmp = *newstr;
957 *newstr = *curstr;
958 *curstr = tmp;
959 if (!(stream->flags & MU_STREAM_AUTOCLOSE))
960 {
961 if (*newstr)
962 mu_stream_unref (*newstr);
963 if (tmp)
964 mu_stream_ref (tmp);
965 }
966 if (!tmp)
967 mu_stream_seterr (stream, MU_ERR_NO_TRANSPORT, 1);
968 else if (stream->last_err == MU_ERR_NO_TRANSPORT)
969 mu_stream_clearerr (stream);
970 }
951 971
972 static int
973 swapstr_recursive (mu_stream_t stream, mu_stream_t *curstr,
974 mu_stream_t *newstr, int flags)
975 {
976 mu_stream_t strtab[2];
977 int rc = ENOSYS;
952 978
979 if (*curstr == NULL && *newstr == NULL)
980 return 0;
981
982 if (*curstr)
983 {
984 strtab[0] = *newstr;
985 strtab[1] = NULL;
986 rc = mu_stream_ioctl (*curstr, MU_IOCTL_SWAP_STREAM, strtab);
987 if (rc)
988 {
989 if ((flags & _MU_SWAP_IOCTL_MUST_SUCCEED)
990 || !(rc == ENOSYS || rc == EINVAL))
991 return rc;
992 }
993 }
994 if (rc == 0)
995 *newstr = strtab[0];
996 else
997 swapstr (stream, curstr, newstr);
998 return 0;
999 }
1000
1001 /* CURTRANS[2] contains I/O transport streams used by STREAM,
1002 NEWTRANS[2] contains another pair of streams.
1003 This function swaps the items of these two arrays using the
1004 MU_IOCTL_SWAP_STREAM ioctl. It is intended for use by STREAM's
1005 ioctl method and is currently used by iostream.c */
1006
1007 int
1008 _mu_stream_swap_streams (mu_stream_t stream, mu_stream_t *curtrans,
1009 mu_stream_t *newtrans, int flags)
1010 {
1011 int rc;
1012
1013 rc = swapstr_recursive (stream, &curtrans[0], &newtrans[0], flags);
1014 if (rc)
1015 return rc;
1016 if (flags & _MU_SWAP_FIRST_ONLY)
1017 return 0;
1018 rc = swapstr_recursive (stream, &curtrans[1], &newtrans[1], flags);
1019 if (rc)
1020 {
1021 int rc1 = swapstr_recursive (stream, &curtrans[0], &newtrans[0], flags);
1022 if (rc1)
1023 {
1024 mu_diag_output (MU_DIAG_CRIT,
1025 _("restoring streams on %p failed: %s"),
1026 stream, mu_strerror (rc1));
1027 abort ();
1028 }
1029 }
1030 return rc;
1031 }
1032
953 1033
954 1034
955 1035
......
...@@ -176,7 +176,8 @@ _xscript_ctl (struct _mu_stream *str, int op, void *arg) ...@@ -176,7 +176,8 @@ _xscript_ctl (struct _mu_stream *str, int op, void *arg)
176 { 176 {
177 struct _mu_xscript_stream *sp = (struct _mu_xscript_stream *)str; 177 struct _mu_xscript_stream *sp = (struct _mu_xscript_stream *)str;
178 mu_transport_t *ptrans; 178 mu_transport_t *ptrans;
179 179 mu_stream_t strtab[2];
180
180 switch (op) 181 switch (op)
181 { 182 {
182 case MU_IOCTL_GET_TRANSPORT: 183 case MU_IOCTL_GET_TRANSPORT:
...@@ -196,7 +197,9 @@ _xscript_ctl (struct _mu_stream *str, int op, void *arg) ...@@ -196,7 +197,9 @@ _xscript_ctl (struct _mu_stream *str, int op, void *arg)
196 if (ptrans[1]) 197 if (ptrans[1])
197 sp->logstr = (mu_stream_t) ptrans[1]; 198 sp->logstr = (mu_stream_t) ptrans[1];
198 break; 199 break;
199 200
201 case MU_IOCTL_SWAP_STREAM:
202 /* fall through */
200 default: 203 default:
201 return mu_stream_ioctl (sp->transport, op, arg); 204 return mu_stream_ioctl (sp->transport, op, arg);
202 } 205 }
......
...@@ -126,14 +126,6 @@ pop3d_abquit (int reason) ...@@ -126,14 +126,6 @@ pop3d_abquit (int reason)
126 exit (code); 126 exit (code);
127 } 127 }
128 128
129 /* Keeps the *real* output stream. Ostream is a RFC822 filter built over
130 real_ostream, or even over a TLS stream, which in turn is based on this
131 real_ostream.
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.
134 */
135 static mu_stream_t real_istream, real_ostream;
136
137 void 129 void
138 pop3d_setio (FILE *in, FILE *out) 130 pop3d_setio (FILE *in, FILE *out)
139 { 131 {
...@@ -147,20 +139,24 @@ pop3d_setio (FILE *in, FILE *out) ...@@ -147,20 +139,24 @@ pop3d_setio (FILE *in, FILE *out)
147 if (mu_stdio_stream_create (&istream, fileno (in), 139 if (mu_stdio_stream_create (&istream, fileno (in),
148 MU_STREAM_READ | MU_STREAM_AUTOCLOSE)) 140 MU_STREAM_READ | MU_STREAM_AUTOCLOSE))
149 pop3d_abquit (ERR_NO_IFILE); 141 pop3d_abquit (ERR_NO_IFILE);
150 real_istream = istream;
151 mu_stream_set_buffer (istream, mu_buffer_line, 1024); 142 mu_stream_set_buffer (istream, mu_buffer_line, 1024);
152 143
153 if (mu_stdio_stream_create (&str, fileno (out), 144 if (mu_stdio_stream_create (&ostream, fileno (out),
154 MU_STREAM_WRITE | MU_STREAM_AUTOCLOSE)) 145 MU_STREAM_WRITE | MU_STREAM_AUTOCLOSE))
155 pop3d_abquit (ERR_NO_OFILE); 146 pop3d_abquit (ERR_NO_OFILE);
156 real_ostream = str;
157 if (mu_filter_create (&ostream, str, "rfc822", MU_FILTER_ENCODE,
158 MU_STREAM_WRITE))
159 pop3d_abquit (ERR_NO_IFILE);
160 mu_stream_set_buffer (ostream, mu_buffer_line, 1024);
161 147
162 if (mu_iostream_create (&iostream, istream, ostream)) 148 /* Combine the two streams into an I/O one. */
149 if (mu_iostream_create (&str, istream, ostream))
163 pop3d_abquit (ERR_FILE); 150 pop3d_abquit (ERR_FILE);
151
152 /* Convert all writes to CRLF form.
153 There is no need to convert reads, as the code ignores extra \r anyway.
154 This also installs an extra full buffering, which is needed for TLS
155 code (see below). */
156 if (mu_filter_create (&iostream, str, "rfc822", MU_FILTER_ENCODE,
157 MU_STREAM_WRITE | MU_STREAM_RDTHRU))
158 pop3d_abquit (ERR_NO_IFILE);
159
164 if (pop3d_transcript) 160 if (pop3d_transcript)
165 { 161 {
166 int rc; 162 int rc;
...@@ -192,36 +188,40 @@ pop3d_setio (FILE *in, FILE *out) ...@@ -192,36 +188,40 @@ pop3d_setio (FILE *in, FILE *out)
192 int 188 int
193 pop3d_init_tls_server () 189 pop3d_init_tls_server ()
194 { 190 {
195 mu_stream_t stream; 191 mu_stream_t tlsstream, stream[2];
196 int rc; 192 int rc;
197 193
198 rc = mu_tls_server_stream_create (&stream, real_istream, real_ostream, 0); 194 stream[0] = stream[1] = NULL;
195 rc = mu_stream_ioctl (iostream, MU_IOCTL_SWAP_STREAM, stream);
196 if (rc)
197 {
198 mu_error (_("%s failed: %s"), "MU_IOCTL_SWAP_STREAM",
199 mu_stream_strerror (iostream, rc));
200 return 1;
201 }
202
203 rc = mu_tls_server_stream_create (&tlsstream, stream[0], stream[1], 0);
199 if (rc) 204 if (rc)
200 return 1; 205 return 1;
201 206
202 rc = mu_stream_open (stream); 207 rc = mu_stream_open (tlsstream);
203 if (rc) 208 if (rc)
204 { 209 {
205 mu_diag_output (MU_DIAG_ERROR, _("cannot open TLS stream: %s"), 210 mu_diag_output (MU_DIAG_ERROR, _("cannot open TLS stream: %s"),
206 mu_stream_strerror (stream, rc)); 211 mu_stream_strerror (tlsstream, rc));
207 mu_stream_destroy (&stream); 212 mu_stream_destroy (&tlsstream);
208 return 1; 213 return 1;
209 } 214 }
215 else
216 stream[0] = stream[1] = tlsstream;
210 217
211 if (mu_filter_create (&stream, stream, "rfc822", MU_FILTER_ENCODE, 218 rc = mu_stream_ioctl (iostream, MU_IOCTL_SWAP_STREAM, stream);
212 MU_STREAM_WRITE | MU_STREAM_RDTHRU)) 219 if (rc)
213 pop3d_abquit (ERR_NO_IFILE);
214
215 if (pop3d_transcript)
216 { 220 {
217 mu_transport_t trans[2]; 221 mu_error (_("%s failed: %s"), "MU_IOCTL_SWAP_STREAM",
218 222 mu_stream_strerror (iostream, rc));
219 trans[0] = (mu_transport_t) stream; 223 pop3d_abquit (ERR_IO);
220 trans[1] = NULL;
221 mu_stream_ioctl (iostream, MU_IOCTL_SET_TRANSPORT, trans);
222 } 224 }
223 else
224 iostream = stream;
225 return 0; 225 return 0;
226 } 226 }
227 #endif 227 #endif
......