]> diplodocus.org Git - nmh/blob - uip/repl.c
Just for sanity's sake, double check the "inc" results also with "scan".
[nmh] / uip / repl.c
1
2 /*
3 * repl.c -- reply to a message
4 *
5 * This code is Copyright (c) 2002, by the authors of nmh. See the
6 * COPYRIGHT file in the root directory of the nmh distribution for
7 * complete copyright information.
8 */
9
10 #include <h/mh.h>
11 #include <h/utils.h>
12
13
14 static struct swit switches[] = {
15 #define GROUPSW 0
16 { "group", 0 },
17 #define NGROUPSW 1
18 { "nogroup", 0 },
19 #define ANNOSW 2
20 { "annotate", 0 },
21 #define NANNOSW 3
22 { "noannotate", 0 },
23 #define CCSW 4
24 { "cc all|to|cc|me", 0 },
25 #define NCCSW 5
26 { "nocc type", 0 },
27 #define DFOLDSW 6
28 { "draftfolder +folder", 0 },
29 #define DMSGSW 7
30 { "draftmessage msg", 0 },
31 #define NDFLDSW 8
32 { "nodraftfolder", 0 },
33 #define EDITRSW 9
34 { "editor editor", 0 },
35 #define NEDITSW 10
36 { "noedit", 0 },
37 #define FCCSW 11
38 { "fcc folder", 0 },
39 #define FILTSW 12
40 { "filter filterfile", 0 },
41 #define FORMSW 13
42 { "form formfile", 0 },
43 #define FRMTSW 14
44 { "format", 5 },
45 #define NFRMTSW 15
46 { "noformat", 7 },
47 #define INPLSW 16
48 { "inplace", 0 },
49 #define NINPLSW 17
50 { "noinplace", 0 },
51 #define MIMESW 18
52 { "mime", 0 },
53 #define NMIMESW 19
54 { "nomime", 0 },
55 #define QURYSW 20
56 { "query", 0 },
57 #define NQURYSW 21
58 { "noquery", 0 },
59 #define WHATSW 22
60 { "whatnowproc program", 0 },
61 #define NWHATSW 23
62 { "nowhatnowproc", 0 },
63 #define WIDTHSW 24
64 { "width columns", 0 },
65 #define VERSIONSW 25
66 { "version", 0 },
67 #define HELPSW 26
68 { "help", 0 },
69 #define FILESW 27
70 { "file file", 4 }, /* interface from msh */
71 #define BILDSW 28
72 { "build", 5 }, /* interface from mhe */
73 #define ATFILESW 29
74 { "atfile", 0 },
75 #define NOATFILESW 30
76 { "noatfile", 0 },
77
78 { NULL, 0 }
79 };
80
81 static struct swit ccswitches[] = {
82 #define CTOSW 0
83 { "to", 0 },
84 #define CCCSW 1
85 { "cc", 0 },
86 #define CMESW 2
87 { "me", 0 },
88 #define CALSW 3
89 { "all", 0 },
90 { NULL, 0 }
91 };
92
93 static struct swit aqrnl[] = {
94 #define NOSW 0
95 { "quit", 0 },
96 #define YESW 1
97 { "replace", 0 },
98 #define LISTDSW 2
99 { "list", 0 },
100 #define REFILSW 3
101 { "refile +folder", 0 },
102 #define NEWSW 4
103 { "new", 0 },
104 { NULL, 0 }
105 };
106
107 static struct swit aqrl[] = {
108 { "quit", 0 },
109 { "replace", 0 },
110 { "list", 0 },
111 { "refile +folder", 0 },
112 { NULL, 0 }
113 };
114
115 short ccto = -1; /* global for replsbr */
116 short cccc = -1;
117 short ccme = -1;
118 short querysw = 0;
119
120 short outputlinelen = OUTPUTLINELEN;
121 short groupreply = 0; /* Is this a group reply? */
122
123 int mime = 0; /* include original as MIME part */
124 char *form = NULL; /* form (components) file */
125 char *filter = NULL; /* message filter file */
126 char *fcc = NULL; /* folders to add to Fcc: header */
127
128
129 /*
130 * prototypes
131 */
132 void docc (char *, int);
133
134
135 int
136 main (int argc, char **argv)
137 {
138 int i, isdf = 0;
139 int anot = 0, inplace = 1;
140 int nedit = 0, nwhat = 0;
141 int atfile = 1;
142 char *cp, *cwd, *dp, *maildir, *file = NULL;
143 char *folder = NULL, *msg = NULL, *dfolder = NULL;
144 char *dmsg = NULL, *ed = NULL, drft[BUFSIZ], buf[BUFSIZ];
145 char **argp, **arguments;
146 struct msgs *mp = NULL;
147 struct stat st;
148 FILE *in;
149
150 int buildsw = 0;
151
152 #ifdef LOCALE
153 setlocale(LC_ALL, "");
154 #endif
155 invo_name = r1bindex (argv[0], '/');
156
157 /* read user profile/context */
158 context_read();
159
160 arguments = getarguments (invo_name, argc, argv, 1);
161 argp = arguments;
162
163 while ((cp = *argp++)) {
164 if (*cp == '-') {
165 switch (smatch (++cp, switches)) {
166 case AMBIGSW:
167 ambigsw (cp, switches);
168 done (1);
169 case UNKWNSW:
170 adios (NULL, "-%s unknown", cp);
171
172 case HELPSW:
173 snprintf (buf, sizeof(buf), "%s: [+folder] [msg] [switches]",
174 invo_name);
175 print_help (buf, switches, 1);
176 done (0);
177 case VERSIONSW:
178 print_version(invo_name);
179 done (1);
180
181 case GROUPSW:
182 groupreply++;
183 continue;
184 case NGROUPSW:
185 groupreply = 0;
186 continue;
187
188 case ANNOSW:
189 anot++;
190 continue;
191 case NANNOSW:
192 anot = 0;
193 continue;
194
195 case CCSW:
196 if (!(cp = *argp++) || *cp == '-')
197 adios (NULL, "missing argument to %s", argp[-2]);
198 docc (cp, 1);
199 continue;
200 case NCCSW:
201 if (!(cp = *argp++) || *cp == '-')
202 adios (NULL, "missing argument to %s", argp[-2]);
203 docc (cp, 0);
204 continue;
205
206 case EDITRSW:
207 if (!(ed = *argp++) || *ed == '-')
208 adios (NULL, "missing argument to %s", argp[-2]);
209 nedit = 0;
210 continue;
211 case NEDITSW:
212 nedit++;
213 continue;
214
215 case WHATSW:
216 if (!(whatnowproc = *argp++) || *whatnowproc == '-')
217 adios (NULL, "missing argument to %s", argp[-2]);
218 nwhat = 0;
219 continue;
220 case BILDSW:
221 buildsw++; /* fall... */
222 case NWHATSW:
223 nwhat++;
224 continue;
225
226 case FCCSW:
227 if (!(cp = *argp++) || *cp == '-')
228 adios (NULL, "missing argument to %s", argp[-2]);
229 dp = NULL;
230 if (*cp == '@')
231 cp = dp = path (cp + 1, TSUBCWF);
232 if (fcc)
233 fcc = add (", ", fcc);
234 fcc = add (cp, fcc);
235 if (dp)
236 free (dp);
237 continue;
238
239 case FILESW:
240 if (file)
241 adios (NULL, "only one file at a time!");
242 if (!(cp = *argp++) || *cp == '-')
243 adios (NULL, "missing argument to %s", argp[-2]);
244 file = path (cp, TFILE);
245 continue;
246 case FILTSW:
247 if (!(cp = *argp++) || *cp == '-')
248 adios (NULL, "missing argument to %s", argp[-2]);
249 filter = getcpy (etcpath (cp));
250 mime = 0;
251 continue;
252 case FORMSW:
253 if (!(form = *argp++) || *form == '-')
254 adios (NULL, "missing argument to %s", argp[-2]);
255 continue;
256
257 case FRMTSW:
258 filter = getcpy (etcpath (mhlreply));
259 mime = 0;
260 continue;
261 case NFRMTSW:
262 filter = NULL;
263 continue;
264
265 case INPLSW:
266 inplace++;
267 continue;
268 case NINPLSW:
269 inplace = 0;
270 continue;
271
272 case MIMESW:
273 mime++;
274 filter = NULL;
275 continue;
276 case NMIMESW:
277 mime = 0;
278 continue;
279
280 case QURYSW:
281 querysw++;
282 continue;
283 case NQURYSW:
284 querysw = 0;
285 continue;
286
287 case WIDTHSW:
288 if (!(cp = *argp++) || *cp == '-')
289 adios (NULL, "missing argument to %s", argp[-2]);
290 if ((outputlinelen = atoi (cp)) < 10)
291 adios (NULL, "impossible width %d", outputlinelen);
292 continue;
293
294 case DFOLDSW:
295 if (dfolder)
296 adios (NULL, "only one draft folder at a time!");
297 if (!(cp = *argp++) || *cp == '-')
298 adios (NULL, "missing argument to %s", argp[-2]);
299 dfolder = path (*cp == '+' || *cp == '@' ? cp + 1 : cp,
300 *cp != '@' ? TFOLDER : TSUBCWF);
301 continue;
302 case DMSGSW:
303 if (dmsg)
304 adios (NULL, "only one draft message at a time!");
305 if (!(dmsg = *argp++) || *dmsg == '-')
306 adios (NULL, "missing argument to %s", argp[-2]);
307 continue;
308 case NDFLDSW:
309 dfolder = NULL;
310 isdf = NOTOK;
311 continue;
312
313 case ATFILESW:
314 atfile++;
315 continue;
316 case NOATFILESW:
317 atfile = 0;
318 continue;
319 }
320 }
321 if (*cp == '+' || *cp == '@') {
322 if (folder)
323 adios (NULL, "only one folder at a time!");
324 else
325 folder = pluspath (cp);
326 } else {
327 if (msg)
328 adios (NULL, "only one message at a time!");
329 else
330 msg = cp;
331 }
332 }
333
334 if (ccto == -1)
335 ccto = groupreply;
336 if (cccc == -1)
337 cccc = groupreply;
338 if (ccme == -1)
339 ccme = groupreply;
340
341 cwd = getcpy (pwd ());
342
343 if (!context_find ("path"))
344 free (path ("./", TFOLDER));
345 if (file && (msg || folder))
346 adios (NULL, "can't mix files and folders/msgs");
347
348 try_it_again:
349
350 strncpy (drft, buildsw ? m_maildir ("reply")
351 : m_draft (dfolder, NULL, NOUSE, &isdf), sizeof(drft));
352
353 /* Check if a draft exists */
354 if (!buildsw && stat (drft, &st) != NOTOK) {
355 printf ("Draft \"%s\" exists (%ld bytes).", drft, (long) st.st_size);
356 for (i = LISTDSW; i != YESW;) {
357 if (!(argp = getans ("\nDisposition? ", isdf ? aqrnl : aqrl)))
358 done (1);
359 switch (i = smatch (*argp, isdf ? aqrnl : aqrl)) {
360 case NOSW:
361 done (0);
362 case NEWSW:
363 dmsg = NULL;
364 goto try_it_again;
365 case YESW:
366 break;
367 case LISTDSW:
368 showfile (++argp, drft);
369 break;
370 case REFILSW:
371 if (refile (++argp, drft) == 0)
372 i = YESW;
373 break;
374 default:
375 advise (NULL, "say what?");
376 break;
377 }
378 }
379 }
380
381 if (file) {
382 /*
383 * We are replying to a file.
384 */
385 anot = 0; /* we don't want to annotate a file */
386 } else {
387 /*
388 * We are replying to a message.
389 */
390 if (!msg)
391 msg = "cur";
392 if (!folder)
393 folder = getfolder (1);
394 maildir = m_maildir (folder);
395
396 if (chdir (maildir) == NOTOK)
397 adios (maildir, "unable to change directory to");
398
399 /* read folder and create message structure */
400 if (!(mp = folder_read (folder)))
401 adios (NULL, "unable to read folder %s", folder);
402
403 /* check for empty folder */
404 if (mp->nummsg == 0)
405 adios (NULL, "no messages in %s", folder);
406
407 /* parse the message range/sequence/name and set SELECTED */
408 if (!m_convert (mp, msg))
409 done (1);
410 seq_setprev (mp); /* set the previous-sequence */
411
412 if (mp->numsel > 1)
413 adios (NULL, "only one message at a time!");
414
415 context_replace (pfolder, folder); /* update current folder */
416 seq_setcur (mp, mp->lowsel); /* update current message */
417 seq_save (mp); /* synchronize sequences */
418 context_save (); /* save the context file */
419 }
420
421 msg = file ? file : getcpy (m_name (mp->lowsel));
422
423 if ((in = fopen (msg, "r")) == NULL)
424 adios (msg, "unable to open");
425
426 /* find form (components) file */
427 if (!form) {
428 if (groupreply)
429 form = etcpath (replgroupcomps);
430 else
431 form = etcpath (replcomps);
432 }
433
434 replout (in, msg, drft, mp, outputlinelen, mime, form, filter, fcc);
435 fclose (in);
436
437 if (nwhat)
438 done (0);
439 what_now (ed, nedit, NOUSE, drft, atfile ? msg : NULL, 0, mp,
440 anot ? "Replied" : NULL, inplace, cwd);
441 done (1);
442 return 1;
443 }
444
445 void
446 docc (char *cp, int ccflag)
447 {
448 switch (smatch (cp, ccswitches)) {
449 case AMBIGSW:
450 ambigsw (cp, ccswitches);
451 done (1);
452 case UNKWNSW:
453 adios (NULL, "-%scc %s unknown", ccflag ? "" : "no", cp);
454
455 case CTOSW:
456 ccto = ccflag;
457 break;
458
459 case CCCSW:
460 cccc = ccflag;
461 break;
462
463 case CMESW:
464 ccme = ccflag;
465 break;
466
467 case CALSW:
468 ccto = cccc = ccme = ccflag;
469 break;
470 }
471 }