NeoMutt  2020-08-21-74-g346364
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_b2s(tmpfile), "w")))
94  {
95  mutt_file_copy_stream(fp_in, fp_out);
96  mutt_str_replace(&a->filename, mutt_b2s(tmpfile));
97  a->unlink = true;
98 
99  if (a->stamp >= st.st_mtime)
101  }
102  else
103  mutt_perror(fp_in ? mutt_b2s(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:891
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
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
#define mutt_b2s(buf)
Definition: buffer.h:41
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:588
+ 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\t newfile: %s\n", a->filename, mutt_b2s(newfile));
141  if (mutt_file_symlink(a->filename, mutt_b2s(newfile)) == -1)
142  {
143  if (mutt_yesorno(_("Can't match 'nametemplate', continue?"), MUTT_YES) != MUTT_YES)
144  goto bailout;
145  mutt_buffer_strcpy(newfile, a->filename);
146  }
147  else
148  unlink_newfile = true;
149 
150  if (mailcap_expand_command(a, mutt_b2s(newfile), type, cmd))
151  {
152  /* For now, editing requires a file, no piping */
153  mutt_error(_("Mailcap compose entry requires %%s"));
154  }
155  else
156  {
157  int r;
158 
159  mutt_endwin();
160  r = mutt_system(mutt_b2s(cmd));
161  if (r == -1)
162  mutt_error(_("Error running \"%s\""), mutt_b2s(cmd));
163 
164  if ((r != -1) && entry->composetypecommand)
165  {
166  struct Body *b = NULL;
167 
168  FILE *fp = mutt_file_fopen(a->filename, "r");
169  if (!fp)
170  {
171  mutt_perror(_("Failure to open file to parse headers"));
172  goto bailout;
173  }
174 
175  b = mutt_read_mime_header(fp, 0);
176  if (b)
177  {
178  if (!TAILQ_EMPTY(&b->parameter))
179  {
181  a->parameter = b->parameter;
182  TAILQ_INIT(&b->parameter);
183  }
184  if (b->description)
185  {
186  FREE(&a->description);
187  a->description = b->description;
188  b->description = NULL;
189  }
190  if (b->form_name)
191  {
192  FREE(&a->form_name);
193  a->form_name = b->form_name;
194  b->form_name = NULL;
195  }
196 
197  /* Remove headers by copying out data to another file, then
198  * copying the file back */
199  fseeko(fp, b->offset, SEEK_SET);
200  mutt_body_free(&b);
201  mutt_buffer_mktemp(tmpfile);
202  FILE *fp_tmp = mutt_file_fopen(mutt_b2s(tmpfile), "w");
203  if (!fp_tmp)
204  {
205  mutt_perror(_("Failure to open file to strip headers"));
206  mutt_file_fclose(&fp);
207  goto bailout;
208  }
209  mutt_file_copy_stream(fp, fp_tmp);
210  mutt_file_fclose(&fp);
211  mutt_file_fclose(&fp_tmp);
213  if (mutt_file_rename(mutt_b2s(tmpfile), a->filename) != 0)
214  {
215  mutt_perror(_("Failure to rename file"));
216  goto bailout;
217  }
218  }
219  }
220  }
221  }
222  }
223  else
224  {
225  mutt_message(_("No mailcap compose entry for %s, creating empty file"), type);
226  rc = 1;
227  goto bailout;
228  }
229 
230  rc = 1;
231 
232 bailout:
233 
234  if (unlink_newfile)
235  unlink(mutt_b2s(newfile));
236 
238  mutt_buffer_pool_release(&newfile);
239  mutt_buffer_pool_release(&tmpfile);
240 
241  mailcap_entry_free(&entry);
242  return rc;
243 }
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
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
#define mutt_b2s(buf)
Definition: buffer.h:41
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:588
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 258 of file mutt_attach.c.

