Commit 8c9829fd 8c9829fdb977ad2b9c4c3ac372655e6cb7d9dff7 by Sergey Poznyakoff

movemail: minor improvements.

* libmailutils/base/list.c (list_itrctl): Accept mu_itrctl_set_direction
and mu_itrctl_qry_direction even if mu_iterator_first has not been called
yet.
* movemail/movemail.c: Rewrite using iterators.

* libmailutils/mailer/mailer.c (safe_address_create): Bugfix.
1 parent b54dd743
...@@ -562,49 +562,56 @@ list_itrctl (void *owner, enum mu_itrctl_req req, void *arg) ...@@ -562,49 +562,56 @@ list_itrctl (void *owner, enum mu_itrctl_req req, void *arg)
562 mu_list_t list = itr->list; 562 mu_list_t list = itr->list;
563 struct list_data *ptr; 563 struct list_data *ptr;
564 564
565 if (itr->cur == NULL)
566 return MU_ERR_NOENT;
567 switch (req) 565 switch (req)
568 { 566 {
569 case mu_itrctl_tell: 567 case mu_itrctl_tell:
570 /* Return current position in the object */ 568 /* Return current position in the object */
571 { 569 if (itr->cur == NULL)
572 size_t count;
573
574 for (count = 0, ptr = list->head.next; ptr != &list->head;
575 ptr = ptr->next, count++)
576 {
577 if (ptr == itr->cur)
578 {
579 *(size_t*)arg = count;
580 return 0;
581 }
582 }
583 return MU_ERR_NOENT; 570 return MU_ERR_NOENT;
584 } 571 else
585 572 {
573 size_t count;
574
575 for (count = 0, ptr = list->head.next; ptr != &list->head;
576 ptr = ptr->next, count++)
577 {
578 if (ptr == itr->cur)
579 {
580 *(size_t*)arg = count;
581 return 0;
582 }
583 }
584 return MU_ERR_NOENT;
585 }
586 break;
587
586 case mu_itrctl_delete: 588 case mu_itrctl_delete:
587 case mu_itrctl_delete_nd: 589 case mu_itrctl_delete_nd:
588 /* Delete current element */ 590 /* Delete current element */
589 { 591 if (itr->cur == NULL)
590 struct list_data *prev; 592 return MU_ERR_NOENT;
593 else
594 {
595 struct list_data *prev;
591 596
592 ptr = itr->cur; 597 ptr = itr->cur;
593 prev = ptr->prev; 598 prev = ptr->prev;
594 599
595 mu_iterator_advance (list->itr, ptr); 600 mu_iterator_advance (list->itr, ptr);
596 prev->next = ptr->next; 601 prev->next = ptr->next;
597 ptr->next->prev = prev; 602 ptr->next->prev = prev;
598 if (req == mu_itrctl_delete) 603 if (req == mu_itrctl_delete)
599 DESTROY_ITEM (list, ptr); 604 DESTROY_ITEM (list, ptr);
600 free (ptr); 605 free (ptr);
601 list->count--; 606 list->count--;
602 } 607 }
603 break; 608 break;
604 609
605 case mu_itrctl_replace: 610 case mu_itrctl_replace:
606 case mu_itrctl_replace_nd: 611 case mu_itrctl_replace_nd:
607 /* Replace current element */ 612 /* Replace current element */
613 if (itr->cur == NULL)
614 return MU_ERR_NOENT;
608 if (!arg) 615 if (!arg)
609 return EINVAL; 616 return EINVAL;
610 ptr = itr->cur; 617 ptr = itr->cur;
...@@ -616,12 +623,16 @@ list_itrctl (void *owner, enum mu_itrctl_req req, void *arg) ...@@ -616,12 +623,16 @@ list_itrctl (void *owner, enum mu_itrctl_req req, void *arg)
616 623
617 case mu_itrctl_insert: 624 case mu_itrctl_insert:
618 /* Insert new element in the current position */ 625 /* Insert new element in the current position */
626 if (itr->cur == NULL)
627 return MU_ERR_NOENT;
619 if (!arg) 628 if (!arg)
620 return EINVAL; 629 return EINVAL;
621 return _insert_item (list, itr->cur, arg, 0); 630 return _insert_item (list, itr->cur, arg, 0);
622 631
623 case mu_itrctl_insert_list: 632 case mu_itrctl_insert_list:
624 /* Insert a list of elements */ 633 /* Insert a list of elements */
634 if (itr->cur == NULL)
635 return MU_ERR_NOENT;
625 if (!arg) 636 if (!arg)
626 return EINVAL; 637 return EINVAL;
627 else 638 else
......
...@@ -380,9 +380,13 @@ safe_address_create (mu_address_t *paddr, const char *addr_str, ...@@ -380,9 +380,13 @@ safe_address_create (mu_address_t *paddr, const char *addr_str,
380 mu_debug (MU_DEBCAT_MAILER, MU_DEBUG_ERROR, 380 mu_debug (MU_DEBCAT_MAILER, MU_DEBUG_ERROR,
381 ("bad %s address: %s", who, addr_str)); 381 ("bad %s address: %s", who, addr_str));
382 rc = recover_email (addr_str, &p); 382 rc = recover_email (addr_str, &p);
383 if (rc && rc != MU_ERR_NOENT) 383 if (rc)
384 mu_debug (MU_DEBCAT_MAILER, MU_DEBUG_ERROR, 384 {
385 ("%s address recovery failed: %s", who, mu_strerror (rc))); 385 if (rc != MU_ERR_NOENT)
386 mu_debug (MU_DEBCAT_MAILER, MU_DEBUG_ERROR,
387 ("%s address recovery failed: %s",
388 who, mu_strerror (rc)));
389 }
386 else 390 else
387 { 391 {
388 mu_debug (MU_DEBCAT_MAILER, MU_DEBUG_TRACE1, 392 mu_debug (MU_DEBCAT_MAILER, MU_DEBUG_TRACE1,
......
...@@ -80,6 +80,10 @@ static size_t max_messages_option; ...@@ -80,6 +80,10 @@ static size_t max_messages_option;
80 80
81 static int onerror_flags; 81 static int onerror_flags;
82 82
83 size_t msg_count = 0; /* Number of processed messages */
84 size_t get_err_count = 0; /* Number of message retrieval errors */
85 size_t app_err_count = 0; /* Number of message appending errors */
86
83 enum set_ownership_mode 87 enum set_ownership_mode
84 { 88 {
85 copy_owner_id, 89 copy_owner_id,
...@@ -324,6 +328,11 @@ cb_onerror (void *data, mu_config_value_t *val) ...@@ -324,6 +328,11 @@ cb_onerror (void *data, mu_config_value_t *val)
324 328
325 if (mu_cfg_assert_value_type (val, MU_CFG_STRING)) 329 if (mu_cfg_assert_value_type (val, MU_CFG_STRING))
326 return 1; 330 return 1;
331 if (strcmp (val->v.string, "abort") == 0)
332 {
333 onerror_flags = 0;
334 return 0;
335 }
327 ws.ws_delim = ","; 336 ws.ws_delim = ",";
328 if (mu_wordsplit (val->v.string, &ws, 337 if (mu_wordsplit (val->v.string, &ws,
329 MU_WRDSF_NOVAR | MU_WRDSF_NOCMD | 338 MU_WRDSF_NOVAR | MU_WRDSF_NOCMD |
...@@ -384,7 +393,9 @@ struct mu_cfg_param movemail_cfg_param[] = { ...@@ -384,7 +393,9 @@ struct mu_cfg_param movemail_cfg_param[] = {
384 N_("What to do after an error. Argument is a comma-separated list of:\n" 393 N_("What to do after an error. Argument is a comma-separated list of:\n"
385 " skip - skip to the next message\n" 394 " skip - skip to the next message\n"
386 " delete - delete this one and to the next message\n" 395 " delete - delete this one and to the next message\n"
387 " count - count this message as processed") }, 396 " count - count this message as processed\n"
397 "Each keyword can be prefixed with \"no\" to reverse its meaning\n"
398 "Setting onerror=abort reverts to the default behavior.") },
388 { NULL } 399 { NULL }
389 }; 400 };
390 401
...@@ -495,17 +506,10 @@ open_mailbox (mu_mailbox_t *mbx, char *name, int flags, char *passwd) ...@@ -495,17 +506,10 @@ open_mailbox (mu_mailbox_t *mbx, char *name, int flags, char *passwd)
495 } 506 }
496 507
497 int 508 int
498 move_message (mu_mailbox_t src, mu_mailbox_t dst, size_t msgno) 509 move_message (mu_mailbox_t dst, mu_message_t msg, size_t msgno)
499 { 510 {
500 int rc; 511 int rc;
501 mu_message_t msg;
502 512
503 if ((rc = mu_mailbox_get_message (src, msgno, &msg)) != 0)
504 {
505 mu_error (_("cannot read message %lu: %s"),
506 (unsigned long) msgno, mu_strerror (rc));
507 return rc;
508 }
509 if ((rc = mu_mailbox_append_message (dst, msg)) != 0) 513 if ((rc = mu_mailbox_append_message (dst, msg)) != 0)
510 { 514 {
511 mu_error (_("cannot append message %lu: %s"), 515 mu_error (_("cannot append message %lu: %s"),
...@@ -522,6 +526,26 @@ move_message (mu_mailbox_t src, mu_mailbox_t dst, size_t msgno) ...@@ -522,6 +526,26 @@ move_message (mu_mailbox_t src, mu_mailbox_t dst, size_t msgno)
522 return rc; 526 return rc;
523 } 527 }
524 528
529 int
530 movemail (mu_mailbox_t dst, mu_message_t msg, size_t msgno)
531 {
532 int rc = move_message (dst, msg, msgno);
533 if (rc == 0)
534 ++msg_count;
535 else
536 {
537 app_err_count++;
538 if (onerror_flags)
539 {
540 if (onerror_flags & ONERROR_COUNT)
541 ++msg_count;
542 }
543 else
544 return 1;
545 }
546 return max_messages_option && msg_count >= max_messages_option;
547 }
548
525 /* Open source mailbox using compatibility syntax. Source_name is 549 /* Open source mailbox using compatibility syntax. Source_name is
526 of the form: 550 of the form:
527 551
...@@ -806,17 +830,17 @@ set_program_id (const char *source_name, const char *dest_name) ...@@ -806,17 +830,17 @@ set_program_id (const char *source_name, const char *dest_name)
806 mu_wordsplit_free (&ws); 830 mu_wordsplit_free (&ws);
807 } 831 }
808 832
833
809 int 834 int
810 main (int argc, char **argv) 835 main (int argc, char **argv)
811 { 836 {
812 int index; 837 int index;
813 size_t i, total; 838 size_t total;
814 int rc = 0; 839 int rc = 0;
815 int errs = 0;
816 char *source_name, *dest_name; 840 char *source_name, *dest_name;
817 int flags; 841 int flags;
818 mu_list_t src_uidl_list = NULL; 842 mu_list_t src_uidl_list = NULL;
819 size_t msg_count = 0; 843 mu_iterator_t itr;
820 844
821 /* Native Language Support */ 845 /* Native Language Support */
822 MU_APP_INIT_NLS (); 846 MU_APP_INIT_NLS ();
...@@ -845,7 +869,7 @@ main (int argc, char **argv) ...@@ -845,7 +869,7 @@ main (int argc, char **argv)
845 } 869 }
846 870
847 if (ignore_errors) 871 if (ignore_errors)
848 onerror_flags |= ONERROR_SKIP; 872 onerror_flags |= ONERROR_SKIP|ONERROR_COUNT;
849 873
850 if (emacs_mode) 874 if (emacs_mode)
851 { 875 {
...@@ -900,7 +924,6 @@ main (int argc, char **argv) ...@@ -900,7 +924,6 @@ main (int argc, char **argv)
900 924
901 if (uidl_option) 925 if (uidl_option)
902 { 926 {
903 mu_iterator_t itr;
904 mu_list_t dst_uidl_list = NULL; 927 mu_list_t dst_uidl_list = NULL;
905 928
906 rc = mu_mailbox_get_uidls (source, &src_uidl_list); 929 rc = mu_mailbox_get_uidls (source, &src_uidl_list);
...@@ -922,102 +945,93 @@ main (int argc, char **argv) ...@@ -922,102 +945,93 @@ main (int argc, char **argv)
922 if (mu_list_locate (dst_uidl_list, uidl, NULL) == 0) 945 if (mu_list_locate (dst_uidl_list, uidl, NULL) == 0)
923 mu_iterator_ctl (itr, mu_itrctl_delete, NULL); 946 mu_iterator_ctl (itr, mu_itrctl_delete, NULL);
924 } 947 }
925 mu_iterator_destroy (&itr);
926 mu_list_destroy (&dst_uidl_list); 948 mu_list_destroy (&dst_uidl_list);
927 mu_list_set_comparator (src_uidl_list, NULL); 949 mu_list_set_comparator (src_uidl_list, NULL);
928 }
929 950
930 /* FIXME: Implementing a mailbox iterator would allow to merge the three
931 branches of this conditional. */
932 if (src_uidl_list)
933 {
934 mu_iterator_t itr;
935
936 rc = mu_list_get_iterator (src_uidl_list, &itr);
937 if (rc)
938 {
939 mu_error(_("cannot get iterator: %s"), mu_strerror (rc));
940 exit (1);
941 }
942 rc = mu_iterator_ctl (itr, mu_itrctl_set_direction, &reverse_order); 951 rc = mu_iterator_ctl (itr, mu_itrctl_set_direction, &reverse_order);
943 if (rc) 952 if (rc)
944 { 953 {
945 mu_error(_("cannot set iteration direction: %s"), mu_strerror (rc)); 954 mu_error (_("cannot set iteration direction: %s"), mu_strerror (rc));
946 exit (1); 955 exit (1);
947 } 956 }
957
948 for (mu_iterator_first (itr); !mu_iterator_is_done (itr); 958 for (mu_iterator_first (itr); !mu_iterator_is_done (itr);
949 mu_iterator_next (itr)) 959 mu_iterator_next (itr))
950 { 960 {
951 struct mu_uidl *uidl; 961 struct mu_uidl *uidl;
952 962 mu_message_t msg;
963
953 mu_iterator_current (itr, (void **)&uidl); 964 mu_iterator_current (itr, (void **)&uidl);
954 rc = move_message (source, dest, uidl->msgno); 965
955 if (rc == 0) 966 if ((rc = mu_mailbox_get_message (source, uidl->msgno, &msg)) != 0)
956 {
957 ++msg_count;
958 }
959 else if (onerror_flags)
960 { 967 {
961 if (onerror_flags & ONERROR_COUNT) 968 mu_error (_("cannot read message %lu: %s"),
962 ++msg_count; 969 (unsigned long) uidl->msgno, mu_strerror (rc));
963 errs = 1; 970 get_err_count++;
971 continue;
964 } 972 }
965 else 973 if (movemail (dest, msg, uidl->msgno))
966 break;
967 if (max_messages_option && msg_count >= max_messages_option)
968 break; 974 break;
969 } 975 }
970 mu_iterator_destroy (&itr);
971 } 976 }
972 else if (reverse_order) 977 else
973 { 978 {
974 for (i = total; i > 0; i--) 979 rc = mu_mailbox_get_iterator (source, &itr);
980 if (rc)
975 { 981 {
976 rc = move_message (source, dest, i); 982 mu_error (_("cannot obtain mailbox iterator: %s"), mu_strerror (rc));
977 if (rc == 0) 983 return 1;
978 {
979 ++msg_count;
980 }
981 else if (onerror_flags)
982 {
983 if (onerror_flags & ONERROR_COUNT)
984 ++msg_count;
985 errs = 1;
986 }
987 else
988 break;
989 if (max_messages_option && msg_count >= max_messages_option)
990 break;
991 } 984 }
992 } 985
993 else 986 rc = mu_iterator_ctl (itr, mu_itrctl_set_direction, &reverse_order);
994 { 987 if (rc)
995 for (i = 1; i <= total; i++)
996 { 988 {
997 rc = move_message (source, dest, i); 989 mu_error (_("cannot set iteration direction: %s"),
998 if (rc == 0) 990 mu_strerror (rc));
991 return 1;
992 }
993
994 for (mu_iterator_first (itr); !mu_iterator_is_done (itr);
995 mu_iterator_next (itr))
996 {
997 mu_message_t msg;
998 size_t msgno;
999
1000 rc = mu_iterator_ctl (itr, mu_itrctl_tell, &msgno);
1001 if (rc)
999 { 1002 {
1000 ++msg_count; 1003 mu_error (_("cannot get iterator position: %s"),
1004 mu_strerror (rc));
1005 return 1;
1001 } 1006 }
1002 else if (onerror_flags) 1007
1008 rc = mu_iterator_current (itr, (void **)&msg);
1009 if (rc)
1003 { 1010 {
1004 if (onerror_flags & ONERROR_COUNT) 1011 mu_error (_("cannot read message %lu: %s"),
1005 ++msg_count; 1012 (unsigned long) msgno, mu_strerror (rc));
1006 errs = 1; 1013 get_err_count++;
1014 continue;
1007 } 1015 }
1008 else 1016
1009 break; 1017 if (movemail (dest, msg, msgno))
1010 if (max_messages_option && msg_count >= max_messages_option)
1011 break; 1018 break;
1012 } 1019 }
1013 } 1020 }
1021 mu_iterator_destroy (&itr);
1014 1022
1015 if (verbose_option) 1023 if (verbose_option)
1016 mu_diag_output (MU_DIAG_INFO, 1024 {
1017 _("number of processed messages: %lu"), 1025 mu_diag_output (MU_DIAG_INFO,
1018 (unsigned long) msg_count); 1026 _("number of processed messages: %lu"),
1019 1027 (unsigned long) msg_count);
1020 if (errs && !(onerror_flags & (ONERROR_DELETE|ONERROR_COUNT))) 1028 mu_diag_output (MU_DIAG_INFO,
1029 _("number of errors: %lu / %lu"),
1030 (unsigned long) get_err_count,
1031 (unsigned long) app_err_count);
1032 }
1033
1034 if (app_err_count && !(onerror_flags & (ONERROR_DELETE|ONERROR_COUNT)))
1021 /* FIXME: mailboxes are not properly closed */ 1035 /* FIXME: mailboxes are not properly closed */
1022 return 1; 1036 return 1;
1023 1037
...@@ -1032,5 +1046,8 @@ main (int argc, char **argv) ...@@ -1032,5 +1046,8 @@ main (int argc, char **argv)
1032 mu_mailbox_close (source); 1046 mu_mailbox_close (source);
1033 mu_mailbox_destroy (&source); 1047 mu_mailbox_destroy (&source);
1034 1048
1035 return !(rc == 0 && errs == 0); 1049 if (onerror_flags & ONERROR_COUNT)
1050 app_err_count = 0;
1051
1052 return !(rc == 0 && (app_err_count + get_err_count) == 0);
1036 } 1053 }
......