NeoMutt  2023-05-17-16-g61469c
Teaching an old dog new tricks
DOXYGEN
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 EmailList *el)
 Bounce an email. More...
 
bool mutt_check_traditional_pgp (struct Mailbox *m, struct EmailList *el)
 Check if a message has inline PGP content. More...
 
void commands_cleanup (void)
 Clean up commands globals. More...
 
void mutt_display_address (struct Envelope *env)
 Display the address of a message. More...
 
bool mutt_edit_content_type (struct Email *e, struct Body *b, FILE *fp)
 Edit the content type of an attachment. More...
 
void mutt_enter_command (void)
 Enter a neomutt command. More...
 
void mutt_pipe_message (struct Mailbox *m, struct EmailList *el)
 Pipe a message. More...
 
void mutt_print_message (struct Mailbox *m, struct EmailList *el)
 Print a message. More...
 
int mutt_save_message (struct Mailbox *m, struct EmailList *el, enum MessageSaveOpt, enum MessageTransformOpt transform_opt)
 Save an email. More...
 
int mutt_save_message_ctx (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. More...
 
bool mutt_select_sort (bool reverse)
 Ask the user for a sort method. More...
 
bool mutt_shell_escape (void)
 Invoke a command in a subshell. More...
 

Detailed Description

Manage where the email is piped to external commands.

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

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

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

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

Function Documentation

◆ index_bounce_message()

void index_bounce_message ( struct Mailbox m,
struct EmailList *  el 
)

Bounce an email.

Parameters
mMailbox
elList of Emails to bounce

Definition at line 90 of file external.c.

91{
92 if (!m || !el || STAILQ_EMPTY(el))
93 return;
94
95 struct Buffer *buf = buf_pool_get();
96 struct Buffer *prompt = buf_pool_get();
97 struct Buffer *scratch = NULL;
98
99 struct AddressList al = TAILQ_HEAD_INITIALIZER(al);
100 char *err = NULL;
101 int rc;
102 int msg_count = 0;
103
104 struct EmailNode *en = NULL;
105 STAILQ_FOREACH(en, el, entries)
106 {
107 /* RFC5322 mandates a From: header,
108 * so warn before bouncing messages without one */
109 if (TAILQ_EMPTY(&en->email->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
120 rc = buf_get_field(buf_string(prompt), buf, MUTT_COMP_ALIAS, false, NULL, NULL, 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#define EXTRA_SPACE (15 + 7 + 2)
144 scratch = buf_pool_get();
145 buf_printf(scratch, ngettext("Bounce message to %s?", "Bounce messages to %s?", msg_count),
146 buf_string(buf));
147
148 const size_t width = msgwin_get_width();
149 if (mutt_strwidth(buf_string(scratch)) > (width - EXTRA_SPACE))
150 {
151 mutt_simple_format(prompt->data, prompt->dsize, 0, width - EXTRA_SPACE,
152 JUSTIFY_LEFT, 0, scratch->data, scratch->dsize, false);
153 buf_addstr(prompt, "...?");
154 }
155 else
156 {
157 buf_copy(prompt, scratch);
158 }
159
160 const enum QuadOption c_bounce = cs_subset_quad(NeoMutt->sub, "bounce");
161 if (query_quadoption(c_bounce, buf_string(prompt)) != MUTT_YES)
162 {
164 mutt_message(ngettext("Message not bounced", "Messages not bounced", msg_count));
165 goto done;
166 }
167
169
170 struct Message *msg = NULL;
171 STAILQ_FOREACH(en, el, entries)
172 {
173 msg = mx_msg_open(m, en->email);
174 if (!msg)
175 {
176 rc = -1;
177 break;
178 }
179
180 rc = mutt_bounce_message(msg->fp, m, en->email, &al, NeoMutt->sub);
181 mx_msg_close(m, &msg);
182
183 if (rc < 0)
184 break;
185 }
186
187 /* If no error, or background, display message. */
188 if ((rc == 0) || (rc == S_BKG))
189 mutt_message(ngettext("Message bounced", "Messages bounced", msg_count));
190
191done:
193 buf_pool_release(&buf);
194 buf_pool_release(&prompt);
195 buf_pool_release(&scratch);
196}
void mutt_addrlist_clear(struct AddressList *al)
Unlink and free all Address in an AddressList.
Definition: address.c:1450
size_t mutt_addrlist_write(const struct AddressList *al, struct Buffer *buf, bool display)
Write an Address to a buffer.
Definition: address.c:1199
int mutt_addrlist_parse2(struct AddressList *al, const char *s)
Parse a list of email addresses.
Definition: address.c:627
int mutt_addrlist_to_intl(struct AddressList *al, char **err)
Convert an Address list to Punycode.
Definition: address.c:1285
void mutt_expand_aliases(struct AddressList *al)
Expand aliases in a List of Addresses.
Definition: alias.c:297
int buf_printf(struct Buffer *buf, const char *fmt,...)
Format a string overwriting a Buffer.
Definition: buffer.c:171
void buf_reset(struct Buffer *buf)
Reset an existing Buffer.
Definition: buffer.c:86
bool buf_is_empty(const struct Buffer *buf)
Is the Buffer empty?
Definition: buffer.c:301
size_t buf_addstr(struct Buffer *buf, const char *s)
Add a string to a Buffer.
Definition: buffer.c:236
size_t buf_strcpy(struct Buffer *buf, const char *s)
Copy a string into a Buffer.
Definition: buffer.c:370
size_t buf_copy(struct Buffer *dst, const struct Buffer *src)
Copy a Buffer's contents to another Buffer.
Definition: buffer.c:505
static const char * buf_string(const struct Buffer *buf)
Convert a buffer to a const char * "string".
Definition: buffer.h:78
enum QuadOption cs_subset_quad(const struct ConfigSubset *sub, const char *name)
Get a quad-value config item by name.
Definition: helpers.c:218
void mutt_simple_format(char *buf, size_t buflen, int min_width, int max_width, enum FormatJustify justify, char pad_char, const char *s, size_t n, bool arboreal)
Format a string, like snprintf()
Definition: curs_lib.c:640
size_t mutt_strwidth(const char *s)
Measure a string's width in screen cells.
Definition: curs_lib.c:914
@ JUSTIFY_LEFT
Left justify the text.
Definition: curs_lib.h:42
int buf_get_field(const char *field, struct Buffer *buf, CompletionFlags complete, bool multiple, struct Mailbox *m, char ***files, int *numfiles)
Ask the user for a string.
Definition: window.c:180
#define EXTRA_SPACE
#define mutt_error(...)
Definition: logging2.h:87
#define mutt_message(...)
Definition: logging2.h:86
#define FREE(x)
Definition: memory.h:43
size_t msgwin_get_width(void)
Get the width of the Message Window.
Definition: msgwin.c:270
void msgwin_clear_text(void)
Clear the text in the Message Window.
Definition: msgwin.c:250
#define _(a)
Definition: message.h:28
#define MUTT_COMP_ALIAS
Alias completion (in alias dialog)
Definition: mutt.h:56
int mx_msg_close(struct Mailbox *m, struct Message **msg)
Close a message.
Definition: mx.c:1198
struct Message * mx_msg_open(struct Mailbox *m, struct Email *e)
Return a stream pointer for a message.
Definition: mx.c:1152
struct Buffer * buf_pool_get(void)
Get a Buffer from the pool.
Definition: pool.c:106
void buf_pool_release(struct Buffer **ptr)
Return a Buffer to the pool.
Definition: pool.c:119
QuadOption
Possible values for a quad-option.
Definition: quad.h:36
@ MUTT_YES
User answered 'Yes', or assume 'Yes'.
Definition: quad.h:39
enum QuadOption query_quadoption(enum QuadOption opt, const char *prompt)
Ask the user a quad-question.
Definition: question.c:386
#define STAILQ_FOREACH(var, head, field)
Definition: queue.h:352
#define STAILQ_EMPTY(head)
Definition: queue.h:348
#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:913
#define S_BKG
Definition: string2.h:41
String manipulation buffer.
Definition: buffer.h:34
size_t dsize
Length of data.
Definition: buffer.h:37
char * data
Pointer to data.
Definition: buffer.h:35
List of Emails.
Definition: email.h:131
struct Email * email
Email in the list.
Definition: email.h:132
struct Envelope * env
Envelope information.
Definition: email.h:66
struct AddressList from
Email's 'From' list.
Definition: envelope.h:59
A local copy of an email.
Definition: mxapi.h:43
FILE * fp
pointer to the message data
Definition: mxapi.h:44
Container for Accounts, Notifications.
Definition: neomutt.h:37
struct ConfigSubset * sub
Inherited config items.
Definition: neomutt.h:39
+ 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 EmailList *  el 
)

Check if a message has inline PGP content.

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

Definition at line 1230 of file external.c.

1231{
1232 bool rc = false;
1233 struct EmailNode *en = NULL;
1234 STAILQ_FOREACH(en, el, entries)
1235 {
1237 rc = check_traditional_pgp(m, en->email) || rc;
1238 }
1239
1240 return rc;
1241}
static bool check_traditional_pgp(struct Mailbox *m, struct Email *e)
Check for an inline PGP content.
Definition: external.c:1202
#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:41
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ commands_cleanup()

void commands_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:352
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 681 of file external.c.

682{
683 const char *pfx = NULL;
684
685 struct AddressList *al = mutt_get_address(env, &pfx);
686 if (!al)
687 return;
688
689 /* Note: We don't convert IDNA to local representation this time.
690 * That is intentional, so the user has an opportunity to copy &
691 * paste the on-the-wire form of the address to other, IDN-unable
692 * software. */
693 struct Buffer *buf = buf_pool_get();
694 mutt_addrlist_write(al, buf, false);
695 mutt_message("%s: %s", pfx, buf_string(buf));
696 buf_pool_release(&buf);
697}
struct AddressList * mutt_get_address(struct Envelope *env, const char **prefix)
Get an Address from an Envelope.
Definition: alias.c:329
+ 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 1089 of file external.c.

1090{
1091 struct Buffer *buf = buf_pool_get();
1092 struct Buffer *charset = buf_pool_get();
1093 struct Buffer *obuf = buf_pool_get();
1094 struct Buffer *tmp = buf_pool_get();
1095
1096 bool rc = false;
1097 bool charset_changed = false;
1098 bool type_changed = false;
1099 bool structure_changed = false;
1100
1101 char *cp = mutt_param_get(&b->parameter, "charset");
1102 buf_strcpy(charset, cp);
1103
1104 buf_printf(buf, "%s/%s", TYPE(b), b->subtype);
1105 buf_copy(obuf, buf);
1106 if (!TAILQ_EMPTY(&b->parameter))
1107 {
1108 struct Parameter *np = NULL;
1109 TAILQ_FOREACH(np, &b->parameter, entries)
1110 {
1111 mutt_addr_cat(tmp->data, tmp->dsize, np->value, MimeSpecials);
1112 buf_add_printf(buf, "; %s=%s", np->attribute, buf_string(tmp));
1113 }
1114 }
1115
1116 if ((buf_get_field("Content-Type: ", buf, MUTT_COMP_NO_FLAGS, false, NULL, NULL, NULL) != 0) ||
1117 buf_is_empty(buf))
1118 {
1119 goto done;
1120 }
1121
1122 /* clean up previous junk */
1124 FREE(&b->subtype);
1125
1127
1128 buf_printf(tmp, "%s/%s", TYPE(b), NONULL(b->subtype));
1129 type_changed = !mutt_istr_equal(buf_string(tmp), buf_string(obuf));
1130 charset_changed = !mutt_istr_equal(buf_string(charset),
1131 mutt_param_get(&b->parameter, "charset"));
1132
1133 /* if in send mode, check for conversion - current setting is default. */
1134
1135 if (!e && (b->type == TYPE_TEXT) && charset_changed)
1136 {
1137 buf_printf(tmp, _("Convert to %s upon sending?"),
1138 mutt_param_get(&b->parameter, "charset"));
1139 enum QuadOption ans = mutt_yesorno(buf_string(tmp), b->noconv ? MUTT_NO : MUTT_YES);
1140 if (ans != MUTT_ABORT)
1141 b->noconv = (ans == MUTT_NO);
1142 }
1143
1144 /* inform the user */
1145
1146 buf_printf(tmp, "%s/%s", TYPE(b), NONULL(b->subtype));
1147 if (type_changed)
1148 mutt_message(_("Content-Type changed to %s"), buf_string(tmp));
1149 if ((b->type == TYPE_TEXT) && charset_changed)
1150 {
1151 if (type_changed)
1152 mutt_sleep(1);
1153 mutt_message(b->noconv ? _("Character set changed to %s; not converting") :
1154 _("Character set changed to %s; converting"),
1155 mutt_param_get(&b->parameter, "charset"));
1156 }
1157
1158 b->force_charset |= charset_changed;
1159
1160 if (!is_multipart(b) && b->parts)
1161 {
1162 structure_changed = true;
1163 mutt_body_free(&b->parts);
1164 }
1165 if (!mutt_is_message_type(b->type, b->subtype) && b->email)
1166 {
1167 structure_changed = true;
1168 b->email->body = NULL;
1169 email_free(&b->email);
1170 }
1171
1172 if (fp && !b->parts && (is_multipart(b) || mutt_is_message_type(b->type, b->subtype)))
1173 {
1174 structure_changed = true;
1175 mutt_parse_part(fp, b);
1176 }
1177
1178 if ((WithCrypto != 0) && e)
1179 {
1180 if (e->body == b)
1182
1183 e->security |= crypt_query(b);
1184 }
1185
1186 rc = structure_changed | type_changed;
1187
1188done:
1189 buf_pool_release(&buf);
1190 buf_pool_release(&charset);
1191 buf_pool_release(&obuf);
1192 buf_pool_release(&tmp);
1193 return rc;
1194}
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:694
int buf_add_printf(struct Buffer *buf, const char *fmt,...)
Format a string appending a Buffer.
Definition: buffer.c:214
SecurityFlags crypt_query(struct Body *b)
Check out the type of encryption used.
Definition: crypt.c:677
void mutt_body_free(struct Body **ptr)
Free a Body.
Definition: body.c:57
void email_free(struct Email **ptr)
Free an Email.
Definition: email.c:44
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:810
#define MUTT_COMP_NO_FLAGS
No flags are set.
Definition: mutt.h:55
void mutt_sleep(short s)
Sleep for a while.
Definition: muttlib.c:1424
#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:84
void mutt_param_free(struct ParameterList *pl)
Free a ParameterList.
Definition: parameter.c:61
void mutt_parse_part(FILE *fp, struct Body *b)
Parse a MIME part.
Definition: parse.c:1772
void mutt_parse_content_type(const char *s, struct Body *ct)
Parse a content type.
Definition: parse.c:425
bool mutt_is_message_type(int type, const char *subtype)
Determine if a mime type matches a message or not.
Definition: parse.c:1475
@ 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 mutt_yesorno(const char *msg, enum QuadOption def)
Ask the user a Yes/No question.
Definition: question.c:194
#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
struct Body * body
List of MIME parts.
Definition: email.h:67
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 642 of file external.c.

643{
644 struct Buffer *buf = buf_pool_get();
645 struct Buffer *err = buf_pool_get();
646
647 window_redraw(NULL);
648 /* if enter is pressed after : with no command, just return */
649 if ((buf_get_field(":", buf, MUTT_COMP_COMMAND, false, NULL, NULL, NULL) != 0) ||
650 buf_is_empty(buf))
651 {
652 goto done;
653 }
654
655 enum CommandResult rc = parse_rc_line(buf_string(buf), err);
656 if (!buf_is_empty(err))
657 {
658 if (rc == MUTT_CMD_SUCCESS) /* command succeeded with message */
659 mutt_message("%s", buf_string(err));
660 else if (rc == MUTT_CMD_ERROR)
661 mutt_error("%s", buf_string(err));
662 else if (rc == MUTT_CMD_WARNING)
663 mutt_warning("%s", buf_string(err));
664 }
665
666 if (NeoMutt)
667 {
668 // Running commands could cause anything to change, so let others know
670 }
671
672done:
673 buf_pool_release(&buf);
674 buf_pool_release(&err);
675}
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
#define mutt_warning(...)
Definition: logging2.h:85
bool notify_send(struct Notify *notify, enum NotifyType event_type, int event_subtype, void *event_data)
Send out a notification message.
Definition: notify.c:171
#define MUTT_COMP_COMMAND
Complete a NeoMutt command.
Definition: mutt.h:57
void window_redraw(struct MuttWindow *win)
Reflow, recalc and repaint a tree of Windows.
Definition: mutt_window.c:605
@ NT_GLOBAL_COMMAND
A NeoMutt command.
Definition: neomutt.h:55
@ 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:108
struct Notify * notify
Notifications handler.
Definition: neomutt.h:38
+ 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 EmailList *  el 
)

Pipe a message.

Parameters
mMailbox
elList of Emails to pipe

Definition at line 421 of file external.c.

422{
423 if (!m || !el)
424 return;
425
426 struct Buffer *buf = buf_pool_get();
427
428 if (buf_get_field(_("Pipe to command: "), buf, MUTT_COMP_FILE_SIMPLE, false,
429 NULL, NULL, NULL) != 0)
430 {
431 goto cleanup;
432 }
433
434 if (buf_len(buf) == 0)
435 goto cleanup;
436
437 buf_expand_path(buf);
438 const bool c_pipe_decode = cs_subset_bool(NeoMutt->sub, "pipe_decode");
439 const bool c_pipe_split = cs_subset_bool(NeoMutt->sub, "pipe_split");
440 const char *const c_pipe_sep = cs_subset_string(NeoMutt->sub, "pipe_sep");
441 pipe_message(m, el, buf_string(buf), c_pipe_decode, false, c_pipe_split, c_pipe_sep);
442
443cleanup:
444 buf_pool_release(&buf);
445}
size_t buf_len(const struct Buffer *buf)
Calculate the length of a Buffer.
Definition: buffer.c:414
const char * cs_subset_string(const struct ConfigSubset *sub, const char *name)
Get a string config item by name.
Definition: helpers.c:317
bool cs_subset_bool(const struct ConfigSubset *sub, const char *name)
Get a boolean config item by name.
Definition: helpers.c:73
static int pipe_message(struct Mailbox *m, struct EmailList *el, const char *cmd, bool decode, bool print, bool split, const char *sep)
Pipe message to a command.
Definition: external.c:293
#define MUTT_COMP_FILE_SIMPLE
File completion (no browser)
Definition: mutt.h:60
void buf_expand_path(struct Buffer *buf)
Create the canonical path.
Definition: muttlib.c:333
+ 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 EmailList *  el 
)

Print a message.

Parameters
mMailbox
elList of Emails to print

Definition at line 452 of file external.c.

453{
454 if (!m || !el)
455 return;
456
457 const enum QuadOption c_print = cs_subset_quad(NeoMutt->sub, "print");
458 const char *const c_print_command = cs_subset_string(NeoMutt->sub, "print_command");
459 if (c_print && !c_print_command)
460 {
461 mutt_message(_("No printing command has been defined"));
462 return;
463 }
464
465 int msg_count = 0;
466 struct EmailNode *en = NULL;
467 STAILQ_FOREACH(en, el, entries)
468 {
469 msg_count++;
470 }
471
472 if (query_quadoption(c_print, (msg_count == 1) ? _("Print message?") :
473 _("Print tagged messages?")) != MUTT_YES)
474 {
475 return;
476 }
477
478 const bool c_print_decode = cs_subset_bool(NeoMutt->sub, "print_decode");
479 const bool c_print_split = cs_subset_bool(NeoMutt->sub, "print_split");
480 if (pipe_message(m, el, c_print_command, c_print_decode, true, c_print_split, "\f") == 0)
481 {
482 mutt_message(ngettext("Message printed", "Messages printed", msg_count));
483 }
484 else
485 {
486 mutt_message(ngettext("Message could not be printed",
487 "Messages could not be printed", msg_count));
488 }
489}
+ 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 EmailList *  el,
enum MessageSaveOpt  save_opt,
enum MessageTransformOpt  transform_opt 
)

Save an email.

Parameters
mMailbox
elList 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 798 of file external.c.

800{
801 if (!el || STAILQ_EMPTY(el))
802 return -1;
803
804 int rc = -1;
805 int tagged_progress_count = 0;
806 unsigned int msg_count = 0;
807 struct Mailbox *m_save = NULL;
808
809 struct Buffer *buf = buf_pool_get();
810 struct stat st = { 0 };
811 struct EmailNode *en = NULL;
812
813 STAILQ_FOREACH(en, el, entries)
814 {
815 msg_count++;
816 }
817 en = STAILQ_FIRST(el);
818
819 const SecurityFlags security_flags = WithCrypto ? en->email->security : SEC_NO_FLAGS;
820 const bool is_passphrase_needed = security_flags & SEC_ENCRYPT;
821
822 const char *prompt = NULL;
823 const char *progress_msg = NULL;
824
825 // Set prompt and progress_msg
826 switch (save_opt)
827 {
828 case SAVE_COPY:
829 // L10N: Progress meter message when copying tagged messages
830 progress_msg = (msg_count > 1) ? _("Copying tagged messages...") : NULL;
831 switch (transform_opt)
832 {
833 case TRANSFORM_NONE:
834 prompt = (msg_count > 1) ? _("Copy tagged to mailbox") : _("Copy to mailbox");
835 break;
837 prompt = (msg_count > 1) ? _("Decrypt-copy tagged to mailbox") :
838 _("Decrypt-copy to mailbox");
839 break;
840 case TRANSFORM_DECODE:
841 prompt = (msg_count > 1) ? _("Decode-copy tagged to mailbox") :
842 _("Decode-copy to mailbox");
843 break;
844 }
845 break;
846
847 case SAVE_MOVE:
848 // L10N: Progress meter message when saving tagged messages
849 progress_msg = (msg_count > 1) ? _("Saving tagged messages...") : NULL;
850 switch (transform_opt)
851 {
852 case TRANSFORM_NONE:
853 prompt = (msg_count > 1) ? _("Save tagged to mailbox") : _("Save to mailbox");
854 break;
856 prompt = (msg_count > 1) ? _("Decrypt-save tagged to mailbox") :
857 _("Decrypt-save to mailbox");
858 break;
859 case TRANSFORM_DECODE:
860 prompt = (msg_count > 1) ? _("Decode-save tagged to mailbox") :
861 _("Decode-save to mailbox");
862 break;
863 }
864 break;
865 }
866
868 mutt_default_save(buf->data, buf->dsize, en->email);
869 buf_fix_dptr(buf);
871
872 if (buf_enter_fname(prompt, buf, false, NULL, false, NULL, NULL, MUTT_SEL_NO_FLAGS) == -1)
873 {
874 goto cleanup;
875 }
876
877 size_t pathlen = buf_len(buf);
878 if (pathlen == 0)
879 goto cleanup;
880
881 /* Trim any trailing '/' */
882 if (buf->data[pathlen - 1] == '/')
883 buf->data[pathlen - 1] = '\0';
884
885 /* This is an undocumented feature of ELM pointed out to me by Felix von
886 * Leitner <leitner@prz.fu-berlin.de> */
887 if (buf_len(&LastSaveFolder) == 0)
889 if (mutt_str_equal(buf_string(buf), "."))
891 else
893
894 buf_expand_path(buf);
895
896 /* check to make sure that this file is really the one the user wants */
897 if (mutt_save_confirm(buf_string(buf), &st) != 0)
898 goto cleanup;
899
900 if (is_passphrase_needed && (transform_opt != TRANSFORM_NONE) &&
901 !crypt_valid_passphrase(security_flags))
902 {
903 rc = -1;
904 goto errcleanup;
905 }
906
907 mutt_message(_("Copying to %s..."), buf_string(buf));
908
909#ifdef USE_IMAP
910 enum MailboxType mailbox_type = imap_path_probe(buf_string(buf), NULL);
911 if ((m->type == MUTT_IMAP) && (transform_opt == TRANSFORM_NONE) && (mailbox_type == MUTT_IMAP))
912 {
913 rc = imap_copy_messages(m, el, buf_string(buf), save_opt);
914 switch (rc)
915 {
916 /* success */
917 case 0:
919 rc = 0;
920 goto cleanup;
921 /* non-fatal error: continue to fetch/append */
922 case 1:
923 break;
924 /* fatal error, abort */
925 case -1:
926 goto errcleanup;
927 }
928 }
929#endif
930
932 m_save = mx_path_resolve(buf_string(buf));
933 bool old_append = m_save->append;
934 OpenMailboxFlags mbox_flags = MUTT_NEWFOLDER;
935 /* Display a tagged message progress counter, rather than (for
936 * IMAP) a per-message progress counter */
937 if (msg_count > 1)
938 mbox_flags |= MUTT_QUIET;
939 if (!mx_mbox_open(m_save, mbox_flags))
940 {
941 rc = -1;
942 mailbox_free(&m_save);
943 goto errcleanup;
944 }
945 m_save->append = true;
946
947#ifdef USE_COMP_MBOX
948 /* If we're saving to a compressed mailbox, the stats won't be updated
949 * until the next open. Until then, improvise. */
950 struct Mailbox *m_comp = NULL;
951 if (m_save->compress_info)
952 {
953 m_comp = mailbox_find(m_save->realpath);
954 }
955 /* We probably haven't been opened yet */
956 if (m_comp && (m_comp->msg_count == 0))
957 m_comp = NULL;
958#endif
959 if (msg_count == 1)
960 {
961 rc = mutt_save_message_ctx(m, en->email, save_opt, transform_opt, m_save);
962 if (rc != 0)
963 {
964 mx_mbox_close(m_save);
965 m_save->append = old_append;
966 goto errcleanup;
967 }
968#ifdef USE_COMP_MBOX
969 if (m_comp)
970 {
971 m_comp->msg_count++;
972 if (!en->email->read)
973 {
974 m_comp->msg_unread++;
975 if (!en->email->old)
976 m_comp->msg_new++;
977 }
978 if (en->email->flagged)
979 m_comp->msg_flagged++;
980 }
981#endif
982 }
983 else
984 {
985 rc = 0;
986
987#ifdef USE_NOTMUCH
988 if (m->type == MUTT_NOTMUCH)
989 nm_db_longrun_init(m, true);
990#endif
991 struct Progress *progress = progress_new(progress_msg, MUTT_PROGRESS_WRITE, msg_count);
992 STAILQ_FOREACH(en, el, entries)
993 {
994 progress_update(progress, ++tagged_progress_count, -1);
996 rc = mutt_save_message_ctx(m, en->email, save_opt, transform_opt, m_save);
997 if (rc != 0)
998 break;
999#ifdef USE_COMP_MBOX
1000 if (m_comp)
1001 {
1002 struct Email *e2 = en->email;
1003 m_comp->msg_count++;
1004 if (!e2->read)
1005 {
1006 m_comp->msg_unread++;
1007 if (!e2->old)
1008 m_comp->msg_new++;
1009 }
1010 if (e2->flagged)
1011 m_comp->msg_flagged++;
1012 }
1013#endif
1014 }
1015 progress_free(&progress);
1016
1017#ifdef USE_NOTMUCH
1018 if (m->type == MUTT_NOTMUCH)
1020#endif
1021 if (rc != 0)
1022 {
1023 mx_mbox_close(m_save);
1024 m_save->append = old_append;
1025 goto errcleanup;
1026 }
1027 }
1028
1029 const bool need_mailbox_cleanup = ((m_save->type == MUTT_MBOX) ||
1030 (m_save->type == MUTT_MMDF));
1031
1032 mx_mbox_close(m_save);
1033 m_save->append = old_append;
1034
1035 if (need_mailbox_cleanup)
1037
1039 rc = 0;
1040
1041errcleanup:
1042 if (rc != 0)
1043 {
1044 switch (save_opt)
1045 {
1046 case SAVE_MOVE:
1047 if (msg_count > 1)
1048 {
1049 // L10N: Message when an index tagged save operation fails for some reason
1050 mutt_error(_("Error saving tagged messages"));
1051 }
1052 else
1053 {
1054 // L10N: Message when an index/pager save operation fails for some reason
1055 mutt_error(_("Error saving message"));
1056 }
1057 break;
1058 case SAVE_COPY:
1059 if (msg_count > 1)
1060 {
1061 // L10N: Message when an index tagged copy operation fails for some reason
1062 mutt_error(_("Error copying tagged messages"));
1063 }
1064 else
1065 {
1066 // L10N: Message when an index/pager copy operation fails for some reason
1067 mutt_error(_("Error copying message"));
1068 }
1069 break;
1070 }
1071 }
1072
1073 mailbox_free(&m_save);
1074
1075cleanup:
1076 buf_pool_release(&buf);
1077 return rc;
1078}
#define MUTT_SEL_NO_FLAGS
No flags are set.
Definition: lib.h:55
void buf_fix_dptr(struct Buffer *buf)
Move the dptr to end of the Buffer.
Definition: buffer.c:192
void buf_alloc(struct Buffer *buf, size_t new_size)
Make sure a buffer can store at least new_size bytes.
Definition: buffer.c:316
bool crypt_valid_passphrase(SecurityFlags flags)
Check that we have a usable passphrase, ask if not.
Definition: crypt.c:135
int buf_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:446
int mutt_save_message_ctx(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:757
void mutt_file_resolve_symlink(struct Buffer *buf)
Resolve a symlink in place.
Definition: file.c:1678
enum MailboxType imap_path_probe(const char *path, const struct stat *st)
Is this an IMAP Mailbox? - Implements MxOps::path_probe() -.
Definition: imap.c:2441
void mutt_default_save(char *path, size_t pathlen, struct Email *e)
Find the default save path for an email.
Definition: hook.c:737
void mutt_message_hook(struct Mailbox *m, struct Email *e, HookFlags type)
Perform a message hook.
Definition: hook.c:658
#define MUTT_MESSAGE_HOOK
message-hook: run before displaying a message
Definition: hook.h:45
int imap_copy_messages(struct Mailbox *m, struct EmailList *el, const char *dest, enum MessageSaveOpt save_opt)
Server COPY messages to another folder.
Definition: message.c:1665
void mailbox_free(struct Mailbox **ptr)
Free a Mailbox.
Definition: mailbox.c:88
struct Mailbox * mailbox_find(const char *path)
Find the mailbox with a given path.
Definition: mailbox.c:140
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 mutt_str_equal(const char *a, const char *b)
Compare two strings.
Definition: string.c:798
#define PATH_MAX
Definition: mutt.h:41
void mutt_clear_error(void)
Clear the message line (bottom line of screen)
Definition: mutt_logging.c:73
void mutt_mailbox_cleanup(const char *path, struct stat *st)
Restore the timestamp of a mailbox.
Definition: mutt_mailbox.c:424
void buf_pretty_mailbox(struct Buffer *buf)
Shorten a mailbox path using '~' or '='.
Definition: muttlib.c:560
int mutt_save_confirm(const char *s, struct stat *st)
Ask the user to save.
Definition: muttlib.c:1325
bool mx_mbox_open(struct Mailbox *m, OpenMailboxFlags flags)
Open a mailbox and parse it.
Definition: mx.c:307
struct Mailbox * mx_path_resolve(const char *path)
Get a Mailbox for a path.
Definition: mx.c:1682
enum MxStatus mx_mbox_close(struct Mailbox *m)
Save changes and close mailbox.
Definition: mx.c:618
uint8_t OpenMailboxFlags
Flags for mutt_open_mailbox(), e.g. MUTT_NOSORT.
Definition: mxapi.h:60
#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:66
#define MUTT_QUIET
Do not print any messages.
Definition: mxapi.h:65
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:370
void nm_db_longrun_init(struct Mailbox *m, bool writable)
Start a long transaction.
Definition: db.c:355
@ MUTT_PROGRESS_WRITE
Progress tracks elements, according to $write_inc
Definition: lib.h:50
void progress_free(struct Progress **ptr)
Free a Progress Bar.
Definition: progress.c:89
bool progress_update(struct Progress *progress, size_t pos, int percent)
Update the state of the progress bar.
Definition: progress.c:73
struct Progress * progress_new(const char *msg, enum ProgressType type, size_t size)
Create a new Progress Bar.
Definition: progress.c:121
#define STAILQ_FIRST(head)
Definition: queue.h:350
The envelope/body of an email.
Definition: email.h:37
bool read
Email is read.
Definition: email.h:48
bool old
Email is seen, but unread.
Definition: email.h:47
bool flagged
Marked important?
Definition: email.h:45
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:120
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_ctx()

int mutt_save_message_ctx ( 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 757 of file external.c.

759{
762 int rc;
763
764 set_copy_flags(e, transform_opt, &cmflags, &chflags);
765
766 struct Message *msg = mx_msg_open(m_src, e);
767 if (msg && transform_opt != TRANSFORM_NONE)
768 {
770 }
771
772 rc = mutt_append_message(m_dst, m_src, e, msg, cmflags, chflags);
773 mx_msg_close(m_src, &msg);
774 if (rc != 0)
775 return rc;
776
777 if (save_opt == SAVE_MOVE)
778 {
779 mutt_set_flag(m_src, e, MUTT_DELETE, true, true);
780 mutt_set_flag(m_src, e, MUTT_PURGE, true, true);
781 const bool c_delete_untag = cs_subset_bool(NeoMutt->sub, "delete_untag");
782 if (c_delete_untag)
783 mutt_set_flag(m_src, e, MUTT_TAG, false, true);
784 }
785
786 return 0;
787}
void mutt_parse_mime_message(struct Email *e, FILE *fp)
Parse a MIME email.
Definition: attachments.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:959
uint32_t CopyHeaderFlags
Flags for mutt_copy_header(), e.g. CH_UPDATE.
Definition: copy.h:50
#define MUTT_CM_NO_FLAGS
No flags are set.
Definition: copy.h:35
uint16_t CopyMessageFlags
Flags for mutt_copy_message(), e.g. MUTT_CM_NOHEADER.
Definition: copy.h:34
#define CH_NO_FLAGS
No flags are set.
Definition: copy.h:51
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:706
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:52
@ MUTT_PURGE
Messages to be purged (bypass trash)
Definition: mutt.h:85
@ MUTT_TAG
Tagged messages.
Definition: mutt.h:88
@ MUTT_DELETE
Messages to be deleted.
Definition: mutt.h:83
+ 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 496 of file external.c.

497{
498 enum SortType sort = SORT_DATE;
499
500 switch (mutt_multi_choice(
501 reverse ?
502 /* L10N: The highlighted letters must match the "Sort" options */
503 _("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?") :
504 /* L10N: The highlighted letters must match the "Rev-Sort" options */
505 _("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?"),
506 /* L10N: These must match the highlighted letters from "Sort" and "Rev-Sort" */
507 _("dfrsotuzcpl")))
508 {
509 case -1: /* abort - don't resort */
510 return false;
511
512 case 1: /* (d)ate */
513 sort = SORT_DATE;
514 break;
515
516 case 2: /* (f)rm */
517 sort = SORT_FROM;
518 break;
519
520 case 3: /* (r)ecv */
521 sort = SORT_RECEIVED;
522 break;
523
524 case 4: /* (s)ubj */
525 sort = SORT_SUBJECT;
526 break;
527
528 case 5: /* t(o) */
529 sort = SORT_TO;
530 break;
531
532 case 6: /* (t)hread */
533 sort = SORT_THREADS;
534 break;
535
536 case 7: /* (u)nsort */
537 sort = SORT_ORDER;
538 break;
539
540 case 8: /* si(z)e */
541 sort = SORT_SIZE;
542 break;
543
544 case 9: /* s(c)ore */
545 sort = SORT_SCORE;
546 break;
547
548 case 10: /* s(p)am */
549 sort = SORT_SPAM;
550 break;
551
552 case 11: /* (l)abel */
553 sort = SORT_LABEL;
554 break;
555 }
556
557 const unsigned char c_use_threads = cs_subset_enum(NeoMutt->sub, "use_threads");
558 const enum SortType c_sort = cs_subset_sort(NeoMutt->sub, "sort");
559 int rc = CSR_ERR_CODE;
560 if ((sort != SORT_THREADS) || (c_use_threads == UT_UNSET))
561 {
562 if ((sort != SORT_THREADS) && (c_sort & SORT_LAST))
563 sort |= SORT_LAST;
564 if (reverse)
565 sort |= SORT_REVERSE;
566
567 rc = cs_subset_str_native_set(NeoMutt->sub, "sort", sort, NULL);
568 }
569 else
570 {
571 assert((c_sort & SORT_MASK) != SORT_THREADS); /* See index_config_observer() */
572 /* Preserve the value of $sort, and toggle whether we are threaded. */
573 switch (c_use_threads)
574 {
575 case UT_FLAT:
576 rc = cs_subset_str_native_set(NeoMutt->sub, "use_threads",
577 reverse ? UT_REVERSE : UT_THREADS, NULL);
578 break;
579 case UT_THREADS:
580 rc = cs_subset_str_native_set(NeoMutt->sub, "use_threads",
581 reverse ? UT_REVERSE : UT_FLAT, NULL);
582 break;
583 case UT_REVERSE:
584 rc = cs_subset_str_native_set(NeoMutt->sub, "use_threads",
585 reverse ? UT_FLAT : UT_THREADS, NULL);
586 break;
587 default:
588 assert(false);
589 }
590 }
591
592 return ((CSR_RESULT(rc) == CSR_SUCCESS) && !(rc & CSR_SUC_NO_CHANGE));
593}
unsigned char cs_subset_enum(const struct ConfigSubset *sub, const char *name)
Get a enumeration config item by name.
Definition: helpers.c:97
short cs_subset_sort(const struct ConfigSubset *sub, const char *name)
Get a sort config item by name.
Definition: helpers.c:292
#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
@ UT_FLAT
Unthreaded.
Definition: mutt_thread.h:97
@ UT_UNSET
Not yet set by user, stick to legacy semantics.
Definition: mutt_thread.h:96
@ UT_THREADS
Normal threading (root above subthreads)
Definition: mutt_thread.h:98
@ UT_REVERSE
Reverse threading (subthreads above root)
Definition: mutt_thread.h:99
int mutt_multi_choice(const char *prompt, const char *letters)
Offer the user a multiple choice question.
Definition: question.c:54
#define SORT_MASK
Mask for the sort id.
Definition: sort2.h:74
#define SORT_LAST
Sort thread by last-X, e.g. received date.
Definition: sort2.h:76
SortType
Methods for sorting.
Definition: sort2.h:38
@ SORT_SUBJECT
Sort by the email's subject.
Definition: sort2.h:42
@ SORT_ORDER
Sort by the order the messages appear in the mailbox.
Definition: sort2.h:44
@ SORT_THREADS
Sort by email threads.
Definition: sort2.h:45
@ SORT_SPAM
Sort by the email's spam score.
Definition: sort2.h:53
@ SORT_LABEL
Sort by the emails label.
Definition: sort2.h:58
@ SORT_FROM
Sort by the email's From field.
Definition: sort2.h:43
@ SORT_SIZE
Sort by the size of the email.
Definition: sort2.h:40
@ SORT_RECEIVED
Sort by when the message were delivered locally.
Definition: sort2.h:46
@ SORT_TO
Sort by the email's To field.
Definition: sort2.h:47
@ SORT_DATE
Sort by the date the email was sent.
Definition: sort2.h:39
@ SORT_SCORE
Sort by the email's score.
Definition: sort2.h:48
#define SORT_REVERSE
Reverse the order of the sort.
Definition: sort2.h:75
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:310
+ 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 600 of file external.c.

601{
602 bool rc = false;
603 struct Buffer *buf = buf_pool_get();
604
605 if (buf_get_field(_("Shell command: "), buf, MUTT_COMP_FILE_SIMPLE, false,
606 NULL, NULL, NULL) != 0)
607 {
608 goto done;
609 }
610
611 if (buf_is_empty(buf))
612 {
613 const char *const c_shell = cs_subset_string(NeoMutt->sub, "shell");
614 buf_strcpy(buf, c_shell);
615 }
616
617 if (buf_is_empty(buf))
618 {
619 goto done;
620 }
621
623 mutt_endwin();
624 fflush(stdout);
625 int rc2 = mutt_system(buf_string(buf));
626 if (rc2 == -1)
627 mutt_debug(LL_DEBUG1, "Error running \"%s\"\n", buf_string(buf));
628
629 const bool c_wait_key = cs_subset_bool(NeoMutt->sub, "wait_key");
630 if ((rc2 != 0) || c_wait_key)
632
633 rc = true;
634done:
635 buf_pool_release(&buf);
636 return rc;
637}
int mutt_any_key_to_continue(const char *s)
Prompt the user to 'press any key' and wait.
Definition: curs_lib.c:388
void mutt_endwin(void)
Shutdown curses.
Definition: curs_lib.c:355
#define mutt_debug(LEVEL,...)
Definition: logging2.h:84
@ LL_DEBUG1
Log at debug level 1.
Definition: logging2.h:40
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: