Commit 1e4c4488 1e4c44886b7dd9d9995f60ae038e04b08ecbd786 by Sergey Poznyakoff

Initialize standard I/O streams statically.

This allows programmers to use them right away, much like their stdio
counterparts.  The mu_stdstream_setup and friends can be used to
re-initialize them, should the need be.

* include/mailutils/sys/file_stream.h
(_MU_FILE_STREAM_STATIC_FILENAME): New flag.
(_mu_file_stream_setup): New proto.
* include/mailutils/sys/logstream.h (_mu_log_stream_setup): New proto.
* include/mailutils/sys/stream.h (_MU_STR_EVENT_BOOTSTRAP): New event
code.
(_mu_stream) <destroy>: New method.
* libmailutils/stdstream/basestr.c: Define the three standard streams
statically, use bootstrap event to initialize them.
* libmailutils/stdstream/strerr.c (mu_stdstream_strerr_create): Accept
tag==NULL.
* libmailutils/stream/file_stream.c (fd_done): Do not free filename if
_MU_FILE_STREAM_STATIC_FILENAME is set.
(_mu_file_stream_setup): New function.
* libmailutils/stream/logstream.c (NEXT): Check size before advancing
buffer pointer.
(_mu_log_stream_setup): New function.
* libmailutils/stream/stream.c (_bootstrap_event): New macro.
(mu_stream_destroy): If .destroy is defined, use it instead of free(2).
(mu_stream_open,mu_stream_seek,mu_stream_set_buffer)
(mu_stream_read,mu_stream_readdelim,mu_stream_getdelim)
(mu_stream_write,mu_stream_size,mu_stream_wait)
(mu_stream_truncate,mu_stream_shutdown): Call _bootstrap_event at the
beginning.
* libmailutils/tests/.gitignore: Add strin, strout.
* libmailutils/tests/Makefile.am (noinst_PROGRAMS): Add strin, strout.
(TESTSUITE_AT): Add stdstream tests.
* libmailutils/tests/testsuite.at: Include stdstream tests.
* libmailutils/tests/strerr.at: New test case.
* libmailutils/tests/strin.at: Likewise.
* libmailutils/tests/strout.at: Likewise.
* libmailutils/tests/strin.c: New test program.
* libmailutils/tests/strout.c: Likewise.
1 parent c42e6194
...@@ -24,6 +24,7 @@ ...@@ -24,6 +24,7 @@
24 #define _MU_FILE_STREAM_TEMP 0x01 24 #define _MU_FILE_STREAM_TEMP 0x01
25 #define _MU_FILE_STREAM_ECHO_OFF 0x02 25 #define _MU_FILE_STREAM_ECHO_OFF 0x02
26 #define _MU_FILE_STREAM_FD_BORROWED 0x04 26 #define _MU_FILE_STREAM_FD_BORROWED 0x04
27 #define _MU_FILE_STREAM_STATIC_FILENAME 0x08
27 28
28 struct _mu_file_stream 29 struct _mu_file_stream
29 { 30 {
...@@ -36,5 +37,6 @@ struct _mu_file_stream ...@@ -36,5 +37,6 @@ struct _mu_file_stream
36 37
37 int _mu_file_stream_create (struct _mu_file_stream **pstream, size_t size, 38 int _mu_file_stream_create (struct _mu_file_stream **pstream, size_t size,
38 const char *filename, int fd, int flags); 39 const char *filename, int fd, int flags);
40 void _mu_file_stream_setup (struct _mu_file_stream *str);
39 41
40 #endif 42 #endif
......
...@@ -33,4 +33,6 @@ struct _mu_log_stream ...@@ -33,4 +33,6 @@ struct _mu_log_stream
33 struct mu_locus locus; /* Location */ 33 struct mu_locus locus; /* Location */
34 }; 34 };
35 35
36 void _mu_log_stream_setup (struct _mu_log_stream *sp, mu_stream_t transport);
37
36 #endif 38 #endif
......
...@@ -30,6 +30,7 @@ ...@@ -30,6 +30,7 @@
30 #define _MU_STR_EVENT_FILLBUF 2 30 #define _MU_STR_EVENT_FILLBUF 2
31 #define _MU_STR_EVENT_FLUSHBUF 3 31 #define _MU_STR_EVENT_FLUSHBUF 3
32 #define _MU_STR_EVENT_CLOSE 4 32 #define _MU_STR_EVENT_CLOSE 4
33 #define _MU_STR_EVENT_BOOTSTRAP 5
33 34
34 #define _MU_STR_EVMASK(n) (1<<(n)) 35 #define _MU_STR_EVMASK(n) (1<<(n))
35 36
...@@ -58,6 +59,7 @@ struct _mu_stream ...@@ -58,6 +59,7 @@ struct _mu_stream
58 int (*open) (struct _mu_stream *); 59 int (*open) (struct _mu_stream *);
59 int (*close) (struct _mu_stream *); 60 int (*close) (struct _mu_stream *);
60 void (*done) (struct _mu_stream *); 61 void (*done) (struct _mu_stream *);
62 void (*destroy) (struct _mu_stream *);
61 int (*seek) (struct _mu_stream *, mu_off_t, mu_off_t *); 63 int (*seek) (struct _mu_stream *, mu_off_t, mu_off_t *);
62 int (*size) (struct _mu_stream *, mu_off_t *); 64 int (*size) (struct _mu_stream *, mu_off_t *);
63 int (*ctl) (struct _mu_stream *, int, int, void *); 65 int (*ctl) (struct _mu_stream *, int, int, void *);
......
...@@ -28,10 +28,127 @@ ...@@ -28,10 +28,127 @@
28 #include <mailutils/stream.h> 28 #include <mailutils/stream.h>
29 #include <mailutils/stdstream.h> 29 #include <mailutils/stdstream.h>
30 #include <mailutils/util.h> 30 #include <mailutils/util.h>
31 #include <mailutils/io.h>
32 #include <mailutils/filter.h>
33 #include <mailutils/sys/stream.h>
34 #include <mailutils/sys/file_stream.h>
35 #include <mailutils/sys/logstream.h>
31 36
32 mu_stream_t mu_strin; 37 static void stdstream_flushall_setup (void);
33 mu_stream_t mu_strout; 38
34 mu_stream_t mu_strerr; 39 /* This event callback bootstraps standard I/O streams mu_strin and
40 mu_strout. It is invoked when the stream core emits the bootstrap
41 event for the stream. */
42 static void
43 std_bootstrap (struct _mu_stream *str, int code,
44 unsigned long lval, void *pval)
45 {
46 struct _mu_file_stream *fstr = (struct _mu_file_stream *) str;
47 _mu_file_stream_setup (fstr);
48 str->event_cb = NULL;
49 str->event_mask = 0;
50 str->event_cb_data = 0;
51 fstr->stream.flags |= _MU_STR_OPEN;
52 mu_stream_set_buffer ((mu_stream_t) fstr, mu_buffer_line, 0);
53 stdstream_flushall_setup ();
54 }
55
56 /* This event callback bootstraps standard error stream (mu_strerr).
57 It is invoked when the stream core emits the bootstrap event for
58 the stream. */
59 static void
60 std_log_bootstrap (struct _mu_stream *str, int code,
61 unsigned long lval, void *pval)
62 {
63 struct _mu_log_stream *logstr = (struct _mu_log_stream *) str;
64 int yes = 1;
65 mu_stream_t errstr, transport;
66 int rc;
67
68 rc = mu_stdio_stream_create (&errstr, MU_STDERR_FD, 0);
69 if (rc)
70 {
71 fprintf (stderr, "%s: cannot open error stream: %s\n",
72 mu_program_name ? mu_program_name : "<unknown>",
73 mu_strerror (rc));
74 abort ();
75 }
76 /* Make sure 2 is not closed when errstr is destroyed. */
77 mu_stream_ioctl (errstr, MU_IOCTL_FD, MU_IOCTL_FD_SET_BORROW, &yes);
78 if (!mu_program_name)
79 transport = errstr;
80 else
81 {
82 char *fltargs[3] = { "INLINE-COMMENT", };
83 mu_asprintf (&fltargs[1], "%s: ", mu_program_name);
84 fltargs[2] = NULL;
85 rc = mu_filter_create_args (&transport, errstr,
86 "INLINE-COMMENT",
87 2, (const char**)fltargs,
88 MU_FILTER_ENCODE, MU_STREAM_WRITE);
89 mu_stream_unref (errstr);
90 free (fltargs[1]);
91 if (rc)
92 {
93 fprintf (stderr,
94 "%s: cannot open output filter stream: %s",
95 mu_program_name ? mu_program_name : "<unknown>",
96 mu_strerror (rc));
97 abort ();
98 }
99 mu_stream_set_buffer (transport, mu_buffer_line, 0);
100 }
101
102 str->event_cb = NULL;
103 str->event_mask = 0;
104 str->event_cb_data = 0;
105
106 _mu_log_stream_setup (logstr, transport);
107 stdstream_flushall_setup ();
108 }
109
110 /* The noop destroy function is necessary to prevent stream core from
111 freeing the stream on mu_stream_unref. */
112 static void
113 bootstrap_destroy (struct _mu_stream *str)
114 {
115 /* Nothing */
116 }
117
118 /* Standard I/O streams: */
119 static struct _mu_file_stream stdstream[2] = {
120 { { ref_count: 1,
121 buftype: mu_buffer_none,
122 flags: MU_STREAM_READ,
123 destroy: bootstrap_destroy,
124 event_cb: std_bootstrap,
125 event_mask: _MU_STR_EVMASK (_MU_STR_EVENT_BOOTSTRAP)
126 }, fd: MU_STDIN_FD, filename: "<stdin>",
127 flags: _MU_FILE_STREAM_FD_BORROWED|_MU_FILE_STREAM_STATIC_FILENAME },
128 { { ref_count: 1,
129 buftype: mu_buffer_none,
130 flags: MU_STREAM_WRITE,
131 event_cb: std_bootstrap,
132 event_mask: _MU_STR_EVMASK (_MU_STR_EVENT_BOOTSTRAP)
133 }, fd: MU_STDOUT_FD, filename: "<stdout>",
134 flags: _MU_FILE_STREAM_FD_BORROWED|_MU_FILE_STREAM_STATIC_FILENAME }
135 };
136
137 /* Standard error stream: */
138 static struct _mu_log_stream default_strerr = {
139 { ref_count: 1,
140 buftype: mu_buffer_none,
141 flags: MU_STREAM_WRITE,
142 destroy: bootstrap_destroy,
143 event_cb: std_log_bootstrap,
144 event_mask: _MU_STR_EVMASK (_MU_STR_EVENT_BOOTSTRAP)
145 }
146 };
147
148 /* Pointers to these: */
149 mu_stream_t mu_strin = (mu_stream_t) &stdstream[MU_STDIN_FD];
150 mu_stream_t mu_strout = (mu_stream_t) &stdstream[MU_STDOUT_FD];
151 mu_stream_t mu_strerr = (mu_stream_t) &default_strerr;
35 152
36 static void 153 static void
37 stdstream_flushall (void *data MU_ARG_UNUSED) 154 stdstream_flushall (void *data MU_ARG_UNUSED)
...@@ -41,7 +158,17 @@ stdstream_flushall (void *data MU_ARG_UNUSED) ...@@ -41,7 +158,17 @@ stdstream_flushall (void *data MU_ARG_UNUSED)
41 mu_stream_flush (mu_strerr); 158 mu_stream_flush (mu_strerr);
42 } 159 }
43 160
44 static int stdstream_flushall_setup = 0; 161 static void
162 stdstream_flushall_setup (void)
163 {
164 static int _setup = 0;
165
166 if (!_setup)
167 {
168 mu_onexit (stdstream_flushall, NULL);
169 _setup = 1;
170 }
171 }
45 172
46 void 173 void
47 mu_stdstream_setup (int flags) 174 mu_stdstream_setup (int flags)
...@@ -120,11 +247,7 @@ mu_stdstream_setup (int flags) ...@@ -120,11 +247,7 @@ mu_stdstream_setup (int flags)
120 abort (); 247 abort ();
121 } 248 }
122 249
123 if (!stdstream_flushall_setup) 250 stdstream_flushall_setup ();
124 {
125 mu_onexit (stdstream_flushall, NULL);
126 stdstream_flushall_setup = 1;
127 }
128 } 251 }
129 252
130 int 253 int
......
...@@ -50,7 +50,7 @@ mu_stdstream_strerr_create (mu_stream_t *plogger, int type, int facility, ...@@ -50,7 +50,7 @@ mu_stdstream_strerr_create (mu_stream_t *plogger, int type, int facility,
50 if (rc) 50 if (rc)
51 { 51 {
52 fprintf (stderr, _("%s: cannot open error stream: %s\n"), 52 fprintf (stderr, _("%s: cannot open error stream: %s\n"),
53 tag, mu_strerror (rc)); 53 tag ? tag : "<unknown>", mu_strerror (rc));
54 return MU_ERR_FAILURE; 54 return MU_ERR_FAILURE;
55 } 55 }
56 /* Make sure 2 is not closed when str is destroyed. 56 /* Make sure 2 is not closed when str is destroyed.
...@@ -74,7 +74,7 @@ mu_stdstream_strerr_create (mu_stream_t *plogger, int type, int facility, ...@@ -74,7 +74,7 @@ mu_stdstream_strerr_create (mu_stream_t *plogger, int type, int facility,
74 { 74 {
75 fprintf (stderr, 75 fprintf (stderr,
76 _("%s: cannot open output filter stream: %s"), 76 _("%s: cannot open output filter stream: %s"),
77 tag, mu_strerror (rc)); 77 tag ? tag : "<unknown>", mu_strerror (rc));
78 return MU_ERR_FAILURE; 78 return MU_ERR_FAILURE;
79 } 79 }
80 mu_stream_set_buffer (transport, mu_buffer_line, 0); 80 mu_stream_set_buffer (transport, mu_buffer_line, 0);
...@@ -88,14 +88,14 @@ mu_stdstream_strerr_create (mu_stream_t *plogger, int type, int facility, ...@@ -88,14 +88,14 @@ mu_stdstream_strerr_create (mu_stream_t *plogger, int type, int facility,
88 if (rc) 88 if (rc)
89 { 89 {
90 fprintf (stderr, _("%s: cannot create syslog stream: %s\n"), 90 fprintf (stderr, _("%s: cannot create syslog stream: %s\n"),
91 tag, mu_strerror (rc)); 91 tag ? tag : "<unknown>", mu_strerror (rc));
92 return MU_ERR_FAILURE; 92 return MU_ERR_FAILURE;
93 } 93 }
94 break; 94 break;
95 95
96 default: 96 default:
97 fprintf (stderr, _("%s: cannot create error stream: %s\n"), 97 fprintf (stderr, _("%s: cannot create error stream: %s\n"),
98 tag, mu_strerror (EINVAL)); 98 tag ? tag : "<unknown>", mu_strerror (EINVAL));
99 return EINVAL; 99 return EINVAL;
100 } 100 }
101 101
...@@ -104,7 +104,7 @@ mu_stdstream_strerr_create (mu_stream_t *plogger, int type, int facility, ...@@ -104,7 +104,7 @@ mu_stdstream_strerr_create (mu_stream_t *plogger, int type, int facility,
104 if (rc) 104 if (rc)
105 { 105 {
106 fprintf (stderr, _("%s: cannot open logger stream: %s\n"), 106 fprintf (stderr, _("%s: cannot open logger stream: %s\n"),
107 tag , mu_strerror (rc)); 107 tag ? tag : "<unknown>", mu_strerror (rc));
108 return MU_ERR_FAILURE; 108 return MU_ERR_FAILURE;
109 } 109 }
110 return 0; 110 return 0;
......
...@@ -153,7 +153,7 @@ fd_done (struct _mu_stream *str) ...@@ -153,7 +153,7 @@ fd_done (struct _mu_stream *str)
153 struct _mu_file_stream *fstr = (struct _mu_file_stream *) str; 153 struct _mu_file_stream *fstr = (struct _mu_file_stream *) str;
154 if (fstr->fd != -1) 154 if (fstr->fd != -1)
155 fd_close (str); 155 fd_close (str);
156 if (fstr->filename) 156 if (fstr->filename && !(fstr->flags & _MU_FILE_STREAM_STATIC_FILENAME))
157 free (fstr->filename); 157 free (fstr->filename);
158 if (fstr->echo_state) 158 if (fstr->echo_state)
159 free (fstr->echo_state); 159 free (fstr->echo_state);
...@@ -312,15 +312,9 @@ fd_truncate (mu_stream_t stream, mu_off_t size) ...@@ -312,15 +312,9 @@ fd_truncate (mu_stream_t stream, mu_off_t size)
312 return 0; 312 return 0;
313 } 313 }
314 314
315 int 315 void
316 _mu_file_stream_create (struct _mu_file_stream **pstream, size_t size, 316 _mu_file_stream_setup (struct _mu_file_stream *str)
317 const char *filename, int fd, int flags)
318 { 317 {
319 struct _mu_file_stream *str =
320 (struct _mu_file_stream *) _mu_stream_create (size, flags);
321 if (!str)
322 return ENOMEM;
323
324 str->stream.read = fd_read; 318 str->stream.read = fd_read;
325 str->stream.write = fd_write; 319 str->stream.write = fd_write;
326 str->stream.open = fd_open; 320 str->stream.open = fd_open;
...@@ -331,6 +325,18 @@ _mu_file_stream_create (struct _mu_file_stream **pstream, size_t size, ...@@ -331,6 +325,18 @@ _mu_file_stream_create (struct _mu_file_stream **pstream, size_t size,
331 str->stream.ctl = fd_ioctl; 325 str->stream.ctl = fd_ioctl;
332 str->stream.wait = fd_wait; 326 str->stream.wait = fd_wait;
333 str->stream.truncate = fd_truncate; 327 str->stream.truncate = fd_truncate;
328 }
329
330 int
331 _mu_file_stream_create (struct _mu_file_stream **pstream, size_t size,
332 const char *filename, int fd, int flags)
333 {
334 struct _mu_file_stream *str =
335 (struct _mu_file_stream *) _mu_stream_create (size, flags);
336 if (!str)
337 return ENOMEM;
338
339 _mu_file_stream_setup (str);
334 340
335 if (filename) 341 if (filename)
336 str->filename = mu_strdup (filename); 342 str->filename = mu_strdup (filename);
......
...@@ -103,7 +103,7 @@ _log_write (struct _mu_stream *str, const char *buf, size_t size, ...@@ -103,7 +103,7 @@ _log_write (struct _mu_stream *str, const char *buf, size_t size,
103 int rc; 103 int rc;
104 int escape_error = 0; 104 int escape_error = 0;
105 105
106 #define NEXT do { buf++; size--; if (size == 0) return EINVAL; } while (0) 106 #define NEXT do { if (size == 0) return EINVAL; buf++; size--; } while (0)
107 #define READNUM(n) do { \ 107 #define READNUM(n) do { \
108 unsigned __x = 0; \ 108 unsigned __x = 0; \
109 if (*buf != '<') \ 109 if (*buf != '<') \
...@@ -470,17 +470,11 @@ _log_ctl (struct _mu_stream *str, int code, int opcode, void *arg) ...@@ -470,17 +470,11 @@ _log_ctl (struct _mu_stream *str, int code, int opcode, void *arg)
470 return 0; 470 return 0;
471 } 471 }
472 472
473 int 473 void
474 mu_log_stream_create (mu_stream_t *pstr, mu_stream_t transport) 474 _mu_log_stream_setup (struct _mu_log_stream *sp, mu_stream_t transport)
475 { 475 {
476 struct _mu_log_stream *sp;
477 mu_stream_t stream; 476 mu_stream_t stream;
478 int rc;
479 477
480 sp = (struct _mu_log_stream *)
481 _mu_stream_create (sizeof (*sp), MU_STREAM_WRITE);
482 if (!sp)
483 return ENOMEM;
484 sp->base.write = _log_write; 478 sp->base.write = _log_write;
485 sp->base.flush = _log_flush; 479 sp->base.flush = _log_flush;
486 sp->base.close = _log_close; 480 sp->base.close = _log_close;
...@@ -494,13 +488,21 @@ mu_log_stream_create (mu_stream_t *pstr, mu_stream_t transport) ...@@ -494,13 +488,21 @@ mu_log_stream_create (mu_stream_t *pstr, mu_stream_t transport)
494 488
495 stream = (mu_stream_t) sp; 489 stream = (mu_stream_t) sp;
496 mu_stream_set_buffer (stream, mu_buffer_line, 0); 490 mu_stream_set_buffer (stream, mu_buffer_line, 0);
497 rc = mu_stream_open (stream); 491 }
498 if (rc)
499 mu_stream_destroy (&stream);
500 else
501 *pstr = stream;
502 492
503 return rc; 493 int
494 mu_log_stream_create (mu_stream_t *pstr, mu_stream_t transport)
495 {
496 struct _mu_log_stream *sp;
497
498 sp = (struct _mu_log_stream *)
499 _mu_stream_create (sizeof (*sp), MU_STREAM_WRITE);
500 if (!sp)
501 return ENOMEM;
502 _mu_log_stream_setup (sp, transport);
503 *pstr = (mu_stream_t) sp;
504
505 return 0;
504 } 506 }
505 507
506 508
......
...@@ -46,6 +46,19 @@ size_t mu_stream_default_buffer_size = MU_STREAM_DEFBUFSIZ; ...@@ -46,6 +46,19 @@ size_t mu_stream_default_buffer_size = MU_STREAM_DEFBUFSIZ;
46 } \ 46 } \
47 while (0) 47 while (0)
48 48
49 #define _bootstrap_event(stream) \
50 do \
51 { \
52 if ((stream)->event_cb && \
53 ((stream)->event_mask & _MU_STR_EVMASK(_MU_STR_EVENT_BOOTSTRAP))) \
54 { \
55 (stream)->event_cb (stream, _MU_STR_EVENT_BOOTSTRAP, 0, NULL); \
56 (stream)->event_mask &= ~_MU_STR_EVMASK(_MU_STR_EVENT_BOOTSTRAP); \
57 } \
58 } \
59 while (0)
60
61
49 #define _stream_stat_incr(s, k, n) \ 62 #define _stream_stat_incr(s, k, n) \
50 (((s)->statmask & MU_STREAM_STAT_MASK(k)) ? ((s)->statbuf[k] += n) : 0) 63 (((s)->statmask & MU_STREAM_STAT_MASK(k)) ? ((s)->statbuf[k] += n) : 0)
51 64
...@@ -292,6 +305,9 @@ mu_stream_destroy (mu_stream_t *pstream) ...@@ -292,6 +305,9 @@ mu_stream_destroy (mu_stream_t *pstream)
292 mu_stream_close (str); 305 mu_stream_close (str);
293 if (str->done) 306 if (str->done)
294 str->done (str); 307 str->done (str);
308 if (str->destroy)
309 str->destroy (str);
310 else
295 free (str); 311 free (str);
296 *pstream = NULL; 312 *pstream = NULL;
297 } 313 }
...@@ -336,6 +352,7 @@ mu_stream_open (mu_stream_t stream) ...@@ -336,6 +352,7 @@ mu_stream_open (mu_stream_t stream)
336 352
337 if (stream->flags & _MU_STR_OPEN) 353 if (stream->flags & _MU_STR_OPEN)
338 return MU_ERR_OPEN; 354 return MU_ERR_OPEN;
355 _bootstrap_event (stream);
339 if (stream->open) 356 if (stream->open)
340 { 357 {
341 if ((rc = stream->open (stream))) 358 if ((rc = stream->open (stream)))
...@@ -399,6 +416,7 @@ mu_stream_seek (mu_stream_t stream, mu_off_t offset, int whence, ...@@ -399,6 +416,7 @@ mu_stream_seek (mu_stream_t stream, mu_off_t offset, int whence,
399 int rc; 416 int rc;
400 mu_off_t size; 417 mu_off_t size;
401 418
419 _bootstrap_event (stream);
402 if (!(stream->flags & _MU_STR_OPEN)) 420 if (!(stream->flags & _MU_STR_OPEN))
403 { 421 {
404 if (stream->open) 422 if (stream->open)
...@@ -551,6 +569,8 @@ int ...@@ -551,6 +569,8 @@ int
551 mu_stream_set_buffer (mu_stream_t stream, enum mu_buffer_type type, 569 mu_stream_set_buffer (mu_stream_t stream, enum mu_buffer_type type,
552 size_t size) 570 size_t size)
553 { 571 {
572 _bootstrap_event (stream);
573
554 if (size == 0) 574 if (size == 0)
555 size = mu_stream_default_buffer_size; 575 size = mu_stream_default_buffer_size;
556 576
...@@ -717,6 +737,8 @@ _stream_write_unbuffered (mu_stream_t stream, ...@@ -717,6 +737,8 @@ _stream_write_unbuffered (mu_stream_t stream,
717 int 737 int
718 mu_stream_read (mu_stream_t stream, void *buf, size_t size, size_t *pread) 738 mu_stream_read (mu_stream_t stream, void *buf, size_t size, size_t *pread)
719 { 739 {
740 _bootstrap_event (stream);
741
720 if (!(stream->flags & _MU_STR_OPEN)) 742 if (!(stream->flags & _MU_STR_OPEN))
721 { 743 {
722 if (stream->open) 744 if (stream->open)
...@@ -857,6 +879,8 @@ mu_stream_readdelim (mu_stream_t stream, char *buf, size_t size, ...@@ -857,6 +879,8 @@ mu_stream_readdelim (mu_stream_t stream, char *buf, size_t size,
857 { 879 {
858 int rc; 880 int rc;
859 881
882 _bootstrap_event (stream);
883
860 if (size == 0) 884 if (size == 0)
861 return EINVAL; 885 return EINVAL;
862 886
...@@ -905,6 +929,8 @@ mu_stream_getdelim (mu_stream_t stream, char **pbuf, size_t *psize, ...@@ -905,6 +929,8 @@ mu_stream_getdelim (mu_stream_t stream, char **pbuf, size_t *psize,
905 size_t n = *psize; 929 size_t n = *psize;
906 size_t cur_len = 0; 930 size_t cur_len = 0;
907 931
932 _bootstrap_event (stream);
933
908 if (!(stream->flags & _MU_STR_OPEN)) 934 if (!(stream->flags & _MU_STR_OPEN))
909 { 935 {
910 if (stream->open) 936 if (stream->open)
...@@ -996,6 +1022,8 @@ mu_stream_write (mu_stream_t stream, const void *buf, size_t size, ...@@ -996,6 +1022,8 @@ mu_stream_write (mu_stream_t stream, const void *buf, size_t size,
996 { 1022 {
997 int rc = 0; 1023 int rc = 0;
998 1024
1025 _bootstrap_event (stream);
1026
999 if (!(stream->flags & _MU_STR_OPEN)) 1027 if (!(stream->flags & _MU_STR_OPEN))
1000 { 1028 {
1001 if (stream->open) 1029 if (stream->open)
...@@ -1063,6 +1091,7 @@ mu_stream_flush (mu_stream_t stream) ...@@ -1063,6 +1091,7 @@ mu_stream_flush (mu_stream_t stream)
1063 1091
1064 if (!stream) 1092 if (!stream)
1065 return EINVAL; 1093 return EINVAL;
1094 _bootstrap_event (stream);
1066 if (!(stream->flags & _MU_STR_OPEN)) 1095 if (!(stream->flags & _MU_STR_OPEN))
1067 { 1096 {
1068 if (stream->open) 1097 if (stream->open)
...@@ -1105,6 +1134,7 @@ mu_stream_size (mu_stream_t stream, mu_off_t *psize) ...@@ -1105,6 +1134,7 @@ mu_stream_size (mu_stream_t stream, mu_off_t *psize)
1105 int rc; 1134 int rc;
1106 mu_off_t size; 1135 mu_off_t size;
1107 1136
1137 _bootstrap_event (stream);
1108 if (!(stream->flags & _MU_STR_OPEN)) 1138 if (!(stream->flags & _MU_STR_OPEN))
1109 { 1139 {
1110 if (stream->open) 1140 if (stream->open)
...@@ -1126,6 +1156,7 @@ mu_stream_size (mu_stream_t stream, mu_off_t *psize) ...@@ -1126,6 +1156,7 @@ mu_stream_size (mu_stream_t stream, mu_off_t *psize)
1126 int 1156 int
1127 mu_stream_ioctl (mu_stream_t stream, int family, int opcode, void *ptr) 1157 mu_stream_ioctl (mu_stream_t stream, int family, int opcode, void *ptr)
1128 { 1158 {
1159 _bootstrap_event (stream);
1129 if (stream->ctl == NULL) 1160 if (stream->ctl == NULL)
1130 return ENOSYS; 1161 return ENOSYS;
1131 return stream->ctl (stream, family, opcode, ptr); 1162 return stream->ctl (stream, family, opcode, ptr);
...@@ -1138,6 +1169,7 @@ mu_stream_wait (mu_stream_t stream, int *pflags, struct timeval *tvp) ...@@ -1138,6 +1169,7 @@ mu_stream_wait (mu_stream_t stream, int *pflags, struct timeval *tvp)
1138 1169
1139 if (stream == NULL) 1170 if (stream == NULL)
1140 return EINVAL; 1171 return EINVAL;
1172 _bootstrap_event (stream);
1141 #if 0 1173 #if 0
1142 /* NOTE: Sometimes mu_stream_wait is called after a failed mu_stream_open. 1174 /* NOTE: Sometimes mu_stream_wait is called after a failed mu_stream_open.
1143 In particular, this is needed for a TCP stream opened with a 1175 In particular, this is needed for a TCP stream opened with a
...@@ -1181,6 +1213,8 @@ mu_stream_wait (mu_stream_t stream, int *pflags, struct timeval *tvp) ...@@ -1181,6 +1213,8 @@ mu_stream_wait (mu_stream_t stream, int *pflags, struct timeval *tvp)
1181 int 1213 int
1182 mu_stream_truncate (mu_stream_t stream, mu_off_t size) 1214 mu_stream_truncate (mu_stream_t stream, mu_off_t size)
1183 { 1215 {
1216 _bootstrap_event (stream);
1217
1184 if (!(stream->flags & _MU_STR_OPEN)) 1218 if (!(stream->flags & _MU_STR_OPEN))
1185 { 1219 {
1186 if (stream->open) 1220 if (stream->open)
...@@ -1204,6 +1238,8 @@ mu_stream_shutdown (mu_stream_t stream, int how) ...@@ -1204,6 +1238,8 @@ mu_stream_shutdown (mu_stream_t stream, int how)
1204 { 1238 {
1205 int rc; 1239 int rc;
1206 1240
1241 _bootstrap_event (stream);
1242
1207 if (!(stream->flags & _MU_STR_OPEN)) 1243 if (!(stream->flags & _MU_STR_OPEN))
1208 { 1244 {
1209 if (stream->open) 1245 if (stream->open)
......
...@@ -18,6 +18,8 @@ mailcap ...@@ -18,6 +18,8 @@ mailcap
18 prop 18 prop
19 scantime 19 scantime
20 strftime 20 strftime
21 strin
22 strout
21 url-comp 23 url-comp
22 url-parse 24 url-parse
23 wicket 25 wicket
......
...@@ -53,6 +53,8 @@ noinst_PROGRAMS = \ ...@@ -53,6 +53,8 @@ noinst_PROGRAMS = \
53 prop\ 53 prop\
54 scantime\ 54 scantime\
55 strftime\ 55 strftime\
56 strin\
57 strout\
56 tempfile\ 58 tempfile\
57 url-comp\ 59 url-comp\
58 url-parse\ 60 url-parse\
...@@ -85,6 +87,9 @@ TESTSUITE_AT = \ ...@@ -85,6 +87,9 @@ TESTSUITE_AT = \
85 prop.at\ 87 prop.at\
86 scantime.at\ 88 scantime.at\
87 strftime.at\ 89 strftime.at\
90 strerr.at\
91 strin.at\
92 strout.at\
88 testsuite.at\ 93 testsuite.at\
89 url.at\ 94 url.at\
90 url-comp.at\ 95 url-comp.at\
......
1 # This file is part of GNU Mailutils. -*- Autotest -*-
2 # Copyright (C) 2011 Free Software Foundation, Inc.
3 #
4 # GNU Mailutils is free software; you can redistribute it and/or
5 # modify it under the terms of the GNU General Public License as
6 # published by the Free Software Foundation; either version 3, or (at
7 # your option) any later version.
8 #
9 # GNU Mailutils is distributed in the hope that it will be useful, but
10 # WITHOUT ANY WARRANTY; without even the implied warranty of
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 # General Public License for more details.
13 #
14 # You should have received a copy of the GNU General Public License
15 # along with GNU Mailutils. If not, see <http://www.gnu.org/licenses/>.
16
17 AT_SETUP([strerr])
18 AT_KEYWORDS([stdstream])
19
20 AT_CHECK([
21 strout -err now is the time for all good men
22 ],
23 [0],
24 [],
25 [strout: now
26 strout: is
27 strout: the
28 strout: time
29 strout: for
30 strout: all
31 strout: good
32 strout: men
33 ])
34
35 AT_CLEANUP
36
37
1 # This file is part of GNU Mailutils. -*- Autotest -*-
2 # Copyright (C) 2011 Free Software Foundation, Inc.
3 #
4 # GNU Mailutils is free software; you can redistribute it and/or
5 # modify it under the terms of the GNU General Public License as
6 # published by the Free Software Foundation; either version 3, or (at
7 # your option) any later version.
8 #
9 # GNU Mailutils is distributed in the hope that it will be useful, but
10 # WITHOUT ANY WARRANTY; without even the implied warranty of
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 # General Public License for more details.
13 #
14 # You should have received a copy of the GNU General Public License
15 # along with GNU Mailutils. If not, see <http://www.gnu.org/licenses/>.
16
17 AT_SETUP([strin])
18 AT_KEYWORDS([stdstream])
19
20 AT_DATA([input],
21 [Omnis enim res, quae dando non deficit,
22 dum habetur et non datur, nondum habetur,
23 quomodo habenda est.
24 ])
25
26 AT_CHECK([
27 strin < input
28 ],
29 [0],
30 [Omnis enim res, quae dando non deficit,
31 dum habetur et non datur, nondum habetur,
32 quomodo habenda est.
33 ])
34
35 AT_CLEANUP
36
37
1 /* GNU Mailutils -- a suite of utilities for electronic mail
2 Copyright (C) 2011 Free Software Foundation, Inc.
3
4 GNU Mailutils is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 3, or (at your option)
7 any later version.
8
9 GNU Mailutils 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 General Public License for more details.
13
14 You should have received a copy of the GNU 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 <stdio.h>
22 #include <string.h>
23 #include <mailutils/stream.h>
24 #include <mailutils/stdstream.h>
25 #include <mailutils/diag.h>
26 #include <mailutils/errno.h>
27
28 int
29 main (int argc, char **argv)
30 {
31 int i, rc;
32 int echo_state = 0;
33 size_t n;
34 char buf[80];
35
36 for (i = 1; i < argc; i++)
37 {
38 char *arg = argv[i];
39 if (arg[0] == '-')
40 {
41 if (strcmp (arg, "-noecho") == 0)
42 {
43 MU_ASSERT (mu_stream_ioctl (mu_strin, MU_IOCTL_ECHO,
44 MU_IOCTL_OP_SET,
45 &echo_state));
46 echo_state = 1;
47 }
48 else
49 {
50 fprintf (stderr, "usage: %s [-noecho]\n", argv[0]);
51 return 1;
52 }
53 }
54 }
55
56 while ((rc = mu_stream_read (mu_strin, buf, sizeof (buf), &n) == 0) &&
57 n > 0)
58 fwrite (buf, 1, n, stdout);
59
60 if (echo_state)
61 MU_ASSERT (mu_stream_ioctl (mu_strin, MU_IOCTL_ECHO, MU_IOCTL_OP_SET,
62 &echo_state));
63 return 0;
64 }
1 # This file is part of GNU Mailutils. -*- Autotest -*-
2 # Copyright (C) 2011 Free Software Foundation, Inc.
3 #
4 # GNU Mailutils is free software; you can redistribute it and/or
5 # modify it under the terms of the GNU General Public License as
6 # published by the Free Software Foundation; either version 3, or (at
7 # your option) any later version.
8 #
9 # GNU Mailutils is distributed in the hope that it will be useful, but
10 # WITHOUT ANY WARRANTY; without even the implied warranty of
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 # General Public License for more details.
13 #
14 # You should have received a copy of the GNU General Public License
15 # along with GNU Mailutils. If not, see <http://www.gnu.org/licenses/>.
16
17 AT_SETUP([strout])
18 AT_KEYWORDS([stdstream])
19
20 AT_CHECK([
21 strout now is the time for all good men
22 ],
23 [0],
24 [now
25 is
26 the
27 time
28 for
29 all
30 good
31 men
32 ])
33
34 AT_CLEANUP
35
36
1 /* GNU Mailutils -- a suite of utilities for electronic mail
2 Copyright (C) 2011 Free Software Foundation, Inc.
3
4 GNU Mailutils is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 3, or (at your option)
7 any later version.
8
9 GNU Mailutils 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 General Public License for more details.
13
14 You should have received a copy of the GNU 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 <stdio.h>
22 #include <string.h>
23 #include <mailutils/stream.h>
24 #include <mailutils/stdstream.h>
25 #include <mailutils/diag.h>
26
27 int
28 main (int argc, char **argv)
29 {
30 mu_stream_t str = mu_strout;
31 int i;
32
33 if (argc == 1)
34 {
35 fprintf (stderr, "usage: %s: word|option [word|option...]\n", argv[0]);
36 fprintf (stderr, "options are: -out, -err, -reset\n");
37 return 1;
38 }
39
40 mu_set_program_name (argv[0]);
41
42 for (i = 1; i < argc; i++)
43 {
44 char *arg = argv[i];
45 if (arg[0] == '-')
46 {
47 if (strcmp (arg, "-out") == 0)
48 str = mu_strout;
49 else if (strcmp (arg, "-err") == 0)
50 str = mu_strerr;
51 else if (strcmp (arg, "-reset") == 0)
52 {
53 if (str == mu_strout)
54 {
55 mu_stdstream_setup (MU_STDSTREAM_RESET_STROUT);
56 str = mu_strout;
57 }
58 else
59 {
60 mu_stdstream_setup (MU_STDSTREAM_RESET_STRERR);
61 str = mu_strerr;
62 }
63 }
64 else
65 {
66 fprintf (stderr, "%s: unrecognized option %s\n", argv[0], arg);
67 return 1;
68 }
69 }
70 else
71 mu_stream_printf (str, "%s\n", arg);
72 }
73
74 return 0;
75 }
...@@ -54,6 +54,11 @@ AT_CLEANUP ...@@ -54,6 +54,11 @@ AT_CLEANUP
54 54
55 AT_INIT 55 AT_INIT
56 56
57 AT_BANNER([Standard streams])
58 m4_include([strin.at])
59 m4_include([strout.at])
60 m4_include([strerr.at])
61
57 m4_include([list.at]) 62 m4_include([list.at])
58 m4_include([address.at]) 63 m4_include([address.at])
59 m4_include([wordsplit.at]) 64 m4_include([wordsplit.at])
......