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