NeoMutt  2025-12-11-435-g4ac674
Teaching an old dog new tricks
DOXYGEN
Loading...
Searching...
No Matches
exec.h File Reference

Execute user-defined Hooks. More...

#include "core/lib.h"
+ Include dependency graph for exec.h:
+ This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Functions

void exec_account_hook (const char *url)
 Perform an account hook.
 
void exec_folder_hook (const char *path, const char *desc)
 Perform a folder hook.
 
void exec_message_hook (struct Mailbox *m, struct Email *e, enum CommandId id)
 Perform a message hook.
 
void exec_startup_shutdown_hook (enum CommandId id)
 Execute any startup/shutdown hooks.
 
void exec_timeout_hook (void)
 Execute any timeout hooks.
 
void mutt_crypt_hook (struct ListHead *list, struct Address *addr)
 Find crypto hooks for an Address.
 
void mutt_default_save (struct Buffer *path, struct Email *e)
 Find the default save path for an email.
 
void mutt_delete_hooks (enum CommandId id)
 Delete matching hooks.
 
char * mutt_find_hook (enum CommandId id, const char *pat)
 Find a matching hook.
 
const struct Expandomutt_idxfmt_hook (const char *name, struct Mailbox *m, struct Email *e)
 Get index-format-hook format string.
 
void mutt_select_fcc (struct Buffer *path, struct Email *e)
 Select the FCC path for an email.
 

Detailed Description

Execute user-defined Hooks.

Authors
  • Richard Russon

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 exec.h.

Function Documentation

◆ exec_account_hook()

void exec_account_hook ( const char * url)

Perform an account hook.

Parameters
urlAccount URL to match

Definition at line 323 of file exec.c.

324{
325 /* parsing commands with URLs in an account hook can cause a recursive
326 * call. We just skip processing if this occurs. Typically such commands
327 * belong in a folder-hook -- perhaps we should warn the user. */
328 static bool inhook = false;
329 if (inhook)
330 return;
331
332 struct Hook *hook = NULL;
333 struct ParseContext *pc = parse_context_new();
334 struct ParseError *pe = parse_error_new();
335
337
338 TAILQ_FOREACH(hook, &Hooks, entries)
339 {
340 if (!(hook->command && (hook->id == CMD_ACCOUNT_HOOK)))
341 continue;
342
343 if (mutt_regex_match(&hook->regex, url))
344 {
345 inhook = true;
346 mutt_debug(LL_DEBUG1, "account-hook '%s' matches '%s'\n", hook->regex.pattern, url);
347 mutt_debug(LL_DEBUG5, " %s\n", hook->command);
348
349 if (parse_rc_line_cwd(hook->command, hook->source_file, pc, pe) == MUTT_CMD_ERROR)
350 {
351 mutt_error("%s", buf_string(pe->message));
352 inhook = false;
353 goto done;
354 }
355
356 inhook = false;
357 }
358 }
359
360done:
363 parse_error_free(&pe);
364}
static const char * buf_string(const struct Buffer *buf)
Convert a buffer to a const char * "string".
Definition buffer.h:96
@ CMD_NONE
No Command.
Definition command.h:59
@ CMD_ACCOUNT_HOOK
:account-hook
Definition command.h:60
@ MUTT_CMD_ERROR
Error: Can't help the user.
Definition command.h:38
#define mutt_error(...)
Definition logging2.h:94
#define mutt_debug(LEVEL,...)
Definition logging2.h:91
enum CommandId CurrentHookId
The ID of the Hook currently being executed, e.g. CMD_SAVE_HOOK.
Definition parse.c:55
struct HookList Hooks
All simple hooks, e.g. CMD_FOLDER_HOOK.
Definition parse.c:49
@ LL_DEBUG5
Log at debug level 5.
Definition logging2.h:49
@ LL_DEBUG1
Log at debug level 1.
Definition logging2.h:45
bool mutt_regex_match(const struct Regex *regex, const char *str)
Shorthand to mutt_regex_capture()
Definition regex.c:614
void parse_context_free(struct ParseContext **pptr)
Free a ParseContext.
Definition pcontext.c:48
struct ParseContext * parse_context_new(void)
Create a new ParseContext.
Definition pcontext.c:37
void parse_error_free(struct ParseError **pptr)
Free a ParseError.
Definition perror.c:50
struct ParseError * parse_error_new(void)
Create a new ParseError.
Definition perror.c:37
#define TAILQ_FOREACH(var, head, field)
Definition queue.h:782
enum CommandResult parse_rc_line_cwd(const char *line, char *cwd, struct ParseContext *pc, struct ParseError *pe)
Parse and run a muttrc line in a relative directory.
Definition source.c:287
A list of user hooks.
Definition hook.h:33
struct Regex regex
Regular expression.
Definition hook.h:35
char * command
Filename, command or pattern to execute.
Definition hook.h:36
enum CommandId id
Hook CommandId, e.g. CMD_FOLDER_HOOK.
Definition hook.h:34
char * source_file
Used for relative-directory source.
Definition hook.h:37
Context for config parsing (history/backtrace)
Definition pcontext.h:34
Detailed error information from config parsing.
Definition perror.h:34
struct Buffer * message
Error message.
Definition perror.h:35
char * pattern
printable version
Definition regex3.h:86
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ exec_folder_hook()

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

