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