Add/update copyright notice in all source code files.
[mmh] / sbr / seq_save.c
1
2 /*
3  * seq_save.c -- 1) synchronize sequences
4  *            -- 2) save public sequences
5  *
6  * $Id$
7  *
8  * This code is Copyright (c) 2002, by the authors of nmh.  See the
9  * COPYRIGHT file in the root directory of the nmh distribution for
10  * complete copyright information.
11  */
12
13 #include <h/mh.h>
14 #include <h/signals.h>
15
16
17 /*
18  * 1.  If sequence is public and folder is readonly,
19  *     then change it to be private
20  * 2a. If sequence is public, then add it to the sequences file
21  *     in folder (name specified by mh-sequences profile entry).
22  * 2b. If sequence is private, then add it to the
23  *     context file.
24  */
25
26 void
27 seq_save (struct msgs *mp)
28 {
29     int i;
30     char flags, *cp, attr[BUFSIZ], seqfile[PATH_MAX];
31     FILE *fp;
32     sigset_t set, oset;
33
34     /* sanity check - check that context has been read */
35     if (defpath == NULL)
36         adios (NULL, "oops, context hasn't been read yet");
37
38     /* check if sequence information has changed */
39     if (!(mp->msgflags & SEQMOD))
40         return;
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; mp->msgattrs[i]; i++) {
57         snprintf (attr, sizeof(attr), "atr-%s-%s", mp->msgattrs[i], mp->foldpath);
58
59         /* get space separated list of sequence ranges */
60         if (!(cp = seq_list(mp, 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                 /*
79                  * Attempt to open file for public sequences.
80                  * If that fails (probably because folder is
81                  * readonly), then make sequence private.
82                  */
83                 if ((fp = fopen (seqfile, "w")) == NULL
84                         && (unlink (seqfile) == -1 ||
85                             (fp = fopen (seqfile, "w")) == NULL)) {
86                     admonish (attr, "unable to write");
87                     goto priv;
88                 }
89
90                 /* block a few signals */
91                 sigemptyset (&set);
92                 sigaddset(&set, SIGHUP);
93                 sigaddset(&set, SIGINT);
94                 sigaddset(&set, SIGQUIT);
95                 sigaddset(&set, SIGTERM);
96                 SIGPROCMASK (SIG_BLOCK, &set, &oset);
97             }
98             fprintf (fp, "%s: %s\n", mp->msgattrs[i], cp);
99         }
100     }
101
102     if (fp) {
103         fclose (fp);
104         SIGPROCMASK (SIG_SETMASK, &oset, &set);  /* reset signal mask */
105     } else {
106         /*
107          * If folder is not readonly, and we didn't save any
108          * public sequences, then remove that file.
109          */
110         if (!is_readonly(mp))
111             unlink (seqfile);
112     }
113
114     /*
115      * Reset folder flag, since we may be
116      * pretending that folder is readonly.
117      */
118     mp->msgflags = flags;
119 }