NeoMutt  2021-02-05-89-gabe350
Teaching an old dog new tricks
DOXYGEN
hook.c File Reference
#include "config.h"
#include <limits.h>
#include <stdbool.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include "mutt/lib.h"
#include "address/lib.h"
#include "email/lib.h"
#include "alias/lib.h"
#include "mutt.h"
#include "hook.h"
#include "ncrypt/lib.h"
#include "pattern/lib.h"
#include "context.h"
#include "format_flags.h"
#include "hdrline.h"
#include "init.h"
#include "mutt_attach.h"
#include "mutt_commands.h"
#include "mutt_globals.h"
#include "muttlib.h"
#include "mx.h"
#include "compmbox/lib.h"
+ Include dependency graph for hook.c:

Go to the source code of this file.

Data Structures

struct  Hook
 A list of user hooks. More...
 

Functions

 TAILQ_HEAD (HookList, Hook)
 
enum CommandResult mutt_parse_hook (struct Buffer *buf, struct Buffer *s, intptr_t data, struct Buffer *err)
 Parse the 'hook' family of commands - Implements Command::parse() More...
 
static void delete_hook (struct Hook *h)
 Delete a Hook. More...
 
void mutt_delete_hooks (HookFlags type)
 Delete matching hooks. More...
 
static void delete_idxfmt_hooklist (int type, void *obj, intptr_t data)
 Delete a index-format-hook from the Hash Table - Implements hash_hdata_free_t. More...
 
static void delete_idxfmt_hooks (void)
 Delete all the index-format-hooks. More...
 
enum CommandResult mutt_parse_idxfmt_hook (struct Buffer *buf, struct Buffer *s, intptr_t data, struct Buffer *err)
 Parse the 'index-format-hook' command - Implements Command::parse() More...
 
enum CommandResult mutt_parse_unhook (struct Buffer *buf, struct Buffer *s, intptr_t data, struct Buffer *err)
 Parse the 'unhook' command - Implements Command::parse() More...
 
void mutt_folder_hook (const char *path, const char *desc)
 Perform a folder hook. More...
 
char * mutt_find_hook (HookFlags type, const char *pat)
 Find a matching hook. More...
 
void mutt_message_hook (struct Mailbox *m, struct Email *e, HookFlags type)
 Perform a message hook. More...
 
static int addr_hook (char *path, size_t pathlen, HookFlags type, struct Context *ctx, struct Email *e)
 Perform an address hook (get a path) More...
 
void mutt_default_save (char *path, size_t pathlen, struct Email *e)
 Find the default save path for an email. More...
 
void mutt_select_fcc (struct Buffer *path, struct Email *e)
 Select the FCC path for an email. More...
 
static void list_hook (struct ListHead *matches, const char *match, HookFlags hook)
 Find hook strings matching. More...
 
void mutt_crypt_hook (struct ListHead *list, struct Address *addr)
 Find crypto hooks for an Address. More...
 
void mutt_account_hook (const char *url)
 Perform an account hook. More...
 
void mutt_timeout_hook (void)
 Execute any timeout hooks. More...
 
void mutt_startup_shutdown_hook (HookFlags type)
 Execute any startup/shutdown hooks. More...
 
const char * mutt_idxfmt_hook (const char *name, struct Mailbox *m, struct Email *e)
 Get index-format-hook format string. More...
 

Variables

char * C_DefaultHook
 Config: Pattern to use for hooks that only have a simple regex. More...
 
bool C_ForceName
 Config: Save outgoing mail in a folder of their name. More...
 
bool C_SaveName
 Config: Save outgoing message to mailbox of recipient's name if it exists. More...
 
static struct HookList Hooks = TAILQ_HEAD_INITIALIZER(Hooks)
 
static struct HashTableIdxFmtHooks = NULL
 
static HookFlags current_hook_type = MUTT_HOOK_NO_FLAGS
 

Detailed Description

Parse and execute user-defined hooks

Authors
  • Michael R. Elkins, and others
  • Pietro Cerutti

This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.

You should have received a copy of the GNU General Public License along with this program. If not, see http://www.gnu.org/licenses/.

Definition in file hook.c.

Function Documentation

◆ TAILQ_HEAD()

TAILQ_HEAD ( HookList  ,
Hook   
)

◆ mutt_parse_hook()

enum CommandResult mutt_parse_hook ( struct Buffer buf,
struct Buffer s,
intptr_t  data,
struct Buffer err 
)

Parse the 'hook' family of commands - Implements Command::parse()

This is used by 'account-hook', 'append-hook' and many more.

Definition at line 85 of file hook.c.

