1: /* burst.c - explode digests into individual messages */ 2: 3: #include "../h/mh.h" 4: #include <stdio.h> 5: #include <sys/types.h> 6: #include <sys/stat.h> 7: 8: /* */ 9: 10: static struct swit switches[] = { 11: #define INPLSW 0 12: "inplace", 0, 13: #define NINPLSW 1 14: "noinplace", 0, 15: 16: #define QIETSW 2 17: "quiet", 0, 18: #define NQIETSW 3 19: "noquiet", 0, 20: 21: #define VERBSW 4 22: "verbose", 0, 23: #define NVERBSW 5 24: "noverbose", 0, 25: 26: #define HELPSW 6 27: "help", 4, 28: 29: NULL, NULL 30: }; 31: 32: /* */ 33: 34: static char delim3[] = "-------"; 35: 36: 37: static struct msgs *mp; 38: 39: struct smsg { 40: long s_start; 41: long s_stop; 42: }; 43: 44: /* */ 45: 46: /* ARGSUSED */ 47: 48: main (argc, argv) 49: int argc; 50: char **argv; 51: { 52: int inplace = 0, 53: quietsw = 0, 54: verbosw = 0, 55: msgp = 0, 56: hi, 57: msgnum; 58: char *cp, 59: *maildir, 60: *folder = NULL, 61: buf[100], 62: **ap, 63: **argp, 64: *arguments[MAXARGS], 65: *msgs[MAXARGS]; 66: struct smsg *smsgs; 67: 68: invo_name = r1bindex (argv[0], '/'); 69: if ((cp = m_find (invo_name)) != NULL) { 70: ap = brkstring (cp = getcpy (cp), " ", "\n"); 71: ap = copyip (ap, arguments); 72: } 73: else 74: ap = arguments; 75: (void) copyip (argv + 1, ap); 76: argp = arguments; 77: 78: /* */ 79: 80: while (cp = *argp++) { 81: if (*cp == '-') 82: switch (smatch (++cp, switches)) { 83: case AMBIGSW: 84: ambigsw (cp, switches); 85: done (1); 86: case UNKWNSW: 87: adios (NULLCP, "-%s unknown\n", cp); 88: case HELPSW: 89: (void) sprintf (buf, "%s [+folder] [msgs] [switches]", 90: invo_name); 91: help (buf, switches); 92: done (1); 93: 94: case INPLSW: 95: inplace++; 96: continue; 97: case NINPLSW: 98: inplace = 0; 99: continue; 100: 101: case QIETSW: 102: quietsw++; 103: continue; 104: case NQIETSW: 105: quietsw = 0; 106: continue; 107: 108: case VERBSW: 109: verbosw++; 110: continue; 111: case NVERBSW: 112: verbosw = 0; 113: continue; 114: } 115: if (*cp == '+' || *cp == '@') { 116: if (folder) 117: adios (NULLCP, "only one folder at a time!"); 118: else 119: folder = path (cp + 1, *cp == '+' ? TFOLDER : TSUBCWF); 120: } 121: else 122: msgs[msgp++] = cp; 123: } 124: 125: /* */ 126: 127: if (!m_find ("path")) 128: free (path ("./", TFOLDER)); 129: if (!msgp) 130: msgs[msgp++] = "cur"; 131: if (!folder) 132: folder = m_getfolder (); 133: maildir = m_maildir (folder); 134: 135: if (chdir (maildir) == NOTOK) 136: adios (maildir, "unable to change directory to"); 137: if (!(mp = m_gmsg (folder))) 138: adios (NULLCP, "unable to read folder %s", folder); 139: if (mp -> hghmsg == 0) 140: adios (NULLCP, "no messages in %s", folder); 141: 142: for (msgnum = 0; msgnum < msgp; msgnum++) 143: if (!m_convert (mp, msgs[msgnum])) 144: done (1); 145: m_setseq (mp); 146: 147: smsgs = (struct smsg *) 148: calloc ((unsigned) (MAXFOLDER + 2), sizeof *smsgs); 149: if (smsgs == NULL) 150: adios (NULLCP, "unable to allocate burst storage"); 151: 152: hi = mp -> hghmsg + 1; 153: for (msgnum = mp -> lowsel; msgnum <= mp -> hghsel; msgnum++) 154: if (mp -> msgstats[msgnum] & SELECTED) 155: burst (smsgs, msgnum, inplace, quietsw, verbosw); 156: 157: free ((char *) smsgs); 158: 159: m_replace (pfolder, folder); 160: if (inplace) { 161: if (mp -> lowsel != mp -> curmsg) 162: m_setcur (mp, mp -> lowsel); 163: } 164: else 165: if (hi <= mp -> hghmsg) 166: m_setcur (mp, hi); 167: m_sync (mp); 168: m_update (); 169: 170: done (0); 171: } 172: 173: /* */ 174: 175: static burst (smsgs, msgnum, inplace, quietsw, verbosw) 176: register struct smsg *smsgs; 177: int msgnum, 178: inplace, 179: quietsw, 180: verbosw; 181: { 182: int i, 183: j, 184: ld3, 185: wasdlm, 186: mode, 187: msgp; 188: register long pos; 189: register char c, 190: *msgnam; 191: char buffer[BUFSIZ], 192: f1[BUFSIZ], 193: f2[BUFSIZ], 194: f3[BUFSIZ]; 195: struct stat st; 196: register FILE *in, 197: *out; 198: 199: ld3 = strlen (delim3); 200: 201: if ((in = fopen (msgnam = m_name (msgnum), "r")) == NULL) 202: adios (msgnam, "unable to read message"); 203: 204: mode = fstat (fileno (in), &st) != NOTOK ? (st.st_mode & 0777) 205: : m_gmprot (); 206: for (msgp = 1, pos = 0L; msgp <= MAXFOLDER;) { 207: while (fgets (buffer, sizeof buffer, in) != NULL 208: && buffer[0] == '\n') 209: pos += (long) strlen (buffer); 210: if (feof (in)) 211: break; 212: (void) fseek (in, pos, 0); 213: smsgs[msgp].s_start = pos; 214: 215: for (c = NULL; 216: fgets (buffer, sizeof buffer, in) != NULL; 217: c = buffer[0]) 218: if (strncmp (buffer, delim3, ld3) == 0 219: && peekc (in) == '\n' 220: && (msgp == 1 || c == '\n')) 221: break; 222: else 223: pos += (long) strlen (buffer); 224: 225: wasdlm = strncmp (buffer, delim3, ld3) == 0; 226: if (smsgs[msgp].s_start != pos) 227: smsgs[msgp++].s_stop = c == '\n' && wasdlm ? pos - 1 : pos; 228: if (feof (in)) { 229: if (wasdlm) { 230: smsgs[msgp - 1].s_stop -= ((long) strlen (buffer) + 1); 231: msgp++; /* fake "End of XXX Digest" */ 232: } 233: break; 234: } 235: pos += (long) strlen (buffer); 236: } 237: 238: /* */ 239: 240: switch (--msgp) { /* toss "End of XXX Digest" */ 241: case 0: 242: adios (NULLCP, "burst() botch -- you lose big"); 243: 244: case 1: 245: if (!quietsw) 246: admonish (NULLCP, "message %d not in digest format", msgnum); 247: (void) fclose (in); 248: return; 249: 250: default: 251: if (verbosw) 252: printf ("%d message%s exploded from digest %d\n", 253: msgp - 1, msgp - 1 != 1 ? "s" : "", msgnum); 254: if (msgp == 2) /* XXX */ 255: msgp++; 256: break; 257: } 258: 259: if ((mp = m_remsg (mp, 0, mp -> hghmsg + msgp)) == NULL) 260: adios (NULLCP, "unable to allocate folder storage"); 261: 262: /* */ 263: 264: msgp--; 265: j = mp -> hghmsg; 266: mp -> hghmsg += msgp - 1; 267: mp -> nummsg += msgp - 1; 268: if (mp -> hghsel > msgnum) 269: mp -> hghsel += msgp - 1; 270: 271: if (inplace && msgp > 1) 272: for (i = mp -> hghmsg; j > msgnum; i--, j--) { 273: (void) strcpy (f1, m_name (i)); 274: (void) strcpy (f2, m_name (j)); 275: if (mp -> msgstats[j] & EXISTS) { 276: if (verbosw) 277: printf ("message %d becomes message %d\n", j, i); 278: 279: if (rename (f2, f1) == NOTOK) 280: admonish (f1, "unable to rename %s to", f2); 281: mp -> msgstats[i] = mp -> msgstats[j]; 282: mp -> msgstats[j] = NULL; 283: mp -> msgflags |= SEQMOD; 284: } 285: } 286: 287: mp -> msgstats[msgnum] &= ~SELECTED; 288: i = inplace ? msgnum + msgp - 1 : mp -> hghmsg; 289: for (j = msgp; j >= (inplace ? 1 : 2); i--, j--) { 290: (void) strcpy (f1, m_name (i)); 291: (void) strcpy (f2, m_scratch ("", invo_name)); 292: if (verbosw && i != msgnum) 293: printf ("message %d of digest %d becomes message %d\n", 294: j, msgnum, i); 295: 296: if ((out = fopen (f2, "w")) == NULL) 297: adios (f2, "unable to write message"); 298: (void) chmod (f2, mode); 299: (void) fseek (in, pos = smsgs[j].s_start, 0); 300: cpybrst (in, out, msgnam, f2, 301: (int) (smsgs[j].s_stop - smsgs[j].s_start)); 302: (void) fclose (out); 303: 304: if (i == msgnum) { 305: (void) strcpy (f3, m_backup (f1)); 306: if (rename (f1, f3) == NOTOK) 307: admonish (f3, "unable to rename %s to", f1); 308: } 309: if (rename (f2, f1) == NOTOK) 310: admonish (f1, "unable to rename %s to", f2); 311: mp -> msgstats[i] = mp -> msgstats[msgnum]; 312: mp -> msgflags |= SEQMOD; 313: } 314: 315: (void) fclose (in); 316: } 317: 318: 319: /* */ 320: 321: #define S1 0 322: #define S2 1 323: #define S3 2 324: 325: static cpybrst (in, out, ifile, ofile, len) 326: register FILE *in, 327: *out; 328: register char *ifile, 329: *ofile; 330: register int len; 331: { 332: register int c, 333: state; 334: 335: for (state = S1; (c = fgetc (in)) != EOF && len > 0; len--) { 336: if (c == NULL) 337: continue; 338: switch (state) { 339: case S1: 340: switch (c) { 341: case '-': 342: state = S3; 343: break; 344: 345: default: 346: state = S2; 347: case '\n': 348: (void) fputc (c, out); 349: break; 350: } 351: break; 352: 353: case S2: 354: switch (c) { 355: case '\n': 356: state = S1; 357: default: 358: (void) fputc (c, out); 359: break; 360: } 361: break; 362: 363: case S3: 364: switch (c) { 365: case ' ': 366: state = S2; 367: break; 368: 369: default: 370: state = c == '\n' ? S1 : S2; 371: (void) fputc ('-', out); 372: (void) fputc (c, out); 373: break; 374: } 375: break; 376: } 377: } 378: 379: if (ferror (in)) 380: adios (ifile, "error reading"); 381: if (ferror (out)) 382: adios (ofile, "error writing"); 383: }