NeoMutt  2025-09-05-70-gcfdde0
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 (struct MuttWindow *win)
 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 41 of file external.h.

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

◆ 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 51 of file external.h.

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

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 90 of file external.c.

91{
92 if (!m || !ea || ARRAY_EMPTY(ea))
93 return;
94
95 struct Buffer *buf = buf_pool_get();
96 struct Buffer *prompt = buf_pool_get();
97 struct AddressList al = TAILQ_HEAD_INITIALIZER(al);
98 char *err = NULL;
99 int rc;
100 int msg_count = 0;
101
102 struct Email **ep = NULL;
103 ARRAY_FOREACH(ep, ea)
104 {
105 struct Email *e = *ep;
106 /* RFC5322 mandates a From: header,
107 * so warn before bouncing messages without one */
108 if (TAILQ_EMPTY(&e->env->from))
109 mutt_error(_("Warning: message contains no From: header"));
110
111 msg_count++;
112 }
113
114 if (msg_count == 1)
115 buf_strcpy(prompt, _("Bounce message to: "));
116 else
117 buf_strcpy(prompt, _("Bounce tagged messages to: "));
118
120 &CompleteAliasOps, NULL);
121 if ((rc != 0) || buf_is_empty(buf))
122 goto done;
123
125 if (TAILQ_EMPTY(&al))
126 {
127 mutt_error(_("Error parsing address"));
128 goto done;
129 }
130
132
133 if (mutt_addrlist_to_intl(&al, &err) < 0)
134 {
135 mutt_error(_("Bad IDN: '%s'"), err);
136 FREE(&err);
137 goto done;
138 }
139
140 buf_reset(buf);
141 mutt_addrlist_write(&al, buf, true);
142
143 buf_printf(prompt, ngettext("Bounce message to %s?", "Bounce messages to %s?", msg_count),
144 buf_string(buf));
145
146 if (query_quadoption(buf_string(prompt), NeoMutt->sub, "bounce") != MUTT_YES)
147 {
148 msgwin_clear_text(NULL);
149 mutt_message(ngettext("Message not bounced", "Messages not bounced", msg_count));
150 goto done;
151 }
152
153 msgwin_clear_text(NULL);
154
155 struct Message *msg = NULL;
156 ARRAY_FOREACH(ep, ea)
157 {
158 struct Email *e = *ep;
159 msg = mx_msg_open(m, e);
160 if (!msg)
161 {
162 rc = -1;
163 break;
164 }
165
166 rc = mutt_bounce_message(msg->fp, m, e, &al, NeoMutt->sub);
167 mx_msg_close(m, &msg);
168
169 if (rc < 0)
170 break;
171 }
172
173 /* If no error, or background, display message. */
174 if ((rc == 0) || (rc == S_BKG))
175 mutt_message(ngettext("Message bounced", "Messages bounced", msg_count));
176
177done:
179 buf_pool_release(&buf);
180 buf_pool_release(&prompt);
181}
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:294
#define ARRAY_FOREACH(elem, head)
Iterate over all elements of the array.
Definition array.h:214
#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:161
void buf_reset(struct Buffer *buf)
Reset an existing Buffer.
Definition buffer.c:76
bool buf_is_empty(const struct Buffer *buf)
Is the Buffer empty?
Definition buffer.c:291
size_t buf_strcpy(struct Buffer *buf, const char *s)
Copy a string into a Buffer.
Definition buffer.c:395
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:272
#define mutt_error(...)
Definition logging2.h:93
#define mutt_message(...)
Definition logging2.h:92
@ HC_ALIAS
Aliases.
Definition lib.h:55
#define FREE(x)
Definition memory.h:62
void msgwin_clear_text(struct MuttWindow *win)
Clear the text in the Message Window.
Definition msgwin.c:518
#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:1185
struct Message * mx_msg_open(struct Mailbox *m, struct Email *e)
Return a stream pointer for a message.
Definition mx.c:1139
struct Buffer * buf_pool_get(void)
Get a Buffer from the pool.
Definition pool.c:82
void buf_pool_release(struct Buffer **ptr)
Return a Buffer to the pool.
Definition pool.c:96
@ MUTT_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:377
#define TAILQ_HEAD_INITIALIZER(head)
Definition queue.h:694
#define TAILQ_EMPTY(head)
Definition queue.h:778
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:47
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:42
struct ConfigSubset * sub
Inherited config items.
Definition neomutt.h:46
+ 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 1214 of file external.c.

