make-config.in: complete path (leftover of [807f64e2], 2015-12-26!)
[s-mailx.git] / cmd-folder.c
blob84af9e64f0a903c5bd319066f12cab9b3bed3447
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 * SPDX-License-Identifier: BSD-3-Clause
7 */
8 /*
9 * Copyright (c) 1980, 1993
10 * The Regents of the University of California. All rights reserved.
12 * Redistribution and use in source and binary forms, with or without
13 * modification, are permitted provided that the following conditions
14 * are met:
15 * 1. Redistributions of source code must retain the above copyright
16 * notice, this list of conditions and the following disclaimer.
17 * 2. Redistributions in binary form must reproduce the above copyright
18 * notice, this list of conditions and the following disclaimer in the
19 * documentation and/or other materials provided with the distribution.
20 * 3. Neither the name of the University nor the names of its contributors
21 * may be used to endorse or promote products derived from this software
22 * without specific prior written permission.
24 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
25 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
26 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
27 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
28 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
29 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
30 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
31 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
32 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
33 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
34 * SUCH DAMAGE.
36 #undef n_FILE
37 #define n_FILE cmd_folder
39 #ifndef HAVE_AMALGAMATION
40 # include "nail.h"
41 #endif
43 /* c_file, c_File */
44 static int _c_file(void *v, enum fedit_mode fm);
46 static int
47 _c_file(void *v, enum fedit_mode fm)
49 char **argv = v;
50 int i;
51 NYD2_ENTER;
53 if(*argv == NULL){
54 n_folder_announce(n_ANNOUNCE_STATUS);
55 i = 0;
56 goto jleave;
59 if (n_pstate & n_PS_HOOK_MASK) {
60 n_err(_("Cannot change folder from within a hook\n"));
61 i = 1;
62 goto jleave;
65 save_mbox_for_possible_quitstuff();
67 i = setfile(*argv, fm);
68 if (i < 0) {
69 i = 1;
70 goto jleave;
72 assert(!(fm & FEDIT_NEWMAIL)); /* (Prevent implementation error) */
73 if (n_pstate & n_PS_SETFILE_OPENED)
74 temporary_folder_hook_check(FAL0);
76 if (i > 0) {
77 /* TODO Don't report "no messages" == 1 == error when we're in, e.g.,
78 * TODO a macro: because that recursed commando loop will terminate the
79 * TODO entire macro due to that! So either the user needs to be able
80 * TODO to react&ignore this "error" (as in "if DOSTUFF" or "DOSTUFF;
81 * TODO if $?", then "overriding an "error"), or we need a different
82 * TODO return that differentiates */
83 i = (n_pstate & n_PS_ROBOT) ? 0 : 1;
84 goto jleave;
87 if(n_pstate & n_PS_SETFILE_OPENED)
88 n_folder_announce(n_ANNOUNCE_CHANGE);
89 i = 0;
90 jleave:
91 NYD2_LEAVE;
92 return i;
95 FL int
96 c_file(void *v)
98 int rv;
99 NYD_ENTER;
101 rv = _c_file(v, FEDIT_NONE);
102 NYD_LEAVE;
103 return rv;
106 FL int
107 c_File(void *v)
109 int rv;
110 NYD_ENTER;
112 rv = _c_file(v, FEDIT_RDONLY);
113 NYD_LEAVE;
114 return rv;
117 FL int
118 c_newmail(void *v)
120 int val = 1, mdot;
121 NYD_ENTER;
122 n_UNUSED(v);
124 if (n_pstate & n_PS_HOOK_MASK)
125 n_err(_("Cannot call `newmail' from within a hook\n"));
126 #ifdef HAVE_IMAP
127 else if(mb.mb_type == MB_IMAP && !imap_newmail(1))
129 #endif
130 else if ((val = setfile(mailname,
131 FEDIT_NEWMAIL | ((mb.mb_perm & MB_DELE) ? 0 : FEDIT_RDONLY))
132 ) == 0) {
133 mdot = getmdot(1);
134 setdot(message + mdot - 1);
136 NYD_LEAVE;
137 return val;
140 FL int
141 c_noop(void *v)
143 int rv = 0;
144 NYD_ENTER;
145 n_UNUSED(v);
147 switch (mb.mb_type) {
148 #ifdef HAVE_POP3
149 case MB_POP3:
150 pop3_noop();
151 break;
152 #endif
153 #ifdef HAVE_IMAP
154 case MB_IMAP:
155 imap_noop();
156 break;
157 #endif
158 default:
159 break;
161 NYD_LEAVE;
162 return rv;
165 FL int
166 c_remove(void *v)
168 char const *fmt;
169 size_t fmt_len;
170 char **args, *name, *ename;
171 int ec;
172 NYD_ENTER;
174 if (*(args = v) == NULL) {
175 n_err(_("Synopsis: remove: <mailbox>...\n"));
176 ec = 1;
177 goto jleave;
180 ec = 0;
182 fmt = _("Remove %s");
183 fmt_len = strlen(fmt);
184 do {
185 if ((name = fexpand(*args, FEXP_FULL)) == NULL)
186 continue;
187 ename = n_shexp_quote_cp(name, FAL0);
189 if (!strcmp(name, mailname)) {
190 n_err(_("Cannot remove current mailbox %s\n"), ename);
191 ec |= 1;
192 continue;
194 /* C99 */{
195 bool_t asw;
196 char *vb;
197 size_t vl;
199 vl = strlen(ename) + fmt_len +1;
200 vb = n_autorec_alloc(vl);
201 snprintf(vb, vl, fmt, ename);
202 asw = getapproval(vb, TRU1);
203 if (!asw)
204 continue;
207 switch (which_protocol(name, TRU1, FAL0, NULL)) {
208 case PROTO_FILE:
209 if (unlink(name) == -1) {
210 int se = n_err_no;
212 if (se == n_ERR_ISDIR) {
213 struct stat sb;
215 if (!stat(name, &sb) && S_ISDIR(sb.st_mode)) {
216 if (!rmdir(name))
217 break;
218 se = n_err_no;
221 n_perr(name, se);
222 ec |= 1;
224 break;
225 case PROTO_POP3:
226 n_err(_("Cannot remove POP3 mailbox %s\n"), ename);
227 ec |= 1;
228 break;
229 case PROTO_MAILDIR:
230 #ifdef HAVE_MAILDIR
231 if(maildir_remove(name) != OKAY)
232 ec |= 1;
233 #else
234 n_err(_("No Maildir directory support compiled in\n"));
235 ec |= 1;
236 #endif
237 break;
238 case PROTO_IMAP:
239 #ifdef HAVE_IMAP
240 if(imap_remove(name) != OKAY)
241 ec |= 1;
242 #else
243 n_err(_("No IMAP support compiled in\n"));
244 ec |= 1;
245 #endif
246 break;
247 case PROTO_UNKNOWN:
248 default:
249 n_err(_("Not removed: unknown protocol: %s\n"), ename);
250 ec |= 1;
251 break;
253 } while (*++args != NULL);
254 jleave:
255 NYD_LEAVE;
256 return ec;
259 FL int
260 c_rename(void *v)
262 char **args = v, *oldn, *newn;
263 enum protocol oldp;
264 int ec;
265 NYD_ENTER;
267 ec = 1;
269 if (args[0] == NULL || args[1] == NULL || args[2] != NULL) {
270 n_err(_("Synopsis: rename: <old> <new>\n"));
271 goto jleave;
274 if ((oldn = fexpand(args[0], FEXP_FULL)) == NULL)
275 goto jleave;
276 oldp = which_protocol(oldn, TRU1, FAL0, NULL);
277 if ((newn = fexpand(args[1], FEXP_FULL)) == NULL)
278 goto jleave;
279 if(oldp != which_protocol(newn, TRU1, FAL0, NULL)) {
280 n_err(_("Can only rename folders of same type\n"));
281 goto jleave;
283 if (!strcmp(oldn, mailname) || !strcmp(newn, mailname)) {
284 n_err(_("Cannot rename current mailbox %s\n"),
285 n_shexp_quote_cp(oldn, FAL0));
286 goto jleave;
289 ec = 0;
291 switch (oldp) {
292 case PROTO_FILE:
293 if (link(oldn, newn) == -1) {
294 switch (n_err_no) {
295 case n_ERR_ACCES:
296 case n_ERR_EXIST:
297 case n_ERR_NAMETOOLONG:
298 case n_ERR_NOSPC:
299 case n_ERR_XDEV:
300 n_perr(newn, 0);
301 break;
302 default:
303 n_perr(oldn, 0);
304 break;
306 ec |= 1;
307 } else if (unlink(oldn) == -1) {
308 n_perr(oldn, 0);
309 ec |= 1;
311 break;
312 case PROTO_MAILDIR:
313 #ifdef HAVE_MAILDIR
314 if(rename(oldn, newn) == -1){
315 n_perr(oldn, 0);
316 ec |= 1;
318 #else
319 n_err(_("No Maildir directory support compiled in\n"));
320 ec |= 1;
321 #endif
322 break;
323 case PROTO_POP3:
324 n_err(_("Cannot rename POP3 mailboxes\n"));
325 ec |= 1;
326 break;
327 case PROTO_IMAP:
328 #ifdef HAVE_IMAP
329 if(imap_rename(oldn, newn) != OKAY)
330 ec |= 1;
331 #else
332 n_err(_("No IMAP support compiled in\n"));
333 ec |= 1;
334 #endif
335 break;
336 case PROTO_UNKNOWN:
337 default:
338 n_err(_("Unknown protocol in %s and %s; not renamed\n"),
339 n_shexp_quote_cp(oldn, FAL0), n_shexp_quote_cp(newn, FAL0));
340 ec |= 1;
341 break;
343 jleave:
344 NYD_LEAVE;
345 return ec;
348 FL int
349 c_folders(void *v){ /* TODO fexpand*/
350 enum fexp_mode const fexp = FEXP_NSHELL
351 #ifndef HAVE_IMAP
352 | FEXP_LOCAL
353 #endif
356 char const *cp;
357 char **argv;
358 int rv;
359 NYD_ENTER;
361 rv = 1;
363 if(*(argv = v) != NULL){
364 if((cp = fexpand(*argv, fexp)) == NULL)
365 goto jleave;
366 }else
367 cp = n_folder_query();
369 #ifdef HAVE_IMAP
370 if(which_protocol(cp, FAL0, FAL0, NULL) == PROTO_IMAP)
371 rv = imap_folders(cp, *argv == NULL);
372 else
373 #endif
374 rv = n_child_run(ok_vlook(LISTER), 0, n_CHILD_FD_PASS, n_CHILD_FD_PASS,
375 cp, NULL, NULL, NULL, NULL);
376 jleave:
377 NYD_LEAVE;
378 return rv;
381 /* s-it-mode */