NeoMutt  2024-03-23-147-g885fbc
Teaching an old dog new tricks
DOXYGEN
Loading...
Searching...
No Matches
external.h File Reference

Manage where the email is piped to external commands. More...

#include <stdbool.h>
#include <stdio.h>
+ Include dependency graph for external.h:
+ This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Enumerations

enum  MessageTransformOpt { TRANSFORM_NONE = 0 , TRANSFORM_DECRYPT , TRANSFORM_DECODE }
 Message transformation option. More...
 
enum  MessageSaveOpt { SAVE_COPY = 0 , SAVE_MOVE }
 Message save option. More...
 

Functions

void index_bounce_message (struct Mailbox *m, struct EmailArray *ea)
 Bounce an email.
 
bool mutt_check_traditional_pgp (struct Mailbox *m, struct EmailArray *ea)
 Check if a message has inline PGP content.
 
void external_cleanup (void)
 Clean up commands globals.
 
void mutt_display_address (struct Envelope *env)
 Display the address of a message.
 
bool mutt_edit_content_type (struct Email *e, struct Body *b, FILE *fp)
 Edit the content type of an attachment.
 
void mutt_enter_command (void)
 Enter a neomutt command.
 
void mutt_pipe_message (struct Mailbox *m, struct EmailArray *ea)
 Pipe a message.
 
void mutt_print_message (struct Mailbox *m, struct EmailArray *ea)
 Print a message.
 
int mutt_save_message (struct Mailbox *m, struct EmailArray *ea, enum MessageSaveOpt save_opt, enum MessageTransformOpt transform_opt)
 Save an email.
 
int mutt_save_message_mbox (struct Mailbox *m_src, struct Email *e, enum MessageSaveOpt save_opt, enum MessageTransformOpt transform_opt, struct Mailbox *m_dst)
 Save a message to a given mailbox.
 
bool mutt_select_sort (bool reverse)
 Ask the user for a sort method.
 
bool mutt_shell_escape (void)
 Invoke a command in a subshell.
 

Detailed Description

Manage where the email is piped to external commands.

Authors
  • Richard Russon
  • Pietro Cerutti
  • Ihor Antonov

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

Enumeration Type Documentation

◆ MessageTransformOpt

Message transformation option.

Enumerator
TRANSFORM_NONE 

No transformation.

TRANSFORM_DECRYPT 

Decrypt message.

TRANSFORM_DECODE 

Decode message.

Definition at line 40 of file external.h.

41{
42 TRANSFORM_NONE = 0,
45};
@ TRANSFORM_NONE
No transformation.
Definition: external.h:42
@ TRANSFORM_DECODE
Decode message.
Definition: external.h:44
@ TRANSFORM_DECRYPT
Decrypt message.
Definition: external.h:43

◆ MessageSaveOpt

Message save option.

Enumerator
SAVE_COPY 

Copy message, making a duplicate in another mailbox.

SAVE_MOVE 

Move message to another mailbox, removing the original.

Definition at line 50 of file external.h.

51{
52 SAVE_COPY = 0,
53 SAVE_MOVE,
54};
@ SAVE_MOVE
Move message to another mailbox, removing the original.
Definition: external.h:53
@ SAVE_COPY
Copy message, making a duplicate in another mailbox.
Definition: external.h:52

Function Documentation

◆ index_bounce_message()

void index_bounce_message ( struct Mailbox m,
struct EmailArray *  ea 
)

Bounce an email.

Parameters
mMailbox
eaArray of Emails to bounce

Definition at line 91 of file external.c.

92{
93 if (!m || !ea || ARRAY_EMPTY(ea))
94 return;
95
96 struct Buffer *buf = buf_pool_get();
97 struct Buffer *prompt = buf_pool_get();
98 struct AddressList al = TAILQ_HEAD_INITIALIZER(al);
99 char *err = NULL;
100 int rc;
101 int msg_count = 0;
102
103 struct Email **ep = NULL;
104 ARRAY_FOREACH(ep, ea)
105 {
106 struct Email *e = *ep;
107 /* RFC5322 mandates a From: header,
108 * so warn before bouncing messages without one */
109 if (TAILQ_EMPTY(&e->env->from))
110 mutt_error(_("Warning: message contains no From: header"));
111
112 msg_count++;
113 }
114
115 if (msg_count == 1)
116 buf_strcpy(prompt, _("Bounce message to: "));
117 else
118 buf_strcpy(prompt, _("Bounce tagged messages to: "));
119
121 &CompleteAliasOps, NULL);
122 if ((rc != 0) || buf_is_empty(buf))
123 goto done;
124
126 if (TAILQ_EMPTY(&al))
127 {
128 mutt_error(_("Error parsing address"));
129 goto done;
130 }
131
133
134 if (mutt_addrlist_to_intl(&al, &err) < 0)
135 {
136 mutt_error(_("Bad IDN: '%s'"), err);
137 FREE(&err);
138 goto done;
139 }
140
141 buf_reset(buf);
142 mutt_addrlist_write(&al, buf, true);
143
144 buf_printf(prompt, ngettext("Bounce message to %s?", "Bounce messages to %s?", msg_count),
145 buf_string(buf));
146
147 if (query_quadoption(buf_string(prompt), NeoMutt->sub, "bounce") != MUTT_YES)
148 {
149 msgwin_clear_text(NULL);
150 mutt_message(ngettext("Message not bounced", "Messages not bounced", msg_count));
151 goto done;
152 }
153
154 msgwin_clear_text(NULL);
155
156 struct Message *msg = NULL;
157 ARRAY_FOREACH(ep, ea)
158 {
159 struct Email *e = *ep;
160 msg = mx_msg_open(m, e);
161 if (!msg)
162 {
163 rc = -1;
164 break;
165 }
166
167 rc = mutt_bounce_message(msg->fp, m, e, &al, NeoMutt->sub);
168 mx_msg_close(m, &msg);
169
170 if (rc < 0)
171 break;
172 }
173
174 /* If no error, or background, display message. */
175 if ((rc == 0) || (rc == S_BKG))
176 mutt_message(ngettext("Message bounced", "Messages bounced", msg_count));
177
178done:
180 buf_pool_release(&buf);
181 buf_pool_release(&prompt);
182}
void mutt_addrlist_clear(struct AddressList *al)
Unlink and free all Address in an AddressList.
Definition: address.c:1460
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_parse2(struct AddressList *al, const char *s)
Parse a list of email addresses.
Definition: address.c:644
int mutt_addrlist_to_intl(struct AddressList *al, char **err)
Convert an Address list to Punycode.
Definition: address.c:1293
const struct CompleteOps CompleteAliasOps
Auto-Completion of Aliases.
Definition: complete.c:108
void mutt_expand_aliases(struct AddressList *al)
Expand aliases in a List of Addresses.
Definition: alias.c:295
#define ARRAY_FOREACH(elem, head)
Iterate over all elements of the array.
Definition: array.h:212
#define ARRAY_EMPTY(head)
Check if an array is empty.
Definition: array.h:74
int buf_printf(struct Buffer *buf, const char *fmt,...)
Format a string overwriting a Buffer.
Definition: buffer.c:160
void buf_reset(struct Buffer *buf)
Reset an existing Buffer.
Definition: buffer.c:75
bool buf_is_empty(const struct Buffer *buf)
Is the Buffer empty?
Definition: buffer.c:290
size_t buf_strcpy(struct Buffer *buf, const char *s)
Copy a string into a Buffer.
Definition: buffer.c:394
static const char * buf_string(const struct Buffer *buf)
Convert a buffer to a const char * "string".
Definition: buffer.h:96
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
@ HC_ALIAS
Aliases.
Definition: lib.h:52
#define FREE(x)
Definition: memory.h:45
void msgwin_clear_text(struct MuttWindow *win)
Clear the text in the Message Window.
Definition: msgwin.c:519
#define _(a)
Definition: message.h:28
#define MUTT_COMP_NO_FLAGS
No flags are set.
Definition: mutt.h:56
int mx_msg_close(struct Mailbox *m, struct Message **ptr)
Close a message.
Definition: mx.c:1178
struct Message * mx_msg_open(struct Mailbox *m, struct Email *e)
Return a stream pointer for a message.
Definition: mx.c:1132
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_YES
User answered 'Yes', or assume 'Yes'.
Definition: quad.h:39
enum QuadOption query_quadoption(const char *prompt, struct ConfigSubset *sub, const char *name)
Ask the user a quad-question.
Definition: question.c:366
#define TAILQ_HEAD_INITIALIZER(head)
Definition: queue.h:637
#define TAILQ_EMPTY(head)
Definition: queue.h:721
int mutt_bounce_message(FILE *fp, struct Mailbox *m, struct Email *e, struct AddressList *to, struct ConfigSubset *sub)
Bounce an email message.
Definition: sendlib.c:916
#define S_BKG
Definition: string2.h:41
String manipulation buffer.
Definition: buffer.h:36
The envelope/body of an email.
Definition: email.h:39
struct Envelope * env
Envelope information.
Definition: email.h:68
struct AddressList from
Email's 'From' list.
Definition: envelope.h:59
A local copy of an email.
Definition: message.h:34
FILE * fp
pointer to the message data
Definition: message.h:35
Container for Accounts, Notifications.
Definition: neomutt.h:41
struct ConfigSubset * sub
Inherited config items.
Definition: neomutt.h:45
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mutt_check_traditional_pgp()