87 {
88  struct Hook *hook = NULL;
89  int rc = MUTT_CMD_ERROR;
90  bool pat_not = false;
91  regex_t *rx = NULL;
92  struct PatternList *pat = NULL;
93 
94  struct Buffer *cmd = mutt_buffer_pool_get();
95  struct Buffer *pattern = mutt_buffer_pool_get();
96 
97  if (~data & MUTT_GLOBAL_HOOK) /* NOT a global hook */
98  {
99  if (*s->dptr == '!')
100  {
101  s->dptr++;
102  SKIPWS(s->dptr);
103  pat_not = true;
104  }
105 
107 
108  if (!MoreArgs(s))
109  {
110  mutt_buffer_printf(err, _("%s: too few arguments"), buf->data);
111  rc = MUTT_CMD_WARNING;
112  goto cleanup;
113  }
114  }
115 
116  mutt_extract_token(cmd, s,
121 
122  if (mutt_buffer_is_empty(cmd))
123  {
124  mutt_buffer_printf(err, _("%s: too few arguments"), buf->data);
125  rc = MUTT_CMD_WARNING;
126  goto cleanup;
127  }
128 
129  if (MoreArgs(s))
130  {
131  mutt_buffer_printf(err, _("%s: too many arguments"), buf->data);
132  rc = MUTT_CMD_WARNING;
133  goto cleanup;
134  }
135 
137  {
138  /* Accidentally using the ^ mailbox shortcut in the .neomuttrc is a
139  * common mistake */
140  if ((pattern->data[0] == '^') && !CurrentFolder)
141  {
142  mutt_buffer_strcpy(err, _("current mailbox shortcut '^' is unset"));
143  goto cleanup;
144  }
145 
146  struct Buffer *tmp = mutt_buffer_pool_get();
147  mutt_buffer_copy(tmp, pattern);
149 
150  /* Check for other mailbox shortcuts that expand to the empty string.
151  * This is likely a mistake too */
152  if (mutt_buffer_is_empty(tmp) && !mutt_buffer_is_empty(pattern))
153  {
154  mutt_buffer_strcpy(err, _("mailbox shortcut expanded to empty regex"));
156  goto cleanup;
157  }
158 
159  mutt_buffer_copy(pattern, tmp);
161  }
162 #ifdef USE_COMP_MBOX
164  {
166  {
167  mutt_buffer_strcpy(err, _("badly formatted command string"));
168  goto cleanup;
169  }
170  }
171 #endif
172  else if (C_DefaultHook && (~data & MUTT_GLOBAL_HOOK) &&
174  (!WithCrypto || !(data & MUTT_CRYPT_HOOK)))
175  {
176  /* At this stage remain only message-hooks, reply-hooks, send-hooks,
177  * send2-hooks, save-hooks, and fcc-hooks: All those allowing full
178  * patterns. If given a simple regex, we expand $default_hook. */
180  }
181 
183  {
185  }
186 
187  /* check to make sure that a matching hook doesn't already exist */
188  TAILQ_FOREACH(hook, &Hooks, entries)
189  {
190  if (data & MUTT_GLOBAL_HOOK)
191  {
192  /* Ignore duplicate global hooks */
193  if (mutt_str_equal(hook->command, mutt_buffer_string(cmd)))
194  {
195  rc = MUTT_CMD_SUCCESS;
196  goto cleanup;
197  }
198  }
199  else if ((hook->type == data) && (hook->regex.pat_not == pat_not) &&
201  {
205  {
206  /* these hooks allow multiple commands with the same
207  * pattern, so if we've already seen this pattern/command pair, just
208  * ignore it instead of creating a duplicate */
209  if (mutt_str_equal(hook->command, mutt_buffer_string(cmd)))
210  {
211  rc = MUTT_CMD_SUCCESS;
212  goto cleanup;
213  }
214  }
215  else
216  {
217  /* other hooks only allow one command per pattern, so update the
218  * entry with the new command. this currently does not change the
219  * order of execution of the hooks, which i think is desirable since
220  * a common action to perform is to change the default (.) entry
221  * based upon some other information. */
222  FREE(&hook->command);
223  hook->command = mutt_buffer_strdup(cmd);
224  rc = MUTT_CMD_SUCCESS;
225  goto cleanup;
226  }
227  }
228  }
229 
231  {
232  /* These are managed separately by the charset code */
234  if (mutt_ch_lookup_add(type, mutt_buffer_string(pattern), mutt_buffer_string(cmd), err))
235  rc = MUTT_CMD_SUCCESS;
236  goto cleanup;
237  }
240  {
241  PatternCompFlags comp_flags;
242 
243  if (data & (MUTT_SEND2_HOOK))
244  comp_flags = MUTT_PC_SEND_MODE_SEARCH;
245  else if (data & (MUTT_SEND_HOOK | MUTT_FCC_HOOK))
246  comp_flags = MUTT_PC_NO_FLAGS;
247  else
248  comp_flags = MUTT_PC_FULL_MSG;
249 
250  pat = mutt_pattern_comp(Context, mutt_buffer_string(pattern), comp_flags, err);
251  if (!pat)
252  goto cleanup;
253  }
254  else if (~data & MUTT_GLOBAL_HOOK) /* NOT a global hook */
255  {
256  /* Hooks not allowing full patterns: Check syntax of regex */
257  rx = mutt_mem_malloc(sizeof(regex_t));
258  int rc2 = REG_COMP(rx, NONULL(mutt_buffer_string(pattern)),
259  ((data & MUTT_CRYPT_HOOK) ? REG_ICASE : 0));
260  if (rc2 != 0)
261  {
262  regerror(rc2, rx, err->data, err->dsize);
263  FREE(&rx);
264  goto cleanup;
265  }
266  }
267 
268  hook = mutt_mem_calloc(1, sizeof(struct Hook));
269  hook->type = data;
270  hook->command = mutt_buffer_strdup(cmd);
271  hook->pattern = pat;
272  hook->regex.pattern = mutt_buffer_strdup(pattern);
273  hook->regex.regex = rx;
274  hook->regex.pat_not = pat_not;
275  TAILQ_INSERT_TAIL(&Hooks, hook, entries);
276  rc = MUTT_CMD_SUCCESS;
277 
278 cleanup:
280  mutt_buffer_pool_release(&pattern);
281  return rc;
282 }
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ delete_hook()

static void delete_hook ( struct Hook h)
static

Delete a Hook.

Parameters
hHook to delete

Definition at line 288 of file hook.c.

289 {
290  FREE(&h->command);
291  FREE(&h->regex.pattern);
292  if (h->regex.regex)
293  {
294  regfree(h->regex.regex);
295  FREE(&h->regex.regex);
296  }
298  FREE(&h);
299 }
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mutt_delete_hooks()

void mutt_delete_hooks ( HookFlags  type)

Delete matching hooks.

Parameters
typeHook type to delete, see HookFlags

If 0 is passed, all the hooks will be deleted.

Definition at line 307 of file hook.c.

308 {
309  struct Hook *h = NULL;
310  struct Hook *tmp = NULL;
311 
312  TAILQ_FOREACH_SAFE(h, &Hooks, entries, tmp)
313  {
314  if ((type == MUTT_HOOK_NO_FLAGS) || (type == h->type))
315  {
316  TAILQ_REMOVE(&Hooks, h, entries);
317  delete_hook(h);
318  }
319  }
320 }
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ delete_idxfmt_hooklist()

static void delete_idxfmt_hooklist ( int  type,
void *  obj,
intptr_t  data 
)
static

Delete a index-format-hook from the Hash Table - Implements hash_hdata_free_t.

Definition at line 325 of file hook.c.

326 {
327  struct HookList *hl = obj;
328  struct Hook *h = NULL;
329  struct Hook *tmp = NULL;
330 
331  TAILQ_FOREACH_SAFE(h, hl, entries, tmp)
332  {
333  TAILQ_REMOVE(hl, h, entries);
334  delete_hook(h);
335  }
336 
337  FREE(&hl);
338 }
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ delete_idxfmt_hooks()

static void delete_idxfmt_hooks ( void  )
static

Delete all the index-format-hooks.

Definition at line 343 of file hook.c.

344 {
346 }
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mutt_parse_idxfmt_hook()

enum CommandResult mutt_parse_idxfmt_hook ( struct Buffer buf,
struct Buffer s,
intptr_t  data,
struct Buffer err 
)

Parse the 'index-format-hook' command - Implements Command::parse()

Definition at line 351 of file hook.c.

353 {
354  enum CommandResult rc = MUTT_CMD_ERROR;
355  bool pat_not = false;
356 
357  struct Buffer *name = mutt_buffer_pool_get();
358  struct Buffer *pattern = mutt_buffer_pool_get();
359  struct Buffer *fmtstring = mutt_buffer_pool_get();
360 
361  if (!IdxFmtHooks)
362  {
365  }
366 
367  if (!MoreArgs(s))
368  {
369  mutt_buffer_printf(err, _("%s: too few arguments"), buf->data);
370  goto out;
371  }
373  struct HookList *hl = mutt_hash_find(IdxFmtHooks, mutt_buffer_string(name));
374 
375  if (*s->dptr == '!')
376  {
377  s->dptr++;
378  SKIPWS(s->dptr);
379  pat_not = true;
380  }
382 
383  if (!MoreArgs(s))
384  {
385  mutt_buffer_printf(err, _("%s: too few arguments"), buf->data);
386  goto out;
387  }
389 
390  if (MoreArgs(s))
391  {
392  mutt_buffer_printf(err, _("%s: too many arguments"), buf->data);
393  goto out;
394  }
395 
396  if (C_DefaultHook)
398 
399  /* check to make sure that a matching hook doesn't already exist */
400  struct Hook *hook = NULL;
401  if (hl)
402  {
403  TAILQ_FOREACH(hook, hl, entries)
404  {
405  if ((hook->regex.pat_not == pat_not) &&
407  {
408  mutt_str_replace(&hook->command, mutt_buffer_string(fmtstring));
409  rc = MUTT_CMD_SUCCESS;
410  goto out;
411  }
412  }
413  }
414 
415  /* MUTT_PC_PATTERN_DYNAMIC sets so that date ranges are regenerated during
416  * matching. This of course is slower, but index-format-hook is commonly
417  * used for date ranges, and they need to be evaluated relative to "now", not
418  * the hook compilation time. */
419  struct PatternList *pat =
422  if (!pat)
423  goto out;
424 
425  hook = mutt_mem_calloc(1, sizeof(struct Hook));
426  hook->type = MUTT_IDXFMTHOOK;
427  hook->command = mutt_buffer_strdup(fmtstring);
428  hook->pattern = pat;
429  hook->regex.pattern = mutt_buffer_strdup(pattern);
430  hook->regex.regex = NULL;
431  hook->regex.pat_not = pat_not;
432 
433  if (!hl)
434  {
435  hl = mutt_mem_calloc(1, sizeof(*hl));
436  TAILQ_INIT(hl);
438  }
439 
440  TAILQ_INSERT_TAIL(hl, hook, entries);
441  rc = MUTT_CMD_SUCCESS;
442 
443 out:
445  mutt_buffer_pool_release(&pattern);
446  mutt_buffer_pool_release(&fmtstring);
447 
448  return rc;
449 }
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mutt_parse_unhook()

enum CommandResult mutt_parse_unhook ( struct Buffer buf,
struct Buffer s,
intptr_t  data,
struct Buffer err 
)

Parse the 'unhook' command - Implements Command::parse()

Definition at line 454 of file hook.c.

456 {
457  while (MoreArgs(s))
458  {
460  if (mutt_str_equal("*", buf->data))
461  {
463  {
464  mutt_buffer_printf(err, "%s", _("unhook: Can't do unhook * from within a hook"));
465  return MUTT_CMD_WARNING;
466  }
470  }
471  else
472  {
473  HookFlags type = mutt_get_hook_type(buf->data);
474 
475  if (type == MUTT_HOOK_NO_FLAGS)
476  {
477  mutt_buffer_printf(err, _("unhook: unknown hook type: %s"), buf->data);
478  return MUTT_CMD_ERROR;
479  }
480  if (type & (MUTT_CHARSET_HOOK | MUTT_ICONV_HOOK))
481  {
483  return MUTT_CMD_SUCCESS;
484  }
485  if (current_hook_type == type)
486  {
487  mutt_buffer_printf(err, _("unhook: Can't delete a %s from within a %s"),
488  buf->data, buf->data);
489  return MUTT_CMD_WARNING;
490  }
491  if (type == MUTT_IDXFMTHOOK)
493  else
494  mutt_delete_hooks(type);
495  }
496  }
497  return MUTT_CMD_SUCCESS;
498 }
+ Here is the call graph for this function:

◆ mutt_folder_hook()

void mutt_folder_hook ( const char *  path,
const char *  desc 
)

Perform a folder hook.

Parameters
pathPath to potentially match
descDescription to potentially match

Definition at line 505 of file hook.c.

506 {
507  if (!path && !desc)
508  return;
509 
510  struct Hook *hook = NULL;
511  struct Buffer *err = mutt_buffer_pool_get();
512 
514 
515  TAILQ_FOREACH(hook, &Hooks, entries)
516  {
517  if (!hook->command)
518  continue;
519 
520  if (!(hook->type & MUTT_FOLDER_HOOK))
521  continue;
522 
523  const char *match = NULL;
524  if (mutt_regex_match(&hook->regex, path))
525  match = path;
526  else if (mutt_regex_match(&hook->regex, desc))
527  match = desc;
528 
529  if (match)
530  {
531  mutt_debug(LL_DEBUG1, "folder-hook '%s' matches '%s'\n", hook->regex.pattern, match);
532  mutt_debug(LL_DEBUG5, " %s\n", hook->command);
533  if (mutt_parse_rc_line(hook->command, err) == MUTT_CMD_ERROR)
534  {
535  mutt_error("%s", mutt_buffer_string(err));
536  break;
537  }
538  }
539  }
541 
543 }
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mutt_find_hook()

char* mutt_find_hook ( HookFlags  type,
const char *  pat 
)

Find a matching hook.

Parameters
typeHook type, see HookFlags
patPattern to match
Return values
ptrCommand string
Note
The returned string must not be freed.

Definition at line 553 of file hook.c.

554 {
555  struct Hook *tmp = NULL;
556 
557  TAILQ_FOREACH(tmp, &Hooks, entries)
558  {
559  if (tmp->type & type)
560  {
561  if (mutt_regex_match(&tmp->regex, pat))
562  return tmp->command;
563  }
564  }
565  return NULL;
566 }
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mutt_message_hook()

void mutt_message_hook ( struct Mailbox m,
struct Email e,
HookFlags  type 
)

Perform a message hook.

Parameters
mMailbox Context
eEmail
typeHook type, see HookFlags

Definition at line 574 of file hook.c.

575 {
576  struct Hook *hook = NULL;
577  struct PatternCache cache = { 0 };
578  struct Buffer *err = mutt_buffer_pool_get();
579 
580  current_hook_type = type;
581 
582  TAILQ_FOREACH(hook, &Hooks, entries)
583  {
584  if (!hook->command)
585  continue;
586 
587  if (hook->type & type)
588  {
589  if ((mutt_pattern_exec(SLIST_FIRST(hook->pattern), 0, m, e, &cache) > 0) ^
590  hook->regex.pat_not)
591  {
592  if (mutt_parse_rc_line(hook->command, err) == MUTT_CMD_ERROR)
593  {
594  mutt_error("%s", mutt_buffer_string(err));
597 
598  return;
599  }
600  /* Executing arbitrary commands could affect the pattern results,
601  * so the cache has to be wiped */
602  memset(&cache, 0, sizeof(cache));
603  }
604  }
605  }
607 
609 }
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ addr_hook()

static int addr_hook ( char *  path,
size_t  pathlen,
HookFlags  type,
struct Context ctx,
struct Email e 
)
static

Perform an address hook (get a path)

Parameters
pathBuffer for path
pathlenLength of buffer
typeHook type, see HookFlags
ctxMailbox Context
eEmail
Return values
0Success
-1Failure

Definition at line 621 of file hook.c.

623 {
624  struct Hook *hook = NULL;
625  struct PatternCache cache = { 0 };
626 
627  /* determine if a matching hook exists */
628  TAILQ_FOREACH(hook, &Hooks, entries)
629  {
630  if (!hook->command)
631  continue;
632 
633  if (hook->type & type)
634  {
635  struct Mailbox *m = ctx ? ctx->mailbox : NULL;
636  if ((mutt_pattern_exec(SLIST_FIRST(hook->pattern), 0, m, e, &cache) > 0) ^
637  hook->regex.pat_not)
638  {
639  mutt_make_string(path, pathlen, 0, hook->command, m,
640  ctx ? ctx->msg_in_pager : -1, e, MUTT_FORMAT_PLAIN, NULL);
641  return 0;
642  }
643  }
644  }
645 
646  return -1;
647 }
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mutt_default_save()

void mutt_default_save ( char *  path,
size_t  pathlen,
struct Email e 
)

Find the default save path for an email.

Parameters
pathBuffer for the path
pathlenLength of buffer
eEmail

Definition at line 655 of file hook.c.

656 {
657  *path = '\0';
658  if (addr_hook(path, pathlen, MUTT_SAVE_HOOK, Context, e) == 0)
659  return;
660 
661  struct Envelope *env = e->env;
662  const struct Address *from = TAILQ_FIRST(&env->from);
663  const struct Address *reply_to = TAILQ_FIRST(&env->reply_to);
664  const struct Address *to = TAILQ_FIRST(&env->to);
665  const struct Address *cc = TAILQ_FIRST(&env->cc);
666  const struct Address *addr = NULL;
667  bool from_me = mutt_addr_is_user(from);
668 
669  if (!from_me && reply_to && reply_to->mailbox)
670  addr = reply_to;
671  else if (!from_me && from && from->mailbox)
672  addr = from;
673  else if (to && to->mailbox)
674  addr = to;
675  else if (cc && cc->mailbox)
676  addr = cc;
677  else
678  addr = NULL;
679  if (addr)
680  {
681  struct Buffer *tmp = mutt_buffer_pool_get();
682  mutt_safe_path(tmp, addr);
683  snprintf(path, pathlen, "=%s", mutt_buffer_string(tmp));
685  }
686 }
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mutt_select_fcc()

void mutt_select_fcc ( struct Buffer path,
struct Email e 
)

Select the FCC path for an email.

Parameters
pathBuffer for the path
eEmail

Definition at line 693 of file hook.c.

694 {
696 
697  if (addr_hook(path->data, path->dsize, MUTT_FCC_HOOK, NULL, e) != 0)
698  {
699  const struct Address *to = TAILQ_FIRST(&e->env->to);
700  const struct Address *cc = TAILQ_FIRST(&e->env->cc);
701  const struct Address *bcc = TAILQ_FIRST(&e->env->bcc);
702  if ((C_SaveName || C_ForceName) && (to || cc || bcc))
703  {
704  const struct Address *addr = to ? to : (cc ? cc : bcc);
705  struct Buffer *buf = mutt_buffer_pool_get();
706  mutt_safe_path(buf, addr);
709  if (!C_ForceName && (mx_access(mutt_buffer_string(path), W_OK) != 0))
711  }
712  else
714  }
715  else
716  mutt_buffer_fix_dptr(path);
717 
719 }
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ list_hook()

static void list_hook ( struct ListHead *  matches,
const char *  match,
HookFlags  hook 
)
static

Find hook strings matching.

Parameters
[out]matchesList of hook strings
[in]matchString to match
[in]hookHook type, see HookFlags

Definition at line 727 of file hook.c.

728 {
729  struct Hook *tmp = NULL;
730 
731  TAILQ_FOREACH(tmp, &Hooks, entries)
732  {
733  if ((tmp->type & hook) && mutt_regex_match(&tmp->regex, match))
734  {
736  }
737  }
738 }
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mutt_crypt_hook()

void mutt_crypt_hook ( struct ListHead *  list,
struct Address addr 
)

Find crypto hooks for an Address.

Parameters
[out]listList of keys
[in]addrAddress to match

The crypt-hook associates keys with addresses.

Definition at line 747 of file hook.c.

748 {
749  list_hook(list, addr->mailbox, MUTT_CRYPT_HOOK);
750 }
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mutt_account_hook()

void mutt_account_hook ( const char *  url)

Perform an account hook.

Parameters
urlAccount URL to match

Definition at line 756 of file hook.c.

757 {
758  /* parsing commands with URLs in an account hook can cause a recursive
759  * call. We just skip processing if this occurs. Typically such commands
760  * belong in a folder-hook -- perhaps we should warn the user. */
761  static bool inhook = false;
762  if (inhook)
763  return;
764 
765  struct Hook *hook = NULL;
766  struct Buffer *err = mutt_buffer_pool_get();
767 
768  TAILQ_FOREACH(hook, &Hooks, entries)
769  {
770  if (!(hook->command && (hook->type & MUTT_ACCOUNT_HOOK)))
771  continue;
772 
773  if (mutt_regex_match(&hook->regex, url))
774  {
775  inhook = true;
776  mutt_debug(LL_DEBUG1, "account-hook '%s' matches '%s'\n", hook->regex.pattern, url);
777  mutt_debug(LL_DEBUG5, " %s\n", hook->command);
778 
779  if (mutt_parse_rc_line(hook->command, err) == MUTT_CMD_ERROR)
780  {
781  mutt_error("%s", mutt_buffer_string(err));
783 
784  inhook = false;
785  goto done;
786  }
787 
788  inhook = false;
789  }
790  }
791 done:
793 }
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mutt_timeout_hook()

void mutt_timeout_hook ( void  )

Execute any timeout hooks.

The user can configure hooks to be run on timeout. This function finds all the matching hooks and executes them.

Definition at line 801 of file hook.c.

802 {
803  struct Hook *hook = NULL;
804  struct Buffer err;
805  char buf[256];
806 
807  mutt_buffer_init(&err);
808  err.data = buf;
809  err.dsize = sizeof(buf);
810 
811  TAILQ_FOREACH(hook, &Hooks, entries)
812  {
813  if (!(hook->command && (hook->type & MUTT_TIMEOUT_HOOK)))
814  continue;
815 
816  if (mutt_parse_rc_line(hook->command, &err) == MUTT_CMD_ERROR)
817  {
818  mutt_error("%s", err.data);
819  mutt_buffer_reset(&err);
820 
821  /* The hooks should be independent of each other, so even though this on
822  * failed, we'll carry on with the others. */
823  }
824  }
825 
826  /* Delete temporary attachment files */
828 }
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mutt_startup_shutdown_hook()

void mutt_startup_shutdown_hook ( HookFlags  type)

Execute any startup/shutdown hooks.

Parameters
typeHook type: MUTT_STARTUP_HOOK or MUTT_SHUTDOWN_HOOK

The user can configure hooks to be run on startup/shutdown. This function finds all the matching hooks and executes them.

Definition at line 837 of file hook.c.

838 {
839  struct Hook *hook = NULL;
840  struct Buffer err = mutt_buffer_make(0);
841  char buf[256];
842 
843  err.data = buf;
844  err.dsize = sizeof(buf);
845 
846  TAILQ_FOREACH(hook, &Hooks, entries)
847  {
848  if (!(hook->command && (hook->type & type)))
849  continue;
850 
851  if (mutt_parse_rc_line(hook->command, &err) == MUTT_CMD_ERROR)
852  {
853  mutt_error("%s", err.data);
854  mutt_buffer_reset(&err);
855  }
856  }
857 }
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mutt_idxfmt_hook()

const char* mutt_idxfmt_hook ( const char *  name,
struct Mailbox m,
struct Email e 
)

Get index-format-hook format string.

Parameters
nameHook name
mMailbox
eEmail
Return values
ptrprintf(3)-like format string
NULLNo matching hook

Definition at line 867 of file hook.c.

868 {
869  if (!IdxFmtHooks)
870  return NULL;
871 
872  struct HookList *hl = mutt_hash_find(IdxFmtHooks, name);
873  if (!hl)
874  return NULL;
875 
877 
878  struct PatternCache cache = { 0 };
879  const char *fmtstring = NULL;
880  struct Hook *hook = NULL;
881 
882  TAILQ_FOREACH(hook, hl, entries)
883  {
884  struct Pattern *pat = SLIST_FIRST(hook->pattern);
885  if ((mutt_pattern_exec(pat, 0, m, e, &cache) > 0) ^ hook->regex.pat_not)
886  {
887  fmtstring = hook->command;
888  break;
889  }
890  }
891 
893 
894  return fmtstring;
895 }
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

Variable Documentation

◆ C_DefaultHook

char* C_DefaultHook

Config: Pattern to use for hooks that only have a simple regex.

Definition at line 58 of file hook.c.

◆ C_ForceName

bool C_ForceName

Config: Save outgoing mail in a folder of their name.

Definition at line 59 of file hook.c.

◆ C_SaveName

bool C_SaveName

Config: Save outgoing message to mailbox of recipient's name if it exists.

Definition at line 60 of file hook.c.

◆ Hooks

struct HookList Hooks = TAILQ_HEAD_INITIALIZER(Hooks)
static

Definition at line 75 of file hook.c.

◆ IdxFmtHooks

struct HashTable* IdxFmtHooks = NULL
static

Definition at line 77 of file hook.c.

◆ current_hook_type

HookFlags current_hook_type = MUTT_HOOK_NO_FLAGS
static

Definition at line 78 of file hook.c.

Envelope
The header of an Email.
Definition: envelope.h:54
IdxFmtHooks
static struct HashTable * IdxFmtHooks
Definition: hook.c:77
Envelope::bcc
struct AddressList bcc
Email's 'Bcc' list.
Definition: envelope.h:60
mutt_pattern_comp
struct PatternList * mutt_pattern_comp(struct Context *ctx, const char *s, PatternCompFlags flags, struct Buffer *err)
Create a Pattern.
Definition: compile.c:1082
Hook
A list of user hooks.
Definition: hook.c:65
mutt_parse_rc_line
enum CommandResult mutt_parse_rc_line(const char *line, struct Buffer *err)
Parse a line of user config.
Definition: init.c:1044
mutt_hash_new
struct HashTable * mutt_hash_new(size_t num_elems, HashFlags flags)
Create a new Hash Table (with string keys)
Definition: hash.c:251
TAILQ_INIT
#define TAILQ_INIT(head)
Definition: queue.h:758
mx_access
int mx_access(const char *path, int flags)
Wrapper for access, checks permissions on a given mailbox.
Definition: mx.c:189
Regex::pat_not
bool pat_not
do not match
Definition: regex3.h:93
mutt_mem_calloc
void * mutt_mem_calloc(size_t nmemb, size_t size)
Allocate zeroed memory on the heap.
Definition: memory.c:50
_
#define _(a)
Definition: message.h:28
NONULL
#define NONULL(x)
Definition: string2.h:37
Mailbox
A mailbox.
Definition: mailbox.h:81
MUTT_ICONV_HOOK
#define MUTT_ICONV_HOOK
iconv-hook: create a system charset alias
Definition: hook.h:51
mutt_make_string
void mutt_make_string(char *buf, size_t buflen, int cols, const char *s, struct Mailbox *m, int inpgr, struct Email *e, MuttFormatFlags flags, const char *progress)
Create formatted strings using mailbox expandos.
Definition: hdrline.c:1427
MUTT_SEND2_HOOK
#define MUTT_SEND2_HOOK
send2-hook: when changing fields in the compose menu
Definition: hook.h:56
mutt_pattern_free
void mutt_pattern_free(struct PatternList **pat)
Free a Pattern.
Definition: compile.c:1029
MoreArgs
#define MoreArgs(buf)
Definition: buffer.h:40
MUTT_MBOX_HOOK
#define MUTT_MBOX_HOOK
mbox-hook: move messages after reading them
Definition: hook.h:46
MUTT_PC_PATTERN_DYNAMIC
#define MUTT_PC_PATTERN_DYNAMIC
Enable runtime date range evaluation.
Definition: lib.h:66
MUTT_SAVE_HOOK
#define MUTT_SAVE_HOOK
save-hook: set a default folder when saving an email
Definition: hook.h:49
Buffer
String manipulation buffer.
Definition: buffer.h:33
mutt_hash_set_destructor
void mutt_hash_set_destructor(struct HashTable *table, hash_hdata_free_t fn, intptr_t fn_data)
Set the destructor for a Hash Table.
Definition: hash.c:293
mutt_buffer_pretty_mailbox
void mutt_buffer_pretty_mailbox(struct Buffer *buf)
Shorten a mailbox path using '~' or '='.
Definition: muttlib.c:599
C_DefaultHook
char * C_DefaultHook
Config: Pattern to use for hooks that only have a simple regex.
Definition: hook.c:58
mutt_buffer_is_empty
bool mutt_buffer_is_empty(const struct Buffer *buf)
Is the Buffer empty?
Definition: buffer.c:252
MUTT_SEND_HOOK
#define MUTT_SEND_HOOK
send-hook: when composing a new email
Definition: hook.h:47
mutt_pattern_exec
int mutt_pattern_exec(struct Pattern *pat, PatternExecFlags flags, struct Mailbox *m, struct Email *e, struct PatternCache *cache)
Match a pattern against an email header.
Definition: exec.c:738
TAILQ_FOREACH
#define TAILQ_FOREACH(var, head, field)
Definition: queue.h:718
mutt_buffer_init
struct Buffer * mutt_buffer_init(struct Buffer *buf)
Initialise a new Buffer.
Definition: buffer.c:46
Context
The "current" mailbox.
Definition: context.h:38
mutt_str_dup
char * mutt_str_dup(const char *str)
Copy a string, safely.
Definition: string.c:370
LL_DEBUG1
@ LL_DEBUG1
Log at debug level 1.
Definition: logging.h:40
FREE
#define FREE(x)
Definition: memory.h:40
TAILQ_INSERT_TAIL
#define TAILQ_INSERT_TAIL(head, elm, field)
Definition: queue.h:802
MUTT_TOKEN_NO_FLAGS
#define MUTT_TOKEN_NO_FLAGS
No flags are set.
Definition: mutt.h:70
MUTT_APPEND_HOOK
#define MUTT_APPEND_HOOK
append-hook: append to a compressed mailbox
Definition: hook.h:59
Buffer::dptr
char * dptr
Current read/write position.
Definition: buffer.h:36
mutt_comp_valid_command
int mutt_comp_valid_command(const char *cmd)
Is this command string allowed?
Definition: compress.c:405
Buffer::dsize
size_t dsize
Length of data.
Definition: buffer.h:37
LL_DEBUG5
@ LL_DEBUG5
Log at debug level 5.
Definition: logging.h:44
PATH_MAX
#define PATH_MAX
Definition: mutt.h:44
mutt_buffer_reset
void mutt_buffer_reset(struct Buffer *buf)
Reset an existing Buffer.
Definition: buffer.c:79
MUTT_OPEN_HOOK
#define MUTT_OPEN_HOOK
open-hook: to read a compressed mailbox
Definition: hook.h:58
mutt_buffer_pool_release
void mutt_buffer_pool_release(struct Buffer **pbuf)
Free a Buffer from the pool.
Definition: pool.c:112
PatternCompFlags
uint8_t PatternCompFlags
Flags for mutt_pattern_comp(), e.g. MUTT_PC_FULL_MSG.
Definition: lib.h:63
Hook::regex
struct Regex regex
Regular expression.
Definition: hook.c:68
MUTT_PC_NO_FLAGS
#define MUTT_PC_NO_FLAGS
No flags are set.
Definition: lib.h:64
MUTT_STARTUP_HOOK
#define MUTT_STARTUP_HOOK
startup-hook: run when starting NeoMutt
Definition: hook.h:64
mutt_list_insert_tail
struct ListNode * mutt_list_insert_tail(struct ListHead *h, char *s)
Append a string to the end of a List.
Definition: list.c:64
mutt_buffer_alloc
void mutt_buffer_alloc(struct Buffer *buf, size_t new_size)
Make sure a buffer can store at least new_size bytes.
Definition: buffer.c:265
mutt_get_hook_type
HookFlags mutt_get_hook_type(const char *name)
Find a hook by name.
Definition: init.c:700
Context::msg_in_pager
int msg_in_pager
Message currently shown in the pager.
Definition: context.h:44
SKIPWS
#define SKIPWS(ch)
Definition: string2.h:46
mutt_hash_find
void * mutt_hash_find(const struct HashTable *table, const char *strkey)
Find the HashElem data in a Hash Table element using a key.
Definition: hash.c:354
mutt_str_equal
bool mutt_str_equal(const char *a, const char *b)
Compare two strings.
Definition: string.c:871
delete_hook
static void delete_hook(struct Hook *h)
Delete a Hook.
Definition: hook.c:288
Envelope::reply_to
struct AddressList reply_to
Email's 'reply-to'.
Definition: envelope.h:62
mutt_buffer_expand_path_regex
void mutt_buffer_expand_path_regex(struct Buffer *buf, bool regex)
Create the canonical path (with regex char escaping)
Definition: muttlib.c:140
TAILQ_REMOVE
#define TAILQ_REMOVE(head, elm, field)
Definition: queue.h:834
mutt_extract_token
int mutt_extract_token(struct Buffer *dest, struct Buffer *tok, TokenFlags flags)
Extract one token from a string.
Definition: init.c:393
TAILQ_FIRST
#define TAILQ_FIRST(head)
Definition: queue.h:716
Envelope::cc
struct AddressList cc
Email's 'Cc' list.
Definition: envelope.h:59
MUTT_CLOSE_HOOK
#define MUTT_CLOSE_HOOK
close-hook: write to a compressed mailbox
Definition: hook.h:60
MUTT_CHARSET_HOOK
#define MUTT_CHARSET_HOOK
charset-hook: create a charset alias for malformed emails
Definition: hook.h:50
mutt_buffer_pool_get
struct Buffer * mutt_buffer_pool_get(void)
Get a Buffer from the pool.
Definition: pool.c:101
mutt_buffer_copy
size_t mutt_buffer_copy(struct Buffer *dst, const struct Buffer *src)
Copy a Buffer's contents to another Buffer.
Definition: buffer.c:445
mutt_ch_lookup_remove
void mutt_ch_lookup_remove(void)
Remove all the character set lookups.
Definition: charset.c:517
C_Folder
WHERE char * C_Folder
Config: Base folder for a set of mailboxes.
Definition: mutt_globals.h:96
Hook::command
char * command
Filename, command or pattern to execute.
Definition: hook.c:69
addr_hook
static int addr_hook(char *path, size_t pathlen, HookFlags type, struct Context *ctx, struct Email *e)
Perform an address hook (get a path)
Definition: hook.c:621
list_hook
static void list_hook(struct ListHead *matches, const char *match, HookFlags hook)
Find hook strings matching.
Definition: hook.c:727
C_SaveName
bool C_SaveName
Config: Save outgoing message to mailbox of recipient's name if it exists.
Definition: hook.c:60
mutt_hash_insert
struct HashElem * mutt_hash_insert(struct HashTable *table, const char *strkey, void *data)
Add a new element to the Hash Table (with string keys)
Definition: hash.c:327
mutt_safe_path
void mutt_safe_path(struct Buffer *dest, const struct Address *a)
Make a safe filename from an email address.
Definition: muttlib.c:755
MUTT_PC_FULL_MSG
#define MUTT_PC_FULL_MSG
Enable body and header matching.
Definition: lib.h:65
Envelope::to
struct AddressList to
Email's 'To' list.
Definition: envelope.h:58
current_hook_type
static HookFlags current_hook_type
Definition: hook.c:78
Context::mailbox
struct Mailbox * mailbox
Definition: context.h:50
mutt_buffer_concat_path
size_t mutt_buffer_concat_path(struct Buffer *buf, const char *dir, const char *fname)
Join a directory name and a filename.
Definition: buffer.c:374
Email::env
struct Envelope * env
Envelope information.
Definition: email.h:90
MUTT_FCC_HOOK
#define MUTT_FCC_HOOK
fcc-hook: to save outgoing email
Definition: hook.h:48
mutt_debug
#define mutt_debug(LEVEL,...)
Definition: logging.h:81
HookFlags
uint32_t HookFlags
Flags for mutt_parse_hook(), e.g. MUTT_FOLDER_HOOK.
Definition: hook.h:43
MUTT_LOOKUP_ICONV
@ MUTT_LOOKUP_ICONV
Character set conversion.
Definition: charset.h:70
MUTT_CMD_SUCCESS
@ MUTT_CMD_SUCCESS
Success: Command worked.
Definition: mutt_commands.h:38
REG_COMP
#define REG_COMP(preg, regex, cflags)
Compile a regular expression.
Definition: regex3.h:54
mutt_buffer_expand_path
void mutt_buffer_expand_path(struct Buffer *buf)
Create the canonical path.
Definition: muttlib.c:323
mutt_regex_match
bool mutt_regex_match(const struct Regex *regex, const char *str)
Shorthand to mutt_regex_capture()
Definition: regex.c:611
TAILQ_FOREACH_SAFE
#define TAILQ_FOREACH_SAFE(var, head, field, tvar)
Definition: queue.h:728
mutt_buffer_string
static const char * mutt_buffer_string(const struct Buffer *buf)
Convert a buffer to a const char * "string".
Definition: buffer.h:77
MUTT_FORMAT_PLAIN
#define MUTT_FORMAT_PLAIN
Do not prepend DISP_TO, DISP_CC ...
Definition: format_flags.h:38
MUTT_CMD_ERROR
@ MUTT_CMD_ERROR
Error: Can't help the user.
Definition: mutt_commands.h:36
MUTT_LOOKUP_CHARSET
@ MUTT_LOOKUP_CHARSET
Alias for another character set.
Definition: charset.h:69
SLIST_FIRST
#define SLIST_FIRST(head)
Definition: queue.h:228
mutt_check_simple
void mutt_check_simple(struct Buffer *s, const char *simple)
Convert a simple search into a real request.
Definition: pattern.c:111
mutt_str_replace
char * mutt_str_replace(char **p, const char *s)
Replace one string with another.
Definition: string.c:446
CommandResult
CommandResult
Error codes for command_t parse functions.
Definition: mutt_commands.h:34
WithCrypto
#define WithCrypto
Definition: lib.h:123
C_Record
WHERE char * C_Record
Config: Folder to save 'sent' messages.
Definition: mutt_globals.h:98
Address::mailbox
char * mailbox
Mailbox and host address.
Definition: address.h:37
MUTT_CMD_WARNING
@ MUTT_CMD_WARNING
Warning: Help given to the user.
Definition: mutt_commands.h:37
MUTT_SHUTDOWN_HOOK
#define MUTT_SHUTDOWN_HOOK
shutdown-hook: run when leaving NeoMutt
Definition: hook.h:65
Envelope::from
struct AddressList from
Email's 'From' list.
Definition: envelope.h:57
delete_idxfmt_hooks
static void delete_idxfmt_hooks(void)
Delete all the index-format-hooks.
Definition: hook.c:343
mutt_mem_malloc
void * mutt_mem_malloc(size_t size)
Allocate memory on the heap.
Definition: memory.c:90
mutt_unlink_temp_attachments
void mutt_unlink_temp_attachments(void)
Delete all temporary attachments.
Definition: mutt_attach.c:1266
MUTT_HASH_STRDUP_KEYS
#define MUTT_HASH_STRDUP_KEYS
make a copy of the keys
Definition: hash.h:99
MUTT_GLOBAL_HOOK
#define MUTT_GLOBAL_HOOK
Hooks which don't take a regex.
Definition: hook.h:66
MUTT_MESSAGE_HOOK
#define MUTT_MESSAGE_HOOK
message-hook: run before displaying a message
Definition: hook.h:52
mutt_buffer_fix_dptr
void mutt_buffer_fix_dptr(struct Buffer *buf)
Move the dptr to end of the Buffer.
Definition: buffer.c:181
Hooks
static struct HookList Hooks
Definition: hook.c:75
MUTT_PC_SEND_MODE_SEARCH
#define MUTT_PC_SEND_MODE_SEARCH
Allow send-mode body searching.
Definition: lib.h:67
Regex::regex
regex_t * regex
compiled expression
Definition: regex3.h:92
MUTT_ACCOUNT_HOOK
#define MUTT_ACCOUNT_HOOK
account-hook: when changing between accounts
Definition: hook.h:54
LookupType
LookupType
Types of character set lookups.
Definition: charset.h:67
CurrentFolder
WHERE char * CurrentFolder
Currently selected mailbox.
Definition: mutt_globals.h:54
mutt_delete_hooks
void mutt_delete_hooks(HookFlags type)
Delete matching hooks.
Definition: hook.c:307
C_ForceName
bool C_ForceName
Config: Save outgoing mail in a folder of their name.
Definition: hook.c:59
Regex::pattern
char * pattern
printable version
Definition: regex3.h:91
mutt_buffer_strdup
char * mutt_buffer_strdup(const struct Buffer *buf)
Copy a Buffer's string.
Definition: buffer.c:432
delete_idxfmt_hooklist
static void delete_idxfmt_hooklist(int type, void *obj, intptr_t data)
Delete a index-format-hook from the Hash Table - Implements hash_hdata_free_t.
Definition: hook.c:325
Buffer::data
char * data
Pointer to data.
Definition: buffer.h:35
Hook::pattern
struct PatternList * pattern
Used for fcc,save,send-hook.
Definition: hook.c:70
mutt_buffer_printf
int mutt_buffer_printf(struct Buffer *buf, const char *fmt,...)
Format a string overwriting a Buffer.
Definition: buffer.c:160
mutt_buffer_make
struct Buffer mutt_buffer_make(size_t size)
Make a new buffer on the stack.
Definition: buffer.c:61
mutt_ch_lookup_add
bool mutt_ch_lookup_add(enum LookupType type, const char *pat, const char *replace, struct Buffer *err)
Add a new character set lookup.
Definition: charset.c:485
MUTT_FOLDER_HOOK
#define MUTT_FOLDER_HOOK
folder-hook: when entering a mailbox
Definition: hook.h:45
mutt_buffer_strcpy
size_t mutt_buffer_strcpy(struct Buffer *buf, const char *s)
Copy a string into a Buffer.
Definition: buffer.c:312
MUTT_CRYPT_HOOK
#define MUTT_CRYPT_HOOK
crypt-hook: automatically select a PGP/SMIME key
Definition: hook.h:53
MUTT_REPLY_HOOK
#define MUTT_REPLY_HOOK
reply-hook: when replying to an email
Definition: hook.h:55
Pattern
A simple (non-regex) pattern.
Definition: lib.h:72
mutt_hash_free
void mutt_hash_free(struct HashTable **ptr)
Free a hash table.
Definition: hash.c:447
MUTT_TOKEN_SPACE
#define MUTT_TOKEN_SPACE
Don't treat whitespace as a term.
Definition: mutt.h:73
MUTT_TIMEOUT_HOOK
#define MUTT_TIMEOUT_HOOK
timeout-hook: run a command periodically
Definition: hook.h:63
mutt_addr_is_user
bool mutt_addr_is_user(const struct Address *addr)
Does the address belong to the user.
Definition: alias.c:556
Address
An email address.
Definition: address.h:34
PatternCache
Cache commonly-used patterns.
Definition: lib.h:109
MUTT_HOOK_NO_FLAGS
#define MUTT_HOOK_NO_FLAGS
No flags are set.
Definition: hook.h:44
MUTT_IDXFMTHOOK
#define MUTT_IDXFMTHOOK
index-format-hook: customise the format of the index
Definition: hook.h:62
Hook::type
HookFlags type
Hook type.
Definition: hook.c:67
mutt_error
#define mutt_error(...)
Definition: logging.h:84