]> diplodocus.org Git - nmh/blob - sbr/folder_delmsgs.c
Improve fmttest output
[nmh] / sbr / folder_delmsgs.c
1 /* folder_delmsgs.c -- "remove" SELECTED messages from a folder
2 *
3 * This code is Copyright (c) 2002, by the authors of nmh. See the
4 * COPYRIGHT file in the root directory of the nmh distribution for
5 * complete copyright information.
6 */
7
8 #include "h/mh.h"
9 #include "m_name.h"
10 #include "seq_save.h"
11 #include "m_backup.h"
12 #include "ext_hook.h"
13 #include "folder_delmsgs.h"
14 #include "context_save.h"
15 #include "arglist.h"
16 #include "error.h"
17 #include "h/utils.h"
18 #include "m_mktemp.h"
19
20 /*
21 * 1) If we are using an external rmmproc, then exec it.
22 * 2) Else if unlink_msgs is non-zero, then unlink the
23 * SELECTED messages.
24 * 3) Else rename SELECTED messages by prefixing name
25 * with a standard prefix.
26 *
27 * If there is an error, return -1, else return 0.
28 */
29
30 int
31 folder_delmsgs (struct msgs *mp, int unlink_msgs, int nohook)
32 {
33 pid_t pid;
34 int msgnum, vecp, retval = 0;
35 char buf[100], *dp, **vec, *prog;
36 char msgpath[BUFSIZ];
37
38 /*
39 * If "rmmproc" is defined, exec it to remove messages.
40 */
41 if (rmmproc) {
42 /* Unset the EXISTS flag for each message to be removed */
43 for (msgnum = mp->lowsel; msgnum <= mp->hghsel; msgnum++) {
44 if (is_selected (mp, msgnum))
45 unset_exists (mp, msgnum);
46 }
47
48 /* Mark that the sequence information has changed */
49 mp->msgflags |= SEQMOD;
50
51 /*
52 * Write out the sequence and context files; this will release
53 * any locks before the rmmproc is called.
54 */
55
56 seq_save (mp);
57 context_save ();
58
59 vec = argsplit(rmmproc, &prog, &vecp);
60
61 /*
62 * argsplit allocates a MAXARGS vector by default, If we need
63 * something bigger, allocate it ourselves
64 */
65
66 if (mp->numsel + vecp + 1 > MAXARGS)
67 vec = mh_xrealloc(vec, (mp->numsel + vecp + 1) * sizeof *vec);
68 for (msgnum = mp->lowsel; msgnum <= mp->hghsel; msgnum++) {
69 if (is_selected (mp, msgnum) &&
70 !(vec[vecp++] = strdup (m_name (msgnum))))
71 die("strdup failed");
72 }
73 vec[vecp] = NULL;
74
75 fflush (stdout);
76
77 switch (pid = fork()) {
78 case -1:
79 advise ("fork", "unable to");
80 return -1;
81
82 case 0:
83 execvp (prog, vec);
84 fprintf (stderr, "unable to exec ");
85 perror (rmmproc);
86 _exit(1);
87
88 default:
89 arglist_free(prog, vec);
90 return pidwait(pid, -1);
91 }
92 }
93
94 /*
95 * Either unlink or rename the SELECTED messages
96 */
97 for (msgnum = mp->lowsel; msgnum <= mp->hghsel; msgnum++) {
98 if (is_selected (mp, msgnum)) {
99 /* unselect message */
100 unset_selected (mp, msgnum);
101 mp->numsel--;
102
103 /*
104 * Run the external hook on the message if one was specified in the context.
105 * All we have is the message number; we have changed to the directory
106 * containing the message. So, we need to extract that directory to form
107 * the complete path. Note that the caller knows the directory, but has
108 * no way of passing that to us.
109 */
110
111 if (!nohook) {
112 (void)snprintf(msgpath, sizeof (msgpath), "%s/%d", mp->foldpath, msgnum);
113 (void)ext_hook("del-hook", msgpath, NULL);
114 }
115
116 dp = m_name (msgnum);
117
118 if (unlink_msgs) {
119 /* just unlink the messages */
120 if (m_unlink (dp) == -1) {
121 admonish (dp, "unable to unlink");
122 retval = -1;
123 continue;
124 }
125 } else {
126 /* or rename messages with standard prefix */
127 strncpy (buf, m_backup (dp), sizeof(buf));
128 if (rename (dp, buf) == -1) {
129 admonish (buf, "unable to rename %s to", dp);
130 retval = -1;
131 continue;
132 }
133 }
134
135 /* If removal was successful, decrement message count */
136 unset_exists (mp, msgnum);
137 mp->nummsg--;
138 }
139 }
140
141 /* Sanity check */
142 if (mp->numsel != 0)
143 die("oops, mp->numsel should be 0");
144
145 /* Mark that the sequence information has changed */
146 mp->msgflags |= SEQMOD;
147
148 /*
149 * Write out sequence and context files
150 */
151
152 seq_save (mp);
153 context_save ();
154
155 return retval;
156 }