259 {
260  char type[256];
261  struct MailcapEntry *entry = mailcap_entry_new();
262  bool unlink_newfile = false;
263  int rc = 0;
264  struct Buffer *cmd = mutt_buffer_pool_get();
265  struct Buffer *newfile = mutt_buffer_pool_get();
266 
267  snprintf(type, sizeof(type), "%s/%s", TYPE(a), a->subtype);
268  if (mailcap_lookup(a, type, sizeof(type), entry, MUTT_MC_EDIT))
269  {
270  if (entry->editcommand)
271  {
272  mutt_buffer_strcpy(cmd, entry->editcommand);
273  mailcap_expand_filename(entry->nametemplate, a->filename, newfile);
274  mutt_debug(LL_DEBUG1, "oldfile: %s\t newfile: %s\n", a->filename, mutt_b2s(newfile));
275  if (mutt_file_symlink(a->filename, mutt_b2s(newfile)) == -1)
276  {
277  if (mutt_yesorno(_("Can't match 'nametemplate', continue?"), MUTT_YES) != MUTT_YES)
278  goto bailout;
279  mutt_buffer_strcpy(newfile, a->filename);
280  }
281  else
282  unlink_newfile = true;
283 
284  if (mailcap_expand_command(a, mutt_b2s(newfile), type, cmd))
285  {
286  /* For now, editing requires a file, no piping */
287  mutt_error(_("Mailcap Edit entry requires %%s"));
288  goto bailout;
289  }
290  else
291  {
292  mutt_endwin();
293  if (mutt_system(mutt_b2s(cmd)) == -1)
294  {
295  mutt_error(_("Error running \"%s\""), mutt_b2s(cmd));
296  goto bailout;
297  }
298  }
299  }
300  }
301  else if (a->type == TYPE_TEXT)
302  {
303  /* On text, default to editor */
305  }
306  else
307  {
308  mutt_error(_("No mailcap edit entry for %s"), type);
309  rc = 0;
310  goto bailout;
311  }
312 
313  rc = 1;
314 
315 bailout:
316 
317  if (unlink_newfile)
318  unlink(mutt_b2s(newfile));
319 
321  mutt_buffer_pool_release(&newfile);
322 
323  mailcap_entry_free(&entry);
324  return rc;
325 }
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
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
#define mutt_b2s(buf)
Definition: buffer.h:41
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 333 of file mutt_attach.c.

334 {
335  struct ListNode *np = NULL;
336  STAILQ_FOREACH(np, &MimeLookupList, entries)
337  {
338  const int i = mutt_str_len(np->data) - 1;
339  if (((i > 0) && (np->data[i - 1] == '/') && (np->data[i] == '*') &&
340  mutt_istrn_equal(type, np->data, i)) ||
341  mutt_istr_equal(type, np->data))
342  {
343  struct Body tmp = { 0 };
344  enum ContentType n;
345  if ((n = mutt_lookup_mime_type(&tmp, b->filename)) != TYPE_OTHER ||
346  (n = mutt_lookup_mime_type(&tmp, b->description)) != TYPE_OTHER)
347  {
348  snprintf(type, len, "%s/%s",
349  (n == TYPE_AUDIO) ?
350  "audio" :
351  (n == TYPE_APPLICATION) ?
352  "application" :
353  (n == TYPE_IMAGE) ?
354  "image" :
355  (n == TYPE_MESSAGE) ?
356  "message" :
357  (n == TYPE_MODEL) ?
358  "model" :
359  (n == TYPE_MULTIPART) ?
360  "multipart" :
361  (n == TYPE_TEXT) ? "text" : (n == TYPE_VIDEO) ? "video" : "other",
362  tmp.subtype);
363  mutt_debug(LL_DEBUG1, "\"%s\" -> %s\n", b->filename, type);
364  }
365  FREE(&tmp.subtype);
366  FREE(&tmp.xtype);
367  }
368  }
369 }
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:563
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 384 of file mutt_attach.c.

385 {
386  int rc;
387 
388 #ifdef USE_IMAP
389  rc = imap_wait_keepalive(pid);
390 #else
391  waitpid(pid, &rc, 0);
392 #endif
394  rc = WIFEXITED(rc) ? WEXITSTATUS(rc) : -1;
395 
396  return rc;
397 }
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:1102
+ 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 416 of file mutt_attach.c.

