NeoMutt  2022-04-29-215-gc12b98
Teaching an old dog new tricks
DOXYGEN
commands.h File Reference

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

#include <stdbool.h>
#include <stdio.h>
+ Include dependency graph for commands.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 ci_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 mutt_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 commands.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 commands.h.

39{
40 TRANSFORM_NONE = 0,
43};
@ TRANSFORM_NONE
No transformation.
Definition: commands.h:40
@ TRANSFORM_DECODE
Decode message.
Definition: commands.h:42
@ TRANSFORM_DECRYPT
Decrypt message.
Definition: commands.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 commands.h.

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

Function Documentation

◆ ci_bounce_message()

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

Bounce an email.

Parameters
mMailbox
elList of Emails to bounce

Definition at line 91 of file commands.c.

92{
93 if (!m || !el || STAILQ_EMPTY(el))
94 return;
95
96 struct Buffer *buf = mutt_buffer_pool_get();
97 struct Buffer *prompt = mutt_buffer_pool_get();
98 struct Buffer *scratch = NULL;
99
100 struct AddressList al = TAILQ_HEAD_INITIALIZER(al);
101 char *err = NULL;
102 int rc;
103 int msg_count = 0;
104
105 struct EmailNode *en = NULL;
106 STAILQ_FOREACH(en, el, entries)
107 {
108 /* RFC5322 mandates a From: header,
109 * so warn before bouncing messages without one */
110 if (TAILQ_EMPTY(&en->email->env->from))
111 mutt_error(_("Warning: message contains no From: header"));
112
113 msg_count++;
114 }
115
116 if (msg_count == 1)
117 mutt_buffer_strcpy(prompt, _("Bounce message to: "));
118 else
119 mutt_buffer_strcpy(prompt, _("Bounce tagged messages to: "));
120
122 false, NULL, NULL, NULL);
123 if ((rc != 0) || mutt_buffer_is_empty(buf))
124 goto done;
125
127 if (TAILQ_EMPTY(&al))
128 {
129 mutt_error(_("Error parsing address"));
130 goto done;
131 }
132
134
135 if (mutt_addrlist_to_intl(&al, &err) < 0)
136 {
137 mutt_error(_("Bad IDN: '%s'"), err);
138 FREE(&err);
139 goto done;
140 }
141
143 mutt_addrlist_write(&al, buf->data, buf->dsize, true);
144
145#define EXTRA_SPACE (15 + 7 + 2)
146 scratch = mutt_buffer_pool_get();
147 mutt_buffer_printf(scratch,
148 ngettext("Bounce message to %s?", "Bounce messages to %s?", msg_count),
149 mutt_buffer_string(buf));
150
151 const size_t width = msgwin_get_width();
152 if (mutt_strwidth(mutt_buffer_string(scratch)) > (width - EXTRA_SPACE))
153 {
154 mutt_simple_format(prompt->data, prompt->dsize, 0, width - EXTRA_SPACE,
155 JUSTIFY_LEFT, 0, scratch->data, scratch->dsize, false);
156 mutt_buffer_addstr(prompt, "...?");
157 }
158 else
159 mutt_buffer_copy(prompt, scratch);
160
161 const enum QuadOption c_bounce = cs_subset_quad(NeoMutt->sub, "bounce");
162 if (query_quadoption(c_bounce, mutt_buffer_string(prompt)) != MUTT_YES)
163 {
165 mutt_message(ngettext("Message not bounced", "Messages not bounced", msg_count));
166 goto done;
167 }
168
170
171 struct Message *msg = NULL;
172 STAILQ_FOREACH(en, el, entries)
173 {
174 msg = mx_msg_open(m, en->email->msgno);
175 if (!msg)
176 {
177 rc = -1;
178 break;
179 }
180
181 rc = mutt_bounce_message(msg->fp, m, en->email, &al, NeoMutt->sub);
182 mx_msg_close(m, &msg);
183
184 if (rc < 0)
185 break;
186 }
187
188 /* If no error, or background, display message. */
189 if ((rc == 0) || (rc == S_BKG))
190 mutt_message(ngettext("Message bounced", "Messages bounced", msg_count));
191
192done:
196 mutt_buffer_pool_release(&scratch);
197}
void mutt_addrlist_clear(struct AddressList *al)
Unlink and free all Address in an AddressList.
Definition: address.c:1470
size_t mutt_addrlist_write(const struct AddressList *al, char *buf, size_t buflen, bool display)
Write an Address to a buffer.
Definition: address.c:1150
int mutt_addrlist_parse2(struct AddressList *al, const char *s)
Parse a list of email addresses.
Definition: address.c:616
int mutt_addrlist_to_intl(struct AddressList *al, char **err)
Convert an Address list to Punycode.
Definition: address.c:1305
void mutt_expand_aliases(struct AddressList *al)
Expand aliases in a List of Addresses.
Definition: alias.c:298
bool mutt_buffer_is_empty(const struct Buffer *buf)
Is the Buffer empty?
Definition: buffer.c:260
size_t mutt_buffer_strcpy(struct Buffer *buf, const char *s)
Copy a string into a Buffer.
Definition: buffer.c:327
size_t mutt_buffer_addstr(struct Buffer *buf, const char *s)
Add a string to a Buffer.
Definition: buffer.c:233
int mutt_buffer_printf(struct Buffer *buf, const char *fmt,...)
Format a string overwriting a Buffer.
Definition: buffer.c:168
size_t mutt_buffer_copy(struct Buffer *dst, const struct Buffer *src)
Copy a Buffer's contents to another Buffer.
Definition: buffer.c:462
void mutt_buffer_reset(struct Buffer *buf)
Reset an existing Buffer.
Definition: buffer.c:85
static const char * mutt_buffer_string(const struct Buffer *buf)
Convert a buffer to a const char * "string".
Definition: buffer.h:77
#define EXTRA_SPACE
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:639
size_t mutt_strwidth(const char *s)
Measure a string's width in screen cells.
Definition: curs_lib.c:907
@ JUSTIFY_LEFT
Left justify the text.
Definition: curs_lib.h:42
int mutt_buffer_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 mutt_error(...)
Definition: logging.h:87
#define mutt_message(...)
Definition: logging.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:269
void msgwin_clear_text(void)
Clear the text in the Message Window.
Definition: msgwin.c:249
#define _(a)
Definition: message.h:28
#define MUTT_COMP_ALIAS
Alias completion (in alias dialog)
Definition: mutt.h:53
int mx_msg_close(struct Mailbox *m, struct Message **msg)
Close a message.
Definition: mx.c:1193
struct Message * mx_msg_open(struct Mailbox *m, int msgno)
Return a stream pointer for a message.
Definition: mx.c:1147
void mutt_buffer_pool_release(struct Buffer **pbuf)
Free a Buffer from the pool.
Definition: pool.c:112
struct Buffer * mutt_buffer_pool_get(void)
Get a Buffer from the pool.
Definition: pool.c:101
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:894
#define S_BKG
Definition: string2.h:42
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
int msgno
Number displayed to the user.
Definition: email.h:111
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 1247 of file commands.c.

