|
|
1.1 root 1: /* pick.c - select messages by content */
2:
3: #include "../h/mh.h"
4: #include "../zotnet/tws.h"
5: #include <stdio.h>
6:
7: /* */
8:
9: static struct swit switches[] = {
10: #define ANDSW 0
11: "and", 0,
12: #define ORSW 1
13: "or", 0,
14: #define NOTSW 2
15: "not", 0,
16: #define LBRSW 3
17: "lbrace", 0,
18: #define RBRSW 4
19: "rbrace", 0,
20:
21: #define CCSW 5
22: "cc pattern", 0,
23: #define DATESW 6
24: "date pattern", 0,
25: #define FROMSW 7
26: "from pattern", 0,
27: #define SRCHSW 8
28: "search pattern", 0,
29: #define SUBJSW 9
30: "subject pattern", 0,
31: #define TOSW 10
32: "to pattern", 0,
33: #define OTHRSW 11
34: "-othercomponent pattern", 0,
35: #define AFTRSW 12
36: "after date", 0,
37: #define BEFRSW 13
38: "before date", 0,
39: #define DATFDSW 14
40: "datefield field", 5,
41:
42: #define SEQSW 15
43: "sequence name", 0,
44: #define PUBLSW 16
45: "public", 0,
46: #define NPUBLSW 17
47: "nopublic", 0,
48: #define ZEROSW 18
49: "zero", 0,
50: #define NZEROSW 19
51: "nozero", 0,
52:
53: #define LISTSW 20
54: "list", 0,
55: #define NLISTSW 21
56: "nolist", 0,
57:
58: #define HELPSW 22
59: "help", 4,
60:
61: NULL, NULL
62: };
63:
64: /* */
65:
66: static int listsw = 0;
67:
68: /* */
69:
70: /* ARGSUSED */
71:
72: main (argc, argv)
73: char *argv[];
74: {
75: int publicsw = -1,
76: zerosw = 1,
77: msgp = 0,
78: seqp = 0,
79: vecp = 0,
80: lo,
81: hi,
82: msgnum;
83: char *maildir,
84: *folder = NULL,
85: buf[100],
86: *cp,
87: **ap,
88: **argp,
89: *arguments[MAXARGS],
90: *msgs[MAXARGS],
91: *seqs[NATTRS + 1],
92: *vec[MAXARGS];
93: struct msgs *mp;
94: register FILE *fp;
95:
96: invo_name = r1bindex (argv[0], '/');
97: if ((cp = m_find (invo_name)) != NULL) {
98: ap = brkstring (cp = getcpy (cp), " ", "\n");
99: ap = copyip (ap, arguments);
100: }
101: else
102: ap = arguments;
103: (void) copyip (argv + 1, ap);
104: argp = arguments;
105:
106: /* */
107:
108: while (cp = *argp++) {
109: if (*cp == '-') {
110: if (*++cp == '-') {
111: vec[vecp++] = --cp;
112: goto pattern;
113: }
114: switch (smatch (cp, switches)) {
115: case AMBIGSW:
116: ambigsw (cp, switches);
117: done (1);
118: case UNKWNSW:
119: adios (NULLCP, "-%s unknown", cp);
120: case HELPSW:
121: (void) sprintf (buf, "%s [+folder] [msgs] [switches]",
122: invo_name);
123: help (buf, switches);
124: listsw = 0; /* HACK */
125: done (1);
126:
127: case CCSW:
128: case DATESW:
129: case FROMSW:
130: case SUBJSW:
131: case TOSW:
132: case DATFDSW:
133: case AFTRSW:
134: case BEFRSW:
135: case SRCHSW:
136: vec[vecp++] = --cp;
137: pattern: ;
138: if (!(cp = *argp++))/* allow -xyz arguments */
139: adios (NULLCP, "missing argument to %s", argp[-2]);
140: vec[vecp++] = cp;
141: continue;
142: case OTHRSW:
143: adios (NULLCP, "internal error!");
144:
145: case ANDSW:
146: case ORSW:
147: case NOTSW:
148: case LBRSW:
149: case RBRSW:
150: vec[vecp++] = --cp;
151: continue;
152:
153: case SEQSW:
154: if (!(cp = *argp++) || *cp == '-')
155: adios (NULLCP, "missing argument to %s", argp[-2]);
156: if (seqp < NATTRS)
157: seqs[seqp++] = cp;
158: else
159: adios (NULLCP, "only %d sequences allowed!", NATTRS);
160: listsw = 0;
161: continue;
162: case PUBLSW:
163: publicsw = 1;
164: continue;
165: case NPUBLSW:
166: publicsw = 0;
167: continue;
168: case ZEROSW:
169: zerosw++;
170: continue;
171: case NZEROSW:
172: zerosw = 0;
173: continue;
174:
175: case LISTSW:
176: listsw++;
177: continue;
178: case NLISTSW:
179: listsw = 0;
180: continue;
181: }
182: }
183: if (*cp == '+' || *cp == '@')
184: if (folder)
185: adios (NULLCP, "only one folder at a time!");
186: else
187: folder = path (cp + 1, *cp == '+' ? TFOLDER : TSUBCWF);
188: else
189: msgs[msgp++] = cp;
190: }
191: vec[vecp] = NULL;
192:
193: /* */
194:
195: if (!m_find ("path"))
196: free (path ("./", TFOLDER));
197: if (!msgp)
198: msgs[msgp++] = "all";
199: if (!folder)
200: folder = m_getfolder ();
201: 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: if (seqp == 0)
216: listsw++;
217: if (publicsw == -1)
218: publicsw = mp -> msgflags & READONLY ? 0 : 1;
219: if (publicsw && (mp -> msgflags & READONLY))
220: adios (NULLCP, "folder %s is read-only, so -public not allowed",
221: folder);
222:
223: /* */
224:
225: if (!pcompile (vec, NULLCP))
226: done (1);
227:
228: lo = mp -> lowsel;
229: hi = mp -> hghsel;
230:
231: for (msgnum = mp -> lowsel; msgnum <= mp -> hghsel; msgnum++)
232: if (mp -> msgstats[msgnum] & SELECTED) {
233: if ((fp = fopen (cp = m_name (msgnum), "r")) == NULL)
234: admonish (cp, "unable to read message");
235: if (fp && pmatches (fp, msgnum, 0L, 0L)) {
236: if (msgnum < lo)
237: lo = msgnum;
238: if (msgnum > hi)
239: hi = msgnum;
240: }
241: else {
242: mp -> msgstats[msgnum] &= ~SELECTED;
243: mp -> numsel--;
244: }
245: if (fp)
246: (void) fclose (fp);
247: }
248:
249: mp -> lowsel = lo;
250: mp -> hghsel = hi;
251:
252: if (mp -> numsel <= 0)
253: adios (NULLCP, "no messages match specification");
254:
255: /* */
256:
257: seqs[seqp] = NULL;
258: for (seqp = 0; seqs[seqp]; seqp++) {
259: if (zerosw && !m_seqnew (mp, seqs[seqp], publicsw))
260: done (1);
261: for (msgnum = mp -> lowsel; msgnum <= mp -> hghsel; msgnum++)
262: if (mp -> msgstats[msgnum] & SELECTED)
263: if (!m_seqadd (mp, seqs[seqp], msgnum, publicsw))
264: done (1);
265: }
266:
267: if (listsw) {
268: for (msgnum = mp -> lowsel; msgnum <= mp -> hghsel; msgnum++)
269: if (mp -> msgstats[msgnum] & SELECTED)
270: printf ("%s\n", m_name (msgnum));
271: }
272: else
273: printf ("%d hit%s\n", mp -> numsel,
274: mp -> numsel == 1 ? "" : "s");
275:
276: m_replace (pfolder, folder);
277: m_sync (mp);
278: m_update ();
279:
280: done (0);
281: }
282:
283: /* */
284:
285: void done (status)
286: int status;
287: {
288: if (listsw && status && !isatty (fileno (stdout)))
289: printf ("0\n");
290: exit (status);
291: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.