Perform a folder hook.

Parameters
pathPath to potentially match
descDescription to potentially match

Definition at line 64 of file exec.c.

65{
66 if (!path && !desc)
67 return;
68
69 struct Hook *hook = NULL;
70 struct ParseContext *pc = parse_context_new();
71 struct ParseError *pe = parse_error_new();
72
74
75 TAILQ_FOREACH(hook, &Hooks, entries)
76 {
77 if (!hook->command)
78 continue;
79
80 if (!(hook->id == CMD_FOLDER_HOOK))
81 continue;
82
83 const char *match = NULL;
84 if (mutt_regex_match(&hook->regex, path))
85 match = path;
86 else if (mutt_regex_match(&hook->regex, desc))
87 match = desc;
88
89 if (match)
90 {
91 mutt_debug(LL_DEBUG1, "folder-hook '%s' matches '%s'\n", hook->regex.pattern, match);
92 mutt_debug(LL_DEBUG5, " %s\n", hook->command);
93 if (parse_rc_line_cwd(hook->command, hook->source_file, pc, pe) == MUTT_CMD_ERROR)
94 {
95 mutt_error("%s", buf_string(pe->message));
96 break;
97 }
98 }
99 }
100
103 parse_error_free(&pe);
104}
@ CMD_FOLDER_HOOK
:folder-hook
Definition command.h:78
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ exec_message_hook()

void exec_message_hook ( struct Mailbox * m,
struct Email * e,
enum CommandId id )

Perform a message hook.

Parameters
mMailbox
eEmail
idHook CommandId, e.g CMD_FOLDER_HOOK

Definition at line 135 of file exec.c.

136{
137 struct Hook *hook = NULL;
138 struct PatternCache cache = { 0 };
139 struct ParseContext *pc = parse_context_new();
140 struct ParseError *pe = parse_error_new();
141
142 CurrentHookId = id;
143
144 TAILQ_FOREACH(hook, &Hooks, entries)
145 {
146 if (!hook->command)
147 continue;
148
149 if (hook->id == id)
150 {
151 if ((mutt_pattern_exec(SLIST_FIRST(hook->pattern), 0, m, e, &cache) > 0) ^
152 hook->regex.pat_not)
153 {
154 if (parse_rc_line_cwd(hook->command, hook->source_file, pc, pe) == MUTT_CMD_ERROR)
155 {
156 mutt_error("%s", buf_string(pe->message));
157 goto done;
158 }
159 /* Executing arbitrary commands could affect the pattern results,
160 * so the cache has to be wiped */
161 memset(&cache, 0, sizeof(cache));
162 }
163 }
164 }
165
166done:
169 parse_error_free(&pe);
170}
bool 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:1146
#define SLIST_FIRST(head)
Definition queue.h:227
struct PatternList * pattern
Used for fcc,save,send-hook.
Definition hook.h:38
Cache commonly-used patterns.
Definition lib.h:118
bool pat_not
do not match
Definition regex3.h:88
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ exec_startup_shutdown_hook()

void exec_startup_shutdown_hook ( enum CommandId id)

Execute any startup/shutdown hooks.

Parameters
idHook CommandId: CMD_STARTUP_HOOK or CMD_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 410 of file exec.c.

411{
412 struct Hook *hook = NULL;
413 struct ParseContext *pc = parse_context_new();
414 struct ParseError *pe = parse_error_new();
415
416 CurrentHookId = id;
417
418 TAILQ_FOREACH(hook, &Hooks, entries)
419 {
420 if (!(hook->command && (hook->id == id)))
421 continue;
422
423 if (parse_rc_line_cwd(hook->command, hook->source_file, pc, pe) == MUTT_CMD_ERROR)
424 {
425 mutt_error("%s", buf_string(pe->message));
427 }
428 }
429
432 parse_error_free(&pe);
433}
void parse_error_reset(struct ParseError *pe)
Clear the contents of a ParseError.
Definition perror.c:66
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ exec_timeout_hook()

void exec_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 372 of file exec.c.

