a_go_evaluate(): fix un/signed comparison
[s-mailx.git] / cmd-folder.c
blob71b2ee1426e42bdb76d9de53a2e1514eb167c730
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 = n_autorec_alloc(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 #ifdef HAVE_MAILDIR
230 if(maildir_remove(name) != OKAY)
231 ec |= 1;
232 #else
233 n_err(_("No Maildir directory support compiled in\n"));
234 ec |= 1;
235 #endif
236 break;
237 case PROTO_IMAP:
238 #ifdef HAVE_IMAP
239 if(imap_remove(name) != OKAY)
240 ec |= 1;
241 #else
242 n_err(_("No IMAP support compiled in\n"));
243 ec |= 1;
244 #endif
245 break;
246 case PROTO_UNKNOWN:
247 default:
248 n_err(_("Not removed: unknown protocol: %s\n"), ename);
249 ec |= 1;
250 break;
252 } while (*++args != NULL);
253 jleave:
254 NYD_LEAVE;
255 return ec;
258 FL int
259 c_rename(void *v)
261 char **args = v, *oldn, *newn;
262 enum protocol oldp;
263 int ec;
264 NYD_ENTER;
266 ec = 1;
268 if (args[0] == NULL || args[1] == NULL || args[2] != NULL) {
269 n_err(_("Synopsis: rename: <old> <new>\n"));
270 goto jleave;
273 if ((oldn = fexpand(args[0], FEXP_FULL)) == NULL)
274 goto jleave;
275 oldp = which_protocol(oldn, TRU1, FAL0, NULL);
276 if ((newn = fexpand(args[1], FEXP_FULL)) == NULL)
277 goto jleave;
278 if(oldp != which_protocol(newn, TRU1, FAL0, NULL)) {
279 n_err(_("Can only rename folders of same type\n"));
280 goto jleave;
282 if (!strcmp(oldn, mailname) || !strcmp(newn, mailname)) {
283 n_err(_("Cannot rename current mailbox %s\n"),
284 n_shexp_quote_cp(oldn, FAL0));
285 goto jleave;
288 ec = 0;
290 switch (oldp) {
291 case PROTO_FILE:
292 if (link(oldn, newn) == -1) {
293 switch (n_err_no) {
294 case n_ERR_ACCES:
295 case n_ERR_EXIST:
296 case n_ERR_NAMETOOLONG:
297 case n_ERR_NOSPC:
298 case n_ERR_XDEV:
299 n_perr(newn, 0);
300 break;
301 default:
302 n_perr(oldn, 0);
303 break;
305 ec |= 1;
306 } else if (unlink(oldn) == -1) {
307 n_perr(oldn, 0);
308 ec |= 1;
310 break;
311 case PROTO_MAILDIR:
312 #ifdef HAVE_MAILDIR
313 if(rename(oldn, newn) == -1){
314 n_perr(oldn, 0);
315 ec |= 1;
317 #else
318 n_err(_("No Maildir directory support compiled in\n"));
319 ec |= 1;
320 #endif
321 break;
322 case PROTO_POP3:
323 n_err(_("Cannot rename POP3 mailboxes\n"));
324 ec |= 1;
325 break;
326 case PROTO_IMAP:
327 #ifdef HAVE_IMAP
328 if(imap_rename(oldn, newn) != OKAY)
329 ec |= 1;
330 #else
331 n_err(_("No IMAP support compiled in\n"));
332 ec |= 1;
333 #endif
334 break;
335 case PROTO_UNKNOWN:
336 default:
337 n_err(_("Unknown protocol in %s and %s; not renamed\n"),
338 n_shexp_quote_cp(oldn, FAL0), n_shexp_quote_cp(newn, FAL0));
339 ec |= 1;
340 break;
342 jleave:
343 NYD_LEAVE;
344 return ec;
347 FL int
348 c_folders(void *v){ /* TODO fexpand*/
349 enum fexp_mode const fexp = FEXP_NSHELL
350 #ifndef HAVE_IMAP
351 | FEXP_LOCAL
352 #endif
355 char const *cp;
356 char **argv;
357 int rv;
358 NYD_ENTER;
360 rv = 1;
362 if(*(argv = v) != NULL){
363 if((cp = fexpand(*argv, fexp)) == NULL)
364 goto jleave;
365 }else
366 cp = n_folder_query();
368 #ifdef HAVE_IMAP
369 if(which_protocol(cp, FAL0, FAL0, NULL) == PROTO_IMAP)
370 rv = imap_folders(cp, *argv == NULL);
371 else
372 #endif
373 rv = n_child_run(ok_vlook(LISTER), 0, n_CHILD_FD_PASS, n_CHILD_FD_PASS,
374 cp, NULL, NULL, NULL, NULL);
375 jleave:
376 NYD_LEAVE;
377 return rv;
380 /* s-it-mode */