NeoMutt  2025-12-11-694-ga89709
Teaching an old dog new tricks
DOXYGEN
Loading...
Searching...
No Matches
mailboxes.c
Go to the documentation of this file.
1
22
28
29#include "config.h"
30#include <stdbool.h>
31#include <stdio.h>
32#include "mutt/lib.h"
33#include "config/lib.h"
34#include "core/lib.h"
35#include "mailboxes.h"
36#include "parse/lib.h"
37#include "muttlib.h"
38#include "mx.h"
39#ifdef USE_INOTIFY
40#include "monitor.h"
41#endif
42
53static enum CommandResult mailbox_add(const char *folder, const char *mailbox,
54 const char *label, enum TriBool poll,
55 enum TriBool notify, struct Buffer *err)
56{
57 mutt_debug(LL_DEBUG1, "Adding mailbox: '%s' label '%s', poll %s, notify %s\n",
58 mailbox, label ? label : "[NONE]",
59 (poll == TB_UNSET) ? "[UNSPECIFIED]" :
60 (poll == TB_TRUE) ? "true" :
61 "false",
62 (notify == TB_UNSET) ? "[UNSPECIFIED]" :
63 (notify == TB_TRUE) ? "true" :
64 "false");
65 struct Mailbox *m = mailbox_new();
66
67 buf_strcpy(&m->pathbuf, mailbox);
68 /* int rc = */ mx_path_canon2(m, folder);
69
70 if (m->type <= MUTT_UNKNOWN)
71 {
72 buf_printf(err, "Unknown Mailbox: %s", m->realpath);
73 mailbox_free(&m);
74 return MUTT_CMD_ERROR;
75 }
76
77 bool new_account = false;
78 struct Account *a = mx_ac_find(m);
79 if (!a)
80 {
81 a = account_new(NULL, NeoMutt->sub);
82 a->type = m->type;
83 new_account = true;
84 }
85
86 if (!new_account)
87 {
88 struct Mailbox *m_old = mx_mbox_find(a, m->realpath);
89 if (m_old)
90 {
91 if (!m_old->visible)
92 {
93 m_old->visible = true;
94 m_old->gen = mailbox_gen();
95 }
96
97 if (label)
98 mutt_str_replace(&m_old->name, label);
99
100 if (notify != TB_UNSET)
101 m_old->notify_user = notify;
102
103 if (poll != TB_UNSET)
104 m_old->poll_new_mail = poll;
105
106 struct EventMailbox ev_m = { m_old };
108
109 mailbox_free(&m);
110 return MUTT_CMD_SUCCESS;
111 }
112 }
113
114 if (label)
115 m->name = mutt_str_dup(label);
116
117 if (notify != TB_UNSET)
118 m->notify_user = notify;
119
120 if (poll != TB_UNSET)
121 m->poll_new_mail = poll;
122
123 if (!mx_ac_add(a, m))
124 {
125 mailbox_free(&m);
126 if (new_account)
127 {
128 cs_subset_free(&a->sub);
129 FREE(&a->name);
130 notify_free(&a->notify);
131 FREE(&a);
132 }
133 return MUTT_CMD_SUCCESS;
134 }
135
136 if (new_account)
137 {
139 }
140
141 // this is finally a visible mailbox in the sidebar and mailboxes list
142 m->visible = true;
143
144#ifdef USE_INOTIFY
146#endif
147
148 return MUTT_CMD_SUCCESS;
149}
150
157bool mailbox_add_simple(const char *mailbox, struct Buffer *err)
158{
159 enum CommandResult rc = mailbox_add("", mailbox, NULL, TB_UNSET, TB_UNSET, err);
160
161 return (rc == MUTT_CMD_SUCCESS);
162}
163
169{
170 if (!pm)
171 return;
172
173 FREE(&pm->path);
174 FREE(&pm->label);
175}
176
181void parse_mailbox_array_free(struct ParseMailboxArray *pma)
182{
183 if (!pma)
184 return;
185
186 struct ParseMailbox *pm = NULL;
187 ARRAY_FOREACH(pm, pma)
188 {
190 }
191 ARRAY_FREE(pma);
192}
193
206bool parse_mailboxes_args(const struct Command *cmd, struct Buffer *line,
207 struct Buffer *err, struct ParseMailboxArray *args)
208{
209 if (!cmd || !line || !err || !args)
210 return false;
211
212 if (!MoreArgs(line))
213 {
214 buf_printf(err, _("%s: too few arguments"), cmd->name);
215 return false;
216 }
217
218 // Parsed (label, mailbox, flags) tuples will be appended to the @args array
219 struct Buffer *label = buf_pool_get();
220 struct Buffer *mailbox = buf_pool_get();
221 struct Buffer *token = buf_pool_get();
222 bool rc = false;
223
224 /* Parse each mailbox specification: consume optional flags (-label, -notify,
225 * -poll and their negations) then the mailbox path itself */
226 while (MoreArgs(line))
227 {
228 bool label_set = false;
229 enum TriBool notify = TB_UNSET;
230 enum TriBool poll = TB_UNSET;
231
232 do
233 {
234 // Start by handling the options
236
237 if (mutt_str_equal(buf_string(token), "-label"))
238 {
239 if (!MoreArgs(line))
240 {
241 buf_printf(err, _("%s: too few arguments"), "mailboxes -label");
242 goto done;
243 }
244
246 label_set = true;
247 }
248 else if (mutt_str_equal(buf_string(token), "-nolabel"))
249 {
250 buf_reset(label);
251 label_set = true;
252 }
253 else if (mutt_str_equal(buf_string(token), "-notify"))
254 {
255 notify = TB_TRUE;
256 }
257 else if (mutt_str_equal(buf_string(token), "-nonotify"))
258 {
259 notify = TB_FALSE;
260 }
261 else if (mutt_str_equal(buf_string(token), "-poll"))
262 {
263 poll = TB_TRUE;
264 }
265 else if (mutt_str_equal(buf_string(token), "-nopoll"))
266 {
267 poll = TB_FALSE;
268 }
269 else if ((cmd->id == CMD_NAMED_MAILBOXES) && !label_set)
270 {
271 if (!MoreArgs(line))
272 {
273 buf_printf(err, _("%s: too few arguments"), cmd->name);
274 goto done;
275 }
276
277 buf_copy(label, token);
278 label_set = true;
279 }
280 else
281 {
282 buf_copy(mailbox, token);
283 break;
284 }
285 } while (MoreArgs(line));
286
287 if (buf_is_empty(mailbox))
288 {
289 buf_printf(err, _("%s: too few arguments"), cmd->name);
290 goto done;
291 }
292
293 /* Store the parsed mailbox entry with its associated options */
294 struct ParseMailbox pm = {
295 .path = buf_strdup(mailbox),
296 .label = label_set ? buf_strdup(label) : NULL,
297 .poll = poll,
298 .notify = notify,
299 };
300 ARRAY_ADD(args, pm);
301
303 buf_reset(mailbox);
304 }
305
306 rc = true;
307
308done:
310 buf_pool_release(&mailbox);
311 buf_pool_release(&token);
312 return rc;
313}
314
323 struct ParseMailboxArray *args, struct Buffer *err)
324{
325 if (!cmd || !args || !err)
326 return MUTT_CMD_ERROR;
327
328 const char *const c_folder = cs_subset_string(NeoMutt->sub, "folder");
330
331 struct ParseMailbox *pm = NULL;
332 ARRAY_FOREACH(pm, args)
333 {
334 rc = mailbox_add(c_folder, pm->path, pm->label, pm->poll, pm->notify, err);
335 if (rc != MUTT_CMD_SUCCESS)
336 return rc;
337 }
338
339 return rc;
340}
341
349enum CommandResult parse_mailboxes(const struct Command *cmd, struct Buffer *line,
350 const struct ParseContext *pc, struct ParseError *pe)
351{
352 struct Buffer *err = pe->message;
353
354 struct ParseMailboxArray args = ARRAY_HEAD_INITIALIZER;
356
357 if (!parse_mailboxes_args(cmd, line, err, &args))
358 goto done;
359
360 rc = parse_mailboxes_exec(cmd, &args, err);
361
362done:
364 return rc;
365}
366
371static void do_unmailboxes(struct Mailbox *m)
372{
373#ifdef USE_INOTIFY
374 if (m->poll_new_mail)
376#endif
377 m->visible = false;
378 m->gen = -1;
379 if (m->opened)
380 {
381 struct EventMailbox ev_m = { NULL };
382 mutt_debug(LL_NOTIFY, "NT_MAILBOX_CHANGE: NULL\n");
384 }
385 else
386 {
388 mailbox_free(&m);
389 }
390}
391
398{
399 struct Buffer *buf = buf_pool_get();
400 buf_strcpy(buf, mailbox);
401 expand_path(buf, false);
402
403 struct Account **ap = NULL;
405 {
406 struct Mailbox *m = mx_mbox_find(*ap, buf_string(buf));
407 if (m)
408 {
410 buf_pool_release(&buf);
411 return true;
412 }
413 }
414
415 buf_pool_release(&buf);
416 return false;
417}
418
422static void do_unmailboxes_star(void)
423{
424 struct MailboxArray ma = neomutt_mailboxes_get(NeoMutt, MUTT_MAILBOX_ANY);
425
426 struct Mailbox **mp = NULL;
427 ARRAY_FOREACH(mp, &ma)
428 {
429 do_unmailboxes(*mp);
430 }
431 ARRAY_FREE(&ma); // Clean up the ARRAY, but not the Mailboxes
432}
433
440enum CommandResult parse_unmailboxes(const struct Command *cmd, struct Buffer *line,
441 const struct ParseContext *pc, struct ParseError *pe)
442{
443 struct Buffer *err = pe->message;
444
445 if (!MoreArgs(line))
446 {
447 buf_printf(err, _("%s: too few arguments"), cmd->name);
448 return MUTT_CMD_WARNING;
449 }
450
451 struct Buffer *token = buf_pool_get();
452
453 while (MoreArgs(line))
454 {
456
457 if (mutt_str_equal(buf_string(token), "*"))
458 {
460 goto done;
461 }
462
463 expand_path(token, false);
464
465 struct Account **ap = NULL;
467 {
468 struct Mailbox *m = mx_mbox_find(*ap, buf_string(token));
469 if (m)
470 {
472 break;
473 }
474 }
475 }
476
477done:
478 buf_pool_release(&token);
479 return MUTT_CMD_SUCCESS;
480}
#define ARRAY_ADD(head, elem)
Add an element at the end of the array.
Definition array.h:157
#define ARRAY_FOREACH(elem, head)
Iterate over all elements of the array.
Definition array.h:223
#define ARRAY_FREE(head)
Release all memory.
Definition array.h:209
#define ARRAY_HEAD_INITIALIZER
Static initializer for arrays.
Definition array.h:58
int buf_printf(struct Buffer *buf, const char *fmt,...)
Format a string overwriting a Buffer.
Definition buffer.c:161
void buf_reset(struct Buffer *buf)
Reset an existing Buffer.
Definition buffer.c:76
bool buf_is_empty(const struct Buffer *buf)
Is the Buffer empty?
Definition buffer.c:291
size_t buf_strcpy(struct Buffer *buf, const char *s)
Copy a string into a Buffer.
Definition buffer.c:395
size_t buf_copy(struct Buffer *dst, const struct Buffer *src)
Copy a Buffer's contents to another Buffer.
Definition buffer.c:601
char * buf_strdup(const struct Buffer *buf)
Copy a Buffer's string.
Definition buffer.c:571
static const char * buf_string(const struct Buffer *buf)
Convert a buffer to a const char * "string".
Definition buffer.h:96
@ CMD_NAMED_MAILBOXES
:named-mailboxes
Definition command.h:98
CommandResult
Error codes for command_t parse functions.
Definition command.h:37
@ MUTT_CMD_SUCCESS
Success: Command worked.
Definition command.h:40
@ MUTT_CMD_ERROR
Error: Can't help the user.
Definition command.h:38
@ MUTT_CMD_WARNING
Warning: Help given to the user.
Definition command.h:39
const char * cs_subset_string(const struct ConfigSubset *sub, const char *name)
Get a string config item by name.
Definition helpers.c:291
Convenience wrapper for the config headers.
void account_mailbox_remove(struct Account *a, struct Mailbox *m)
Remove a Mailbox from an Account.
Definition account.c:94
struct Account * account_new(const char *name, struct ConfigSubset *sub)
Create a new Account.
Definition account.c:44
Convenience wrapper for the core headers.
int mailbox_gen(void)
Get the next generation number.
Definition mailbox.c:59
struct Mailbox * mailbox_new(void)
Create a new Mailbox.
Definition mailbox.c:69
void mailbox_free(struct Mailbox **ptr)
Free a Mailbox.
Definition mailbox.c:90
@ NT_MAILBOX_CHANGE
Mailbox has been changed.
Definition mailbox.h:175
@ MUTT_MAILBOX_ANY
Match any Mailbox type.
Definition mailbox.h:41
@ MUTT_UNKNOWN
Mailbox wasn't recognised.
Definition mailbox.h:43
int parse_extract_token(struct Buffer *dest, struct Buffer *line, TokenFlags flags)
Extract one token from a string.
Definition extract.c:49
#define MoreArgs(buf)
Definition extract.h:31
#define TOKEN_NO_FLAGS
No flags are set.
Definition extract.h:45
enum CommandResult parse_unmailboxes(const struct Command *cmd, struct Buffer *line, const struct ParseContext *pc, struct ParseError *pe)
Parse the 'unmailboxes' command - Implements Command::parse() -.
Definition mailboxes.c:440
enum CommandResult parse_mailboxes(const struct Command *cmd, struct Buffer *line, const struct ParseContext *pc, struct ParseError *pe)
Parse the 'mailboxes' command - Implements Command::parse() -.
Definition mailboxes.c:349
#define mutt_debug(LEVEL,...)
Definition logging2.h:91
@ LL_DEBUG1
Log at debug level 1.
Definition logging2.h:45
@ LL_NOTIFY
Log of notifications.
Definition logging2.h:50
static enum CommandResult mailbox_add(const char *folder, const char *mailbox, const char *label, enum TriBool poll, enum TriBool notify, struct Buffer *err)
Add a new Mailbox.
Definition mailboxes.c:53
bool mailbox_remove_simple(const char *mailbox)
Remove a Mailbox.
Definition mailboxes.c:397
void parse_mailbox_free(struct ParseMailbox *pm)
Free a ParseMailbox structure.
Definition mailboxes.c:168
void parse_mailbox_array_free(struct ParseMailboxArray *pma)
Free a ParseMailboxArray.
Definition mailboxes.c:181
bool parse_mailboxes_args(const struct Command *cmd, struct Buffer *line, struct Buffer *err, struct ParseMailboxArray *args)
Parse the 'mailboxes' and 'named-mailboxes' commands.
Definition mailboxes.c:206
static void do_unmailboxes_star(void)
Remove all Mailboxes from the Sidebar/notifications.
Definition mailboxes.c:422
enum CommandResult parse_mailboxes_exec(const struct Command *cmd, struct ParseMailboxArray *args, struct Buffer *err)
Execute the 'mailboxes' or 'named-mailboxes' command.
Definition mailboxes.c:322
bool mailbox_add_simple(const char *mailbox, struct Buffer *err)
Add a new Mailbox.
Definition mailboxes.c:157
static void do_unmailboxes(struct Mailbox *m)
Remove a Mailbox from the Sidebar/notifications.
Definition mailboxes.c:371
Parse Mailboxes Commands.
TriBool
Tri-state boolean.
Definition mailboxes.h:37
@ TB_FALSE
Value is false.
Definition mailboxes.h:39
@ TB_TRUE
Value is true.
Definition mailboxes.h:40
@ TB_UNSET
Value hasn't been set.
Definition mailboxes.h:38
#define FREE(x)
Free memory and set the pointer to NULL.
Definition memory.h:68
int mutt_monitor_add(struct Mailbox *m)
Add a watch for a mailbox.
Definition monitor.c:484
int mutt_monitor_remove(struct Mailbox *m)
Remove a watch for a mailbox.
Definition monitor.c:528
Monitor files for changes.
Convenience wrapper for the library headers.
#define _(a)
Definition message.h:28
bool notify_send(struct Notify *notify, enum NotifyType event_type, int event_subtype, void *event_data)
Send out a notification message.
Definition notify.c:173
void notify_free(struct Notify **ptr)
Free a notification handler.
Definition notify.c:75
char * mutt_str_dup(const char *str)
Copy a string, safely.
Definition string.c:257
bool mutt_str_equal(const char *a, const char *b)
Compare two strings.
Definition string.c:665
char * mutt_str_replace(char **p, const char *s)
Replace one string with another.
Definition string.c:284
void expand_path(struct Buffer *buf, bool regex)
Create the canonical path.
Definition muttlib.c:122
Some miscellaneous functions.
struct Mailbox * mx_mbox_find(struct Account *a, const char *path)
Find a Mailbox on an Account.
Definition mx.c:1546
bool mx_ac_add(struct Account *a, struct Mailbox *m)
Add a Mailbox to an Account - Wrapper for MxOps::ac_add()
Definition mx.c:1737
struct Account * mx_ac_find(struct Mailbox *m)
Find the Account owning a Mailbox.
Definition mx.c:1521
int mx_path_canon2(struct Mailbox *m, const char *folder)
Canonicalise the path to realpath.
Definition mx.c:1473
API for mailboxes.
struct MailboxArray neomutt_mailboxes_get(struct NeoMutt *n, enum MailboxType type)
Get an Array of matching Mailboxes.
Definition neomutt.c:526
bool neomutt_account_add(struct NeoMutt *n, struct Account *a)
Add an Account to the global list.
Definition neomutt.c:456
@ NT_MAILBOX
Mailbox has changed, NotifyMailbox, EventMailbox.
Definition notify_type.h:49
Text parsing functions.
struct Buffer * buf_pool_get(void)
Get a Buffer from the pool.
Definition pool.c:91
void buf_pool_release(struct Buffer **ptr)
Return a Buffer to the pool.
Definition pool.c:111
A group of associated Mailboxes.
Definition account.h:36
enum MailboxType type
Type of Mailboxes this Account contains.
Definition account.h:37
char * name
Name of Account.
Definition account.h:38
struct Notify * notify
Notifications: NotifyAccount, EventAccount.
Definition account.h:41
struct ConfigSubset * sub
Inherited config items.
Definition account.h:39
String manipulation buffer.
Definition buffer.h:36
const char * name
Name of the Command.
Definition command.h:159
enum CommandId id
ID of the Command.
Definition command.h:160
An Event that happened to a Mailbox.
Definition mailbox.h:189
struct Mailbox * mailbox
The Mailbox this Event relates to.
Definition mailbox.h:190
A mailbox.
Definition mailbox.h:78
char * realpath
Used for duplicate detection, context comparison, and the sidebar.
Definition mailbox.h:80
enum MailboxType type
Mailbox type.
Definition mailbox.h:101
bool poll_new_mail
Check for new mail.
Definition mailbox.h:114
char * name
A short name for the Mailbox.
Definition mailbox.h:81
struct Notify * notify
Notifications: NotifyMailbox, EventMailbox.
Definition mailbox.h:144
bool notify_user
Notify the user of new mail.
Definition mailbox.h:112
struct Buffer pathbuf
Path of the Mailbox.
Definition mailbox.h:79
struct Account * account
Account that owns this Mailbox.
Definition mailbox.h:126
bool visible
True if a result of "mailboxes".
Definition mailbox.h:129
int opened
Number of times mailbox is opened.
Definition mailbox.h:127
int gen
Generation number, for sorting.
Definition mailbox.h:146
Container for Accounts, Notifications.
Definition neomutt.h:41
struct AccountArray accounts
All Accounts.
Definition neomutt.h:50
struct Notify * notify
Notifications handler.
Definition neomutt.h:45
struct ConfigSubset * sub
Inherited config items.
Definition neomutt.h:49
Context for config parsing (history/backtrace)
Definition pcontext.h:34
Detailed error information from config parsing.
Definition perror.h:34
struct Buffer * message
Error message.
Definition perror.h:35
Parsed data for a single mailbox.
Definition mailboxes.h:47
enum TriBool notify
Enable mailbox notification?
Definition mailboxes.h:51
char * label
Descriptive label (strdup'd, may be NULL)
Definition mailboxes.h:49
enum TriBool poll
Enable mailbox polling?
Definition mailboxes.h:50
char * path
Mailbox path.
Definition mailboxes.h:48
void cs_subset_free(struct ConfigSubset **ptr)
Free a Config Subset.
Definition subset.c:112