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