Commit 8fcdf745 8fcdf7455d1948df3c6ed48cfe10a32d393742dd by Sergey Poznyakoff

MH send: improve compatibility with MH/nmh.

1 parent 734f1b38
Showing 1 changed file with 147 additions and 57 deletions
...@@ -35,8 +35,8 @@ static struct argp_option options[] = { ...@@ -35,8 +35,8 @@ static struct argp_option options[] = {
35 N_("use prepared draft") }, 35 N_("use prepared draft") },
36 {"draftfolder", ARG_DRAFTFOLDER, N_("FOLDER"), 0, 36 {"draftfolder", ARG_DRAFTFOLDER, N_("FOLDER"), 0,
37 N_("specify the folder for message drafts") }, 37 N_("specify the folder for message drafts") },
38 {"draftmessage", ARG_DRAFTMESSAGE, NULL, 0, 38 {"draftmessage", ARG_DRAFTMESSAGE, N_("MSG"), 0,
39 N_("treat the arguments as a list of messages from the draftfolder") }, 39 N_("use MSG from the draftfolder as a draft") },
40 {"nodraftfolder", ARG_NODRAFTFOLDER, NULL, 0, 40 {"nodraftfolder", ARG_NODRAFTFOLDER, NULL, 0,
41 N_("undo the effect of the last --draftfolder option") }, 41 N_("undo the effect of the last --draftfolder option") },
42 {"filter", ARG_FILTER, N_("FILE"), 0, 42 {"filter", ARG_FILTER, N_("FILE"), 0,
...@@ -99,9 +99,10 @@ struct mh_option mh_option[] = { ...@@ -99,9 +99,10 @@ struct mh_option mh_option[] = {
99 { NULL } 99 { NULL }
100 }; 100 };
101 101
102 static int use_draft; /* Use the prepared draft */
103 static const char *draftfolder; /* Use this draft folder */ 102 static const char *draftfolder; /* Use this draft folder */
104 static char *draftmessage = "cur"; 103 static int use_draftfolder = 1;
104 static int use_draft;
105
105 static int reformat_recipients; /* --format option */ 106 static int reformat_recipients; /* --format option */
106 static int forward_notice; /* Forward the failure notice to the sender, 107 static int forward_notice; /* Forward the failure notice to the sender,
107 --forward flag */ 108 --forward flag */
...@@ -126,6 +127,9 @@ static int keep_files; /* Keep draft files */ ...@@ -126,6 +127,9 @@ static int keep_files; /* Keep draft files */
126 watch_printf c;\ 127 watch_printf c;\
127 } while (0) 128 } while (0)
128 129
130 static int add_file (char *name);
131 static void mesg_list_fixup (void);
132
129 static error_t 133 static error_t
130 opt_handler (int key, char *arg, struct argp_state *state) 134 opt_handler (int key, char *arg, struct argp_state *state)
131 { 135 {
...@@ -152,14 +156,16 @@ opt_handler (int key, char *arg, struct argp_state *state) ...@@ -152,14 +156,16 @@ opt_handler (int key, char *arg, struct argp_state *state)
152 156
153 case ARG_DRAFTFOLDER: 157 case ARG_DRAFTFOLDER:
154 draftfolder = arg; 158 draftfolder = arg;
159 use_draftfolder = 1;
155 break; 160 break;
156 161
157 case ARG_NODRAFTFOLDER: 162 case ARG_NODRAFTFOLDER:
158 draftfolder = NULL; 163 draftfolder = NULL;
164 use_draftfolder = 0;
159 break; 165 break;
160 166
161 case ARG_DRAFTMESSAGE: 167 case ARG_DRAFTMESSAGE:
162 draftmessage = arg; 168 add_file (arg);
163 break; 169 break;
164 170
165 case ARG_FILTER: 171 case ARG_FILTER:
...@@ -284,30 +290,58 @@ static mu_list_t mesg_list; ...@@ -284,30 +290,58 @@ static mu_list_t mesg_list;
284 static mu_property_t mts_profile; 290 static mu_property_t mts_profile;
285 291
286 int 292 int
287 check_file (char *name) 293 add_file (char *name)
288 { 294 {
289 struct list_elt *elt; 295 struct list_elt *elt;
290 mu_message_t msg;
291 char *file_name = mh_expand_name (draftfolder, name, 0);
292 296
293 msg = mh_file_to_message (NULL, file_name);
294 if (!msg)
295 {
296 free (file_name);
297 return 1;
298 }
299 if (!mesg_list && mu_list_create (&mesg_list)) 297 if (!mesg_list && mu_list_create (&mesg_list))
300 { 298 {
301 free (file_name);
302 mu_error (_("cannot create message list")); 299 mu_error (_("cannot create message list"));
303 return 1; 300 return 1;
304 } 301 }
302
305 elt = mu_alloc (sizeof *elt); 303 elt = mu_alloc (sizeof *elt);
306 elt->file_name = file_name; 304 elt->file_name = name;
307 elt->msg = msg; 305 elt->msg = NULL;
308 return mu_list_append (mesg_list, elt); 306 return mu_list_append (mesg_list, elt);
309 } 307 }
310 308
309 int
310 checkdraft (const char *name)
311 {
312 struct stat st;
313
314 if (stat (name, &st))
315 {
316 mu_error (_("unable to stat draft file %s: %s"), name,
317 mu_strerror (errno));
318 return 1;
319 }
320 return 0;
321 }
322
323 int
324 elt_fixup (void *item, void *data)
325 {
326 struct list_elt *elt = item;
327
328 elt->file_name = mh_expand_name (draftfolder, elt->file_name, 0);
329 if (checkdraft (elt->file_name))
330 exit (1);
331 elt->msg = mh_file_to_message (NULL, elt->file_name);
332 if (!elt->msg)
333 return 1;
334
335 return 0;
336 }
337
338 void
339 mesg_list_fixup ()
340 {
341 if (mesg_list && mu_list_foreach (mesg_list, elt_fixup, NULL))
342 exit (1);
343 }
344
311 void 345 void
312 read_mts_profile () 346 read_mts_profile ()
313 { 347 {
...@@ -741,11 +775,25 @@ _add_to_mesg_list (size_t num, mu_message_t msg, void *data) ...@@ -741,11 +775,25 @@ _add_to_mesg_list (size_t num, mu_message_t msg, void *data)
741 struct list_elt *elt; 775 struct list_elt *elt;
742 size_t uid; 776 size_t uid;
743 int rc; 777 int rc;
778 char *file_name;
779
780 if (!mesg_list && mu_list_create (&mesg_list))
781 {
782 mu_error (_("cannot create message list"));
783 return 1;
784 }
785
786 mu_message_get_uid (msg, &uid);
787 file_name = mu_make_file_name (path, mu_umaxtostr (0, uid));
788 if (!use_draft)
789 {
790 if (!mh_usedraft (file_name))
791 exit (0);
792 }
744 793
745 elt = mu_alloc (sizeof *elt); 794 elt = mu_alloc (sizeof *elt);
746 elt->msg = msg; 795 elt->msg = msg;
747 mu_message_get_uid (msg, &uid); 796 elt->file_name = file_name;
748 elt->file_name = mu_make_file_name (path, mu_umaxtostr (0, uid));
749 rc = mu_list_append (mesg_list, elt); 797 rc = mu_list_append (mesg_list, elt);
750 if (rc) 798 if (rc)
751 { 799 {
...@@ -755,6 +803,57 @@ _add_to_mesg_list (size_t num, mu_message_t msg, void *data) ...@@ -755,6 +803,57 @@ _add_to_mesg_list (size_t num, mu_message_t msg, void *data)
755 return 0; 803 return 0;
756 } 804 }
757 805
806 static void
807 addfolder (const char *folder, int argc, char **argv)
808 {
809 mu_url_t url;
810 const char *path;
811 mu_msgset_t msgset;
812
813 mu_mailbox_t mbox = mh_open_folder (folder, MU_STREAM_READ);
814 if (!mbox)
815 {
816 mu_error (_("cannot open folder %s: %s"), folder,
817 mu_strerror (errno));
818 exit (1);
819 }
820
821 mh_msgset_parse (&msgset, mbox, argc, argv, "cur");
822 if (!use_draft)
823 {
824 size_t count = 0;
825 mu_msgset_count (msgset, &count);
826 if (count > 1)
827 use_draft = 1;
828 }
829
830 mu_mailbox_get_url (mbox, &url);
831 mu_url_sget_path (url, &path);
832 mu_msgset_foreach_message (msgset, _add_to_mesg_list, (void*)path);
833
834 mu_msgset_free (msgset);
835 }
836
837 /* Usage cases:
838 *
839 * 1. send
840 * a) If Draft-Folder is set: ask whether to use "cur" message from that
841 * folder as a draft;
842 * b) If Draft-Folder is not set: ask whether to use $(Path)/draft;
843 * 2. send -draft
844 * Use $(Path)/draft
845 * 3. send MSG
846 * Use $(Path)/MSG
847 * 4. send -draftmessage MSG
848 * Same as (3)
849 * 5. send -draftfolder DIR
850 * Use "cur" from that folder
851 * 6. send -draftfolder DIR MSG
852 * Use MSG from folder DIR
853 * 7. send -draftfolder DIR -draftmessage MSG
854 * Same as 6.
855 */
856
758 int 857 int
759 main (int argc, char **argv) 858 main (int argc, char **argv)
760 { 859 {
...@@ -768,59 +867,50 @@ main (int argc, char **argv) ...@@ -768,59 +867,50 @@ main (int argc, char **argv)
768 mh_argp_init (); 867 mh_argp_init ();
769 mh_argp_parse (&argc, &argv, 0, options, mh_option, args_doc, doc, 868 mh_argp_parse (&argc, &argv, 0, options, mh_option, args_doc, doc,
770 opt_handler, NULL, &index); 869 opt_handler, NULL, &index);
870 argc -= index;
871 argv += index;
771 872
772 mh_read_aliases (); 873 mh_read_aliases ();
773 /* Process the mtstailor file */ 874 /* Process the mtstailor file */
774 read_mts_profile (); 875 read_mts_profile ();
775 876
776 argc -= index; 877 if (!draftfolder)
777 argv += index;
778
779 if (draftfolder)
780 { 878 {
781 mu_msgset_t msgset; 879 if (mu_list_is_empty (mesg_list) && argc == 0)
782 mu_url_t url; 880 {
783 const char *path; 881 char *dfolder =
882 (!use_draft && use_draftfolder) ?
883 mh_global_profile_get ("Draft-Folder", NULL) : NULL;
784 884
785 mbox = mh_open_folder (draftfolder, MU_STREAM_RDWR|MU_STREAM_CREAT); 885 if (dfolder)
786 mh_msgset_parse (&msgset, mbox, argc, argv, draftmessage); 886 addfolder (dfolder, 0, NULL);
787 mu_mailbox_get_url (mbox, &url); 887 else
788 mu_url_sget_path (url, &path);
789 if ((rc = mu_list_create (&mesg_list)))
790 { 888 {
791 mu_error (_("cannot create message list: %s"), mu_strerror (rc)); 889 char *df = mh_expand_name (mu_folder_directory (), "draft", 0);
890 if (checkdraft (df))
792 exit (1); 891 exit (1);
892 if (!use_draft && !mh_usedraft (df))
893 exit (0);
894 add_file (df);
895 mesg_list_fixup ();
793 } 896 }
794 mu_msgset_foreach_message (msgset, _add_to_mesg_list, (void*)path);
795
796 mu_msgset_free (msgset);
797 } 897 }
798 else 898 else
799 { 899 {
800 int i; 900 while (argc--)
801 901 add_file (*argv++);
802 if (argc == 0) 902 mesg_list_fixup ();
803 {
804 char *xargv[2];
805 struct stat st;
806
807 xargv[0] = mh_draft_name ();
808
809 if (stat (xargv[0], &st))
810 {
811 mu_diag_funcall (MU_DIAG_ERROR, "stat", xargv[0], errno);
812 return 1;
813 } 903 }
814
815 if (!use_draft && !mh_usedraft (xargv[0]))
816 exit (0);
817 xargv[1] = NULL;
818 argv = xargv;
819 argc = 1;
820 } 904 }
821 for (i = 0; i < argc; i++) 905 else
822 if (check_file (argv[i])) 906 {
823 return 1; 907 /* -draftfolder is supplied */
908 draftfolder = mh_expand_name (mu_folder_directory (),
909 draftfolder, 0);
910 use_draft = 1;
911 mesg_list_fixup ();
912 if (mu_list_is_empty (mesg_list) || argc != 0)
913 addfolder (draftfolder, argc, argv);
824 } 914 }
825 915
826 /* Detach from the console if required */ 916 /* Detach from the console if required */
......