📄 mx.c
字号:
/* save changes to mailbox * * return values: * 0 success * -1 error */int mx_sync_mailbox (CONTEXT *ctx, int *index_hint){ int rc, i; int purge = 1; int msgcount, deleted; if (ctx->dontwrite) { char buf[STRING], tmp[STRING]; if (km_expand_key (buf, sizeof(buf), km_find_func (MENU_MAIN, OP_TOGGLE_WRITE))) snprintf (tmp, sizeof(tmp), _(" Press '%s' to toggle write"), buf); else strfcpy (tmp, _("Use 'toggle-write' to re-enable write!"), sizeof(tmp)); mutt_error (_("Mailbox is marked unwritable. %s"), tmp); return -1; } else if (ctx->readonly) { mutt_error _("Mailbox is read-only."); return -1; } if (!ctx->changed && !ctx->deleted) { mutt_message _("Mailbox is unchanged."); return (0); } if (ctx->deleted) { char buf[SHORT_STRING]; snprintf (buf, sizeof (buf), ctx->deleted == 1 ? _("Purge %d deleted message?") : _("Purge %d deleted messages?"), ctx->deleted); if ((purge = query_quadoption (OPT_DELETE, buf)) < 0) return (-1); else if (purge == M_NO) { if (!ctx->changed) return 0; /* nothing to do! */#ifdef USE_IMAP /* let IMAP servers hold on to D flags */ if (ctx->magic != M_IMAP)#endif { for (i = 0 ; i < ctx->msgcount ; i++) ctx->hdrs[i]->deleted = 0; ctx->deleted = 0; } } else if (ctx->last_tag && ctx->last_tag->deleted) ctx->last_tag = NULL; /* reset last tagged msg now useless */ } /* really only for IMAP - imap_sync_mailbox results in a call to * mx_update_tables, so ctx->deleted is 0 when it comes back */ msgcount = ctx->msgcount; deleted = ctx->deleted;#ifdef USE_IMAP if (ctx->magic == M_IMAP) rc = imap_sync_mailbox (ctx, purge, index_hint); else#endif rc = sync_mailbox (ctx, index_hint); if (rc == 0) {#ifdef USE_IMAP if (ctx->magic == M_IMAP && !purge) mutt_message _("Mailbox checkpointed."); else#endif mutt_message (_("%d kept, %d deleted."), msgcount - deleted, deleted); mutt_sleep (0); if (ctx->msgcount == ctx->deleted && (ctx->magic == M_MBOX || ctx->magic == M_MMDF) && !mutt_is_spool (ctx->path) && !option (OPTSAVEEMPTY)) { unlink (ctx->path); mx_fastclose_mailbox (ctx); return 0; } /* if we haven't deleted any messages, we don't need to resort */ /* ... except for certain folder formats which need "unsorted" * sort order in order to synchronize folders. * * MH and maildir are safe. mbox-style seems to need re-sorting, * at least with the new threading code. */ if (purge || (ctx->magic != M_MAILDIR && ctx->magic != M_MH)) {#ifdef USE_IMAP /* IMAP does this automatically after handling EXPUNGE */ if (ctx->magic != M_IMAP)#endif { mx_update_tables (ctx, 1); mutt_sort_headers (ctx, 1); /* rethread from scratch */ } } } return (rc);}/* {maildir,mh}_open_new_message are in mh.c. */int mbox_open_new_message (MESSAGE *msg, CONTEXT *dest, HEADER *hdr){ msg->fp = dest->fp; return 0;}#ifdef USE_IMAPint imap_open_new_message (MESSAGE *msg, CONTEXT *dest, HEADER *hdr){ char tmp[_POSIX_PATH_MAX]; mutt_mktemp(tmp); if ((msg->fp = safe_fopen (tmp, "w")) == NULL) { mutt_perror (tmp); return (-1); } msg->path = safe_strdup(tmp); return 0;}#endif/* args: * dest destintation mailbox * hdr message being copied (required for maildir support, because * the filename depends on the message flags) */MESSAGE *mx_open_new_message (CONTEXT *dest, HEADER *hdr, int flags){ MESSAGE *msg; int (*func) (MESSAGE *, CONTEXT *, HEADER *); ADDRESS *p = NULL; switch (dest->magic) { case M_MMDF: case M_MBOX: func = mbox_open_new_message; break; case M_MAILDIR: func = maildir_open_new_message; break; case M_MH: func = mh_open_new_message; break;#ifdef USE_IMAP case M_IMAP: func = imap_open_new_message; break;#endif default: dprint (1, (debugfile, "mx_open_new_message(): function unimplemented for mailbox type %d.\n", dest->magic)); return (NULL); } msg = safe_calloc (1, sizeof (MESSAGE)); msg->magic = dest->magic; msg->write = 1; if (hdr) { msg->flags.flagged = hdr->flagged; msg->flags.replied = hdr->replied; msg->flags.read = hdr->read; msg->received = hdr->received; } if(msg->received == 0) time(&msg->received); if (func (msg, dest, hdr) == 0) { if (dest->magic == M_MMDF) fputs (MMDF_SEP, msg->fp); if ((msg->magic == M_MBOX || msg->magic == M_MMDF) && flags & M_ADD_FROM) { if (hdr) { if (hdr->env->return_path) p = hdr->env->return_path; else if (hdr->env->sender) p = hdr->env->sender; else p = hdr->env->from; } fprintf (msg->fp, "From %s %s", p ? p->mailbox : NONULL(Username), ctime (&msg->received)); } } else FREE (&msg); return msg;}/* check for new mail */int mx_check_mailbox (CONTEXT *ctx, int *index_hint, int lock){ int rc; if (ctx) { if (ctx->locked) lock = 0; switch (ctx->magic) { case M_MBOX: case M_MMDF: if (lock) { mutt_block_signals (); if (mbox_lock_mailbox (ctx, 0, 0) == -1) { mutt_unblock_signals (); return M_LOCKED; } } rc = mbox_check_mailbox (ctx, index_hint); if (lock) { mutt_unblock_signals (); mbox_unlock_mailbox (ctx); } return rc; case M_MH: return (mh_check_mailbox (ctx, index_hint)); case M_MAILDIR: return (maildir_check_mailbox (ctx, index_hint));#ifdef USE_IMAP case M_IMAP: return (imap_check_mailbox (ctx, index_hint, 0));#endif /* USE_IMAP */#ifdef USE_POP case M_POP: return (pop_check_mailbox (ctx, index_hint));#endif /* USE_POP */ } } dprint (1, (debugfile, "mx_check_mailbox: null or invalid context.\n")); return (-1);}/* return a stream pointer for a message */MESSAGE *mx_open_message (CONTEXT *ctx, int msgno){ MESSAGE *msg; msg = safe_calloc (1, sizeof (MESSAGE)); switch (msg->magic = ctx->magic) { case M_MBOX: case M_MMDF: msg->fp = ctx->fp; break; case M_MH: case M_MAILDIR: { HEADER *cur = ctx->hdrs[msgno]; char path[_POSIX_PATH_MAX]; snprintf (path, sizeof (path), "%s/%s", ctx->path, cur->path); if ((msg->fp = fopen (path, "r")) == NULL && errno == ENOENT && ctx->magic == M_MAILDIR) msg->fp = maildir_open_find_message (ctx->path, cur->path); if (msg->fp == NULL) { mutt_perror (path); dprint (1, (debugfile, "mx_open_message: fopen: %s: %s (errno %d).\n", path, strerror (errno), errno)); FREE (&msg); } } break; #ifdef USE_IMAP case M_IMAP: { if (imap_fetch_message (msg, ctx, msgno) != 0) FREE (&msg); break; }#endif /* USE_IMAP */#ifdef USE_POP case M_POP: { if (pop_fetch_message (msg, ctx, msgno) != 0) FREE (&msg); break; }#endif /* USE_POP */ default: dprint (1, (debugfile, "mx_open_message(): function not implemented for mailbox type %d.\n", ctx->magic)); FREE (&msg); break; } return (msg);}/* commit a message to a folder */int mx_commit_message (MESSAGE *msg, CONTEXT *ctx){ int r = 0; if (!(msg->write && ctx->append)) { dprint (1, (debugfile, "mx_commit_message(): msg->write = %d, ctx->append = %d\n", msg->write, ctx->append)); return -1; } switch (msg->magic) { case M_MMDF: { if (fputs (MMDF_SEP, msg->fp) == EOF) r = -1; break; } case M_MBOX: { if (fputc ('\n', msg->fp) == EOF) r = -1; break; }#ifdef USE_IMAP case M_IMAP: { if ((r = safe_fclose (&msg->fp)) == 0) r = imap_append_message (ctx, msg); break; }#endif case M_MAILDIR: { r = maildir_commit_message (ctx, msg, NULL); break; } case M_MH: { r = mh_commit_message (ctx, msg, NULL); break; } } if (r == 0 && (ctx->magic == M_MBOX || ctx->magic == M_MMDF) && (fflush (msg->fp) == EOF || fsync (fileno (msg->fp)) == -1)) { mutt_perror _("Can't write message"); r = -1; } return r;}/* close a pointer to a message */int mx_close_message (MESSAGE **msg){ int r = 0; if ((*msg)->magic == M_MH || (*msg)->magic == M_MAILDIR#ifdef USE_IMAP || (*msg)->magic == M_IMAP#endif#ifdef USE_POP || (*msg)->magic == M_POP#endif ) { r = safe_fclose (&(*msg)->fp); } else (*msg)->fp = NULL; if ((*msg)->path) { dprint (1, (debugfile, "mx_close_message (): unlinking %s\n", (*msg)->path)); unlink ((*msg)->path); FREE (&(*msg)->path); } FREE (msg); /* __FREE_CHECKED__ */ return (r);}void mx_alloc_memory (CONTEXT *ctx){ int i; size_t s = MAX (sizeof (HEADER *), sizeof (int)); if ((ctx->hdrmax + 25) * s < ctx->hdrmax * s) { mutt_error _("Integer overflow -- can't allocate memory."); sleep (1); mutt_exit (1); } if (ctx->hdrs) { safe_realloc (&ctx->hdrs, sizeof (HEADER *) * (ctx->hdrmax += 25)); safe_realloc (&ctx->v2r, sizeof (int) * ctx->hdrmax); } else { ctx->hdrs = safe_calloc ((ctx->hdrmax += 25), sizeof (HEADER *)); ctx->v2r = safe_calloc (ctx->hdrmax, sizeof (int)); } for (i = ctx->msgcount ; i < ctx->hdrmax ; i++) { ctx->hdrs[i] = NULL; ctx->v2r[i] = -1; }}/* this routine is called to update the counts in the context structure for * the last message header parsed. */void mx_update_context (CONTEXT *ctx, int new_messages){ HEADER *h; int msgno; for (msgno = ctx->msgcount - new_messages; msgno < ctx->msgcount; msgno++) { h = ctx->hdrs[msgno]; if (WithCrypto) { /* NOTE: this _must_ be done before the check for mailcap! */ h->security = crypt_query (h->content); } if (!ctx->pattern) { ctx->v2r[ctx->vcount] = msgno; h->virtual = ctx->vcount++; } else h->virtual = -1; h->msgno = msgno; if (h->env->supersedes) { HEADER *h2; if (!ctx->id_hash) ctx->id_hash = mutt_make_id_hash (ctx); h2 = hash_find (ctx->id_hash, h->env->supersedes); /* FREE (&h->env->supersedes); should I ? */ if (h2) { h2->superseded = 1; if (option (OPTSCORE)) mutt_score_message (ctx, h2, 1); } } /* add this message to the hash tables */ if (ctx->id_hash && h->env->message_id) hash_insert (ctx->id_hash, h->env->message_id, h, 0); if (ctx->subj_hash && h->env->real_subj) hash_insert (ctx->subj_hash, h->env->real_subj, h, 1); if (option (OPTSCORE)) mutt_score_message (ctx, h, 0); if (h->changed) ctx->changed = 1; if (h->flagged) ctx->flagged++; if (h->deleted) ctx->deleted++; if (!h->read) { ctx->unread++; if (!h->old) ctx->new++; } }}/* * Return: * 1 if the specified mailbox contains 0 messages. * 0 if the mailbox contains messages * -1 on error */int mx_check_empty (const char *path){ switch (mx_get_magic (path)) { case M_MBOX: case M_MMDF: return mbox_check_empty (path); case M_MH: return mh_check_empty (path); case M_MAILDIR: return maildir_check_empty (path); default: errno = EINVAL; return -1; } /* not reached */}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -