masqmail
view src/header.c @ 421:f37384470855
Changed lockdir to /var/lock/masqmail; Create lockdir and piddir on startup.
Moved the lockdir out of the spool dir. (When /var/lock is a ramdisk
we do well to have the lock files there.) Added the new configure option
--with-lockdir to change that location. Nontheless, if we run_as_user,
then lock files are always stored in the spool dir directly.
Instead of installing the lockdir and piddir at installation time, we
create them on startup time now if they are missing. This is necessary
if lockdir or piddir are a tmpfs.
author | markus schnalke <meillo@marmaro.de> |
---|---|
date | Wed, 30 May 2012 09:38:38 +0200 |
parents | 028bc124d744 |
children |
line source
1 /*
2 ** MasqMail
3 ** Copyright (C) 2000 Oliver Kurth
4 **
5 ** This program is free software; you can redistribute it and/or modify
6 ** it under the terms of the GNU General Public License as published by
7 ** the Free Software Foundation; either version 2 of the License, or
8 ** (at your option) any later version.
9 **
10 ** This program is distributed in the hope that it will be useful,
11 ** but WITHOUT ANY WARRANTY; without even the implied warranty of
12 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 ** GNU General Public License for more details.
14 **
15 ** You should have received a copy of the GNU General Public License
16 ** along with this program; if not, write to the Free Software
17 ** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
18 */
19 #include "masqmail.h"
21 header_name header_names[] = {
22 {"From", HEAD_FROM,},
23 {"Sender", HEAD_SENDER,},
24 {"To", HEAD_TO,},
25 {"Cc", HEAD_CC,},
26 {"Bcc", HEAD_BCC,},
27 {"Date", HEAD_DATE,},
28 {"Message-Id", HEAD_MESSAGE_ID,},
29 {"Reply-To", HEAD_REPLY_TO,},
30 {"Subject", HEAD_SUBJECT,},
31 {"Return-Path", HEAD_RETURN_PATH,},
32 {"Envelope-To", HEAD_ENVELOPE_TO,},
33 {"Received", HEAD_RECEIVED},
34 };
36 /* this was borrowed from exim and slightly changed */
37 gchar*
38 rec_timestamp()
39 {
40 static gchar buf[64];
41 int len;
43 time_t now = time(NULL);
44 struct tm *t = localtime(&now);
46 int diff_hour, diff_min;
47 struct tm local;
48 struct tm *gmt;
50 memcpy(&local, t, sizeof(struct tm));
51 gmt = gmtime(&now);
52 diff_min = 60 * (local.tm_hour - gmt->tm_hour) + local.tm_min - gmt->tm_min;
53 if (local.tm_year != gmt->tm_year) {
54 diff_min += (local.tm_year > gmt->tm_year) ? 1440 : -1440;
55 } else if (local.tm_yday != gmt->tm_yday) {
56 diff_min += (local.tm_yday > gmt->tm_yday) ? 1440 : -1440;
57 }
58 diff_hour = diff_min / 60;
59 diff_min = abs(diff_min - diff_hour * 60);
61 len = strftime(buf, sizeof(buf), "%a, ", &local);
62 g_snprintf(buf + len, sizeof(buf) - len, "%02d ", local.tm_mday);
63 len += strlen(buf + len);
64 len += strftime(buf + len, sizeof(buf) - len, "%b %Y %H:%M:%S", &local);
65 g_snprintf(buf + len, sizeof(buf) - len, " %+03d%02d", diff_hour, diff_min);
67 return buf;
68 }
70 /*
71 ** finds list of headers matching id
72 ** if id == HEAD_UNKNOWN and header == NULL finds all unknown headers
73 ** else finds all headers matching header
74 */
75 GList*
76 find_header(GList *hdr_list, header_id id, gchar *hdr_str)
77 {
78 GList *found_list = NULL;
79 GList *node;
81 if ((id != HEAD_UNKNOWN) || !hdr_str) {
82 foreach(hdr_list, node) {
83 header *hdr = (header *) (node->data);
84 if (hdr->id == id) {
85 found_list = g_list_append(found_list, hdr);
86 }
87 }
88 return found_list;
89 }
91 foreach(hdr_list, node) {
92 header *hdr = (header *) (node->data);
93 gchar buf[64], *q = buf, *p = hdr->header;
95 while (*p != ':' && q < buf+sizeof(buf)-1 && *p) {
96 *(q++) = *(p++);
97 }
98 *q = '\0';
100 if (strcasecmp(buf, hdr_str) == 0) {
101 found_list = g_list_append(found_list, hdr);
102 }
103 }
104 return found_list;
105 }
107 void
108 header_unfold(header *hdr)
109 {
110 char *src = hdr->header;
111 char *dest = src;
112 char *p;
114 p = strchr(src, '\n');
115 if (!p || !p[1]) {
116 /* no folded header */
117 return;
118 }
120 while (*src) {
121 if (*src == '\n') {
122 /* ignore */
123 src++;
124 } else {
125 /* copy */
126 *(dest++) = *(src++);
127 }
128 }
129 *(dest++) = '\n';
130 *(dest++) = '\0';
131 }
133 /*
134 ** fold the header at maxlen chars (newline excluded)
135 ** (We exclude the newline because the RFCs deal with it this way)
136 */
137 void
138 header_fold(header *hdr, unsigned int maxlen)
139 {
140 int len = strlen(hdr->header);
141 char *src = hdr->header;
142 char *dest;
143 char *tmp;
144 char *p;
145 int valueoffset;
147 if (len <= maxlen) {
148 /* we don't need to do anything */
149 return;
150 }
152 /* strip trailing whitespace */
153 for (p=src+len-1; *p==' '||*p=='\t'||*p=='\n'; p--) {
154 *p = '\0';
155 len--;
156 printf(" trailing whitespace\n");
157 }
158 printf("stripped len: %d\n", len);
160 /*
161 ** FIXME: would be nice to have a better size calculation
162 ** (the current size + what we insert as break, twice as often as
163 ** we have breaks in the optimal case)
164 */
165 tmp = malloc(len + 2 * (len/maxlen) * strlen("\n\t"));
166 dest = tmp;
168 /* the position in hdr->header where the value part start */
169 valueoffset = hdr->value - hdr->header;
171 while (strlen(src) > maxlen) {
172 char *pp;
174 for (pp=src+maxlen; pp>src; pp--) {
175 if (*pp==' ' || *pp=='\t' || *p=='\n') {
176 break;
177 }
178 }
180 if (src == pp) {
181 /* no potential break point was found within
182 maxlen so advance further until the next */
183 for (pp=src+maxlen; *pp; pp++) {
184 if (*pp==' ' || *pp=='\t' || *p=='\n') {
185 break;
186 }
187 }
188 }
189 if (!*pp) {
190 break;
191 }
193 memcpy(dest, src, pp-src);
194 dest += pp-src;
195 *(dest++) = '\n';
196 *(dest++) = '\t';
197 while (*pp == ' ' || *pp == '\t' || *p=='\n') {
198 pp++;
199 }
200 src = pp;
201 }
202 memcpy(dest, src, strlen(src));
203 dest += strlen(src);
205 if (*(dest-1) != '\n') {
206 *dest = '\n';
207 *(dest+1) = '\0';
208 }
210 hdr->header = tmp;
211 hdr->value = hdr->header + valueoffset;
212 }
214 header*
215 create_header(header_id id, gchar *fmt, ...)
216 {
217 gchar *p;
218 header *hdr;
219 va_list args;
220 va_start(args, fmt);
222 /* g_malloc() calls exit on failure */
223 hdr = g_malloc(sizeof(header));
225 hdr->id = id;
226 hdr->header = g_strdup_vprintf(fmt, args);
227 hdr->value = NULL;
229 /*
230 ** value shall point to the first non-whitespace char in the
231 ** value part of the header line (i.e. after the first colon)
232 */
233 p = strchr(hdr->header, ':');
234 if (p) {
235 p++;
236 while (*p == ' ' || *p == '\t' || *p == '\n') {
237 p++;
238 }
239 hdr->value = (*p) ? p : NULL;
240 }
242 DEBUG(3) debugf("create_header(): %s", hdr->header);
243 /* DEBUG(3) debugf("create_header(): val: `%s'\n", hdr->value); */
245 va_end(args);
246 return hdr;
247 }
249 void
250 destroy_header(header *hdr)
251 {
252 if (hdr) {
253 if (hdr->header) {
254 g_free(hdr->header);
255 }
256 g_free(hdr);
257 }
258 }
260 header*
261 copy_header(header *hdr)
262 {
263 header *new_hdr = NULL;
265 if (hdr) {
266 new_hdr = g_malloc(sizeof(header));
267 new_hdr->id = hdr->id;
268 new_hdr->header = g_strdup(hdr->header);
269 new_hdr->value = new_hdr->header + (hdr->value - hdr->header);
270 }
271 return new_hdr;
272 }
274 header*
275 get_header(gchar *line)
276 {
277 gchar *p = line;
278 gchar buf[64], *q = buf;
279 gint i;
280 header *hdr;
282 while (*p && (*p != ':') && (q < buf+sizeof(buf)-1)) {
283 *(q++) = *(p++);
284 }
285 *q = '\0';
287 if (*p != ':') {
288 return NULL;
289 }
291 hdr = g_malloc(sizeof(header));
293 hdr->value = NULL;
294 p++;
296 while (*p && (*p == ' ' || *p == '\t')) {
297 p++;
298 }
299 hdr->value = p;
300 /*
301 ** Note: an empty value can also mean that it's only the first part
302 ** of a folded header line
303 */
305 for (i = 0; i < HEAD_NUM_IDS; i++) {
306 if (strcasecmp(header_names[i].header, buf) == 0) {
307 break;
308 }
309 }
310 hdr->id = (header_id) i;
311 hdr->header = g_strdup(line);
312 hdr->value = hdr->header + (hdr->value - line);
314 DEBUG(4) debugf("header: %d = %s", hdr->id, hdr->header);
315 /* Note: This only outputs the first line if the header is folded */
317 return hdr;
318 }