Commit 1fd9c8f6 1fd9c8f6cd8c072971a34c7835d2cbf2e1670b52 by Sergey Poznyakoff

Implements comp utility.

1 parent ee136061
Showing 1 changed file with 302 additions and 0 deletions
1 /* GNU Mailutils -- a suite of utilities for electronic mail
2 Copyright (C) 2003 Free Software Foundation, Inc.
3
4 GNU Mailutils is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 2, or (at your option)
7 any later version.
8
9 GNU Mailutils is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
13
14 You should have received a copy of the GNU General Public License
15 along with GNU Mailutils; if not, write to the Free Software
16 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
17
18 /* MH comp command */
19
20 #include <mh.h>
21 #include <sys/types.h>
22 #include <sys/stat.h>
23
24 const char *argp_program_version = "comp (" PACKAGE_STRING ")";
25 static char doc[] = "GNU MH comp";
26 static char args_doc[] = "[msg]";
27
28 #define ARG_NOEDIT 1
29 #define ARG_WHATNOWPROC 2
30 #define ARG_NOWHATNOWPROC 3
31 #define ARG_NODRAFTFOLDER 4
32 #define ARG_FILE 5
33
34 /* GNU options */
35 static struct argp_option options[] = {
36 {"build", 'b', 0, 0,
37 N_("Build the draft and quit immediately.")},
38 {"draftfolder", 'd', N_("FOLDER"), 0,
39 N_("Specify the folder for message drafts")},
40 {"nodraftfolder", ARG_NODRAFTFOLDER, 0, 0,
41 N_("Undo the effect of the last --draftfolder option")},
42 {"draftmessage" , 'm', N_("MSG"), 0,
43 N_("Invoke the draftmessage facility")},
44 {"folder", 'f', N_("FOLDER"), 0, N_("Specify folder to operate upon")},
45 {"file", ARG_FILE, N_("FILE"), 0, N_("Use FILE as the message draft")},
46 {"editor", 'e', N_("PROG"), 0, N_("Set the editor program to use")},
47 {"noedit", ARG_NOEDIT, 0, 0, N_("Suppress the initial edit")},
48 {"form", 'F', N_("FILE"), 0, N_("Read format from given file")},
49 {"whatnowproc", ARG_WHATNOWPROC, N_("PROG"), 0,
50 N_("Set the replacement for whatnow program")},
51 {"use", 'u', N_("BOOL"), OPTION_ARG_OPTIONAL, N_("Use draft file preserved after the last session") },
52 { N_("\nUse -help switch to obtain the list of traditional MH options. "), 0, 0, OPTION_DOC, "" },
53 { 0 }
54 };
55
56 /* Traditional MH options */
57 struct mh_option mh_option[] = {
58 {"build", 1, NULL, },
59 {"file", 2, NULL, MH_OPT_ARG, "draftfile"},
60 {"form", 2, NULL, MH_OPT_ARG, "formatfile"},
61 {"draftfolder", 6, NULL, MH_OPT_ARG, "folder"},
62 {"nodraftfolder", 3, NULL },
63 {"draftmessage", 6, NULL },
64 {"editor", 1, NULL, MH_OPT_ARG, "program"},
65 {"noedit", 3, NULL, },
66 {"whatnowproc", 2, NULL, MH_OPT_ARG, "program"},
67 {"nowhatnowproc", 3, NULL },
68 { 0 }
69 };
70
71 static char *format_str =
72 "To:\n"
73 "cc:\n"
74 "Subject:\n"
75 "--------\n";
76
77 struct mh_whatnow_env wh_env = { 0 };
78 const char *formfile;
79 static int initial_edit = 1;
80 static int build_only = 0; /* --build flag */
81 static int query_mode = 0; /* --query flag */
82 static int use_draft = 0; /* --use flag */
83
84 static int
85 opt_handler (int key, char *arg, void *unused)
86 {
87 char *s;
88
89 switch (key)
90 {
91 case 'b':
92 case ARG_NOWHATNOWPROC:
93 build_only = 1;
94 break;
95
96 case 'd':
97 wh_env.draftfolder = arg;
98 break;
99
100 case 'e':
101 wh_env.editor = arg;
102 break;
103
104 case '+':
105 case 'f':
106 current_folder = arg;
107 break;
108
109 case 'F':
110 formfile = mh_expand_name (MHLIBDIR, arg, 0);
111 break;
112
113 case 'm':
114 wh_env.draftmessage = arg;
115 break;
116
117 case 'u':
118 use_draft = is_true (arg);
119 break;
120
121 case ARG_FILE:
122 wh_env.draftfile = mh_expand_name (NULL, arg, 0);
123 break;
124
125 case ARG_NODRAFTFOLDER:
126 wh_env.draftfolder = NULL;
127 break;
128
129 case ARG_NOEDIT:
130 initial_edit = 0;
131 break;
132
133 case ARG_WHATNOWPROC:
134 mh_error (_("option is not yet implemented"));
135 exit (1);
136
137 default:
138 return 1;
139 }
140 return 0;
141 }
142
143 int
144 check_draft_disposition (struct mh_whatnow_env *wh)
145 {
146 struct stat st;
147 int disp = DISP_REPLACE;
148
149 /* First check if the draft exists */
150 if (stat (wh->draftfile, &st) == 0)
151 {
152 if (use_draft)
153 disp = DISP_USE;
154 else
155 {
156 printf (_("Draft \"%s\" exists (%lu bytes).\n"),
157 wh->draftfile, (unsigned long) st.st_size);
158 disp = mh_disposition (wh->draftfile);
159 }
160 }
161
162 return disp;
163 }
164
165 int
166 copy_message (mailbox_t mbox, size_t n, const char *file)
167 {
168 message_t msg;
169 stream_t in;
170 stream_t out;
171 int rc;
172 size_t size;
173 char *buffer;
174 size_t bufsize, rdsize;
175
176 mailbox_get_message (mbox, n, &msg);
177 message_size (msg, &size);
178
179 for (bufsize = size; bufsize > 0 && (buffer = malloc (bufsize)) == 0;
180 bufsize /= 2)
181 ;
182
183 if (!bufsize)
184 mh_err_memory (1);
185
186 message_get_stream (msg, &in);
187
188 if ((rc = file_stream_create (&out,
189 file, MU_STREAM_RDWR|MU_STREAM_CREAT)) != 0
190 || (rc = stream_open (out)))
191 {
192 mh_error (_("cannot open output file \"%s\": %s"),
193 file, mu_errstring (rc));
194 free (buffer);
195 return 1;
196 }
197
198 while (size > 0
199 && (rc = stream_sequential_read (in, buffer, bufsize, &rdsize)) == 0
200 && rdsize > 0)
201 {
202 if ((rc = stream_sequential_write (out, buffer, rdsize)) != 0)
203 {
204 mh_error (_("error writing to \"%s\": %s"),
205 file, mu_errstring (rc));
206 break;
207 }
208 size -= rdsize;
209 }
210
211 stream_close (out);
212 stream_destroy (&out, stream_get_owner (out));
213
214 return rc;
215 }
216
217 int
218 main (int argc, char **argv)
219 {
220 int index;
221
222 /* Native Language Support */
223 mu_init_nls ();
224
225 mh_argp_parse (argc, argv, options, mh_option, args_doc, doc,
226 opt_handler, NULL, &index);
227
228 if (!wh_env.draftfolder)
229 wh_env.draftfolder = mh_global_profile_get ("Draft-Folder",
230 mu_path_folder_dir);
231
232 wh_env.file = mh_expand_name (wh_env.draftfolder, "comp", 0);
233 if (!wh_env.draftfile)
234 wh_env.draftfile = mh_expand_name (wh_env.draftfolder, "draft", 0);
235
236 switch (check_draft_disposition (&wh_env))
237 {
238 case DISP_QUIT:
239 exit (0);
240
241 case DISP_USE:
242 unlink (wh_env.file);
243 rename (wh_env.draftfile, wh_env.file);
244 break;
245
246 case DISP_REPLACE:
247 unlink (wh_env.draftfile);
248
249 if (index < argc)
250 {
251 static mh_msgset_t msgset;
252 static mailbox_t mbox;
253
254 mbox = mh_open_folder (current_folder, 0);
255 mh_msgset_parse (mbox, &msgset, argc - index, argv + index, "cur");
256 if (msgset.count != 1)
257 {
258 mh_error (_("only one message at a time!"));
259 return 1;
260 }
261 copy_message (mbox, msgset.list[0], wh_env.file);
262 }
263 else if (formfile)
264 {
265 if (mh_file_copy (formfile, wh_env.file) == 0)
266 exit (1);
267 }
268 else
269 {
270 int rc;
271 stream_t stream;
272
273 if ((rc = file_stream_create (&stream,
274 wh_env.file,
275 MU_STREAM_WRITE|MU_STREAM_CREAT)) != 0
276 || (rc = stream_open (stream)))
277 {
278 mh_error (_("cannot open output file \"%s\": %s"),
279 wh_env.file, mu_errstring (rc));
280 exit (1);
281 }
282
283 rc = stream_sequential_write (stream,
284 format_str, strlen (format_str));
285 stream_close (stream);
286 stream_destroy (&stream, stream_get_owner (stream));
287
288 if (rc)
289 {
290 mh_error (_("error writing to \"%s\": %s"),
291 wh_env.file, mu_errstring (rc));
292 exit (1);
293 }
294 }
295 }
296
297 /* Exit immediately if --build is given */
298 if (build_only)
299 return 0;
300
301 return mh_whatnow (&wh_env, initial_edit);
302 }