373{
374 struct Hook *hook = NULL;
375 struct ParseContext *pc = parse_context_new();
376 struct ParseError *pe = parse_error_new();
377
379
380 TAILQ_FOREACH(hook, &Hooks, entries)
381 {
382 if (!(hook->command && (hook->id == CMD_TIMEOUT_HOOK)))
383 continue;
384
385 if (parse_rc_line_cwd(hook->command, hook->source_file, pc, pe) == MUTT_CMD_ERROR)
386 {
387 mutt_error("%s", buf_string(pe->message));
389
390 /* The hooks should be independent of each other, so even though this one
391 * failed, we'll carry on with the others. */
392 }
393 }
394
395 /* Delete temporary attachment files */
397
400 parse_error_free(&pe);
401}
@ CMD_TIMEOUT_HOOK
:timeout-hook
Definition command.h:121
void mutt_temp_attachments_cleanup(void)
Delete all temporary attachments.
+ 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 314 of file exec.c.

315{
317}
@ CMD_CRYPT_HOOK
:crypt-hook
Definition command.h:72
static void list_hook(struct ListHead *matches, const char *match, enum CommandId id)
Find hook strings matching.
Definition exec.c:294
struct Buffer * mailbox
Mailbox and host address.
Definition address.h:37
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mutt_default_save()

void mutt_default_save ( struct Buffer * path,
struct Email * e )

Find the default save path for an email.

Parameters
pathBuffer for the path
eEmail

Definition at line 214 of file exec.c.

215{
216 struct Mailbox *m_cur = get_current_mailbox();
217 if (addr_hook(path, CMD_SAVE_HOOK, m_cur, e) == 0)
218 return;
219
220 struct Envelope *env = e->env;
221 const struct Address *from = TAILQ_FIRST(&env->from);
222 const struct Address *reply_to = TAILQ_FIRST(&env->reply_to);
223 const struct Address *to = TAILQ_FIRST(&env->to);
224 const struct Address *cc = TAILQ_FIRST(&env->cc);
225 const struct Address *addr = NULL;
226 bool from_me = mutt_addr_is_user(from);
227
228 if (!from_me && reply_to && reply_to->mailbox)
229 addr = reply_to;
230 else if (!from_me && from && from->mailbox)
231 addr = from;
232 else if (to && to->mailbox)
233 addr = to;
234 else if (cc && cc->mailbox)
235 addr = cc;
236 else
237 addr = NULL;
238 if (addr)
239 {
240 struct Buffer *tmp = buf_pool_get();
241 generate_save_path(tmp, addr);
242 buf_add_printf(path, "=%s", buf_string(tmp));
243 buf_pool_release(&tmp);
244 }
245}
bool mutt_addr_is_user(const struct Address *addr)
Does the address belong to the user.
Definition alias.c:600
int buf_add_printf(struct Buffer *buf, const char *fmt,...)
Format a string appending a Buffer.
Definition buffer.c:204
@ CMD_SAVE_HOOK
:save-hook
Definition command.h:104
static int addr_hook(struct Buffer *path, enum CommandId id, struct Mailbox *m, struct Email *e)
Perform an address hook (get a path)
Definition exec.c:181
struct Mailbox * get_current_mailbox(void)
Get the current Mailbox.
Definition index.c:721
void generate_save_path(struct Buffer *dest, const struct Address *a)
Make a safe filename from an email address.
Definition muttlib.c:607
struct Buffer * buf_pool_get(void)
Get a Buffer from the pool.
Definition pool.c:91
void buf_pool_release(struct Buffer **ptr)
Return a Buffer to the pool.
Definition pool.c:111
#define TAILQ_FIRST(head)
Definition queue.h:780
An email address.
Definition address.h:35
String manipulation buffer.
Definition buffer.h:36
struct Envelope * env
Envelope information.
Definition email.h:68
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 cc
Email's 'Cc' list.
Definition envelope.h:61
struct AddressList from
Email's 'From' list.
Definition envelope.h:59
A mailbox.
Definition mailbox.h:78
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mutt_delete_hooks()

void mutt_delete_hooks ( enum CommandId id)

Delete matching hooks.

Parameters
idHook CommandId to delete, e.g. CMD_SEND_HOOK

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

Definition at line 1014 of file parse.c.

1015{
1016 struct Hook *h = NULL;
1017 struct Hook *tmp = NULL;
1018
1019 TAILQ_FOREACH_SAFE(h, &Hooks, entries, tmp)
1020 {
1021 if ((id == CMD_NONE) || (id == h->id))
1022 {
1023 TAILQ_REMOVE(&Hooks, h, entries);
1024 hook_free(&h);
1025 }
1026 }
1027}
void hook_free(struct Hook **ptr)
Free a Hook.
Definition hook.c:47
#define TAILQ_FOREACH_SAFE(var, head, field, tvar)
Definition queue.h:792
#define TAILQ_REMOVE(head, elm, field)
Definition queue.h:901
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mutt_find_hook()

