]> diplodocus.org Git - nmh/blob - docs/historical/mh-6.8.5/uip/refile.c
sbr/mts.c: Delete mmdlm2; use same-valued mmdlm1 instead.
[nmh] / docs / historical / mh-6.8.5 / uip / refile.c
1 /* refile.c - file messages away */
2 #ifndef lint
3 static char ident[] = "@(#)$Id: refile.c,v 1.10 1992/12/15 00:20:22 jromine Exp $";
4 #endif /* lint */
5
6 #include "../h/mh.h"
7 #include <errno.h>
8 #include <stdio.h>
9 #include <sys/types.h>
10 #include <sys/stat.h>
11 #ifdef LOCALE
12 #include <locale.h>
13 #endif
14
15 /* \f */
16
17 static struct swit switches[] = {
18 #define DRAFTSW 0
19 "draft", 0,
20
21 #define LINKSW 1
22 "link", 0,
23 #define NLINKSW 2
24 "nolink", 0,
25
26 #define PRESSW 3
27 "preserve", 0,
28 #define NPRESSW 4
29 "nopreserve", 0,
30
31 #define SRCSW 5
32 "src +folder", 0,
33
34 #define FILESW 6
35 "file file", 0,
36
37 #define RPROCSW 7
38 "rmmproc program", 0,
39 #define NRPRCSW 8
40 "normmproc", 0,
41
42 #define HELPSW 9
43 "help", 4,
44
45 NULL, 0
46 };
47
48 /* \f */
49
50 extern int errno;
51
52
53 static char maildir[BUFSIZ];
54
55
56 struct st_fold {
57 char *f_name;
58 struct msgs *f_mp;
59 };
60
61 static opnfolds(), clsfolds(), removeit();
62 /* \f */
63
64 /* ARGSUSED */
65
66 main (argc, argv)
67 int argc;
68 char **argv;
69 {
70 int linkf = 0,
71 prsrvf = 0,
72 filep = 0,
73 foldp = 0,
74 msgp = 0,
75 isdf = 0,
76 i,
77 msgnum;
78 char *cp,
79 *folder = NULL,
80 buf[100],
81 **ap,
82 **argp,
83 *arguments[MAXARGS],
84 *filevec[NFOLDERS + 2],
85 **files = &filevec[1], /* leave room for removeit:vec[0] */
86 *msgs[MAXARGS];
87 struct st_fold folders[NFOLDERS + 1];
88 struct msgs *mp;
89
90 #ifdef LOCALE
91 setlocale(LC_ALL, "");
92 #endif
93 invo_name = r1bindex (argv[0], '/');
94 if ((cp = m_find (invo_name)) != NULL) {
95 ap = brkstring (cp = getcpy (cp), " ", "\n");
96 ap = copyip (ap, arguments);
97 }
98 else
99 ap = arguments;
100 (void) copyip (argv + 1, ap);
101 argp = arguments;
102
103 /* \f */
104
105 while (cp = *argp++) {
106 if (*cp == '-')
107 switch (smatch (++cp, switches)) {
108 case AMBIGSW:
109 ambigsw (cp, switches);
110 done (1);
111 case UNKWNSW:
112 adios (NULLCP, "-%s unknown\n", cp);
113 case HELPSW:
114 (void) sprintf (buf, "%s [msgs] [switches] +folder ...",
115 invo_name);
116 help (buf, switches);
117 done (1);
118
119 case LINKSW:
120 linkf++;
121 continue;
122 case NLINKSW:
123 linkf = 0;
124 continue;
125
126 case PRESSW:
127 prsrvf++;
128 continue;
129 case NPRESSW:
130 prsrvf = 0;
131 continue;
132
133 case SRCSW:
134 if (folder)
135 adios (NULLCP, "only one source folder at a time!");
136 if (!(cp = *argp++) || *cp == '-')
137 adios (NULLCP, "missing argument to %s", argp[-2]);
138 folder = path (*cp == '+' || *cp == '@' ? cp + 1 : cp,
139 *cp != '@' ? TFOLDER : TSUBCWF);
140 continue;
141 case DRAFTSW:
142 if (filep > NFOLDERS)
143 adios (NULLCP, "only %d files allowed!", NFOLDERS);
144 isdf = 0;
145 files[filep++] = getcpy (m_draft (NULLCP, NULLCP, 1, &isdf));
146 continue;
147 case FILESW:
148 if (filep > NFOLDERS)
149 adios (NULLCP, "only %d files allowed!", NFOLDERS);
150 if (!(cp = *argp++) || *cp == '-')
151 adios (NULLCP, "missing argument to %s", argp[-2]);
152 files[filep++] = path (cp, TFILE);
153 continue;
154
155 case RPROCSW:
156 if (!(rmmproc = *argp++) || *rmmproc == '-')
157 adios (NULLCP, "missing argument to %s", argp[-2]);
158 continue;
159 case NRPRCSW:
160 rmmproc = (char *)0;
161 continue;
162 }
163 if (*cp == '+' || *cp == '@') {
164 if (foldp > NFOLDERS)
165 adios (NULLCP, "only %d folders allowed!", NFOLDERS);
166 folders[foldp++].f_name =
167 path (cp + 1, *cp == '+' ? TFOLDER : TSUBCWF);
168 }
169 else
170 msgs[msgp++] = cp;
171 }
172
173 /* \f */
174
175 if (!m_find ("path"))
176 free (path ("./", TFOLDER));
177 if (foldp == 0)
178 adios (NULLCP, "no folder specified");
179
180 #ifdef WHATNOW
181 if (!msgp && !foldp && !filep && (cp = getenv ("mhdraft")) && *cp)
182 files[filep++] = cp;
183 #endif /* WHATNOW */
184
185 if (filep > 0) {
186 if (folder || msgp)
187 adios (NULLCP, "use -file or some messages, not both");
188 opnfolds (folders, foldp);
189 for (i = 0; i < filep; i++)
190 if (m_file (files[i], folders, foldp, prsrvf))
191 done (1);
192 if (!linkf)
193 removeit (NULLMP, filep, filevec);
194 done (0);
195 }
196
197 if (!msgp)
198 msgs[msgp++] = "cur";
199 if (!folder)
200 folder = m_getfolder ();
201 (void) strcpy (maildir, m_maildir (folder));
202
203 if (chdir (maildir) == NOTOK)
204 adios (maildir, "unable to change directory to");
205 if (!(mp = m_gmsg (folder)))
206 adios (NULLCP, "unable to read folder %s", folder);
207 if (mp -> hghmsg == 0)
208 adios (NULLCP, "no messages in %s", folder);
209
210 for (msgnum = 0; msgnum < msgp; msgnum++)
211 if (!m_convert (mp, msgs[msgnum]))
212 done (1);
213 m_setseq (mp);
214
215 opnfolds (folders, foldp);
216 for (msgnum = mp -> lowsel; msgnum <= mp -> hghsel; msgnum++)
217 if (mp -> msgstats[msgnum] & SELECTED) {
218 cp = getcpy (m_name (msgnum));
219 if (m_file (cp, folders, foldp, prsrvf))
220 done (1);
221 free (cp);
222 if (!linkf) {
223 #ifdef notdef
224 mp -> msgstats[msgnum] |= DELETED;
225 #endif /* notdef */
226 mp -> msgstats[msgnum] &= ~EXISTS;
227 }
228 }
229 if (!linkf)
230 mp -> msgflags |= SEQMOD;
231 clsfolds (folders, foldp);
232
233 m_replace (pfolder, folder);
234 if (mp -> hghsel != mp -> curmsg
235 && (mp -> numsel != mp -> nummsg || linkf))
236 m_setcur (mp, mp -> hghsel);
237 m_sync (mp);
238 m_update ();
239
240 if (!linkf)
241 removeit (mp, filep, filevec);
242
243 done (0);
244 }
245
246 /* \f */
247
248 static opnfolds (folders, nfolders)
249 register struct st_fold *folders;
250 int nfolders;
251 {
252 register char *cp;
253 char nmaildir[BUFSIZ];
254 register struct st_fold *fp,
255 *ep;
256 register struct msgs *mp;
257 struct stat st;
258
259 for (ep = (fp = folders) + nfolders; fp < ep; fp++) {
260 (void) chdir (m_maildir (""));
261 (void) strcpy (nmaildir, m_maildir (fp -> f_name));
262
263 if (stat (nmaildir, &st) == NOTOK) {
264 if (errno != ENOENT)
265 adios (nmaildir, "error on folder");
266 cp = concat ("Create folder \"", nmaildir, "\"? ", NULLCP);
267 if (!getanswer (cp))
268 done (1);
269 free (cp);
270 if (!makedir (nmaildir))
271 adios (NULLCP, "unable to create folder %s", nmaildir);
272 }
273
274 if (chdir (nmaildir) == NOTOK)
275 adios (nmaildir, "unable to change directory to");
276 if (!(mp = m_gmsg (fp -> f_name)))
277 adios (NULLCP, "unable to read folder %s", fp -> f_name);
278 mp -> curmsg = 0;
279
280 fp -> f_mp = mp;
281
282 (void) chdir (maildir);
283 }
284 }
285
286 /* \f */
287
288 static clsfolds (folders, nfolders)
289 register struct st_fold *folders;
290 int nfolders;
291 {
292 register struct st_fold *fp,
293 *ep;
294 register struct msgs *mp;
295
296 for (ep = (fp = folders) + nfolders; fp < ep; fp++) {
297 mp = fp -> f_mp;
298 m_setseq (mp);
299 m_sync (mp);
300 }
301 }
302
303 /* \f */
304
305 static removeit (mp, filep, files)
306 register struct msgs *mp;
307 register int filep;
308 register char **files;
309 {
310 register int i,
311 vecp;
312 register char *cp,
313 **vec;
314
315 if (rmmproc) {
316 if (filep > 0) {
317 vec = files++; /* filevec[1] */
318 files[filep] = NULL;
319 }
320 else {
321 if (mp -> numsel > MAXARGS - 2)
322 adios (NULLCP, "more than %d messages for %s exec",
323 MAXARGS - 2, rmmproc);
324 vec = (char **) calloc ((unsigned) (mp -> numsel + 2), sizeof *vec);
325 if (vec == NULL)
326 adios (NULLCP, "unable to allocate exec vector");
327 vecp = 1;
328 for (i = mp -> lowsel; i <= mp -> hghsel; i++)
329 if (mp -> msgstats[i] & SELECTED)
330 vec[vecp++] = getcpy (m_name (i));
331 vec[vecp] = NULL;
332 }
333
334 (void) fflush (stdout);
335 vec[0] = r1bindex (rmmproc, '/');
336 execvp (rmmproc, vec);
337 adios (rmmproc, "unable to exec");
338 }
339
340 if (filep > 0) {
341 files++; /* filevec[1] */
342 for (i = 0; i < filep; i++)
343 if (unlink (files[i]) == NOTOK)
344 admonish (files[i], "unable to unlink");
345 }
346 else
347 for (i = mp -> lowsel; i <= mp -> hghsel; i++)
348 if (mp -> msgstats[i] & SELECTED)
349 if (unlink (cp = m_name (i)) == NOTOK)
350 admonish (cp, "unable to unlink");
351 }
352
353 /* \f */
354
355 m_file (msg, folders, nfolders, prsrvf)
356 register char *msg;
357 struct st_fold *folders;
358 int nfolders,
359 prsrvf;
360 {
361 int in,
362 out,
363 linkerr,
364 msgnum;
365 register char *nmsg;
366 char newmsg[BUFSIZ];
367 register struct st_fold *fp,
368 *ep;
369 register struct msgs *mp;
370 struct stat st,
371 s1;
372
373 for (ep = (fp = folders) + nfolders; fp < ep; fp++) {
374 mp = fp -> f_mp;
375 if (prsrvf && (msgnum = m_atoi (nmsg = msg)) > 0) {
376 if (msgnum >= mp -> hghoff)
377 if (mp = m_remsg (mp, 0, msgnum + MAXFOLDER))
378 fp -> f_mp = mp;
379 else
380 adios (NULLCP, "unable to allocate folder storage");
381 if (!(mp -> msgstats[msgnum] & EXISTS)) {
382 mp -> msgstats[msgnum] |= EXISTS;
383 #ifdef notdef
384 mp -> msgstats[msgnum] &= ~DELETED;
385 #endif /* notdef */
386 mp -> nummsg++;
387 }
388 mp -> msgstats[msgnum] |= SELECTED;
389 if (msgnum > mp -> hghmsg)
390 mp -> hghmsg = msgnum;
391 }
392 else {
393 if (mp -> hghmsg >= mp -> hghoff)
394 if (mp = m_remsg (mp, 0, mp -> hghoff + MAXFOLDER))
395 fp -> f_mp = mp;
396 else
397 adios (NULLCP, "unable to allocate folder storage");
398
399 nmsg = m_name (msgnum = ++mp -> hghmsg);
400 mp -> nummsg++;
401 mp -> msgstats[msgnum] |= EXISTS | SELECTED;
402 }
403 if (mp -> lowmsg == 0)
404 mp -> lowmsg = msgnum;
405 if (mp -> lowsel == 0 || msgnum < mp -> lowsel)
406 mp -> lowsel = msgnum;
407 if (msgnum > mp -> hghsel)
408 mp -> hghsel = msgnum;
409
410 /* \f */
411
412 (void) sprintf (newmsg, "%s/%s", mp -> foldpath, nmsg);
413 if (link (msg, newmsg) == NOTOK) {
414 #ifndef EISREMOTE
415 linkerr = errno;
416 #else /* EISREMOTE */
417 if ((linkerr = errno) == EISREMOTE)
418 linkerr = EXDEV;
419 #endif /* EISREMOTE */
420 if (linkerr == EEXIST
421 || (linkerr == EXDEV && stat (newmsg, &st) != NOTOK)) {
422 if (linkerr != EEXIST
423 || stat (msg, &s1) == NOTOK
424 || stat (newmsg, &st) == NOTOK
425 || s1.st_ino != st.st_ino) {
426 advise (NULLCP, "message %s:%s already exists",
427 fp -> f_name, newmsg);
428 return 1;
429 }
430 continue;
431 }
432 if (linkerr == EXDEV) {
433 if ((in = open (msg, 0)) == NOTOK) {
434 advise (msg, "unable to open message %s");
435 return 1;
436 }
437 (void) fstat (in, &st);
438 if ((out = creat (newmsg, (int) st.st_mode & 0777))
439 == NOTOK) {
440 advise (newmsg, "unable to create");
441 (void) close (in);
442 return 1;
443 }
444 cpydata (in, out, msg, newmsg);
445 (void) close (in);
446 (void) close (out);
447 }
448 else {
449 advise (newmsg, "error linking %s to", msg);
450 return 1;
451 }
452 }
453 }
454
455 return 0;
456 }