summaryrefslogtreecommitdiff
path: root/usr.sbin
diff options
context:
space:
mode:
Diffstat (limited to 'usr.sbin')
-rw-r--r--usr.sbin/smtpd/mail.maildir.840
-rw-r--r--usr.sbin/smtpd/mail.maildir.c177
-rw-r--r--usr.sbin/smtpd/mail/Makefile3
-rw-r--r--usr.sbin/smtpd/mail/mail.maildir/Makefile21
4 files changed, 240 insertions, 1 deletions
diff --git a/usr.sbin/smtpd/mail.maildir.8 b/usr.sbin/smtpd/mail.maildir.8
new file mode 100644
index 00000000000..45f60f53ccd
--- /dev/null
+++ b/usr.sbin/smtpd/mail.maildir.8
@@ -0,0 +1,40 @@
+.\" $OpenBSD: mail.maildir.8,v 1.1 2017/02/14 16:48:30 gilles Exp $
+.\"
+.\" Copyright (c) 2017 Gilles Chehade <gilles@poolp.org>
+.\"
+.\" Permission to use, copy, modify, and distribute this software for any
+.\" purpose with or without fee is hereby granted, provided that the above
+.\" copyright notice and this permission notice appear in all copies.
+.\"
+.\" THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+.\" WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+.\" MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+.\" ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+.\" WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+.\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+.\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+.\"
+.Dd $Mdocdate: February 14 2017 $
+.Dt MAIL.MAILDIR 8
+.Os
+.Sh NAME
+.Nm mail.maildir
+.Nd store mail in a maildir
+.Sh SYNOPSIS
+.Nm mail.maildir
+.Op Fl d Ar maildir
+.Sh DESCRIPTION
+.Nm
+reads the standard input up to an end-of-file and adds it to the
+provided mail directory.
+.Pp
+The options are as follows:
+.Bl -tag -width Ds
+.It Fl d Ar maildir
+Specify the path to user mail directory.
+.El
+.Sh EXIT STATUS
+.Ex -std mail.maildir
+.Sh SEE ALSO
+.Xr mail 1 ,
+.Xr smtpd 8
diff --git a/usr.sbin/smtpd/mail.maildir.c b/usr.sbin/smtpd/mail.maildir.c
new file mode 100644
index 00000000000..effbc49a3b5
--- /dev/null
+++ b/usr.sbin/smtpd/mail.maildir.c
@@ -0,0 +1,177 @@
+/*
+ * Copyright (c) 2017 Gilles Chehade <gilles@poolp.org>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <sys/types.h>
+#include <sys/stat.h>
+
+#include <ctype.h>
+#include <err.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <limits.h>
+#include <netdb.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+static void maildir_engine(const char *);
+static int mkdirs_component(const char *, mode_t);
+static int mkdirs(const char *, mode_t);
+
+int
+main(int argc, char *argv[])
+{
+ int ch;
+ char *dirname = NULL;
+
+ while ((ch = getopt(argc, argv, "d:")) != -1) {
+ switch (ch) {
+ case 'd':
+ dirname = optarg;
+ break;
+ default:
+ break;
+ }
+ }
+ argc -= optind;
+ argv += optind;
+
+ if (dirname == NULL) {
+ exit(1);
+ }
+
+ maildir_engine(dirname);
+
+ return (0);
+}
+
+static void
+maildir_engine(const char *dirname)
+{
+ char tmp[PATH_MAX];
+ char new[PATH_MAX];
+ int fd;
+ FILE *fp;
+ char *line = NULL;
+ size_t linesize = 0;
+ ssize_t linelen;
+
+ if (mkdirs(dirname, 0700) < 0 && errno != EEXIST)
+ err(1, NULL);
+
+ if (chdir(dirname) < 0)
+ err(1, NULL);
+
+ if (mkdir("cur", 0700) < 0 && errno != EEXIST)
+ err(1, NULL);
+ if (mkdir("tmp", 0700) < 0 && errno != EEXIST)
+ err(1, NULL);
+ if (mkdir("new", 0700) < 0 && errno != EEXIST)
+ err(1, NULL);
+
+ (void)snprintf(tmp, sizeof tmp, "tmp/%lld.%08x.%s",
+ (long long int) time(NULL),
+ arc4random(),
+ "localhost");
+
+ fd = open(tmp, O_CREAT | O_EXCL | O_WRONLY, 0600);
+ if (fd < 0)
+ err(1, NULL);
+ if ((fp = fdopen(fd, "w")) == NULL)
+ err(1, NULL);
+
+ while ((linelen = getline(&line, &linesize, stdin)) != -1) {
+ line[strcspn(line, "\n")] = '\0';
+ fprintf(fp, "%s\n", line);
+ }
+ free(line);
+ if (ferror(stdin))
+ err(1, NULL);
+
+
+ if (fflush(fp) == EOF ||
+ ferror(fp) ||
+ fsync(fd) < 0 ||
+ fclose(fp) == EOF)
+ err(1, NULL);
+
+ (void)snprintf(new, sizeof new, "new/%s", tmp + 4);
+ if (rename(tmp, new) < 0)
+ err(1, NULL);
+
+ exit(0);
+}
+
+
+static int
+mkdirs_component(const char *path, mode_t mode)
+{
+ struct stat sb;
+
+ if (stat(path, &sb) == -1) {
+ if (errno != ENOENT)
+ return 0;
+ if (mkdir(path, mode | S_IWUSR | S_IXUSR) == -1)
+ return 0;
+ }
+ else if (!S_ISDIR(sb.st_mode))
+ return 0;
+
+ return 1;
+}
+
+static int
+mkdirs(const char *path, mode_t mode)
+{
+ char buf[PATH_MAX];
+ int i = 0;
+ int done = 0;
+ const char *p;
+
+ /* absolute path required */
+ if (*path != '/')
+ return 0;
+
+ /* make sure we don't exceed PATH_MAX */
+ if (strlen(path) >= sizeof buf)
+ return 0;
+
+ memset(buf, 0, sizeof buf);
+ for (p = path; *p; p++) {
+ if (*p == '/') {
+ if (buf[0] != '\0')
+ if (!mkdirs_component(buf, mode))
+ return 0;
+ while (*p == '/')
+ p++;
+ buf[i++] = '/';
+ buf[i++] = *p;
+ if (*p == '\0' && ++done)
+ break;
+ continue;
+ }
+ buf[i++] = *p;
+ }
+ if (!done)
+ if (!mkdirs_component(buf, mode))
+ return 0;
+
+ if (chmod(path, mode) == -1)
+ return 0;
+
+ return 1;
+}
diff --git a/usr.sbin/smtpd/mail/Makefile b/usr.sbin/smtpd/mail/Makefile
index 87b902116ab..e83da45179a 100644
--- a/usr.sbin/smtpd/mail/Makefile
+++ b/usr.sbin/smtpd/mail/Makefile
@@ -1,8 +1,9 @@
-# $OpenBSD: Makefile,v 1.2 2017/02/14 16:43:28 gilles Exp $
+# $OpenBSD: Makefile,v 1.3 2017/02/14 16:48:30 gilles Exp $
.include <bsd.own.mk>
SUBDIR = mail.lmtp
SUBDIR+= mail.file
+SUBDIR+= mail.maildir
.include <bsd.subdir.mk>
diff --git a/usr.sbin/smtpd/mail/mail.maildir/Makefile b/usr.sbin/smtpd/mail/mail.maildir/Makefile
new file mode 100644
index 00000000000..a728ad4fa4a
--- /dev/null
+++ b/usr.sbin/smtpd/mail/mail.maildir/Makefile
@@ -0,0 +1,21 @@
+.PATH: ${.CURDIR}/../..
+
+PROG= mail.maildir
+BINOWN= root
+BINGRP= wheel
+
+BINMODE?=0555
+
+BINDIR= /usr/libexec
+MAN= mail.maildir.8
+
+CFLAGS+= -fstack-protector-all
+CFLAGS+= -Wall -Wstrict-prototypes -Wmissing-prototypes
+CFLAGS+= -Wmissing-declarations
+CFLAGS+= -Wshadow -Wpointer-arith -Wcast-qual
+CFLAGS+= -Wsign-compare
+CFLAGS+= -Werror-implicit-function-declaration
+
+SRCS= mail.maildir.c
+
+.include <bsd.prog.mk>