⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 mx.c

📁 mutt-1.5.12 源代码。linux 下邮件接受的工具。
💻 C
📖 第 1 页 / 共 3 页
字号:
/* * Copyright (C) 1996-2002 Michael R. Elkins <me@mutt.org> * Copyright (C) 1999-2000 Thomas Roessler <roessler@does-not-exist.org> *  *     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., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA. */ #if HAVE_CONFIG_H# include "config.h"#endif#include "mutt.h"#include "mx.h"#include "rfc2047.h"#include "sort.h"#include "mailbox.h"#include "copy.h"#include "keymap.h"#include "url.h"#ifdef USE_IMAP#include "imap.h"#endif#ifdef USE_POP#include "pop.h"#endif#ifdef BUFFY_SIZE#include "buffy.h"#endif#ifdef USE_DOTLOCK#include "dotlock.h"#endif#include "mutt_crypt.h"#include <dirent.h>#include <fcntl.h>#include <sys/file.h>#include <sys/stat.h>#include <errno.h>#include <unistd.h>#include <stdlib.h>#include <string.h>#include <ctype.h>#ifndef BUFFY_SIZE#include <utime.h>#endif#define mutt_is_spool(s)  (mutt_strcmp (Spoolfile, s) == 0)#ifdef USE_DOTLOCK/* parameters:  * path - file to lock * retry - should retry if unable to lock? */#ifdef DL_STANDALONEstatic int invoke_dotlock (const char *path, int dummy, int flags, int retry){  char cmd[LONG_STRING + _POSIX_PATH_MAX];  char f[SHORT_STRING + _POSIX_PATH_MAX];  char r[SHORT_STRING];    if (flags & DL_FL_RETRY)    snprintf (r, sizeof (r), "-r %d ", retry ? MAXLOCKATTEMPT : 0);    mutt_quote_filename (f, sizeof (f), path);    snprintf (cmd, sizeof (cmd),	    "%s %s%s%s%s%s%s%s",	    NONULL (MuttDotlock),	    flags & DL_FL_TRY ? "-t " : "",	    flags & DL_FL_UNLOCK ? "-u " : "",	    flags & DL_FL_USEPRIV ? "-p " : "",	    flags & DL_FL_FORCE ? "-f " : "",	    flags & DL_FL_UNLINK ? "-d " : "",	    flags & DL_FL_RETRY ? r : "",	    f);    return mutt_system (cmd);}#else #define invoke_dotlock dotlock_invoke#endifstatic int dotlock_file (const char *path, int fd, int retry){  int r;  int flags = DL_FL_USEPRIV | DL_FL_RETRY;  if (retry) retry = 1;retry_lock:  if ((r = invoke_dotlock(path, fd, flags, retry)) == DL_EX_EXIST)  {    if (!option (OPTNOCURSES))    {      char msg[LONG_STRING];            snprintf(msg, sizeof(msg), _("Lock count exceeded, remove lock for %s?"),	       path);      if(retry && mutt_yesorno(msg, M_YES) == M_YES)      {	flags |= DL_FL_FORCE;	retry--;	mutt_clear_error ();	goto retry_lock;      }    }     else    {      mutt_error ( _("Can't dotlock %s.\n"), path);    }  }  return (r == DL_EX_OK ? 0 : -1);}static int undotlock_file (const char *path, int fd){  return (invoke_dotlock(path, fd, DL_FL_USEPRIV | DL_FL_UNLOCK, 0) == DL_EX_OK ? 	  0 : -1);}#endif /* USE_DOTLOCK *//* Args: *	excl		if excl != 0, request an exclusive lock *	dot		if dot != 0, try to dotlock the file *	timeout 	should retry locking? */int mx_lock_file (const char *path, int fd, int excl, int dot, int timeout){#if defined (USE_FCNTL) || defined (USE_FLOCK)  int count;  int attempt;  struct stat prev_sb;#endif  int r = 0;#ifdef USE_FCNTL  struct flock lck;    memset (&lck, 0, sizeof (struct flock));  lck.l_type = excl ? F_WRLCK : F_RDLCK;  lck.l_whence = SEEK_SET;  count = 0;  attempt = 0;  prev_sb.st_size = 0; /* silence a GCC warning */  while (fcntl (fd, F_SETLK, &lck) == -1)  {    struct stat sb;    dprint(1,(debugfile, "mx_lock_file(): fcntl errno %d.\n", errno));    if (errno != EAGAIN && errno != EACCES)    {      mutt_perror ("fcntl");      return (-1);    }    if (fstat (fd, &sb) != 0)     sb.st_size = 0;        if (count == 0)      prev_sb = sb;    /* only unlock file if it is unchanged */    if (prev_sb.st_size == sb.st_size && ++count >= (timeout?MAXLOCKATTEMPT:0))    {      if (timeout)	mutt_error _("Timeout exceeded while attempting fcntl lock!");      return (-1);    }    prev_sb = sb;    mutt_message (_("Waiting for fcntl lock... %d"), ++attempt);    sleep (1);  }#endif /* USE_FCNTL */#ifdef USE_FLOCK  count = 0;  attempt = 0;  while (flock (fd, (excl ? LOCK_EX : LOCK_SH) | LOCK_NB) == -1)  {    struct stat sb;    if (errno != EWOULDBLOCK)    {      mutt_perror ("flock");      r = -1;      break;    }    if (fstat(fd,&sb) != 0 )     sb.st_size=0;        if (count == 0)      prev_sb=sb;    /* only unlock file if it is unchanged */    if (prev_sb.st_size == sb.st_size && ++count >= (timeout?MAXLOCKATTEMPT:0))    {      if (timeout)	mutt_error _("Timeout exceeded while attempting flock lock!");      r = -1;      break;    }    prev_sb = sb;    mutt_message (_("Waiting for flock attempt... %d"), ++attempt);    sleep (1);  }#endif /* USE_FLOCK */#ifdef USE_DOTLOCK  if (r == 0 && dot)    r = dotlock_file (path, fd, timeout);#endif /* USE_DOTLOCK */  if (r == -1)  {    /* release any other locks obtained in this routine */#ifdef USE_FCNTL    lck.l_type = F_UNLCK;    fcntl (fd, F_SETLK, &lck);#endif /* USE_FCNTL */#ifdef USE_FLOCK    flock (fd, LOCK_UN);#endif /* USE_FLOCK */    return (-1);  }  return 0;}int mx_unlock_file (const char *path, int fd, int dot){#ifdef USE_FCNTL  struct flock unlockit = { F_UNLCK, 0, 0, 0 };  memset (&unlockit, 0, sizeof (struct flock));  unlockit.l_type = F_UNLCK;  unlockit.l_whence = SEEK_SET;  fcntl (fd, F_SETLK, &unlockit);#endif#ifdef USE_FLOCK  flock (fd, LOCK_UN);#endif#ifdef USE_DOTLOCK  if (dot)    undotlock_file (path, fd);#endif    return 0;}void mx_unlink_empty (const char *path){  int fd;#ifndef USE_DOTLOCK  struct stat sb;#endif  if ((fd = open (path, O_RDWR)) == -1)    return;  if (mx_lock_file (path, fd, 1, 0, 1) == -1)  {    close (fd);    return;  }#ifdef USE_DOTLOCK  invoke_dotlock (path, fd, DL_FL_UNLINK, 1);#else  if (fstat (fd, &sb) == 0 && sb.st_size == 0)    unlink (path);#endif  mx_unlock_file (path, fd, 0);  close (fd);}/* try to figure out what type of mailbox ``path'' is * * return values: *	M_*	mailbox type *	0	not a mailbox *	-1	error */#ifdef USE_IMAPint mx_is_imap(const char *p){  url_scheme_t scheme;  if (!p)    return 0;  if (*p == '{')    return 1;  scheme = url_check_scheme (p);  if (scheme == U_IMAP || scheme == U_IMAPS)    return 1;  return 0;}#endif#ifdef USE_POPint mx_is_pop (const char *p){  url_scheme_t scheme;  if (!p)    return 0;  scheme = url_check_scheme (p);  if (scheme == U_POP || scheme == U_POPS)    return 1;  return 0;}#endifint mx_get_magic (const char *path){  struct stat st;  int magic = 0;  char tmp[_POSIX_PATH_MAX];  FILE *f;#ifdef USE_IMAP  if(mx_is_imap(path))    return M_IMAP;#endif /* USE_IMAP */#ifdef USE_POP  if (mx_is_pop (path))    return M_POP;#endif /* USE_POP */  if (stat (path, &st) == -1)  {    dprint (1, (debugfile, "mx_get_magic(): unable to stat %s: %s (errno %d).\n",		path, strerror (errno), errno));    return (-1);  }  if (S_ISDIR (st.st_mode))  {    /* check for maildir-style mailbox */    snprintf (tmp, sizeof (tmp), "%s/cur", path);    if (stat (tmp, &st) == 0 && S_ISDIR (st.st_mode))      return (M_MAILDIR);    /* check for mh-style mailbox */    snprintf (tmp, sizeof (tmp), "%s/.mh_sequences", path);    if (access (tmp, F_OK) == 0)      return (M_MH);    snprintf (tmp, sizeof (tmp), "%s/.xmhcache", path);    if (access (tmp, F_OK) == 0)      return (M_MH);        snprintf (tmp, sizeof (tmp), "%s/.mew_cache", path);    if (access (tmp, F_OK) == 0)      return (M_MH);    snprintf (tmp, sizeof (tmp), "%s/.mew-cache", path);    if (access (tmp, F_OK) == 0)      return (M_MH);        snprintf (tmp, sizeof (tmp), "%s/.sylpheed_cache", path);    if (access (tmp, F_OK) == 0)      return (M_MH);    /*      * ok, this isn't an mh folder, but mh mode can be used to read     * Usenet news from the spool. ;-)      */    snprintf (tmp, sizeof (tmp), "%s/.overview", path);    if (access (tmp, F_OK) == 0)      return (M_MH);  }  else if (st.st_size == 0)  {    /* hard to tell what zero-length files are, so assume the default magic */    if (DefaultMagic == M_MBOX || DefaultMagic == M_MMDF)      return (DefaultMagic);    else      return (M_MBOX);  }  else if ((f = fopen (path, "r")) != NULL)  {#ifndef BUFFY_SIZE    struct utimbuf times;#endif    fgets (tmp, sizeof (tmp), f);    if (mutt_strncmp ("From ", tmp, 5) == 0)      magic = M_MBOX;    else if (mutt_strcmp (MMDF_SEP, tmp) == 0)      magic = M_MMDF;    safe_fclose (&f);#ifndef BUFFY_SIZE    /* need to restore the times here, the file was not really accessed,     * only the type was accessed.  This is important, because detection     * of "new mail" depends on those times set correctly.     */    times.actime = st.st_atime;    times.modtime = st.st_mtime;    utime (path, &times);#endif  }  else  {    dprint (1, (debugfile, "mx_get_magic(): unable to open file %s for reading.\n",		path));    mutt_perror (path);    return (-1);  }  return (magic);}/* * set DefaultMagic to the given value */int mx_set_magic (const char *s){  if (ascii_strcasecmp (s, "mbox") == 0)    DefaultMagic = M_MBOX;  else if (ascii_strcasecmp (s, "mmdf") == 0)    DefaultMagic = M_MMDF;  else if (ascii_strcasecmp (s, "mh") == 0)    DefaultMagic = M_MH;  else if (ascii_strcasecmp (s, "maildir") == 0)    DefaultMagic = M_MAILDIR;  else    return (-1);  return 0;}/* mx_access: Wrapper for access, checks permissions on a given mailbox. *   We may be interested in using ACL-style flags at some point, currently *   we use the normal access() flags. */int mx_access (const char* path, int flags){#ifdef USE_IMAP  if (mx_is_imap (path))    return imap_access (path, flags);#endif  return access (path, flags);}static int mx_open_mailbox_append (CONTEXT *ctx, int flags){  struct stat sb;  ctx->append = 1;#ifdef USE_IMAP    if(mx_is_imap(ctx->path))      return imap_open_mailbox_append (ctx);#endif    if(stat(ctx->path, &sb) == 0)  {    ctx->magic = mx_get_magic (ctx->path);        switch (ctx->magic)    {      case 0:	mutt_error (_("%s is not a mailbox."), ctx->path);	/* fall through */      case -1:	return (-1);    }  }  else if (errno == ENOENT)  {    ctx->magic = DefaultMagic;    if (ctx->magic == M_MH || ctx->magic == M_MAILDIR)    {      char tmp[_POSIX_PATH_MAX];      if (mkdir (ctx->path, S_IRWXU))      {	mutt_perror (ctx->path);	return (-1);      }      if (ctx->magic == M_MAILDIR)      {	snprintf (tmp, sizeof (tmp), "%s/cur", ctx->path);	if (mkdir (tmp, S_IRWXU))	{	  mutt_perror (tmp);	  rmdir (ctx->path);	  return (-1);	}	snprintf (tmp, sizeof (tmp), "%s/new", ctx->path);	if (mkdir (tmp, S_IRWXU))	{	  mutt_perror (tmp);	  snprintf (tmp, sizeof (tmp), "%s/cur", ctx->path);	  rmdir (tmp);	  rmdir (ctx->path);	  return (-1);	}	snprintf (tmp, sizeof (tmp), "%s/tmp", ctx->path);	if (mkdir (tmp, S_IRWXU))

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -