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