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