masqmail

annotate src/queue.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 41958685480d
children bdbedce60247
rev   line source
meillo@367 1 /*
meillo@367 2 ** MasqMail
meillo@367 3 ** Copyright (C) 1999-2001 Oliver Kurth
meillo@367 4 ** Copyright (C) 2010 markus schnalke <meillo@marmaro.de>
meillo@367 5 **
meillo@367 6 ** This program is free software; you can redistribute it and/or modify
meillo@367 7 ** it under the terms of the GNU General Public License as published by
meillo@367 8 ** the Free Software Foundation; either version 2 of the License, or
meillo@367 9 ** (at your option) any later version.
meillo@367 10 **
meillo@367 11 ** This program is distributed in the hope that it will be useful,
meillo@367 12 ** but WITHOUT ANY WARRANTY; without even the implied warranty of
meillo@367 13 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
meillo@367 14 ** GNU General Public License for more details.
meillo@367 15 **
meillo@367 16 ** You should have received a copy of the GNU General Public License
meillo@367 17 ** along with this program; if not, write to the Free Software
meillo@367 18 ** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
meillo@0 19 */
meillo@0 20
meillo@0 21 #include <sys/stat.h>
meillo@0 22 #include <glob.h>
meillo@0 23
meillo@15 24 #include "masqmail.h"
meillo@15 25
meillo@10 26 static void
meillo@10 27 mix_arr(int *buf, int len)
meillo@0 28 {
meillo@10 29 int i;
meillo@0 30
meillo@10 31 for (i = 0; i < len; i++)
meillo@10 32 buf[i] = i;
meillo@10 33 for (i = 0; i < len - 1; i++) {
meillo@10 34 int j = (int) ((float) (len - i) * ((float) rand()) / (RAND_MAX + 1.0));
meillo@10 35 int tmp;
meillo@0 36
meillo@10 37 if (i != j) {
meillo@10 38 tmp = buf[i];
meillo@10 39 buf[i] = buf[j];
meillo@10 40 buf[j] = tmp;
meillo@10 41 }
meillo@10 42 }
meillo@0 43 }
meillo@0 44
meillo@10 45 GList*
meillo@348 46 read_queue(void)
meillo@0 47 {
meillo@10 48 GList *msg_list = NULL;
meillo@10 49 glob_t gl;
meillo@10 50 gchar *pattern;
meillo@10 51 int i, *idx_arr;
meillo@0 52
meillo@367 53 /*
meillo@367 54 ** Escaping the question marks prevents them from being
meillo@367 55 ** interpreted as trigraphs
meillo@367 56 */
meillo@38 57 pattern = g_strdup_printf("%s/input/?????\?-??\?-?\?-H", conf.spool_dir);
meillo@10 58 gl.gl_offs = 0;
meillo@10 59 glob(pattern, 0, NULL, &gl);
meillo@0 60
meillo@10 61 g_free(pattern);
meillo@0 62
meillo@10 63 DEBUG(4) {
meillo@10 64 int i;
meillo@10 65 for (i = 0; i < gl.gl_pathc; i++) {
meillo@10 66 debugf("spoolfile: %s\n", gl.gl_pathv[i]);
meillo@10 67 }
meillo@10 68 }
meillo@0 69
meillo@10 70 idx_arr = g_malloc(sizeof(int) * gl.gl_pathc);
meillo@10 71 mix_arr(idx_arr, gl.gl_pathc);
meillo@0 72
meillo@10 73 for (i = 0; i < gl.gl_pathc; i++) {
meillo@10 74 gchar *uid;
meillo@0 75
meillo@10 76 /* copy 13 chars, offset spooldir path + 7 chars for /input/ */
meillo@10 77 /* uid length = 6 chars + '-' + 3 chars + '-' + 2 = 13 chars */
meillo@10 78 uid = g_strndup(&(gl.gl_pathv[idx_arr[i]][strlen(conf.spool_dir) + 7]), 13);
meillo@0 79
meillo@10 80 DEBUG(5) debugf("uid: %s\n", uid);
meillo@0 81
meillo@349 82 msg_list = g_list_append(msg_list, msg_spool_read(uid));
meillo@0 83
meillo@10 84 DEBUG(5) debugf("after read spool file for %s\n", uid);
meillo@0 85
meillo@10 86 g_free(uid);
meillo@10 87 }
meillo@10 88 return msg_list;
meillo@0 89 }
meillo@0 90
meillo@10 91 gboolean
meillo@10 92 queue_run()
meillo@0 93 {
meillo@10 94 GList *msg_list;
meillo@10 95 gboolean ok = TRUE;
meillo@0 96
meillo@10 97 logwrite(LOG_NOTICE, "Starting queue run.\n");
meillo@348 98 msg_list = read_queue();
meillo@277 99 if (msg_list) {
meillo@10 100 ok = deliver_msg_list(msg_list, DLVR_ALL);
meillo@277 101 DEBUG(5) debugf(" deliver_msg_list() returned: %d\n", ok);
meillo@10 102 destroy_msg_list(msg_list);
meillo@10 103 }
meillo@10 104 logwrite(LOG_NOTICE, "Finished queue run.\n");
meillo@0 105
meillo@10 106 return ok;
meillo@0 107 }
meillo@0 108
meillo@10 109 gboolean
meillo@10 110 queue_run_online()
meillo@0 111 {
meillo@277 112 GList *msg_list;
meillo@10 113 gboolean ok = TRUE;
meillo@0 114
meillo@10 115 logwrite(LOG_NOTICE, "Starting online queue run.\n");
meillo@348 116 msg_list = read_queue();
meillo@277 117 if (msg_list) {
meillo@10 118 ok = deliver_msg_list(msg_list, DLVR_ONLINE);
meillo@277 119 DEBUG(5) debugf(" deliver_msg_list() returned: %d\n", ok);
meillo@10 120 destroy_msg_list(msg_list);
meillo@10 121 }
meillo@10 122 logwrite(LOG_NOTICE, "Finished online queue run.\n");
meillo@0 123
meillo@10 124 return ok;
meillo@0 125 }
meillo@0 126
meillo@10 127 static gchar*
meillo@10 128 format_difftime(double secs)
meillo@0 129 {
meillo@10 130 if (secs > 86400)
meillo@10 131 return g_strdup_printf("%.1fd", secs / 86400);
meillo@10 132 else if (secs > 3600)
meillo@10 133 return g_strdup_printf("%.1fh", secs / 3600);
meillo@10 134 else if (secs > 60)
meillo@10 135 return g_strdup_printf("%.1fm", secs / 60);
meillo@10 136 else
meillo@10 137 return g_strdup_printf("%.0fs", secs);
meillo@10 138 }
meillo@0 139
meillo@10 140 void
meillo@10 141 queue_list()
meillo@0 142 {
meillo@10 143 GList *msg_list;
meillo@10 144 GList *msg_node;
meillo@0 145
meillo@348 146 msg_list = read_queue();
meillo@0 147
meillo@82 148 if (msg_list == NULL) {
meillo@82 149 printf("mail queue is empty.\n");
meillo@82 150 return;
meillo@82 151 }
meillo@0 152
meillo@82 153 foreach(msg_list, msg_node) {
meillo@82 154 message *msg = (message *) (msg_node->data);
meillo@82 155 GList *rcpt_node;
meillo@82 156 gchar *size_str = NULL;
meillo@82 157 gchar *time_str = NULL;
meillo@82 158 gchar *host_str = NULL;
meillo@82 159 gchar *ident_str = NULL;
meillo@0 160
meillo@82 161 if (msg->data_size >= 0)
meillo@82 162 size_str = g_strdup_printf(" size=%d", msg->data_size);
meillo@82 163 if (msg->received_time > 0) {
meillo@82 164 gchar *tmp_str;
meillo@82 165 time_str = g_strdup_printf(" age=%s", tmp_str = format_difftime(difftime(time(NULL), msg->received_time)));
meillo@82 166 g_free(tmp_str);
meillo@82 167 }
meillo@82 168 if (msg->received_host != NULL)
meillo@82 169 host_str = g_strdup_printf(" host=%s", msg->received_host);
meillo@82 170 if (msg->ident != NULL)
meillo@82 171 ident_str = g_strdup_printf(" ident=%s", msg->ident);
meillo@0 172
meillo@82 173 printf("%s <= %s%s%s%s%s\n", msg->uid, addr_string(msg->return_path), size_str ? size_str : "",
meillo@82 174 time_str ? time_str : "", host_str ? host_str : "", ident_str ? ident_str : "");
meillo@0 175
meillo@82 176 if (size_str)
meillo@82 177 g_free(size_str);
meillo@82 178 if (time_str)
meillo@82 179 g_free(time_str);
meillo@82 180 if (host_str)
meillo@82 181 g_free(host_str);
meillo@82 182 if (ident_str)
meillo@82 183 g_free(ident_str);
meillo@10 184
meillo@82 185 foreach(msg->rcpt_list, rcpt_node) {
meillo@82 186 address *rcpt = (address *) (rcpt_node->data);
meillo@82 187
meillo@82 188 printf(" %s %s\n", addr_is_delivered(rcpt) ? "=>" : (addr_is_failed(rcpt) ? "!=" : "=="), addr_string(rcpt));
meillo@10 189 }
meillo@82 190 g_free(msg);
meillo@82 191 }
meillo@10 192 }
meillo@10 193
meillo@10 194 gboolean
meillo@366 195 queue_delete(gchar *uid)
meillo@0 196 {
meillo@10 197 gboolean hdr_ok = TRUE;
meillo@10 198 gboolean dat_ok = TRUE;
meillo@10 199 gchar *hdr_name = g_strdup_printf("%s/input/%s-H", conf.spool_dir, uid);
meillo@10 200 gchar *dat_name = g_strdup_printf("%s/input/%s-D", conf.spool_dir, uid);
meillo@10 201 struct stat stat_buf;
meillo@0 202
meillo@82 203 if (!spool_lock(uid)) {
meillo@10 204 fprintf(stderr, "message %s is locked.\n", uid);
meillo@10 205 return FALSE;
meillo@10 206 }
meillo@0 207
meillo@82 208 if (stat(hdr_name, &stat_buf) == 0) {
meillo@82 209 if (unlink(hdr_name) != 0) {
meillo@82 210 fprintf(stderr, "could not unlink %s: %s\n", hdr_name, strerror(errno));
meillo@82 211 hdr_ok = FALSE;
meillo@82 212 }
meillo@82 213 } else {
meillo@82 214 fprintf(stderr, "could not stat file %s: %s\n", hdr_name, strerror(errno));
meillo@82 215 hdr_ok = FALSE;
meillo@82 216 }
meillo@82 217 if (stat(dat_name, &stat_buf) == 0) {
meillo@82 218 if (unlink(dat_name) != 0) {
meillo@82 219 fprintf(stderr, "could not unlink %s: %s\n", dat_name, strerror(errno));
meillo@82 220 dat_ok = FALSE;
meillo@82 221 }
meillo@82 222 } else {
meillo@82 223 fprintf(stderr, "could not stat file %s: %s\n", dat_name, strerror(errno));
meillo@82 224 dat_ok = FALSE;
meillo@82 225 }
meillo@82 226 printf("message %s deleted\n", uid);
meillo@82 227
meillo@82 228 spool_unlock(uid);
meillo@82 229
meillo@10 230 return (dat_ok && hdr_ok);
meillo@0 231 }