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

📄 mh.c

📁 mutt-1.5.12 源代码。linux 下邮件接受的工具。
💻 C
📖 第 1 页 / 共 4 页
字号:
    }  }#if USE_HCACHE  if (ctx->magic == M_MAILDIR || ctx->magic == M_MH)    mutt_hcache_close (hc);#endif /* USE_HCACHE */  if (ctx->magic == M_MH)    mh_update_sequences (ctx);  /* XXX race condition? */  maildir_update_mtime (ctx);  /* adjust indices */  if (ctx->deleted)  {    for (i = 0, j = 0; i < ctx->msgcount; i++)    {      if (!ctx->hdrs[i]->deleted	  || (ctx->magic == M_MAILDIR && option (OPTMAILDIRTRASH)))	ctx->hdrs[i]->index = j++;    }  }  return 0;err:#if USE_HCACHE  if (ctx->magic == M_MAILDIR || ctx->magic == M_MH)    mutt_hcache_close (hc);#endif /* USE_HCACHE */  return -1;}static char *maildir_canon_filename (char *dest, const char *src, size_t l){  char *t, *u;  if ((t = strrchr (src, '/')))    src = t + 1;  strfcpy (dest, src, l);  if ((u = strrchr (dest, ':')))    *u = '\0';  return dest;}static void maildir_update_tables (CONTEXT *ctx, int *index_hint){  short old_sort;  int old_count;  int i, j;    if (Sort != SORT_ORDER)  {    old_sort = Sort;    Sort = SORT_ORDER;    mutt_sort_headers (ctx, 1);    Sort = old_sort;  }    old_count = ctx->msgcount;  for (i = 0, j = 0; i < old_count; i++)  {    if (ctx->hdrs[i]->active && index_hint && *index_hint == i)      *index_hint = j;        if (ctx->hdrs[i]->active)      ctx->hdrs[i]->index = j++;  }  mx_update_tables (ctx, 0);  mutt_clear_threads (ctx);}static void maildir_update_flags (CONTEXT *ctx, HEADER *o, HEADER *n){  /* save the global state here so we can reset it at the   * end of list block if required.   */  int context_changed = ctx->changed;    /* user didn't modify this message.  alter the flags to   * match the current state on disk.  This may not actually   * do anything, but we can't tell right now.  mutt_set_flag()   * will just ignore the call if the status bits are   * already properly set.   */  mutt_set_flag (ctx, o, M_FLAG, n->flagged);  mutt_set_flag (ctx, o, M_REPLIED, n->replied);  mutt_set_flag (ctx, o, M_READ, n->read);  mutt_set_flag (ctx, o, M_OLD, n->old);  /* mutt_set_flag() will set this, but we don't need to   * sync the changes we made because we just updated the   * context to match the current on-disk state of the   * message.   */  o->changed = 0;    /* if the mailbox was not modified before we made these   * changes, unset the changed flag since nothing needs to   * be synchronized.   */  if (!context_changed)    ctx->changed = 0;}/* This function handles arrival of new mail and reopening of * maildir folders.  The basic idea here is we check to see if either * the new or cur subdirectories have changed, and if so, we scan them * for the list of files.  We check for newly added messages, and * then merge the flags messages we already knew about.  We don't treat * either subdirectory differently, as mail could be copied directly into * the cur directory from another agent. */int maildir_check_mailbox (CONTEXT * ctx, int *index_hint){  struct stat st_new;		/* status of the "new" subdirectory */  struct stat st_cur;		/* status of the "cur" subdirectory */  char buf[_POSIX_PATH_MAX];  int changed = 0;		/* bitmask representing which subdirectories				   have changed.  0x1 = new, 0x2 = cur */  int occult = 0;		/* messages were removed from the mailbox */  int have_new = 0;		/* messages were added to the mailbox */  struct maildir *md;		/* list of messages in the mailbox */  struct maildir **last, *p;  int i;  HASH *fnames;			/* hash table for quickly looking up the base filename				   for a maildir message */  /* XXX seems like this check belongs in mx_check_mailbox()   * rather than here.   */  if (!option (OPTCHECKNEW))    return 0;  snprintf (buf, sizeof (buf), "%s/new", ctx->path);  if (stat (buf, &st_new) == -1)    return -1;  snprintf (buf, sizeof (buf), "%s/cur", ctx->path);  if (stat (buf, &st_cur) == -1)    return -1;  /* determine which subdirectories need to be scanned */  if (st_new.st_mtime > ctx->mtime)    changed = 1;  if (st_cur.st_mtime > ctx->mtime_cur)    changed |= 2;  if (!changed)    return 0;			/* nothing to do */  /* update the modification times on the mailbox */  ctx->mtime_cur = st_cur.st_mtime;  ctx->mtime = st_new.st_mtime;  /* do a fast scan of just the filenames in   * the subdirectories that have changed.   */  md = NULL;  last = &md;  if (changed & 1)    maildir_parse_dir (ctx, &last, "new", NULL);  if (changed & 2)    maildir_parse_dir (ctx, &last, "cur", NULL);  /* we create a hash table keyed off the canonical (sans flags) filename   * of each message we scanned.  This is used in the loop over the   * existing messages below to do some correlation.   */  fnames = hash_create (1031);  for (p = md; p; p = p->next)  {    maildir_canon_filename (buf, p->h->path, sizeof (buf));    p->canon_fname = safe_strdup (buf);    hash_insert (fnames, p->canon_fname, p, 0);  }  /* check for modifications and adjust flags */  for (i = 0; i < ctx->msgcount; i++)  {    ctx->hdrs[i]->active = 0;    maildir_canon_filename (buf, ctx->hdrs[i]->path, sizeof (buf));    p = hash_find (fnames, buf);    if (p && p->h)    {      /* message already exists, merge flags */      ctx->hdrs[i]->active = 1;      /* check to see if the message has moved to a different       * subdirectory.  If so, update the associated filename.       */      if (mutt_strcmp (ctx->hdrs[i]->path, p->h->path))	mutt_str_replace (&ctx->hdrs[i]->path, p->h->path);      /* if the user hasn't modified the flags on this message, update       * the flags we just detected.       */      if (!ctx->hdrs[i]->changed)	maildir_update_flags (ctx, ctx->hdrs[i], p->h);      if (ctx->hdrs[i]->deleted == ctx->hdrs[i]->trash)	ctx->hdrs[i]->deleted = p->h->deleted;      ctx->hdrs[i]->trash = p->h->trash;      /* this is a duplicate of an existing header, so remove it */      mutt_free_header (&p->h);    }    /* This message was not in the list of messages we just scanned.     * Check to see if we have enough information to know if the     * message has disappeared out from underneath us.     */    else if (((changed & 1) && (!strncmp (ctx->hdrs[i]->path, "new/", 4))) ||	     ((changed & 2) && (!strncmp (ctx->hdrs[i]->path, "cur/", 4))))    {      /* This message disappeared, so we need to simulate a "reopen"       * event.  We know it disappeared because we just scanned the       * subdirectory it used to reside in.       */      occult = 1;    }    else    {      /* This message resides in a subdirectory which was not       * modified, so we assume that it is still present and       * unchanged.       */      ctx->hdrs[i]->active = 1;    }  }  /* destroy the file name hash */  hash_destroy (&fnames, NULL);  /* If we didn't just get new mail, update the tables. */  if (occult)    maildir_update_tables (ctx, index_hint);    /* do any delayed parsing we need to do. */  maildir_delayed_parsing (ctx, md);  /* Incorporate new messages */  have_new = maildir_move_to_context (ctx, &md);  return occult ? M_REOPENED : (have_new ? M_NEW_MAIL : 0);}/*  * This function handles arrival of new mail and reopening of * mh/maildir folders. Things are getting rather complex because we * don't have a well-defined "mailbox order", so the tricks from * mbox.c and mx.c won't work here. * * Don't change this code unless you _really_ understand what * happens. * */int mh_check_mailbox (CONTEXT * ctx, int *index_hint){  char buf[_POSIX_PATH_MAX];  struct stat st, st_cur;  short modified = 0, have_new = 0, occult = 0;  struct maildir *md, *p;  struct maildir **last = NULL;  struct mh_sequences mhs;  HASH *fnames;  int i;  if (!option (OPTCHECKNEW))    return 0;  strfcpy (buf, ctx->path, sizeof (buf));  if (stat (buf, &st) == -1)    return -1;    /* create .mh_sequences when there isn't one. */  snprintf (buf, sizeof (buf), "%s/.mh_sequences", ctx->path);  if ((i = stat (buf, &st_cur) == -1) && errno == ENOENT)  {    char *tmp;    FILE *fp = NULL;        if (mh_mkstemp (ctx, &fp, &tmp) == 0)    {      safe_fclose (&fp);      if (safe_rename (tmp, buf) == -1)	unlink (tmp);      FREE (&tmp);    }  }  if (i == -1 && stat (buf, &st_cur) == -1)    modified = 1;  if (st.st_mtime > ctx->mtime || st_cur.st_mtime > ctx->mtime_cur)    modified = 1;  if (!modified)    return 0;  ctx->mtime_cur = st_cur.st_mtime;  ctx->mtime = st.st_mtime;  memset (&mhs, 0, sizeof (mhs));    md   = NULL;  last = &md;  maildir_parse_dir (ctx, &last, NULL, NULL);  mh_read_sequences (&mhs, ctx->path);  mh_update_maildir (md, &mhs);  mhs_free_sequences (&mhs);  /* check for modifications and adjust flags */  fnames = hash_create (1031);  for (p = md; p; p = p->next)    hash_insert (fnames, p->h->path, p, 0);  for (i = 0; i < ctx->msgcount; i++)  {    ctx->hdrs[i]->active = 0;    if ((p = hash_find (fnames, ctx->hdrs[i]->path)) && p->h &&	(mbox_strict_cmp_headers (ctx->hdrs[i], p->h)))    {      ctx->hdrs[i]->active = 1;      /* found the right message */      if (!ctx->hdrs[i]->changed)	maildir_update_flags (ctx, ctx->hdrs[i], p->h);      mutt_free_header (&p->h);    }    else /* message has disappeared */      occult = 1;  }  /* destroy the file name hash */  hash_destroy (&fnames, NULL);  /* If we didn't just get new mail, update the tables. */  if (occult)    maildir_update_tables (ctx, index_hint);  /* Incorporate new messages */  have_new = maildir_move_to_context (ctx, &md);  return occult ? M_REOPENED : (have_new ? M_NEW_MAIL : 0);}/* * These functions try to find a message in a maildir folder when it * has moved under our feet.  Note that this code is rather expensive, but * then again, it's called rarely. */FILE *_maildir_open_find_message (const char *folder, const char *unique,				  const char *subfolder){  char dir[_POSIX_PATH_MAX];  char tunique[_POSIX_PATH_MAX];  char fname[_POSIX_PATH_MAX];  DIR *dp;  struct dirent *de;  FILE *fp = NULL;  int oe = ENOENT;  snprintf (dir, sizeof (dir), "%s/%s", folder, subfolder);  if ((dp = opendir (dir)) == NULL)  {    errno = ENOENT;    return NULL;  }  while ((de = readdir (dp)))  {    maildir_canon_filename (tunique, de->d_name, sizeof (tunique));    if (!mutt_strcmp (tunique, unique))    {      snprintf (fname, sizeof (fname), "%s/%s/%s", folder, subfolder,		de->d_name);      fp = fopen (fname, "r");	/* __FOPEN_CHECKED__ */      oe = errno;      break;    }  }  closedir (dp);  errno = oe;  return fp;}FILE *maildir_open_find_message (const char *folder, const char *msg){  char unique[_POSIX_PATH_MAX];  FILE *fp;  static unsigned int new_hits = 0, cur_hits = 0;	/* simple dynamic optimization */  maildir_canon_filename (unique, msg, sizeof (unique));  if (      (fp =       _maildir_open_find_message (folder, unique,				   new_hits > cur_hits ? "new" : "cur"))      || errno != ENOENT)  {    if (new_hits < UINT_MAX && cur_hits < UINT_MAX)    {      new_hits += (new_hits > cur_hits ? 1 : 0);      cur_hits += (new_hits > cur_hits ? 0 : 1);    }    return fp;  }  if (      (fp =       _maildir_open_find_message (folder, unique,				   new_hits > cur_hits ? "cur" : "new"))      || errno != ENOENT)  {    if (new_hits < UINT_MAX && cur_hits < UINT_MAX)    {      new_hits += (new_hits > cur_hits ? 0 : 1);      cur_hits += (new_hits > cur_hits ? 1 : 0);    }    return fp;  }  return NULL;}/* * Returns: * 1 if there are no messages in the mailbox * 0 if there are messages in the mailbox * -1 on error */int maildir_check_empty (const char *path){  DIR *dp;  struct dirent *de;  int r = 1; /* assume empty until we find a message */  char realpath[_POSIX_PATH_MAX];  int iter = 0;  /* Strategy here is to look for any file not beginning with a period */  do {    /* we do "cur" on the first iteration since its more likely that we'll     * find old messages without having to scan both subdirs     */    snprintf (realpath, sizeof (realpath), "%s/%s", path,	      iter == 0 ? "cur" : "new");    if ((dp = opendir (realpath)) == NULL)      return -1;    while ((de = readdir (dp)))    {      if (*de->d_name != '.')      {	r = 0;	break;      }    }    closedir (dp);    iter++;  } while (r && iter < 2);  return r;}/* * Returns: * 1 if there are no messages in the mailbox * 0 if there are messages in the mailbox * -1 on error */int mh_check_empty (const char *path){  DIR *dp;  struct dirent *de;  int r = 1; /* assume empty until we find a message */    if ((dp = opendir (path)) == NULL)    return -1;  while ((de = readdir (dp)))  {    if (mh_valid_message (de->d_name))    {      r = 0;      break;    }  }  closedir (dp);    return r;}

⌨️ 快捷键说明

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