summaryrefslogtreecommitdiff
path: root/mail
diff options
context:
space:
mode:
authorSergey Poznyakoff <gray@gnu.org>2015-05-04 16:11:53 +0300
committerSergey Poznyakoff <gray@gnu.org>2015-05-04 16:11:53 +0300
commiteea2c4aa6f4383f3288ddc0c9e5084e36d31d9ac (patch)
tree3cf30a1d02bf23dbce7bf842c62b0b2468c467ad /mail
parentbe9580f6db6b710e0cd67ca326cac794742a112c (diff)
downloadmailutils-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.c235
-rw-r--r--mail/testsuite/mail/write.exp4
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"

Return to:

Send suggestions and report system problems to the System administrator.