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