bool mutt_check_traditional_pgp ( struct Mailbox m,
struct EmailArray *  ea 
)

Check if a message has inline PGP content.

Parameters
mMailbox
eaArray of Emails to check
Return values
trueMessage contains inline PGP content

Definition at line 1212 of file external.c.

1213{
1214 bool rc = false;
1215
1216 struct Email **ep = NULL;
1217 ARRAY_FOREACH(ep, ea)
1218 {
1219 struct Email *e = *ep;
1221 rc = check_traditional_pgp(m, e) || rc;
1222 }
1223
1224 return rc;
1225}
static bool check_traditional_pgp(struct Mailbox *m, struct Email *e)
Check for an inline PGP content.
Definition: external.c:1184
#define PGP_TRADITIONAL_CHECKED
Email has a traditional (inline) signature.
Definition: lib.h:92
SecurityFlags security
bit 0-10: flags, bit 11,12: application, bit 13: traditional pgp See: ncrypt/lib.h pgplib....
Definition: email.h:43
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ external_cleanup()

void external_cleanup ( void  )

Clean up commands globals.

Definition at line 81 of file external.c.

82{
84}
void buf_dealloc(struct Buffer *buf)
Release the memory allocated by a buffer.
Definition: buffer.c:376
static struct Buffer LastSaveFolder
The folder the user last saved to. Used by ci_save_message()
Definition: external.c:76
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mutt_display_address()

void mutt_display_address ( struct Envelope env)

Display the address of a message.

Parameters
envEnvelope containing address

Definition at line 662 of file external.c.

663{
664 const char *pfx = NULL;
665
666 struct AddressList *al = mutt_get_address(env, &pfx);
667 if (!al)
668 return;
669
670 /* Note: We don't convert IDNA to local representation this time.
671 * That is intentional, so the user has an opportunity to copy &
672 * paste the on-the-wire form of the address to other, IDN-unable
673 * software. */
674 struct Buffer *buf = buf_pool_get();
675 mutt_addrlist_write(al, buf, false);
676 mutt_message("%s: %s", pfx, buf_string(buf));
677 buf_pool_release(&buf);
678}
struct AddressList * mutt_get_address(struct Envelope *env, const char **prefix)
Get an Address from an Envelope.
Definition: alias.c:327
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mutt_edit_content_type()

bool mutt_edit_content_type ( struct Email e,
struct Body b,
FILE *  fp 
)

Edit the content type of an attachment.

Parameters
eEmail
bAttachment
fpFile handle to the attachment
Return values
trueA Any change is made

recvattach requires the return code to know when to regenerate the actx.

Definition at line 1071 of file external.c.

