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