Unix Technical Forum

Re: sendmail, mail.local and quota

This is a discussion on Re: sendmail, mail.local and quota within the mailing.openbsd.tech forums, part of the OpenBSD category; --> On Mon, 13 Jun 2005, Otto Moerbeek wrote: > This new version deals with that by forking an unprivileged ...


Go Back   Unix Technical Forum > Unix Operating Systems > OpenBSD > mailing.openbsd.tech

FAQ Members List Calendar Search Today's Posts Mark Forums Read
  #1 (permalink)  
Old 02-18-2008, 08:55 AM
Otto Moerbeek
 
Posts: n/a
Default Re: sendmail, mail.local and quota

On Mon, 13 Jun 2005, Otto Moerbeek wrote:

> This new version deals with that by forking an unprivileged child, and
> doing the locking and unlocking in the parent. This way, even if the
> child gets killed, the parent will remove the lock file.


New version with more accurate error reporting.

-Otto

Index: mail.local.8
================================================== =================
RCS file: /cvs/src/libexec/mail.local/mail.local.8,v
retrieving revision 1.25
diff -u -p -r1.25 mail.local.8
--- mail.local.8 20 May 2004 08:46:50 -0000 1.25
+++ mail.local.8 20 Jun 2005 08:02:34 -0000
@@ -36,8 +36,7 @@
.Nd store mail in a mailbox
.Sh SYNOPSIS
.Nm mail.local
-.Op Fl L
-.Op Fl l
+.Op Fl bLl
.Op Fl f Ar from
.Ar user ...
.Sh DESCRIPTION
@@ -52,6 +51,9 @@ must be a valid user name.
.Pp
The options are as follows:
.Bl -tag -width Ds
+.It Fl b
+Return a permanent failure if the mailbox is over quota, instead
+of a temporary failure.
.It Fl f Ar from
Specify the sender's name.
.It Fl l
Index: mail.local.c
================================================== =================
RCS file: /cvs/src/libexec/mail.local/mail.local.c,v
retrieving revision 1.27
diff -u -p -r1.27 mail.local.c
--- mail.local.c 29 May 2005 02:11:49 -0000 1.27
+++ mail.local.c 20 Jun 2005 08:02:34 -0000
@@ -48,9 +48,11 @@ static char rcsid[] = "$OpenBSD: mail.lo
#include <sys/param.h>
#include <sys/stat.h>
#include <sys/socket.h>
+#include <sys/wait.h>
#include <netinet/in.h>
#include <sys/signal.h>
#include <syslog.h>
+#include <sysexits.h>
#include <fcntl.h>
#include <netdb.h>
#include <pwd.h>
@@ -63,6 +65,11 @@ static char rcsid[] = "$OpenBSD: mail.lo
#include "pathnames.h"
#include "mail.local.h"

