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