NeoMutt  2024-02-01-23-g345d7b
Teaching an old dog new tricks
DOXYGEN
Loading...
Searching...
No Matches
alias.c
Go to the documentation of this file.
1
33#include "config.h"
34#include <stddef.h>
35#include <pwd.h>
36#include <stdbool.h>
37#include <stdio.h>
38#include <stdlib.h>
39#include <string.h>
40#include <wchar.h>
41#include <wctype.h>
42#include "mutt/lib.h"
43#include "address/lib.h"
44#include "config/lib.h"
45#include "email/lib.h"
46#include "core/lib.h"
47#include "gui/lib.h"
48#include "mutt.h"
49#include "alias.h"
50#include "lib.h"
51#include "browser/lib.h"
52#include "editor/lib.h"
53#include "history/lib.h"
54#include "question/lib.h"
55#include "send/lib.h"
56#include "alternates.h"
57#include "globals.h"
58#include "maillist.h"
59#include "muttlib.h"
60#include "reverse.h"
61
63
88static void write_safe_address(FILE *fp, const char *s)
89{
90 while (*s)
91 {
92 if ((*s == '\\') || (*s == '`') || (*s == '\'') || (*s == '"') || (*s == '$'))
93 fputc('\\', fp);
94 fputc(*s, fp);
95 s++;
96 }
97}
98
106static void expand_aliases_r(struct AddressList *al, struct ListHead *expn)
107{
108 struct Address *a = TAILQ_FIRST(al);
109 while (a)
110 {
111 if (!a->group && !a->personal && a->mailbox && !buf_find_char(a->mailbox, '@'))
112 {
113 struct AddressList *alias = alias_lookup(buf_string(a->mailbox));
114 if (alias)
115 {
116 bool duplicate = false;
117 struct ListNode *np = NULL;
118 STAILQ_FOREACH(np, expn, entries)
119 {
120 if (mutt_str_equal(buf_string(a->mailbox), np->data)) /* alias already found */
121 {
122 mutt_debug(LL_DEBUG1, "loop in alias found for '%s'\n", buf_string(a->mailbox));
123 duplicate = true;
124 break;
125 }
126 }
127
128 if (duplicate)
129 {
130 // We've already seen this alias, so drop it
131 struct Address *next = TAILQ_NEXT(a, entries);
132 TAILQ_REMOVE(al, a, entries);
133 mutt_addr_free(&a);
134 a = next;
135 continue;
136 }
137
138 // Keep a list of aliases that we've already seen
140
141 /* The alias may expand to several addresses,
142 * some of which may themselves be aliases.
143 * Create a copy and recursively expand any aliases within. */
144 struct AddressList copy = TAILQ_HEAD_INITIALIZER(copy);
145 mutt_addrlist_copy(&copy, alias, false);
146 expand_aliases_r(&copy, expn);
147
148 /* Next, move the expanded addresses
149 * from the copy into the original list (before the alias) */
150 struct Address *a2 = NULL, *tmp = NULL;
151 TAILQ_FOREACH_SAFE(a2, &copy, entries, tmp)
152 {
153 TAILQ_INSERT_BEFORE(a, a2, entries);
154 }
155 a = TAILQ_PREV(a, AddressList, entries);
156 // Finally, remove the alias itself
157 struct Address *next = TAILQ_NEXT(a, entries);
158 TAILQ_REMOVE(al, next, entries);
159 mutt_addr_free(&next);
160 }
161 else
162 {
163 struct passwd *pw = getpwnam(buf_string(a->mailbox));
164 if (pw)
165 {
166 char namebuf[256] = { 0 };
167
168 mutt_gecos_name(namebuf, sizeof(namebuf), pw);
169 a->personal = buf_new(namebuf);
170 }
171 }
172 }
173 a = TAILQ_NEXT(a, entries);
174 }
175
176 const char *fqdn = NULL;
177 const bool c_use_domain = cs_subset_bool(NeoMutt->sub, "use_domain");
178 if (c_use_domain && (fqdn = mutt_fqdn(true, NeoMutt->sub)))
179 {
180 /* now qualify all local addresses */
181 mutt_addrlist_qualify(al, fqdn);
182 }
183}
184
192static void recode_buf(struct Buffer *buf)
193{
194 const char *const c_config_charset = cs_subset_string(NeoMutt->sub, "config_charset");
195 if (!c_config_charset || !cc_charset())
196 return;
197
198 char *s = buf_strdup(buf);
199 if (!s)
200 return;
201 if (mutt_ch_convert_string(&s, cc_charset(), c_config_charset, MUTT_ICONV_NO_FLAGS) == 0)
202 buf_strcpy(buf, s);
203 FREE(&s);
204}
205
217static int check_alias_name(const char *s, char *dest, size_t destlen)
218{
219 wchar_t wc = 0;
220 mbstate_t mbstate = { 0 };
221 size_t l;
222 int rc = 0;
223 bool dry = !dest || !destlen;
224
225 if (!dry)
226 destlen--;
227 for (; s && *s && (dry || destlen) && (l = mbrtowc(&wc, s, MB_CUR_MAX, &mbstate)) != 0;
228 s += l, destlen -= l)
229 {
230 bool bad = (l == ICONV_ILLEGAL_SEQ) || (l == ICONV_BUF_TOO_SMALL); /* conversion error */
231 bad = bad || (!dry && l > destlen); /* too few room for mb char */
232 if (l == 1)
233 bad = bad || (!strchr("-_+=.", *s) && !iswalnum(wc));
234 else
235 bad = bad || !iswalnum(wc);
236 if (bad)
237 {
238 if (dry)
239 return -1;
240 if (l == ICONV_ILLEGAL_SEQ)
241 memset(&mbstate, 0, sizeof(mbstate_t));
242 *dest++ = '_';
243 rc = -1;
244 }
245 else if (!dry)
246 {
247 memcpy(dest, s, l);
248 dest += l;
249 }
250 }
251 if (!dry)
252 *dest = '\0';
253 return rc;
254}
255
263static bool string_is_address(const char *str, const char *user, const char *domain)
264{
265 char buf[1024] = { 0 };
266
267 snprintf(buf, sizeof(buf), "%s@%s", NONULL(user), NONULL(domain));
268 if (mutt_istr_equal(str, buf))
269 return true;
270
271 return false;
272}
273
282struct AddressList *alias_lookup(const char *name)
283{
284 struct Alias *a = NULL;
285
286 TAILQ_FOREACH(a, &Aliases, entries)
287 {
288 if (mutt_istr_equal(name, a->name))
289 return &a->addr;
290 }
291 return NULL;
292}
293
300void mutt_expand_aliases(struct AddressList *al)
301{
302 // previously expanded aliases to avoid loops
303 struct ListHead expn = STAILQ_HEAD_INITIALIZER(expn);
304
305 expand_aliases_r(al, &expn);
306 mutt_list_free(&expn);
308}
309
315{
317 mutt_expand_aliases(&env->to);
318 mutt_expand_aliases(&env->cc);
322}
323
332struct AddressList *mutt_get_address(struct Envelope *env, const char **prefix)
333{
334 struct AddressList *al = NULL;
335 const char *pfx = NULL;
336
338 {
339 if (!TAILQ_EMPTY(&env->to) && !mutt_is_mail_list(TAILQ_FIRST(&env->to)))
340 {
341 pfx = "To";
342 al = &env->to;
343 }
344 else
345 {
346 pfx = "Cc";
347 al = &env->cc;
348 }
349 }
350 else if (!TAILQ_EMPTY(&env->reply_to) && !mutt_is_mail_list(TAILQ_FIRST(&env->reply_to)))
351 {
352 pfx = "Reply-To";
353 al = &env->reply_to;
354 }
355 else
356 {
357 al = &env->from;
358 pfx = "From";
359 }
360
361 if (prefix)
362 *prefix = pfx;
363
364 return al;
365}
366
372void alias_create(struct AddressList *al, const struct ConfigSubset *sub)
373{
374 struct Buffer *buf = buf_pool_get();
375 struct Buffer *fixed = buf_pool_get();
376 struct Buffer *prompt = NULL;
377 struct Buffer *tmp = buf_pool_get();
378
379 struct Address *addr = NULL;
380 char *pc = NULL;
381 char *err = NULL;
382 FILE *fp_alias = NULL;
383
384 if (al)
385 {
386 addr = TAILQ_FIRST(al);
387 if (addr && addr->mailbox)
388 {
389 buf_copy(tmp, addr->mailbox);
390 pc = strchr(buf_string(tmp), '@');
391 if (pc)
392 *pc = '\0';
393 }
394 }
395
396 /* Don't suggest a bad alias name in the event of a strange local part. */
397 check_alias_name(buf_string(tmp), buf->data, buf->dsize);
398
399retry_name:
400 /* L10N: prompt to add a new alias */
401 if ((mw_get_field(_("Alias as: "), buf, MUTT_COMP_NO_FLAGS, HC_OTHER, NULL, NULL) != 0) ||
402 buf_is_empty(buf))
403 {
404 goto done;
405 }
406
407 /* check to see if the user already has an alias defined */
408 if (alias_lookup(buf_string(buf)))
409 {
410 mutt_error(_("You already have an alias defined with that name"));
411 goto done;
412 }
413
414 if (check_alias_name(buf_string(buf), fixed->data, fixed->dsize))
415 {
416 switch (query_yesorno(_("Warning: This alias name may not work. Fix it?"), MUTT_YES))
417 {
418 case MUTT_YES:
419 buf_copy(buf, fixed);
420 goto retry_name;
421 case MUTT_ABORT:
422 goto done;
423 default:; // do nothing
424 }
425 }
426
427 struct Alias *alias = alias_new();
428 alias->name = buf_strdup(buf);
429
431
432 if (addr && addr->mailbox)
433 buf_copy(buf, addr->mailbox);
434 else
435 buf_reset(buf);
436
437 mutt_addrlist_to_intl(al, NULL);
438
439 do
440 {
441 if ((mw_get_field(_("Address: "), buf, MUTT_COMP_NO_FLAGS, HC_OTHER, NULL, NULL) != 0) ||
442 buf_is_empty(buf))
443 {
444 alias_free(&alias);
445 goto done;
446 }
447
448 mutt_addrlist_parse(&alias->addr, buf_string(buf));
449 if (TAILQ_EMPTY(&alias->addr))
450 mutt_beep(false);
451 if (mutt_addrlist_to_intl(&alias->addr, &err))
452 {
453 mutt_error(_("Bad IDN: '%s'"), err);
454 FREE(&err);
455 continue;
456 }
457 } while (TAILQ_EMPTY(&alias->addr));
458
459 if (addr && addr->personal && !mutt_is_mail_list(addr))
460 buf_copy(buf, addr->personal);
461 else
462 buf_reset(buf);
463
464 if (mw_get_field(_("Personal name: "), buf, MUTT_COMP_NO_FLAGS, HC_OTHER, NULL, NULL) != 0)
465 {
466 alias_free(&alias);
467 goto done;
468 }
469
470 TAILQ_FIRST(&alias->addr)->personal = buf_new(buf_string(buf));
471
472 buf_reset(buf);
473 if (mw_get_field(_("Comment: "), buf, MUTT_COMP_NO_FLAGS, HC_OTHER, NULL, NULL) == 0)
474 {
475 mutt_str_replace(&alias->comment, buf_string(buf));
476 }
477
478 buf_reset(buf);
479 if (mw_get_field(_("Tags (comma-separated): "), buf, MUTT_COMP_NO_FLAGS,
480 HC_OTHER, NULL, NULL) == 0)
481 {
482 parse_alias_tags(buf_string(buf), &alias->tags);
483 }
484
485 buf_reset(buf);
486 mutt_addrlist_write(&alias->addr, buf, true);
487 prompt = buf_pool_get();
488
489 buf_printf(prompt, "alias %s %s", alias->name, buf_string(buf));
490
491 bool has_tags = STAILQ_FIRST(&alias->tags);
492
493 if (alias->comment || has_tags)
494 buf_addstr(prompt, " #");
495
496 if (alias->comment)
497 buf_add_printf(prompt, " %s", alias->comment);
498
499 if (has_tags)
500 {
501 if (STAILQ_FIRST(&alias->tags))
502 {
503 buf_addstr(prompt, " tags:");
504 alias_tags_to_buffer(&alias->tags, prompt);
505 }
506 }
507
508 buf_add_printf(prompt, "\n%s", _("Accept?"));
509
510 if (query_yesorno(buf_string(prompt), MUTT_YES) != MUTT_YES)
511 {
512 alias_free(&alias);
513 goto done;
514 }
515
516 alias_reverse_add(alias);
517 TAILQ_INSERT_TAIL(&Aliases, alias, entries);
518
519 const char *const c_alias_file = cs_subset_path(sub, "alias_file");
520 buf_strcpy(buf, c_alias_file);
521
522 struct FileCompletionData cdata = { false, NULL, NULL, NULL };
523 if (mw_get_field(_("Save to file: "), buf, MUTT_COMP_CLEAR, HC_FILE,
524 &CompleteFileOps, &cdata) != 0)
525 {
526 goto done;
527 }
528 mutt_expand_path(buf->data, buf->dsize);
529 fp_alias = mutt_file_fopen(buf_string(buf), "a+");
530 if (!fp_alias)
531 {
532 mutt_perror("%s", buf_string(buf));
533 goto done;
534 }
535
536 /* terminate existing file with \n if necessary */
537 if (!mutt_file_seek(fp_alias, 0, SEEK_END))
538 {
539 goto done;
540 }
541 if (ftell(fp_alias) > 0)
542 {
543 if (!mutt_file_seek(fp_alias, -1, SEEK_CUR))
544 {
545 goto done;
546 }
547 if (fread(buf->data, 1, 1, fp_alias) != 1)
548 {
549 mutt_perror(_("Error reading alias file"));
550 goto done;
551 }
552 if (!mutt_file_seek(fp_alias, 0, SEEK_END))
553 {
554 goto done;
555 }
556 if (buf->data[0] != '\n')
557 fputc('\n', fp_alias);
558 }
559
560 if (check_alias_name(alias->name, NULL, 0))
561 mutt_file_quote_filename(alias->name, buf->data, buf->dsize);
562 else
563 buf_strcpy(buf, alias->name);
564
565 recode_buf(buf);
566 fprintf(fp_alias, "alias %s ", buf_string(buf));
567 buf_reset(buf);
568
569 mutt_addrlist_write(&alias->addr, buf, false);
570 recode_buf(buf);
571 write_safe_address(fp_alias, buf_string(buf));
572 if (alias->comment)
573 fprintf(fp_alias, " # %s", alias->comment);
574 if (STAILQ_FIRST(&alias->tags))
575 {
576 fprintf(fp_alias, " tags:");
577
578 struct Tag *tag = NULL;
579 STAILQ_FOREACH(tag, &alias->tags, entries)
580 {
581 fprintf(fp_alias, "%s", tag->name);
582 if (STAILQ_NEXT(tag, entries))
583 fprintf(fp_alias, ",");
584 }
585 }
586 fputc('\n', fp_alias);
587 if (mutt_file_fsync_close(&fp_alias) != 0)
588 mutt_perror(_("Trouble adding alias"));
589 else
590 mutt_message(_("Alias added"));
591
592done:
593 mutt_file_fclose(&fp_alias);
594 buf_pool_release(&buf);
595 buf_pool_release(&fixed);
596 buf_pool_release(&prompt);
597 buf_pool_release(&tmp);
598}
599
605bool mutt_addr_is_user(const struct Address *addr)
606{
607 if (!addr)
608 {
609 mutt_debug(LL_DEBUG5, "no, NULL address\n");
610 return false;
611 }
612 if (!addr->mailbox)
613 {
614 mutt_debug(LL_DEBUG5, "no, no mailbox\n");
615 return false;
616 }
617
619 {
620 mutt_debug(LL_DEBUG5, "#1 yes, %s = %s\n", buf_string(addr->mailbox), Username);
621 return true;
622 }
624 {
625 mutt_debug(LL_DEBUG5, "#2 yes, %s = %s @ %s\n", buf_string(addr->mailbox),
627 return true;
628 }
629 const char *fqdn = mutt_fqdn(false, NeoMutt->sub);
630 if (string_is_address(buf_string(addr->mailbox), Username, fqdn))
631 {
632 mutt_debug(LL_DEBUG5, "#3 yes, %s = %s @ %s\n", buf_string(addr->mailbox),
633 Username, NONULL(fqdn));
634 return true;
635 }
636 fqdn = mutt_fqdn(true, NeoMutt->sub);
637 if (string_is_address(buf_string(addr->mailbox), Username, fqdn))
638 {
639 mutt_debug(LL_DEBUG5, "#4 yes, %s = %s @ %s\n", buf_string(addr->mailbox),
640 Username, NONULL(fqdn));
641 return true;
642 }
643
644 const struct Address *c_from = cs_subset_address(NeoMutt->sub, "from");
645 if (c_from && mutt_istr_equal(buf_string(c_from->mailbox), buf_string(addr->mailbox)))
646 {
647 mutt_debug(LL_DEBUG5, "#5 yes, %s = %s\n", buf_string(addr->mailbox),
648 buf_string(c_from->mailbox));
649 return true;
650 }
651
653 return true;
654
655 mutt_debug(LL_DEBUG5, "no, all failed\n");
656 return false;
657}
658
665struct Alias *alias_new(void)
666{
667 struct Alias *a = mutt_mem_calloc(1, sizeof(struct Alias));
668 TAILQ_INIT(&a->addr);
669 STAILQ_INIT(&a->tags);
670 return a;
671}
672
677void alias_free(struct Alias **ptr)
678{
679 if (!ptr || !*ptr)
680 return;
681
682 struct Alias *alias = *ptr;
683
684 mutt_debug(LL_NOTIFY, "NT_ALIAS_DELETE: %s\n", alias->name);
685 struct EventAlias ev_a = { alias };
687
688 FREE(&alias->name);
689 FREE(&alias->comment);
692
693 FREE(ptr);
694}
695
702void aliaslist_clear(struct AliasList *al)
703{
704 if (!al)
705 return;
706
707 struct Alias *np = NULL, *tmp = NULL;
708 TAILQ_FOREACH_SAFE(np, al, entries, tmp)
709 {
710 TAILQ_REMOVE(al, np, entries);
711 alias_free(&np);
712 }
713 TAILQ_INIT(al);
714}
715
719void alias_init(void)
720{
722}
723
728{
729 struct Alias *np = NULL;
730 TAILQ_FOREACH(np, &Aliases, entries)
731 {
733 }
736}
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:1464
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:1382
size_t mutt_addrlist_write(const struct AddressList *al, struct Buffer *buf, bool display)
Write an Address to a buffer.
Definition: address.c:1210
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:1297
void mutt_addrlist_dedupe(struct AddressList *al)
Remove duplicate addresses.
Definition: address.c:1401
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
void alias_cleanup(void)
Clean up the Alias globals.
Definition: alias.c:727
void alias_free(struct Alias **ptr)
Free an Alias.
Definition: alias.c:677
struct AliasList Aliases
List of all the user's email aliases.
Definition: alias.c:62
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:263
static int check_alias_name(const char *s, char *dest, size_t destlen)
Sanity-check an alias name.
Definition: alias.c:217
struct AddressList * alias_lookup(const char *name)
Find an Alias.
Definition: alias.c:282
void mutt_expand_aliases(struct AddressList *al)
Expand aliases in a List of Addresses.
Definition: alias.c:300
static void recode_buf(struct Buffer *buf)
Convert some text between two character sets.
Definition: alias.c:192
void alias_create(struct AddressList *al, const struct ConfigSubset *sub)
Create a new Alias from an Address.
Definition: alias.c:372
bool mutt_addr_is_user(const struct Address *addr)
Does the address belong to the user.
Definition: alias.c:605
void alias_init(void)
Set up the Alias globals.
Definition: alias.c:719
struct Alias * alias_new(void)
Create a new Alias.
Definition: alias.c:665
void mutt_expand_aliases_env(struct Envelope *env)
Expand aliases in all the fields of an Envelope.
Definition: alias.c:314
struct AddressList * mutt_get_address(struct Envelope *env, const char **prefix)
Get an Address from an Envelope.
Definition: alias.c:332
void aliaslist_clear(struct AliasList *al)
Empty a List of Aliases.
Definition: alias.c:702
static void write_safe_address(FILE *fp, const char *s)
Defang malicious email addresses.
Definition: alias.c:88
static void expand_aliases_r(struct AddressList *al, struct ListHead *expn)
Expand aliases, recursively.
Definition: alias.c:106
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:153
Select a Mailbox from a list.
int buf_printf(struct Buffer *buf, const char *fmt,...)
Format a string overwriting a Buffer.
Definition: buffer.c:178
int buf_add_printf(struct Buffer *buf, const char *fmt,...)
Format a string appending a Buffer.
Definition: buffer.c:221
void buf_reset(struct Buffer *buf)
Reset an existing Buffer.
Definition: buffer.c:93
bool buf_is_empty(const struct Buffer *buf)
Is the Buffer empty?
Definition: buffer.c:308
struct Buffer * buf_new(const char *str)
Allocate a new Buffer.
Definition: buffer.c:321
size_t buf_addstr(struct Buffer *buf, const char *s)
Add a string to a Buffer.
Definition: buffer.c:243
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:672
size_t buf_strcpy(struct Buffer *buf, const char *s)
Copy a string into a Buffer.
Definition: buffer.c:412
size_t buf_copy(struct Buffer *dst, const struct Buffer *src)
Copy a Buffer's contents to another Buffer.
Definition: buffer.c:618
char * buf_strdup(const struct Buffer *buf)
Copy a Buffer's string.
Definition: buffer.c:588
static const char * buf_string(const struct Buffer *buf)
Convert a buffer to a const char * "string".
Definition: buffer.h:97
const char * cs_subset_string(const struct ConfigSubset *sub, const char *name)
Get a string config item by name.
Definition: helpers.c:292
const char * cs_subset_path(const struct ConfigSubset *sub, const char *name)
Get a path config item by name.
Definition: helpers.c:169
bool cs_subset_bool(const struct ConfigSubset *sub, const char *name)
Get a boolean config item by name.
Definition: helpers.c:48
Convenience wrapper for the config headers.
const char * cc_charset(void)
Get the cached value of $charset.
Definition: config_cache.c:116
const struct Address * cs_subset_address(const struct ConfigSubset *sub, const char *name)
Get an Address config item by name.
Definition: config_type.c:264
Convenience wrapper for the core headers.
void mutt_beep(bool force)
Irritate the user.
Definition: curs_lib.c:68
Edit a string.
Structs that make up an email.
size_t mutt_file_quote_filename(const char *filename, char *buf, size_t buflen)
Quote a filename to survive the shell's quoting rules.
Definition: file.c:929
bool mutt_file_seek(FILE *fp, LOFF_T offset, int whence)
Wrapper for fseeko with error handling.
Definition: file.c:771
int mutt_file_fsync_close(FILE **fp)
Flush the data, before closing a file (and NULL the pointer)
Definition: file.c:188
#define mutt_file_fclose(FP)
Definition: file.h:148
#define mutt_file_fopen(PATH, MODE)
Definition: file.h:147
char * ShortHostname
Short version of the hostname.
Definition: globals.c:39
char * Username
User's login name.
Definition: globals.c:41
bool mutt_is_mail_list(const struct Address *addr)
Is this the email address of a mailing list? - Implements addr_predicate_t -.
Definition: maillist.c:45
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:274
#define mutt_error(...)
Definition: logging2.h:92
#define mutt_message(...)
Definition: logging2.h:91
#define mutt_debug(LEVEL,...)
Definition: logging2.h:89
#define mutt_perror(...)
Definition: logging2.h:93
Convenience wrapper for the gui headers.
Read/write command history from/to a file.
@ HC_FILE
Files.
Definition: lib.h:54
@ HC_OTHER
Miscellaneous strings.
Definition: lib.h:56
struct ListNode * mutt_list_insert_head(struct ListHead *h, char *s)
Insert a string at the beginning of a List.
Definition: list.c:45
void mutt_list_free(struct ListHead *h)
Free a List AND its strings.
Definition: list.c:122
@ LL_DEBUG5
Log at debug level 5.
Definition: logging2.h:47
@ LL_DEBUG1
Log at debug level 1.
Definition: logging2.h:43
@ LL_NOTIFY
Log of notifications.
Definition: logging2.h:48
Handle mailing lists.
void * mutt_mem_calloc(size_t nmemb, size_t size)
Allocate zeroed memory on the heap.
Definition: memory.c:50
#define FREE(x)
Definition: memory.h:45
int mutt_ch_convert_string(char **ps, const char *from, const char *to, uint8_t flags)
Convert a string between encodings.
Definition: charset.c:830
#define ICONV_BUF_TOO_SMALL
Error value for iconv() - Buffer too small.
Definition: charset.h:106
#define MUTT_ICONV_NO_FLAGS
No flags are set.
Definition: charset.h:72
#define ICONV_ILLEGAL_SEQ
Error value for iconv() - Illegal sequence.
Definition: charset.h:104
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:721
bool mutt_str_equal(const char *a, const char *b)
Compare two strings.
Definition: string.c:709
char * mutt_str_replace(char **p, const char *s)
Replace one string with another.
Definition: string.c:329
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:370
char * mutt_expand_path(char *buf, size_t buflen)
Create the canonical path.
Definition: muttlib.c:126
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:81
void buf_pool_release(struct Buffer **ptr)
Return a Buffer to the pool.
Definition: pool.c:94
@ 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:334
#define TAILQ_FOREACH(var, head, field)
Definition: queue.h:725
#define TAILQ_FOREACH_SAFE(var, head, field, tvar)
Definition: queue.h:735
#define STAILQ_INIT(head)
Definition: queue.h:372
#define STAILQ_HEAD_INITIALIZER(head)
Definition: queue.h:324
#define STAILQ_FIRST(head)
Definition: queue.h:350
#define TAILQ_INIT(head)
Definition: queue.h:765
#define TAILQ_INSERT_TAIL(head, elm, field)
Definition: queue.h:809
#define TAILQ_PREV(elm, headname, field)
Definition: queue.h:834
#define STAILQ_FOREACH(var, head, field)
Definition: queue.h:352
#define TAILQ_FIRST(head)
Definition: queue.h:723
#define TAILQ_REMOVE(head, elm, field)
Definition: queue.h:841
#define TAILQ_NEXT(elm, field)
Definition: queue.h:832
#define TAILQ_HEAD_INITIALIZER(head)
Definition: queue.h:637
#define TAILQ_EMPTY(head)
Definition: queue.h:721
#define TAILQ_INSERT_BEFORE(listelm, elm, field)
Definition: queue.h:786
#define STAILQ_NEXT(elm, field)
Definition: queue.h:400
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
Key value store.
#define NONULL(x)
Definition: string2.h:37
An email address.
Definition: address.h:36
struct Buffer * personal
Real name of address.
Definition: address.h:37
bool group
Group mailbox?
Definition: address.h:39
struct Buffer * mailbox
Mailbox and host address.
Definition: address.h:38
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
size_t dsize
Length of data.
Definition: buffer.h:39
char * data
Pointer to data.
Definition: buffer.h:37
A set of inherited config items.
Definition: subset.h:47
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:40
A List node for strings.
Definition: list.h:35
char * data
String.
Definition: list.h:36
Container for Accounts, Notifications.
Definition: neomutt.h:41
struct Notify * notify
Notifications handler.
Definition: neomutt.h:42
struct ConfigSubset * sub
Inherited config items.
Definition: neomutt.h:45
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