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