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: }