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