Rearranged whitespace (and comments) in all the code!
[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", 0 },
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 #ifdef LOCALE
38         setlocale(LC_ALL, "");
39 #endif
40         invo_name = r1bindex (argv[0], '/');
41
42         /* read user profile/context */
43         context_read();
44
45         arguments = getarguments (invo_name, argc, argv, 1);
46         argp = arguments;
47
48         while ((cp = *argp++)) {
49                 if (*cp == '-') {
50                         switch (smatch (++cp, switches)) {
51                                 case AMBIGSW:
52                                         ambigsw (cp, switches);
53                                         done (1);
54                                 case UNKWNSW:
55                                         adios (NULL, "-%s unknown", cp);
56
57                                 case HELPSW:
58                                         snprintf (buf, sizeof(buf), "%s [+folder] [switches]",
59                                                 invo_name);
60                                         print_help (buf, switches, 1);
61                                         done (1);
62                                 case VERSIONSW:
63                                         print_version(invo_name);
64                                         done (1);
65
66                                 case INTRSW:
67                                         interactive = 1;
68                                         continue;
69                                 case NINTRSW:
70                                         interactive = 0;
71                                         continue;
72                         }
73                 }
74                 if (*cp == '+' || *cp == '@') {
75                         if (folder)
76                                 adios (NULL, "only one folder at a time!");
77                         else
78                                 folder = pluspath (cp);
79                 } else {
80                         adios (NULL, "usage: %s [+folder] [switches]", invo_name);
81                 }
82         }
83
84         if (!context_find ("path"))
85                 free (path ("./", TFOLDER));
86         if (!folder) {
87                 folder = getfolder (1);
88                 defolder++;
89         }
90         if (strcmp (m_mailpath (folder), pwd ()) == 0)
91                 adios (NULL, "sorry, you can't remove the current working directory");
92
93         if (interactive == -1)
94                 interactive = defolder;
95
96         if (strchr (folder, '/') && (*folder != '/') && (*folder != '.')) {
97                 for (cp = copy (folder, newfolder); cp > newfolder && *cp != '/'; cp--)
98                         continue;
99                 if (cp > newfolder)
100                         *cp = '\0';
101                 else
102                         strncpy (newfolder, getfolder(0), sizeof(newfolder));
103         } else {
104                 strncpy (newfolder, getfolder(0), sizeof(newfolder));
105         }
106
107         if (interactive) {
108                 cp = concat ("Remove folder \"", folder, "\"? ", NULL);
109                 if (!getanswer (cp))
110                         done (0);
111                 free (cp);
112         }
113
114         if (rmf (folder) == OK) {
115                 char *cfolder = context_find(pfolder);
116                 if (cfolder && strcmp (cfolder, newfolder)) {
117                         printf ("[+%s now current]\n", newfolder);
118                         context_replace (pfolder, newfolder);  /* update current folder */
119                 }
120         }
121         context_save ();  /* save the context file */
122         done (0);
123         return 1;
124 }
125
126 static int
127 rmf (char *folder)
128 {
129         int i, j, others;
130         register char *maildir;
131         char cur[BUFSIZ];
132         register struct dirent *dp;
133         register DIR *dd;
134
135         switch (i = chdir (maildir = m_maildir (folder))) {
136                 case OK:
137                         if (access (".", W_OK) != NOTOK && access ("..", W_OK) != NOTOK)
138                                 break;  /* fall otherwise */
139
140                 case NOTOK:
141                         snprintf (cur, sizeof(cur), "atr-%s-%s",
142                                                 current, m_mailpath (folder));
143                         if (!context_del (cur)) {
144                                 printf ("[+%s de-referenced]\n", folder);
145                                 return OK;
146                         }
147                         advise (NULL, "you have no profile entry for the %s folder +%s",
148                                         i == NOTOK ? "unreadable" : "read-only", 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         (void)ext_hook("del-hook", maildir, (char *)0);
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 #ifdef MHE
172                         case '+':
173 #endif /* MHE */
174 #ifdef UCI
175                         case '_':
176                         case '#':
177 #endif /* UCI */
178                                 break;
179
180                         default:
181                                 if (m_atoi (dp->d_name))
182                                         break;
183                                 if (strcmp (dp->d_name, altmsglink) == 0
184                                                 || strncmp (dp->d_name, backup_prefix, j) == 0)
185                                         break;
186
187                                 admonish (NULL, "file \"%s/%s\" not deleted",
188                                                 folder, dp->d_name);
189                                 others++;
190                                 continue;
191                 }
192                 if (unlink (dp->d_name) == NOTOK) {
193                         admonish (dp->d_name, "unable to unlink %s:", folder);
194                         others++;
195                 }
196         }
197
198         closedir (dd);
199
200         /*
201          * Remove any relevant private sequences
202          * or attributes from context file.
203          */
204         rma (folder);
205
206         chdir ("..");
207         if (others == 0 && remdir (maildir))
208                 return OK;
209
210         advise (NULL, "folder +%s not removed", folder);
211         return NOTOK;
212 }
213
214
215 /*
216  * Remove all the (private) sequence information for
217  * this folder from the profile/context list.
218  */
219
220 static void
221 rma (char *folder)
222 {
223         register int alen, j, plen;
224         register char *cp;
225         register struct node *np, *pp;
226
227         alen = strlen ("atr-");
228         plen = strlen (cp = m_mailpath (folder)) + 1;
229
230         /*
231          * Search context list for keys that look like
232          * "atr-something-folderpath", and remove them.
233          */
234         for (np = m_defs, pp = NULL; np; np = np->n_next) {
235                 if (ssequal ("atr-", np->n_name)
236                                 && (j = strlen (np->n_name) - plen) > alen
237                                 && *(np->n_name + j) == '-'
238                                 && strcmp (cp, np->n_name + j + 1) == 0) {
239                         if (!np->n_context)
240                                 admonish (NULL, "bug: context_del(key=\"%s\")", np->n_name);
241                         if (pp) {
242                                 pp->n_next = np->n_next;
243                                 np = pp;
244                         } else {
245                                 m_defs = np->n_next;
246                         }
247                         ctxflags |= CTXMOD;
248                 } else {
249                         pp = np;
250                 }
251         }
252 }