418 {
419  bool use_mailcap = false;
420  bool use_pipe = false;
421  bool use_pager = true;
422  char type[256];
423  char desc[256];
424  char *fname = NULL;
425  struct MailcapEntry *entry = NULL;
426  int rc = -1;
427  bool unlink_tempfile = false;
428  bool unlink_pagerfile = false;
429 
430  bool is_message = mutt_is_message_type(a->type, a->subtype);
431  if ((WithCrypto != 0) && is_message && a->email &&
433  {
434  return rc;
435  }
436 
437  struct Buffer *tmpfile = mutt_buffer_pool_get();
438  struct Buffer *pagerfile = mutt_buffer_pool_get();
439  struct Buffer *cmd = mutt_buffer_pool_get();
440 
441  use_mailcap =
442  (mode == MUTT_VA_MAILCAP || (mode == MUTT_VA_REGULAR && mutt_needs_mailcap(a)));
443  snprintf(type, sizeof(type), "%s/%s", TYPE(a), a->subtype);
444 
445  char columns[16];
446  snprintf(columns, sizeof(columns), "%d", win->state.cols);
447  mutt_envlist_set("COLUMNS", columns, true);
448 
449  if (use_mailcap)
450  {
451  entry = mailcap_entry_new();
452  if (!mailcap_lookup(a, type, sizeof(type), entry, MUTT_MC_NO_FLAGS))
453  {
454  if (mode == MUTT_VA_REGULAR)
455  {
456  /* fallback to view as text */
457  mailcap_entry_free(&entry);
458  mutt_error(_("No matching mailcap entry found. Viewing as text."));
459  mode = MUTT_VA_AS_TEXT;
460  use_mailcap = false;
461  }
462  else
463  goto return_error;
464  }
465  }
466 
467  if (use_mailcap)
468  {
469  if (!entry->command)
470  {
471  mutt_error(_("MIME type not defined. Can't view attachment."));
472  goto return_error;
473  }
474  mutt_buffer_strcpy(cmd, entry->command);
475 
476  fname = mutt_str_dup(a->filename);
477  /* In send mode(!fp), we allow slashes because those are part of
478  * the tmpfile. The path will be removed in expand_filename */
479  mutt_file_sanitize_filename(fname, fp ? true : false);
480  mailcap_expand_filename(entry->nametemplate, fname, tmpfile);
481  FREE(&fname);
482 
483  if (mutt_save_attachment(fp, a, mutt_b2s(tmpfile), 0, NULL) == -1)
484  goto return_error;
485  unlink_tempfile = true;
486 
488 
489  use_pipe = mailcap_expand_command(a, mutt_b2s(tmpfile), type, cmd);
490  use_pager = entry->copiousoutput;
491  }
492 
493  if (use_pager)
494  {
495  if (fp && !use_mailcap && a->filename)
496  {
497  /* recv case */
498  mutt_buffer_strcpy(pagerfile, a->filename);
499  mutt_adv_mktemp(pagerfile);
500  }
501  else
502  mutt_buffer_mktemp(pagerfile);
503  }
504 
505  if (use_mailcap)
506  {
507  pid_t pid = 0;
508  int fd_temp = -1, fd_pager = -1;
509 
510  if (!use_pager)
511  mutt_endwin();
512 
513  if (use_pager || use_pipe)
514  {
515  if (use_pager && ((fd_pager = mutt_file_open(mutt_b2s(pagerfile),
516  O_CREAT | O_EXCL | O_WRONLY)) == -1))
517  {
518  mutt_perror("open");
519  goto return_error;
520  }
521  unlink_pagerfile = true;
522 
523  if (use_pipe && ((fd_temp = open(mutt_b2s(tmpfile), 0)) == -1))
524  {
525  if (fd_pager != -1)
526  close(fd_pager);
527  mutt_perror("open");
528  goto return_error;
529  }
530  unlink_pagerfile = true;
531 
532  pid = filter_create_fd(mutt_b2s(cmd), NULL, NULL, NULL,
533  use_pipe ? fd_temp : -1, use_pager ? fd_pager : -1, -1);
534 
535  if (pid == -1)
536  {
537  if (fd_pager != -1)
538  close(fd_pager);
539 
540  if (fd_temp != -1)
541  close(fd_temp);
542 
543  mutt_error(_("Can't create filter"));
544  goto return_error;
545  }
546 
547  if (use_pager)
548  {
549  if (a->description)
550  {
551  snprintf(desc, sizeof(desc), _("---Command: %-20.20s Description: %s"),
552  mutt_b2s(cmd), a->description);
553  }
554  else
555  {
556  snprintf(desc, sizeof(desc), _("---Command: %-30.30s Attachment: %s"),
557  mutt_b2s(cmd), type);
558  }
559  filter_wait(pid);
560  }
561  else
562  {
563  if (wait_interactive_filter(pid) || (entry->needsterminal && C_WaitKey))
565  }
566 
567  if (fd_temp != -1)
568  close(fd_temp);
569  if (fd_pager != -1)
570  close(fd_pager);
571  }
572  else
573  {
574  /* interactive cmd */
575  int rv = mutt_system(mutt_b2s(cmd));
576  if (rv == -1)
577  mutt_debug(LL_DEBUG1, "Error running \"%s\"", cmd->data);
578 
579  if ((rv != 0) || (entry->needsterminal && C_WaitKey))
581  }
582  }
583  else
584  {
585  /* Don't use mailcap; the attachment is viewed in the pager */
586 
587  if (mode == MUTT_VA_AS_TEXT)
588  {
589  /* just let me see the raw data */
590  if (fp)
591  {
592  /* Viewing from a received message.
593  *
594  * Don't use mutt_save_attachment() because we want to perform charset
595  * conversion since this will be displayed by the internal pager. */
596  struct State decode_state = { 0 };
597 
598  decode_state.fp_out = mutt_file_fopen(mutt_b2s(pagerfile), "w");
599  if (!decode_state.fp_out)
600  {
601  mutt_debug(LL_DEBUG1, "mutt_file_fopen(%s) errno=%d %s\n",
602  mutt_b2s(pagerfile), errno, strerror(errno));
603  mutt_perror(mutt_b2s(pagerfile));
604  goto return_error;
605  }
606  decode_state.fp_in = fp;
607  decode_state.flags = MUTT_CHARCONV;
608  mutt_decode_attachment(a, &decode_state);
609  if (mutt_file_fclose(&decode_state.fp_out) == EOF)
610  {
611  mutt_debug(LL_DEBUG1, "fclose(%s) errno=%d %s\n", mutt_b2s(pagerfile),
612  errno, strerror(errno));
613  }
614  }
615  else
616  {
617  /* in compose mode, just copy the file. we can't use
618  * mutt_decode_attachment() since it assumes the content-encoding has
619  * already been applied */
620  if (mutt_save_attachment(fp, a, mutt_b2s(pagerfile), MUTT_SAVE_NO_FLAGS, NULL))
621  goto return_error;
622  unlink_pagerfile = true;
623  }
625  }
626  else
627  {
628  /* Use built-in handler */
629  OptViewAttach = true; /* disable the "use 'v' to view this part"
630  * message in case of error */
632  {
633  OptViewAttach = false;
634  goto return_error;
635  }
636  unlink_pagerfile = true;
637  OptViewAttach = false;
638  }
639 
640  if (a->description)
641  mutt_str_copy(desc, a->description, sizeof(desc));
642  else if (a->filename)
643  snprintf(desc, sizeof(desc), _("---Attachment: %s: %s"), a->filename, type);
644  else
645  snprintf(desc, sizeof(desc), _("---Attachment: %s"), type);
646  }
647 
648  /* We only reach this point if there have been no errors */
649 
650  if (use_pager)
651  {
652  struct Pager info = { 0 };
653  info.fp = fp;
654  info.body = a;
655  info.ctx = Context;
656  info.actx = actx;
657  info.email = e;
658 
659  rc = mutt_do_pager(desc, mutt_b2s(pagerfile),
661  &info);
662  mutt_buffer_reset(pagerfile);
663  unlink_pagerfile = false;
664  }
665  else
666  rc = 0;
667 
668 return_error:
669 
670  if (!entry || !entry->xneomuttkeep)
671  {
672  if (fp && !mutt_buffer_is_empty(tmpfile))
673  {
674  /* add temporary file to TempAttachmentsList to be deleted on timeout hook */
676  }
677  else if (unlink_tempfile)
678  {
679  unlink(mutt_b2s(tmpfile));
680  }
681  }
682 
683  mailcap_entry_free(&entry);
684 
685  if (unlink_pagerfile)
686  mutt_file_unlink(mutt_b2s(pagerfile));
687 
688  mutt_buffer_pool_release(&tmpfile);
689  mutt_buffer_pool_release(&pagerfile);
691  mutt_envlist_unset("COLUMNS");
692 
693  return rc;
694 }
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:1843
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
#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:55
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:869
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
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:384
void mutt_add_temp_attachment(const char *filename)
Add file to list of temporary attachments.
Definition: mutt_attach.c:1250
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
#define mutt_b2s(buf)
Definition: buffer.h:41
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:1000
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
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
int mutt_file_open(const char *path, int flags)
Open a file.
Definition: file.c:522
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
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:588
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:168
+ 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 705 of file mutt_attach.c.

706 {
707  pid_t pid = 0;
708  int out = -1, rc = 0;
709  bool is_flowed = false;
710  bool unlink_unstuff = false;
711  FILE *fp_filter = NULL, *fp_unstuff = NULL, *fp_in = NULL;
712  struct Buffer *unstuff_tempfile = NULL;
713 
714  if (outfile && *outfile)
715  {
716  out = mutt_file_open(outfile, O_CREAT | O_EXCL | O_WRONLY);
717  if (out < 0)
718  {
719  mutt_perror("open");
720  return 0;
721  }
722  }
723 
725  {
726  is_flowed = true;
727  unstuff_tempfile = mutt_buffer_pool_get();
728  mutt_buffer_mktemp(unstuff_tempfile);
729  }
730 
731  mutt_endwin();
732 
733  if (outfile && *outfile)
734  pid = filter_create_fd(path, &fp_filter, NULL, NULL, -1, out, -1);
735  else
736  pid = filter_create(path, &fp_filter, NULL, NULL);
737  if (pid < 0)
738  {
739  mutt_perror(_("Can't create filter"));
740  goto bail;
741  }
742 
743  /* recv case */
744  if (fp)
745  {
746  struct State s = { 0 };
747 
748  /* perform charset conversion on text attachments when piping */
749  s.flags = MUTT_CHARCONV;
750 
751  if (is_flowed)
752  {
753  fp_unstuff = mutt_file_fopen(mutt_b2s(unstuff_tempfile), "w");
754  if (fp_unstuff == NULL)
755  {
756  mutt_perror("mutt_file_fopen");
757  goto bail;
758  }
759  unlink_unstuff = true;
760 
761  s.fp_in = fp;
762  s.fp_out = fp_unstuff;
763  mutt_decode_attachment(b, &s);
764  mutt_file_fclose(&fp_unstuff);
765 
766  mutt_rfc3676_space_unstuff_attachment(b, mutt_b2s(unstuff_tempfile));
767 
768  fp_unstuff = mutt_file_fopen(mutt_b2s(unstuff_tempfile), "r");
769  if (fp_unstuff == NULL)
770  {
771  mutt_perror("mutt_file_fopen");
772  goto bail;
773  }
774  mutt_file_copy_stream(fp_unstuff, fp_filter);
775  mutt_file_fclose(&fp_unstuff);
776  }
777  else
778  {
779  s.fp_in = fp;
780  s.fp_out = fp_filter;
781  mutt_decode_attachment(b, &s);
782  }
783  }
784 
785  /* send case */
786  else
787  {
788  const char *infile = NULL;
789 
790  if (is_flowed)
791  {
792  if (mutt_save_attachment(fp, b, mutt_b2s(unstuff_tempfile),
793  MUTT_SAVE_NO_FLAGS, NULL) == -1)
794  goto bail;
795  unlink_unstuff = true;
796  mutt_rfc3676_space_unstuff_attachment(b, mutt_b2s(unstuff_tempfile));
797  infile = mutt_b2s(unstuff_tempfile);
798  }
799  else
800  infile = b->filename;
801 
802  fp_in = fopen(infile, "r");
803  if (!fp_in)
804  {
805  mutt_perror("fopen");
806  goto bail;
807  }
808 
809  mutt_file_copy_stream(fp_in, fp_filter);
810  mutt_file_fclose(&fp_in);
811  }
812 
813  mutt_file_fclose(&fp_filter);
814  rc = 1;
815 
816 bail:
817  if (outfile && *outfile)
818  {
819  close(out);
820  if (rc == 0)
821  unlink(outfile);
822  else if (is_flowed)
824  }
825 
826  mutt_file_fclose(&fp_unstuff);
827  mutt_file_fclose(&fp_filter);
828  mutt_file_fclose(&fp_in);
829 
830  if (unlink_unstuff)
831  mutt_file_unlink(mutt_b2s(unstuff_tempfile));
832  mutt_buffer_pool_release(&unstuff_tempfile);
833 
834  /* check for error exit from child process */
835  if ((pid > 0) && (filter_wait(pid) != 0))
836  rc = 0;
837 
838  if ((rc == 0) || C_WaitKey)
840  return rc;
841 }
void mutt_decode_attachment(struct Body *b, struct State *s)
Decode an email&#39;s attachment.
Definition: handler.c:1843
#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:55
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:869
FILE * fp_in
File to read from.
Definition: state.h:46
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
#define mutt_b2s(buf)
Definition: buffer.h:41
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_open(const char *path, int flags)
Open a file.
Definition: file.c:522
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:588
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:168
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 849 of file mutt_attach.c.

850 {
851  if (opt == MUTT_SAVE_APPEND)
852  return fopen(path, "a");
853  if (opt == MUTT_SAVE_OVERWRITE)
854  return fopen(path, "w");
855 
856  return mutt_file_fopen(path, "w");
857 }
Overwrite existing file.
Definition: mutt_attach.h:57
Append to existing file.
Definition: mutt_attach.h:56
FILE * mutt_file_fopen(const char *path, const char *mode)
Call fopen() safely.
Definition: file.c:588
+ 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 869 of file mutt_attach.c.

871 {
872  if (!m)
873  return -1;
874 
875  if (fp)
876  {
877  /* recv mode */
878 
879  if (e && m->email && (m->encoding != ENC_BASE64) &&
881  {
882  /* message type attachments are written to mail folders. */
883 
884  char buf[8192];
885  struct Message *msg = NULL;
886  CopyHeaderFlags chflags = CH_NO_FLAGS;
887  int rc = -1;
888 
889  struct Email *e_new = m->email;
890  e_new->msgno = e->msgno; /* required for MH/maildir */
891  e_new->read = true;
892 
893  if (fseeko(fp, m->offset, SEEK_SET) < 0)
894  return -1;
895  if (!fgets(buf, sizeof(buf), fp))
896  return -1;
897  struct Mailbox *m_att = mx_path_resolve(path);
898  struct Context *ctx = mx_mbox_open(m_att, MUTT_APPEND | MUTT_QUIET);
899  if (!ctx)
900  {
901  mailbox_free(&m_att);
902  return -1;
903  }
904  msg = mx_msg_open_new(ctx->mailbox, e_new,
905  is_from(buf, NULL, 0, NULL) ? MUTT_MSG_NO_FLAGS : MUTT_ADD_FROM);
906  if (!msg)
907  {
908  mx_mbox_close(&ctx);
909  return -1;
910  }
911  if ((ctx->mailbox->type == MUTT_MBOX) || (ctx->mailbox->type == MUTT_MMDF))
912  chflags = CH_FROM | CH_UPDATE_LEN;
913  chflags |= ((ctx->mailbox->type == MUTT_MAILDIR) ? CH_NOSTATUS : CH_UPDATE);
914  if ((mutt_copy_message_fp(msg->fp, fp, e_new, MUTT_CM_NO_FLAGS, chflags, 0) == 0) &&
915  (mx_msg_commit(ctx->mailbox, msg) == 0))
916  {
917  rc = 0;
918  }
919  else
920  {
921  rc = -1;
922  }
923 
924  mx_msg_close(ctx->mailbox, &msg);
925  mx_mbox_close(&ctx);
926  return rc;
927  }
928  else
929  {
930  /* In recv mode, extract from folder and decode */
931 
932  struct State s = { 0 };
933 
934  s.fp_out = save_attachment_open(path, opt);
935  if (!s.fp_out)
936  {
937  mutt_perror("fopen");
938  return -1;
939  }
940  fseeko((s.fp_in = fp), m->offset, SEEK_SET);
941  mutt_decode_attachment(m, &s);
942 
943  if (mutt_file_fsync_close(&s.fp_out) != 0)
944  {
945  mutt_perror("fclose");
946  return -1;
947  }
948  }
949  }
950  else
951  {
952  if (!m->filename)
953  return -1;
954 
955  /* In send mode, just copy file */
956 
957  FILE *fp_old = fopen(m->filename, "r");
958  if (!fp_old)
959  {
960  mutt_perror("fopen");
961  return -1;
962  }
963 
964  FILE *fp_new = save_attachment_open(path, opt);
965  if (!fp_new)
966  {
967  mutt_perror("fopen");
968  mutt_file_fclose(&fp_old);
969  return -1;
970  }
971 
972  if (mutt_file_copy_stream(fp_old, fp_new) == -1)
973  {
974  mutt_error(_("Write fault"));
975  mutt_file_fclose(&fp_old);
976  mutt_file_fclose(&fp_new);
977  return -1;
978  }
979  mutt_file_fclose(&fp_old);
980  if (mutt_file_fsync_close(&fp_new) != 0)
981  {
982  mutt_error(_("Write fault"));
983  return -1;
984  }
985  }
986 
987  return 0;
988 }
#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:1843
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:1206
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:1072
struct Mailbox * mailbox
Definition: context.h:50
void mailbox_free(struct Mailbox **ptr)
Free a Mailbox.
Definition: mailbox.c:60
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:1185
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:1696
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:849
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:609
#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 1000 of file mutt_attach.c.

1002 {
1003  struct State s = { 0 };
1004  unsigned int saved_encoding = 0;
1005  struct Body *saved_parts = NULL;
1006  struct Email *e_saved = NULL;
1007  int rc = 0;
1008 
1009  s.flags = displaying;
1010 
1011  if (opt == MUTT_SAVE_APPEND)
1012  s.fp_out = fopen(path, "a");
1013  else if (opt == MUTT_SAVE_OVERWRITE)
1014  s.fp_out = fopen(path, "w");
1015  else
1016  s.fp_out = mutt_file_fopen(path, "w");
1017 
1018  if (!s.fp_out)
1019  {
1020  mutt_perror("fopen");
1021  return -1;
1022  }
1023 
1024  if (!fp)
1025  {
1026  /* When called from the compose menu, the attachment isn't parsed,
1027  * so we need to do it here. */
1028  struct stat st;
1029 
1030  if (stat(m->filename, &st) == -1)
1031  {
1032  mutt_perror("stat");
1034  return -1;
1035  }
1036 
1037  s.fp_in = fopen(m->filename, "r");
1038  if (!s.fp_in)
1039  {
1040  mutt_perror("fopen");
1041  return -1;
1042  }
1043 
1044  saved_encoding = m->encoding;
1045  if (!is_multipart(m))
1046  m->encoding = ENC_8BIT;
1047 
1048  m->length = st.st_size;
1049  m->offset = 0;
1050  saved_parts = m->parts;
1051  e_saved = m->email;
1052  mutt_parse_part(s.fp_in, m);
1053 
1054  if (m->noconv || is_multipart(m))
1055  s.flags |= MUTT_CHARCONV;
1056  }
1057  else
1058  {
1059  s.fp_in = fp;
1060  s.flags |= MUTT_CHARCONV;
1061  }
1062 
1063  mutt_body_handler(m, &s);
1064 
1065  if (mutt_file_fsync_close(&s.fp_out) != 0)
1066  {
1067  mutt_perror("fclose");
1068  rc = -1;
1069  }
1070  if (!fp)
1071  {
1072  m->length = 0;
1073  m->encoding = saved_encoding;
1074  if (saved_parts)
1075  {
1076  email_free(&m->email);
1077  m->parts = saved_parts;
1078  m->email = e_saved;
1079  }
1080  mutt_file_fclose(&s.fp_in);
1081  }
1082 
1083  return rc;
1084 }
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
#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:57
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:56
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:1593
FILE * mutt_file_fopen(const char *path, const char *mode)
Call fopen() safely.
Definition: file.c:588
void email_free(struct Email **ptr)
Free an Email.
Definition: email.c:43
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 1099 of file mutt_attach.c.

1100 {
1101  char type[256];
1102  pid_t pid;
1103  FILE *fp_in = NULL, *fp_out = NULL;
1104  bool unlink_newfile = false;
1105  struct Buffer *newfile = mutt_buffer_pool_get();
1106  struct Buffer *cmd = mutt_buffer_pool_get();
1107 
1108  int rc = 0;
1109 
1110  snprintf(type, sizeof(type), "%s/%s", TYPE(a), a->subtype);
1111 
1112  if (mailcap_lookup(a, type, sizeof(type), NULL, MUTT_MC_PRINT))
1113  {
1114  int piped = false;
1115 
1116  mutt_debug(LL_DEBUG2, "Using mailcap\n");
1117 
1118  struct MailcapEntry *entry = mailcap_entry_new();
1119  mailcap_lookup(a, type, sizeof(type), entry, MUTT_MC_PRINT);
1120  mailcap_expand_filename(entry->nametemplate, a->filename, newfile);
1121 
1122  if (mutt_save_attachment(fp, a, mutt_b2s(newfile), MUTT_SAVE_NO_FLAGS, NULL) == -1)
1123  goto mailcap_cleanup;
1124  unlink_newfile = 1;
1125 
1127 
1128  mutt_buffer_strcpy(cmd, entry->printcommand);
1129  piped = mailcap_expand_command(a, mutt_b2s(newfile), type, cmd);
1130 
1131  mutt_endwin();
1132 
1133  /* interactive program */
1134  if (piped)
1135  {
1136  fp_in = fopen(mutt_b2s(newfile), "r");
1137  if (!fp_in)
1138  {
1139  mutt_perror("fopen");
1140  mailcap_entry_free(&entry);
1141  goto mailcap_cleanup;
1142  }
1143 
1144  pid = filter_create(mutt_b2s(cmd), &fp_out, NULL, NULL);
1145  if (pid < 0)
1146  {
1147  mutt_perror(_("Can't create filter"));
1148  mailcap_entry_free(&entry);
1149  mutt_file_fclose(&fp_in);
1150  goto mailcap_cleanup;
1151  }
1152  mutt_file_copy_stream(fp_in, fp_out);
1153  mutt_file_fclose(&fp_out);
1154  mutt_file_fclose(&fp_in);
1155  if (filter_wait(pid) || C_WaitKey)
1157  }
1158  else
1159  {
1160  int rc2 = mutt_system(mutt_b2s(cmd));
1161  if (rc2 == -1)
1162  mutt_debug(LL_DEBUG1, "Error running \"%s\"", cmd->data);
1163 
1164  if ((rc2 != 0) || C_WaitKey)
1166  }
1167 
1168  rc = 1;
1169 
1170  mailcap_cleanup:
1171  if (unlink_newfile)
1172  mutt_file_unlink(mutt_b2s(newfile));
1173 
1174  mailcap_entry_free(&entry);
1175  goto out;
1176  }
1177 
1178  if (mutt_istr_equal("text/plain", type) ||
1179  mutt_istr_equal("application/postscript", type))
1180  {
1181  rc = (mutt_pipe_attachment(fp, a, NONULL(C_PrintCommand), NULL));
1182  goto out;
1183  }
1184  else if (mutt_can_decode(a))
1185  {
1186  /* decode and print */
1187 
1188  fp_in = NULL;
1189  fp_out = NULL;
1190 
1191  mutt_buffer_mktemp(newfile);
1192  if (mutt_decode_save_attachment(fp, a, mutt_b2s(newfile), MUTT_PRINTING,
1193  MUTT_SAVE_NO_FLAGS) == 0)
1194  {
1195  unlink_newfile = true;
1196  mutt_debug(LL_DEBUG2, "successfully decoded %s type attachment to %s\n",
1197  type, mutt_b2s(newfile));
1198 
1199  fp_in = fopen(mutt_b2s(newfile), "r");
1200  if (!fp_in)
1201  {
1202  mutt_perror("fopen");
1203  goto decode_cleanup;
1204  }
1205 
1206  mutt_debug(LL_DEBUG2, "successfully opened %s read-only\n", mutt_b2s(newfile));
1207 
1208  mutt_endwin();
1209  pid = filter_create(NONULL(C_PrintCommand), &fp_out, NULL, NULL);
1210  if (pid < 0)
1211  {
1212  mutt_perror(_("Can't create filter"));
1213  goto decode_cleanup;
1214  }
1215 
1216  mutt_debug(LL_DEBUG2, "Filter created\n");
1217 
1218  mutt_file_copy_stream(fp_in, fp_out);
1219 
1220  mutt_file_fclose(&fp_out);
1221  mutt_file_fclose(&fp_in);
1222 
1223  if ((filter_wait(pid) != 0) || C_WaitKey)
1225  rc = 1;
1226  }
1227  decode_cleanup:
1228  mutt_file_fclose(&fp_in);
1229  mutt_file_fclose(&fp_out);
1230  if (unlink_newfile)
1231  mutt_file_unlink(mutt_b2s(newfile));
1232  }
1233  else
1234  {
1235  mutt_error(_("I don't know how to print that"));
1236  rc = 0;
1237  }
1238 
1239 out:
1240  mutt_buffer_pool_release(&newfile);
1242 
1243  return rc;
1244 }
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:55
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:869
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
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
#define mutt_b2s(buf)
Definition: buffer.h:41
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:1000
bool mutt_can_decode(struct Body *a)
Will decoding the attachment produce any output.
Definition: handler.c:1803
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:705
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:168
+ 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 1250 of file mutt_attach.c.

1251 {
1252  mutt_list_insert_tail(&TempAttachmentsList, mutt_str_dup(filename));
1253 }
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 1258 of file mutt_attach.c.

1259 {
1260  struct ListNode *np = NULL;
1261 
1262  STAILQ_FOREACH(np, &TempAttachmentsList, entries)
1263  {
1264  mutt_file_chmod_add(np->data, S_IWUSR);
1265  mutt_file_unlink(np->data);
1266  }
1267 
1268  mutt_list_free(&TempAttachmentsList);
1269 }
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: