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