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