1215{
1216 bool rc = false;
1217
1218 struct Email **ep = NULL;
1219 ARRAY_FOREACH(ep, ea)
1220 {
1221 struct Email *e = *ep;
1223 rc = check_traditional_pgp(m, e) || rc;
1224 }
1225
1226 return rc;
1227}
static bool check_traditional_pgp(struct Mailbox *m, struct Email *e)
Check for an inline PGP content.
Definition external.c:1186
#define PGP_TRADITIONAL_CHECKED
Email has a traditional (inline) signature.
Definition lib.h:98
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 80 of file external.c.

81{
83}
void buf_dealloc(struct Buffer *buf)
Release the memory allocated by a buffer.
Definition buffer.c:377
static struct Buffer LastSaveFolder
The folder the user last saved to. Used by ci_save_message()
Definition external.c:75
+ 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 664 of file external.c.

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

1074{
1075 struct Buffer *buf = buf_pool_get();
1076 struct Buffer *charset = buf_pool_get();
1077 struct Buffer *obuf = buf_pool_get();
1078 struct Buffer *tmp = buf_pool_get();
1079
1080 bool rc = false;
1081 bool charset_changed = false;
1082 bool type_changed = false;
1083 bool structure_changed = false;
1084
1085 char *cp = mutt_param_get(&b->parameter, "charset");
1086 buf_strcpy(charset, cp);
1087
1088 buf_printf(buf, "%s/%s", BODY_TYPE(b), b->subtype);
1089 buf_copy(obuf, buf);
1090 if (!TAILQ_EMPTY(&b->parameter))
1091 {
1092 struct Parameter *np = NULL;
1093 TAILQ_FOREACH(np, &b->parameter, entries)
1094 {
1095 mutt_addr_cat(tmp->data, tmp->dsize, np->value, MimeSpecials);
1096 buf_add_printf(buf, "; %s=%s", np->attribute, buf_string(tmp));
1097 }
1098 }
1099
1100 if ((mw_get_field("Content-Type: ", buf, MUTT_COMP_NO_FLAGS, HC_OTHER, NULL, NULL) != 0) ||
1101 buf_is_empty(buf))
1102 {
1103 goto done;
1104 }
1105
1106 /* clean up previous junk */
1108 FREE(&b->subtype);
1109
1111
1112 buf_printf(tmp, "%s/%s", BODY_TYPE(b), NONULL(b->subtype));
1113 type_changed = !mutt_istr_equal(buf_string(tmp), buf_string(obuf));
1114 charset_changed = !mutt_istr_equal(buf_string(charset),
1115 mutt_param_get(&b->parameter, "charset"));
1116
1117 /* if in send mode, check for conversion - current setting is default. */
1118
1119 if (!e && (b->type == TYPE_TEXT) && charset_changed)
1120 {
1121 buf_printf(tmp, _("Convert to %s upon sending?"),
1122 mutt_param_get(&b->parameter, "charset"));
1123 enum QuadOption ans = query_yesorno(buf_string(tmp), b->noconv ? MUTT_NO : MUTT_YES);
1124 if (ans != MUTT_ABORT)
1125 b->noconv = (ans == MUTT_NO);
1126 }
1127
1128 /* inform the user */
1129
1130 buf_printf(tmp, "%s/%s", BODY_TYPE(b), NONULL(b->subtype));
1131 if (type_changed)
1132 mutt_message(_("Content-Type changed to %s"), buf_string(tmp));
1133 if ((b->type == TYPE_TEXT) && charset_changed)
1134 {
1135 if (type_changed)
1136 mutt_sleep(1);
1137 mutt_message(b->noconv ? _("Character set changed to %s; not converting") :
1138 _("Character set changed to %s; converting"),
1139 mutt_param_get(&b->parameter, "charset"));
1140 }
1141
1142 b->force_charset |= charset_changed;
1143
1144 if (!is_multipart(b) && b->parts)
1145 {
1146 structure_changed = true;
1147 mutt_body_free(&b->parts);
1148 }
1149 if (!mutt_is_message_type(b->type, b->subtype) && b->email)
1150 {
1151 structure_changed = true;
1152 b->email->body = NULL;
1153 email_free(&b->email);
1154 }
1155
1156 if (fp && !b->parts && (is_multipart(b) || mutt_is_message_type(b->type, b->subtype)))
1157 {
1158 structure_changed = true;
1159 mutt_parse_part(fp, b);
1160 }
1161
1162 if ((WithCrypto != 0) && e)
1163 {
1164 if (e->body == b)
1166
1167 e->security |= crypt_query(b);
1168 }
1169
1170 rc = structure_changed | type_changed;
1171
1172done:
1173 buf_pool_release(&buf);
1174 buf_pool_release(&charset);
1175 buf_pool_release(&obuf);
1176 buf_pool_release(&tmp);
1177 return rc;
1178}
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:204
size_t buf_copy(struct Buffer *dst, const struct Buffer *src)
Copy a Buffer's contents to another Buffer.
Definition buffer.c:601
SecurityFlags crypt_query(struct Body *b)
Check out the type of encryption used.
Definition crypt.c:687
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:1821
void mutt_parse_content_type(const char *s, struct Body *b)
Parse a content type.
Definition parse.c:462
bool mutt_is_message_type(int type, const char *subtype)
Determine if a mime type matches a message or not.
Definition parse.c:1497
@ HC_OTHER
Miscellaneous strings.
Definition lib.h:59
const char MimeSpecials[]
Characters that need special treatment in MIME.
Definition mime.c:67
@ TYPE_TEXT
Type: 'text/*'.
Definition mime.h:38
#define BODY_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:672
void mutt_sleep(short s)
Sleep for a while.
Definition muttlib.c:841
#define SEC_NO_FLAGS
No flags are set.
Definition lib.h:83
#define WithCrypto
Definition lib.h:122
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:325
#define TAILQ_FOREACH(var, head, field)
Definition queue.h:782
#define NONULL(x)
Definition string2.h:43
struct Body * parts
parts of a multipart or message/rfc822
Definition body.h:73
bool noconv
Don't do character set conversion.
Definition body.h:46
struct ParameterList parameter
Parameters of the content-type.
Definition body.h:63
struct Email * email
header information for message/rfc822
Definition body.h:74
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:61
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 ( struct MuttWindow * win)

