void mh_update_sequences (CONTEXT *ctx) { FILE *ofp, *nfp; char sequences[_POSIX_PATH_MAX]; char *tmpfname; char *buff = NULL; char *p; size_t s; int l = 0; int i; int unseen = 0; int flagged = 0; int replied = 0; char seq_unseen[STRING]; char seq_replied[STRING]; char seq_flagged[STRING]; struct mh_sequences mhs; memset (&mhs, 0, sizeof (mhs)); snprintf (seq_unseen, sizeof (seq_unseen), "%s:", NONULL (MhUnseen)); snprintf (seq_replied, sizeof (seq_replied), "%s:", NONULL (MhReplied)); snprintf (seq_flagged, sizeof (seq_flagged), "%s:", NONULL (MhFlagged)); if (mh_mkstemp (ctx, &nfp, &tmpfname) != 0) { /* error message? */ return; } snprintf (sequences, sizeof (sequences), "%s/.mh_sequences", ctx->path); /* first, copy unknown sequences */ if ((ofp = fopen (sequences, "r"))) { while ((buff = mutt_read_line (buff, &s, ofp, &l))) { if (!mutt_strncmp (buff, seq_unseen, mutt_strlen (seq_unseen))) continue; if (!mutt_strncmp (buff, seq_flagged, mutt_strlen (seq_flagged))) continue; if (!mutt_strncmp (buff, seq_replied, mutt_strlen (seq_replied))) continue; fprintf (nfp, "%s\n", buff); } } safe_fclose (&ofp); /* now, update our unseen, flagged, and replied sequences */ for (l = 0; l < ctx->msgcount; l++) { if (ctx->hdrs[l]->deleted) continue; if ((p = strrchr (ctx->hdrs[l]->path, '/'))) p++; else p = ctx->hdrs[l]->path; i = atoi (p); if (!ctx->hdrs[l]->read) { mhs_set (&mhs, i, MH_SEQ_UNSEEN); unseen++; } if (ctx->hdrs[l]->flagged) { mhs_set (&mhs, i, MH_SEQ_FLAGGED); flagged++; } if (ctx->hdrs[l]->replied) { mhs_set (&mhs, i, MH_SEQ_REPLIED); replied++; } } /* write out the new sequences */ if (unseen) mhs_write_one_sequence (nfp, &mhs, MH_SEQ_UNSEEN, NONULL (MhUnseen)); if (flagged) mhs_write_one_sequence (nfp, &mhs, MH_SEQ_FLAGGED, NONULL (MhFlagged)); if (replied) mhs_write_one_sequence (nfp, &mhs, MH_SEQ_REPLIED, NONULL (MhReplied)); mhs_free_sequences (&mhs); /* try to commit the changes - no guarantee here */ safe_fclose (&nfp); unlink (sequences); if (safe_rename (tmpfname, sequences) != 0) { /* report an error? */ unlink (tmpfname); } safe_free ((void **) &tmpfname); }
/** * mh_update_sequences - Update sequence numbers * @param m Mailbox * * XXX we don't currently remove deleted messages from sequences we don't know. * Should we? */ void mh_update_sequences(struct Mailbox *m) { char sequences[PATH_MAX]; char *tmpfname = NULL; char *buf = NULL; char *p = NULL; size_t s; int l = 0; int i; int unseen = 0; int flagged = 0; int replied = 0; char seq_unseen[256]; char seq_replied[256]; char seq_flagged[256]; struct MhSequences mhs = { 0 }; snprintf(seq_unseen, sizeof(seq_unseen), "%s:", NONULL(C_MhSeqUnseen)); snprintf(seq_replied, sizeof(seq_replied), "%s:", NONULL(C_MhSeqReplied)); snprintf(seq_flagged, sizeof(seq_flagged), "%s:", NONULL(C_MhSeqFlagged)); FILE *fp_new = NULL; if (mh_mkstemp(m, &fp_new, &tmpfname) != 0) { /* error message? */ return; } snprintf(sequences, sizeof(sequences), "%s/.mh_sequences", m->path); /* first, copy unknown sequences */ FILE *fp_old = fopen(sequences, "r"); if (fp_old) { while ((buf = mutt_file_read_line(buf, &s, fp_old, &l, 0))) { if (mutt_str_startswith(buf, seq_unseen, CASE_MATCH) || mutt_str_startswith(buf, seq_flagged, CASE_MATCH) || mutt_str_startswith(buf, seq_replied, CASE_MATCH)) continue; fprintf(fp_new, "%s\n", buf); } } mutt_file_fclose(&fp_old); /* now, update our unseen, flagged, and replied sequences */ for (l = 0; l < m->msg_count; l++) { if (m->emails[l]->deleted) continue; p = strrchr(m->emails[l]->path, '/'); if (p) p++; else p = m->emails[l]->path; if (mutt_str_atoi(p, &i) < 0) continue; if (!m->emails[l]->read) { mhs_set(&mhs, i, MH_SEQ_UNSEEN); unseen++; } if (m->emails[l]->flagged) { mhs_set(&mhs, i, MH_SEQ_FLAGGED); flagged++; } if (m->emails[l]->replied) { mhs_set(&mhs, i, MH_SEQ_REPLIED); replied++; } } /* write out the new sequences */ if (unseen) mhs_write_one_sequence(fp_new, &mhs, MH_SEQ_UNSEEN, NONULL(C_MhSeqUnseen)); if (flagged) mhs_write_one_sequence(fp_new, &mhs, MH_SEQ_FLAGGED, NONULL(C_MhSeqFlagged)); if (replied) mhs_write_one_sequence(fp_new, &mhs, MH_SEQ_REPLIED, NONULL(C_MhSeqReplied)); mhs_free_sequences(&mhs); /* try to commit the changes - no guarantee here */ mutt_file_fclose(&fp_new); unlink(sequences); if (mutt_file_safe_rename(tmpfname, sequences) != 0) { /* report an error? */ unlink(tmpfname); } FREE(&tmpfname); }