1072{
1073 struct Buffer *buf = buf_pool_get();
1074 struct Buffer *charset = buf_pool_get();
1075 struct Buffer *obuf = buf_pool_get();
1076 struct Buffer *tmp = buf_pool_get();
1077
1078 bool rc = false;
1079 bool charset_changed = false;
1080 bool type_changed = false;
1081 bool structure_changed = false;
1082
1083 char *cp = mutt_param_get(&b->parameter, "charset");
1084 buf_strcpy(charset, cp);
1085
1086 buf_printf(buf, "%s/%s", TYPE(b), b->subtype);
1087 buf_copy(obuf, buf);
1088 if (!TAILQ_EMPTY(&b->parameter))
1089 {
1090 struct Parameter *np = NULL;
1091 TAILQ_FOREACH(np, &b->parameter, entries)
1092 {
1093 mutt_addr_cat(tmp->data, tmp->dsize, np->value, MimeSpecials);
1094 buf_add_printf(buf, "; %s=%s", np->attribute, buf_string(tmp));
1095 }
1096 }
1097
1098 if ((mw_get_field("Content-Type: ", buf, MUTT_COMP_NO_FLAGS, HC_OTHER, NULL, NULL) != 0) ||
1099 buf_is_empty(buf))
1100 {
1101 goto done;
1102 }
1103
1104 /* clean up previous junk */
1106 FREE(&b->subtype);
1107
1109
1110 buf_printf(tmp, "%s/%s", TYPE(b), NONULL(b->subtype));
1111 type_changed = !mutt_istr_equal(buf_string(tmp), buf_string(obuf));
1112 charset_changed = !mutt_istr_equal(buf_string(charset),
1113 mutt_param_get(&b->parameter, "charset"));
1114
1115 /* if in send mode, check for conversion - current setting is default. */
1116
1117 if (!e && (b->type == TYPE_TEXT) && charset_changed)
1118 {
1119 buf_printf(tmp, _("Convert to %s upon sending?"),
1120 mutt_param_get(&b->parameter, "charset"));
1121 enum QuadOption ans = query_yesorno(buf_string(tmp), b->noconv ? MUTT_NO : MUTT_YES);
1122 if (ans != MUTT_ABORT)
1123 b->noconv = (ans == MUTT_NO);
1124 }
1125
1126 /* inform the user */
1127
1128 buf_printf(tmp, "%s/%s", TYPE(b), NONULL(b->subtype));
1129 if (type_changed)
1130 mutt_message(_("Content-Type changed to %s"), buf_string(tmp));
1131 if ((b->type == TYPE_TEXT) && charset_changed)
1132 {
1133 if (type_changed)
1134 mutt_sleep(1);
1135 mutt_message(b->noconv ? _("Character set changed to %s; not converting") :
1136 _("Character set changed to %s; converting"),
1137 mutt_param_get(&b->parameter, "charset"));
1138 }
1139
1140 b->force_charset |= charset_changed;
1141
1142 if (!is_multipart(b) && b->parts)
1143 {
1144 structure_changed = true;
1145 mutt_body_free(&b->parts);
1146 }
1147 if (!mutt_is_message_type(b->type, b->subtype) && b->email)
1148 {
1149 structure_changed = true;
1150 b->email->body = NULL;
1151 email_free(&b->email);
1152 }
1153
1154 if (fp && !b->parts && (is_multipart(b) || mutt_is_message_type(b->type, b->subtype)))
1155 {
1156 structure_changed = true;
1157 mutt_parse_part(fp, b);
1158 }
1159
1160 if ((WithCrypto != 0) && e)
1161 {
1162 if (e->body == b)
1164
1165 e->security |= crypt_query(b);
1166 }
1167
1168 rc = structure_changed | type_changed;
1169
1170done:
1171 buf_pool_release(&buf);
1172 buf_pool_release(&charset);
1173 buf_pool_release(&obuf);
1174 buf_pool_release(&tmp);
1175 return rc;
1176}
void mutt_addr_cat(char *buf, size_t buflen, const char *value, const char *specials)
Copy a string and wrap it in quotes if it contains special characters.
Definition: address.c:708
int buf_add_printf(struct Buffer *buf, const char *fmt,...)
Format a string appending a Buffer.
Definition: buffer.c:203
size_t buf_copy(struct Buffer *dst, const struct Buffer *src)
Copy a Buffer's contents to another Buffer.
Definition: buffer.c:600
SecurityFlags crypt_query(struct Body *b)
Check out the type of encryption used.
Definition: crypt.c:673
void mutt_body_free(struct Body **ptr)
Free a Body.
Definition: body.c:58
void email_free(struct Email **ptr)
Free an Email.
Definition: email.c:46
void mutt_parse_part(FILE *fp, struct Body *b)
Parse a MIME part.
Definition: parse.c:1817
void mutt_parse_content_type(const char *s, struct Body *b)
Parse a content type.
Definition: parse.c:463
bool mutt_is_message_type(int type, const char *subtype)
Determine if a mime type matches a message or not.
Definition: parse.c:1493
@ HC_OTHER
Miscellaneous strings.
Definition: lib.h:56
const char MimeSpecials[]
Characters that need special treatment in MIME.
Definition: mime.c:67
@ TYPE_TEXT
Type: 'text/*'.
Definition: mime.h:38
#define TYPE(body)
Definition: mime.h:89
#define is_multipart(body)
Definition: mime.h:82
bool mutt_istr_equal(const char *a, const char *b)
Compare two strings, ignoring case.
Definition: string.c:721
void mutt_sleep(short s)
Sleep for a while.
Definition: muttlib.c:878
#define SEC_NO_FLAGS
No flags are set.
Definition: lib.h:77
#define WithCrypto
Definition: lib.h:116
char * mutt_param_get(const struct ParameterList *pl, const char *s)
Find a matching Parameter.
Definition: parameter.c:85
void mutt_param_free(struct ParameterList *pl)
Free a ParameterList.
Definition: parameter.c:62
QuadOption
Possible values for a quad-option.
Definition: quad.h:36
@ MUTT_ABORT
User aborted the question (with Ctrl-G)
Definition: quad.h:37
@ MUTT_NO
User answered 'No', or assume 'No'.
Definition: quad.h:38
enum QuadOption query_yesorno(const char *prompt, enum QuadOption def)
Ask the user a Yes/No question.
Definition: question.c:327
#define TAILQ_FOREACH(var, head, field)
Definition: queue.h:725
#define NONULL(x)
Definition: string2.h:37
struct Body * parts
parts of a multipart or message/rfc822
Definition: body.h:72
bool noconv
Don't do character set conversion.
Definition: body.h:46
struct ParameterList parameter
Parameters of the content-type.
Definition: body.h:62
struct Email * email
header information for message/rfc822
Definition: body.h:73
bool force_charset
Send mode: don't adjust the character set when in send-mode.
Definition: body.h:44
char * subtype
content-type subtype
Definition: body.h:60
unsigned int type
content-type primary type, ContentType
Definition: body.h:40
size_t dsize
Length of data.
Definition: buffer.h:39
char * data
Pointer to data.
Definition: buffer.h:37
struct Body * body
List of MIME parts.
Definition: email.h:69
Attribute associated with a MIME part.
Definition: parameter.h:33
char * attribute
Parameter name.
Definition: parameter.h:34
char * value
Parameter value.
Definition: parameter.h:35
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mutt_enter_command()

void mutt_enter_command ( void  )

