NeoMutt  2021-02-05
Teaching an old dog new tricks
DOXYGEN
mutt_attach.c File Reference

Handling of email attachments. More...

#include "config.h"
#include <errno.h>
#include <fcntl.h>
#include <stdbool.h>
#include <stdio.h>
#include <string.h>
#include <sys/stat.h>
#include <sys/wait.h>
#include <unistd.h>
#include "mutt/lib.h"
#include "config/lib.h"
#include "email/lib.h"
#include "core/lib.h"
#include "gui/lib.h"
#include "mutt_attach.h"
#include "ncrypt/lib.h"
#include "send/lib.h"
#include "context.h"
#include "copy.h"
#include "handler.h"
#include "mailcap.h"
#include "mutt_globals.h"
#include "muttlib.h"
#include "mx.h"
#include "options.h"
#include "pager.h"
#include "protos.h"
#include "rfc3676.h"
#include "state.h"
#include "imap/lib.h"
+ Include dependency graph for mutt_attach.c:

Go to the source code of this file.

Functions

int mutt_get_tmp_attachment (struct Body *a)
 Get a temporary copy of an attachment. More...
 
int mutt_compose_attachment (struct Body *a)
 Create an attachment. More...
 
int mutt_edit_attachment (struct Body *a)
 Edit an attachment. More...
 
void mutt_check_lookup_list (struct Body *b, char *type, size_t len)
 Update the mime type. More...
 
static int wait_interactive_filter (pid_t pid)
 Wait after an interactive filter. More...
 
int mutt_view_attachment (FILE *fp, struct Body *a, enum ViewAttachMode mode, struct Email *e, struct AttachCtx *actx, struct MuttWindow *win)
 View an attachment. More...
 
int mutt_pipe_attachment (FILE *fp, struct Body *b, const char *path, char *outfile)
 Pipe an attachment to a command. More...
 
static FILE * save_attachment_open (const char *path, enum SaveAttach opt)
 Open a file to write an attachment to. More...
 
int mutt_save_attachment (FILE *fp, struct Body *m, const char *path, enum SaveAttach opt, struct Email *e)
 Save an attachment. More...
 
int mutt_decode_save_attachment (FILE *fp, struct Body *m, const char *path, int displaying, enum SaveAttach opt)
 Decode, then save an attachment. More...
 
int mutt_print_attachment (FILE *fp, struct Body *a)
 Print out an attachment. More...
 
void mutt_add_temp_attachment (const char *filename)
 Add file to list of temporary attachments. More...
 
void mutt_unlink_temp_attachments (void)
 Delete all temporary attachments. More...
 

Detailed Description

Handling of email attachments.

Authors
  • Michael R. Elkins
  • Thomas Roessler

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 mutt_attach.c.

Function Documentation

◆ mutt_get_tmp_attachment()

int mutt_get_tmp_attachment ( struct Body a)

Get a temporary copy of an attachment.

Parameters
aAttachment to copy
Return values
0Success
-1Error

Definition at line 69 of file mutt_attach.c.

70 {
71  char type[256];
72  struct stat st;
73 
74  if (a->unlink)
75  return 0;
76 
77  struct Buffer *tmpfile = mutt_buffer_pool_get();
78  struct MailcapEntry *entry = mailcap_entry_new();
79  snprintf(type, sizeof(type), "%s/%s", TYPE(a), a->subtype);
80  mailcap_lookup(a, type, sizeof(type), entry, MUTT_MC_NO_FLAGS);
81  mailcap_expand_filename(entry->nametemplate, a->filename, tmpfile);
82 
83  mailcap_entry_free(&entry);
84 
85  if (stat(a->filename, &st) == -1)
86  {
87  mutt_buffer_pool_release(&tmpfile);
88  return -1;
89  }
90 
91  FILE *fp_in = NULL, *fp_out = NULL;
92  if ((fp_in = fopen(a->filename, "r")) &&
93  (fp_out = mutt_file_fopen(mutt_buffer_string(tmpfile), "w")))
94  {
95  mutt_file_copy_stream(fp_in, fp_out);
97  a->unlink = true;
98 
99  if (a->stamp >= st.st_mtime)
101  }
102  else
103  mutt_perror(fp_in ? mutt_buffer_string(tmpfile) : a->filename);
104 
105  mutt_file_fclose(&fp_in);
106  mutt_file_fclose(&fp_out);
107 
108  mutt_buffer_pool_release(&tmpfile);
109 
110  return a->unlink ? 0 : -1;
111 }
A mailcap entry.
Definition: mailcap.h:38
struct MailcapEntry * mailcap_entry_new(void)
Allocate memory for a new rfc1524 entry.
Definition: mailcap.c:427
void mutt_stamp_attachment(struct Body *a)
Timestamp an Attachment.
Definition: sendlib.c:893
char * filename
when sending a message, this is the file to which this structure refers
Definition: body.h:46
struct Buffer * mutt_buffer_pool_get(void)
Get a Buffer from the pool.
Definition: pool.c:101
#define mutt_perror(...)
Definition: logging.h:85
void mutt_buffer_pool_release(struct Buffer **pbuf)
Free a Buffer from the pool.
Definition: pool.c:112
String manipulation buffer.
Definition: buffer.h:33
No flags set.
Definition: mailcap.h:58
bool mailcap_lookup(struct Body *a, char *type, size_t typelen, struct MailcapEntry *entry, enum MailcapLookup opt)
Find given type in the list of mailcap files.
Definition: mailcap.c:465
void mailcap_expand_filename(const char *nametemplate, const char *oldfile, struct Buffer *newfile)
Expand a new filename from a template or existing filename.
Definition: mailcap.c:533
static const char * mutt_buffer_string(const struct Buffer *buf)
Convert a buffer to a const char * "string".
Definition: buffer.h:77
int mutt_file_fclose(FILE **fp)
Close a FILE handle (and NULL the pointer)
Definition: file.c:153
char * subtype
content-type subtype
Definition: body.h:37
void mailcap_entry_free(struct MailcapEntry **ptr)
Deallocate an struct MailcapEntry.
Definition: mailcap.c:436
char * nametemplate
Definition: mailcap.h:46
#define TYPE(body)
Definition: mime.h:89
int mutt_file_copy_stream(FILE *fp_in, FILE *fp_out)
Copy the contents of one file into another.
Definition: file.c:271
char * mutt_str_replace(char **p, const char *s)
Replace one string with another.
Definition: string.c:446
time_t stamp
Time stamp of last encoding update.
Definition: body.h:61
bool unlink
If true, filename should be unlink()ed before free()ing this structure.
Definition: body.h:69
FILE * mutt_file_fopen(const char *path, const char *mode)
Call fopen() safely.
Definition: file.c:589
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mutt_compose_attachment()

int mutt_compose_attachment ( struct Body a)

Create an attachment.

Parameters
aBody of email
Return values
1if require full screen redraw
0otherwise

Definition at line 119 of file mutt_attach.c.

