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