1248{
1249 bool rc = false;
1250 struct EmailNode *en = NULL;
1251 STAILQ_FOREACH(en, el, entries)
1252 {
1254 rc = check_traditional_pgp(m, en->email) || rc;
1255 }
1256
1257 return rc;
1258}
static bool check_traditional_pgp(struct Mailbox *m, struct Email *e)
Check for an inline PGP content.
Definition: commands.c:1219
#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:

◆ mutt_commands_cleanup()

void mutt_commands_cleanup ( void  )

Clean up commands globals.

Definition at line 81 of file commands.c.

82{
84}
void mutt_buffer_dealloc(struct Buffer *buf)
Release the memory allocated by a buffer.
Definition: buffer.c:309
static struct Buffer LastSaveFolder
The folder the user last saved to.
Definition: commands.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 696 of file commands.c.

697{
698 const char *pfx = NULL;
699 char buf[128] = { 0 };
700
701 struct AddressList *al = mutt_get_address(env, &pfx);
702 if (!al)
703 return;
704
705 /* Note: We don't convert IDNA to local representation this time.
706 * That is intentional, so the user has an opportunity to copy &
707 * paste the on-the-wire form of the address to other, IDN-unable
708 * software. */
709 buf[0] = '\0';
710 mutt_addrlist_write(al, buf, sizeof(buf), false);
711 mutt_message("%s: %s", pfx, buf);
712}
struct AddressList * mutt_get_address(struct Envelope *env, const char **prefix)
Get an Address from an Envelope.
Definition: alias.c:330
+ 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 1105 of file commands.c.

1106{
1107 struct Buffer *buf = mutt_buffer_pool_get();
1108 struct Buffer *charset = mutt_buffer_pool_get();
1109 struct Buffer *obuf = mutt_buffer_pool_get();
1110 struct Buffer *tmp = mutt_buffer_pool_get();
1111
1112 bool rc = false;
1113 bool charset_changed = false;
1114 bool type_changed = false;
1115 bool structure_changed = false;
1116
1117 char *cp = mutt_param_get(&b->parameter, "charset");
1118 mutt_buffer_strcpy(charset, cp);
1119
1120 mutt_buffer_printf(buf, "%s/%s", TYPE(b), b->subtype);
1121 mutt_buffer_copy(obuf, buf);
1122 if (!TAILQ_EMPTY(&b->parameter))
1123 {
1124 struct Parameter *np = NULL;
1125 TAILQ_FOREACH(np, &b->parameter, entries)
1126 {
1127 mutt_addr_cat(tmp->data, tmp->dsize, np->value, MimeSpecials);
1128 mutt_buffer_add_printf(buf, "; %s=%s", np->attribute, mutt_buffer_string(tmp));
1129 }
1130 }
1131
1132 if ((mutt_buffer_get_field("Content-Type: ", buf, MUTT_COMP_NO_FLAGS, false,
1133 NULL, NULL, NULL) != 0) ||
1135 {
1136 goto done;
1137 }
1138
1139 /* clean up previous junk */
1141 FREE(&b->subtype);
1142
1144
1145 mutt_buffer_printf(tmp, "%s/%s", TYPE(b), NONULL(b->subtype));
1146 type_changed = !mutt_istr_equal(mutt_buffer_string(tmp), mutt_buffer_string(obuf));
1147 charset_changed = !mutt_istr_equal(mutt_buffer_string(charset),
1148 mutt_param_get(&b->parameter, "charset"));
1149
1150 /* if in send mode, check for conversion - current setting is default. */
1151
1152 if (!e && (b->type == TYPE_TEXT) && charset_changed)
1153 {
1154 mutt_buffer_printf(tmp, _("Convert to %s upon sending?"),
1155 mutt_param_get(&b->parameter, "charset"));
1157 if (ans != MUTT_ABORT)
1158 b->noconv = (ans == MUTT_NO);
1159 }
1160
1161 /* inform the user */
1162
1163 mutt_buffer_printf(tmp, "%s/%s", TYPE(b), NONULL(b->subtype));
1164 if (type_changed)
1165 mutt_message(_("Content-Type changed to %s"), mutt_buffer_string(tmp));
1166 if ((b->type == TYPE_TEXT) && charset_changed)
1167 {
1168 if (type_changed)
1169 mutt_sleep(1);
1170 mutt_message(b->noconv ? _("Character set changed to %s; not converting") :
1171 _("Character set changed to %s; converting"),
1172 mutt_param_get(&b->parameter, "charset"));
1173 }
1174
1175 b->force_charset |= charset_changed;
1176
1177 if (!is_multipart(b) && b->parts)
1178 {
1179 structure_changed = true;
1180 mutt_body_free(&b->parts);
1181 }
1182 if (!mutt_is_message_type(b->type, b->subtype) && b->email)
1183 {
1184 structure_changed = true;
1185 b->email->body = NULL;
1186 email_free(&b->email);
1187 }
1188
1189 if (fp && !b->parts && (is_multipart(b) || mutt_is_message_type(b->type, b->subtype)))
1190 {
1191 structure_changed = true;
1192 mutt_parse_part(fp, b);
1193 }
1194
1195 if ((WithCrypto != 0) && e)
1196 {
1197 if (e->body == b)
1199
1200 e->security |= crypt_query(b);
1201 }
1202
1203 rc = structure_changed | type_changed;
1204
1205done:
1207 mutt_buffer_pool_release(&charset);
1210 return rc;
1211}
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:681
int mutt_buffer_add_printf(struct Buffer *buf, const char *fmt,...)
Format a string appending a Buffer.
Definition: buffer.c:211
SecurityFlags crypt_query(struct Body *b)
Check out the type of encryption used.
Definition: crypt.c:675
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:819
#define MUTT_COMP_NO_FLAGS
No flags are set.
Definition: mutt.h:52
void mutt_sleep(short s)
Sleep for a while.
Definition: muttlib.c:1455
#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:1737
void mutt_parse_content_type(const char *s, struct Body *ct)
Parse a content type.
Definition: parse.c:424
bool mutt_is_message_type(int type, const char *subtype)
Determine if a mime type matches a message or not.
Definition: parse.c:1442
@ 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 641 of file commands.c.

642{
643 struct Buffer *buf = mutt_buffer_pool_get();
644 struct Buffer *err = mutt_buffer_pool_get();
645
646 window_redraw(NULL);
647 /* if enter is pressed after : with no command, just return */
648 if ((mutt_buffer_get_field(":", buf, MUTT_COMP_COMMAND, false, NULL, NULL, NULL) != 0) ||
650 {
651 goto done;
652 }
653
654 /* check if buf is a valid icommand, else fall back quietly to parse_rc_lines */
656 if (!mutt_buffer_is_empty(err))
657 {
658 /* since errbuf could potentially contain printf() sequences in it,
659 * we must call mutt_error() in this fashion so that vsprintf()
660 * doesn't expect more arguments that we passed */
661 if (rc == MUTT_CMD_ERROR)
662 mutt_error("%s", mutt_buffer_string(err));
663 else
665 }
666 else if (rc != MUTT_CMD_SUCCESS)
667 {
669 if (!mutt_buffer_is_empty(err))
670 {
671 if (rc == MUTT_CMD_SUCCESS) /* command succeeded with message */
673 else if (rc == MUTT_CMD_ERROR)
674 mutt_error("%s", mutt_buffer_string(err));
675 else if (rc == MUTT_CMD_WARNING)
677 }
678 }
679 /* else successful command */
680
681 if (NeoMutt)
682 {
683 // Running commands could cause anything to change, so let others know
685 }
686
687done:
690}
CommandResult
Error codes for command_t parse functions.
Definition: command.h:34
@ MUTT_CMD_SUCCESS
Success: Command worked.
Definition: command.h:37
@ MUTT_CMD_ERROR
Error: Can't help the user.
Definition: command.h:35
@ MUTT_CMD_WARNING
Warning: Help given to the user.
Definition: command.h:36
#define mutt_warning(...)
Definition: logging.h:85
enum CommandResult mutt_parse_icommand(const char *line, struct Buffer *err)
Parse an informational command.
Definition: icommands.c:91
enum CommandResult mutt_parse_rc_line(const char *line, struct Buffer *err)
Parse a line of user config.
Definition: init.c:894
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:54
void window_redraw(struct MuttWindow *win)
Reflow, recalc and repaint a tree of Windows.
Definition: mutt_window.c:604
@ NT_GLOBAL_COMMAND
A NeoMutt command.
Definition: neomutt.h:55
@ NT_GLOBAL
Not object-related, NotifyGlobal.
Definition: notify_type.h:46
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 422 of file commands.c.

423{
424 if (!m || !el)
425 return;
426
427 struct Buffer *buf = mutt_buffer_pool_get();
428
429 if (mutt_buffer_get_field(_("Pipe to command: "), buf, MUTT_COMP_FILE_SIMPLE,
430 false, NULL, NULL, NULL) != 0)
431 {
432 goto cleanup;
433 }
434
435 if (mutt_buffer_len(buf) == 0)
436 goto cleanup;
437
439 const bool c_pipe_decode = cs_subset_bool(NeoMutt->sub, "pipe_decode");
440 const bool c_pipe_split = cs_subset_bool(NeoMutt->sub, "pipe_split");
441 const char *const c_pipe_sep = cs_subset_string(NeoMutt->sub, "pipe_sep");
442 pipe_message(m, el, mutt_buffer_string(buf), c_pipe_decode, false, c_pipe_split, c_pipe_sep);
443
444cleanup:
446}
size_t mutt_buffer_len(const struct Buffer *buf)
Calculate the length of a Buffer.
Definition: buffer.c:371
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: commands.c:294
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
#define MUTT_COMP_FILE_SIMPLE
File completion (no browser)
Definition: mutt.h:57
void mutt_buffer_expand_path(struct Buffer *buf)
Create the canonical path.
Definition: muttlib.c:322
+ 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 453 of file commands.c.

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

815{
816 if (!el || STAILQ_EMPTY(el))
817 return -1;
818
819 int rc = -1;
820 int tagged_progress_count = 0;
821 unsigned int msg_count = 0;
822 struct Mailbox *m_save = NULL;
823
824 struct Buffer *buf = mutt_buffer_pool_get();
825 struct stat st = { 0 };
826 struct EmailNode *en = NULL;
827
828 STAILQ_FOREACH(en, el, entries)
829 {
830 msg_count++;
831 }
832 en = STAILQ_FIRST(el);
833
834 const SecurityFlags security_flags = WithCrypto ? en->email->security : SEC_NO_FLAGS;
835 const bool is_passphrase_needed = security_flags & SEC_ENCRYPT;
836
837 const char *prompt = NULL;
838 const char *progress_msg = NULL;
839
840 // Set prompt and progress_msg
841 switch (save_opt)
842 {
843 case SAVE_COPY:
844 // L10N: Progress meter message when copying tagged messages
845 progress_msg = (msg_count > 1) ? _("Copying tagged messages...") : NULL;
846 switch (transform_opt)
847 {
848 case TRANSFORM_NONE:
849 prompt = (msg_count > 1) ? _("Copy tagged to mailbox") : _("Copy to mailbox");
850 break;
852 prompt = (msg_count > 1) ? _("Decrypt-copy tagged to mailbox") :
853 _("Decrypt-copy to mailbox");
854 break;
855 case TRANSFORM_DECODE:
856 prompt = (msg_count > 1) ? _("Decode-copy tagged to mailbox") :
857 _("Decode-copy to mailbox");
858 break;
859 }
860 break;
861
862 case SAVE_MOVE:
863 // L10N: Progress meter message when saving tagged messages
864 progress_msg = (msg_count > 1) ? _("Saving tagged messages...") : NULL;
865 switch (transform_opt)
866 {
867 case TRANSFORM_NONE:
868 prompt = (msg_count > 1) ? _("Save tagged to mailbox") : _("Save to mailbox");
869 break;
871 prompt = (msg_count > 1) ? _("Decrypt-save tagged to mailbox") :
872 _("Decrypt-save to mailbox");
873 break;
874 case TRANSFORM_DECODE:
875 prompt = (msg_count > 1) ? _("Decode-save tagged to mailbox") :
876 _("Decode-save to mailbox");
877 break;
878 }
879 break;
880 }
881
883 mutt_default_save(buf->data, buf->dsize, en->email);
886
887 if (mutt_buffer_enter_fname(prompt, buf, false, NULL, false, NULL, NULL,
888 MUTT_SEL_NO_FLAGS) == -1)
889 {
890 goto cleanup;
891 }
892
893 size_t pathlen = mutt_buffer_len(buf);
894 if (pathlen == 0)
895 goto cleanup;
896
897 /* Trim any trailing '/' */
898 if (buf->data[pathlen - 1] == '/')
899 buf->data[pathlen - 1] = '\0';
900
901 /* This is an undocumented feature of ELM pointed out to me by Felix von
902 * Leitner <leitner@prz.fu-berlin.de> */
905 if (mutt_str_equal(mutt_buffer_string(buf), "."))
907 else
909
911
912 /* check to make sure that this file is really the one the user wants */
913 if (mutt_save_confirm(mutt_buffer_string(buf), &st) != 0)
914 goto cleanup;
915
916 if (is_passphrase_needed && (transform_opt != TRANSFORM_NONE) &&
917 !crypt_valid_passphrase(security_flags))
918 {
919 rc = -1;
920 goto errcleanup;
921 }
922
923 mutt_message(_("Copying to %s..."), mutt_buffer_string(buf));
924
925#ifdef USE_IMAP
926 enum MailboxType mailbox_type = imap_path_probe(mutt_buffer_string(buf), NULL);
927 if ((m->type == MUTT_IMAP) && (transform_opt == TRANSFORM_NONE) && (mailbox_type == MUTT_IMAP))
928 {
929 rc = imap_copy_messages(m, el, mutt_buffer_string(buf), save_opt);
930 switch (rc)
931 {
932 /* success */
933 case 0:
935 rc = 0;
936 goto cleanup;
937 /* non-fatal error: continue to fetch/append */
938 case 1:
939 break;
940 /* fatal error, abort */
941 case -1:
942 goto errcleanup;
943 }
944 }
945#endif
946
948 m_save = mx_path_resolve(mutt_buffer_string(buf));
949 bool old_append = m_save->append;
950 OpenMailboxFlags mbox_flags = MUTT_NEWFOLDER;
951 /* Display a tagged message progress counter, rather than (for
952 * IMAP) a per-message progress counter */
953 if (msg_count > 1)
954 mbox_flags |= MUTT_QUIET;
955 if (!mx_mbox_open(m_save, mbox_flags))
956 {
957 rc = -1;
958 mailbox_free(&m_save);
959 goto errcleanup;
960 }
961 m_save->append = true;
962
963#ifdef USE_COMP_MBOX
964 /* If we're saving to a compressed mailbox, the stats won't be updated
965 * until the next open. Until then, improvise. */
966 struct Mailbox *m_comp = NULL;
967 if (m_save->compress_info)
968 {
969 m_comp = mailbox_find(m_save->realpath);
970 }
971 /* We probably haven't been opened yet */
972 if (m_comp && (m_comp->msg_count == 0))
973 m_comp = NULL;
974#endif
975 if (msg_count == 1)
976 {
977 rc = mutt_save_message_ctx(m, en->email, save_opt, transform_opt, m_save);
978 if (rc != 0)
979 {
980 mx_mbox_close(m_save);
981 m_save->append = old_append;
982 goto errcleanup;
983 }
984#ifdef USE_COMP_MBOX
985 if (m_comp)
986 {
987 m_comp->msg_count++;
988 if (!en->email->read)
989 {
990 m_comp->msg_unread++;
991 if (!en->email->old)
992 m_comp->msg_new++;
993 }
994 if (en->email->flagged)
995 m_comp->msg_flagged++;
996 }
997#endif
998 }
999 else
1000 {
1001 rc = 0;
1002
1003#ifdef USE_NOTMUCH
1004 if (m->type == MUTT_NOTMUCH)
1005 nm_db_longrun_init(m, true);
1006#endif
1007 struct Progress *progress = progress_new(progress_msg, MUTT_PROGRESS_WRITE, msg_count);
1008 STAILQ_FOREACH(en, el, entries)
1009 {
1010 progress_update(progress, ++tagged_progress_count, -1);
1012 rc = mutt_save_message_ctx(m, en->email, save_opt, transform_opt, m_save);
1013 if (rc != 0)
1014 break;
1015#ifdef USE_COMP_MBOX
1016 if (m_comp)
1017 {
1018 struct Email *e2 = en->email;
1019 m_comp->msg_count++;
1020 if (!e2->read)
1021 {
1022 m_comp->msg_unread++;
1023 if (!e2->old)
1024 m_comp->msg_new++;
1025 }
1026 if (e2->flagged)
1027 m_comp->msg_flagged++;
1028 }
1029#endif
1030 }
1031 progress_free(&progress);
1032
1033#ifdef USE_NOTMUCH
1034 if (m->type == MUTT_NOTMUCH)
1036#endif
1037 if (rc != 0)
1038 {
1039 mx_mbox_close(m_save);
1040 m_save->append = old_append;
1041 goto errcleanup;
1042 }
1043 }
1044
1045 const bool need_mailbox_cleanup = ((m_save->type == MUTT_MBOX) ||
1046 (m_save->type == MUTT_MMDF));
1047
1048 mx_mbox_close(m_save);
1049 m_save->append = old_append;
1050
1051 if (need_mailbox_cleanup)
1053
1055 rc = 0;
1056
1057errcleanup:
1058 if (rc != 0)
1059 {
1060 switch (save_opt)
1061 {
1062 case SAVE_MOVE:
1063 if (msg_count > 1)
1064 {
1065 // L10N: Message when an index tagged save operation fails for some reason
1066 mutt_error(_("Error saving tagged messages"));
1067 }
1068 else
1069 {
1070 // L10N: Message when an index/pager save operation fails for some reason
1071 mutt_error(_("Error saving message"));
1072 }
1073 break;
1074 case SAVE_COPY:
1075 if (msg_count > 1)
1076 {
1077 // L10N: Message when an index tagged copy operation fails for some reason
1078 mutt_error(_("Error copying tagged messages"));
1079 }
1080 else
1081 {
1082 // L10N: Message when an index/pager copy operation fails for some reason
1083 mutt_error(_("Error copying message"));
1084 }
1085 break;
1086 }
1087 }
1088
1089 mailbox_free(&m_save);
1090
1091cleanup:
1093 return rc;
1094}
#define MUTT_SEL_NO_FLAGS
No flags are set.
Definition: lib.h:55
void mutt_buffer_alloc(struct Buffer *buf, size_t new_size)
Make sure a buffer can store at least new_size bytes.
Definition: buffer.c:275
void mutt_buffer_fix_dptr(struct Buffer *buf)
Move the dptr to end of the Buffer.
Definition: buffer.c:189
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: commands.c:772
bool crypt_valid_passphrase(SecurityFlags flags)
Check that we have a usable passphrase, ask if not.
Definition: crypt.c:134
int mutt_buffer_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:445
void mutt_file_resolve_symlink(struct Buffer *buf)
Resolve a symlink in place.
Definition: file.c:1691
enum MailboxType imap_path_probe(const char *path, const struct stat *st)
Is this an IMAP Mailbox? - Implements MxOps::path_probe() -.
Definition: imap.c:2400
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:1683
void mailbox_free(struct Mailbox **ptr)
Free a Mailbox.
Definition: mailbox.c:87
struct Mailbox * mailbox_find(const char *path)
Find the mailbox with a given path.
Definition: mailbox.c:139
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:807
#define PATH_MAX
Definition: mutt.h:40
void mutt_clear_error(void)
Clear the message line (bottom line of screen)
Definition: mutt_logging.c:74
void mutt_mailbox_cleanup(const char *path, struct stat *st)
Restore the timestamp of a mailbox.
Definition: mutt_mailbox.c:424
void mutt_buffer_pretty_mailbox(struct Buffer *buf)
Shorten a mailbox path using '~' or '='.
Definition: muttlib.c:599
int mutt_save_confirm(const char *s, struct stat *st)
Ask the user to save.
Definition: muttlib.c:1356
bool mx_mbox_open(struct Mailbox *m, OpenMailboxFlags flags)
Open a mailbox and parse it.
Definition: mx.c:304
struct Mailbox * mx_path_resolve(const char *path)
Get a Mailbox for a path.
Definition: mx.c:1677
enum MxStatus mx_mbox_close(struct Mailbox *m)
Save changes and close mailbox.
Definition: mx.c:615
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:368
void nm_db_longrun_init(struct Mailbox *m, bool writable)
Start a long transaction.
Definition: db.c:353
@ 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:86
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:118
#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 772 of file commands.c.

774{
777 int rc;
778
779 set_copy_flags(e, transform_opt, &cmflags, &chflags);
780
781 struct Message *msg = mx_msg_open(m_src, e->msgno);
782 if (msg && transform_opt != TRANSFORM_NONE)
783 {
785 }
786
787 rc = mutt_append_message(m_dst, m_src, e, msg, cmflags, chflags);
788 mx_msg_close(m_src, &msg);
789 if (rc != 0)
790 return rc;
791
792 if (save_opt == SAVE_MOVE)
793 {
794 mutt_set_flag(m_src, e, MUTT_DELETE, true);
795 mutt_set_flag(m_src, e, MUTT_PURGE, true);
796 const bool c_delete_untag = cs_subset_bool(NeoMutt->sub, "delete_untag");
797 if (c_delete_untag)
798 mutt_set_flag(m_src, e, MUTT_TAG, false);
799 }
800
801 return 0;
802}
void mutt_parse_mime_message(struct Email *e, FILE *fp)
Parse a MIME email.
Definition: attachments.c:591
static void set_copy_flags(struct Email *e, enum MessageTransformOpt transform_opt, CopyMessageFlags *cmflags, CopyHeaderFlags *chflags)
Set the flags for a message copy.
Definition: commands.c:721
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:939
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
@ MUTT_PURGE
Messages to be purged (bypass trash)
Definition: mutt.h:97
@ MUTT_TAG
Tagged messages.
Definition: mutt.h:100
@ MUTT_DELETE
Messages to be deleted.
Definition: mutt.h:95
#define mutt_set_flag(m, e, flag, bf)
Definition: protos.h:63
+ 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 495 of file commands.c.

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

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