120 {
121  char type[256];
122  struct MailcapEntry *entry = mailcap_entry_new();
123  bool unlink_newfile = false;
124  int rc = 0;
125  struct Buffer *cmd = mutt_buffer_pool_get();
126  struct Buffer *newfile = mutt_buffer_pool_get();
127  struct Buffer *tmpfile = mutt_buffer_pool_get();
128 
129  snprintf(type, sizeof(type), "%s/%s", TYPE(a), a->subtype);
130  if (mailcap_lookup(a, type, sizeof(type), entry, MUTT_MC_COMPOSE))
131  {
132  if (entry->composecommand || entry->composetypecommand)
133  {
134  if (entry->composetypecommand)
136  else
137  mutt_buffer_strcpy(cmd, entry->composecommand);
138 
139  mailcap_expand_filename(entry->nametemplate, a->filename, newfile);
140  mutt_debug(LL_DEBUG1, "oldfile: %s newfile: %s\n", a->filename,
141  mutt_buffer_string(newfile));
142  if (mutt_file_symlink(a->filename, mutt_buffer_string(newfile)) == -1)
143  {
144  if (mutt_yesorno(_("Can't match 'nametemplate', continue?"), MUTT_YES) != MUTT_YES)
145  goto bailout;
146  mutt_buffer_strcpy(newfile, a->filename);
147  }
148  else
149  unlink_newfile = true;
150 
151  if (mailcap_expand_command(a, mutt_buffer_string(newfile), type, cmd))
152  {
153  /* For now, editing requires a file, no piping */
154  mutt_error(_("Mailcap compose entry requires %%s"));
155  }
156  else
157  {
158  int r;
159 
160  mutt_endwin();
162  if (r == -1)
163  mutt_error(_("Error running \"%s\""), mutt_buffer_string(cmd));
164 
165  if ((r != -1) && entry->composetypecommand)
166  {
167  struct Body *b = NULL;
168 
169  FILE *fp = mutt_file_fopen(a->filename, "r");
170  if (!fp)
171  {
172  mutt_perror(_("Failure to open file to parse headers"));
173  goto bailout;
174  }
175 
176  b = mutt_read_mime_header(fp, 0);
177  if (b)
178  {
179  if (!TAILQ_EMPTY(&b->parameter))
180  {
182  a->parameter = b->parameter;
183  TAILQ_INIT(&b->parameter);
184  }
185  if (b->description)
186  {
187  FREE(&a->description);
188  a->description = b->description;
189  b->description = NULL;
190  }
191  if (b->form_name)
192  {
193  FREE(&a->form_name);
194  a->form_name = b->form_name;
195  b->form_name = NULL;
196  }
197 
198  /* Remove headers by copying out data to another file, then
199  * copying the file back */
200  fseeko(fp, b->offset, SEEK_SET);
201  mutt_body_free(&b);
202  mutt_buffer_mktemp(tmpfile);
203  FILE *fp_tmp = mutt_file_fopen(mutt_buffer_string(tmpfile), "w");
204  if (!fp_tmp)
205  {
206  mutt_perror(_("Failure to open file to strip headers"));
207  mutt_file_fclose(&fp);
208  goto bailout;
209  }
210  mutt_file_copy_stream(fp, fp_tmp);
211  mutt_file_fclose(&fp);
212  mutt_file_fclose(&fp_tmp);
214  if (mutt_file_rename(mutt_buffer_string(tmpfile), a->filename) != 0)
215  {
216  mutt_perror(_("Failure to rename file"));
217  goto bailout;
218  }
219  }
220  }
221  }
222  }
223  }
224  else
225  {
226  mutt_message(_("No mailcap compose entry for %s, creating empty file"), type);
227  rc = 1;
228  goto bailout;
229  }
230 
231  rc = 1;
232 
233 bailout:
234 
235  if (unlink_newfile)
236  unlink(mutt_buffer_string(newfile));
237 
239  mutt_buffer_pool_release(&newfile);
240  mutt_buffer_pool_release(&tmpfile);
241 
242  mailcap_entry_free(&entry);
243  return rc;
244 }
A mailcap entry.
Definition: mailcap.h:38
struct MailcapEntry * mailcap_entry_new(void)
Allocate memory for a new rfc1524 entry.
Definition: mailcap.c:427
#define mutt_buffer_mktemp(buf)
Definition: muttlib.h:77
char * filename
when sending a message, this is the file to which this structure refers
Definition: body.h:46
struct Buffer * mutt_buffer_pool_get(void)
Get a Buffer from the pool.
Definition: pool.c:101
#define mutt_perror(...)
Definition: logging.h:85
#define mutt_message(...)
Definition: logging.h:83
int mutt_file_rename(const char *oldfile, const char *newfile)
Rename a file.
Definition: file.c:1347
char * composetypecommand
Definition: mailcap.h:43
void mutt_buffer_pool_release(struct Buffer **pbuf)
Free a Buffer from the pool.
Definition: pool.c:112
void mutt_file_unlink(const char *s)
Delete a file, carefully.
Definition: file.c:195
String manipulation buffer.
Definition: buffer.h:33
LOFF_T offset
offset where the actual data begins
Definition: body.h:44
#define _(a)
Definition: message.h:28
char * form_name
Content-Disposition form-data name param.
Definition: body.h:41
The body of an email.
Definition: body.h:34
bool mailcap_lookup(struct Body *a, char *type, size_t typelen, struct MailcapEntry *entry, enum MailcapLookup opt)
Find given type in the list of mailcap files.
Definition: mailcap.c:465
int mailcap_expand_command(struct Body *a, const char *filename, const char *type, struct Buffer *command)
Expand expandos in a command.
Definition: mailcap.c:69
void mailcap_expand_filename(const char *nametemplate, const char *oldfile, struct Buffer *newfile)
Expand a new filename from a template or existing filename.
Definition: mailcap.c:533
static const char * mutt_buffer_string(const struct Buffer *buf)
Convert a buffer to a const char * "string".
Definition: buffer.h:77
Mailcap compose field.
Definition: mailcap.h:60
enum QuadOption mutt_yesorno(const char *msg, enum QuadOption def)
Ask the user a Yes/No question.
Definition: curs_lib.c:379
int mutt_file_fclose(FILE **fp)
Close a FILE handle (and NULL the pointer)
Definition: file.c:153
#define TAILQ_INIT(head)
Definition: queue.h:758
void mutt_param_free(struct ParameterList *pl)
Free a ParameterList.
Definition: parameter.c:61
char * subtype
content-type subtype
Definition: body.h:37
void mutt_endwin(void)
Shutdown curses/slang.
Definition: curs_lib.c:571
void mailcap_entry_free(struct MailcapEntry **ptr)
Deallocate an struct MailcapEntry.
Definition: mailcap.c:436
void mutt_body_free(struct Body **ptr)
Free a Body.
Definition: body.c:57
char * description
content-description
Definition: body.h:40
size_t mutt_buffer_strcpy(struct Buffer *buf, const char *s)
Copy a string into a Buffer.
Definition: buffer.c:312
char * nametemplate
Definition: mailcap.h:46
#define TYPE(body)
Definition: mime.h:89
Log at debug level 1.
Definition: logging.h:40
int mutt_file_copy_stream(FILE *fp_in, FILE *fp_out)
Copy the contents of one file into another.
Definition: file.c:271
#define mutt_error(...)
Definition: logging.h:84
bool unlink
If true, filename should be unlink()ed before free()ing this structure.
Definition: body.h:69
char * composecommand
Definition: mailcap.h:42
#define FREE(x)
Definition: memory.h:40
#define mutt_debug(LEVEL,...)
Definition: logging.h:81
#define TAILQ_EMPTY(head)
Definition: queue.h:714
int mutt_file_symlink(const char *oldpath, const char *newpath)
Create a symlink.
Definition: file.c:299
FILE * mutt_file_fopen(const char *path, const char *mode)
Call fopen() safely.
Definition: file.c:589
struct ParameterList parameter
parameters of the content-type
Definition: body.h:39
int mutt_system(const char *cmd)
Run an external command.
Definition: system.c:51
struct Body * mutt_read_mime_header(FILE *fp, bool digest)
Parse a MIME header.
Definition: parse.c:1267
User answered &#39;Yes&#39;, or assume &#39;Yes&#39;.
Definition: quad.h:40
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mutt_edit_attachment()

int mutt_edit_attachment ( struct Body a)

Edit an attachment.

Parameters
aEmail containing attachment
Return values
1if editor found
0if not

Currently, this only works for send mode, as it assumes that the Body->filename actually contains the information. I'm not sure we want to deal with editing attachments we've already received, so this should be ok.

Returning 0 is useful to tell the calling menu to redraw

Definition at line 259 of file mutt_attach.c.

260 {
261  char type[256];
262  struct MailcapEntry *entry = mailcap_entry_new();
263  bool unlink_newfile = false;
264  int rc = 0;
265  struct Buffer *cmd = mutt_buffer_pool_get();
266  struct Buffer *newfile = mutt_buffer_pool_get();
267 
268  snprintf(type, sizeof(type), "%s/%s", TYPE(a), a->subtype);
269  if (mailcap_lookup(a, type, sizeof(type), entry, MUTT_MC_EDIT))
270  {
271  if (entry->editcommand)
272  {
273  mutt_buffer_strcpy(cmd, entry->editcommand);
274  mailcap_expand_filename(entry->nametemplate, a->filename, newfile);
275  mutt_debug(LL_DEBUG1, "oldfile: %s newfile: %s\n", a->filename,
276  mutt_buffer_string(newfile));
277  if (mutt_file_symlink(a->filename, mutt_buffer_string(newfile)) == -1)
278  {
279  if (mutt_yesorno(_("Can't match 'nametemplate', continue?"), MUTT_YES) != MUTT_YES)
280  goto bailout;
281  mutt_buffer_strcpy(newfile, a->filename);
282  }
283  else
284  unlink_newfile = true;
285 
286  if (mailcap_expand_command(a, mutt_buffer_string(newfile), type, cmd))
287  {
288  /* For now, editing requires a file, no piping */
289  mutt_error(_("Mailcap Edit entry requires %%s"));
290  goto bailout;
291  }
292  else
293  {
294  mutt_endwin();
295  if (mutt_system(mutt_buffer_string(cmd)) == -1)
296  {
297  mutt_error(_("Error running \"%s\""), mutt_buffer_string(cmd));
298  goto bailout;
299  }
300  }
301  }
302  }
303  else if (a->type == TYPE_TEXT)
304  {
305  /* On text, default to editor */
307  }
308  else
309  {
310  mutt_error(_("No mailcap edit entry for %s"), type);
311  rc = 0;
312  goto bailout;
313  }
314 
315  rc = 1;
316 
317 bailout:
318 
319  if (unlink_newfile)
320  unlink(mutt_buffer_string(newfile));
321 
323  mutt_buffer_pool_release(&newfile);
324 
325  mailcap_entry_free(&entry);
326  return rc;
327 }
A mailcap entry.
Definition: mailcap.h:38
struct MailcapEntry * mailcap_entry_new(void)
Allocate memory for a new rfc1524 entry.
Definition: mailcap.c:427
char * filename
when sending a message, this is the file to which this structure refers
Definition: body.h:46
#define NONULL(x)
Definition: string2.h:37
struct Buffer * mutt_buffer_pool_get(void)
Get a Buffer from the pool.
Definition: pool.c:101
void mutt_buffer_pool_release(struct Buffer **pbuf)
Free a Buffer from the pool.
Definition: pool.c:112
String manipulation buffer.
Definition: buffer.h:33
#define _(a)
Definition: message.h:28
bool mailcap_lookup(struct Body *a, char *type, size_t typelen, struct MailcapEntry *entry, enum MailcapLookup opt)
Find given type in the list of mailcap files.
Definition: mailcap.c:465
int mailcap_expand_command(struct Body *a, const char *filename, const char *type, struct Buffer *command)
Expand expandos in a command.
Definition: mailcap.c:69
void mailcap_expand_filename(const char *nametemplate, const char *oldfile, struct Buffer *newfile)
Expand a new filename from a template or existing filename.
Definition: mailcap.c:533
static const char * mutt_buffer_string(const struct Buffer *buf)
Convert a buffer to a const char * "string".
Definition: buffer.h:77
enum QuadOption mutt_yesorno(const char *msg, enum QuadOption def)
Ask the user a Yes/No question.
Definition: curs_lib.c:379
char * editcommand
Definition: mailcap.h:44
char * subtype
content-type subtype
Definition: body.h:37
void mutt_endwin(void)
Shutdown curses/slang.
Definition: curs_lib.c:571
WHERE char * C_Editor
Config: External command to use as an email editor.
Definition: mutt_globals.h:90
void mailcap_entry_free(struct MailcapEntry **ptr)
Deallocate an struct MailcapEntry.
Definition: mailcap.c:436
Type: &#39;text/*&#39;.
Definition: mime.h:38
size_t mutt_buffer_strcpy(struct Buffer *buf, const char *s)
Copy a string into a Buffer.
Definition: buffer.c:312
unsigned int type
content-type primary type, ContentType
Definition: body.h:65
char * nametemplate
Definition: mailcap.h:46
#define TYPE(body)
Definition: mime.h:89
Log at debug level 1.
Definition: logging.h:40
#define mutt_error(...)
Definition: logging.h:84
#define mutt_debug(LEVEL,...)
Definition: logging.h:81
Mailcap edit field.
Definition: mailcap.h:59
int mutt_file_symlink(const char *oldpath, const char *newpath)
Create a symlink.
Definition: file.c:299
void mutt_edit_file(const char *editor, const char *file)
Let the user edit a file.
Definition: curs_lib.c:355
int mutt_system(const char *cmd)
Run an external command.
Definition: system.c:51
User answered &#39;Yes&#39;, or assume &#39;Yes&#39;.
Definition: quad.h:40
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mutt_check_lookup_list()