char * mutt_find_hook ( enum CommandId id,
const char * pat )

Find a matching hook.

Parameters
idHook CommandId, e.g CMD_FOLDER_HOOK
patPattern to match
Return values
ptrCommand string
Note
The returned string must not be freed.

Definition at line 114 of file exec.c.

115{
116 struct Hook *hook = NULL;
117
118 TAILQ_FOREACH(hook, &Hooks, entries)
119 {
120 if (hook->id == id)
121 {
122 if (mutt_regex_match(&hook->regex, pat))
123 return hook->command;
124 }
125 }
126 return NULL;
127}
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mutt_idxfmt_hook()

const struct Expando * 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
ptrExpando
NULLNo matching hook

Definition at line 443 of file exec.c.

444{
445 if (!IdxFmtHooks)
446 return NULL;
447
448 struct HookList *hl = mutt_hash_find(IdxFmtHooks, name);
449 if (!hl)
450 return NULL;
451
452 struct PatternCache cache = { 0 };
453 const struct Expando *exp = NULL;
454 struct Hook *hook = NULL;
455
456 TAILQ_FOREACH(hook, hl, entries)
457 {
458 struct Pattern *pat = SLIST_FIRST(hook->pattern);
459 if ((mutt_pattern_exec(pat, 0, m, e, &cache) > 0) ^ hook->regex.pat_not)
460 {
461 exp = hook->expando;
462 break;
463 }
464 }
465
466 return exp;
467}
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:364
struct HashTable * IdxFmtHooks
All Index Format hooks.
Definition parse.c:52
Parsed Expando trees.
Definition expando.h:41
struct Expando * expando
Used for format hooks.
Definition hook.h:39
A simple (non-regex) pattern.
Definition lib.h:78
+ 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 252 of file exec.c.

253{
254 buf_alloc(path, PATH_MAX);
255
256 if (addr_hook(path, CMD_FCC_HOOK, NULL, e) != 0)
257 {
258 const struct Address *to = TAILQ_FIRST(&e->env->to);
259 const struct Address *cc = TAILQ_FIRST(&e->env->cc);
260 const struct Address *bcc = TAILQ_FIRST(&e->env->bcc);
261 const bool c_save_name = cs_subset_bool(NeoMutt->sub, "save_name");
262 const bool c_force_name = cs_subset_bool(NeoMutt->sub, "force_name");
263 const char *const c_record = cs_subset_string(NeoMutt->sub, "record");
264 if ((c_save_name || c_force_name) && (to || cc || bcc))
265 {
266 const struct Address *addr = to ? to : (cc ? cc : bcc);
267 struct Buffer *buf = buf_pool_get();
268 generate_save_path(buf, addr);
269 const char *const c_folder = cs_subset_string(NeoMutt->sub, "folder");
270 buf_concat_path(path, NONULL(c_folder), buf_string(buf));
271 buf_pool_release(&buf);
272 if (!c_force_name && (mx_access(buf_string(path), W_OK) != 0))
273 buf_strcpy(path, c_record);
274 }
275 else
276 {
277 buf_strcpy(path, c_record);
278 }
279 }
280 else
281 {
282 buf_fix_dptr(path);
283 }
284
285 pretty_mailbox(path);
286}
void buf_fix_dptr(struct Buffer *buf)
Move the dptr to end of the Buffer.
Definition buffer.c:182
size_t buf_strcpy(struct Buffer *buf, const char *s)
Copy a string into a Buffer.
Definition buffer.c:395
size_t buf_concat_path(struct Buffer *buf, const char *dir, const char *fname)
Join a directory name and a filename.
Definition buffer.c:509
void buf_alloc(struct Buffer *buf, size_t new_size)
Make sure a buffer can store at least new_size bytes.
Definition buffer.c:337
@ CMD_FCC_HOOK
:fcc-hook
Definition command.h:75
const char * cs_subset_string(const struct ConfigSubset *sub, const char *name)
Get a string config item by name.
Definition helpers.c:291
bool cs_subset_bool(const struct ConfigSubset *sub, const char *name)
Get a boolean config item by name.
Definition helpers.c:47
#define PATH_MAX
Definition mutt.h:49
void pretty_mailbox(struct Buffer *buf)
Shorten a mailbox path using '~' or '='.
Definition muttlib.c:427
int mx_access(const char *path, int flags)
Wrapper for access, checks permissions on a given mailbox.
Definition mx.c:167
#define NONULL(x)
Definition string2.h:44
struct AddressList bcc
Email's 'Bcc' list.
Definition envelope.h:62
Container for Accounts, Notifications.
Definition neomutt.h:41
struct ConfigSubset * sub
Inherited config items.
Definition neomutt.h:49
+ Here is the call graph for this function:
+ Here is the caller graph for this function: