cc-test.sh: t_behave_iconv_mainbody() should compile test instead, sigh!
[s-mailx.git] / cmd-folder.c
blobd94e7881ce0a81fd4292669c79e17116c19837e5
1 /*@ S-nail - a mail user agent derived from Berkeley Mail.
2 *@ Folder related user commands.
4 * Copyright (c) 2000-2004 Gunnar Ritter, Freiburg i. Br., Germany.
5 * Copyright (c) 2012 - 2018 Steffen (Daode) Nurpmeso <steffen@sdaoden.eu>.
6 */
7 /*
8 * Copyright (c) 1980, 1993
9 * The Regents of the University of California. All rights reserved.
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
13 * are met:
14 * 1. Redistributions of source code must retain the above copyright
15 * notice, this list of conditions and the following disclaimer.
16 * 2. Redistributions in binary form must reproduce the above copyright
17 * notice, this list of conditions and the following disclaimer in the
18 * documentation and/or other materials provided with the distribution.
19 * 3. Neither the name of the University nor the names of its contributors
20 * may be used to endorse or promote products derived from this software
21 * without specific prior written permission.
23 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
24 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
27 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
28 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
29 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
32 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
33 * SUCH DAMAGE.
35 #undef n_FILE
36 #define n_FILE cmd_folder
38 #ifndef HAVE_AMALGAMATION
39 # include "nail.h"
40 #endif
42 /* c_file, c_File */
43 static int _c_file(void *v, enum fedit_mode fm);
45 static int
46 _c_file(void *v, enum fedit_mode fm)
48 char **argv = v;
49 int i;
50 NYD2_ENTER;
52 if(*argv == NULL){
53 n_folder_announce(n_ANNOUNCE_STATUS);
54 i = 0;
55 goto jleave;
58 if (n_pstate & n_PS_HOOK_MASK) {
59 n_err(_("Cannot change folder from within a hook\n"));
60 i = 1;
61 goto jleave;
64 save_mbox_for_possible_quitstuff();
66 i = setfile(*argv, fm);
67 if (i < 0) {
68 i = 1;
69 goto jleave;
71 assert(!(fm & FEDIT_NEWMAIL)); /* (Prevent implementation error) */
72 if (n_pstate & n_PS_SETFILE_OPENED)
73 temporary_folder_hook_check(FAL0);
75 if (i > 0) {
76 /* TODO Don't report "no messages" == 1 == error when we're in, e.g.,
77 * TODO a macro: because that recursed commando loop will terminate the
78 * TODO entire macro due to that! So either the user needs to be able
79 * TODO to react&ignore this "error" (as in "if DOSTUFF" or "DOSTUFF;
80 * TODO if $?", then "overriding an "error"), or we need a different
81 * TODO return that differentiates */
82 i = (n_pstate & n_PS_ROBOT) ? 0 : 1;
83 goto jleave;
86 if(n_pstate & n_PS_SETFILE_OPENED)
87 n_folder_announce(n_ANNOUNCE_CHANGE);
88 i = 0;
89 jleave:
90 NYD2_LEAVE;
91 return i;
94 FL int
95 c_file(void *v)
97 int rv;
98 NYD_ENTER;
100 rv = _c_file(v, FEDIT_NONE);
101 NYD_LEAVE;
102 return rv;
105 FL int
106 c_File(void *v)
108 int rv;
109 NYD_ENTER;
111 rv = _c_file(v, FEDIT_RDONLY);
112 NYD_LEAVE;
113 return rv;
116 FL int
117 c_newmail(void *v)
119 int val = 1, mdot;
120 NYD_ENTER;
121 n_UNUSED(v);
123 if (n_pstate & n_PS_HOOK_MASK)
124 n_err(_("Cannot call `newmail' from within a hook\n"));
125 #ifdef HAVE_IMAP
126 else if(mb.mb_type == MB_IMAP && !imap_newmail(1))
128 #endif
129 else if ((val = setfile(mailname,
130 FEDIT_NEWMAIL | ((mb.mb_perm & MB_DELE) ? 0 : FEDIT_RDONLY))
131 ) == 0) {
132 mdot = getmdot(1);
133 setdot(message + mdot - 1);
135 NYD_LEAVE;
136 return val;
139 FL int
140 c_noop(void *v)
142 int rv = 0;
143 NYD_ENTER;
144 n_UNUSED(v);
146 switch (mb.mb_type) {
147 #ifdef HAVE_POP3
148 case MB_POP3:
149 pop3_noop();
150 break;
151 #endif
152 #ifdef HAVE_IMAP
153 case MB_IMAP:
154 imap_noop();
155 break;
156 #endif
157 default:
158 break;
160 NYD_LEAVE;
161 return rv;
164 FL int
165 c_remove(void *v)
167 char const *fmt;
168 size_t fmt_len;
169 char **args, *name, *ename;
170 int ec;
171 NYD_ENTER;
173 if (*(args = v) == NULL) {
174 n_err(_("Synopsis: remove: <mailbox>...\n"));
175 ec = 1;
176 goto jleave;
179 ec = 0;
181 fmt = _("Remove %s");
182 fmt_len = strlen(fmt);
183 do {
184 if ((name = fexpand(*args, FEXP_FULL)) == NULL)
185 continue;
186 ename = n_shexp_quote_cp(name, FAL0);
188 if (!strcmp(name, mailname)) {
189 n_err(_("Cannot remove current mailbox %s\n"), ename);
190 ec |= 1;
191 continue;
193 /* C99 */{
194 bool_t asw;
195 char *vb;
196 size_t vl;
198 vl = strlen(ename) + fmt_len +1;
199 vb = salloc(vl);
200 snprintf(vb, vl, fmt, ename);
201 asw = getapproval(vb, TRU1);
202 if (!asw)
203 continue;
206 switch (which_protocol(name, TRU1, FAL0, NULL)) {
207 case PROTO_FILE:
208 if (unlink(name) == -1) {
209 int se = n_err_no;
211 if (se == n_ERR_ISDIR) {
212 struct stat sb;
214 if (!stat(name, &sb) && S_ISDIR(sb.st_mode)) {
215 if (!rmdir(name))
216 break;
217 se = n_err_no;
220 n_perr(name, se);
221 ec |= 1;
223 break;
224 case PROTO_POP3:
225 n_err(_("Cannot remove POP3 mailbox %s\n"), ename);
226 ec |= 1;
227 break;
228 case PROTO_MAILDIR:
229 if (maildir_remove(name) != OKAY)
230 ec |= 1;
231 break;
232 case PROTO_IMAP:
233 #ifdef HAVE_IMAP
234 if(imap_remove(name) != OKAY)
235 ec |= 1;
236 #else
237 n_err(_("No IMAP support compiled in\n"));
238 ec |= 1;
239 #endif
240 break;
241 case PROTO_UNKNOWN:
242 default:
243 n_err(_("Not removed: unknown protocol: %s\n"), ename);
244 ec |= 1;
245 break;
247 } while (*++args != NULL);
248 jleave:
249 NYD_LEAVE;
250 return ec;
253 FL int
254 c_rename(void *v)
256 char **args = v, *oldn, *newn;
257 enum protocol oldp;
258 int ec;
259 NYD_ENTER;
261 ec = 1;
263 if (args[0] == NULL || args[1] == NULL || args[2] != NULL) {
264 n_err(_("Synopsis: rename: <old> <new>\n"));
265 goto jleave;
268 if ((oldn = fexpand(args[0], FEXP_FULL)) == NULL)
269 goto jleave;
270 oldp = which_protocol(oldn, TRU1, FAL0, NULL);
271 if ((newn = fexpand(args[1], FEXP_FULL)) == NULL)
272 goto jleave;
273 if(oldp != which_protocol(newn, TRU1, FAL0, NULL)) {
274 n_err(_("Can only rename folders of same type\n"));
275 goto jleave;
277 if (!strcmp(oldn, mailname) || !strcmp(newn, mailname)) {
278 n_err(_("Cannot rename current mailbox %s\n"),
279 n_shexp_quote_cp(oldn, FAL0));
280 goto jleave;
283 ec = 0;
285 switch (oldp) {
286 case PROTO_FILE:
287 if (link(oldn, newn) == -1) {
288 switch (n_err_no) {
289 case n_ERR_ACCES:
290 case n_ERR_EXIST:
291 case n_ERR_NAMETOOLONG:
292 case n_ERR_NOSPC:
293 case n_ERR_XDEV:
294 n_perr(newn, 0);
295 break;
296 default:
297 n_perr(oldn, 0);
298 break;
300 ec |= 1;
301 } else if (unlink(oldn) == -1) {
302 n_perr(oldn, 0);
303 ec |= 1;
305 break;
306 case PROTO_MAILDIR:
307 if (rename(oldn, newn) == -1) {
308 n_perr(oldn, 0);
309 ec |= 1;
311 break;
312 case PROTO_POP3:
313 n_err(_("Cannot rename POP3 mailboxes\n"));
314 ec |= 1;
315 break;
316 case PROTO_IMAP:
317 #ifdef HAVE_IMAP
318 if(imap_rename(oldn, newn) != OKAY)
319 ec |= 1;
320 #else
321 n_err(_("No IMAP support compiled in\n"));
322 ec |= 1;
323 #endif
324 break;
325 case PROTO_UNKNOWN:
326 default:
327 n_err(_("Unknown protocol in %s and %s; not renamed\n"),
328 n_shexp_quote_cp(oldn, FAL0), n_shexp_quote_cp(newn, FAL0));
329 ec |= 1;
330 break;
332 jleave:
333 NYD_LEAVE;
334 return ec;
337 FL int
338 c_folders(void *v){ /* TODO fexpand*/
339 enum fexp_mode const fexp = FEXP_NSHELL
340 #ifndef HAVE_IMAP
341 | FEXP_LOCAL
342 #endif
345 char const *cp;
346 char **argv;
347 int rv;
348 NYD_ENTER;
350 rv = 1;
352 if(*(argv = v) != NULL){
353 if((cp = fexpand(*argv, fexp)) == NULL)
354 goto jleave;
355 }else
356 cp = n_folder_query();
358 #ifdef HAVE_IMAP
359 if(which_protocol(cp, FAL0, FAL0, NULL) == PROTO_IMAP)
360 rv = imap_folders(cp, *argv == NULL);
361 else
362 #endif
363 rv = n_child_run(ok_vlook(LISTER), 0, n_CHILD_FD_PASS, n_CHILD_FD_PASS,
364 cp, NULL, NULL, NULL, NULL);
365 jleave:
366 NYD_LEAVE;
367 return rv;
370 /* s-it-mode */