void mutt_check_lookup_list ( struct Body b,
char *  type,
size_t  len 
)

Update the mime type.

Parameters
bMessage attachment body
typeBuffer with mime type of attachment in "type/subtype" format
lenBuffer length

Definition at line 335 of file mutt_attach.c.

336 {
337  struct ListNode *np = NULL;
338  STAILQ_FOREACH(np, &MimeLookupList, entries)
339  {
340  const int i = mutt_str_len(np->data) - 1;
341  if (((i > 0) && (np->data[i - 1] == '/') && (np->data[i] == '*') &&
342  mutt_istrn_equal(type, np->data, i)) ||
343  mutt_istr_equal(type, np->data))
344  {
345  struct Body tmp = { 0 };
346  enum ContentType n;
347  if ((n = mutt_lookup_mime_type(&tmp, b->filename)) != TYPE_OTHER ||
348  (n = mutt_lookup_mime_type(&tmp, b->description)) != TYPE_OTHER)
349  {
350  snprintf(type, len, "%s/%s",
351  (n == TYPE_AUDIO) ? "audio" :
352  (n == TYPE_APPLICATION) ? "application" :
353  (n == TYPE_IMAGE) ? "image" :
354  (n == TYPE_MESSAGE) ? "message" :
355  (n == TYPE_MODEL) ? "model" :
356  (n == TYPE_MULTIPART) ? "multipart" :
357  (n == TYPE_TEXT) ? "text" :
358  (n == TYPE_VIDEO) ? "video" :
359  "other",
360  tmp.subtype);
361  mutt_debug(LL_DEBUG1, "\"%s\" -> %s\n", b->filename, type);
362  }
363  FREE(&tmp.subtype);
364  FREE(&tmp.xtype);
365  }
366  }
367 }
Unknown Content-Type.
Definition: mime.h:31
char * filename
when sending a message, this is the file to which this structure refers
Definition: body.h:46
Type: &#39;audio/*&#39;.
Definition: mime.h:32
The body of an email.
Definition: body.h:34
bool mutt_istrn_equal(const char *a, const char *b, size_t l)
Check for equality of two strings ignoring case (to a maximum), safely.
Definition: string.c:621
Type: &#39;video/*&#39;.
Definition: mime.h:39
bool mutt_istr_equal(const char *a, const char *b)
Compare two strings, ignoring case.
Definition: string.c:883
char * subtype
content-type subtype
Definition: body.h:37
Type: &#39;text/*&#39;.
Definition: mime.h:38
char * xtype
content-type if x-unknown
Definition: body.h:36
#define STAILQ_FOREACH(var, head, field)
Definition: queue.h:349
char * description
content-description
Definition: body.h:40
unsigned int type
content-type primary type, ContentType
Definition: body.h:65
Type: &#39;message/*&#39;.
Definition: mime.h:35
size_t mutt_str_len(const char *a)
Calculate the length of a string, safely.
Definition: string.c:631
char * data
String.
Definition: list.h:36
Type: &#39;multipart/*&#39;.
Definition: mime.h:37
Log at debug level 1.
Definition: logging.h:40
enum ContentType mutt_lookup_mime_type(struct Body *att, const char *path)
Find the MIME type for an attachment.
Definition: sendlib.c:565
Type: &#39;model/*&#39;.
Definition: mime.h:36
#define FREE(x)
Definition: memory.h:40
Type: &#39;image/*&#39;.
Definition: mime.h:34
#define mutt_debug(LEVEL,...)
Definition: logging.h:81
A List node for strings.
Definition: list.h:34
Type: &#39;application/*&#39;.
Definition: mime.h:33
ContentType
Content-Type.
Definition: mime.h:29
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ wait_interactive_filter()

static int wait_interactive_filter ( pid_t  pid)
static

Wait after an interactive filter.

Parameters
pidProcess id of the process to wait for
Return values
numExit status of the process identified by pid
-1Error

This is used for filters that are actually interactive commands with input piped in: e.g. in mutt_view_attachment(), a mailcap entry without copiousoutput and without a s.

For those cases, we treat it like a blocking system command, and poll IMAP to keep connections open.

Definition at line 382 of file mutt_attach.c.

383 {
384  int rc;
385 
386 #ifdef USE_IMAP
387  rc = imap_wait_keepalive(pid);
388 #else
389  waitpid(pid, &rc, 0);
390 #endif
392  rc = WIFEXITED(rc) ? WEXITSTATUS(rc) : -1;
393 
394  return rc;
395 }
void mutt_sig_unblock_system(bool restore)
Restore previously blocked signals.
Definition: signal.c:207
int imap_wait_keepalive(pid_t pid)
Wait for a process to change state.
Definition: util.c:1103
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mutt_view_attachment()

int mutt_view_attachment ( FILE *  fp,
struct Body a,
enum ViewAttachMode  mode,
struct Email e,
struct AttachCtx actx,
struct MuttWindow win 
)

View an attachment.

Parameters
fpSource file stream. Can be NULL
aThe message body containing the attachment
modeHow the attachment should be viewed, see ViewAttachMode
eCurrent Email. Can be NULL
actxAttachment context
winWindow
Return values
0If the viewer is run and exited successfully
-1Error
numReturn value of mutt_do_pager() when it is used

Display a message attachment using the viewer program configured in mailcap. If there is no mailcap entry for a file type, view the image as text. Viewer processes are opened and waited on synchronously so viewing an attachment this way will block the main neomutt process until the viewer process exits.

Definition at line 414 of file mutt_attach.c.