Enter a neomutt command.

Definition at line 622 of file external.c.

623{
624 struct Buffer *buf = buf_pool_get();
625 struct Buffer *err = buf_pool_get();
626
627 window_redraw(NULL);
628 /* if enter is pressed after : with no command, just return */
630 &CompleteCommandOps, NULL) != 0) ||
631 buf_is_empty(buf))
632 {
633 goto done;
634 }
635
636 enum CommandResult rc = parse_rc_line(buf_string(buf), err);
637 if (!buf_is_empty(err))
638 {
639 if (rc == MUTT_CMD_SUCCESS) /* command succeeded with message */
640 mutt_message("%s", buf_string(err));
641 else if (rc == MUTT_CMD_ERROR)
642 mutt_error("%s", buf_string(err));
643 else if (rc == MUTT_CMD_WARNING)
644 mutt_warning("%s", buf_string(err));
645 }
646
647 if (NeoMutt)
648 {
649 // Running commands could cause anything to change, so let others know
651 }
652
653done:
654 buf_pool_release(&buf);
655 buf_pool_release(&err);
656}
CommandResult
Error codes for command_t parse functions.
Definition: command.h:36
@ MUTT_CMD_SUCCESS
Success: Command worked.
Definition: command.h:39
@ MUTT_CMD_ERROR
Error: Can't help the user.
Definition: command.h:37
@ MUTT_CMD_WARNING
Warning: Help given to the user.
Definition: command.h:38
const struct CompleteOps CompleteCommandOps
Auto-Completion of Commands.
Definition: helpers.c:477
#define mutt_warning(...)
Definition: logging2.h:90
@ HC_NEO_COMMAND
NeoMutt commands.
Definition: lib.h:53
bool notify_send(struct Notify *notify, enum NotifyType event_type, int event_subtype, void *event_data)
Send out a notification message.
Definition: notify.c:173
void window_redraw(struct MuttWindow *win)
Reflow, recalc and repaint a tree of Windows.
Definition: mutt_window.c:634
@ NT_GLOBAL_COMMAND
A NeoMutt command.
Definition: neomutt.h:61
@ NT_GLOBAL
Not object-related, NotifyGlobal.
Definition: notify_type.h:46
enum CommandResult parse_rc_line(const char *line, struct Buffer *err)
Parse a line of user config.
Definition: rc.c:104
struct Notify * notify
Notifications handler.
Definition: neomutt.h:42
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mutt_pipe_message()

void mutt_pipe_message ( struct Mailbox m,
struct EmailArray *  ea 
)

Pipe a message.

Parameters
mMailbox
eaArray of Emails to pipe

Definition at line 408 of file external.c.

409{
410 if (!m || !ea)
411 return;
412
413 struct Buffer *buf = buf_pool_get();
414
415 if (mw_get_field(_("Pipe to command: "), buf, MUTT_COMP_NO_FLAGS,
416 HC_EXT_COMMAND, &CompleteFileOps, NULL) != 0)
417 {
418 goto cleanup;
419 }
420
421 if (buf_is_empty(buf))
422 goto cleanup;
423
424 buf_expand_path(buf);
425 const bool c_pipe_decode = cs_subset_bool(NeoMutt->sub, "pipe_decode");
426 const bool c_pipe_split = cs_subset_bool(NeoMutt->sub, "pipe_split");
427 const char *const c_pipe_sep = cs_subset_string(NeoMutt->sub, "pipe_sep");
428 pipe_message(m, ea, buf_string(buf), c_pipe_decode, false, c_pipe_split, c_pipe_sep);
429
430cleanup:
431 buf_pool_release(&buf);
432}
const struct CompleteOps CompleteFileOps
Auto-Completion of Files.
Definition: complete.c:155
const char * cs_subset_string(const struct ConfigSubset *sub, const char *name)
Get a string config item by name.
Definition: helpers.c:292
bool cs_subset_bool(const struct ConfigSubset *sub, const char *name)
Get a boolean config item by name.
Definition: helpers.c:48
static int pipe_message(struct Mailbox *m, struct EmailArray *ea, const char *cmd, bool decode, bool print, bool split, const char *sep)
Pipe message to a command.
Definition: external.c:279
@ HC_EXT_COMMAND
External commands.
Definition: lib.h:51
void buf_expand_path(struct Buffer *buf)
Create the canonical path.
Definition: muttlib.c:328
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mutt_print_message()

void mutt_print_message ( struct Mailbox m,
struct EmailArray *  ea 
)

Print a message.

Parameters
mMailbox
eaArray of Emails to print

Definition at line 439 of file external.c.

440{
441 if (!m || !ea)
442 return;
443
444 const enum QuadOption c_print = cs_subset_quad(NeoMutt->sub, "print");
445 const char *const c_print_command = cs_subset_string(NeoMutt->sub, "print_command");
446 if (c_print && !c_print_command)
447 {
448 mutt_message(_("No printing command has been defined"));
449 return;
450 }
451
452 int msg_count = ARRAY_SIZE(ea);
453 const char *msg = ngettext("Print message?", "Print tagged messages?", msg_count);
454 if (query_quadoption(msg, NeoMutt->sub, "print") != MUTT_YES)
455 {
456 return;
457 }
458
459 const bool c_print_decode = cs_subset_bool(NeoMutt->sub, "print_decode");
460 const bool c_print_split = cs_subset_bool(NeoMutt->sub, "print_split");
461 if (pipe_message(m, ea, c_print_command, c_print_decode, true, c_print_split, "\f") == 0)
462 {
463 mutt_message(ngettext("Message printed", "Messages printed", msg_count));
464 }
465 else
466 {
467 mutt_message(ngettext("Message could not be printed",
468 "Messages could not be printed", msg_count));
469 }
470}
#define ARRAY_SIZE(head)
The number of elements stored.
Definition: array.h:87
enum QuadOption cs_subset_quad(const struct ConfigSubset *sub, const char *name)
Get a quad-value config item by name.
Definition: helpers.c:193
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mutt_save_message()

int mutt_save_message ( struct Mailbox m,
struct EmailArray *  ea,
enum MessageSaveOpt  save_opt,
enum MessageTransformOpt  transform_opt 
)

Save an email.

Parameters
mMailbox
eaArray of Emails to save
save_optCopy or move, e.g. SAVE_MOVE
transform_optTransformation, e.g. TRANSFORM_DECRYPT
Return values
0Copy/save was successful
-1Error/abort

Definition at line 779 of file external.c.

