Mercurial > masqmail
comparison src/local.c @ 205:4fd237550525
REMOVED MAILDIR SUPPORT
if you want to deliver to maildir, use an MDA like procmail
masqmail can pass mail to an MDA by setting `mda' in masqmail.conf
author | meillo@marmaro.de |
---|---|
date | Fri, 16 Jul 2010 16:38:50 +0200 |
parents | d1c53e76096f |
children | 996b53a50f55 |
comparison
equal
deleted
inserted
replaced
204:5745edd5b769 | 205:4fd237550525 |
---|---|
142 } | 142 } |
143 | 143 |
144 return ok; | 144 return ok; |
145 } | 145 } |
146 | 146 |
147 #ifdef ENABLE_MAILDIR | |
148 gboolean | |
149 maildir_out(message * msg, GList * hdr_list, gchar * user, guint flags) | |
150 { | |
151 struct passwd *pw; | |
152 gboolean ok = FALSE; | |
153 | |
154 /* headers may be special for a local delivery */ | |
155 if (hdr_list == NULL) | |
156 hdr_list = msg->hdr_list; | |
157 | |
158 if ((pw = getpwnam(user))) { | |
159 uid_t saved_uid = geteuid(); | |
160 gid_t saved_gid = getegid(); | |
161 gboolean uid_ok = TRUE, gid_ok = TRUE; | |
162 | |
163 if (!conf.run_as_user) { | |
164 uid_ok = (seteuid(0) == 0); | |
165 if (uid_ok) { | |
166 gid_ok = (setegid(conf.mail_gid) == 0); | |
167 uid_ok = (seteuid(pw->pw_uid) == 0); | |
168 } | |
169 } | |
170 | |
171 DEBUG(5) debugf("running as euid %d, egid %d\n", geteuid(), getegid()); | |
172 | |
173 if (uid_ok && gid_ok) { | |
174 char *path = g_strdup_printf("%s/Maildir", pw->pw_dir); | |
175 struct stat statbuf; | |
176 int ret; | |
177 | |
178 DEBUG(5) debugf(" path = %s\n", path); | |
179 | |
180 ok = TRUE; | |
181 ret = stat(path, &statbuf); | |
182 if (ret != 0) { | |
183 ok = FALSE; | |
184 if (errno == ENOENT) { | |
185 logwrite(LOG_NOTICE, "directory %s does not exist, creating\n", path); | |
186 if (mkdir(path, 0700) == 0) | |
187 ok = TRUE; | |
188 } else | |
189 logwrite(LOG_ALERT, "stat of %s failed: %s\n", path, strerror(errno)); | |
190 } | |
191 if (ok) { | |
192 ok = FALSE; | |
193 ret = stat(path, &statbuf); | |
194 if (S_ISDIR(statbuf.st_mode)) { | |
195 gchar *subdirs[] = { "tmp", "new", "cur" }; | |
196 int i; | |
197 for (i = 0; i < 3; i++) { | |
198 char *path1 = g_strdup_printf("%s/%s", path, subdirs[i]); | |
199 ret = stat(path1, &statbuf); | |
200 if (ret != 0) { | |
201 if (errno == ENOENT) { | |
202 logwrite(LOG_NOTICE, "directory %s does not exist, creating\n", path1); | |
203 if (mkdir(path1, 0700) != 0) | |
204 break; | |
205 } | |
206 } | |
207 g_free(path1); | |
208 } | |
209 if (i == 3) { | |
210 FILE *out; | |
211 mode_t saved_mode = umask(066); | |
212 /* the qmail style unique works only if delivering with different process. | |
213 We do not fork for each delivery, so our uid is more unique. | |
214 Hope it is compatible with all MUAs. | |
215 */ | |
216 gchar *filename = g_strdup_printf("%s/tmp/%s.%s", path, msg->uid, conf.host_name); | |
217 | |
218 DEBUG(5) debugf("filename = %s\n", filename); | |
219 | |
220 if ((out = fopen(filename, "w"))) { | |
221 gchar *newname = g_strdup_printf("%s/new/%s.%s", path, msg->uid, conf.host_name); | |
222 message_stream(out, msg, hdr_list, flags); | |
223 ok = TRUE; | |
224 if (fflush(out) == EOF) | |
225 ok = FALSE; | |
226 else if (fdatasync(fileno(out)) != 0) { | |
227 if (errno != EINVAL) | |
228 /* some fs do not support this.. I hope this also means that it is not necessary */ | |
229 ok = FALSE; | |
230 } | |
231 fclose(out); | |
232 if (rename(filename, newname) != 0) { | |
233 ok = FALSE; | |
234 logwrite(LOG_ALERT, "moving %s to %s failed: %s", filename, newname, strerror(errno)); | |
235 } | |
236 g_free(newname); | |
237 } | |
238 umask(saved_mode); | |
239 g_free(filename); | |
240 } | |
241 } else { | |
242 logwrite(LOG_ALERT, "%s is not a directory\n", path); | |
243 errno = ENOTDIR; | |
244 } | |
245 } | |
246 if (!conf.run_as_user) { | |
247 uid_ok = (seteuid(0) == 0); | |
248 if (uid_ok) { | |
249 gid_ok = (setegid(saved_gid) == 0); | |
250 uid_ok = (seteuid(saved_uid) == 0); | |
251 } | |
252 } | |
253 if (!uid_ok || !gid_ok) { | |
254 /* FIXME: if this fails we HAVE to exit, because we shall not run | |
255 with some users id. But we do not return, and so this message | |
256 will not be finished, so the user will get the message again | |
257 next time a delivery is attempted... */ | |
258 logwrite(LOG_ALERT, "could not set back uid or gid after local delivery: %s\n", strerror(errno)); | |
259 exit(EXIT_FAILURE); | |
260 } | |
261 g_free(path); | |
262 } else { | |
263 logwrite(LOG_ALERT, "could not set uid or gid for local delivery, uid = %d: %s\n", pw->pw_uid, strerror(errno)); | |
264 } | |
265 } else { | |
266 logwrite(LOG_ALERT, "could not find password entry for user %s\n", user); | |
267 errno = ENOENT; /* getpwnam does not set errno correctly */ | |
268 } | |
269 return ok; | |
270 } | |
271 #endif | |
272 | |
273 gboolean | 147 gboolean |
274 pipe_out(message * msg, GList * hdr_list, address * rcpt, gchar * cmd, guint flags) | 148 pipe_out(message * msg, GList * hdr_list, address * rcpt, gchar * cmd, guint flags) |
275 { | 149 { |
276 gchar *envp[40]; | 150 gchar *envp[40]; |
277 FILE *out; | 151 FILE *out; |