Enter a neomutt command.

Parameters
winFocused Window

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
629 /* if enter is pressed after : with no command, just return */
630 struct FileCompletionData cdata = { false, NULL, NULL, NULL, win };
632 &CompleteCommandOps, &cdata) != 0) ||
633 buf_is_empty(buf))
634 {
635 goto done;
636 }
637
638 enum CommandResult rc = parse_rc_line(buf_string(buf), err);
639 if (!buf_is_empty(err))
640 {
641 if (rc == MUTT_CMD_SUCCESS) /* command succeeded with message */
642 mutt_message("%s", buf_string(err));
643 else if (rc == MUTT_CMD_ERROR)
644 mutt_error("%s", buf_string(err));
645 else if (rc == MUTT_CMD_WARNING)
646 mutt_warning("%s", buf_string(err));
647 }
648
649 if (NeoMutt)
650 {
651 // Running commands could cause anything to change, so let others know
653 }
654
655done:
656 buf_pool_release(&buf);
657 buf_pool_release(&err);
658}
CommandResult
Error codes for command_t parse functions.
Definition command.h:35
@ MUTT_CMD_SUCCESS
Success: Command worked.
Definition command.h:38
@ MUTT_CMD_ERROR
Error: Can't help the user.
Definition command.h:36
@ MUTT_CMD_WARNING
Warning: Help given to the user.
Definition command.h:37
const struct CompleteOps CompleteCommandOps
Auto-Completion of Commands.
Definition helpers.c:492
#define mutt_warning(...)
Definition logging2.h:91
@ HC_NEO_COMMAND
NeoMutt commands.
Definition lib.h:56
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.
@ NT_GLOBAL_COMMAND
A NeoMutt command.
Definition neomutt.h:68
@ 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:109
Input for the file completion function.
Definition curs_lib.h:39
struct MuttWindow * win
Current Focused Window.
Definition curs_lib.h:44
struct Notify * notify
Notifications handler.
Definition neomutt.h:43
+ 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 407 of file external.c.

