]> diplodocus.org Git - nmh/blob - sbr/seq_save.c
uip/mhcachesbr.c: Move exported symbols to existing h/mhcachesbr.h.
[nmh] / sbr / seq_save.c
1 /* seq_save.c -- 1) synchronize sequences
2 * -- 2) save public sequences
3 *
4 * This code is Copyright (c) 2002, by the authors of nmh. See the
5 * COPYRIGHT file in the root directory of the nmh distribution for
6 * complete copyright information.
7 */
8
9 #include <h/mh.h>
10 #include <h/signals.h>
11 #include "m_mktemp.h"
12
13
14 /*
15 * 1. If sequence is public and folder is readonly,
16 * then change it to be private
17 * 2a. If sequence is public, then add it to the sequences file
18 * in folder (name specified by mh-sequences profile entry).
19 * 2b. If sequence is private, then add it to the
20 * context file.
21 */
22
23 void
24 seq_save (struct msgs *mp)
25 {
26 size_t i;
27 char flags, *cp, attr[BUFSIZ], seqfile[PATH_MAX];
28 FILE *fp;
29 sigset_t set, oset;
30
31 /* check if sequence information has changed */
32 if (!(mp->msgflags & SEQMOD)) {
33 if (mp->seqhandle) {
34 lkfclosedata (mp->seqhandle, mp->seqname);
35 mp->seqhandle = NULL;
36 free(mp->seqname);
37 mp->seqname = NULL;
38 }
39 return;
40 }
41 mp->msgflags &= ~SEQMOD;
42
43 fp = NULL;
44 flags = mp->msgflags; /* record folder flags */
45
46 /*
47 * If no mh-sequences file is defined, or if a mh-sequences file
48 * is defined but empty (*mh_seq == '\0'), then pretend folder
49 * is readonly. This will force all sequences to be private.
50 */
51 if (mh_seq == NULL || *mh_seq == '\0')
52 set_readonly (mp);
53 else
54 snprintf (seqfile, sizeof(seqfile), "%s/%s", mp->foldpath, mh_seq);
55
56 for (i = 0; i < svector_size (mp->msgattrs); i++) {
57 snprintf (attr, sizeof(attr), "atr-%s-%s",
58 svector_at (mp->msgattrs, i), mp->foldpath);
59
60 /* get space separated list of sequence ranges */
61 if (!(cp = seq_list(mp, svector_at (mp->msgattrs, i)))) {
62 context_del (attr); /* delete sequence from context */
63 continue;
64 }
65
66 if (is_readonly(mp) || is_seq_private(mp, i)) {
67 priv:
68 /*
69 * sequence is private
70 */
71 context_replace (attr, cp); /* update sequence in context */
72 } else {
73 /*
74 * sequence is public
75 */
76 context_del (attr); /* delete sequence from context */
77
78 if (!fp) {
79 int failed_to_lock = 0;
80
81 /*
82 * Attempt to open file for public sequences.
83 * If that fails (probably because folder is
84 * readonly), then make sequence private.
85 */
86
87 if (mp->seqhandle) {
88 fp = mp->seqhandle;
89 mp->seqhandle = NULL;
90 free(mp->seqname);
91 mp->seqname = NULL;
92 rewind(fp);
93 if (ftruncate(fileno(fp), 0) < 0) {
94 advise ("sequence file", "ftruncate");
95 }
96 } else if ((fp = lkfopendata (seqfile, "w", &failed_to_lock))
97 == NULL
98 && (m_unlink (seqfile) == -1 ||
99 (fp = lkfopendata (seqfile, "w", &failed_to_lock))
100 == NULL)) {
101 if (failed_to_lock) {
102 admonish (attr, "unable to lock");
103 } else {
104 admonish (attr, "unable to write");
105 }
106 goto priv;
107 }
108
109 /* block a few signals */
110 sigemptyset (&set);
111 sigaddset(&set, SIGHUP);
112 sigaddset(&set, SIGINT);
113 sigaddset(&set, SIGQUIT);
114 sigaddset(&set, SIGTERM);
115 sigprocmask (SIG_BLOCK, &set, &oset);
116 }
117 fprintf (fp, "%s: %s\n", svector_at (mp->msgattrs, i), cp);
118 }
119 }
120
121 if (fp) {
122 lkfclosedata (fp, seqfile);
123 sigprocmask (SIG_SETMASK, &oset, &set); /* reset signal mask */
124 } else {
125 /*
126 * If folder is not readonly, and we didn't save any
127 * public sequences, then remove that file.
128 */
129 if (!is_readonly(mp))
130 (void) m_unlink (seqfile);
131 }
132
133 /*
134 * Reset folder flag, since we may be
135 * pretending that folder is readonly.
136 */
137 mp->msgflags = flags;
138 }