]> diplodocus.org Git - nmh/blob - uip/rmf.c
95328881421fd3aba988a9361d1a0602db358c33
[nmh] / uip / rmf.c
1 /* rmf.c -- remove 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 "sbr/context_save.h"
10 #include "sbr/context_replace.h"
11 #include "sbr/context_del.h"
12 #include "sbr/context_find.h"
13 #include "sbr/ambigsw.h"
14 #include "sbr/path.h"
15 #include "sbr/print_version.h"
16 #include "sbr/print_help.h"
17 #include "sbr/error.h"
18 #include "h/done.h"
19 #include "h/utils.h"
20 #include "sbr/m_maildir.h"
21 #include "sbr/m_mktemp.h"
22
23 #define RMF_SWITCHES \
24 X("interactive", 0, INTRSW) \
25 X("nointeractive", 0, NINTRSW) \
26 X("version", 0, VERSIONSW) \
27 X("help", 0, HELPSW) \
28
29 #define X(sw, minchars, id) id,
30 DEFINE_SWITCH_ENUM(RMF);
31 #undef X
32
33 #define X(sw, minchars, id) { sw, minchars, id },
34 DEFINE_SWITCH_ARRAY(RMF, switches);
35 #undef X
36
37 /*
38 * static prototypes
39 */
40 static int rmf(char *);
41 static void rma (char *);
42
43
44 int
45 main (int argc, char **argv)
46 {
47 bool defolder = false;
48 int interactive = -1;
49 char *cp, *folder = NULL, newfolder[BUFSIZ];
50 char buf[BUFSIZ], **argp, **arguments;
51 char *fp;
52
53 if (nmh_init(argv[0], true, true)) { return 1; }
54
55 arguments = getarguments (invo_name, argc, argv, 1);
56 argp = arguments;
57
58 while ((cp = *argp++)) {
59 if (*cp == '-') {
60 switch (smatch (++cp, switches)) {
61 case AMBIGSW:
62 ambigsw (cp, switches);
63 done (1);
64 case UNKWNSW:
65 die("-%s unknown", cp);
66
67 case HELPSW:
68 snprintf (buf, sizeof(buf), "%s [+folder] [switches]",
69 invo_name);
70 print_help (buf, switches, 1);
71 done (0);
72 case VERSIONSW:
73 print_version(invo_name);
74 done (0);
75
76 case INTRSW:
77 interactive = 1;
78 continue;
79 case NINTRSW:
80 interactive = 0;
81 continue;
82 }
83 }
84 if (*cp == '+' || *cp == '@') {
85 if (folder)
86 die("only one folder at a time!");
87 folder = pluspath (cp);
88 } else {
89 die("usage: %s [+folder] [switches]", invo_name);
90 }
91 }
92
93 if (!context_find ("path"))
94 free (path ("./", TFOLDER));
95 if (!folder) {
96 folder = getfolder (1);
97 defolder = true;
98 }
99 fp = m_mailpath(folder);
100 if (!strcmp(fp, pwd()))
101 die("sorry, you can't remove the current working directory");
102 free(fp);
103
104 if (interactive == -1)
105 interactive = defolder;
106
107 if (strchr (folder, '/') && (*folder != '/') && (*folder != '.')) {
108 for (cp = stpcpy(newfolder, folder); cp > newfolder && *cp != '/'; cp--)
109 continue;
110 if (cp > newfolder)
111 *cp = '\0';
112 else
113 strncpy (newfolder, getfolder(0), sizeof(newfolder));
114 } else {
115 strncpy (newfolder, getfolder(0), sizeof(newfolder));
116 }
117
118 if (interactive) {
119 cp = concat ("Remove folder \"", folder, "\"? ", NULL);
120 if (!read_yes_or_no_if_tty (cp))
121 done (0);
122 free (cp);
123 }
124
125 if (rmf (folder) == OK) {
126 char *cfolder = context_find(pfolder);
127 if (cfolder && strcmp (cfolder, newfolder)) {
128 printf ("[+%s now current]\n", newfolder);
129 context_replace (pfolder, newfolder); /* update current folder */
130 }
131 }
132 context_save (); /* save the context file */
133 done (0);
134 return 1;
135 }
136
137 static int
138 rmf (char *folder)
139 {
140 int i;
141 bool others;
142 char *fp;
143 char *maildir;
144 char cur[BUFSIZ];
145 struct dirent *dp;
146 DIR *dd;
147
148 switch (i = chdir (maildir = m_maildir (folder))) {
149 case OK:
150 if (access (".", W_OK) != NOTOK && access ("..", W_OK) != NOTOK)
151 break;
152 /* FALLTHRU */
153
154 case NOTOK:
155 fp = m_mailpath(folder);
156 snprintf (cur, sizeof(cur), "atr-%s-%s", current, fp);
157 free(fp);
158 if (!context_del (cur)) {
159 printf ("[+%s de-referenced]\n", folder);
160 return OK;
161 }
162 inform("you have no profile entry for the %s folder +%s",
163 i == NOTOK ? "unreadable" : "read-only", folder);
164 return NOTOK;
165 }
166
167 if ((dd = opendir (".")) == NULL)
168 die("unable to read folder +%s", folder);
169 others = false;
170
171 /*
172 * Run the external delete hook program.
173 */
174
175 (void)ext_hook("del-hook", maildir, NULL);
176
177 while ((dp = readdir (dd))) {
178 switch (dp->d_name[0]) {
179 case '.':
180 if (strcmp (dp->d_name, ".") == 0
181 || strcmp (dp->d_name, "..") == 0)
182 continue;
183 break;
184
185 case ',':
186 break;
187
188 default:
189 if (m_atoi (dp->d_name))
190 break;
191 if (strcmp (dp->d_name, LINK) == 0
192 || has_prefix(dp->d_name, BACKUP_PREFIX))
193 break;
194
195 inform("file \"%s/%s\" not deleted, continuing...",
196 folder, dp->d_name);
197 others = true;
198 continue;
199 }
200 if (m_unlink (dp->d_name) == NOTOK) {
201 admonish (dp->d_name, "unable to unlink %s:", folder);
202 others = true;
203 }
204 }
205
206 closedir (dd);
207
208 /*
209 * Remove any relevant private sequences
210 * or attributes from context file.
211 */
212 rma (folder);
213
214 if (chdir ("..") < 0) {
215 advise ("..", "chdir");
216 }
217 if (!others && remdir (maildir))
218 return OK;
219
220 inform("folder +%s not removed", folder);
221 return NOTOK;
222 }
223
224
225 /*
226 * Remove all the (private) sequence information for
227 * this folder from the profile/context list.
228 */
229
230 static void
231 rma (char *folder)
232 {
233 int alen, j, plen;
234 char *cp;
235 struct node *np, *pp;
236
237 alen = LEN("atr-");
238 plen = strlen (cp = m_mailpath (folder)) + 1;
239
240 /*
241 * Search context list for keys that look like
242 * "atr-something-folderpath", and remove them.
243 */
244 for (np = m_defs, pp = NULL; np; np = np->n_next) {
245 if (ssequal ("atr-", np->n_name)
246 && (j = strlen (np->n_name) - plen) > alen
247 && *(np->n_name + j) == '-'
248 && strcmp (cp, np->n_name + j + 1) == 0) {
249 if (!np->n_context)
250 inform("bug: context_del(key=\"%s\"), continuing...",
251 np->n_name);
252 if (pp) {
253 pp->n_next = np->n_next;
254 np = pp;
255 } else {
256 m_defs = np->n_next;
257 }
258 ctxflags |= CTXMOD;
259 } else {
260 pp = np;
261 }
262 }
263
264 free(cp);
265 }