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