diff options
Diffstat (limited to 'usr.sbin')
-rw-r--r-- | usr.sbin/smtpd/mail.maildir.8 | 40 | ||||
-rw-r--r-- | usr.sbin/smtpd/mail.maildir.c | 177 | ||||
-rw-r--r-- | usr.sbin/smtpd/mail/Makefile | 3 | ||||
-rw-r--r-- | usr.sbin/smtpd/mail/mail.maildir/Makefile | 21 |
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> |