Added to the repository
Showing
1 changed file
with
162 additions
and
0 deletions
mh/mh_stream.c
0 → 100644
1 | /* GNU Mailutils -- a suite of utilities for electronic mail | ||
2 | Copyright (C) 1999, 2000, 2001, 2002 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 2, 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, write to the Free Software | ||
16 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ | ||
17 | |||
18 | /* This file implements an MH draftfile stream: a read-only stream used | ||
19 | to transparently pass MH draftfiles to the mailers. The only difference | ||
20 | between the usual RFC822 and MH draft is that the latter allows to use | ||
21 | a string of dashes to separate the headers from the body. */ | ||
22 | |||
23 | #include <mh.h> | ||
24 | #include <mailutils/stream.h> | ||
25 | |||
26 | struct _mhdraft_stream { | ||
27 | stream_t stream; /* Actual stream */ | ||
28 | size_t mark_offset; /* Offset of the header separator */ | ||
29 | size_t mark_length; /* Length of the header separator (not counting the | ||
30 | newline) */ | ||
31 | }; | ||
32 | |||
33 | static int | ||
34 | _mhdraft_read (stream_t stream, char *optr, size_t osize, | ||
35 | off_t offset, size_t *nbytes) | ||
36 | { | ||
37 | struct _mhdraft_stream *s = stream_get_owner (stream); | ||
38 | |||
39 | if (offset < s->mark_offset) | ||
40 | { | ||
41 | if (offset + osize >= s->mark_offset) | ||
42 | osize = s->mark_offset - offset; | ||
43 | } | ||
44 | else | ||
45 | offset += s->mark_length; | ||
46 | return stream_read (s->stream, optr, osize, offset, nbytes); | ||
47 | } | ||
48 | |||
49 | static int | ||
50 | _mhdraft_readline (stream_t stream, char *optr, size_t osize, | ||
51 | off_t offset, size_t *nbytes) | ||
52 | { | ||
53 | struct _mhdraft_stream *s = stream_get_owner (stream); | ||
54 | |||
55 | if (offset < s->mark_offset) | ||
56 | { | ||
57 | if (offset + osize >= s->mark_offset) | ||
58 | { | ||
59 | int rc; | ||
60 | size_t n; | ||
61 | size_t rdsize = s->mark_offset - offset; | ||
62 | rc = stream_readline (s->stream, optr, rdsize, offset, &n); | ||
63 | if (rc == 0) | ||
64 | { | ||
65 | if (nbytes) | ||
66 | *nbytes = n; | ||
67 | } | ||
68 | return rc; | ||
69 | } | ||
70 | } | ||
71 | else | ||
72 | offset += s->mark_length; | ||
73 | |||
74 | return stream_readline (s->stream, optr, osize, offset, nbytes); | ||
75 | } | ||
76 | |||
77 | static int | ||
78 | _mhdraft_size (stream_t stream, off_t *psize) | ||
79 | { | ||
80 | struct _mhdraft_stream *s = stream_get_owner (stream); | ||
81 | int rc = stream_size (s->stream, psize); | ||
82 | |||
83 | if (rc == 0) | ||
84 | *psize -= s->mark_length; | ||
85 | return rc; | ||
86 | } | ||
87 | |||
88 | static int | ||
89 | _mhdraft_open (stream_t stream) | ||
90 | { | ||
91 | struct _mhdraft_stream *s = stream_get_owner (stream); | ||
92 | size_t offset, len; | ||
93 | char buffer[256]; | ||
94 | int rc; | ||
95 | |||
96 | offset = 0; | ||
97 | while ((rc = stream_readline (s->stream, buffer, sizeof buffer, | ||
98 | offset, &len)) == 0 | ||
99 | && len > 0) | ||
100 | { | ||
101 | if (_mh_delim (buffer)) | ||
102 | { | ||
103 | s->mark_offset = offset; | ||
104 | s->mark_length = len - 1; /* do not count the terminating newline */ | ||
105 | break; | ||
106 | } | ||
107 | |||
108 | offset += len; | ||
109 | } | ||
110 | return 0; | ||
111 | } | ||
112 | |||
113 | static int | ||
114 | _mhdraft_close (stream_t stream) | ||
115 | { | ||
116 | struct _mhdraft_stream *s = stream_get_owner (stream); | ||
117 | return stream_close (s->stream); | ||
118 | } | ||
119 | |||
120 | static void | ||
121 | _mhdraft_destroy (stream_t stream) | ||
122 | { | ||
123 | struct _mhdraft_stream *s = stream_get_owner (stream); | ||
124 | if (s->stream) | ||
125 | stream_destroy (&s->stream, stream_get_owner (s->stream)); | ||
126 | free (s); | ||
127 | } | ||
128 | |||
129 | int | ||
130 | mhdraft_stream_create (stream_t *stream, stream_t src, int flags) | ||
131 | { | ||
132 | struct _mhdraft_stream *s; | ||
133 | int rc; | ||
134 | |||
135 | if (!flags) | ||
136 | flags = MU_STREAM_READ; | ||
137 | if (flags != MU_STREAM_READ) | ||
138 | return EINVAL; | ||
139 | |||
140 | s = calloc (1, sizeof (*s)); | ||
141 | if (s == NULL) | ||
142 | return ENOMEM; | ||
143 | |||
144 | s->stream = src; | ||
145 | |||
146 | rc = stream_create (stream, flags|MU_STREAM_NO_CHECK, s); | ||
147 | if (rc) | ||
148 | { | ||
149 | free (s); | ||
150 | return rc; | ||
151 | } | ||
152 | |||
153 | stream_set_open (*stream, _mhdraft_open, s); | ||
154 | stream_set_close (*stream, _mhdraft_close, s); | ||
155 | stream_set_destroy (*stream, _mhdraft_destroy, s); | ||
156 | stream_set_readline (*stream, _mhdraft_readline, s); | ||
157 | stream_set_read (*stream, _mhdraft_read, s); | ||
158 | stream_set_size (*stream, _mhdraft_size, s); | ||
159 | return 0; | ||
160 | } | ||
161 | |||
162 |
-
Please register or sign in to post a comment