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.
Showing
16 changed files
with
472 additions
and
38 deletions
... | @@ -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 | ... | ... |
... | @@ -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) | ... | ... |
... | @@ -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\ | ... | ... |
libmailutils/tests/strerr.at
0 → 100644
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 |
libmailutils/tests/strin.at
0 → 100644
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 |
libmailutils/tests/strin.c
0 → 100644
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 | } |
libmailutils/tests/strout.at
0 → 100644
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 |
libmailutils/tests/strout.c
0 → 100644
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]) | ... | ... |
-
Please register or sign in to post a comment