781{
782 if (!ea || ARRAY_EMPTY(ea))
783 return -1;
784
785 int rc = -1;
786 int tagged_progress_count = 0;
787 unsigned int msg_count = ARRAY_SIZE(ea);
788 struct Mailbox *m_save = NULL;
789
790 struct Buffer *buf = buf_pool_get();
791 struct stat st = { 0 };
792 struct Email *e_cur = *ARRAY_GET(ea, 0);
793
794 const SecurityFlags security_flags = WithCrypto ? e_cur->security : SEC_NO_FLAGS;
795 const bool is_passphrase_needed = security_flags & SEC_ENCRYPT;
796
797 const char *prompt = NULL;
798 const char *progress_msg = NULL;
799
800 // Set prompt and progress_msg
801 switch (save_opt)
802 {
803 case SAVE_COPY:
804 // L10N: Progress meter message when copying tagged messages
805 progress_msg = (msg_count > 1) ? _("Copying tagged messages...") : NULL;
806 switch (transform_opt)
807 {
808 case TRANSFORM_NONE:
809 prompt = (msg_count > 1) ? _("Copy tagged to mailbox") : _("Copy to mailbox");
810 break;
812 prompt = (msg_count > 1) ? _("Decrypt-copy tagged to mailbox") :
813 _("Decrypt-copy to mailbox");
814 break;
815 case TRANSFORM_DECODE:
816 prompt = (msg_count > 1) ? _("Decode-copy tagged to mailbox") :
817 _("Decode-copy to mailbox");
818 break;
819 }
820 break;
821
822 case SAVE_MOVE:
823 // L10N: Progress meter message when saving tagged messages
824 progress_msg = (msg_count > 1) ? _("Saving tagged messages...") : NULL;
825 switch (transform_opt)
826 {
827 case TRANSFORM_NONE:
828 prompt = (msg_count > 1) ? _("Save tagged to mailbox") : _("Save to mailbox");
829 break;
831 prompt = (msg_count > 1) ? _("Decrypt-save tagged to mailbox") :
832 _("Decrypt-save to mailbox");
833 break;
834 case TRANSFORM_DECODE:
835 prompt = (msg_count > 1) ? _("Decode-save tagged to mailbox") :
836 _("Decode-save to mailbox");
837 break;
838 }
839 break;
840 }
841
843 mutt_default_save(buf, e_cur);
845
846 if (mw_enter_fname(prompt, buf, false, NULL, false, NULL, NULL, MUTT_SEL_NO_FLAGS) == -1)
847 {
848 goto cleanup;
849 }
850
851 size_t pathlen = buf_len(buf);
852 if (pathlen == 0)
853 goto cleanup;
854
855 mutt_path_tidy(buf, true);
856
857 /* This is an undocumented feature of ELM pointed out to me by Felix von
858 * Leitner <leitner@prz.fu-berlin.de> */
861 if (mutt_str_equal(buf_string(buf), "."))
863 else
865
866 buf_expand_path(buf);
867
868 /* check to make sure that this file is really the one the user wants */
869 if (mutt_save_confirm(buf_string(buf), &st) != 0)
870 goto cleanup;
871
872 if (is_passphrase_needed && (transform_opt != TRANSFORM_NONE) &&
873 !crypt_valid_passphrase(security_flags))
874 {
875 rc = -1;
876 goto errcleanup;
877 }
878
879 mutt_message(_("Copying to %s..."), buf_string(buf));
880
881 enum MailboxType mailbox_type = imap_path_probe(buf_string(buf), NULL);
882 if ((m->type == MUTT_IMAP) && (transform_opt == TRANSFORM_NONE) && (mailbox_type == MUTT_IMAP))
883 {
884 rc = imap_copy_messages(m, ea, buf_string(buf), save_opt);
885 switch (rc)
886 {
887 /* success */
888 case 0:
890 rc = 0;
891 if (save_opt == SAVE_MOVE)
892 {
893 const bool c_delete_untag = cs_subset_bool(NeoMutt->sub, "delete_untag");
894 if (c_delete_untag)
895 {
896 struct Email **ep = NULL;
897 ARRAY_FOREACH(ep, ea)
898 {
899 mutt_set_flag(m, *ep, MUTT_TAG, false, true);
900 }
901 }
902 }
903 goto cleanup;
904 /* non-fatal error: continue to fetch/append */
905 case 1:
906 break;
907 /* fatal error, abort */
908 case -1:
909 goto errcleanup;
910 }
911 }
912
914 m_save = mx_path_resolve(buf_string(buf));
915 bool old_append = m_save->append;
916 OpenMailboxFlags mbox_flags = MUTT_NEWFOLDER;
917 /* Display a tagged message progress counter, rather than (for
918 * IMAP) a per-message progress counter */
919 if (msg_count > 1)
920 mbox_flags |= MUTT_QUIET;
921 if (!mx_mbox_open(m_save, mbox_flags))
922 {
923 rc = -1;
924 mailbox_free(&m_save);
925 goto errcleanup;
926 }
927 m_save->append = true;
928
929 /* If we're saving to a compressed mailbox, the stats won't be updated
930 * until the next open. Until then, improvise. */
931 struct Mailbox *m_comp = NULL;
932 if (m_save->compress_info)
933 {
934 m_comp = mailbox_find(m_save->realpath);
935 }
936 /* We probably haven't been opened yet */
937 if (m_comp && (m_comp->msg_count == 0))
938 m_comp = NULL;
939
940 if (msg_count == 1)
941 {
942 rc = mutt_save_message_mbox(m, e_cur, save_opt, transform_opt, m_save);
943 if (rc != 0)
944 {
945 mx_mbox_close(m_save);
946 m_save->append = old_append;
947 goto errcleanup;
948 }
949
950 if (m_comp)
951 {
952 m_comp->msg_count++;
953 if (!e_cur->read)
954 {
955 m_comp->msg_unread++;
956 if (!e_cur->old)
957 m_comp->msg_new++;
958 }
959 if (e_cur->flagged)
960 m_comp->msg_flagged++;
961 }
962 }
963 else
964 {
965 rc = 0;
966
967#ifdef USE_NOTMUCH
968 if (m->type == MUTT_NOTMUCH)
969 nm_db_longrun_init(m, true);
970#endif
971 struct Progress *progress = progress_new(MUTT_PROGRESS_WRITE, msg_count);
972 progress_set_message(progress, "%s", progress_msg);
973 struct Email **ep = NULL;
974 ARRAY_FOREACH(ep, ea)
975 {
976 struct Email *e = *ep;
977 progress_update(progress, ++tagged_progress_count, -1);
979 rc = mutt_save_message_mbox(m, e, save_opt, transform_opt, m_save);
980 if (rc != 0)
981 break;
982
983 if (m_comp)
984 {
985 struct Email *e2 = e;
986 m_comp->msg_count++;
987 if (!e2->read)
988 {
989 m_comp->msg_unread++;
990 if (!e2->old)
991 m_comp->msg_new++;
992 }
993 if (e2->flagged)
994 m_comp->msg_flagged++;
995 }
996 }
997 progress_free(&progress);
998
999#ifdef USE_NOTMUCH
1000 if (m->type == MUTT_NOTMUCH)
1002#endif
1003 if (rc != 0)
1004 {
1005 mx_mbox_close(m_save);
1006 m_save->append = old_append;
1007 goto errcleanup;
1008 }
1009 }
1010
1011 const bool need_mailbox_cleanup = ((m_save->type == MUTT_MBOX) ||
1012 (m_save->type == MUTT_MMDF));
1013
1014 mx_mbox_close(m_save);
1015 m_save->append = old_append;
1016
1017 if (need_mailbox_cleanup)
1019
1021 rc = 0;
1022
1023errcleanup:
1024 if (rc != 0)
1025 {
1026 switch (save_opt)
1027 {
1028 case SAVE_MOVE:
1029 if (msg_count > 1)
1030 {
1031 // L10N: Message when an index tagged save operation fails for some reason
1032 mutt_error(_("Error saving tagged messages"));
1033 }
1034 else
1035 {
1036 // L10N: Message when an index/pager save operation fails for some reason
1037 mutt_error(_("Error saving message"));
1038 }
1039 break;
1040 case SAVE_COPY:
1041 if (msg_count > 1)
1042 {
1043 // L10N: Message when an index tagged copy operation fails for some reason
1044 mutt_error(_("Error copying tagged messages"));
1045 }
1046 else
1047 {
1048 // L10N: Message when an index/pager copy operation fails for some reason
1049 mutt_error(_("Error copying message"));
1050 }
1051 break;
1052 }
1053 }
1054
1055 mailbox_free(&m_save);
1056
1057cleanup:
1058 buf_pool_release(&buf);
1059 return rc;
1060}
#define ARRAY_GET(head, idx)
Return the element at index.
Definition: array.h:109
#define MUTT_SEL_NO_FLAGS
No flags are set.
Definition: lib.h:57
size_t buf_len(const struct Buffer *buf)
Calculate the length of a Buffer.
Definition: buffer.c:490
void buf_alloc(struct Buffer *buf, size_t new_size)
Make sure a buffer can store at least new_size bytes.
Definition: buffer.c:336
void mailbox_free(struct Mailbox **ptr)
Free a Mailbox.
Definition: mailbox.c:90
struct Mailbox * mailbox_find(const char *path)
Find the mailbox with a given path.
Definition: mailbox.c:151
MailboxType
Supported mailbox formats.
Definition: mailbox.h:41
@ MUTT_NOTMUCH
'Notmuch' (virtual) Mailbox type
Definition: mailbox.h:51
@ MUTT_MMDF
'mmdf' Mailbox type
Definition: mailbox.h:46
@ MUTT_IMAP
'IMAP' Mailbox type
Definition: mailbox.h:50
@ MUTT_MBOX
'mbox' Mailbox type
Definition: mailbox.h:45
bool crypt_valid_passphrase(SecurityFlags flags)
Check that we have a usable passphrase, ask if not.
Definition: crypt.c:132
int mutt_save_message_mbox(struct Mailbox *m_src, struct Email *e, enum MessageSaveOpt save_opt, enum MessageTransformOpt transform_opt, struct Mailbox *m_dst)
Save a message to a given mailbox.
Definition: external.c:738
void mutt_file_resolve_symlink(struct Buffer *buf)
Resolve a symlink in place.
Definition: file.c:1656
void mutt_set_flag(struct Mailbox *m, struct Email *e, enum MessageType flag, bool bf, bool upd_mbox)
Set a flag on an email.
Definition: flags.c:57
int mw_enter_fname(const char *prompt, struct Buffer *fname, bool mailbox, struct Mailbox *m, bool multiple, char ***files, int *numfiles, SelectFileFlags flags)
Ask the user to select a file -.
Definition: curs_lib.c:236
enum MailboxType imap_path_probe(const char *path, const struct stat *st)
Is this an IMAP Mailbox? - Implements MxOps::path_probe() -.
Definition: imap.c:2344
void mutt_default_save(struct Buffer *path, struct Email *e)
Find the default save path for an email.
Definition: hook.c:770
void mutt_message_hook(struct Mailbox *m, struct Email *e, HookFlags type)
Perform a message hook.
Definition: hook.c:692
#define MUTT_MESSAGE_HOOK
message-hook: run before displaying a message
Definition: hook.h:44
int imap_copy_messages(struct Mailbox *m, struct EmailArray *ea, const char *dest, enum MessageSaveOpt save_opt)
Server COPY messages to another folder.
Definition: message.c:1687
bool mutt_path_tidy(struct Buffer *path, bool is_dir)
Remove unnecessary parts of a path.
Definition: path.c:168
bool mutt_str_equal(const char *a, const char *b)
Compare two strings.
Definition: string.c:709
@ MUTT_TAG
Tagged messages.
Definition: mutt.h:80
#define PATH_MAX
Definition: mutt.h:42
void mutt_clear_error(void)
Clear the message line (bottom line of screen)
Definition: mutt_logging.c:74
void mailbox_restore_timestamp(const char *path, struct stat *st)
Restore the timestamp of a mailbox.
Definition: mutt_mailbox.c:405
void buf_pretty_mailbox(struct Buffer *buf)
Shorten a mailbox path using '~' or '='.
Definition: muttlib.c:554
int mutt_save_confirm(const char *s, struct stat *st)
Ask the user to save.
Definition: muttlib.c:781
bool mx_mbox_open(struct Mailbox *m, OpenMailboxFlags flags)
Open a mailbox and parse it.
Definition: mx.c:286
struct Mailbox * mx_path_resolve(const char *path)
Get a Mailbox for a path.
Definition: mx.c:1634
enum MxStatus mx_mbox_close(struct Mailbox *m)
Save changes and close mailbox.
Definition: mx.c:596
uint8_t OpenMailboxFlags
Flags for mutt_open_mailbox(), e.g. MUTT_NOSORT.
Definition: mxapi.h:39
#define MUTT_NEWFOLDER
Create a new folder - same as MUTT_APPEND, but uses mutt_file_fopen() with mode "w" for mbox-style fo...
Definition: mxapi.h:45
#define MUTT_QUIET
Do not print any messages.
Definition: mxapi.h:44
uint16_t SecurityFlags
Flags, e.g. SEC_ENCRYPT.
Definition: lib.h:76
#define SEC_ENCRYPT
Email is encrypted.
Definition: lib.h:78
void nm_db_longrun_done(struct Mailbox *m)
Finish a long transaction.
Definition: db.c:378
void nm_db_longrun_init(struct Mailbox *m, bool writable)
Start a long transaction.
Definition: db.c:363
@ MUTT_PROGRESS_WRITE
Progress tracks elements, according to $write_inc
Definition: lib.h:83
struct Progress * progress_new(enum ProgressType type, size_t size)
Create a new Progress Bar.
Definition: progress.c:139
void progress_free(struct Progress **ptr)
Free a Progress Bar.
Definition: progress.c:110
void progress_set_message(struct Progress *progress, const char *fmt,...) __attribute__((__format__(__printf__
bool progress_update(struct Progress *progress, size_t pos, int percent)
Update the state of the progress bar.
Definition: progress.c:80
bool read
Email is read.
Definition: email.h:50
bool old
Email is seen, but unread.
Definition: email.h:49
bool flagged
Marked important?
Definition: email.h:47
A mailbox.
Definition: mailbox.h:79
char * realpath
Used for duplicate detection, context comparison, and the sidebar.
Definition: mailbox.h:81
bool append
Mailbox is opened in append mode.
Definition: mailbox.h:109
int msg_new
Number of new messages.
Definition: mailbox.h:92
int msg_count
Total number of messages.
Definition: mailbox.h:88
enum MailboxType type
Mailbox type.
Definition: mailbox.h:102
int msg_flagged
Number of flagged messages.
Definition: mailbox.h:90
void * compress_info
Compressed mbox module private data.
Definition: mailbox.h:121
int msg_unread
Number of unread messages.
Definition: mailbox.h:89
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mutt_save_message_mbox()

int mutt_save_message_mbox ( struct Mailbox m_src,
struct Email e,
enum MessageSaveOpt  save_opt,
enum MessageTransformOpt  transform_opt,
struct Mailbox m_dst 
)

Save a message to a given mailbox.

Parameters
m_srcMailbox to copy from
eEmail
save_optCopy or move, e.g. SAVE_MOVE
transform_optTransformation, e.g. TRANSFORM_DECRYPT
m_dstMailbox to save to
Return values
0Success
-1Error

Definition at line 738 of file external.c.

740{
743 int rc;
744
745 set_copy_flags(e, transform_opt, &cmflags, &chflags);
746
747 struct Message *msg = mx_msg_open(m_src, e);
748 if (msg && transform_opt != TRANSFORM_NONE)
749 {
751 }
752
753 rc = mutt_append_message(m_dst, m_src, e, msg, cmflags, chflags);
754 mx_msg_close(m_src, &msg);
755 if (rc != 0)
756 return rc;
757
758 if (save_opt == SAVE_MOVE)
759 {
760 mutt_set_flag(m_src, e, MUTT_DELETE, true, true);
761 mutt_set_flag(m_src, e, MUTT_PURGE, true, true);
762 const bool c_delete_untag = cs_subset_bool(NeoMutt->sub, "delete_untag");
763 if (c_delete_untag)
764 mutt_set_flag(m_src, e, MUTT_TAG, false, true);
765 }
766
767 return 0;
768}
void mutt_parse_mime_message(struct Email *e, FILE *fp)
Parse a MIME email.
Definition: attachments.c:597
int mutt_append_message(struct Mailbox *m_dst, struct Mailbox *m_src, struct Email *e, struct Message *msg, CopyMessageFlags cmflags, CopyHeaderFlags chflags)
Append a message.
Definition: copy.c:982
uint32_t CopyHeaderFlags
Flags for mutt_copy_header(), e.g. CH_UPDATE.
Definition: copy.h:52
#define MUTT_CM_NO_FLAGS
No flags are set.
Definition: copy.h:37
uint16_t CopyMessageFlags
Flags for mutt_copy_message(), e.g. MUTT_CM_NOHEADER.
Definition: copy.h:36
#define CH_NO_FLAGS
No flags are set.
Definition: copy.h:53
static void set_copy_flags(struct Email *e, enum MessageTransformOpt transform_opt, CopyMessageFlags *cmflags, CopyHeaderFlags *chflags)
Set the flags for a message copy.
Definition: external.c:687
@ MUTT_PURGE
Messages to be purged (bypass trash)
Definition: mutt.h:77
@ MUTT_DELETE
Messages to be deleted.
Definition: mutt.h:75
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mutt_select_sort()

bool mutt_select_sort ( bool  reverse)

Ask the user for a sort method.

Parameters
reverseIf true make it a reverse sort
Return values
trueThe sort type changed

Definition at line 477 of file external.c.

478{
479 enum SortType sort = SORT_DATE;
480
481 switch (mw_multi_choice(reverse ?
482 /* L10N: The highlighted letters must match the "Sort" options */
483 _("Rev-Sort (d)ate,(f)rm,(r)ecv,(s)ubj,t(o),(t)hread,(u)nsort,si(z)e,s(c)ore,s(p)am,(l)abel?") :
484 /* L10N: The highlighted letters must match the "Rev-Sort" options */
485 _("Sort (d)ate,(f)rm,(r)ecv,(s)ubj,t(o),(t)hread,(u)nsort,si(z)e,s(c)ore,s(p)am,(l)abel?"),
486 /* L10N: These must match the highlighted letters from "Sort" and "Rev-Sort" */
487 _("dfrsotuzcpl")))
488 {
489 case -1: /* abort - don't resort */
490 return false;
491
492 case 1: /* (d)ate */
493 sort = SORT_DATE;
494 break;
495
496 case 2: /* (f)rm */
497 sort = SORT_FROM;
498 break;
499
500 case 3: /* (r)ecv */
501 sort = SORT_RECEIVED;
502 break;
503
504 case 4: /* (s)ubj */
505 sort = SORT_SUBJECT;
506 break;
507
508 case 5: /* t(o) */
509 sort = SORT_TO;
510 break;
511
512 case 6: /* (t)hread */
513 sort = SORT_THREADS;
514 break;
515
516 case 7: /* (u)nsort */
517 sort = SORT_ORDER;
518 break;
519
520 case 8: /* si(z)e */
521 sort = SORT_SIZE;
522 break;
523
524 case 9: /* s(c)ore */
525 sort = SORT_SCORE;
526 break;
527
528 case 10: /* s(p)am */
529 sort = SORT_SPAM;
530 break;
531
532 case 11: /* (l)abel */
533 sort = SORT_LABEL;
534 break;
535 }
536
537 const unsigned char c_use_threads = cs_subset_enum(NeoMutt->sub, "use_threads");
538 const enum SortType c_sort = cs_subset_sort(NeoMutt->sub, "sort");
539 int rc = CSR_ERR_CODE;
540 if ((sort != SORT_THREADS) || (c_use_threads == UT_UNSET))
541 {
542 if ((sort != SORT_THREADS) && (c_sort & SORT_LAST))
543 sort |= SORT_LAST;
544 if (reverse)
545 sort |= SORT_REVERSE;
546
547 rc = cs_subset_str_native_set(NeoMutt->sub, "sort", sort, NULL);
548 }
549 else
550 {
551 assert((c_sort & SORT_MASK) != SORT_THREADS); /* See index_config_observer() */
552 /* Preserve the value of $sort, and toggle whether we are threaded. */
553 switch (c_use_threads)
554 {
555 case UT_FLAT:
556 rc = cs_subset_str_native_set(NeoMutt->sub, "use_threads",
557 reverse ? UT_REVERSE : UT_THREADS, NULL);
558 break;
559 case UT_THREADS:
560 rc = cs_subset_str_native_set(NeoMutt->sub, "use_threads",
561 reverse ? UT_REVERSE : UT_FLAT, NULL);
562 break;
563 case UT_REVERSE:
564 rc = cs_subset_str_native_set(NeoMutt->sub, "use_threads",
565 reverse ? UT_FLAT : UT_THREADS, NULL);
566 break;
567 default:
568 assert(false);
569 }
570 }
571
572 return ((CSR_RESULT(rc) == CSR_SUCCESS) && !(rc & CSR_SUC_NO_CHANGE));
573}
unsigned char cs_subset_enum(const struct ConfigSubset *sub, const char *name)
Get a enumeration config item by name.
Definition: helpers.c:72
short cs_subset_sort(const struct ConfigSubset *sub, const char *name)
Get a sort config item by name.
Definition: helpers.c:267
#define CSR_SUC_NO_CHANGE
The value hasn't changed.
Definition: set.h:44
#define CSR_ERR_CODE
Problem with the code.
Definition: set.h:36
#define CSR_RESULT(x)
Definition: set.h:52
#define CSR_SUCCESS
Action completed successfully.
Definition: set.h:35
int mw_multi_choice(const char *prompt, const char *letters)
Offer the user a multiple choice question -.
Definition: question.c:64
@ UT_FLAT
Unthreaded.
Definition: mutt_thread.h:99
@ UT_UNSET
Not yet set by user, stick to legacy semantics.
Definition: mutt_thread.h:98
@ UT_THREADS
Normal threading (root above subthreads)
Definition: mutt_thread.h:100
@ UT_REVERSE
Reverse threading (subthreads above root)
Definition: mutt_thread.h:101
#define SORT_MASK
Mask for the sort id.
Definition: sort2.h:70
#define SORT_LAST
Sort thread by last-X, e.g. received date.
Definition: sort2.h:72
SortType
Methods for sorting.
Definition: sort2.h:34
@ SORT_SUBJECT
Sort by the email's subject.
Definition: sort2.h:38
@ SORT_ORDER
Sort by the order the messages appear in the mailbox.
Definition: sort2.h:40
@ SORT_THREADS
Sort by email threads.
Definition: sort2.h:41
@ SORT_SPAM
Sort by the email's spam score.
Definition: sort2.h:49
@ SORT_LABEL
Sort by the emails label.
Definition: sort2.h:54
@ SORT_FROM
Sort by the email's From field.
Definition: sort2.h:39
@ SORT_SIZE
Sort by the size of the email.
Definition: sort2.h:36
@ SORT_RECEIVED
Sort by when the message were delivered locally.
Definition: sort2.h:42
@ SORT_TO
Sort by the email's To field.
Definition: sort2.h:43
@ SORT_DATE
Sort by the date the email was sent.
Definition: sort2.h:35
@ SORT_SCORE
Sort by the email's score.
Definition: sort2.h:44
#define SORT_REVERSE
Reverse the order of the sort.
Definition: sort2.h:71
int cs_subset_str_native_set(const struct ConfigSubset *sub, const char *name, intptr_t value, struct Buffer *err)
Natively set the value of a string config item.
Definition: subset.c:297
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mutt_shell_escape()

bool mutt_shell_escape ( void  )

Invoke a command in a subshell.

Return values
trueA command was invoked (no matter what its result)
falseNo command was invoked

Definition at line 580 of file external.c.

581{
582 bool rc = false;
583 struct Buffer *buf = buf_pool_get();
584
585 if (mw_get_field(_("Shell command: "), buf, MUTT_COMP_NO_FLAGS,
586 HC_EXT_COMMAND, &CompleteFileOps, NULL) != 0)
587 {
588 goto done;
589 }
590
591 if (buf_is_empty(buf))
592 {
593 const char *const c_shell = cs_subset_string(NeoMutt->sub, "shell");
594 buf_strcpy(buf, c_shell);
595 }
596
597 if (buf_is_empty(buf))
598 {
599 goto done;
600 }
601
602 msgwin_clear_text(NULL);
603 mutt_endwin();
604 fflush(stdout);
605 int rc2 = mutt_system(buf_string(buf));
606 if (rc2 == -1)
607 mutt_debug(LL_DEBUG1, "Error running \"%s\"\n", buf_string(buf));
608
609 const bool c_wait_key = cs_subset_bool(NeoMutt->sub, "wait_key");
610 if ((rc2 != 0) || c_wait_key)
612
613 rc = true;
614done:
615 buf_pool_release(&buf);
616 return rc;
617}
int mutt_any_key_to_continue(const char *s)
Prompt the user to 'press any key' and wait.
Definition: curs_lib.c:173
void mutt_endwin(void)
Shutdown curses.
Definition: curs_lib.c:151
#define mutt_debug(LEVEL,...)
Definition: logging2.h:89
@ LL_DEBUG1
Log at debug level 1.
Definition: logging2.h:43
int mutt_system(const char *cmd)
Run an external command.
Definition: system.c:51
+ Here is the call graph for this function:
+ Here is the caller graph for this function: