diff options
author | Sergey Poznyakoff <gray@gnu.org> | 2015-05-04 16:11:53 +0300 |
---|---|---|
committer | Sergey Poznyakoff <gray@gnu.org> | 2015-05-04 16:11:53 +0300 |
commit | eea2c4aa6f4383f3288ddc0c9e5084e36d31d9ac (patch) | |
tree | 3cf30a1d02bf23dbce7bf842c62b0b2468c467ad /mail | |
parent | be9580f6db6b710e0cd67ca326cac794742a112c (diff) | |
download | mailutils-eea2c4aa6f4383f3288ddc0c9e5084e36d31d9ac.tar.gz mailutils-eea2c4aa6f4383f3288ddc0c9e5084e36d31d9ac.tar.bz2 |
mail: the "copy" command operates on files by default.
Last argument is treated as a mailbox only if it begins with
a mailbox scheme (mbox://, maildir://, etc).
* mail/copy.c (append_to_mailbox)
(append_to_file): New functions.
(mail_copy0): Depending on whether mailbox scheme is specified,
call one of the above functions.
* doc/texinfo/programs.texi (mail): Fix documentation of the copy
command.
* mail/testsuite/mail/write.exp: Update line/character counts for
[Ss]ave commands.
Diffstat (limited to 'mail')
-rw-r--r-- | mail/copy.c | 235 | ||||
-rw-r--r-- | mail/testsuite/mail/write.exp | 4 |
2 files changed, 190 insertions, 49 deletions
diff --git a/mail/copy.c b/mail/copy.c index ccbef62a3..5d35af6e0 100644 --- a/mail/copy.c +++ b/mail/copy.c @@ -16,6 +16,7 @@ along with GNU Mailutils. If not, see <http://www.gnu.org/licenses/>. */ #include "mail.h" +#include <mailutils/locker.h> /* * c[opy] [file] @@ -23,59 +24,33 @@ * C[opy] [msglist] */ -/* - * mail_copy0() is shared between mail_copy() and mail_save(). - * argc, argv -- argument count & vector - * mark -- whether we should mark the message as saved. - */ -int -mail_copy0 (int argc, char **argv, int mark) +struct append_stat { - mu_message_t msg; - mu_mailbox_t mbx; - char *filename = NULL; - msgset_t *msglist = NULL, *mp; - int sender = 0; - size_t total_size = 0, total_lines = 0, size; - int status; - - if (mu_isupper (argv[0][0])) - sender = 1; - else if (argc >= 2) - filename = mail_expand_name (argv[--argc]); - else - filename = mu_strdup ("mbox"); - - if (msgset_parse (argc, argv, MSG_NODELETED|MSG_SILENT, &msglist)) - { - if (filename) - free (filename); - return 1; - } - - if (sender) - filename = util_outfolder_name (util_get_sender (msglist->msg_part[0], 1)); - - if (!filename) - { - msgset_free (msglist); - return 1; - } + size_t size; + size_t lines; +}; +static int +append_to_mailbox (char const *filename, msgset_t *msglist, int mark, + struct append_stat *totals) +{ + int status; + mu_mailbox_t mbx; + msgset_t *mp; + size_t size; + mu_message_t msg; + if ((status = mu_mailbox_create_default (&mbx, filename)) != 0) { mu_error (_("Cannot create mailbox %s: %s"), filename, mu_strerror (status)); - free (filename); - msgset_free (msglist); return 1; } if ((status = mu_mailbox_open (mbx, MU_STREAM_WRITE | MU_STREAM_CREAT)) != 0) { mu_error (_("Cannot open mailbox %s: %s"), filename, mu_strerror (status)); - free (filename); - msgset_free (msglist); + mu_mailbox_destroy (&mbx); return 1; } @@ -93,9 +68,9 @@ mail_copy0 (int argc, char **argv, int mark) } mu_message_size (msg, &size); - total_size += size; + totals->size += size; mu_message_lines (msg, &size); - total_lines += size; + totals->lines += size; if (mark) { @@ -104,13 +79,179 @@ mail_copy0 (int argc, char **argv, int mark) mu_attribute_set_userflag (attr, MAIL_ATTRIBUTE_SAVED); } } + + mu_mailbox_close (mbx); + mu_mailbox_destroy (&mbx); + return 0; +} + +static int +append_to_file (char const *filename, msgset_t *msglist, int mark, + struct append_stat *totals) +{ + int status; + msgset_t *mp; + mu_stream_t ostr, mstr; + mu_off_t size; + size_t lines; + mu_message_t msg; + mu_locker_t locker; + + status = mu_file_stream_create (&ostr, filename, + MU_STREAM_CREAT|MU_STREAM_APPEND); + if (status) + { + mu_error (_("Cannot open output file %s: %s"), + filename, mu_strerror (status)); + return 1; + } + + status = mu_locker_create (&locker, filename, + MU_LOCKER_KERNEL|MU_LOCKER_RETRY); + if (status) + { + mu_error (_("Cannot create locker %s: %s"), + filename, mu_strerror (status)); + mu_stream_unref (ostr); + return 1; + } + mu_locker_lock_mode (locker, mu_lck_exc); + + status = mu_locker_lock (locker); + if (status) + { + mu_error (_("Cannot lock %s: %s"), + filename, mu_strerror (status)); + mu_locker_destroy (&locker); + mu_stream_unref (ostr); + return 1; + } + + for (mp = msglist; mp; mp = mp->next) + { + mu_envelope_t env; + const char *s, *d; + int n; + + status = util_get_message (mbox, mp->msg_part[0], &msg); + if (status) + break; + status = mu_message_get_envelope (msg, &env); + if (status) + { + mu_error (_("Cannot get envelope: %s"), mu_strerror (status)); + break; + } + + status = mu_envelope_sget_sender (env, &s); + if (status) + { + mu_error (_("Cannot get envelope sender: %s"), mu_strerror (status)); + break; + } + + status = mu_envelope_sget_date (env, &d); + if (status) + { + mu_error (_("Cannot get envelope date: %s"), mu_strerror (status)); + break; + } + + status = mu_stream_printf (ostr, "From %s %s\n%n", s, d, &n); + if (status) + { + mu_error (_("Write error: %s"), mu_strerror (status)); + break; + } + + totals->lines++; + totals->size += n; + + status = mu_message_get_streamref (msg, &mstr); + if (status) + { + mu_error (_("Cannot get message: %s"), mu_strerror (status)); + break; + } + + status = mu_stream_copy (ostr, mstr, 0, &size); + if (status) + { + mu_error (_("Cannot append message: %s"), mu_strerror (status)); + break; + } + + mu_stream_unref (mstr); + + mu_stream_write (ostr, "\n", 1, NULL); + + totals->size += size + 1; + mu_message_lines (msg, &lines); + totals->lines += lines + 1; + + if (mark) + { + mu_attribute_t attr; + mu_message_get_attribute (msg, &attr); + mu_attribute_set_userflag (attr, MAIL_ATTRIBUTE_SAVED); + } + } + + mu_stream_close (ostr); + mu_stream_unref (ostr); + + mu_locker_unlock (locker); + mu_locker_destroy (&locker); + + return 0; +} + +/* + * mail_copy0() is shared between mail_copy() and mail_save(). + * argc, argv -- argument count & vector + * mark -- whether we should mark the message as saved. + */ +int +mail_copy0 (int argc, char **argv, int mark) +{ + char *filename = NULL; + msgset_t *msglist = NULL; + int sender = 0; + struct append_stat totals = { 0, 0 }; + int status; + + if (mu_isupper (argv[0][0])) + sender = 1; + else if (argc >= 2) + filename = mail_expand_name (argv[--argc]); + else + filename = mu_strdup ("mbox"); + + if (msgset_parse (argc, argv, MSG_NODELETED|MSG_SILENT, &msglist)) + { + if (filename) + free (filename); + return 1; + } + + if (sender) + filename = util_outfolder_name (util_get_sender (msglist->msg_part[0], 1)); + + if (!filename) + { + msgset_free (msglist); + return 1; + } + + if (mu_is_proto (filename)) + status = append_to_mailbox (filename, msglist, mark, &totals); + else + status = append_to_file (filename, msglist, mark, &totals); + if (status == 0) mu_printf ("\"%s\" %3lu/%-5lu\n", filename, - (unsigned long) total_lines, (unsigned long) total_size); - - mu_mailbox_close (mbx); - mu_mailbox_destroy (&mbx); + (unsigned long) totals.lines, (unsigned long) totals.size); free (filename); msgset_free (msglist); diff --git a/mail/testsuite/mail/write.exp b/mail/testsuite/mail/write.exp index 68923cf10..92447a057 100644 --- a/mail/testsuite/mail/write.exp +++ b/mail/testsuite/mail/write.exp @@ -66,7 +66,7 @@ mail_test "headers" \ # Save messages to the third mailbox mail_command "set folder=\"$MU_FOLDER_DIR\"" mail_test "save 1 2 +three" \ - "\"$MU_FOLDER_DIR/three\" 28/968" + "\"$MU_FOLDER_DIR/three\" 32/1067" mail_test "headers" \ ">* 1 Sergey Poznyakoff Tue Jul 16 12:11 12/390 MBOX"\ @@ -84,7 +84,7 @@ mail_test "headers" \ # Test uppercase commands (Save and Copy) mail_command "set outfolder=\"$MU_FOLDER_DIR\"" mail_test "Save" \ - "\"$MU_FOLDER_DIR/gray\" 12/390" + "\"$MU_FOLDER_DIR/gray\" 14/438" mail_test "file \"$MU_FOLDER_DIR/gray\"" \ "Held 2 messages in $MU_FOLDER_DIR/three" |