408{
409 if (!m || !ea)
410 return;
411
412 struct Buffer *buf = buf_pool_get();
413
414 if (mw_get_field(_("Pipe to command: "), buf, MUTT_COMP_NO_FLAGS,
415 HC_EXT_COMMAND, &CompleteFileOps, NULL) != 0)
416 {
417 goto cleanup;
418 }
419
420 if (buf_is_empty(buf))
421 goto cleanup;
422
423 buf_expand_path(buf);
424 const bool c_pipe_decode = cs_subset_bool(NeoMutt->sub, "pipe_decode");
425 const bool c_pipe_split = cs_subset_bool(NeoMutt->sub, "pipe_split");
426 const char *const c_pipe_sep = cs_subset_string(NeoMutt->sub, "pipe_sep");
427 pipe_message(m, ea, buf_string(buf), c_pipe_decode, false, c_pipe_split, c_pipe_sep);
428
429cleanup:
430 buf_pool_release(&buf);
431}
const struct CompleteOps CompleteFileOps
Auto-Completion of Files.
Definition complete.c:152
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
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:278
@ HC_EXT_COMMAND
External commands.
Definition lib.h:54
void buf_expand_path(struct Buffer *buf)
Create the canonical path.
Definition muttlib.c:314
+ 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 438 of file external.c.

439{
440 if (!m || !ea)
441 return;
442
443 const enum QuadOption c_print = cs_subset_quad(NeoMutt->sub, "print");
444 const char *const c_print_command = cs_subset_string(NeoMutt->sub, "print_command");
445 if (c_print && !c_print_command)
446 {
447 mutt_message(_("No printing command has been defined"));
448 return;
449 }
450
451 int msg_count = ARRAY_SIZE(ea);
452 const char *msg = ngettext("Print message?", "Print tagged messages?", msg_count);
453 if (query_quadoption(msg, NeoMutt->sub, "print") != MUTT_YES)
454 {
455 return;
456 }
457
458 const bool c_print_decode = cs_subset_bool(NeoMutt->sub, "print_decode");
459 const bool c_print_split = cs_subset_bool(NeoMutt->sub, "print_split");
460 if (pipe_message(m, ea, c_print_command, c_print_decode, true, c_print_split, "\f") == 0)
461 {
462 mutt_message(ngettext("Message printed", "Messages printed", msg_count));
463 }
464 else
465 {
466 mutt_message(ngettext("Message could not be printed",
467 "Messages could not be printed", msg_count));
468 }
469}
#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:192
+ 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 781 of file external.c.

