Copied atexit() code from fakesmtp.c to fakepop.c so that its
[mmh] / sbr / folder_delmsgs.c
1
2 /*
3  * folder_delmsgs.c -- "remove" SELECTED messages from a folder
4  *
5  * This code is Copyright (c) 2002, by the authors of nmh.  See the
6  * COPYRIGHT file in the root directory of the nmh distribution for
7  * complete copyright information.
8  */
9
10 #include <h/mh.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;
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         vec = (char **) calloc ((size_t) (mp->numsel + 2), sizeof(*vec));
44         if (vec == NULL)
45             adios (NULL, "unable to allocate exec vector");
46         vecp = 1;
47         for (msgnum = mp->lowsel; msgnum <= mp->hghsel; msgnum++) {
48             if (is_selected (mp, msgnum) &&
49                 !(vec[vecp++] = strdup (m_name (msgnum))))
50                 adios (NULL, "strdup failed");
51         }
52         vec[vecp] = NULL;
53
54         fflush (stdout);
55         vec[0] = r1bindex (rmmproc, '/');
56
57         switch (pid = vfork()) {
58         case -1:
59             advise ("fork", "unable to");
60             return -1;
61
62         case 0:
63             execvp (rmmproc, vec);
64             fprintf (stderr, "unable to exec ");
65             perror (rmmproc);
66             _exit (-1);
67
68         default:
69             return (pidwait (pid, -1));
70         }
71     }
72
73     /*
74      * Either unlink or rename the SELECTED messages
75      */
76     for (msgnum = mp->lowsel; msgnum <= mp->hghsel; msgnum++) {
77         if (is_selected (mp, msgnum)) {
78             /* unselect message */
79             unset_selected (mp, msgnum);
80             mp->numsel--;
81
82             /*
83              *  Run the external hook on the message if one was specified in the context.
84              *  All we have is the message number; we have changed to the directory
85              *  containing the message.  So, we need to extract that directory to form
86              *  the complete path.  Note that the caller knows the directory, but has
87              *  no way of passing that to us.
88              */
89
90             if (!nohook) {
91                     (void)snprintf(msgpath, sizeof (msgpath), "%s/%d", mp->foldpath, msgnum);
92                     (void)ext_hook("del-hook", msgpath, (char *)0);
93                 }
94
95             dp = m_name (msgnum);
96
97             if (unlink_msgs) {
98                 /* just unlink the messages */
99                 if (unlink (dp) == -1) {
100                     admonish (dp, "unable to unlink");
101                     retval = -1;
102                     continue;
103                 }
104             } else {
105                 /* or rename messages with standard prefix */
106                 strncpy (buf, m_backup (dp), sizeof(buf));
107                 if (rename (dp, buf) == -1) {
108                     admonish (buf, "unable to rename %s to", dp);
109                     retval = -1;
110                     continue;
111                 }
112             }
113
114             /* If removal was successful, decrement message count */
115             unset_exists (mp, msgnum);
116             mp->nummsg--;
117         }
118     }
119
120     /* Sanity check */
121     if (mp->numsel != 0)
122         adios (NULL, "oops, mp->numsel should be 0");
123
124     /* Mark that the sequence information has changed */
125     mp->msgflags |= SEQMOD;
126
127     return retval;
128 }