a_tty_kht(): take advantage of new n_SHEXP_STATE_WS_TRAIL
[s-mailx.git] / cmd-folder.c
blobc20ba048b1cc96c01946122755cf24ee4e71be96
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 - 2017 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 else if ((val = setfile(mailname,
126 FEDIT_NEWMAIL | ((mb.mb_perm & MB_DELE) ? 0 : FEDIT_RDONLY))
127 ) == 0) {
128 mdot = getmdot(1);
129 setdot(message + mdot - 1);
131 NYD_LEAVE;
132 return val;
135 FL int
136 c_noop(void *v)
138 int rv = 0;
139 NYD_ENTER;
140 n_UNUSED(v);
142 switch (mb.mb_type) {
143 #ifdef HAVE_POP3
144 case MB_POP3:
145 pop3_noop();
146 break;
147 #endif
148 default:
149 break;
151 NYD_LEAVE;
152 return rv;
155 FL int
156 c_remove(void *v)
158 char const *fmt;
159 size_t fmt_len;
160 char **args, *name, *ename;
161 int ec;
162 NYD_ENTER;
164 if (*(args = v) == NULL) {
165 n_err(_("Synopsis: remove: <mailbox>...\n"));
166 ec = 1;
167 goto jleave;
170 ec = 0;
172 fmt = _("Remove %s");
173 fmt_len = strlen(fmt);
174 do {
175 if ((name = fexpand(*args, FEXP_FULL)) == NULL)
176 continue;
177 ename = n_shexp_quote_cp(name, FAL0);
179 if (!strcmp(name, mailname)) {
180 n_err(_("Cannot remove current mailbox %s\n"), ename);
181 ec |= 1;
182 continue;
184 /* C99 */{
185 bool_t asw;
186 char *vb;
187 size_t vl;
189 vl = strlen(ename) + fmt_len +1;
190 vb = salloc(vl);
191 snprintf(vb, vl, fmt, ename);
192 asw = getapproval(vb, TRU1);
193 if (!asw)
194 continue;
197 switch (which_protocol(name, TRU1, FAL0, NULL)) {
198 case PROTO_FILE:
199 if (unlink(name) == -1) {
200 int se = n_err_no;
202 if (se == n_ERR_ISDIR) {
203 struct stat sb;
205 if (!stat(name, &sb) && S_ISDIR(sb.st_mode)) {
206 if (!rmdir(name))
207 break;
208 se = n_err_no;
211 n_perr(name, se);
212 ec |= 1;
214 break;
215 case PROTO_POP3:
216 n_err(_("Cannot remove POP3 mailbox %s\n"), ename);
217 ec |= 1;
218 break;
219 case PROTO_MAILDIR:
220 if (maildir_remove(name) != OKAY)
221 ec |= 1;
222 break;
223 case PROTO_UNKNOWN:
224 default:
225 n_err(_("Not removed: unknown protocol: %s\n"), ename);
226 ec |= 1;
227 break;
229 } while (*++args != NULL);
230 jleave:
231 NYD_LEAVE;
232 return ec;
235 FL int
236 c_rename(void *v)
238 char **args = v, *old, *new;
239 enum protocol oldp;
240 int ec;
241 NYD_ENTER;
243 ec = 1;
245 if (args[0] == NULL || args[1] == NULL || args[2] != NULL) {
246 n_err(_("Synopsis: rename: <old> <new>\n"));
247 goto jleave;
250 if ((old = fexpand(args[0], FEXP_FULL)) == NULL)
251 goto jleave;
252 oldp = which_protocol(old, TRU1, FAL0, NULL);
253 if ((new = fexpand(args[1], FEXP_FULL)) == NULL)
254 goto jleave;
255 if(oldp != which_protocol(new, TRU1, FAL0, NULL)) {
256 n_err(_("Can only rename folders of same type\n"));
257 goto jleave;
259 if (!strcmp(old, mailname) || !strcmp(new, mailname)) {
260 n_err(_("Cannot rename current mailbox %s\n"),
261 n_shexp_quote_cp(old, FAL0));
262 goto jleave;
265 ec = 0;
267 if (oldp == PROTO_POP3)
268 goto jnopop3;
269 switch (oldp) {
270 case PROTO_FILE:
271 if (link(old, new) == -1) {
272 switch (n_err_no) {
273 case n_ERR_ACCES:
274 case n_ERR_EXIST:
275 case n_ERR_NAMETOOLONG:
276 case n_ERR_NOSPC:
277 case n_ERR_XDEV:
278 n_perr(new, 0);
279 break;
280 default:
281 n_perr(old, 0);
282 break;
284 ec |= 1;
285 } else if (unlink(old) == -1) {
286 n_perr(old, 0);
287 ec |= 1;
289 break;
290 case PROTO_MAILDIR:
291 if (rename(old, new) == -1) {
292 n_perr(old, 0);
293 ec |= 1;
295 break;
296 case PROTO_POP3:
297 jnopop3:
298 n_err(_("Cannot rename POP3 mailboxes\n"));
299 ec |= 1;
300 break;
301 case PROTO_UNKNOWN:
302 default:
303 n_err(_("Unknown protocol in %s and %s; not renamed\n"),
304 n_shexp_quote_cp(old, FAL0), n_shexp_quote_cp(new, FAL0));
305 ec |= 1;
306 break;
308 jleave:
309 NYD_LEAVE;
310 return ec;
313 FL int
314 c_folders(void *v)
316 char const *cp;
317 char **argv;
318 int rv;
319 NYD_ENTER;
321 rv = 1;
323 if(*(argv = v) != NULL){
324 if((cp = fexpand(*argv, FEXP_NSHELL | FEXP_LOCAL)) == NULL) /* XXX NSH? */
325 goto jleave;
326 }else
327 cp = n_folder_query();
329 rv = n_child_run(ok_vlook(LISTER), 0, n_CHILD_FD_PASS, n_CHILD_FD_PASS,
330 cp, NULL, NULL, NULL, NULL);
331 jleave:
332 NYD_LEAVE;
333 return rv;
336 /* s-it-mode */