/*
* Copyright (C) 1996-8 Michael R. Elkins <me@cs.hmc.edu>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
/* This file contains code to parse ``mbox'' and ``mmdf'' style mailboxes */
#include "mutt.h"
#include "mailbox.h"
#include "mx.h"
#include "sort.h"
#include "copy.h"
#include <sys/stat.h>
#include <dirent.h>
#include <string.h>
#include <utime.h>
#include <sys/file.h>
#include <errno.h>
#include <unistd.h>
#include <fcntl.h>
/* struct used by mutt_sync_mailbox() to store new offsets */
struct m_update_t
{
long hdr;
long body;
};
#ifdef USE_DOTLOCK
/*
* Determine whether or not to use a dotlock to lock the indicated file.
* On some systems, the spool directory is not world-writable. If it is
* group-writable, we might need to be setgid() to write the lock. If not
* group-writable, then we assume that fcntl() locking is enough and skip
* the dotlocking.
*
* return values:
* 2 need to be setgid to dotlock
* 1 can use a dotlock
* 0 don't use a dotlock
* -1 error
*/
static int can_dotlock (const char *path)
{
char tmp[_POSIX_PATH_MAX];
char *p;
#ifdef USE_SETGID
struct stat sb;
#endif
strfcpy (tmp, path, sizeof (tmp));
if ((p = strrchr (tmp, '/')))
*p = 0;
else
strfcpy (tmp, ".", sizeof (tmp)); /* use current directory */
if (access (tmp, W_OK) == 0) return 1;
#ifdef USE_SETGID
if (stat (tmp, &sb) == 0)
{
if ((sb.st_mode & S_IWGRP) == S_IWGRP)
{
/* can dotlock, but need to be setgid */
if (sb.st_gid == MailGid)
return (2);
else
{
mutt_error ("Need to be running setgid %d to lock mailbox!", sb.st_gid);
return (-1);
}
}
}
#endif
if (mutt_yesorno ("Can't dotlock mailbox, continue anyway?", 0) == 1)
return 0;
return (-1);
}
#endif
/* parameters:
* ctx - context to lock
* excl - exclusive lock?
* retry - should retry if unable to lock?
*/
int mbox_lock_mailbox (CONTEXT *ctx, int excl, int retry)
{
int r = 0;
#ifdef USE_DOTLOCK
r = can_dotlock (ctx->path);
if (r == -1)
return (-1);
#ifdef USE_SETGID
else if (r == 2)
{
/* need to be setgid to lock the mailbox */
if (SETEGID (MailGid) != 0)
{
mutt_perror ("setegid");
return (-1);
}
ctx->setgid = 1;
}
#endif /* USE_SETGID */
#endif /* USE_DOTLOCK */
if ((r = mx_lock_file (ctx->path, fileno (ctx->fp), excl, r, retry)) == 0)
ctx->locked = 1;
#ifdef USE_SETGID
if (ctx->setgid)
SETEGID (UserGid);
#endif
return (r);
}
void mbox_unlock_mailbox (CONTEXT *ctx)
{
if (ctx->locked)
{
fflush (ctx->fp);
#ifdef USE_SETGID
if (ctx->setgid)
SETEGID (MailGid);
#endif /* USE_SETGID */
mx_unlock_file (ctx->path, fileno (ctx->fp));
ctx->locked = 0;
#ifdef USE_SETGID
if (ctx->setgid)
{
SETEGID (UserGid);
ctx->setgid = 0;
}
#endif
}
}
int mmdf_parse_mailbox (CONTEXT *ctx)
{
char buf[HUGE_STRING];
char return_path[LONG_STRING];
int lines;
time_t t, tz;
long loc, tmploc;
HEADER *hdr;
struct stat sb;
#ifdef NFS_ATTRIBUTE_HACK
struct utimbuf newtime;
#endif
if (stat (ctx->path, &sb) == -1)
{
mutt_perror (ctx->path);
return (-1);
}
ctx->mtime = sb.st_mtime;
ctx->size = sb.st_size;
#ifdef NFS_ATTRIBUTE_HACK
if (sb.st_mtime > sb.st_atime)
{
newtime.modtime = sb.st_mtime;
newtime.actime = time (NULL);