Implements comp utility.
Showing
1 changed file
with
302 additions
and
0 deletions
mh/comp.c
0 → 100644
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 | } |
-
Please register or sign in to post a comment