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
seq_save(struct msgs * mp)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 }
113