Tweak previous, it added a bad memory access
[s-mailx.git] / cmd-folder.c
blobbe1bcbbc0e29db1eacbe1a585bfa6ad1453954da
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 newfileinfo();
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;
85 if (n_pstate & n_PS_SETFILE_OPENED)
86 announce(ok_blook(bsdcompat) || ok_blook(bsdannounce));
87 i = 0;
88 jleave:
89 NYD2_LEAVE;
90 return i;
93 FL int
94 c_file(void *v)
96 int rv;
97 NYD_ENTER;
99 rv = _c_file(v, FEDIT_NONE);
100 NYD_LEAVE;
101 return rv;
104 FL int
105 c_File(void *v)
107 int rv;
108 NYD_ENTER;
110 rv = _c_file(v, FEDIT_RDONLY);
111 NYD_LEAVE;
112 return rv;
115 FL int
116 c_newmail(void *v)
118 int val = 1, mdot;
119 NYD_ENTER;
120 n_UNUSED(v);
122 if (n_pstate & n_PS_HOOK_MASK)
123 n_err(_("Cannot call `newmail' from within a hook\n"));
124 else if ((val = setfile(mailname,
125 FEDIT_NEWMAIL | ((mb.mb_perm & MB_DELE) ? 0 : FEDIT_RDONLY))
126 ) == 0) {
127 mdot = getmdot(1);
128 setdot(message + mdot - 1);
130 NYD_LEAVE;
131 return val;
134 FL int
135 c_noop(void *v)
137 int rv = 0;
138 NYD_ENTER;
139 n_UNUSED(v);
141 switch (mb.mb_type) {
142 case MB_POP3:
143 #ifdef HAVE_POP3
144 pop3_noop();
145 #else
146 rv = c_cmdnotsupp(NULL);
147 #endif
148 break;
149 default:
150 break;
152 NYD_LEAVE;
153 return rv;
156 FL int
157 c_remove(void *v)
159 char const *fmt;
160 size_t fmt_len;
161 char **args, *name, *ename;
162 int ec;
163 NYD_ENTER;
165 if (*(args = v) == NULL) {
166 n_err(_("Synopsis: remove: <mailbox>...\n"));
167 ec = 1;
168 goto jleave;
171 ec = 0;
173 fmt = _("Remove %s");
174 fmt_len = strlen(fmt);
175 do {
176 if ((name = fexpand(*args, FEXP_FULL)) == NULL)
177 continue;
178 ename = n_shexp_quote_cp(name, FAL0);
180 if (!strcmp(name, mailname)) {
181 n_err(_("Cannot remove current mailbox %s\n"), ename);
182 ec |= 1;
183 continue;
186 size_t vl = strlen(ename) + fmt_len +1;
187 char *vb = salloc(vl);
188 bool_t asw;
189 snprintf(vb, vl, fmt, ename);
190 asw = getapproval(vb, TRU1);
191 if (!asw)
192 continue;
195 switch (which_protocol(name)) {
196 case PROTO_FILE:
197 if (unlink(name) == -1) { /* TODO do not handle .zst .xz .gz.. */
198 int se = n_err_no;
200 if (se == n_ERR_ISDIR) {
201 struct stat sb;
203 if (!stat(name, &sb) && S_ISDIR(sb.st_mode)) {
204 if (!rmdir(name))
205 break;
206 se = n_err_no;
209 n_perr(name, se);
210 ec |= 1;
212 break;
213 case PROTO_POP3:
214 n_err(_("Cannot remove POP3 mailbox %s\n"), ename);
215 ec |= 1;
216 break;
217 case PROTO_MAILDIR:
218 if (maildir_remove(name) != OKAY)
219 ec |= 1;
220 break;
221 case PROTO_UNKNOWN:
222 n_err(_("Not removed: unknown protocol: %s\n"), ename);
223 ec |= 1;
224 break;
226 } while (*++args != NULL);
227 jleave:
228 NYD_LEAVE;
229 return ec;
232 FL int
233 c_rename(void *v)
235 char **args = v, *old, *new;
236 enum protocol oldp, newp;
237 int ec;
238 NYD_ENTER;
240 ec = 1;
242 if (args[0] == NULL || args[1] == NULL || args[2] != NULL) {
243 n_err(_("Synopsis: rename: <old> <new>\n"));
244 goto jleave;
247 if ((old = fexpand(args[0], FEXP_FULL)) == NULL)
248 goto jleave;
249 oldp = which_protocol(old);
250 if ((new = fexpand(args[1], FEXP_FULL)) == NULL)
251 goto jleave;
252 newp = which_protocol(new);
254 if (!strcmp(old, mailname) || !strcmp(new, mailname)) {
255 n_err(_("Cannot rename current mailbox %s\n"),
256 n_shexp_quote_cp(old, FAL0));
257 goto jleave;
260 ec = 0;
262 if (newp == PROTO_POP3)
263 goto jnopop3;
264 switch (oldp) {
265 case PROTO_FILE:
266 if (link(old, new) == -1) {
267 switch (n_err_no) {
268 case n_ERR_ACCES:
269 case n_ERR_EXIST:
270 case n_ERR_NAMETOOLONG:
271 case n_ERR_NOENT:
272 case n_ERR_NOSPC:
273 case n_ERR_XDEV:
274 n_perr(new, 0);
275 break;
276 default:
277 n_perr(old, 0);
278 break;
280 ec |= 1;
281 } else if (unlink(old) == -1) {
282 n_perr(old, 0);
283 ec |= 1;
285 break;
286 case PROTO_MAILDIR:
287 if (rename(old, new) == -1) {
288 n_perr(old, 0);
289 ec |= 1;
291 break;
292 case PROTO_POP3:
293 jnopop3:
294 n_err(_("Cannot rename POP3 mailboxes\n"));
295 ec |= 1;
296 break;
297 case PROTO_UNKNOWN:
298 default:
299 n_err(_("Unknown protocol in %s and %s; not renamed\n"),
300 n_shexp_quote_cp(old, FAL0), n_shexp_quote_cp(new, FAL0));
301 ec |= 1;
302 break;
304 jleave:
305 NYD_LEAVE;
306 return ec;
309 FL int
310 c_folders(void *v)
312 char const *cp;
313 char **argv;
314 int rv;
315 NYD_ENTER;
317 rv = 1;
319 if(*(argv = v) != NULL){
320 if((cp = fexpand(*argv, FEXP_NSHELL | FEXP_LOCAL)) == NULL) /* XXX NSH? */
321 goto jleave;
322 }else
323 cp = folder_query();
325 rv = n_child_run(ok_vlook(LISTER), 0, n_CHILD_FD_PASS, n_CHILD_FD_PASS,
326 cp, NULL, NULL, NULL);
327 if(rv < 0)
328 rv = 1; /* XXX */
329 jleave:
330 NYD_LEAVE;
331 return rv;
334 /* s-it-mode */