]> diplodocus.org Git - nmh/blob - uip/comp.c
Fixed three LC_ALL settings:
[nmh] / uip / comp.c
1
2 /*
3 * comp.c -- compose 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 #include <h/fmt_scan.h>
13 #include <fcntl.h>
14
15 #define COMP_SWITCHES \
16 X("draftfolder +folder", 0, DFOLDSW) \
17 X("draftmessage msg", 0, DMSGSW) \
18 X("nodraftfolder", 0, NDFLDSW) \
19 X("editor editor", 0, EDITRSW) \
20 X("noedit", 0, NEDITSW) \
21 X("file file", 0, FILESW) \
22 X("form formfile", 0, FORMSW) \
23 X("use", 0, USESW) \
24 X("nouse", 0, NUSESW) \
25 X("whatnowproc program", 0, WHATSW) \
26 X("nowhatnowproc", 0, NWHATSW) \
27 X("build", 5, BILDSW) \
28 X("version", 0, VERSIONSW) \
29 X("help", 0, HELPSW) \
30 X("to address", 0, TOSW) \
31 X("cc address", 0, CCSW) \
32 X("from address", 0, FROMSW) \
33 X("fcc mailbox", 0, FCCSW) \
34 X("width colums", 0, WIDTHSW) \
35 X("subject text", 0, SUBJECTSW) \
36
37 #define X(sw, minchars, id) id,
38 DEFINE_SWITCH_ENUM(COMP);
39 #undef X
40
41 #define X(sw, minchars, id) { sw, minchars, id },
42 DEFINE_SWITCH_ARRAY(COMP, switches);
43 #undef X
44
45 #define DISPO_SWITCHES \
46 X("quit", 0, NOSW) \
47 X("replace", 0, YESW) \
48 X("use", 0, USELSW) \
49 X("list", 0, LISTDSW) \
50 X("refile +folder", 0, REFILSW) \
51 X("new", 0, NEWSW) \
52
53 #define X(sw, minchars, id) id,
54 DEFINE_SWITCH_ENUM(DISPO);
55 #undef X
56
57 #define X(sw, minchars, id) { sw, minchars, id },
58 DEFINE_SWITCH_ARRAY(DISPO, aqrunl);
59 #undef X
60
61 static struct swit aqrul[] = {
62 { "quit", 0, NOSW },
63 { "replace", 0, YESW },
64 { "use", 0, USELSW },
65 { "list", 0, LISTDSW },
66 { "refile", 0, REFILSW },
67 { NULL, 0, 0 }
68 };
69
70 int
71 main (int argc, char **argv)
72 {
73 int use = NOUSE, nedit = 0, nwhat = 0, build = 0;
74 int i, in = NOTOK, isdf = 0, out, dat[5], format_len = 0;
75 int outputlinelen = OUTPUTLINELEN;
76 char *cp, *cwd, *maildir, *dfolder = NULL;
77 char *ed = NULL, *file = NULL, *form = NULL;
78 char *folder = NULL, *msg = NULL, buf[BUFSIZ];
79 char *to = NULL, *from = NULL, *cc = NULL, *fcc = NULL, *dp;
80 char *subject = NULL;
81 char drft[BUFSIZ], **argp, **arguments;
82 struct msgs *mp = NULL;
83 struct format *fmt;
84 struct stat st;
85
86 setlocale(LC_ALL, "");
87 invo_name = r1bindex (argv[0], '/');
88
89 /* read user profile/context */
90 context_read();
91
92 arguments = getarguments (invo_name, argc, argv, 1);
93 argp = arguments;
94
95 while ((cp = *argp++)) {
96 if (*cp == '-') {
97 switch (smatch (++cp, switches)) {
98 case AMBIGSW:
99 ambigsw (cp, switches);
100 done (1);
101 case UNKWNSW:
102 adios (NULL, "-%s unknown", cp);
103
104 case HELPSW:
105 snprintf (buf, sizeof(buf), "%s [+folder] [msg] [switches]",
106 invo_name);
107 print_help (buf, switches, 1);
108 done (0);
109 case VERSIONSW:
110 print_version(invo_name);
111 done (0);
112
113 case EDITRSW:
114 if (!(ed = *argp++) || *ed == '-')
115 adios (NULL, "missing argument to %s", argp[-2]);
116 nedit = 0;
117 continue;
118 case NEDITSW:
119 nedit++;
120 continue;
121
122 case WHATSW:
123 if (!(whatnowproc = *argp++) || *whatnowproc == '-')
124 adios (NULL, "missing argument to %s", argp[-2]);
125 nwhat = 0;
126 continue;
127
128 case BILDSW:
129 build++;
130 /* fall through */
131 case NWHATSW:
132 nwhat++;
133 continue;
134
135 case FORMSW:
136 if (!(form = *argp++) || *form == '-')
137 adios (NULL, "missing argument to %s", argp[-2]);
138 continue;
139
140 case USESW:
141 use++;
142 continue;
143 case NUSESW:
144 use = NOUSE;
145 continue;
146
147 case FILESW: /* compatibility */
148 if (file)
149 adios (NULL, "only one file at a time!");
150 if (!(file = *argp++) || *file == '-')
151 adios (NULL, "missing argument to %s", argp[-2]);
152 isdf = NOTOK;
153 continue;
154
155 case DFOLDSW:
156 if (dfolder)
157 adios (NULL, "only one draft folder at a time!");
158 if (!(cp = *argp++) || *cp == '-')
159 adios (NULL, "missing argument to %s", argp[-2]);
160 dfolder = path (*cp == '+' || *cp == '@' ? cp + 1 : cp,
161 *cp != '@' ? TFOLDER : TSUBCWF);
162 continue;
163 case DMSGSW:
164 if (file)
165 adios (NULL, "only one draft message at a time!");
166 if (!(file = *argp++) || *file == '-')
167 adios (NULL, "missing argument to %s", argp[-2]);
168 continue;
169 case NDFLDSW:
170 dfolder = NULL;
171 isdf = NOTOK;
172 continue;
173
174 case TOSW:
175 if (!(cp = *argp++) || *cp == '-')
176 adios (NULL, "missing argument to %s", argp[-2]);
177 to = addlist(to, cp);
178 continue;
179
180 case CCSW:
181 if (!(cp = *argp++) || *cp == '-')
182 adios (NULL, "missing argument to %s", argp[-2]);
183 cc = addlist(cc, cp);
184 continue;
185
186 case FROMSW:
187 if (!(cp = *argp++) || *cp == '-')
188 adios (NULL, "missing argument to %s", argp[-2]);
189 from = addlist(from, cp);
190 continue;
191
192 case FCCSW:
193 if (!(cp = *argp++) || *cp == '-')
194 adios (NULL, "missing argument to %s", argp[-2]);
195 dp = NULL;
196 if (*cp == '@')
197 cp = dp = path(cp + 1, TSUBCWF);
198 fcc = addlist(fcc, cp);
199 if (dp)
200 free(dp);
201 continue;
202
203 case WIDTHSW:
204 if (!(cp = *argp++) || *cp == '-')
205 adios (NULL, "missing argument to %s", argp[-2]);
206 if ((outputlinelen = atoi(cp)) < 10)
207 adios (NULL, "impossible width %d", outputlinelen);
208 continue;
209
210 case SUBJECTSW:
211 if (!(cp = *argp++) || *cp == '-')
212 adios (NULL, "missing argument to %s", argp[-2]);
213 subject = cp;
214 continue;
215 }
216 }
217 if (*cp == '+' || *cp == '@') {
218 if (folder)
219 adios (NULL, "only one folder at a time!");
220 else
221 folder = pluspath (cp);
222 } else {
223 if (msg)
224 adios (NULL, "only one message at a time!");
225 else
226 msg = cp;
227 }
228 }
229
230 cwd = getcpy (pwd ());
231
232 if (!context_find ("path"))
233 free (path ("./", TFOLDER));
234
235 /*
236 * Check if we are using a draft folder
237 * and have specified a message in it.
238 */
239 if ((dfolder || context_find ("Draft-Folder")) && !folder && msg && !file) {
240 file = msg;
241 msg = NULL;
242 }
243 if (form && (folder || msg))
244 adios (NULL, "can't mix forms and folders/msgs");
245
246 cp = NULL;
247
248 if (folder || msg) {
249 /*
250 * Use a message as the "form" for the new message.
251 */
252 if (!msg)
253 msg = "cur";
254 if (!folder)
255 folder = getfolder (1);
256 maildir = m_maildir (folder);
257
258 if (chdir (maildir) == NOTOK)
259 adios (maildir, "unable to change directory to");
260
261 /* read folder and create message structure */
262 if (!(mp = folder_read (folder, 1)))
263 adios (NULL, "unable to read folder %s", folder);
264
265 /* check for empty folder */
266 if (mp->nummsg == 0)
267 adios (NULL, "no messages in %s", folder);
268
269 /* parse the message range/sequence/name and set SELECTED */
270 if (!m_convert (mp, msg))
271 done (1);
272 seq_setprev (mp); /* set the previous-sequence */
273 seq_save (mp);
274
275 if (mp->numsel > 1)
276 adios (NULL, "only one message at a time!");
277
278 if ((in = open (form = getcpy (m_name (mp->lowsel)), O_RDONLY)) == NOTOK)
279 adios (form, "unable to open message");
280 } else {
281 struct comp *cptr;
282
283 if (! form)
284 form = components;
285
286 cp = new_fs(form, NULL, NULL);
287 format_len = strlen(cp);
288 fmt_compile(cp, &fmt, 1);
289
290 /*
291 * Set up any components that were fed to us on the command line
292 */
293
294 if (from) {
295 cptr = fmt_findcomp("from");
296 if (cptr)
297 cptr->c_text = from;
298 }
299 if (to) {
300 cptr = fmt_findcomp("to");
301 if (cptr)
302 cptr->c_text = to;
303 }
304 if (cc) {
305 cptr = fmt_findcomp("cc");
306 if (cptr)
307 cptr->c_text = cc;
308 }
309 if (fcc) {
310 cptr = fmt_findcomp("fcc");
311 if (cptr)
312 cptr->c_text = fcc;
313 }
314 if (subject) {
315 cptr = fmt_findcomp("subject");
316 if (cptr)
317 cptr->c_text = subject;
318 }
319 }
320
321 try_it_again:
322 strncpy (drft, build ? m_maildir ("draft")
323 : m_draft (dfolder, file, use, &isdf), sizeof(drft));
324
325 /*
326 * Check if we have an existing draft
327 */
328 if (!build && (out = open (drft, O_RDONLY)) != NOTOK) {
329 i = fdcompare (in, out);
330 close (out);
331
332 /*
333 * If we have given -use flag, or if the
334 * draft is just the same as the components
335 * file, then no need to ask any questions.
336 */
337 if (use || i)
338 goto edit_it;
339
340 if (stat (drft, &st) == NOTOK)
341 adios (drft, "unable to stat");
342 printf ("Draft \"%s\" exists (%ld bytes).", drft, (long) st.st_size);
343 for (i = LISTDSW; i != YESW;) {
344 if (!(argp = getans ("\nDisposition? ", isdf ? aqrunl : aqrul)))
345 done (1);
346 switch (i = smatch (*argp, isdf ? aqrunl : aqrul)) {
347 case NOSW:
348 done (0);
349 case NEWSW:
350 file = NULL;
351 use = NOUSE;
352 goto try_it_again;
353 case YESW:
354 break;
355 case USELSW:
356 use++;
357 goto edit_it;
358 case LISTDSW:
359 showfile (++argp, drft);
360 break;
361 case REFILSW:
362 if (refile (++argp, drft) == 0)
363 i = YESW;
364 break;
365 default:
366 advise (NULL, "say what?");
367 break;
368 }
369 }
370 } else {
371 if (use)
372 adios (drft, "unable to open");
373 }
374
375 if ((out = creat (drft, m_gmprot ())) == NOTOK)
376 adios (drft, "unable to create");
377 if (cp) {
378 char *scanl;
379
380 i = format_len + 1024;
381 scanl = mh_xmalloc((size_t) i + 2);
382 dat[0] = 0;
383 dat[1] = 0;
384 dat[2] = 0;
385 dat[3] = outputlinelen;
386 dat[4] = 0;
387 fmt_scan(fmt, scanl, i + 1, i, dat, NULL);
388 write(out, scanl, strlen(scanl));
389 free(scanl);
390 } else {
391 cpydata (in, out, form, drft);
392 close (in);
393 }
394 close (out);
395
396 edit_it:
397 context_save (); /* save the context file */
398
399 if (nwhat)
400 done (0);
401 what_now (ed, nedit, use, drft, NULL, 0, NULLMP, NULL, 0, cwd, 0);
402 done (1);
403 return 1;
404 }