masqmail

view src/fail_msg.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 b27f66555ba8
children
line source
1 /*
2 ** MasqMail
3 ** Copyright (C) 2000-2001 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., 675 Mass Ave, Cambridge, MA 02139, USA.
18 */
20 #include <sys/wait.h>
22 #include "masqmail.h"
23 #include "peopen.h"
24 #include "readsock.h"
26 gboolean
27 fail_msg(message *msg, gchar *template, GList *failed_rcpts, gchar *err_fmt,
28 va_list args)
29 {
30 gboolean ok = FALSE;
31 address *ret_path = NULL;
33 /* do not bounce bounces, send to postmaster instead */
34 if (msg->return_path->local_part[0] == '\0') {
35 GList *node;
37 ret_path = create_address_qualified("postmaster", TRUE,
38 conf.host_name);
39 foreach(failed_rcpts, node) {
40 address *addr = (address *) (node->data);
42 if (addr_isequal_parent(addr, ret_path, strcasecmp)) {
43 logwrite(LOG_ALERT, "%s == %s: postmaster "
44 "address failed\n", msg->uid,
45 addr_string(ret_path));
46 return FALSE;
47 }
48 }
49 } else
50 ret_path = copy_address(msg->return_path);
52 DEBUG(1) debugf("sending failure notice to %s.\n",
53 addr_string(ret_path));
55 if (template) {
56 FILE *file;
57 GList *var_table = var_table_conf(var_table_msg(NULL, msg));
58 gchar *err_msg = g_strdup_vprintf(err_fmt, args);
60 var_table = g_list_prepend(var_table,
61 create_pair_string("err_msg", err_msg));
62 g_free(err_msg);
64 if ((file = fopen(template, "r"))) {
65 FILE *out;
66 gchar *cmd;
67 pid_t pid;
69 cmd = g_strdup_printf(SBINDIR "/masqmail -oi -f <> %s@%s", ret_path->local_part, ret_path->domain);
70 if (!(out = peidopen(cmd, "w", environ, &pid,
71 conf.mail_uid, conf.mail_gid))) {
72 logwrite(LOG_ERR, "peopen failed: %s\n",
73 strerror(errno));
74 } else {
75 gchar fmt[256], line[256];
76 int status, ret;
78 while ((ret = read_sockline(file, fmt, 256, 0, 0)) > 0) {
79 if (fmt[0] == '@') {
80 GList *node;
81 if (strncmp(fmt, "@failed_rcpts", 13) == 0) {
82 foreach(failed_rcpts, node) {
83 address *rcpt = (address *) (node->data);
84 fprintf(out, "\t%s\n", addr_string(rcpt));
85 }
86 } else if (strncmp(fmt, "@msg_headers", 12) == 0) {
87 foreach(msg->hdr_list, node) {
88 header *hdr = (header *) (node->data);
89 fputs(hdr->header, out);
90 }
91 } else if (strncmp(fmt, "@msg_body", 9) == 0) {
92 /* we may have to read the data at this point and remember if we did */
93 gboolean flag = (msg->data_list == NULL);
94 if (flag) {
95 if (!spool_read_data(msg)) {
96 logwrite(LOG_ALERT, "could not open data spool file %s\n", msg->uid);
97 }
98 }
99 foreach(msg->data_list, node) {
100 gchar *line = (gchar *) (node->data);
101 fputs(line, out);
102 }
103 if (flag)
104 msg_free_data(msg);
105 }
106 } else {
107 expand(var_table, fmt, line, 256);
108 fputs(line, out);
109 }
110 }
112 fclose(out);
113 waitpid(pid, &status, 0);
114 if ((WEXITSTATUS(status) != 0) ||
115 WIFSIGNALED(status)) {
116 if (WEXITSTATUS(status)) {
117 logwrite(LOG_WARNING, "child returned %d\n", WEXITSTATUS(status));
118 }
119 if (WIFSIGNALED(status)) {
120 logwrite(LOG_WARNING, "child got signal: %d\n", WTERMSIG(status));
121 }
122 } else {
123 ok = TRUE;
124 }
125 }
126 g_free(cmd);
127 fclose(file);
128 } else {
129 logwrite(LOG_ALERT, "could not open failure message "
130 "template %s: %s\n",
131 conf.errmsg_file, strerror(errno));
132 }
134 destroy_table(var_table);
135 }
137 destroy_address(ret_path);
139 return ok;
140 }
142 /*
143 ** ival : |--|--|----|--------|--------|
144 ** warned: |-------W-------------W------
145 ** result: |nnnyyyynnnnyyyyyyyyyynnnnnnn
146 */
147 static gboolean
148 warn_msg_is_due(message *msg)
149 {
150 time_t now = time(NULL);
152 GList *node;
153 for (node = g_list_last(conf.warn_intervals); node;
154 node = g_list_previous(node)) {
155 gchar *str_ival = (gchar *) (node->data);
156 gint ival = time_interval(str_ival);
157 if (ival < 0) {
158 logwrite(LOG_WARNING, "invalid time interval: %s\n",
159 str_ival);
160 } else {
161 DEBUG(5) debugf("ival = %d\n", ival);
162 DEBUG(5) debugf("now - msg->received_time = %d\n",
163 now - msg->received_time);
164 if ((now - msg->received_time) > ival) {
165 if (msg->warned_time == 0) {
166 return TRUE;
167 }
168 if ((msg->warned_time - msg->received_time) <
169 ival) {
170 return TRUE;
171 }
172 }
173 }
174 }
175 return FALSE;
176 }
178 gboolean
179 warn_msg(message *msg, gchar *template, GList *defered_rcpts, gchar *err_fmt,
180 va_list args)
181 {
182 time_t now = time(NULL);
184 if (warn_msg_is_due(msg)) {
185 if (fail_msg(msg, template, defered_rcpts, err_fmt, args)) {
186 msg->warned_time = now;
187 return TRUE;
188 } else {
189 return FALSE;
190 }
191 }
192 return TRUE;
193 }