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