From ca4b341b893878f6c46401ae0649cef801e6f6aa Mon Sep 17 00:00:00 2001 From: Baptiste Daroussin Date: Wed, 5 Jan 2022 11:00:27 +0100 Subject: [PATCH] mailqueue: factorize the code opening a file in the queue --- include/mlmmj.h | 2 +- include/prepstdreply.h | 2 +- src/mlmmj-process.c | 137 +++++++++++++++++++---------------------- src/mlmmj.c | 24 +++++++- src/prepstdreply.c | 35 ++++------- src/send_digest.c | 82 +++++++++++------------- 6 files changed, 135 insertions(+), 147 deletions(-) diff --git a/include/mlmmj.h b/include/mlmmj.h index 82655d4c..3c1dd4da 100644 --- a/include/mlmmj.h +++ b/include/mlmmj.h @@ -122,7 +122,7 @@ void mlmmj_list_init(struct mlmmj_list *list); bool mlmmj_list_open(struct mlmmj_list *list); void mlmmj_list_close(struct mlmmj_list *list); void queuedmail_free(struct queuedmail *q); -struct queuedmail *queuedmail_new(void); +struct queuedmail *queuedmail_new(struct mlmmj_list *list); #define MY_ASSERT(expression) if (!(expression)) { \ errno = 0; \ diff --git a/include/prepstdreply.h b/include/prepstdreply.h index 7c6153fd..4f58c2e6 100644 --- a/include/prepstdreply.h +++ b/include/prepstdreply.h @@ -58,7 +58,7 @@ text *open_text_file(struct mlmmj_list *list, const char *filename); text *open_text(struct mlmmj_list *list, const char *purpose, const char *action, const char *reason, const char *type, const char *compat); void register_unformatted(text *txt, const char *token, const char *subst); -void register_originalmail(text *txt, const char *mailname); +void register_originalmail(text *txt, int fd); void register_formatted(text *txt, const char *token, rewind_function rew, get_function get, void * state); char *get_processed_text_line(text *txt, int headers, struct mlmmj_list *list); diff --git a/src/mlmmj-process.c b/src/mlmmj-process.c index 5b557b83..de41f5c7 100644 --- a/src/mlmmj-process.c +++ b/src/mlmmj-process.c @@ -170,7 +170,9 @@ static void newmoderated(struct mlmmj_list *list, const char *mailfilename, register_unformatted(txt, "moderators", "%moderators%"); /* DEPRECATED */ register_formatted(txt, "moderators", rewind_memory_lines, get_memory_line, mls); - register_originalmail(txt, mailfilename); + int fd = open(mailfilename, O_RDONLY); + register_originalmail(txt, fd); + close(fd); queuefilename = prepstdreply(txt, list, "$listowner$", to, replyto, false); MY_ASSERT(queuefilename); close_text(txt); @@ -226,7 +228,9 @@ static void newmoderated(struct mlmmj_list *list, const char *mailfilename, register_unformatted(txt, "moderators", "%moderators%"); /* DEPRECATED */ register_formatted(txt, "moderators", rewind_memory_lines, get_memory_line, mls); - register_originalmail(txt, mailfilename); + int fd2 = open(mailfilename, O_RDONLY); + register_originalmail(txt, fd2); + close(fd2); q = prepqstdreply(txt, list, "$listowner$", efromsender, NULL); MY_ASSERT(q); close_text(txt); @@ -439,7 +443,7 @@ static void print_help(const char *prg) static void send_denymail(struct mlmmj_list *list, const char *cause, const char *subcause, char *causestr, const char *posteraddr, const char *subject, - char *donemailname, const char *mailfile) + struct queuedmail *done, const char *mailfile) { char *fromaddr; text *txt; @@ -453,13 +457,13 @@ send_denymail(struct mlmmj_list *list, const char *cause, const char *subcause, register_unformatted(txt, "posteraddr", posteraddr); if (causestr != NULL) register_unformatted(txt, cause, causestr); - register_originalmail(txt, donemailname); + register_originalmail(txt, done->fd); q = prepqstdreply(txt, list, "$listowner$", posteraddr, NULL); MY_ASSERT(q); close_text(txt); - unlink(donemailname); + unlinkat(list->queuefd, done->name, 0); unlink(mailfile); - free(donemailname); + queuedmail_free(q); free(causestr); memset(&mh, 0, sizeof(mh)); mh.to = posteraddr; @@ -473,12 +477,12 @@ int main(int argc, char **argv) { int i, j, opt, noprocess = 0, moderated = 0, send = 0; enum modreason modreason; - int hdrfd, footfd, rawmailfd, donemailfd, omitfd; + int hdrfd, footfd, rawmailfd, omitfd; int addrtocc, intocc = 0, findaddress = 0; int maxmailsize = 0; int notmetoo = 0; int subonlypost = 0, modonlypost = 0, modnonsubposts = 0, foundaddr = 0; - char *mailfile = NULL, *donemailname = NULL; + char *mailfile = NULL, *donemailname; char *randomstr = NULL, *mqueuename, *omitfilename; char *mlmmjsend, *mlmmjsub, *mlmmjunsub, *mlmmjbounce; char *bindir, *subjectprefix, *discardname; @@ -498,6 +502,7 @@ int main(int argc, char **argv) struct strlist *delheaders = NULL; struct strlist allheaders; struct strlist *listaddrs = NULL; + struct queuedmail *q; struct mailhdr readhdrs[] = { { "From:", 0, NULL }, { "To:", 0, NULL }, @@ -565,28 +570,16 @@ int main(int argc, char **argv) } } - do { - free(donemailname); - free(randomstr); - randomstr = random_str(); - xasprintf(&donemailname, "%s/queue/%s", list.dir, randomstr); - - donemailfd = open(donemailname, O_RDWR|O_CREAT|O_EXCL, - S_IRUSR|S_IWUSR); - - } while ((donemailfd < 0) && (errno == EEXIST)); - - if(donemailfd < 0) { - log_error(LOG_ARGS, "could not create %s", donemailname); - free(donemailname); + q = queuedmail_new(&list); + if (q == NULL) { + log_error(LOG_ARGS, "could not create queued mail"); exit(EXIT_FAILURE); } #if 0 log_error(LOG_ARGS, "donemailname = [%s]\n", donemailname); #endif if((rawmailfd = open(mailfile, O_RDONLY)) < 0) { - unlink(donemailname); - free(donemailname); + unlinkat(list.queuefd, q->name, 0); log_error(LOG_ARGS, "could not open() input mail file"); exit(EXIT_FAILURE); } @@ -612,7 +605,7 @@ int main(int argc, char **argv) subjectprefix = ctrlvalue(&list, "prefix"); - if(do_all_the_voodoo_here(rawmailfd, donemailfd, hdrfd, footfd, + if(do_all_the_voodoo_here(rawmailfd, q->fd, hdrfd, footfd, delheaders, readhdrs, &allheaders, subjectprefix) < 0) { log_error(LOG_ARGS, "Error in do_all_the_voodoo_here"); @@ -624,7 +617,7 @@ int main(int argc, char **argv) free(delheaders->strs); close(rawmailfd); - close(donemailfd); + queuedmail_free(q); if(hdrfd >= 0) close(hdrfd); @@ -725,8 +718,7 @@ int main(int argc, char **argv) log_error(LOG_ARGS, "fromemails.emaillist[%d] = %s\n", i, fromemails.emaillist[i]); rename(mailfile, discardname); - unlink(donemailname); - free(donemailname); + unlinkat(list.queuefd, q->name, 0); free(discardname); free(randomstr); /* TODO: free emailstructs */ @@ -760,6 +752,8 @@ int main(int argc, char **argv) if (!subject) subject = xstrdup(""); if(recipextra) { + char *donemailname; + xasprintf(&donemailname, "%s/queue/%s", list.dir, q->name); xasprintf(&owner, "%s/control/owner", list.dir); if(owner && strcmp(recipextra, "owner") == 0) { /* Why is this here, and not in listcontrol() ? @@ -778,13 +772,7 @@ int main(int argc, char **argv) "input mail file"); exit(EXIT_FAILURE); } - if((donemailfd = open(donemailname, - O_WRONLY|O_TRUNC)) < 0) { - log_error(LOG_ARGS, "could not open() " - "output mail file"); - exit(EXIT_FAILURE); - } - if(do_all_the_voodoo_here(rawmailfd, donemailfd, -1, + if(do_all_the_voodoo_here(rawmailfd, q->fd, -1, -1, delheaders, NULL, &allheaders, NULL) < 0) { log_error(LOG_ARGS, "do_all_the_voodoo_here"); @@ -794,7 +782,7 @@ int main(int argc, char **argv) free(delheaders->strs[i]); free(delheaders->strs); close(rawmailfd); - close(donemailfd); + queuedmail_free(q); unlink(mailfile); log_oper(list.dir, OPLOGFNAME, "mlmmj-process: sending" " mail from %s to owner", @@ -825,8 +813,9 @@ int main(int argc, char **argv) maxmailsizestr = ctrlvalue(&list, "maxmailsize"); if(maxmailsizestr) { maxmailsize = atol(maxmailsizestr); - if(stat(donemailname, &st) < 0) { - log_error(LOG_ARGS, "stat(%s,..) failed", donemailname); + if(fstat(q->fd, &st) < 0) { + log_error(LOG_ARGS, "stat(%s/queue/%s,..) failed", + list.dir, q->name); exit(EXIT_FAILURE); } @@ -834,17 +823,16 @@ int main(int argc, char **argv) if (statctrl(&list, "nomaxmailsizedenymails")) { errno = 0; - log_error(LOG_ARGS, "Discarding %s due to" + log_error(LOG_ARGS, "Discarding %s/queue/%s due to" " size limit (%d bytes too big)", - donemailname, (st.st_size - maxmailsize)); - unlink(donemailname); + list.dir, q->name, (st.st_size - maxmailsize)); + unlinkat(list.queuefd, q->name, 0); unlink(mailfile); - free(donemailname); free(maxmailsizestr); exit(EXIT_SUCCESS); } send_denymail(&list, "maxmailsize", "maxmailsize", - maxmailsizestr, posteraddr, subject, donemailname, mailfile); + maxmailsizestr, posteraddr, subject, q, mailfile); } } @@ -858,8 +846,8 @@ int main(int argc, char **argv) log_error(LOG_ARGS, "Discarding %s due to missing envelope" " from address", mailfile); rename(mailfile, discardname); - unlink(donemailname); - free(donemailname); + unlinkat(list.queuefd, q->name, 0); + queuedmail_free(q); free(discardname); free(randomstr); /* TODO: free emailstructs */ @@ -879,12 +867,12 @@ int main(int argc, char **argv) " and From: was the list or" " notoccdenymails was set", mailfile); - unlink(donemailname); - free(donemailname); + unlinkat(list.queuefd, q->name, 0); + queuedmail_free(q); exit(EXIT_SUCCESS); } send_denymail(&list, "tocc", "notintocc", NULL, - posteraddr, subject, donemailname, mailfile); + posteraddr, subject, q, mailfile); } access_rules = ctrlvalues(&list, "access"); @@ -903,27 +891,27 @@ int main(int argc, char **argv) " address or noaccessdenymails" " was set", mailfile); - unlink(donemailname); - free(donemailname); + unlinkat(list.queuefd, q->name, 0); + queuedmail_free(q); exit(EXIT_SUCCESS); } send_denymail(&list, "access", "access", - NULL, posteraddr, subject, donemailname, mailfile); + NULL, posteraddr, subject, q, mailfile); } else if (accret == MODERATE) { moderated = 1; modreason = ACCESS; } else if (accret == DISCARD) { - xasprintf(&discardname, "%s/queue/discarded/%s", - list.dir, randomstr); + xasprintf(&discardname, "/discarded/%s", randomstr); free(randomstr); - if(rename(donemailname, discardname) < 0) { + if(renameat(list.queuefd, q->name, + list.queuefd, discardname) < 0) { log_error(LOG_ARGS, "could not rename(%s,%s)", - donemailname, discardname); - free(donemailname); + q->name, discardname); + queuedmail_free(q); free(discardname); exit(EXIT_FAILURE); } - free(donemailname); + queuedmail_free(q); free(discardname); exit(EXIT_SUCCESS); } else if (accret == SEND) { @@ -947,8 +935,8 @@ int main(int argc, char **argv) " there are sender restrictions but" " From: was the list address", mailfile); - unlink(donemailname); - free(donemailname); + unlinkat(list.queuefd, q->name, 0); + queuedmail_free(q); exit(EXIT_SUCCESS); } if(subonlypost) { @@ -972,17 +960,17 @@ int main(int argc, char **argv) log_error(LOG_ARGS, "Discarding %s because" " no{sub|mod}onlydenymails was set", mailfile); - unlink(donemailname); - free(donemailname); + unlinkat(list.queuefd, q->name, 0); + queuedmail_free(q); exit(EXIT_SUCCESS); } if (subonlypost) { send_denymail(&list, "subonlypost", - "subonlypost", NULL, posteraddr, subject, donemailname, + "subonlypost", NULL, posteraddr, subject, q, mailfile); } else if (modonlypost) { send_denymail(&list, "modonlypost", - NULL, NULL, posteraddr, subject, donemailname, + NULL, NULL, posteraddr, subject, q, mailfile); } } @@ -999,22 +987,22 @@ int main(int argc, char **argv) notmetoo = statctrl(&list, "notmetoo"); if(moderated) { - xasprintf(&mqueuename, "%s/moderation/%s", list.dir, randomstr); + xasprintf(&mqueuename, "moderation/%s", randomstr); free(randomstr); - if(rename(donemailname, mqueuename) < 0) { + if(renameat(list.queuefd, q->name, list.fd, mqueuename) < 0) { log_error(LOG_ARGS, "could not rename(%s,%s)", - donemailname, mqueuename); - free(donemailname); + q->name, mqueuename); + queuedmail_free(q); free(mqueuename); exit(EXIT_FAILURE); } - free(donemailname); + queuedmail_free(q); if (notmetoo) { xasprintf(&omitfilename, "%s.omit", mqueuename); - omitfd = open(omitfilename, O_RDWR|O_CREAT|O_EXCL, S_IRUSR|S_IWUSR); + omitfd = openat(list.fd, omitfilename, O_RDWR|O_CREAT|O_EXCL, S_IRUSR|S_IWUSR); if (omitfd < 0) { log_error(LOG_ARGS, "could not open %s", - omitfilename); + omitfilename); free(mqueuename); free(omitfilename); exit(EXIT_FAILURE); @@ -1038,20 +1026,23 @@ int main(int argc, char **argv) free(randomstr); if(noprocess) { - free(donemailname); + queuedmail_free(q); /* XXX: toemails and ccemails etc. have to be free() */ exit(EXIT_SUCCESS); } - if (notmetoo) + xasprintf(&donemailname, "%s/queue/%s", list.dir, q->name); + + if (notmetoo) { execlp(mlmmjsend, mlmmjsend, "-L", list.dir, "-o", posteraddr, "-m", donemailname, (char *)NULL); - else + } else { execlp(mlmmjsend, mlmmjsend, "-L", list.dir, "-m", donemailname, (char *)NULL); + } log_error(LOG_ARGS, "execlp() of '%s' failed", mlmmjsend); return EXIT_FAILURE; diff --git a/src/mlmmj.c b/src/mlmmj.c index 4d012fa8..38679a64 100644 --- a/src/mlmmj.c +++ b/src/mlmmj.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2021 Baptiste Daroussin + * Copyright (C) 2021-2022 Baptiste Daroussin * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to @@ -20,16 +20,20 @@ * IN THE SOFTWARE. */ +#include + #include #include #include #include #include +#include #include "xmalloc.h" #include "strgen.h" #include "mlmmj.h" #include "controls.h" +#include "log_error.h" void mlmmj_list_init(struct mlmmj_list *list) @@ -93,6 +97,7 @@ mlmmj_list_open(struct mlmmj_list *list) mlmmj_list_close(list); return (false); } + return (true); } @@ -108,9 +113,24 @@ queuedmail_free(struct queuedmail *q) } struct queuedmail * -queuedmail_new(void) +queuedmail_new(struct mlmmj_list *list) { struct queuedmail *q = xcalloc(1, sizeof(struct queuedmail)); q->fd = -1; + + do { + if (list->queuefd == -1) + list->queuefd = openat(list->fd, "queue", O_DIRECTORY); + free(q->name); + q->name = random_str(); + q->fd = openat(list->queuefd, q->name, O_RDWR|O_CREAT|O_EXCL, S_IRUSR|S_IWUSR); + } while (q->fd < 0 && (errno == EEXIST)); + + if(q->fd < 0) { + log_error(LOG_ARGS, "Could not open std mail %s", q->name); + queuedmail_free(q); + return NULL; + } + return (q); } diff --git a/src/prepstdreply.c b/src/prepstdreply.c index a3b19259..2c76bd18 100644 --- a/src/prepstdreply.c +++ b/src/prepstdreply.c @@ -119,7 +119,7 @@ struct text { char *type; source *src; substitution *substs; - char *mailname; + int mailfd; formatted *fmts; int wrapindent; int wrapwidth; @@ -495,7 +495,7 @@ text *open_text_file(struct mlmmj_list *list, const char *filename) txt->reason = NULL; txt->type = NULL; txt->substs = NULL; - txt->mailname = NULL; + txt->mailfd = -1; txt->fmts = NULL; txt->wrapindent = 0; txt->wrapwidth = 0; @@ -589,9 +589,9 @@ void register_unformatted(text *txt, const char *token, const char *replacement) } -void register_originalmail(text *txt, const char *mailname) +void register_originalmail(text *txt, int fd) { - txt->mailname = xstrdup(mailname); + txt->mailfd = dup(fd); } @@ -1037,8 +1037,7 @@ static int handle_directive(text *txt, char **line_p, char **pos_p, begin_new_source_file(txt, line_p, pos_p, width_p, fd, 0); return 0; } - } else if(strncmp(token, "originalmail", 12) == 0 && - txt->mailname != NULL) { + } else if(strncmp(token, "originalmail", 12) == 0 && txt->mailfd != -1) { token += 12; limit = 0; if (*token == '\0') { @@ -1051,9 +1050,9 @@ static int handle_directive(text *txt, char **line_p, char **pos_p, if (token != NULL) limit = atol(token); } if (limit != 0) { - int fd = open(txt->mailname, O_RDONLY); + lseek(txt->mailfd, 0, SEEK_SET); begin_new_source_file(txt, line_p, pos_p, width_p, - fd, 1); + txt->mailfd, 1); if (limit == -1) txt->src->limit = -1; else txt->src->limit = limit - 1; return 0; @@ -1566,7 +1565,7 @@ void close_text(text *txt) txt->substs = txt->substs->next; free(subst); } - if (txt->mailname != NULL) free(txt->mailname); + if (txt->mailfd != -1) close(txt->mailfd); while (txt->fmts != NULL) { fmt = txt->fmts; free(fmt->token); @@ -1764,21 +1763,9 @@ struct queuedmail *prepqstdreply(text *txt, struct mlmmj_list *list, char *str; char *tmp; char *headers[10] = { NULL }; /* relies on NULL to flag end */ - struct queuedmail *q = xcalloc(1, sizeof(struct queuedmail)); - - do { - if (list->queuefd == -1) - list->queuefd = openat(list->fd, "queue", O_DIRECTORY); - free(q->name); - q->name = random_str(); - q->fd = openat(list->queuefd, q->name, O_RDWR|O_CREAT|O_EXCL, S_IRUSR|S_IWUSR); - } while ((q->fd < 0) && (errno == EEXIST)); - - if(q->fd < 0) { - log_error(LOG_ARGS, "Could not open std mail %s", q->name); - queuedmail_free(q); - return NULL; - } + struct queuedmail *q = queuedmail_new(list); + if (q == NULL) + return (NULL); for (i=0; i<6; i++) { tmp = xstrdup("randomN"); diff --git a/src/send_digest.c b/src/send_digest.c index 69e0c640..728b2b9c 100644 --- a/src/send_digest.c +++ b/src/send_digest.c @@ -233,14 +233,15 @@ static void finish_thread_list(thread_list_state * s) int send_digest(struct mlmmj_list *list, int firstindex, int lastindex, int issue, const char *addr, const char *mlmmjsend) { - int i, fd, archivefd, status, hdrfd, r; + int i, archivefd, status, hdrfd, r; size_t len; text * txt; char buf[100]; - char *tmp, *queuename = NULL, *archivename, *subject = NULL, *line = NULL; + char *tmp, *archivename, *subject = NULL, *line = NULL; char *boundary; pid_t childpid, pid; thread_list_state * tls; + struct queuedmail *q; if (addr) { errno = 0; @@ -251,19 +252,10 @@ int send_digest(struct mlmmj_list *list, int firstindex, int lastindex, if (firstindex > lastindex) return -1; - - do { - tmp = random_str(); - free(queuename); - xasprintf(&queuename, "queue/%s", tmp); - free(tmp); - fd = openat(list->fd, queuename, O_RDWR|O_CREAT|O_EXCL, S_IRUSR|S_IWUSR); - } while ((fd < 0) && (errno == EEXIST)); - if (fd < 0) { - log_error(LOG_ARGS, "Could not open digest queue file '%s'", - queuename); - free(queuename); + q = queuedmail_new(list); + if (q == NULL) { + log_error(LOG_ARGS, "Could not open digest queue file"); return -1; } @@ -354,7 +346,7 @@ fallback_subject: free(tmp); } - r = dprintf(fd, "From: %s%shelp@%s" + r = dprintf(q->fd, "From: %s%shelp@%s" "\nMIME-Version: 1.0" "\nContent-Type: multipart/" DIGESTMIMETYPE "; " "boundary=%s" @@ -365,21 +357,20 @@ fallback_subject: if (r < 0) goto errdighdrs; - if(hdrfd >= 0 && dumpfd2fd(hdrfd, fd) < 0) { + if(hdrfd >= 0 && dumpfd2fd(hdrfd, q->fd) < 0) { goto errdighdrs; } close(hdrfd); hdrfd = -1; - if (dprintf(fd, "\n") < 0) { + if (dprintf(q->fd, "\n") < 0) { errdighdrs: - log_error(LOG_ARGS, "Could not write digest headers to '%s'", - queuename); - close(fd); - unlink(queuename); + log_error(LOG_ARGS, "Could not write digest headers to " + "'%s/queue%s'", list->dir, q->name); + unlinkat(list->queuefd, q->name, 0); + queuedmail_free(q); free(boundary); - free(queuename); if (txt != NULL) { close_text(txt); free(line); @@ -392,16 +383,16 @@ errdighdrs: if ((txt != NULL) && !statctrl(list, "nodigesttext")) { - if (dprintf(fd, "\n--%s" + if (dprintf(q->fd, "\n--%s" "\nContent-Type: text/plain; charset=UTF-8" "\nContent-Transfer-Encoding: 8bit" "\n\n", boundary) == -1) { log_error(LOG_ARGS, "Could not write digest text/plain" - " part headers to '%s'", queuename); - close(fd); - unlink(queuename); + " part headers to '%s/queue/%s'", + list->dir, q->name); + unlinkat(list->queuefd, q->name, 0); + queuedmail_free(q); free(boundary); - free(queuename); if (txt != NULL) { close_text(txt); free(line); @@ -414,7 +405,7 @@ errdighdrs: if (line == NULL) break; len = strlen(line); line[len] = '\n'; - if(dprintf(fd, "%s", line) < 0) { + if(dprintf(q->fd, "%s", line) < 0) { free(line); log_error(LOG_ARGS, "Could not write" " std mail"); @@ -440,47 +431,46 @@ errdighdrs: if (archivefd < 0) continue; - if (dprintf(fd, "\n--%s" + if (dprintf(q->fd, "\n--%s" "\nContent-Type: message/rfc822" "\nContent-Disposition: inline; filename=\"%s_%d.eml\"", boundary, list->name, i) == -1) { log_error(LOG_ARGS, "Could not write digest part " "headers for archive index %d to " - "'%s'", i, queuename); - close(fd); + "'%s/%s'", i, list->dir, q->name); + unlinkat(list->queuefd, q->name, 0); + queuedmail_free(q); close(archivefd); - unlink(queuename); free(boundary); - free(queuename); return -1; } - if (dumpfd2fd(archivefd, fd) < 0) { + if (dumpfd2fd(archivefd, q->fd) < 0) { log_error(LOG_ARGS, "Could not write digest part %d " - "to '%s'", i, - queuename); - close(fd); + "to '%s/queue/%s'", i, list->dir, + q->name); + unlinkat(list->queuefd, q->name, 0); + queuedmail_free(q); close(archivefd); - unlink(queuename); free(boundary); - free(queuename); return -1; } close(archivefd); } - if (dprintf(fd, "\n--%s--\n", boundary) == -1) { - log_error(LOG_ARGS, "Could not write digest end to '%s'", - queuename); - close(fd); - unlink(queuename); + if (dprintf(q->fd, "\n--%s--\n", boundary) == -1) { + log_error(LOG_ARGS, "Could not write digest end to '%s/queue/%s'", + list->dir, q->name); + unlinkat(list->queuefd, q->name, 0); + queuedmail_free(q); free(boundary); - free(queuename); return -1; } - close(fd); + char *queuename; + xasprintf(&queuename, "%s/queue/%s", list->dir, q->name); + queuedmail_free(q); free(boundary); childpid = fork(); -- 2.47.3