783{
784 if (!ea || ARRAY_EMPTY(ea))
785 return -1;
786
787 int rc = -1;
788 int tagged_progress_count = 0;
789 unsigned int msg_count = ARRAY_SIZE(ea);
790 struct Mailbox *m_save = NULL;
791
792 struct Buffer *buf = buf_pool_get();
793 struct stat st = { 0 };
794 struct Email *e_cur = *ARRAY_GET(ea, 0);
795
796 const SecurityFlags security_flags = WithCrypto ? e_cur->security : SEC_NO_FLAGS;
797 const bool is_passphrase_needed = security_flags & SEC_ENCRYPT;
798
799 const char *prompt = NULL;
800 const char *progress_msg = NULL;
801
802 // Set prompt and progress_msg
803 switch (save_opt)
804 {
805 case SAVE_COPY:
806 // L10N: Progress meter message when copying tagged messages
807 progress_msg = (msg_count > 1) ? _("Copying tagged messages...") : NULL;
808 switch (transform_opt)
809 {
810 case TRANSFORM_NONE:
811 prompt = (msg_count > 1) ? _("Copy tagged to mailbox") : _("Copy to mailbox");
812 break;
814 prompt = (msg_count > 1) ? _("Decrypt-copy tagged to mailbox") :
815 _("Decrypt-copy to mailbox");
816 break;
817 case TRANSFORM_DECODE:
818 prompt = (msg_count > 1) ? _("Decode-copy tagged to mailbox") :
819 _("Decode-copy to mailbox");
820 break;
821 }
822 break;
823
824 case SAVE_MOVE:
825 // L10N: Progress meter message when saving tagged messages
826 progress_msg = (msg_count > 1) ? _("Saving tagged messages...") : NULL;
827 switch (transform_opt)
828 {
829 case TRANSFORM_NONE:
830 prompt = (msg_count > 1) ? _("Save tagged to mailbox") : _("Save to mailbox");
831 break;
833 prompt = (msg_count > 1) ? _("Decrypt-save tagged to mailbox") :
834 _("Decrypt-save to mailbox");
835 break;
836 case TRANSFORM_DECODE:
837 prompt = (msg_count > 1) ? _("Decode-save tagged to mailbox") :
838 _("Decode-save to mailbox");
839 break;
840 }
841 break;
842 }
843
845 mutt_default_save(buf, e_cur);
847
848 if (mw_enter_fname(prompt, buf, false, NULL, false, NULL, NULL, MUTT_SEL_NO_FLAGS) == -1)
849 {
850 goto cleanup;
851 }
852
853 size_t pathlen = buf_len(buf);
854 if (pathlen == 0)
855 goto cleanup;
856
857 mutt_path_tidy(buf, true);
858
859 /* This is an undocumented feature of ELM pointed out to me by Felix von
860 * Leitner <leitner@prz.fu-berlin.de> */
863 if (mutt_str_equal(buf_string(buf), "."))
865 else
867
868 buf_expand_path(buf);
869
870 /* check to make sure that this file is really the one the user wants */
871 if (mutt_save_confirm(buf_string(buf), &st) != 0)
872 goto cleanup;
873
874 if (is_passphrase_needed && (transform_opt != TRANSFORM_NONE) &&
875 !crypt_valid_passphrase(security_flags))
876 {
877 rc = -1;
878 goto errcleanup;
879 }
880
881 mutt_message(_("Copying to %s..."), buf_string(buf));
882
883 enum MailboxType mailbox_type = imap_path_probe(buf_string(buf), NULL);
884 if ((m->type == MUTT_IMAP) && (transform_opt == TRANSFORM_NONE) && (mailbox_type == MUTT_IMAP))
885 {
886 rc = imap_copy_messages(m, ea, buf_string(buf), save_opt);
887 switch (rc)
888 {
889 /* success */
890 case 0:
892 rc = 0;
893 if (save_opt == SAVE_MOVE)
894 {
895 const bool c_delete_untag = cs_subset_bool(NeoMutt->sub, "delete_untag");
896 if (c_delete_untag)
897 {
898 struct Email **ep = NULL;
899 ARRAY_FOREACH(ep, ea)
900 {
901 mutt_set_flag(m, *ep, MUTT_TAG, false, true);
902 }
903 }
904 }
905 goto cleanup;
906 /* non-fatal error: continue to fetch/append */
907 case 1:
908 break;
909 /* fatal error, abort */
910 case -1:
911 goto errcleanup;
912 }
913 }
914
916 m_save = mx_path_resolve(buf_string(buf));
917 bool old_append = m_save->append;
918 OpenMailboxFlags mbox_flags = MUTT_APPEND;
919 /* Display a tagged message progress counter, rather than (for
920 * IMAP) a per-message progress counter */
921 if (msg_count > 1)
922 mbox_flags |= MUTT_QUIET;
923 if (!mx_mbox_open(m_save, mbox_flags))
924 {
925 rc = -1;
926 mailbox_free(&m_save);
927 goto errcleanup;
928 }
929 m_save->append = true;
930
931 /* If we're saving to a compressed mailbox, the stats won't be updated
932 * until the next open. Until then, improvise. */
933 struct Mailbox *m_comp = NULL;
934 if (m_save->compress_info)
935 {
936 m_comp = mailbox_find(m_save->realpath);
937 }
938 /* We probably haven't been opened yet */
939 if (m_comp && (m_comp->msg_count == 0))
940 m_comp = NULL;
941
942 if (msg_count == 1)
943 {
944 rc = mutt_save_message_mbox(m, e_cur, save_opt, transform_opt, m_save);
945 if (rc != 0)
946 {
947 mx_mbox_close(m_save);
948 m_save->append = old_append;
949 goto errcleanup;
950 }
951
952 if (m_comp)
953 {
954 m_comp->msg_count++;
955 if (!e_cur->read)
956 {
957 m_comp->msg_unread++;
958 if (!e_cur->old)
959 m_comp->msg_new++;
960 }
961 if (e_cur->flagged)
962 m_comp->msg_flagged++;
963 }
964 }
965 else
966 {
967 rc = 0;
968
969#ifdef USE_NOTMUCH
970 if (m->type == MUTT_NOTMUCH)
971 nm_db_longrun_init(m, true);
972#endif
973 struct Progress *progress = progress_new(MUTT_PROGRESS_WRITE, msg_count);
974 progress_set_message(progress, "%s", progress_msg);
975 struct Email **ep = NULL;
976 ARRAY_FOREACH(ep, ea)
977 {
978 struct Email *e = *ep;
979 progress_update(progress, ++tagged_progress_count, -1);
981 rc = mutt_save_message_mbox(m, e, save_opt, transform_opt, m_save);
982 if (rc != 0)
983 break;
984
985 if (m_comp)
986 {
987 struct Email *e2 = e;
988 m_comp->msg_count++;
989 if (!e2->read)
990 {
991 m_comp->msg_unread++;
992 if (!e2->old)
993 m_comp->msg_new++;
994 }
995 if (e2->flagged)
996 m_comp->msg_flagged++;
997 }
998 }
999 progress_free(&progress);
1000
1001#ifdef USE_NOTMUCH
1002 if (m->type == MUTT_NOTMUCH)
1004#endif
1005 if (rc != 0)
1006 {
1007 mx_mbox_close(m_save);
1008 m_save->append = old_append;
1009 goto errcleanup;
1010 }
1011 }
1012
1013 const bool need_mailbox_cleanup = ((m_save->type == MUTT_MBOX) ||
1014 (m_save->type == MUTT_MMDF));
1015
1016 mx_mbox_close(m_save);
1017 m_save->append = old_append;
1018
1019 if (need_mailbox_cleanup)
1021
1023 rc = 0;
1024
1025errcleanup:
1026 if (rc != 0)
1027 {
1028 switch (save_opt)
1029 {
1030 case SAVE_MOVE:
1031 if (msg_count > 1)
1032 {
1033 // L10N: Message when an index tagged save operation fails for some reason
1034 mutt_error(_("Error saving tagged messages"));
1035 }
1036 else
1037 {
1038 // L10N: Message when an index/pager save operation fails for some reason
1039 mutt_error(_("Error saving message"));
1040 }
1041 break;
1042 case SAVE_COPY:
1043 if (msg_count > 1)
1044 {
1045 // L10N: Message when an index tagged copy operation fails for some reason
1046 mutt_error(_("Error copying tagged messages"));
1047 }
1048 else
1049 {
1050 // L10N: Message when an index/pager copy operation fails for some reason
1051 mutt_error(_("Error copying message"));
1052 }
1053 break;
1054 }
1055 }
1056
1057 mailbox_free(&m_save);
1058
1059cleanup:
1060 buf_pool_release(&buf);
1061 return rc;
1062}
#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:491
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
void mailbox_free(struct Mailbox **ptr)
Free a Mailbox.
Definition mailbox.c:89
struct Mailbox * mailbox_find(const char *path)
Find the mailbox with a given path.
Definition mailbox.c:150
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:131
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:740
void mutt_file_resolve_symlink(struct Buffer *buf)
Resolve a symlink in place.
Definition file.c:1552
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:56
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:237
enum MailboxType imap_path_probe(const char *path, const struct stat *st)
Is this an IMAP Mailbox?
Definition imap.c:2351
void mutt_default_save(struct Buffer *path, struct Email *e)
Find the default save path for an email.
Definition hook.c:777
void mutt_message_hook(struct Mailbox *m, struct Email *e, HookFlags type)
Perform a message hook.
Definition hook.c:699
#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:169
bool mutt_str_equal(const char *a, const char *b)
Compare two strings.
Definition string.c:660
@ 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)
void mailbox_restore_timestamp(const char *path, struct stat *st)
Restore the timestamp of a mailbox.
void buf_pretty_mailbox(struct Buffer *buf)
Shorten a mailbox path using '~' or '='.
Definition muttlib.c:518
int mutt_save_confirm(const char *s, struct stat *st)
Ask the user to save.
Definition muttlib.c:744
bool mx_mbox_open(struct Mailbox *m, OpenMailboxFlags flags)
Open a mailbox and parse it.
Definition mx.c:288
struct Mailbox * mx_path_resolve(const char *path)
Get a Mailbox for a path.
Definition mx.c:1650
enum MxStatus mx_mbox_close(struct Mailbox *m)
Save changes and close mailbox.
Definition mx.c:598
uint8_t OpenMailboxFlags
Flags for mutt_open_mailbox(), e.g. MUTT_NOSORT.
Definition mxapi.h:39
#define MUTT_APPEND
Open mailbox for appending messages.
Definition mxapi.h:42
#define MUTT_QUIET
Do not print any messages.
Definition mxapi.h:44
uint16_t SecurityFlags
Flags, e.g. SEC_ENCRYPT.
Definition lib.h:82
#define SEC_ENCRYPT
Email is encrypted.
Definition lib.h:84
void nm_db_longrun_done(struct Mailbox *m)
Finish a long transaction.
Definition db.c:379
void nm_db_longrun_init(struct Mailbox *m, bool writable)
Start a long transaction.
Definition db.c:364
@ MUTT_PROGRESS_WRITE
Progress tracks elements, according to $write_inc
Definition lib.h:84
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 740 of file external.c.