416 {
417  bool use_mailcap = false;
418  bool use_pipe = false;
419  bool use_pager = true;
420  char type[256];
421  char desc[256];
422  char *fname = NULL;
423  struct MailcapEntry *entry = NULL;
424  int rc = -1;
425  bool unlink_tempfile = false;
426  bool unlink_pagerfile = false;
427 
428  bool is_message = mutt_is_message_type(a->type, a->subtype);
429  if ((WithCrypto != 0) && is_message && a->email &&
431  {
432  return rc;
433  }
434 
435  struct Buffer *tmpfile = mutt_buffer_pool_get();
436  struct Buffer *pagerfile = mutt_buffer_pool_get();
437  struct Buffer *cmd = mutt_buffer_pool_get();
438 
439  use_mailcap = ((mode == MUTT_VA_MAILCAP) ||
440  ((mode == MUTT_VA_REGULAR) && mutt_needs_mailcap(a)) ||
441  (mode == MUTT_VA_PAGER));
442  snprintf(type, sizeof(type), "%s/%s", TYPE(a), a->subtype);
443 
444  char columns[16];
445  snprintf(columns, sizeof(columns), "%d", win->state.cols);
446  mutt_envlist_set("COLUMNS", columns, true);
447 
448  if (use_mailcap)
449  {
450  entry = mailcap_entry_new();
451  enum MailcapLookup mailcap_opt =
453  if (!mailcap_lookup(a, type, sizeof(type), entry, mailcap_opt))
454  {
455  if ((mode == MUTT_VA_REGULAR) || (mode == MUTT_VA_PAGER))
456  {
457  /* fallback to view as text */
458  mailcap_entry_free(&entry);
459  mutt_error(_("No matching mailcap entry found. Viewing as text."));
460  mode = MUTT_VA_AS_TEXT;
461  use_mailcap = false;
462  }
463  else
464  goto return_error;
465  }
466  }
467 
468  if (use_mailcap)
469  {
470  if (!entry->command)
471  {
472  mutt_error(_("MIME type not defined. Can't view attachment."));
473  goto return_error;
474  }
475  mutt_buffer_strcpy(cmd, entry->command);
476 
477  fname = mutt_str_dup(a->filename);
478  /* In send mode(!fp), we allow slashes because those are part of
479  * the tmpfile. The path will be removed in expand_filename */
480  mutt_file_sanitize_filename(fname, fp ? true : false);
481  mailcap_expand_filename(entry->nametemplate, fname, tmpfile);
482  FREE(&fname);
483 
484  if (mutt_save_attachment(fp, a, mutt_buffer_string(tmpfile), 0, NULL) == -1)
485  goto return_error;
486  unlink_tempfile = true;
487 
489 
490  use_pipe = mailcap_expand_command(a, mutt_buffer_string(tmpfile), type, cmd);
491  use_pager = entry->copiousoutput;
492  }
493 
494  if (use_pager)
495  {
496  if (fp && !use_mailcap && a->filename)
497  {
498  /* recv case */
499  mutt_buffer_strcpy(pagerfile, a->filename);
500  mutt_adv_mktemp(pagerfile);
501  }
502  else
503  mutt_buffer_mktemp(pagerfile);
504  }
505 
506  if (use_mailcap)
507  {
508  pid_t pid = 0;
509  int fd_temp = -1, fd_pager = -1;
510 
511  if (!use_pager)
512  mutt_endwin();
513 
514  if (use_pager || use_pipe)
515  {
516  if (use_pager && ((fd_pager = mutt_file_open(mutt_buffer_string(pagerfile),
517  O_CREAT | O_EXCL | O_WRONLY)) == -1))
518  {
519  mutt_perror("open");
520  goto return_error;
521  }
522  unlink_pagerfile = true;
523 
524  if (use_pipe && ((fd_temp = open(mutt_buffer_string(tmpfile), 0)) == -1))
525  {
526  if (fd_pager != -1)
527  close(fd_pager);
528  mutt_perror("open");
529  goto return_error;
530  }
531  unlink_pagerfile = true;
532 
533  pid = filter_create_fd(mutt_buffer_string(cmd), NULL, NULL, NULL,
534  use_pipe ? fd_temp : -1, use_pager ? fd_pager : -1, -1);
535 
536  if (pid == -1)
537  {
538  if (fd_pager != -1)
539  close(fd_pager);
540 
541  if (fd_temp != -1)
542  close(fd_temp);
543 
544  mutt_error(_("Can't create filter"));
545  goto return_error;
546  }
547 
548  if (use_pager)
549  {
550  if (a->description)
551  {
552  snprintf(desc, sizeof(desc), _("---Command: %-20.20s Description: %s"),
554  }
555  else
556  {
557  snprintf(desc, sizeof(desc), _("---Command: %-30.30s Attachment: %s"),
558  mutt_buffer_string(cmd), type);
559  }
560  filter_wait(pid);
561  }
562  else
563  {
564  if (wait_interactive_filter(pid) || (entry->needsterminal && C_WaitKey))
566  }
567 
568  if (fd_temp != -1)
569  close(fd_temp);
570  if (fd_pager != -1)
571  close(fd_pager);
572  }
573  else
574  {
575  /* interactive cmd */
576  int rv = mutt_system(mutt_buffer_string(cmd));
577  if (rv == -1)
578  mutt_debug(LL_DEBUG1, "Error running \"%s\"", cmd->data);
579 
580  if ((rv != 0) || (entry->needsterminal && C_WaitKey))
582  }
583  }
584  else
585  {
586  /* Don't use mailcap; the attachment is viewed in the pager */
587 
588  if (mode == MUTT_VA_AS_TEXT)
589  {
590  /* just let me see the raw data */
591  if (fp)
592  {
593  /* Viewing from a received message.
594  *
595  * Don't use mutt_save_attachment() because we want to perform charset
596  * conversion since this will be displayed by the internal pager. */
597  struct State decode_state = { 0 };
598 
599  decode_state.fp_out = mutt_file_fopen(mutt_buffer_string(pagerfile), "w");
600  if (!decode_state.fp_out)
601  {
602  mutt_debug(LL_DEBUG1, "mutt_file_fopen(%s) errno=%d %s\n",
603  mutt_buffer_string(pagerfile), errno, strerror(errno));
604  mutt_perror(mutt_buffer_string(pagerfile));
605  goto return_error;
606  }
607  decode_state.fp_in = fp;
608  decode_state.flags = MUTT_CHARCONV;
609  mutt_decode_attachment(a, &decode_state);
610  if (mutt_file_fclose(&decode_state.fp_out) == EOF)
611  {
612  mutt_debug(LL_DEBUG1, "fclose(%s) errno=%d %s\n",
613  mutt_buffer_string(pagerfile), errno, strerror(errno));
614  }
615  }
616  else
617  {
618  /* in compose mode, just copy the file. we can't use
619  * mutt_decode_attachment() since it assumes the content-encoding has
620  * already been applied */
621  if (mutt_save_attachment(fp, a, mutt_buffer_string(pagerfile), MUTT_SAVE_NO_FLAGS, NULL))
622  goto return_error;
623  unlink_pagerfile = true;
624  }
626  }
627  else
628  {
629  /* Use built-in handler */
630  OptViewAttach = true; /* disable the "use 'v' to view this part"
631  * message in case of error */
632  if (mutt_decode_save_attachment(fp, a, mutt_buffer_string(pagerfile),
634  {
635  OptViewAttach = false;
636  goto return_error;
637  }
638  unlink_pagerfile = true;
639  OptViewAttach = false;
640  }
641 
642  if (a->description)
643  mutt_str_copy(desc, a->description, sizeof(desc));
644  else if (a->filename)
645  snprintf(desc, sizeof(desc), _("---Attachment: %s: %s"), a->filename, type);
646  else
647  snprintf(desc, sizeof(desc), _("---Attachment: %s"), type);
648  }
649 
650  /* We only reach this point if there have been no errors */
651 
652  if (use_pager)
653  {
654  struct Pager info = { 0 };
655  info.fp = fp;
656  info.body = a;
657  info.ctx = Context;
658  info.actx = actx;
659  info.email = e;
660 
661  rc = mutt_do_pager(desc, mutt_buffer_string(pagerfile),
663  &info);
664  mutt_buffer_reset(pagerfile);
665  unlink_pagerfile = false;
666  }
667  else
668  rc = 0;
669 
670 return_error:
671 
672  if (!entry || !entry->xneomuttkeep)
673  {
674  if (fp && !mutt_buffer_is_empty(tmpfile))
675  {
676  /* add temporary file to TempAttachmentsList to be deleted on timeout hook */
678  }
679  else if (unlink_tempfile)
680  {
681  unlink(mutt_buffer_string(tmpfile));
682  }
683  }
684 
685  mailcap_entry_free(&entry);
686 
687  if (unlink_pagerfile)
689 
690  mutt_buffer_pool_release(&tmpfile);
691  mutt_buffer_pool_release(&pagerfile);
693  mutt_envlist_unset("COLUMNS");
694 
695  return rc;
696 }
bool xneomuttkeep
do not remove the file on command exit
Definition: mailcap.h:50
A mailcap entry.
Definition: mailcap.h:38
void mutt_decode_attachment(struct Body *b, struct State *s)
Decode an email&#39;s attachment.
Definition: handler.c:1845
FILE * fp
Source stream.
Definition: pager.h:70
struct MailcapEntry * mailcap_entry_new(void)
Allocate memory for a new rfc1524 entry.
Definition: mailcap.c:427
#define mutt_buffer_mktemp(buf)
Definition: muttlib.h:77
#define MUTT_DISPLAY
Output is displayed to the user.
Definition: state.h:32
char * filename
when sending a message, this is the file to which this structure refers
Definition: body.h:46
void mutt_buffer_reset(struct Buffer *buf)
Reset an existing Buffer.
Definition: buffer.c:79
#define WithCrypto
Definition: lib.h:123
bool mutt_is_message_type(int type, const char *subtype)
Determine if a mime type matches a message or not.
Definition: parse.c:1366
struct Buffer * mutt_buffer_pool_get(void)
Get a Buffer from the pool.
Definition: pool.c:101
#define mutt_perror(...)
Definition: logging.h:85
#define MUTT_CHARCONV
Do character set conversions.
Definition: state.h:36
Mailcap autoview field.
Definition: mailcap.h:62
#define MUTT_PAGER_MESSAGE
Definition: pager.h:58
#define SEC_ENCRYPT
Email is encrypted.
Definition: lib.h:85
No flags set.
Definition: mutt_attach.h:56
void mutt_buffer_pool_release(struct Buffer **pbuf)
Free a Buffer from the pool.
Definition: pool.c:112
void mutt_file_unlink(const char *s)
Delete a file, carefully.
Definition: file.c:195
String manipulation buffer.
Definition: buffer.h:33
char * mutt_str_dup(const char *str)
Copy a string, safely.
Definition: string.c:370
#define _(a)
Definition: message.h:28
FILE * fp_out
File to write to.
Definition: state.h:47
struct Body * body
Current attachment.
Definition: pager.h:69
Force viewing as text.
Definition: mutt_attach.h:44
No flags set.
Definition: mailcap.h:58
WHERE struct Context * Context
Definition: mutt_globals.h:42
int mutt_save_attachment(FILE *fp, struct Body *m, const char *path, enum SaveAttach opt, struct Email *e)
Save an attachment.
Definition: mutt_attach.c:873
An email being displayed.
Definition: pager.h:65
View using default method.
Definition: mutt_attach.h:42
FILE * fp_in
File to read from.
Definition: state.h:46
#define MUTT_PAGER_ATTACHMENT
Attachments may exist.
Definition: pager.h:55
bool mailcap_lookup(struct Body *a, char *type, size_t typelen, struct MailcapEntry *entry, enum MailcapLookup opt)
Find given type in the list of mailcap files.
Definition: mailcap.c:465
int mailcap_expand_command(struct Body *a, const char *filename, const char *type, struct Buffer *command)
Expand expandos in a command.
Definition: mailcap.c:69
void mailcap_expand_filename(const char *nametemplate, const char *oldfile, struct Buffer *newfile)
Expand a new filename from a template or existing filename.
Definition: mailcap.c:533
static const char * mutt_buffer_string(const struct Buffer *buf)
Convert a buffer to a const char * "string".
Definition: buffer.h:77
StateFlags flags
Flags, e.g. MUTT_DISPLAY.
Definition: state.h:49
bool crypt_valid_passphrase(SecurityFlags flags)
Check that we have a usable passphrase, ask if not.
Definition: crypt.c:134
bool copiousoutput
needs pager, basically
Definition: mailcap.h:49
int mutt_file_fclose(FILE **fp)
Close a FILE handle (and NULL the pointer)
Definition: file.c:153
static int wait_interactive_filter(pid_t pid)
Wait after an interactive filter.
Definition: mutt_attach.c:382
void mutt_add_temp_attachment(const char *filename)
Add file to list of temporary attachments.
Definition: mutt_attach.c:1258
int mutt_file_open(const char *path, uint32_t flags)
Open a file.
Definition: file.c:522
char * command
Definition: mailcap.h:40
char * subtype
content-type subtype
Definition: body.h:37
void mutt_file_sanitize_filename(char *path, bool slash)
Replace unsafe characters in a filename.
Definition: file.c:618
short cols
Number of columns, can be MUTT_WIN_SIZE_UNLIMITED.
Definition: mutt_window.h:57
struct Context * ctx
Current mailbox.
Definition: pager.h:67
struct WindowState state
Current state of the Window.
Definition: mutt_window.h:120
void mutt_endwin(void)
Shutdown curses/slang.
Definition: curs_lib.c:571
bool mutt_envlist_unset(const char *name)
Unset an environment variable.
Definition: envlist.c:132
void mailcap_entry_free(struct MailcapEntry **ptr)
Deallocate an struct MailcapEntry.
Definition: mailcap.c:436
int mutt_decode_save_attachment(FILE *fp, struct Body *m, const char *path, int displaying, enum SaveAttach opt)
Decode, then save an attachment.
Definition: mutt_attach.c:1004
struct AttachCtx * actx
Attachment information.
Definition: pager.h:71
char * data
Pointer to data.
Definition: buffer.h:35
void mutt_rfc3676_space_unstuff_attachment(struct Body *b, const char *filename)
Unstuff attachments.
Definition: rfc3676.c:511
char * description
content-description
Definition: body.h:40
SecurityFlags security
bit 0-10: flags, bit 11,12: application, bit 13: traditional pgp See: ncrypt/lib.h pgplib...
Definition: email.h:39
View attachment in pager using copiousoutput mailcap.
Definition: mutt_attach.h:45
Force viewing using mailcap entry.
Definition: mutt_attach.h:43
size_t mutt_buffer_strcpy(struct Buffer *buf, const char *s)
Copy a string into a Buffer.
Definition: buffer.c:312
unsigned int type
content-type primary type, ContentType
Definition: body.h:65
int mutt_any_key_to_continue(const char *s)
Prompt the user to &#39;press any key&#39; and wait.
Definition: curs_lib.c:604
char * nametemplate
Definition: mailcap.h:46
#define TYPE(body)
Definition: mime.h:89
struct Email * email
Current message.
Definition: pager.h:68
Log at debug level 1.
Definition: logging.h:40
size_t mutt_str_copy(char *dest, const char *src, size_t dsize)
Copy a string into a buffer (guaranteeing NUL-termination)
Definition: string.c:716
int mutt_do_pager(const char *banner, const char *tempfile, PagerFlags do_color, struct Pager *info)
Display some page-able text to the user.
Definition: curs_lib.c:690
pid_t filter_create_fd(const char *cmd, FILE **fp_in, FILE **fp_out, FILE **fp_err, int fdin, int fdout, int fderr)
Run a command on a pipe (optionally connect stdin/stdout)
Definition: filter.c:61
#define mutt_error(...)
Definition: logging.h:84
bool mutt_needs_mailcap(struct Body *m)
Does this type need a mailcap entry do display.
Definition: muttlib.c:405
MailcapLookup
Mailcap actions.
Definition: mailcap.h:56
void mutt_adv_mktemp(struct Buffer *buf)
Create a temporary file.
Definition: muttlib.c:90
#define FREE(x)
Definition: memory.h:40
Keep track when processing files.
Definition: state.h:44
WHERE bool OptViewAttach
(pseudo) signals that we are viewing attachments
Definition: options.h:55
bool mutt_envlist_set(const char *name, const char *value, bool overwrite)
Set an environment variable.
Definition: envlist.c:85
#define mutt_debug(LEVEL,...)
Definition: logging.h:81
FILE * mutt_file_fopen(const char *path, const char *mode)
Call fopen() safely.
Definition: file.c:589
int filter_wait(pid_t pid)
Wait for the exit of a process and return its status.
Definition: filter.c:217
bool mutt_buffer_is_empty(const struct Buffer *buf)
Is the Buffer empty?
Definition: buffer.c:252
struct Email * email
header information for message/rfc822
Definition: body.h:55
bool needsterminal
endwin() and system
Definition: mailcap.h:48
int mutt_system(const char *cmd)
Run an external command.
Definition: system.c:51
#define MUTT_PAGER_NO_FLAGS
No flags are set.
Definition: pager.h:43
WHERE bool C_WaitKey
Config: Prompt to press a key after running external commands.
Definition: mutt_globals.h:169
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mutt_pipe_attachment()

int mutt_pipe_attachment ( FILE *  fp,
struct Body b,
const char *  path,
char *  outfile 
)

Pipe an attachment to a command.

Parameters
fpFile to pipe into the command
bAttachment
pathPath to command
outfileFile to save output to
Return values
1Success
0Error

Definition at line 707 of file mutt_attach.c.

708 {
709  pid_t pid = 0;
710  int out = -1, rc = 0;
711  bool is_flowed = false;
712  bool unlink_unstuff = false;
713  FILE *fp_filter = NULL, *fp_unstuff = NULL, *fp_in = NULL;
714  struct Buffer *unstuff_tempfile = NULL;
715 
716  if (outfile && *outfile)
717  {
718  out = mutt_file_open(outfile, O_CREAT | O_EXCL | O_WRONLY);
719  if (out < 0)
720  {
721  mutt_perror("open");
722  return 0;
723  }
724  }
725 
727  {
728  is_flowed = true;
729  unstuff_tempfile = mutt_buffer_pool_get();
730  mutt_buffer_mktemp(unstuff_tempfile);
731  }
732 
733  mutt_endwin();
734 
735  if (outfile && *outfile)
736  pid = filter_create_fd(path, &fp_filter, NULL, NULL, -1, out, -1);
737  else
738  pid = filter_create(path, &fp_filter, NULL, NULL);
739  if (pid < 0)
740  {
741  mutt_perror(_("Can't create filter"));
742  goto bail;
743  }
744 
745  /* recv case */
746  if (fp)
747  {
748  struct State s = { 0 };
749 
750  /* perform charset conversion on text attachments when piping */
751  s.flags = MUTT_CHARCONV;
752 
753  if (is_flowed)
754  {
755  fp_unstuff = mutt_file_fopen(mutt_buffer_string(unstuff_tempfile), "w");
756  if (fp_unstuff == NULL)
757  {
758  mutt_perror("mutt_file_fopen");
759  goto bail;
760  }
761  unlink_unstuff = true;
762 
763  s.fp_in = fp;
764  s.fp_out = fp_unstuff;
765  mutt_decode_attachment(b, &s);
766  mutt_file_fclose(&fp_unstuff);
767 
769 
770  fp_unstuff = mutt_file_fopen(mutt_buffer_string(unstuff_tempfile), "r");
771  if (fp_unstuff == NULL)
772  {
773  mutt_perror("mutt_file_fopen");
774  goto bail;
775  }
776  mutt_file_copy_stream(fp_unstuff, fp_filter);
777  mutt_file_fclose(&fp_unstuff);
778  }
779  else
780  {
781  s.fp_in = fp;
782  s.fp_out = fp_filter;
783  mutt_decode_attachment(b, &s);
784  }
785  }
786 
787  /* send case */
788  else
789  {
790  const char *infile = NULL;
791 
792  if (is_flowed)
793  {
794  if (mutt_save_attachment(fp, b, mutt_buffer_string(unstuff_tempfile),
795  MUTT_SAVE_NO_FLAGS, NULL) == -1)
796  {
797  goto bail;
798  }
799  unlink_unstuff = true;
801  infile = mutt_buffer_string(unstuff_tempfile);
802  }
803  else
804  infile = b->filename;
805 
806  fp_in = fopen(infile, "r");
807  if (!fp_in)
808  {
809  mutt_perror("fopen");
810  goto bail;
811  }
812 
813  mutt_file_copy_stream(fp_in, fp_filter);
814  mutt_file_fclose(&fp_in);
815  }
816 
817  mutt_file_fclose(&fp_filter);
818  rc = 1;
819 
820 bail:
821  if (outfile && *outfile)
822  {
823  close(out);
824  if (rc == 0)
825  unlink(outfile);
826  else if (is_flowed)
828  }
829 
830  mutt_file_fclose(&fp_unstuff);
831  mutt_file_fclose(&fp_filter);
832  mutt_file_fclose(&fp_in);
833 
834  if (unlink_unstuff)
835  mutt_file_unlink(mutt_buffer_string(unstuff_tempfile));
836  mutt_buffer_pool_release(&unstuff_tempfile);
837 
838  /* check for error exit from child process */
839  if ((pid > 0) && (filter_wait(pid) != 0))
840  rc = 0;
841 
842  if ((rc == 0) || C_WaitKey)
844  return rc;
845 }
void mutt_decode_attachment(struct Body *b, struct State *s)
Decode an email&#39;s attachment.
Definition: handler.c:1845
#define mutt_buffer_mktemp(buf)
Definition: muttlib.h:77
char * filename
when sending a message, this is the file to which this structure refers
Definition: body.h:46
pid_t filter_create(const char *cmd, FILE **fp_in, FILE **fp_out, FILE **fp_err)
Set up filter program.
Definition: filter.c:206
struct Buffer * mutt_buffer_pool_get(void)
Get a Buffer from the pool.
Definition: pool.c:101
#define mutt_perror(...)
Definition: logging.h:85
bool mutt_rfc3676_is_format_flowed(struct Body *b)
Is the Email "format-flowed"?
Definition: rfc3676.c:387
#define MUTT_CHARCONV
Do character set conversions.
Definition: state.h:36
No flags set.
Definition: mutt_attach.h:56
void mutt_buffer_pool_release(struct Buffer **pbuf)
Free a Buffer from the pool.
Definition: pool.c:112
void mutt_file_unlink(const char *s)
Delete a file, carefully.
Definition: file.c:195
String manipulation buffer.
Definition: buffer.h:33
#define _(a)
Definition: message.h:28
FILE * fp_out
File to write to.
Definition: state.h:47
int mutt_save_attachment(FILE *fp, struct Body *m, const char *path, enum SaveAttach opt, struct Email *e)
Save an attachment.
Definition: mutt_attach.c:873
FILE * fp_in
File to read from.
Definition: state.h:46
static const char * mutt_buffer_string(const struct Buffer *buf)
Convert a buffer to a const char * "string".
Definition: buffer.h:77
StateFlags flags
Flags, e.g. MUTT_DISPLAY.
Definition: state.h:49
int mutt_file_fclose(FILE **fp)
Close a FILE handle (and NULL the pointer)
Definition: file.c:153
int mutt_file_open(const char *path, uint32_t flags)
Open a file.
Definition: file.c:522
void mutt_endwin(void)
Shutdown curses/slang.
Definition: curs_lib.c:571
void mutt_rfc3676_space_unstuff_attachment(struct Body *b, const char *filename)
Unstuff attachments.
Definition: rfc3676.c:511
int mutt_any_key_to_continue(const char *s)
Prompt the user to &#39;press any key&#39; and wait.
Definition: curs_lib.c:604
int mutt_file_copy_stream(FILE *fp_in, FILE *fp_out)
Copy the contents of one file into another.
Definition: file.c:271
pid_t filter_create_fd(const char *cmd, FILE **fp_in, FILE **fp_out, FILE **fp_err, int fdin, int fdout, int fderr)
Run a command on a pipe (optionally connect stdin/stdout)
Definition: filter.c:61
Keep track when processing files.
Definition: state.h:44
FILE * mutt_file_fopen(const char *path, const char *mode)
Call fopen() safely.
Definition: file.c:589
int filter_wait(pid_t pid)
Wait for the exit of a process and return its status.
Definition: filter.c:217
WHERE bool C_WaitKey
Config: Prompt to press a key after running external commands.
Definition: mutt_globals.h:169
void mutt_rfc3676_space_stuff_attachment(struct Body *b, const char *filename)
Stuff attachments.
Definition: rfc3676.c:532
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ save_attachment_open()

static FILE* save_attachment_open ( const char *  path,
enum SaveAttach  opt 
)
static

Open a file to write an attachment to.

Parameters
pathPath to file to open
optSave option, see SaveAttach
Return values
ptrFile handle to attachment file

Definition at line 853 of file mutt_attach.c.

854 {
855  if (opt == MUTT_SAVE_APPEND)
856  return fopen(path, "a");
857  if (opt == MUTT_SAVE_OVERWRITE)
858  return fopen(path, "w");
859 
860  return mutt_file_fopen(path, "w");
861 }
Overwrite existing file.
Definition: mutt_attach.h:58
Append to existing file.
Definition: mutt_attach.h:57
FILE * mutt_file_fopen(const char *path, const char *mode)
Call fopen() safely.
Definition: file.c:589
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mutt_save_attachment()

int mutt_save_attachment ( FILE *  fp,
struct Body m,
const char *  path,
enum SaveAttach  opt,
struct Email e 
)

Save an attachment.

Parameters
fpSource file stream. Can be NULL
mEmail Body
pathWhere to save the attachment
optSave option, see SaveAttach
eCurrent Email. Can be NULL
Return values
0Success
-1Error

Definition at line 873 of file mutt_attach.c.

875 {
876  if (!m)
877  return -1;
878 
879  if (fp)
880  {
881  /* recv mode */
882 
883  if (e && m->email && (m->encoding != ENC_BASE64) &&
885  {
886  /* message type attachments are written to mail folders. */
887 
888  char buf[8192];
889  struct Message *msg = NULL;
890  CopyHeaderFlags chflags = CH_NO_FLAGS;
891  int rc = -1;
892 
893  struct Email *e_new = m->email;
894  e_new->msgno = e->msgno; /* required for MH/maildir */
895  e_new->read = true;
896 
897  if (fseeko(fp, m->offset, SEEK_SET) < 0)
898  return -1;
899  if (!fgets(buf, sizeof(buf), fp))
900  return -1;
901  struct Mailbox *m_att = mx_path_resolve(path);
902  struct Context *ctx = mx_mbox_open(m_att, MUTT_APPEND | MUTT_QUIET);
903  if (!ctx)
904  {
905  mailbox_free(&m_att);
906  return -1;
907  }
908  msg = mx_msg_open_new(ctx->mailbox, e_new,
909  is_from(buf, NULL, 0, NULL) ? MUTT_MSG_NO_FLAGS : MUTT_ADD_FROM);
910  if (!msg)
911  {
912  mx_mbox_close(&ctx);
913  return -1;
914  }
915  if ((ctx->mailbox->type == MUTT_MBOX) || (ctx->mailbox->type == MUTT_MMDF))
916  chflags = CH_FROM | CH_UPDATE_LEN;
917  chflags |= ((ctx->mailbox->type == MUTT_MAILDIR) ? CH_NOSTATUS : CH_UPDATE);
918  if ((mutt_copy_message_fp(msg->fp, fp, e_new, MUTT_CM_NO_FLAGS, chflags, 0) == 0) &&
919  (mx_msg_commit(ctx->mailbox, msg) == 0))
920  {
921  rc = 0;
922  }
923  else
924  {
925  rc = -1;
926  }
927 
928  mx_msg_close(ctx->mailbox, &msg);
929  mx_mbox_close(&ctx);
930  return rc;
931  }
932  else
933  {
934  /* In recv mode, extract from folder and decode */
935 
936  struct State s = { 0 };
937 
938  s.fp_out = save_attachment_open(path, opt);
939  if (!s.fp_out)
940  {
941  mutt_perror("fopen");
942  return -1;
943  }
944  fseeko((s.fp_in = fp), m->offset, SEEK_SET);
945  mutt_decode_attachment(m, &s);
946 
947  if (mutt_file_fsync_close(&s.fp_out) != 0)
948  {
949  mutt_perror("fclose");
950  return -1;
951  }
952  }
953  }
954  else
955  {
956  if (!m->filename)
957  return -1;
958 
959  /* In send mode, just copy file */
960 
961  FILE *fp_old = fopen(m->filename, "r");
962  if (!fp_old)
963  {
964  mutt_perror("fopen");
965  return -1;
966  }
967 
968  FILE *fp_new = save_attachment_open(path, opt);
969  if (!fp_new)
970  {
971  mutt_perror("fopen");
972  mutt_file_fclose(&fp_old);
973  return -1;
974  }
975 
976  if (mutt_file_copy_stream(fp_old, fp_new) == -1)
977  {
978  mutt_error(_("Write fault"));
979  mutt_file_fclose(&fp_old);
980  mutt_file_fclose(&fp_new);
981  return -1;
982  }
983  mutt_file_fclose(&fp_old);
984  if (mutt_file_fsync_close(&fp_new) != 0)
985  {
986  mutt_error(_("Write fault"));
987  return -1;
988  }
989  }
990 
991  return 0;
992 }
#define MUTT_APPEND
Open mailbox for appending messages.
Definition: mx.h:53
#define MUTT_MSG_NO_FLAGS
No flags are set.
Definition: mx.h:64
The "current" mailbox.
Definition: context.h:38
void mutt_decode_attachment(struct Body *b, struct State *s)
Decode an email&#39;s attachment.
Definition: handler.c:1845
char * filename
when sending a message, this is the file to which this structure refers
Definition: body.h:46
enum MailboxType type
Mailbox type.
Definition: mailbox.h:105
bool mutt_is_message_type(int type, const char *subtype)
Determine if a mime type matches a message or not.
Definition: parse.c:1366
The envelope/body of an email.
Definition: email.h:37
#define mutt_perror(...)
Definition: logging.h:85
int mx_mbox_close(struct Context **ptr)
Save changes and close mailbox.
Definition: mx.c:630
int mutt_file_fsync_close(FILE **fp)
Flush the data, before closing a file (and NULL the pointer)
Definition: file.c:169
LOFF_T offset
offset where the actual data begins
Definition: body.h:44
#define CH_FROM
Retain the "From " message separator?
Definition: copy.h:55
#define _(a)
Definition: message.h:28
#define CH_NOSTATUS
Suppress the status and x-status fields.
Definition: copy.h:57
struct Context * mx_mbox_open(struct Mailbox *m, OpenMailboxFlags flags)
Open a mailbox and parse it.
Definition: mx.c:303
FILE * fp_out
File to write to.
Definition: state.h:47
#define CH_UPDATE
Update the status and x-status fields?
Definition: copy.h:51
#define MUTT_CM_NO_FLAGS
No flags are set.
Definition: copy.h:34
FILE * fp_in
File to read from.
Definition: state.h:46
int mx_msg_close(struct Mailbox *m, struct Message **msg)
Close a message.
Definition: mx.c:1205
bool read
Email is read.
Definition: email.h:51
struct Message * mx_msg_open_new(struct Mailbox *m, const struct Email *e, MsgOpenFlags flags)
Open a new message.
Definition: mx.c:1073
struct Mailbox * mailbox
Definition: context.h:50
void mailbox_free(struct Mailbox **ptr)
Free a Mailbox.
Definition: mailbox.c:70
int mutt_file_fclose(FILE **fp)
Close a FILE handle (and NULL the pointer)
Definition: file.c:153
unsigned int encoding
content-transfer-encoding, ContentEncoding
Definition: body.h:66
Base-64 encoded text.
Definition: mime.h:52
&#39;Maildir&#39; Mailbox type
Definition: mailbox.h:51
char * subtype
content-type subtype
Definition: body.h:37
A local copy of an email.
Definition: mx.h:82
A mailbox.
Definition: mailbox.h:81
#define CH_NO_FLAGS
No flags are set.
Definition: copy.h:50
&#39;mmdf&#39; Mailbox type
Definition: mailbox.h:49
#define CH_UPDATE_LEN
Update Lines: and Content-Length:
Definition: copy.h:61
#define MUTT_QUIET
Do not print any messages.
Definition: mx.h:55
unsigned int type
content-type primary type, ContentType
Definition: body.h:65
&#39;mbox&#39; Mailbox type
Definition: mailbox.h:48
int mutt_file_copy_stream(FILE *fp_in, FILE *fp_out)
Copy the contents of one file into another.
Definition: file.c:271
uint32_t CopyHeaderFlags
Flags for mutt_copy_header(), e.g. CH_UPDATE.
Definition: copy.h:49
#define mutt_error(...)
Definition: logging.h:84
int mx_msg_commit(struct Mailbox *m, struct Message *msg)
Commit a message to a folder - Wrapper for MxOps::msg_commit()
Definition: mx.c:1184
Quoted-printable text.
Definition: mime.h:51
FILE * fp
pointer to the message data
Definition: mx.h:84
struct Mailbox * mx_path_resolve(const char *path)
Get a Mailbox for a path.
Definition: mx.c:1682
Keep track when processing files.
Definition: state.h:44
static FILE * save_attachment_open(const char *path, enum SaveAttach opt)
Open a file to write an attachment to.
Definition: mutt_attach.c:853
bool is_from(const char *s, char *path, size_t pathlen, time_t *tp)
Is a string a &#39;From&#39; header line?
Definition: from.c:48
int mutt_copy_message_fp(FILE *fp_out, FILE *fp_in, struct Email *e, CopyMessageFlags cmflags, CopyHeaderFlags chflags, int wraplen)
make a copy of a message from a FILE pointer
Definition: copy.c:616
#define MUTT_ADD_FROM
add a From_ line
Definition: mx.h:65
struct Email * email
header information for message/rfc822
Definition: body.h:55
int msgno
Number displayed to the user.
Definition: email.h:87
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mutt_decode_save_attachment()

int mutt_decode_save_attachment ( FILE *  fp,
struct Body m,
const char *  path,
int  displaying,
enum SaveAttach  opt 
)

Decode, then save an attachment.

Parameters
fpFile to read from (OPTIONAL)
mAttachment
pathPath to save the Attachment to
displayingFlags, e.g. MUTT_DISPLAY
optSave option, see SaveAttach
Return values
0Success
-1Error

Definition at line 1004 of file mutt_attach.c.

1006 {
1007  struct State s = { 0 };
1008  unsigned int saved_encoding = 0;
1009  struct Body *saved_parts = NULL;
1010  struct Email *e_saved = NULL;
1011  int rc = 0;
1012 
1013  s.flags = displaying;
1014 
1015  if (opt == MUTT_SAVE_APPEND)
1016  s.fp_out = fopen(path, "a");
1017  else if (opt == MUTT_SAVE_OVERWRITE)
1018  s.fp_out = fopen(path, "w");
1019  else
1020  s.fp_out = mutt_file_fopen(path, "w");
1021 
1022  if (!s.fp_out)
1023  {
1024  mutt_perror("fopen");
1025  return -1;
1026  }
1027 
1028  if (!fp)
1029  {
1030  /* When called from the compose menu, the attachment isn't parsed,
1031  * so we need to do it here. */
1032  struct stat st;
1033 
1034  if (stat(m->filename, &st) == -1)
1035  {
1036  mutt_perror("stat");
1038  return -1;
1039  }
1040 
1041  s.fp_in = fopen(m->filename, "r");
1042  if (!s.fp_in)
1043  {
1044  mutt_perror("fopen");
1045  return -1;
1046  }
1047 
1048  saved_encoding = m->encoding;
1049  if (!is_multipart(m))
1050  m->encoding = ENC_8BIT;
1051 
1052  m->length = st.st_size;
1053  m->offset = 0;
1054  saved_parts = m->parts;
1055  e_saved = m->email;
1056  mutt_parse_part(s.fp_in, m);
1057 
1058  if (m->noconv || is_multipart(m))
1059  s.flags |= MUTT_CHARCONV;
1060  }
1061  else
1062  {
1063  s.fp_in = fp;
1064  s.flags |= MUTT_CHARCONV;
1065  }
1066 
1067  mutt_body_handler(m, &s);
1068 
1069  if (mutt_file_fsync_close(&s.fp_out) != 0)
1070  {
1071  mutt_perror("fclose");
1072  rc = -1;
1073  }
1074  if (!fp)
1075  {
1076  m->length = 0;
1077  m->encoding = saved_encoding;
1078  if (saved_parts)
1079  {
1080  email_free(&m->email);
1081  m->parts = saved_parts;
1082  m->email = e_saved;
1083  }
1084  mutt_file_fclose(&s.fp_in);
1085  }
1086 
1087  return rc;
1088 }
char * filename
when sending a message, this is the file to which this structure refers
Definition: body.h:46
The envelope/body of an email.
Definition: email.h:37
void email_free(struct Email **ptr)
Free an Email.
Definition: email.c:43
#define mutt_perror(...)
Definition: logging.h:85
#define MUTT_CHARCONV
Do character set conversions.
Definition: state.h:36
#define is_multipart(body)
Definition: mime.h:82
int mutt_file_fsync_close(FILE **fp)
Flush the data, before closing a file (and NULL the pointer)
Definition: file.c:169
bool noconv
Don&#39;t do character set conversion.
Definition: body.h:73
Overwrite existing file.
Definition: mutt_attach.h:58
LOFF_T offset
offset where the actual data begins
Definition: body.h:44
8-bit text
Definition: mime.h:50
FILE * fp_out
File to write to.
Definition: state.h:47
FILE * fp_in
File to read from.
Definition: state.h:46
The body of an email.
Definition: body.h:34
StateFlags flags
Flags, e.g. MUTT_DISPLAY.
Definition: state.h:49
int mutt_file_fclose(FILE **fp)
Close a FILE handle (and NULL the pointer)
Definition: file.c:153
unsigned int encoding
content-transfer-encoding, ContentEncoding
Definition: body.h:66
LOFF_T length
length (in bytes) of attachment
Definition: body.h:45
struct Body * parts
parts of a multipart or message/rfc822
Definition: body.h:54
void mutt_parse_part(FILE *fp, struct Body *b)
Parse a MIME part.
Definition: parse.c:1657
char * path
Path of Email (for local Mailboxes)
Definition: email.h:92
Append to existing file.
Definition: mutt_attach.h:57
Keep track when processing files.
Definition: state.h:44
int mutt_body_handler(struct Body *b, struct State *s)
Handler for the Body of an email.
Definition: handler.c:1595
FILE * mutt_file_fopen(const char *path, const char *mode)
Call fopen() safely.
Definition: file.c:589
struct Email * email
header information for message/rfc822
Definition: body.h:55
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mutt_print_attachment()

int mutt_print_attachment ( FILE *  fp,
struct Body a 
)

Print out an attachment.

Parameters
fpFile to write to
aAttachment
Return values
1Success
0Error

Ok, the difference between send and receive: recv: Body->filename is a suggested name, and Mailbox|Email points to the attachment in mailbox which is encoded send: Body->filename points to the un-encoded file which contains the attachment

Definition at line 1103 of file mutt_attach.c.

1104 {
1105  char type[256];
1106  pid_t pid;
1107  FILE *fp_in = NULL, *fp_out = NULL;
1108  bool unlink_newfile = false;
1109  struct Buffer *newfile = mutt_buffer_pool_get();
1110  struct Buffer *cmd = mutt_buffer_pool_get();
1111 
1112  int rc = 0;
1113 
1114  snprintf(type, sizeof(type), "%s/%s", TYPE(a), a->subtype);
1115 
1116  if (mailcap_lookup(a, type, sizeof(type), NULL, MUTT_MC_PRINT))
1117  {
1118  int piped = false;
1119 
1120  mutt_debug(LL_DEBUG2, "Using mailcap\n");
1121 
1122  struct MailcapEntry *entry = mailcap_entry_new();
1123  mailcap_lookup(a, type, sizeof(type), entry, MUTT_MC_PRINT);
1124  mailcap_expand_filename(entry->nametemplate, a->filename, newfile);
1125 
1126  if (mutt_save_attachment(fp, a, mutt_buffer_string(newfile),
1127  MUTT_SAVE_NO_FLAGS, NULL) == -1)
1128  {
1129  goto mailcap_cleanup;
1130  }
1131  unlink_newfile = 1;
1132 
1134 
1135  mutt_buffer_strcpy(cmd, entry->printcommand);
1136  piped = mailcap_expand_command(a, mutt_buffer_string(newfile), type, cmd);
1137 
1138  mutt_endwin();
1139 
1140  /* interactive program */
1141  if (piped)
1142  {
1143  fp_in = fopen(mutt_buffer_string(newfile), "r");
1144  if (!fp_in)
1145  {
1146  mutt_perror("fopen");
1147  mailcap_entry_free(&entry);
1148  goto mailcap_cleanup;
1149  }
1150 
1151  pid = filter_create(mutt_buffer_string(cmd), &fp_out, NULL, NULL);
1152  if (pid < 0)
1153  {
1154  mutt_perror(_("Can't create filter"));
1155  mailcap_entry_free(&entry);
1156  mutt_file_fclose(&fp_in);
1157  goto mailcap_cleanup;
1158  }
1159  mutt_file_copy_stream(fp_in, fp_out);
1160  mutt_file_fclose(&fp_out);
1161  mutt_file_fclose(&fp_in);
1162  if (filter_wait(pid) || C_WaitKey)
1164  }
1165  else
1166  {
1167  int rc2 = mutt_system(mutt_buffer_string(cmd));
1168  if (rc2 == -1)
1169  mutt_debug(LL_DEBUG1, "Error running \"%s\"", cmd->data);
1170 
1171  if ((rc2 != 0) || C_WaitKey)
1173  }
1174 
1175  rc = 1;
1176 
1177  mailcap_cleanup:
1178  if (unlink_newfile)
1180 
1181  mailcap_entry_free(&entry);
1182  goto out;
1183  }
1184 
1185  if (mutt_istr_equal("text/plain", type) ||
1186  mutt_istr_equal("application/postscript", type))
1187  {
1188  rc = (mutt_pipe_attachment(fp, a, NONULL(C_PrintCommand), NULL));
1189  goto out;
1190  }
1191  else if (mutt_can_decode(a))
1192  {
1193  /* decode and print */
1194 
1195  fp_in = NULL;
1196  fp_out = NULL;
1197 
1198  mutt_buffer_mktemp(newfile);
1199  if (mutt_decode_save_attachment(fp, a, mutt_buffer_string(newfile),
1201  {
1202  unlink_newfile = true;
1203  mutt_debug(LL_DEBUG2, "successfully decoded %s type attachment to %s\n",
1204  type, mutt_buffer_string(newfile));
1205 
1206  fp_in = fopen(mutt_buffer_string(newfile), "r");
1207  if (!fp_in)
1208  {
1209  mutt_perror("fopen");
1210  goto decode_cleanup;
1211  }
1212 
1213  mutt_debug(LL_DEBUG2, "successfully opened %s read-only\n",
1214  mutt_buffer_string(newfile));
1215 
1216  mutt_endwin();
1217  pid = filter_create(NONULL(C_PrintCommand), &fp_out, NULL, NULL);
1218  if (pid < 0)
1219  {
1220  mutt_perror(_("Can't create filter"));
1221  goto decode_cleanup;
1222  }
1223 
1224  mutt_debug(LL_DEBUG2, "Filter created\n");
1225 
1226  mutt_file_copy_stream(fp_in, fp_out);
1227 
1228  mutt_file_fclose(&fp_out);
1229  mutt_file_fclose(&fp_in);
1230 
1231  if ((filter_wait(pid) != 0) || C_WaitKey)
1233  rc = 1;
1234  }
1235  decode_cleanup:
1236  mutt_file_fclose(&fp_in);
1237  mutt_file_fclose(&fp_out);
1238  if (unlink_newfile)
1240  }
1241  else
1242  {
1243  mutt_error(_("I don't know how to print that"));
1244  rc = 0;
1245  }
1246 
1247 out:
1248  mutt_buffer_pool_release(&newfile);
1250 
1251  return rc;
1252 }
A mailcap entry.
Definition: mailcap.h:38
struct MailcapEntry * mailcap_entry_new(void)
Allocate memory for a new rfc1524 entry.
Definition: mailcap.c:427
#define mutt_buffer_mktemp(buf)
Definition: muttlib.h:77
char * filename
when sending a message, this is the file to which this structure refers
Definition: body.h:46
#define NONULL(x)
Definition: string2.h:37
pid_t filter_create(const char *cmd, FILE **fp_in, FILE **fp_out, FILE **fp_err)
Set up filter program.
Definition: filter.c:206
struct Buffer * mutt_buffer_pool_get(void)
Get a Buffer from the pool.
Definition: pool.c:101
#define mutt_perror(...)
Definition: logging.h:85
No flags set.
Definition: mutt_attach.h:56
void mutt_buffer_pool_release(struct Buffer **pbuf)
Free a Buffer from the pool.
Definition: pool.c:112
void mutt_file_unlink(const char *s)
Delete a file, carefully.
Definition: file.c:195
String manipulation buffer.
Definition: buffer.h:33
#define _(a)
Definition: message.h:28
#define MUTT_PRINTING
Are we printing? - MUTT_DISPLAY "light".
Definition: state.h:37
int mutt_save_attachment(FILE *fp, struct Body *m, const char *path, enum SaveAttach opt, struct Email *e)
Save an attachment.
Definition: mutt_attach.c:873
bool mailcap_lookup(struct Body *a, char *type, size_t typelen, struct MailcapEntry *entry, enum MailcapLookup opt)
Find given type in the list of mailcap files.
Definition: mailcap.c:465
int mailcap_expand_command(struct Body *a, const char *filename, const char *type, struct Buffer *command)
Expand expandos in a command.
Definition: mailcap.c:69
void mailcap_expand_filename(const char *nametemplate, const char *oldfile, struct Buffer *newfile)
Expand a new filename from a template or existing filename.
Definition: mailcap.c:533
static const char * mutt_buffer_string(const struct Buffer *buf)
Convert a buffer to a const char * "string".
Definition: buffer.h:77
Log at debug level 2.
Definition: logging.h:41
Mailcap print field.
Definition: mailcap.h:61
int mutt_file_fclose(FILE **fp)
Close a FILE handle (and NULL the pointer)
Definition: file.c:153
WHERE char * C_PrintCommand
Config: External command to print a message.
Definition: mutt_globals.h:103
bool mutt_istr_equal(const char *a, const char *b)
Compare two strings, ignoring case.
Definition: string.c:883
char * subtype
content-type subtype
Definition: body.h:37
void mutt_endwin(void)
Shutdown curses/slang.
Definition: curs_lib.c:571
void mailcap_entry_free(struct MailcapEntry **ptr)
Deallocate an struct MailcapEntry.
Definition: mailcap.c:436
int mutt_decode_save_attachment(FILE *fp, struct Body *m, const char *path, int displaying, enum SaveAttach opt)
Decode, then save an attachment.
Definition: mutt_attach.c:1004
bool mutt_can_decode(struct Body *a)
Will decoding the attachment produce any output.
Definition: handler.c:1805
char * data
Pointer to data.
Definition: buffer.h:35
void mutt_rfc3676_space_unstuff_attachment(struct Body *b, const char *filename)
Unstuff attachments.
Definition: rfc3676.c:511
size_t mutt_buffer_strcpy(struct Buffer *buf, const char *s)
Copy a string into a Buffer.
Definition: buffer.c:312
char * printcommand
Definition: mailcap.h:45
int mutt_any_key_to_continue(const char *s)
Prompt the user to &#39;press any key&#39; and wait.
Definition: curs_lib.c:604
char * nametemplate
Definition: mailcap.h:46
#define TYPE(body)
Definition: mime.h:89
Log at debug level 1.
Definition: logging.h:40
int mutt_file_copy_stream(FILE *fp_in, FILE *fp_out)
Copy the contents of one file into another.
Definition: file.c:271
#define mutt_error(...)
Definition: logging.h:84
#define mutt_debug(LEVEL,...)
Definition: logging.h:81
int filter_wait(pid_t pid)
Wait for the exit of a process and return its status.
Definition: filter.c:217
int mutt_pipe_attachment(FILE *fp, struct Body *b, const char *path, char *outfile)
Pipe an attachment to a command.
Definition: mutt_attach.c:707
int mutt_system(const char *cmd)
Run an external command.
Definition: system.c:51
WHERE bool C_WaitKey
Config: Prompt to press a key after running external commands.
Definition: mutt_globals.h:169
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mutt_add_temp_attachment()

void mutt_add_temp_attachment ( const char *  filename)

Add file to list of temporary attachments.

Parameters
filenamefilename with full path

Definition at line 1258 of file mutt_attach.c.

1259 {
1260  mutt_list_insert_tail(&TempAttachmentsList, mutt_str_dup(filename));
1261 }
char * mutt_str_dup(const char *str)
Copy a string, safely.
Definition: string.c:370
struct ListNode * mutt_list_insert_tail(struct ListHead *h, char *s)
Append a string to the end of a List.
Definition: list.c:64
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mutt_unlink_temp_attachments()

void mutt_unlink_temp_attachments ( void  )

Delete all temporary attachments.

Definition at line 1266 of file mutt_attach.c.

1267 {
1268  struct ListNode *np = NULL;
1269 
1270  STAILQ_FOREACH(np, &TempAttachmentsList, entries)
1271  {
1272  mutt_file_chmod_add(np->data, S_IWUSR);
1273  mutt_file_unlink(np->data);
1274  }
1275 
1276  mutt_list_free(&TempAttachmentsList);
1277 }
void mutt_file_unlink(const char *s)
Delete a file, carefully.
Definition: file.c:195
void mutt_list_free(struct ListHead *h)
Free a List AND its strings.
Definition: list.c:122
#define STAILQ_FOREACH(var, head, field)
Definition: queue.h:349
char * data
String.
Definition: list.h:36
int mutt_file_chmod_add(const char *path, mode_t mode)
Add permissions to a file.
Definition: file.c:1067
A List node for strings.
Definition: list.h:34
+ Here is the call graph for this function:
+ Here is the caller graph for this function: