Merge branch 'topic/shoens-2000'
[s-mailx.git] / message.c
bloba2c418b70cfb6cdd1853a636c962ebfa8755d88f
1 /*@ S-nail - a mail user agent derived from Berkeley Mail.
2 *@ Message, message array, and related operations.
4 * Copyright (c) 2000-2004 Gunnar Ritter, Freiburg i. Br., Germany.
5 * Copyright (c) 2012 - 2015 Steffen (Daode) Nurpmeso <sdaoden@users.sf.net>.
6 */
7 /*
8 * Copyright (c) 1980, 1993
9 * The Regents of the University of California. All rights reserved.
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
13 * are met:
14 * 1. Redistributions of source code must retain the above copyright
15 * notice, this list of conditions and the following disclaimer.
16 * 2. Redistributions in binary form must reproduce the above copyright
17 * notice, this list of conditions and the following disclaimer in the
18 * documentation and/or other materials provided with the distribution.
19 * 3. Neither the name of the University nor the names of its contributors
20 * may be used to endorse or promote products derived from this software
21 * without specific prior written permission.
23 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
24 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
27 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
28 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
29 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
32 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
33 * SUCH DAMAGE.
35 #undef n_FILE
36 #define n_FILE message
38 #ifndef HAVE_AMALGAMATION
39 # include "nail.h"
40 #endif
42 /* Slots in ::message */
43 static size_t _message_space;
45 static enum okay get_header(struct message *mp);
47 static enum okay
48 get_header(struct message *mp)
50 enum okay rv;
51 NYD_ENTER;
52 UNUSED(mp);
54 switch (mb.mb_type) {
55 case MB_FILE:
56 case MB_MAILDIR:
57 rv = OKAY;
58 break;
59 #ifdef HAVE_POP3
60 case MB_POP3:
61 rv = pop3_header(mp);
62 break;
63 #endif
64 case MB_VOID:
65 default:
66 rv = STOP;
67 break;
69 NYD_LEAVE;
70 return rv;
73 FL FILE *
74 setinput(struct mailbox *mp, struct message *m, enum needspec need)
76 FILE *rv = NULL;
77 enum okay ok = STOP;
78 NYD_ENTER;
80 switch (need) {
81 case NEED_HEADER:
82 ok = (m->m_have & HAVE_HEADER) ? OKAY : get_header(m);
83 break;
84 case NEED_BODY:
85 ok = (m->m_have & HAVE_BODY) ? OKAY : get_body(m);
86 break;
87 case NEED_UNSPEC:
88 ok = OKAY;
89 break;
91 if (ok != OKAY)
92 goto jleave;
94 fflush(mp->mb_otf);
95 if (fseek(mp->mb_itf, (long)mailx_positionof(m->m_block, m->m_offset),
96 SEEK_SET) == -1) {
97 n_perr(_("fseek"), 0);
98 n_panic(_("temporary file seek"));
100 rv = mp->mb_itf;
101 jleave:
102 NYD_LEAVE;
103 return rv;
106 FL enum okay
107 get_body(struct message *mp)
109 enum okay rv;
110 NYD_ENTER;
111 UNUSED(mp);
113 switch (mb.mb_type) {
114 case MB_FILE:
115 case MB_MAILDIR:
116 rv = OKAY;
117 break;
118 #ifdef HAVE_POP3
119 case MB_POP3:
120 rv = pop3_body(mp);
121 break;
122 #endif
123 case MB_VOID:
124 default:
125 rv = STOP;
126 break;
128 NYD_LEAVE;
129 return rv;
132 FL void
133 message_reset(void)
135 NYD_ENTER;
136 if (message != NULL) {
137 free(message);
138 message = NULL;
140 msgCount = 0;
141 _message_space = 0;
142 NYD_LEAVE;
145 FL void
146 message_append(struct message *mp)
148 NYD_ENTER;
149 if (UICMP(z, msgCount + 1, >=, _message_space)) {
150 /* XXX remove _message_space magics (or use s_Vector) */
151 _message_space = (_message_space >= 128 && _message_space <= 1000000)
152 ? _message_space << 1 : _message_space + 64;
153 message = srealloc(message, _message_space * sizeof *message);
155 if (msgCount > 0) {
156 if (mp != NULL)
157 message[msgCount - 1] = *mp;
158 else
159 memset(message + msgCount - 1, 0, sizeof *message);
161 NYD_LEAVE;
164 FL void
165 message_append_null(void)
167 NYD_ENTER;
168 if (msgCount == 0)
169 message_append(NULL);
170 setdot(message);
171 message[msgCount].m_size = 0;
172 message[msgCount].m_lines = 0;
173 NYD_LEAVE;
176 FL bool_t
177 message_match(struct message *mp, struct search_expr const *sep,
178 bool_t with_headers)
180 char **line;
181 size_t *linesize, cnt;
182 FILE *fp;
183 bool_t rv = FAL0;
184 NYD_ENTER;
186 if ((fp = Ftmp(NULL, "mpmatch", OF_RDWR | OF_UNLINK | OF_REGISTER)) == NULL)
187 goto j_leave;
189 if (sendmp(mp, fp, NULL, NULL, SEND_TOSRCH, NULL) < 0)
190 goto jleave;
191 fflush_rewind(fp);
193 cnt = fsize(fp);
194 line = &termios_state.ts_linebuf; /* XXX line pool */
195 linesize = &termios_state.ts_linesize; /* XXX line pool */
197 if (!with_headers)
198 while (fgetline(line, linesize, &cnt, NULL, fp, 0))
199 if (**line == '\n')
200 break;
202 while (fgetline(line, linesize, &cnt, NULL, fp, 0)) {
203 #ifdef HAVE_REGEX
204 if (sep->ss_sexpr == NULL) {
205 if (regexec(&sep->ss_regex, *line, 0,NULL, 0) == REG_NOMATCH)
206 continue;
207 } else
208 #endif
209 if (!substr(*line, sep->ss_sexpr))
210 continue;
211 rv = TRU1;
212 break;
215 jleave:
216 Fclose(fp);
217 j_leave:
218 NYD_LEAVE;
219 return rv;
222 FL struct message *
223 setdot(struct message *mp)
225 NYD_ENTER;
226 if (dot != mp) {
227 prevdot = dot;
228 pstate &= ~PS_DID_PRINT_DOT;
230 dot = mp;
231 uncollapse1(dot, 0);
232 NYD_LEAVE;
233 return dot;
236 FL void
237 touch(struct message *mp)
239 NYD_ENTER;
240 mp->m_flag |= MTOUCH;
241 if (!(mp->m_flag & MREAD))
242 mp->m_flag |= MREAD | MSTATUS;
243 NYD_LEAVE;
246 /* s-it-mode */