742{
745 int rc;
746
747 set_copy_flags(e, transform_opt, &cmflags, &chflags);
748
749 struct Message *msg = mx_msg_open(m_src, e);
750 if (msg && transform_opt != TRANSFORM_NONE)
751 {
753 }
754
755 rc = mutt_append_message(m_dst, m_src, e, msg, cmflags, chflags);
756 mx_msg_close(m_src, &msg);
757 if (rc != 0)
758 return rc;
759
760 if (save_opt == SAVE_MOVE)
761 {
762 mutt_set_flag(m_src, e, MUTT_DELETE, true, true);
763 mutt_set_flag(m_src, e, MUTT_PURGE, true, true);
764 const bool c_delete_untag = cs_subset_bool(NeoMutt->sub, "delete_untag");
765 if (c_delete_untag)
766 mutt_set_flag(m_src, e, MUTT_TAG, false, true);
767 }
768
769 return 0;
770}
void mutt_parse_mime_message(struct Email *e, FILE *fp)
Parse a MIME email.
Definition commands.c:596
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:983
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:689
@ 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 476 of file external.c.

477{
478 enum EmailSortType sort = EMAIL_SORT_DATE;
479
480 switch (mw_multi_choice(reverse ?
481 /* L10N: The highlighted letters must match the "Sort" options */
482 _("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?") :
483 /* L10N: The highlighted letters must match the "Rev-Sort" options */
484 _("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?"),
485 /* L10N: These must match the highlighted letters from "Sort" and "Rev-Sort" */
486 _("dfrsotuzcpl")))
487 {
488 case -1: /* abort - don't resort */
489 return false;
490
491 case 1: /* (d)ate */
492 sort = EMAIL_SORT_DATE;
493 break;
494
495 case 2: /* (f)rm */
496 sort = EMAIL_SORT_FROM;
497 break;
498
499 case 3: /* (r)ecv */
501 break;
502
503 case 4: /* (s)ubj */
504 sort = EMAIL_SORT_SUBJECT;
505 break;
506
507 case 5: /* t(o) */
508 sort = EMAIL_SORT_TO;
509 break;
510
511 case 6: /* (t)hread */
512 sort = EMAIL_SORT_THREADS;
513 break;
514
515 case 7: /* (u)nsort */
516 sort = EMAIL_SORT_UNSORTED;
517 break;
518
519 case 8: /* si(z)e */
520 sort = EMAIL_SORT_SIZE;
521 break;
522
523 case 9: /* s(c)ore */
524 sort = EMAIL_SORT_SCORE;
525 break;
526
527 case 10: /* s(p)am */
528 sort = EMAIL_SORT_SPAM;
529 break;
530
531 case 11: /* (l)abel */
532 sort = EMAIL_SORT_LABEL;
533 break;
534 }
535
536 const unsigned char c_use_threads = cs_subset_enum(NeoMutt->sub, "use_threads");
537 const enum EmailSortType c_sort = cs_subset_sort(NeoMutt->sub, "sort");
538 int rc = CSR_ERR_CODE;
539 if ((sort != EMAIL_SORT_THREADS) || (c_use_threads == UT_UNSET))
540 {
541 if ((sort != EMAIL_SORT_THREADS) && (c_sort & SORT_LAST))
542 sort |= SORT_LAST;
543 if (reverse)
544 sort |= SORT_REVERSE;
545
546 rc = cs_subset_str_native_set(NeoMutt->sub, "sort", sort, NULL);
547 }
548 else
549 {
550 ASSERT((c_sort & SORT_MASK) != EMAIL_SORT_THREADS); /* See index_config_observer() */
551 /* Preserve the value of $sort, and toggle whether we are threaded. */
552 switch (c_use_threads)
553 {
554 case UT_FLAT:
555 rc = cs_subset_str_native_set(NeoMutt->sub, "use_threads",
556 reverse ? UT_REVERSE : UT_THREADS, NULL);
557 break;
558 case UT_THREADS:
559 rc = cs_subset_str_native_set(NeoMutt->sub, "use_threads",
560 reverse ? UT_REVERSE : UT_FLAT, NULL);
561 break;
562 case UT_REVERSE:
563 rc = cs_subset_str_native_set(NeoMutt->sub, "use_threads",
564 reverse ? UT_FLAT : UT_THREADS, NULL);
565 break;
566 default:
567 ASSERT(false);
568 }
569 }
570
571 return ((CSR_RESULT(rc) == CSR_SUCCESS) && !(rc & CSR_SUC_NO_CHANGE));
572}
unsigned char cs_subset_enum(const struct ConfigSubset *sub, const char *name)
Get a enumeration config item by name.
Definition helpers.c:71
short cs_subset_sort(const struct ConfigSubset *sub, const char *name)
Get a sort config item by name.
Definition helpers.c:266
#define CSR_SUC_NO_CHANGE
The value hasn't changed.
Definition set.h:42
#define CSR_ERR_CODE
Problem with the code.
Definition set.h:34
#define CSR_RESULT(x)
Definition set.h:50
#define CSR_SUCCESS
Action completed successfully.
Definition set.h:33
#define SORT_MASK
Mask for the sort id.
Definition sort.h:38
#define SORT_LAST
Sort thread by last-X, e.g. received date.
Definition sort.h:40
#define SORT_REVERSE
Reverse the order of the sort.
Definition sort.h:39
EmailSortType
Methods for sorting Emails.
Definition sort.h:53
@ EMAIL_SORT_LABEL
Sort by the emails label.
Definition sort.h:57
@ EMAIL_SORT_DATE_RECEIVED
Sort by when the message was delivered locally.
Definition sort.h:55
@ EMAIL_SORT_SPAM
Sort by the email's spam score.
Definition sort.h:60
@ EMAIL_SORT_SCORE
Sort by the email's score.
Definition sort.h:58
@ EMAIL_SORT_DATE
Sort by the date the email was sent.
Definition sort.h:54
@ EMAIL_SORT_THREADS
Sort by email threads.
Definition sort.h:62
@ EMAIL_SORT_SUBJECT
Sort by the email's subject.
Definition sort.h:61
@ EMAIL_SORT_FROM
Sort by the email's From field.
Definition sort.h:56
@ EMAIL_SORT_UNSORTED
Sort by the order the messages appear in the mailbox.
Definition sort.h:64
@ EMAIL_SORT_SIZE
Sort by the size of the email.
Definition sort.h:59
@ EMAIL_SORT_TO
Sort by the email's To field.
Definition sort.h:63
int mw_multi_choice(const char *prompt, const char *letters)
Offer the user a multiple choice question -.
Definition question.c:61
@ UT_FLAT
Unthreaded.
Definition mutt_thread.h:98
@ UT_UNSET
Not yet set by user, stick to legacy semantics.
Definition mutt_thread.h:97
@ UT_THREADS
Normal threading (root above subthreads)
Definition mutt_thread.h:99
@ UT_REVERSE
Reverse threading (subthreads above root)
#define ASSERT(COND)
Definition signal2.h:60
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:303
+ 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 579 of file external.c.

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