/*
+ * Copyright (c) 2008-2014, Simon Schubert <2@0x2c.org>.
* Copyright (c) 2008 The DragonFly Project. All rights reserved.
*
* This code is derived from software contributed to The DragonFly Project
- * by Simon 'corecode' Schubert <corecode@fs.ei.tum.de>.
+ * by Simon Schubert <2@0x2c.org>.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* SUCH DAMAGE.
*/
+#include "dfcompat.h"
+
+#include <sys/file.h>
#include <sys/stat.h>
#include <ctype.h>
struct stritem *t;
int fd;
- if (snprintf(fn, sizeof(fn), "%s/%s", config->spooldir, "tmp_XXXXXXXXXX") <= 0)
+ if (snprintf(fn, sizeof(fn), "%s/%s", config.spooldir, "tmp_XXXXXXXXXX") <= 0)
return (-1);
fd = mkstemp(fn);
if (fd < 0)
return (-1);
+ /* XXX group rights */
+ if (fchmod(fd, 0660) < 0)
+ goto fail;
if (flock(fd, LOCK_EX) == -1)
goto fail;
queue->tmpf = strdup(fn);
*/
if (fstat(fd, &st) != 0)
goto fail;
- if (asprintf(&queue->id, "%"PRIxMAX, st.st_ino) < 0)
+ if (asprintf(&queue->id, "%"PRIxMAX, (uintmax_t)st.st_ino) < 0)
goto fail;
queue->mailf = fdopen(fd, "r+");
int error;
int queuefd;
- queuefd = open_locked(it->queuefn, O_CREAT|O_EXCL|O_RDWR, 0600);
+ queuefd = open_locked(it->queuefn, O_CREAT|O_EXCL|O_RDWR, 0660);
if (queuefd == -1)
return (-1);
+ if (fchmod(queuefd, 0660) < 0)
+ return (-1);
it->queuef = fdopen(queuefd, "w+");
if (it->queuef == NULL)
return (-1);
s++;
s = strdup(s);
- if (s == NULL || s[0] == 0)
+ if (s == NULL)
goto malformed;
if (strcmp(line, "ID") == 0) {
}
}
- if (queueid == NULL || sender == NULL || addr == NULL) {
+ if (queueid == NULL || sender == NULL || addr == NULL ||
+ *queueid == 0 || *addr == 0) {
malformed:
errno = EINVAL;
syslog(LOG_ERR, "malformed queue file `%s'", queuefn);
LIST_FOREACH(it, &queue->queue, next) {
if (asprintf(&it->queueid, "%s.%"PRIxPTR, queue->id, (uintptr_t)it) <= 0)
goto delfiles;
- if (asprintf(&it->queuefn, "%s/Q%s", config->spooldir, it->queueid) <= 0)
+ if (asprintf(&it->queuefn, "%s/Q%s", config.spooldir, it->queueid) <= 0)
goto delfiles;
- if (asprintf(&it->mailfn, "%s/M%s", config->spooldir, it->queueid) <= 0)
+ if (asprintf(&it->mailfn, "%s/M%s", config.spooldir, it->queueid) <= 0)
goto delfiles;
/* Neither file may not exist yet */
char *queuefn;
char *mailfn;
- bzero(queue, sizeof(queue));
+ bzero(queue, sizeof(*queue));
LIST_INIT(&queue->queue);
- spooldir = opendir(config->spooldir);
+ spooldir = opendir(config.spooldir);
if (spooldir == NULL)
- err(1, "reading queue");
+ err(EX_NOINPUT, "reading queue");
while ((de = readdir(spooldir)) != NULL) {
queuefn = NULL;
mailfn = NULL;
- /* ignore temp files */
- if (strncmp(de->d_name, "tmp_", 4) == 0 || de->d_type != DT_REG)
- continue;
+ /* ignore non-queue files */
if (de->d_name[0] != 'Q')
continue;
- if (asprintf(&queuefn, "%s/Q%s", config->spooldir, de->d_name + 1) < 0)
+ if (asprintf(&queuefn, "%s/Q%s", config.spooldir, de->d_name + 1) < 0)
goto fail;
- if (asprintf(&mailfn, "%s/M%s", config->spooldir, de->d_name + 1) < 0)
+ if (asprintf(&mailfn, "%s/M%s", config.spooldir, de->d_name + 1) < 0)
goto fail;
+ /*
+ * Some file systems don't provide a de->d_type, so we have to
+ * do an explicit stat on the queue file.
+ * Move on if it turns out to be something else than a file.
+ */
+ if (stat(queuefn, &sb) != 0)
+ goto skip_item;
+ if (!S_ISREG(sb.st_mode)) {
+ errno = EINVAL;
+ goto skip_item;
+ }
+
if (stat(mailfn, &sb) != 0)
goto skip_item;
if (queuefn != NULL)
free(queuefn);
if (mailfn != NULL)
- free(queuefn);
+ free(mailfn);
}
closedir(spooldir);
return (0);
return (0);
fail:
+ if (errno == EWOULDBLOCK)
+ return (1);
syslog(LOG_INFO, "could not acquire queue file: %m");
return (-1);
}
fclose(it->mailf);
}
}
+
+int
+flushqueue_since(unsigned int period)
+{
+ struct stat st;
+ struct timeval now;
+ char *flushfn = NULL;
+
+ if (asprintf(&flushfn, "%s/%s", config.spooldir, SPOOL_FLUSHFILE) < 0)
+ return (0);
+ if (stat(flushfn, &st) < 0) {
+ free(flushfn);
+ return (0);
+ }
+ free(flushfn);
+ flushfn = NULL;
+ if (gettimeofday(&now, 0) != 0)
+ return (0);
+
+ /* Did the flush file get touched within the last period seconds? */
+ if (st.st_mtim.tv_sec + period >= now.tv_sec)
+ return (1);
+ else
+ return (0);
+}
+
+int
+flushqueue_signal(void)
+{
+ char *flushfn = NULL;
+ int fd;
+
+ if (asprintf(&flushfn, "%s/%s", config.spooldir, SPOOL_FLUSHFILE) < 0)
+ return (-1);
+ fd = open(flushfn, O_CREAT|O_WRONLY|O_TRUNC, 0660);
+ free(flushfn);
+ if (fd < 0) {
+ syslog(LOG_ERR, "could not open flush file: %m");
+ return (-1);
+ }
+ close(fd);
+ return (0);
+}