masqmail

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