NeoMutt  2025-09-05-55-g97fc89
Teaching an old dog new tricks
DOXYGEN
Loading...
Searching...
No Matches
alias.c
Go to the documentation of this file.
1
26
32
33#include "config.h"
34#include <pwd.h>
35#include <stdbool.h>
36#include <stdio.h>
37#include <stdlib.h>
38#include <string.h>
39#include <wchar.h>
40#include <wctype.h>
41#include "mutt/lib.h"
42#include "address/lib.h"
43#include "config/lib.h"
44#include "email/lib.h"
45#include "core/lib.h"
46#include "gui/lib.h"
47#include "mutt.h"
48#include "alias.h"
49#include "lib.h"
50#include "browser/lib.h"
51#include "editor/lib.h"
52#include "history/lib.h"
53#include "question/lib.h"
54#include "send/lib.h"
55#include "alternates.h"
56#include "globals.h"
57#include "maillist.h"
58#include "muttlib.h"
59#include "reverse.h"
60
62
87static void write_safe_address(FILE *fp, const char *s)
88{
89 while (*s)
90 {
91 if ((*s == '\\') || (*s == '`') || (*s == '\'') || (*s == '"') || (*s == '$'))
92 fputc('\\', fp);
93 fputc(*s, fp);
94 s++;
95 }
96}
97
105static void expand_aliases_r(struct AddressList *al, struct ListHead *expn)
106{
107 struct Address *a = TAILQ_FIRST(al);
108 while (a)
109 {
110 if (!a->group && !a->personal && a->mailbox && !buf_find_char(a->mailbox, '@'))
111 {
112 struct AddressList *alias = alias_lookup(buf_string(a->mailbox));
113 if (alias)
114 {
115 bool duplicate = false;
116 struct ListNode *np = NULL;
117 STAILQ_FOREACH(np, expn, entries)
118 {
119 if (mutt_str_equal(buf_string(a->mailbox), np->data)) /* alias already found */
120 {
121 mutt_debug(LL_DEBUG1, "loop in alias found for '%s'\n", buf_string(a->mailbox));
122 duplicate = true;
123 break;
124 }
125 }
126
127 if (duplicate)
128 {
129 // We've already seen this alias, so drop it
130 struct Address *next = TAILQ_NEXT(a, entries);
131 TAILQ_REMOVE(al, a, entries);
132 mutt_addr_free(&a);
133 a = next;
134 continue;
135 }
136
137 // Keep a list of aliases that we've already seen
139
140 /* The alias may expand to several addresses,
141 * some of which may themselves be aliases.
142 * Create a copy and recursively expand any aliases within. */
143 struct AddressList copy = TAILQ_HEAD_INITIALIZER(copy);
144 mutt_addrlist_copy(&copy, alias, false);
145 expand_aliases_r(&copy, expn);
146
147 /* Next, move the expanded addresses
148 * from the copy into the original list (before the alias) */
149 struct Address *a2 = NULL, *tmp = NULL;
150 TAILQ_FOREACH_SAFE(a2, &copy, entries, tmp)
151 {
152 TAILQ_INSERT_BEFORE(a, a2, entries);
153 }
154 a = TAILQ_PREV(a, AddressList, entries);
155 // Finally, remove the alias itself
156 struct Address *next = TAILQ_NEXT(a, entries);
157 TAILQ_REMOVE(al, next, entries);
158 mutt_addr_free(&next);
159 }
160 else
161 {
162 struct passwd *pw = getpwnam(buf_string(a->mailbox));
163 if (pw)
164 {
165 char namebuf[256] = { 0 };
166
167 mutt_gecos_name(namebuf, sizeof(namebuf), pw);
168 a->personal = buf_new(namebuf);
169 }
170 }
171 }
172 a = TAILQ_NEXT(a, entries);
173 }
174
175 const char *fqdn = NULL;
176 const bool c_use_domain = cs_subset_bool(NeoMutt->sub, "use_domain");
177 if (c_use_domain && (fqdn = mutt_fqdn(true, NeoMutt->sub)))
178 {
179 /* now qualify all local addresses */
180 mutt_addrlist_qualify(al, fqdn);
181 }
182}
183
191static void recode_buf(struct Buffer *buf)
192{
193 const char *const c_config_charset = cs_subset_string(NeoMutt->sub, "config_charset");
194 if (!c_config_charset || !cc_charset())
195 return;
196
197 char *s = buf_strdup(buf);
198 if (!s)
199 return;
200 if (mutt_ch_convert_string(&s, cc_charset(), c_config_charset, MUTT_ICONV_NO_FLAGS) == 0)
201 buf_strcpy(buf, s);
202 FREE(&s);
203}
204
215static int check_alias_name(const char *s, struct Buffer *dest)
216{
217 wchar_t wc = 0;
218 mbstate_t mbstate = { 0 };
219 size_t l;
220 int rc = 0;
221 bool dry = !dest; // Dry run
222
223 if (!dry)
224 buf_reset(dest);
225 for (; s && *s && (l = mbrtowc(&wc, s, MB_CUR_MAX, &mbstate)) != 0; s += l)
226 {
227 bool bad = (l == ICONV_ILLEGAL_SEQ) || (l == ICONV_BUF_TOO_SMALL); /* conversion error */
228 if (l == 1)
229 bad = bad || (!strchr("-_+=.", *s) && !iswalnum(wc));
230 else
231 bad = bad || !iswalnum(wc);
232 if (bad)
233 {
234 if (dry)
235 return -1;
236 if (l == ICONV_ILLEGAL_SEQ)
237 memset(&mbstate, 0, sizeof(mbstate_t));
238 buf_addch(dest, '_');
239 rc = -1;
240 }
241 else if (!dry)
242 {
243 buf_addstr_n(dest, s, l);
244 }
245 }
246
247 return rc;
248}
249
257static bool string_is_address(const char *str, const char *user, const char *domain)
258{
259 char buf[1024] = { 0 };
260
261 snprintf(buf, sizeof(buf), "%s@%s", NONULL(user), NONULL(domain));
262 if (mutt_istr_equal(str, buf))
263 return true;
264
265 return false;
266}
267
276struct AddressList *alias_lookup(const char *name)
277{
278 struct Alias *a = NULL;
279
280 TAILQ_FOREACH(a, &Aliases, entries)
281 {
282 if (mutt_istr_equal(name, a->name))
283 return &a->addr;
284 }
285 return NULL;
286}
287
294void mutt_expand_aliases(struct AddressList *al)
295{
296 // previously expanded aliases to avoid loops
297 struct ListHead expn = STAILQ_HEAD_INITIALIZER(expn);
298
299 expand_aliases_r(al, &expn);
300 mutt_list_free(&expn);
302}
303
317
326struct AddressList *mutt_get_address(struct Envelope *env, const char **prefix)
327{
328 struct AddressList *al = NULL;
329 const char *pfx = NULL;
330
332 {
333 if (!TAILQ_EMPTY(&env->to) && !mutt_is_mail_list(TAILQ_FIRST(&env->to)))
334 {
335 pfx = "To";
336 al = &env->to;
337 }
338 else
339 {
340 pfx = "Cc";
341 al = &env->cc;
342 }
343 }
344 else if (!TAILQ_EMPTY(&env->reply_to) && !mutt_is_mail_list(TAILQ_FIRST(&env->reply_to)))
345 {
346 pfx = "Reply-To";
347 al = &env->reply_to;
348 }
349 else
350 {
351 al = &env->from;
352 pfx = "From";
353 }
354
355 if (prefix)
356 *prefix = pfx;
357
358 return al;
359}
360
366void alias_create(struct AddressList *al, const struct ConfigSubset *sub)
367{
368 struct Buffer *buf = buf_pool_get();
369 struct Buffer *fixed = buf_pool_get();
370 struct Buffer *prompt = NULL;
371 struct Buffer *tmp = buf_pool_get();
372
373 struct Address *addr = NULL;
374 char *pc = NULL;
375 char *err = NULL;
376 FILE *fp_alias = NULL;
377
378 if (al)
379 {
380 addr = TAILQ_FIRST(al);
381 if (addr && addr->mailbox)
382 {
383 buf_copy(tmp, addr->mailbox);
384 pc = strchr(buf_string(tmp), '@');
385 if (pc)
386 *pc = '\0';
387 }
388 }
389
390 /* Don't suggest a bad alias name in the event of a strange local part. */
391 check_alias_name(buf_string(tmp), buf);
392
393retry_name:
394 /* L10N: prompt to add a new alias */
395 if ((mw_get_field(_("Alias as: "), buf, MUTT_COMP_NO_FLAGS, HC_OTHER, NULL, NULL) != 0) ||
396 buf_is_empty(buf))
397 {
398 goto done;
399 }
400
401 /* check to see if the user already has an alias defined */
402 if (alias_lookup(buf_string(buf)))
403 {
404 mutt_error(_("You already have an alias defined with that name"));
405 goto done;
406 }
407
408 if (check_alias_name(buf_string(buf), fixed))
409 {
410 switch (query_yesorno(_("Warning: This alias name may not work. Fix it?"), MUTT_YES))
411 {
412 case MUTT_YES:
413 buf_copy(buf, fixed);
414 goto retry_name;
415 case MUTT_ABORT:
416 goto done;
417 default:; // do nothing
418 }
419 }
420
421 struct Alias *alias = alias_new();
422 alias->name = buf_strdup(buf);
423
425
426 if (addr && addr->mailbox)
427 buf_copy(buf, addr->mailbox);
428 else
429 buf_reset(buf);
430
431 mutt_addrlist_to_intl(al, NULL);
432
433 do
434 {
435 if ((mw_get_field(_("Address: "), buf, MUTT_COMP_NO_FLAGS, HC_OTHER, NULL, NULL) != 0) ||
436 buf_is_empty(buf))
437 {
438 alias_free(&alias);
439 goto done;
440 }
441
442 mutt_addrlist_parse(&alias->addr, buf_string(buf));
443 if (TAILQ_EMPTY(&alias->addr))
444 mutt_beep(false);
445 if (mutt_addrlist_to_intl(&alias->addr, &err))
446 {
447 mutt_error(_("Bad IDN: '%s'"), err);
448 FREE(&err);
449 continue;
450 }
451 } while (TAILQ_EMPTY(&alias->addr));
452
453 if (addr && addr->personal && !mutt_is_mail_list(addr))
454 buf_copy(buf, addr->personal);
455 else
456 buf_reset(buf);
457
458 if (mw_get_field(_("Personal name: "), buf, MUTT_COMP_NO_FLAGS, HC_OTHER, NULL, NULL) != 0)
459 {
460 alias_free(&alias);
461 goto done;
462 }
463
464 TAILQ_FIRST(&alias->addr)->personal = buf_new(buf_string(buf));
465
466 buf_reset(buf);
467 if (mw_get_field(_("Comment: "), buf, MUTT_COMP_NO_FLAGS, HC_OTHER, NULL, NULL) == 0)
468 {
469 mutt_str_replace(&alias->comment, buf_string(buf));
470 }
471
472 buf_reset(buf);
473 if (mw_get_field(_("Tags (comma-separated): "), buf, MUTT_COMP_NO_FLAGS,
474 HC_OTHER, NULL, NULL) == 0)
475 {
476 parse_alias_tags(buf_string(buf), &alias->tags);
477 }
478
479 buf_reset(buf);
480 mutt_addrlist_write(&alias->addr, buf, true);
481 prompt = buf_pool_get();
482
483 buf_printf(prompt, "alias %s %s", alias->name, buf_string(buf));
484
485 bool has_tags = STAILQ_FIRST(&alias->tags);
486
487 if (alias->comment || has_tags)
488 buf_addstr(prompt, " #");
489
490 if (alias->comment)
491 buf_add_printf(prompt, " %s", alias->comment);
492
493 if (has_tags)
494 {
495 if (STAILQ_FIRST(&alias->tags))
496 {
497 buf_addstr(prompt, " tags:");
498 alias_tags_to_buffer(&alias->tags, prompt);
499 }
500 }
501
502 buf_add_printf(prompt, "\n%s", _("Accept?"));
503
504 if (query_yesorno(buf_string(prompt), MUTT_YES) != MUTT_YES)
505 {
506 alias_free(&alias);
507 goto done;
508 }
509
510 alias_reverse_add(alias);
511 TAILQ_INSERT_TAIL(&Aliases, alias, entries);
512
513 const char *const c_alias_file = cs_subset_path(sub, "alias_file");
514 buf_strcpy(buf, c_alias_file);
515
516 struct FileCompletionData cdata = { false, NULL, NULL, NULL };
517 if (mw_get_field(_("Save to file: "), buf, MUTT_COMP_CLEAR, HC_FILE,
518 &CompleteFileOps, &cdata) != 0)
519 {
520 goto done;
521 }
522 buf_expand_path(buf);
523 fp_alias = mutt_file_fopen(buf_string(buf), "a+");
524 if (!fp_alias)
525 {
526 mutt_perror("%s", buf_string(buf));
527 goto done;
528 }
529
530 /* terminate existing file with \n if necessary */
531 if (ftell(fp_alias) > 0)
532 {
533 if (!mutt_file_seek(fp_alias, -1, SEEK_CUR))
534 {
535 goto done;
536 }
537 if (fread(buf->data, 1, 1, fp_alias) != 1)
538 {
539 mutt_perror(_("Error reading alias file"));
540 goto done;
541 }
542 if (!mutt_file_seek(fp_alias, 0, SEEK_END))
543 {
544 goto done;
545 }
546 if (buf_at(buf, 0) != '\n')
547 fputc('\n', fp_alias);
548 }
549
550 if (check_alias_name(alias->name, NULL))
551 buf_quote_filename(buf, alias->name, true);
552 else
553 buf_strcpy(buf, alias->name);
554
555 recode_buf(buf);
556 fprintf(fp_alias, "alias %s ", buf_string(buf));
557 buf_reset(buf);
558
559 mutt_addrlist_write(&alias->addr, buf, false);
560 recode_buf(buf);
561 write_safe_address(fp_alias, buf_string(buf));
562 if (alias->comment)
563 fprintf(fp_alias, " # %s", alias->comment);
564 if (STAILQ_FIRST(&alias->tags))
565 {
566 fprintf(fp_alias, " tags:");
567
568 struct Tag *tag = NULL;
569 STAILQ_FOREACH(tag, &alias->tags, entries)
570 {
571 fprintf(fp_alias, "%s", tag->name);
572 if (STAILQ_NEXT(tag, entries))
573 fprintf(fp_alias, ",");
574 }
575 }
576 fputc('\n', fp_alias);
577 if (mutt_file_fsync_close(&fp_alias) != 0)
578 mutt_perror(_("Trouble adding alias"));
579 else
580 mutt_message(_("Alias added"));
581
582done:
583 mutt_file_fclose(&fp_alias);
584 buf_pool_release(&buf);
585 buf_pool_release(&fixed);
586 buf_pool_release(&prompt);
587 buf_pool_release(&tmp);
588}
589
595bool mutt_addr_is_user(const struct Address *addr)
596{
597 if (!addr)
598 {
599 mutt_debug(LL_DEBUG5, "no, NULL address\n");
600 return false;
601 }
602 if (!addr->mailbox)
603 {
604 mutt_debug(LL_DEBUG5, "no, no mailbox\n");
605 return false;
606 }
607
609 {
610 mutt_debug(LL_DEBUG5, "#1 yes, %s = %s\n", buf_string(addr->mailbox),
612 return true;
613 }
615 {
616 mutt_debug(LL_DEBUG5, "#2 yes, %s = %s @ %s\n", buf_string(addr->mailbox),
618 return true;
619 }
620 const char *fqdn = mutt_fqdn(false, NeoMutt->sub);
622 {
623 mutt_debug(LL_DEBUG5, "#3 yes, %s = %s @ %s\n", buf_string(addr->mailbox),
624 NeoMutt->username, NONULL(fqdn));
625 return true;
626 }
627 fqdn = mutt_fqdn(true, NeoMutt->sub);
629 {
630 mutt_debug(LL_DEBUG5, "#4 yes, %s = %s @ %s\n", buf_string(addr->mailbox),
631 NeoMutt->username, NONULL(fqdn));
632 return true;
633 }
634
635 const struct Address *c_from = cs_subset_address(NeoMutt->sub, "from");
636 if (c_from && mutt_istr_equal(buf_string(c_from->mailbox), buf_string(addr->mailbox)))
637 {
638 mutt_debug(LL_DEBUG5, "#5 yes, %s = %s\n", buf_string(addr->mailbox),
639 buf_string(c_from->mailbox));
640 return true;
641 }
642
644 return true;
645
646 mutt_debug(LL_DEBUG5, "no, all failed\n");
647 return false;
648}
649
656struct Alias *alias_new(void)
657{
658 struct Alias *a = MUTT_MEM_CALLOC(1, struct Alias);
659 TAILQ_INIT(&a->addr);
660 STAILQ_INIT(&a->tags);
661 return a;
662}
663
668void alias_free(struct Alias **ptr)
669{
670 if (!ptr || !*ptr)
671 return;
672
673 struct Alias *alias = *ptr;
674
675 mutt_debug(LL_NOTIFY, "NT_ALIAS_DELETE: %s\n", alias->name);
676 struct EventAlias ev_a = { alias };
678
679 FREE(&alias->name);
680 FREE(&alias->comment);
683
684 FREE(ptr);
685}
686
693void aliaslist_clear(struct AliasList *al)
694{
695 if (!al)
696 return;
697
698 struct Alias *np = NULL, *tmp = NULL;
699 TAILQ_FOREACH_SAFE(np, al, entries, tmp)
700 {
701 TAILQ_REMOVE(al, np, entries);
702 alias_free(&np);
703 }
704 TAILQ_INIT(al);
705}
706
710void alias_init(void)
711{
713}
714
719{
720 struct Alias *np = NULL;
721 TAILQ_FOREACH(np, &Aliases, entries)
722 {
724 }
727}
void mutt_addrlist_copy(struct AddressList *dst, const struct AddressList *src, bool prune)
Copy a list of addresses into another list.
Definition address.c:765
void mutt_addrlist_qualify(struct AddressList *al, const char *host)
Expand local names in an Address list using a hostname.
Definition address.c:680
void mutt_addrlist_clear(struct AddressList *al)
Unlink and free all Address in an AddressList.
Definition address.c:1460
void mutt_addr_free(struct Address **ptr)
Free a single Address.
Definition address.c:462
int mutt_addrlist_to_local(struct AddressList *al)
Convert an Address list from Punycode.
Definition address.c:1378
size_t mutt_addrlist_write(const struct AddressList *al, struct Buffer *buf, bool display)
Write an Address to a buffer.
Definition address.c:1206
int mutt_addrlist_parse(struct AddressList *al, const char *s)
Parse a list of email addresses.
Definition address.c:480
int mutt_addrlist_to_intl(struct AddressList *al, char **err)
Convert an Address list to Punycode.
Definition address.c:1293
void mutt_addrlist_dedupe(struct AddressList *al)
Remove duplicate addresses.
Definition address.c:1397
const struct Address * cs_subset_address(const struct ConfigSubset *sub, const char *name)
Get an Address config item by name.
Email Address Handling.
void parse_alias_tags(const char *tags, struct TagList *tl)
Parse a comma-separated list of tags.
Definition commands.c:65
void alias_tags_to_buffer(struct TagList *tl, struct Buffer *buf)
Write a comma-separated list of tags to a Buffer.
Definition commands.c:49
Email Aliases.
void alias_cleanup(void)
Clean up the Alias globals.
Definition alias.c:718
void alias_free(struct Alias **ptr)
Free an Alias.
Definition alias.c:668
struct AliasList Aliases
List of all the user's email aliases.
Definition alias.c:61
static int check_alias_name(const char *s, struct Buffer *dest)
Sanity-check an alias name.
Definition alias.c:215
static bool string_is_address(const char *str, const char *user, const char *domain)
Does an email address match a user and domain?
Definition alias.c:257
struct AddressList * alias_lookup(const char *name)
Find an Alias.
Definition alias.c:276
void mutt_expand_aliases(struct AddressList *al)
Expand aliases in a List of Addresses.
Definition alias.c:294
static void recode_buf(struct Buffer *buf)
Convert some text between two character sets.
Definition alias.c:191
void alias_create(struct AddressList *al, const struct ConfigSubset *sub)
Create a new Alias from an Address.
Definition alias.c:366
bool mutt_addr_is_user(const struct Address *addr)
Does the address belong to the user.
Definition alias.c:595
void alias_init(void)
Set up the Alias globals.
Definition alias.c:710
struct Alias * alias_new(void)
Create a new Alias.
Definition alias.c:656
void mutt_expand_aliases_env(struct Envelope *env)
Expand aliases in all the fields of an Envelope.
Definition alias.c:308
struct AddressList * mutt_get_address(struct Envelope *env, const char **prefix)
Get an Address from an Envelope.
Definition alias.c:326
void aliaslist_clear(struct AliasList *al)
Empty a List of Aliases.
Definition alias.c:693
static void write_safe_address(FILE *fp, const char *s)
Defang malicious email addresses.
Definition alias.c:87
static void expand_aliases_r(struct AddressList *al, struct ListHead *expn)
Expand aliases, recursively.
Definition alias.c:105
Representation of a single alias to an email address.
@ NT_ALIAS_DELETE
Alias is about to be deleted.
Definition alias.h:57
bool mutt_alternates_match(const char *addr)
Compare an Address to the Un/Alternates lists.
Definition alternates.c:155
Alternate address handling.
const struct CompleteOps CompleteFileOps
Auto-Completion of Files.
Definition complete.c:152
Select a Mailbox from a list.
int buf_printf(struct Buffer *buf, const char *fmt,...)
Format a string overwriting a Buffer.
Definition buffer.c:161
int buf_add_printf(struct Buffer *buf, const char *fmt,...)
Format a string appending a Buffer.
Definition buffer.c:204
size_t buf_addstr_n(struct Buffer *buf, const char *s, size_t len)
Add a string to a Buffer, expanding it if necessary.
Definition buffer.c:96
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
char buf_at(const struct Buffer *buf, size_t offset)
Return the character at the given offset.
Definition buffer.c:668
struct Buffer * buf_new(const char *str)
Allocate a new Buffer.
Definition buffer.c:304
size_t buf_addch(struct Buffer *buf, char c)
Add a single character to a Buffer.
Definition buffer.c:241
size_t buf_addstr(struct Buffer *buf, const char *s)
Add a string to a Buffer.
Definition buffer.c:226
const char * buf_find_char(const struct Buffer *buf, const char c)
Return a pointer to a char found in the buffer.
Definition buffer.c:653
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
const char * cs_subset_string(const struct ConfigSubset *sub, const char *name)
Get a string config item by name.
Definition helpers.c:291
const char * cs_subset_path(const struct ConfigSubset *sub, const char *name)
Get a path config item by name.
Definition helpers.c:168
bool cs_subset_bool(const struct ConfigSubset *sub, const char *name)
Get a boolean config item by name.
Definition helpers.c:47
Convenience wrapper for the config headers.
const char * cc_charset(void)
Get the cached value of $charset.
Convenience wrapper for the core headers.
void mutt_beep(bool force)
Irritate the user.
Definition curs_lib.c:69
Edit a string.
Structs that make up an email.
void buf_quote_filename(struct Buffer *buf, const char *filename, bool add_outer)
Quote a filename to survive the shell's quoting rules.
Definition file.c:810
bool mutt_file_seek(FILE *fp, LOFF_T offset, int whence)
Wrapper for fseeko with error handling.
Definition file.c:655
int mutt_file_fsync_close(FILE **fp)
Flush the data, before closing a file (and NULL the pointer)
Definition file.c:131
#define mutt_file_fclose(FP)
Definition file.h:139
#define mutt_file_fopen(PATH, MODE)
Definition file.h:138
char * ShortHostname
Short version of the hostname.
Definition globals.c:37
bool mutt_is_mail_list(const struct Address *addr)
Is this the email address of a mailing list?
Definition maillist.c:44
int mw_get_field(const char *prompt, struct Buffer *buf, CompletionFlags complete, enum HistoryClass hclass, const struct CompleteOps *comp_api, void *cdata)
Ask the user for a string -.
Definition window.c:272
#define mutt_error(...)
Definition logging2.h:93
#define mutt_message(...)
Definition logging2.h:92
#define mutt_debug(LEVEL,...)
Definition logging2.h:90
#define mutt_perror(...)
Definition logging2.h:94
Convenience wrapper for the gui headers.
Read/write command history from/to a file.
@ HC_FILE
Files.
Definition lib.h:57
@ HC_OTHER
Miscellaneous strings.
Definition lib.h:59
struct ListNode * mutt_list_insert_head(struct ListHead *h, char *s)
Insert a string at the beginning of a List.
Definition list.c:46
void mutt_list_free(struct ListHead *h)
Free a List AND its strings.
Definition list.c:123
@ LL_DEBUG5
Log at debug level 5.
Definition logging2.h:48
@ LL_DEBUG1
Log at debug level 1.
Definition logging2.h:44
@ LL_NOTIFY
Log of notifications.
Definition logging2.h:49
Handle mailing lists.
#define FREE(x)
Definition memory.h:62
#define MUTT_MEM_CALLOC(n, type)
Definition memory.h:47
int mutt_ch_convert_string(char **ps, const char *from, const char *to, uint8_t flags)
Convert a string between encodings.
Definition charset.c:831
#define ICONV_BUF_TOO_SMALL
Error value for iconv() - Buffer too small.
Definition charset.h:98
#define MUTT_ICONV_NO_FLAGS
No flags are set.
Definition charset.h:64
#define ICONV_ILLEGAL_SEQ
Error value for iconv() - Illegal sequence.
Definition charset.h:96
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
bool mutt_istr_equal(const char *a, const char *b)
Compare two strings, ignoring case.
Definition string.c:672
bool mutt_str_equal(const char *a, const char *b)
Compare two strings.
Definition string.c:660
char * mutt_str_replace(char **p, const char *s)
Replace one string with another.
Definition string.c:282
Many unsorted constants and some structs.
#define MUTT_COMP_NO_FLAGS
No flags are set.
Definition mutt.h:56
#define MUTT_COMP_CLEAR
Clear input if printable character is pressed.
Definition mutt.h:57
char * mutt_gecos_name(char *dest, size_t destlen, struct passwd *pw)
Lookup a user's real name in /etc/passwd.
Definition muttlib.c:331
void buf_expand_path(struct Buffer *buf)
Create the canonical path.
Definition muttlib.c:314
Some miscellaneous functions.
@ NT_ALIAS
Alias has changed, NotifyAlias, EventAlias.
Definition notify_type.h:37
struct Buffer * buf_pool_get(void)
Get a Buffer from the pool.
Definition pool.c:82
void buf_pool_release(struct Buffer **ptr)
Return a Buffer to the pool.
Definition pool.c:96
@ MUTT_ABORT
User aborted the question (with Ctrl-G)
Definition quad.h:37
@ MUTT_YES
User answered 'Yes', or assume 'Yes'.
Definition quad.h:39
Ask the user a question.
enum QuadOption query_yesorno(const char *prompt, enum QuadOption def)
Ask the user a Yes/No question.
Definition question.c:325
#define TAILQ_FOREACH(var, head, field)
Definition queue.h:782
#define TAILQ_FOREACH_SAFE(var, head, field, tvar)
Definition queue.h:792
#define STAILQ_INIT(head)
Definition queue.h:410
#define STAILQ_HEAD_INITIALIZER(head)
Definition queue.h:324
#define STAILQ_FIRST(head)
Definition queue.h:388
#define TAILQ_INIT(head)
Definition queue.h:822
#define TAILQ_INSERT_TAIL(head, elm, field)
Definition queue.h:866
#define TAILQ_PREV(elm, headname, field)
Definition queue.h:891
#define STAILQ_FOREACH(var, head, field)
Definition queue.h:390
#define TAILQ_FIRST(head)
Definition queue.h:780
#define TAILQ_REMOVE(head, elm, field)
Definition queue.h:901
#define TAILQ_NEXT(elm, field)
Definition queue.h:889
#define TAILQ_HEAD_INITIALIZER(head)
Definition queue.h:694
#define TAILQ_EMPTY(head)
Definition queue.h:778
#define TAILQ_INSERT_BEFORE(listelm, elm, field)
Definition queue.h:843
#define STAILQ_NEXT(elm, field)
Definition queue.h:439
void alias_reverse_add(struct Alias *alias)
Add an email address lookup for an Alias.
Definition reverse.c:61
void alias_reverse_shutdown(void)
Clear up the Reverse Alias Hash Table.
Definition reverse.c:52
void alias_reverse_delete(struct Alias *alias)
Remove an email address lookup for an Alias.
Definition reverse.c:83
void alias_reverse_init(void)
Set up the Reverse Alias Hash Table.
Definition reverse.c:42
Manage alias reverse lookups.
Convenience wrapper for the send headers.
const char * mutt_fqdn(bool may_hide_host, const struct ConfigSubset *sub)
Get the Fully-Qualified Domain Name.
Definition sendlib.c:706
#define NONULL(x)
Definition string2.h:43
An email address.
Definition address.h:35
struct Buffer * personal
Real name of address.
Definition address.h:36
bool group
Group mailbox?
Definition address.h:38
struct Buffer * mailbox
Mailbox and host address.
Definition address.h:37
A shortcut for an email address or addresses.
Definition alias.h:35
struct TagList tags
Tags.
Definition alias.h:39
char * comment
Free-form comment string.
Definition alias.h:38
char * name
Short name.
Definition alias.h:36
struct AddressList addr
List of Addresses the Alias expands to.
Definition alias.h:37
String manipulation buffer.
Definition buffer.h:36
char * data
Pointer to data.
Definition buffer.h:37
A set of inherited config items.
Definition subset.h:46
The header of an Email.
Definition envelope.h:57
struct AddressList to
Email's 'To' list.
Definition envelope.h:60
struct AddressList reply_to
Email's 'reply-to'.
Definition envelope.h:64
struct AddressList mail_followup_to
Email's 'mail-followup-to'.
Definition envelope.h:65
struct AddressList cc
Email's 'Cc' list.
Definition envelope.h:61
struct AddressList bcc
Email's 'Bcc' list.
Definition envelope.h:62
struct AddressList from
Email's 'From' list.
Definition envelope.h:59
An alias-change event.
Definition alias.h:66
struct Alias * alias
Alias that changed.
Definition alias.h:67
Input for the file completion function.
Definition curs_lib.h:39
A List node for strings.
Definition list.h:37
char * data
String.
Definition list.h:38
Container for Accounts, Notifications.
Definition neomutt.h:43
char * username
User's login name.
Definition neomutt.h:54
struct Notify * notify
Notifications handler.
Definition neomutt.h:44
struct ConfigSubset * sub
Inherited config items.
Definition neomutt.h:47
LinkedList Tag Element.
Definition tags.h:42
char * name
Tag name.
Definition tags.h:43
void driver_tags_free(struct TagList *tl)
Free tags from a header.
Definition tags.c:131