+int quotafatal;
+
+int writembox(const char *, const struct stat *, int, const struct passwd *);
+__dead int child(const char *, const struct stat *, int, const struct passwd *);
+
int
main(int argc, char *argv[])
{
@@ -74,7 +81,7 @@ main(int argc, char *argv[])
openlog("mail.local", LOG_PERROR, LOG_MAIL);

from = NULL;
- while ((ch = getopt(argc, argv, "lLdf:r:H")) != -1)
+ while ((ch = getopt(argc, argv, "lLdf:r:Hb")) != -1)
switch (ch) {
case 'd': /* backward compatible */
break;
@@ -93,6 +100,9 @@ main(int argc, char *argv[])
case 'H':
holdme=1;
break;
+ case 'b':
+ quotafatal = 1;
+ break;
case '?':
default:
usage();
@@ -184,11 +194,11 @@ store(char *from)
int
deliver(int fd, char *name, int lockfile)
{
- struct stat sb, fsb;
+ struct stat sb;
struct passwd *pw;
- int mbfd=-1, nr, nw, off, rval=1, lfd=-1;
- char biffmsg[100], buf[8*1024], path[MAXPATHLEN];
- off_t curoff;
+ int mbfd=-1, lfd=-1;
+ int rval = 1;
+ char path[MAXPATHLEN];

/*
* Disallow delivery to unknown names -- special mailboxes can be
@@ -235,68 +245,138 @@ retry:
pw->pw_uid, pw->pw_gid, name);
goto bad;
}
- } else {
- if (sb.st_nlink != 1 || !S_ISREG(sb.st_mode)) {
- merr(NOTFATAL, "%s: linked or special file", path);
+ if (fstat(mbfd, &sb) < 0) {
+ merr(NOTFATAL, "fstat %s: %s\n", path, strerror(errno));
goto bad;
}
- if ((mbfd = open(path, O_APPEND|O_WRONLY|O_EXLOCK,
- S_IRUSR|S_IWUSR)) < 0) {
- merr(NOTFATAL, "%s: %s", path, strerror(errno));
- goto bad;
- }
- if (fstat(mbfd, &fsb)) {
- /* relating error to path may be bad style */
- merr(NOTFATAL, "%s: %s", path, strerror(errno));
- goto bad;
- }
- if (sb.st_dev != fsb.st_dev || sb.st_ino != fsb.st_ino) {
- merr(NOTFATAL, "%s: changed after open", path);
- goto bad;
- }
- /* paranoia? */
- if (fsb.st_nlink != 1 || !S_ISREG(fsb.st_mode)) {
- merr(NOTFATAL, "%s: linked or special file", path);
- goto bad;
+ close(mbfd);
+ }
+
+
+ if (sb.st_nlink != 1 || !S_ISREG(sb.st_mode)) {
+ merr(NOTFATAL, "%s: linked or special file", path);
+ goto bad;
+ }
+ rval = writembox(path, &sb, fd, pw);
+ if (rval == EDQUOT)
+ rval = quotafatal ? EX_UNAVAILABLE : EX_TEMPFAIL;
+bad:
+
+ if (lfd != -1) {
+ rellock();
+ close(lfd);
+ }
+
+ return(rval);
+}
+
+int
+writembox(const char *path, const struct stat *sb, int fd,
+ const struct passwd *pw)
+{
+ pid_t pid;
+ int status;
+
+ pid = fork();
+ switch (pid) {
+ case -1:
+ merr(NOTFATAL, "fork failed: %s\n", errno);
+ return 1;
+ case 0:
+ child(path, sb, fd, pw);
+ break;
+ default:
+ do {
+ if (waitpid(pid, &status, 0) == -1) {
+ if (errno == EINTR)
+ continue;
+ merr(NOTFATAL, "waitpid: %\n", strerror(errno));
+ return 1;
+ }
+ break;
+ } while (1);
+ if (WIFEXITED(status)) {
+ status = WEXITSTATUS(status);
+ if (status == EDQUOT)
+ merr(NOTFATAL, "%s: %s\n", path,
+ strerror(EDQUOT));
+ else if (status != 0)
+ merr(NOTFATAL, "child returned %d\n", status);
+ return status;
+ } else if (WIFSIGNALED(status)) {
+ merr(NOTFATAL, "child got signal %d\n",
+ WTERMSIG(status));
+ return 1;
+ } else {
+ merr(NOTFATAL, "child died\n");
+ return 1;
}
+ break;
+ }
+}
+
+__dead int
+child(const char *path, const struct stat *sb, int fd, const struct passwd *pw)
+{
+ char buf[8 * 1024], biffmsg[100];
+ int mbfd, rval = 1;
+ struct stat fsb;
+ off_t curoff;
+ ssize_t nr, nw;
+ size_t off;
+
+ (void) setresuid(pw->pw_uid, pw->pw_uid, pw->pw_uid);
+ if ((mbfd = open(path, O_APPEND|O_WRONLY|O_EXLOCK,
+ S_IRUSR|S_IWUSR)) < 0) {
+ merr(NOTFATAL, "%s: %s", path, strerror(errno));
+ goto done;
+ }
+ if (fstat(mbfd, &fsb)) {
+ /* relating error to path may be bad style */
+ merr(NOTFATAL, "%s: %s", path, strerror(errno));
+ goto done;
+ }
+ if (sb->st_dev != fsb.st_dev || sb->st_ino != fsb.st_ino) {
+ merr(NOTFATAL, "%s: changed after open", path);
+ goto done;
+ }
+ /* paranoia? */
+ if (fsb.st_nlink != 1 || !S_ISREG(fsb.st_mode)) {
+ merr(NOTFATAL, "%s: linked or special file", path);
+ goto done;
}

curoff = lseek(mbfd, 0, SEEK_END);
- (void)snprintf(biffmsg, sizeof biffmsg, "%s@%qd\n", name, curoff);
+ (void)snprintf(biffmsg, sizeof biffmsg, "%s@%qd\n",
+ pw->pw_name, curoff);
if (lseek(fd, 0, SEEK_SET) == (off_t)-1) {
merr(NOTFATAL, "temporary file: %s", strerror(errno));
- goto bad;
+ goto done;
}

- while ((nr = read(fd, buf, sizeof(buf))) > 0)
- for (off = 0; off < nr; off += nw)
+ while ((nr = read(fd, buf, sizeof(buf))) > 0) {
+ for (off = 0; off < nr; off += nw) {
if ((nw = write(mbfd, buf + off, nr - off)) < 0) {
- merr(NOTFATAL, "%s: %s", path, strerror(errno));
+ rval = errno;
(void)ftruncate(mbfd, curoff);
- goto bad;
+ goto done;
}
-
- if (nr == 0) {
+ }
+ }
+ if (nr == 0)
rval = 0;
- } else {
+ else
(void)ftruncate(mbfd, curoff);
- merr(FATAL, "temporary file: %s", strerror(errno));
- }
-
-bad:
- if (lfd != -1) {
- rellock();
- close(lfd);
- }
-
+done:
if (mbfd != -1) {
- (void)fsync(mbfd); /* Don't wait for update. */
- (void)close(mbfd); /* Implicit unlock. */
+ if (fsync(mbfd) != 0) /* Don't wait for update. */
+ merr(NOTFATAL, "%s: %s", path, strerror(errno));
+ if (close(mbfd) != 0) /* Implicit unlock. */
+ merr(NOTFATAL, "%s: %s", path, strerror(errno));
}
-
- if (!rval)
+ if (rval == 0)
notifybiff(biffmsg);
- return(rval);
+ exit(rval);
}

void
@@ -334,5 +414,5 @@ notifybiff(char *msg)
void
usage(void)
{
- merr(FATAL, "usage: mail.local [-lL] [-f from] user ...");
+ merr(FATAL, "usage: mail.local [-blL] [-f from] user ...");
}

Digg this Post!Add Post to del.icio.usBookmark Post in TechnoratiFurl this Post!
Reply With Quote
Reply


Thread Tools
Display Modes

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

vB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are On
Forum Jump


All times are GMT. The time now is 07:02 AM.


Powered by vBulletin® Version 3.6.5
Copyright ©2000 - 2008, Jelsoft Enterprises Ltd.
SEO by vBSEO 3.2.0
www.UnixAdminTalk.com