]> diplodocus.org Git - nmh/blob - uip/dist.c
Added context_find_prefix().
[nmh] / uip / dist.c
1
2 /*
3 * dist.c -- re-distribute 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 <fcntl.h>
13
14 #define DIST_SWITCHES \
15 X("annotate", 0, ANNOSW) \
16 X("noannotate", 0, NANNOSW) \
17 X("draftfolder +folder", 0, DFOLDSW) \
18 X("draftmessage msg", 0, DMSGSW) \
19 X("nodraftfolder", 0, NDFLDSW) \
20 X("editor editor", 0, EDITRSW) \
21 X("noedit", 0, NEDITSW) \
22 X("form formfile", 0, FORMSW) \
23 X("inplace", 0, INPLSW) \
24 X("noinplace", 0, NINPLSW) \
25 X("whatnowproc program", 0, WHATSW) \
26 X("nowhatnowproc", 0, NWHATSW) \
27 X("version", 0, VERSIONSW) \
28 X("help", 0, HELPSW) \
29 X("file file", -4, FILESW) \
30 X("from address", 0, FROMSW) \
31 X("to address", 0, TOSW) \
32 X("cc address", 0, CCSW) \
33 X("fcc mailbox", 0, FCCSW) \
34 X("width columns", 0, WIDTHSW) \
35 X("atfile", 0, ATFILESW) \
36 X("noatfile", 0, NOATFILESW) \
37
38 #define X(sw, minchars, id) id,
39 DEFINE_SWITCH_ENUM(DIST);
40 #undef X
41
42 #define X(sw, minchars, id) { sw, minchars, id },
43 DEFINE_SWITCH_ARRAY(DIST, switches);
44 #undef X
45
46 #define DISPO_SWITCHES \
47 X("quit", 0, NOSW) \
48 X("replace", 0, YESW) \
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, aqrnl);
59 #undef X
60
61
62 static struct swit aqrl[] = {
63 { "quit", 0, NOSW },
64 { "replace", 0, YESW },
65 { "list", 0, LISTDSW },
66 { "refile +folder", 0, REFILSW },
67 { NULL, 0, 0 }
68 };
69
70
71 int
72 main (int argc, char **argv)
73 {
74 int anot = 0, inplace = 1, nedit = 0;
75 int nwhat = 0, i, in, isdf = 0, out;
76 int outputlinelen = OUTPUTLINELEN;
77 int dat[5], atfile = 0;
78 char *cp, *cwd, *maildir, *msgnam, *dfolder = NULL;
79 char *dmsg = NULL, *ed = NULL, *file = NULL, *folder = NULL;
80 char *form = NULL, *msg = NULL, buf[BUFSIZ], drft[BUFSIZ];
81 char *from = NULL, *to = NULL, *cc = NULL, *fcc = NULL;
82 char **argp, **arguments;
83 struct msgs *mp = NULL;
84 struct stat st;
85
86 if (nmh_init(argv[0], 1)) { return 1; }
87
88 arguments = getarguments (invo_name, argc, argv, 1);
89 argp = arguments;
90
91 while ((cp = *argp++)) {
92 if (*cp == '-') {
93 switch (smatch (++cp, switches)) {
94 case AMBIGSW:
95 ambigsw (cp, switches);
96 done (1);
97 case UNKWNSW:
98 adios (NULL, "-%s unknown", cp);
99
100 case HELPSW:
101 snprintf (buf, sizeof(buf), "%s [+folder] [msg] [switches]",
102 invo_name);
103 print_help (buf, switches, 1);
104 done (0);
105 case VERSIONSW:
106 print_version(invo_name);
107 done (0);
108
109 case ANNOSW:
110 anot++;
111 continue;
112 case NANNOSW:
113 anot = 0;
114 continue;
115
116 case EDITRSW:
117 if (!(ed = *argp++) || *ed == '-')
118 adios (NULL, "missing argument to %s", argp[-2]);
119 nedit = 0;
120 continue;
121 case NEDITSW:
122 nedit++;
123 continue;
124
125 case WHATSW:
126 if (!(whatnowproc = *argp++) || *whatnowproc == '-')
127 adios (NULL, "missing argument to %s", argp[-2]);
128 nwhat = 0;
129 continue;
130 case NWHATSW:
131 nwhat++;
132 continue;
133
134 case FILESW:
135 if (file)
136 adios (NULL, "only one file at a time!");
137 if (!(cp = *argp++) || *cp == '-')
138 adios (NULL, "missing argument to %s", argp[-2]);
139 file = path (cp, TFILE);
140 continue;
141 case FORMSW:
142 if (!(form = *argp++) || *form == '-')
143 adios (NULL, "missing argument to %s", argp[-2]);
144 continue;
145
146 case INPLSW:
147 inplace++;
148 continue;
149 case NINPLSW:
150 inplace = 0;
151 continue;
152
153 case DFOLDSW:
154 if (dfolder)
155 adios (NULL, "only one draft folder at a time!");
156 if (!(cp = *argp++) || *cp == '-')
157 adios (NULL, "missing argument to %s", argp[-2]);
158 dfolder = path (*cp == '+' || *cp == '@' ? cp + 1 : cp,
159 *cp != '@' ? TFOLDER : TSUBCWF);
160 continue;
161 case DMSGSW:
162 if (dmsg)
163 adios (NULL, "only one draft message at a time!");
164 if (!(dmsg = *argp++) || *dmsg == '-')
165 adios (NULL, "missing argument to %s", argp[-2]);
166 continue;
167 case NDFLDSW:
168 dfolder = NULL;
169 isdf = NOTOK;
170 continue;
171
172 case FROMSW:
173 if (!(cp = *argp++) || *cp == '-')
174 adios (NULL, "missing argument to %s", argp[-2]);
175 from = addlist(from, cp);
176 continue;
177 case TOSW:
178 if (!(cp = *argp++) || *cp == '-')
179 adios (NULL, "missing argument to %s", argp[-2]);
180 to = addlist(to, cp);
181 continue;
182 case CCSW:
183 if (!(cp = *argp++) || *cp == '-')
184 adios (NULL, "missing argument to %s", argp[-2]);
185 cc = addlist(cc, cp);
186 continue;
187 case FCCSW:
188 if (!(cp = *argp++) || *cp == '-')
189 adios (NULL, "missing argument to %s", argp[-2]);
190 fcc = addlist(fcc, cp);
191 continue;
192
193 case WIDTHSW:
194 if (!(cp = *argp++) || *cp == '-')
195 adios (NULL, "missing argument to %s", argp[-2]);
196 if ((outputlinelen = atoi(cp)) < 10)
197 adios (NULL, "impossible width %d", outputlinelen);
198 continue;
199
200 case ATFILESW:
201 atfile++;
202 continue;
203 case NOATFILESW:
204 atfile = 0;
205 continue;
206 }
207 }
208 if (*cp == '+' || *cp == '@') {
209 if (folder)
210 adios (NULL, "only one folder at a time!");
211 else
212 folder = pluspath (cp);
213 } else {
214 if (msg)
215 adios (NULL, "only one message at a time!");
216 else
217 msg = cp;
218 }
219 }
220
221 cwd = getcpy (pwd ());
222
223 if (!context_find ("path"))
224 free (path ("./", TFOLDER));
225 if (file && (msg || folder))
226 adios (NULL, "can't mix files and folders/msgs");
227
228 try_it_again:
229 strncpy (drft, m_draft (dfolder, dmsg, NOUSE, &isdf), sizeof(drft));
230
231 /* Check if draft already exists */
232 if (stat (drft, &st) != NOTOK) {
233 printf ("Draft \"%s\" exists (%ld bytes).", drft, (long) st.st_size);
234 for (i = LISTDSW; i != YESW;) {
235 if (!(argp = read_switch_multiword ("\nDisposition? ",
236 isdf ? aqrnl : aqrl)))
237 done (1);
238 switch (i = smatch (*argp, isdf ? aqrnl : aqrl)) {
239 case NOSW:
240 done (0);
241 case NEWSW:
242 dmsg = NULL;
243 goto try_it_again;
244 case YESW:
245 break;
246 case LISTDSW:
247 showfile (++argp, drft);
248 break;
249 case REFILSW:
250 if (refile (++argp, drft) == 0)
251 i = YESW;
252 break;
253 default:
254 advise (NULL, "say what?");
255 break;
256 }
257 }
258 }
259
260 if (file) {
261 /*
262 * Dist a file
263 */
264 anot = 0; /* don't want to annotate a file */
265 } else {
266 /*
267 * Dist a message
268 */
269 if (!msg)
270 msg = "cur";
271 if (!folder)
272 folder = getfolder (1);
273 maildir = m_maildir (folder);
274
275 if (chdir (maildir) == NOTOK)
276 adios (maildir, "unable to change directory to");
277
278 /* read folder and create message structure */
279 if (!(mp = folder_read (folder, 1)))
280 adios (NULL, "unable to read folder %s", folder);
281
282 /* check for empty folder */
283 if (mp->nummsg == 0)
284 adios (NULL, "no messages in %s", folder);
285
286 /* parse the message range/sequence/name and set SELECTED */
287 if (!m_convert (mp, msg))
288 done (1);
289 seq_setprev (mp); /* set the previous-sequence */
290
291 if (mp->numsel > 1)
292 adios (NULL, "only one message at a time!");
293 }
294
295 msgnam = file ? file : getcpy (m_name (mp->lowsel));
296
297 dat[0] = mp ? mp->lowsel : 0;
298 dat[1] = 0;
299 dat[2] = 0;
300 dat[3] = outputlinelen;
301 dat[4] = 0;
302
303 if (!form)
304 form = distcomps;
305
306 in = build_form(form, NULL, dat, from, to, cc, fcc, NULL, msgnam);
307
308 if ((out = creat (drft, m_gmprot ())) == NOTOK)
309 adios (drft, "unable to create");
310
311 cpydata (in, out, form, drft);
312 close (in);
313 close (out);
314
315 if ((in = open (msgnam, O_RDONLY)) == NOTOK)
316 adios (msgnam, "unable to open message");
317
318 if (!file) {
319 context_replace (pfolder, folder);/* update current folder */
320 seq_setcur (mp, mp->lowsel); /* update current message */
321 seq_save (mp); /* synchronize sequences */
322 context_save (); /* save the context file */
323 }
324
325 if (nwhat)
326 done (0);
327 what_now (ed, nedit, NOUSE, drft, msgnam, 1, mp, anot ? "Resent" : NULL,
328 inplace, cwd, atfile);
329 done (1);
330 return 1;
331 }