diff options
author | Kevin McCarthy <kevin@8t8.us> | 2016-02-07 10:15:22 -0800 |
---|---|---|
committer | Kevin McCarthy <kevin@8t8.us> | 2016-02-07 10:15:22 -0800 |
commit | bca31736a8bd296e747c10f812eabc8950c7e1e3 (patch) | |
tree | fa3b2c55d75f16b22dcb713459deefba06b239c3 /main.c | |
parent | 346907218a3b945dc08ec4cf1a158d923fd33234 (diff) |
Add new flag -E to modify draft/include file. (closes #3799)
Specifying -E with -i will cause mutt to directly edit the include
file.
Specifying -E with -H will cause the draft file to be regenerated from
the latest version of the email on exit.
Improve -H so that it will read (and write) multipart messages.
Diffstat (limited to 'main.c')
-rw-r--r-- | main.c | 217 |
1 files changed, 170 insertions, 47 deletions
@@ -114,7 +114,7 @@ static void mutt_usage (void) puts _( "usage: mutt [<options>] [-z] [-f <file> | -yZ]\n\ - mutt [<options>] [-x] [-Hi <file>] [-s <subj>] [-bc <addr>] [-a <file> [...] --] <addr> [...]\n\ + mutt [<options>] [-Ex] [-Hi <file>] [-s <subj>] [-bc <addr>] [-a <file> [...] --] <addr> [...]\n\ mutt [<options>] [-x] [-s <subj>] [-bc <addr>] [-a <file> [...] --] <addr> [...] < message\n\ mutt [<options>] -p\n\ mutt [<options>] -A <alias> [...]\n\ @@ -134,7 +134,8 @@ options:\n\ puts _(" -d <level>\tlog debugging output to ~/.muttdebug0"); #endif puts _( -" -e <command>\tspecify a command to be executed after initialization\n\ +" -E\t\tedit the draft (-H) or include (-i) file\n\ + -e <command>\tspecify a command to be executed after initialization\n\ -f <file>\tspecify which mailbox to read\n\ -F <file>\tspecify an alternate muttrc file\n\ -H <file>\tspecify a draft file to read header and body from\n\ @@ -572,6 +573,7 @@ int main (int argc, char **argv) int i; int explicit_folder = 0; int dump_variables = 0; + int edit_infile = 0; extern char *optarg; extern int optind; int double_dash = argc, nargc = 1; @@ -625,7 +627,7 @@ int main (int argc, char **argv) argv[nargc++] = argv[optind]; } - if ((i = getopt (argc, argv, "+A:a:b:F:f:c:Dd:e:H:s:i:hm:npQ:RvxyzZ")) != EOF) + if ((i = getopt (argc, argv, "+A:a:b:F:f:c:Dd:Ee:H:s:i:hm:npQ:RvxyzZ")) != EOF) switch (i) { case 'A': @@ -673,6 +675,10 @@ int main (int argc, char **argv) #endif break; + case 'E': + edit_infile = 1; + break; + case 'e': commands = mutt_add_list (commands, optarg); break; @@ -859,10 +865,12 @@ int main (int argc, char **argv) optind < argc) { FILE *fin = NULL; + FILE *fout = NULL; char buf[LONG_STRING]; char *tempfile = NULL, *infile = NULL; - char *bodytext = NULL; + char *bodytext = NULL, *bodyfile = NULL; int rv = 0; + char expanded_infile[_POSIX_PATH_MAX]; if (!option (OPTNOCURSES)) mutt_flushinp (); @@ -900,81 +908,141 @@ int main (int argc, char **argv) msg->env->subject = safe_strdup (subject); if (draftFile) + { infile = draftFile; + includeFile = NULL; + } else if (includeFile) infile = includeFile; + else + edit_infile = 0; if (infile || bodytext) { + /* Prepare fin and expanded_infile. */ if (infile) { if (mutt_strcmp ("-", infile) == 0) + { + if (edit_infile) + { + fputs (_("Cannot use -E flag with stdin\n"), stderr); + exit (1); + } fin = stdin; - else + } + else { - char path[_POSIX_PATH_MAX]; - - strfcpy (path, infile, sizeof (path)); - mutt_expand_path (path, sizeof (path)); - if ((fin = fopen (path, "r")) == NULL) + strfcpy (expanded_infile, infile, sizeof (expanded_infile)); + mutt_expand_path (expanded_infile, sizeof (expanded_infile)); + if ((fin = fopen (expanded_infile, "r")) == NULL) { if (!option (OPTNOCURSES)) mutt_endwin (NULL); - perror (path); + perror (expanded_infile); exit (1); } } + } - if (draftFile) - { - ENVELOPE *opts_env = msg->env; - msg->env = mutt_read_rfc822_header (fin, NULL, 1, 0); + /* Copy input to a tempfile, and re-point fin to the tempfile. + * Note: stdin is always copied to a tempfile, ensuring draftFile + * can stat and get the correct st_size below. + */ + if (!edit_infile) + { + mutt_mktemp (buf, sizeof (buf)); + tempfile = safe_strdup (buf); - rfc822_append (&msg->env->to, opts_env->to, 0); - rfc822_append (&msg->env->cc, opts_env->cc, 0); - rfc822_append (&msg->env->bcc, opts_env->bcc, 0); - if (opts_env->subject) - mutt_str_replace (&msg->env->subject, opts_env->subject); + if ((fout = safe_fopen (tempfile, "w")) == NULL) + { + if (!option (OPTNOCURSES)) + mutt_endwin (NULL); + perror (tempfile); + safe_fclose (&fin); + FREE (&tempfile); + exit (1); + } + if (fin) + { + mutt_copy_stream (fin, fout); + if (fin != stdin) + safe_fclose (&fin); + } + else if (bodytext) + fputs (bodytext, fout); + safe_fclose (&fout); - mutt_free_envelope (&opts_env); + if ((fin = fopen (tempfile, "r")) == NULL) + { + if (!option (OPTNOCURSES)) + mutt_endwin (NULL); + perror (tempfile); + FREE (&tempfile); + exit (1); } } + /* If editing the infile, keep it around afterwards so + * it doesn't get unlinked, and we can rebuild the draftFile + */ + else + sendflags |= SENDNOFREEHEADER; - mutt_mktemp (buf, sizeof (buf)); - tempfile = safe_strdup (buf); - - /* is the following if still needed? */ - - if (tempfile) + /* Parse the draftFile into the full HEADER/BODY structure. + * Set SENDUSEHDRBODY so ci_send_message doesn't overwrite + * our msg->content. + */ + if (draftFile) { - FILE *fout; - - if ((fout = safe_fopen (tempfile, "w")) == NULL) - { - if (!option (OPTNOCURSES)) - mutt_endwin (NULL); - perror (tempfile); - safe_fclose (&fin); - FREE (&tempfile); - exit (1); - } - if (fin) - mutt_copy_stream (fin, fout); - else if (bodytext) - fputs (bodytext, fout); - safe_fclose (&fout); + HEADER *context_hdr = NULL; + ENVELOPE *opts_env = msg->env; + struct stat st; + + sendflags |= SENDUSEHDRBODY; + + /* Set up a "context" header with just enough information so that + * mutt_prepare_template() can parse the message in fin. + */ + context_hdr = mutt_new_header (); + context_hdr->offset = 0; + context_hdr->content = mutt_new_body (); + fstat (fileno (fin), &st); + context_hdr->content->length = st.st_size; + + mutt_prepare_template (fin, NULL, msg, context_hdr, 0); + + rfc822_append (&msg->env->to, opts_env->to, 0); + rfc822_append (&msg->env->cc, opts_env->cc, 0); + rfc822_append (&msg->env->bcc, opts_env->bcc, 0); + if (opts_env->subject) + mutt_str_replace (&msg->env->subject, opts_env->subject); + + mutt_free_envelope (&opts_env); + mutt_free_header (&context_hdr); } + /* Editing the includeFile: pass it directly in. + * Note that SENDNOFREEHEADER is set above so it isn't unlinked. + */ + else if (edit_infile) + bodyfile = expanded_infile; + /* For bodytext and unedited includeFile: use the tempfile. + */ + else + bodyfile = tempfile; - if (fin && fin != stdin) + if (fin) safe_fclose (&fin); } FREE (&bodytext); - + if (attach) { LIST *t = attach; - BODY *a = NULL; + BODY *a = msg->content; + + while (a && a->next) + a = a->next; while (t) { @@ -998,7 +1066,62 @@ int main (int argc, char **argv) mutt_free_list (&attach); } - rv = ci_send_message (sendflags, msg, tempfile, NULL, NULL); + rv = ci_send_message (sendflags, msg, bodyfile, NULL, NULL); + + if (edit_infile) + { + if (includeFile) + msg->content->unlink = 0; + else if (draftFile) + { + if (truncate (expanded_infile, 0) == -1) + { + if (!option (OPTNOCURSES)) + mutt_endwin (NULL); + perror (expanded_infile); + exit (1); + } + if ((fout = safe_fopen (expanded_infile, "a")) == NULL) + { + if (!option (OPTNOCURSES)) + mutt_endwin (NULL); + perror (expanded_infile); + exit (1); + } + + /* If the message was sent or postponed, these will already + * have been done. + */ + if (rv < 0) + { + if (msg->content->next) + msg->content = mutt_make_multipart (msg->content); + mutt_encode_descriptions (msg->content, 1); + mutt_prepare_envelope (msg->env, 0); + mutt_env_to_intl (msg->env, NULL, NULL); + } + + mutt_write_rfc822_header (fout, msg->env, msg->content, -1, 0); + fputc ('\n', fout); + if ((mutt_write_mime_body (msg->content, fout) == -1)) + { + if (!option (OPTNOCURSES)) + mutt_endwin (NULL); + safe_fclose (&fout); + exit (1); + } + safe_fclose (&fout); + } + + mutt_free_header (&msg); + } + + /* !edit_infile && draftFile will leave the tempfile around */ + if (tempfile) + { + unlink (tempfile); + FREE (&tempfile); + } if (!option (OPTNOCURSES)) mutt_endwin (NULL); |