1: /* mshcmds.c - command handlers in msh */ 2: 3: #include "../h/mh.h" 4: #include "../h/dropsbr.h" 5: #include "../h/formatsbr.h" 6: #include "../h/scansbr.h" 7: #include "../zotnet/tws.h" 8: #include <stdio.h> 9: #include "../zotnet/mts.h" 10: #include <ctype.h> 11: #include <errno.h> 12: #include <setjmp.h> 13: #include <signal.h> 14: #include "../h/mshsbr.h" 15: #include <sys/types.h> 16: #include <sys/stat.h> 17: 18: /* */ 19: 20: extern int errno; 21: 22: /* BURST */ 23: static char delim3[] = "-------";/* from burst.c */ 24: 25: 26: /* SHOW */ 27: static int mhlnum; 28: static FILE *mhlfp; 29: 30: void clear_screen (); 31: int eom_action (); 32: FP mhl_action (); 33: 34: 35: /* SORTM */ 36: int msgsort (); 37: struct tws *getws (); 38: 39: /* */ 40: 41: forkcmd (args, pgm) 42: char **args, 43: *pgm; 44: { 45: int child_id; 46: char *vec[MAXARGS]; 47: 48: vec[0] = r1bindex (pgm, '/'); 49: (void) copyip (args, vec + 1); 50: 51: if (fmsh) { 52: (void) m_delete (pfolder); 53: m_replace (pfolder, fmsh); 54: m_sync (mp); 55: m_update (); 56: } 57: (void) fflush (stdout); 58: switch (child_id = fork ()) { 59: case NOTOK: 60: advise ("fork", "unable to"); 61: return; 62: 63: case OK: 64: closefds (3); 65: (void) signal (SIGINT, istat); 66: (void) signal (SIGQUIT, qstat); 67: 68: execvp (pgm, vec); 69: fprintf (stderr, "unable to exec "); 70: perror (cmd_name); 71: _exit (1); 72: 73: default: 74: (void) pidXwait (child_id, NULLCP); 75: break; 76: } 77: if (fmsh) { /* assume the worst case */ 78: mp -> msgflags |= MODIFIED; 79: modified++; 80: } 81: } 82: 83: /* */ 84: 85: static struct swit distswit[] = { 86: #define DIANSW 0 87: "annotate", 0, 88: #define DINANSW 1 89: "noannotate", 0, 90: #define DIDFSW 2 91: "draftfolder +folder", 0, 92: #define DIDMSW 3 93: "draftmessage msg", 0, 94: #define DINDFSW 4 95: "nodraftfolder", 0, 96: #define DIEDTSW 5 97: "editor editor", 0, 98: #define DINEDSW 6 99: "noedit", 0, 100: #define DIFRMSW 7 101: "form formfile", 0, 102: #define DIINSW 8 103: "inplace", 0, 104: #define DININSW 9 105: "noinplace", 0, 106: #define DIWHTSW 10 107: "whatnowproc program", 0, 108: #define DINWTSW 11 109: "nowhatnowproc", 0, 110: #define DIHELP 12 111: "help", 4, 112: 113: NULL, NULL 114: }; 115: 116: /* */ 117: 118: distcmd (args) 119: char **args; 120: { 121: int vecp = 1; 122: char *cp, 123: *msg = NULL, 124: buf[BUFSIZ], 125: *vec[MAXARGS]; 126: 127: if (fmsh) { 128: forkcmd (args, cmd_name); 129: return; 130: } 131: 132: while (cp = *args++) { 133: if (*cp == '-') 134: switch (smatch (++cp, distswit)) { 135: case AMBIGSW: 136: ambigsw (cp, distswit); 137: return; 138: case UNKWNSW: 139: fprintf (stderr, "-%s unknown\n", cp); 140: return; 141: case DIHELP: 142: (void) sprintf (buf, "%s [msgs] [switches]", cmd_name); 143: help (buf, distswit); 144: return; 145: 146: case DIANSW: /* not implemented */ 147: case DINANSW: 148: case DIINSW: 149: case DININSW: 150: continue; 151: 152: case DINDFSW: 153: case DINEDSW: 154: case DINWTSW: 155: vec[vecp++] = --cp; 156: continue; 157: 158: case DIEDTSW: 159: case DIFRMSW: 160: case DIDFSW: 161: case DIDMSW: 162: case DIWHTSW: 163: vec[vecp++] = --cp; 164: if (!(cp = *args++) || *cp == '-') { 165: advise (NULLCP, "missing argument to %s", args[-2]); 166: return; 167: } 168: vec[vecp++] = cp; 169: continue; 170: } 171: if (*cp == '+' || *cp == '@') { 172: advise (NULLCP, "sorry, no folders allowed!"); 173: return; 174: } 175: else 176: if (msg) { 177: advise (NULLCP, "only one message at a time!"); 178: return; 179: } 180: else 181: msg = cp; 182: } 183: 184: vec[0] = cmd_name; 185: vec[vecp++] = "-file"; 186: vec[vecp] = NULL; 187: if (!msg) 188: msg = "cur"; 189: if (!m_convert (mp, msg)) 190: return; 191: m_setseq (mp); 192: 193: if (mp -> numsel > 1) { 194: advise (NULLCP, "only one message at a time!"); 195: return; 196: } 197: (void) process (mp -> hghsel, cmd_name, vecp, vec); 198: m_setcur (mp, mp -> hghsel); 199: } 200: 201: /* */ 202: 203: static struct swit explswit[] = { 204: #define EXINSW 0 205: "inplace", 0, 206: #define EXNINSW 1 207: "noinplace", 0, 208: #define EXQISW 2 209: "quiet", 0, 210: #define EXNQISW 3 211: "noquiet", 0, 212: #define EXVBSW 4 213: "verbose", 0, 214: #define EXNVBSW 5 215: "noverbose", 0, 216: #define EXHELP 6 217: "help", 4, 218: 219: NULL, NULL 220: }; 221: 222: /* */ 223: 224: explcmd (args) 225: char **args; 226: { 227: int inplace = 0, 228: quietsw = 0, 229: verbosw = 0, 230: msgp = 0, 231: hi, 232: msgnum; 233: char *cp, 234: buf[BUFSIZ], 235: *msgs[MAXARGS]; 236: struct Msg *smsgs; 237: 238: if (fmsh) { 239: forkcmd (args, cmd_name); 240: return; 241: } 242: 243: while (cp = *args++) { 244: if (*cp == '-') 245: switch (smatch (++cp, explswit)) { 246: case AMBIGSW: 247: ambigsw (cp, explswit); 248: return; 249: case UNKWNSW: 250: fprintf (stderr, "-%s unknown\n", cp); 251: return; 252: case EXHELP: 253: (void) sprintf (buf, "%s [msgs] [switches]", cmd_name); 254: help (buf, explswit); 255: return; 256: 257: case EXINSW: 258: inplace++; 259: continue; 260: case EXNINSW: 261: inplace = 0; 262: continue; 263: case EXQISW: 264: quietsw++; 265: continue; 266: case EXNQISW: 267: quietsw = 0; 268: continue; 269: case EXVBSW: 270: verbosw++; 271: continue; 272: case EXNVBSW: 273: verbosw = 0; 274: continue; 275: } 276: if (*cp == '+' || *cp == '@') { 277: advise (NULLCP, "sorry, no folders allowed!"); 278: return; 279: } 280: else 281: msgs[msgp++] = cp; 282: } 283: 284: if (!msgp) 285: msgs[msgp++] = "cur"; 286: for (msgnum = 0; msgnum < msgp; msgnum++) 287: if (!m_convert (mp, msgs[msgnum])) 288: return; 289: m_setseq (mp); 290: 291: smsgs = (struct Msg *) 292: calloc ((unsigned) (MAXFOLDER + 2), sizeof *smsgs); 293: if (smsgs == NULL) 294: adios (NULLCP, "unable to allocate folder storage"); 295: 296: hi = mp -> hghmsg + 1; 297: interrupted = 0; 298: for (msgnum = mp -> lowsel; 299: msgnum <= mp -> hghsel && !interrupted; 300: msgnum++) 301: if (mp -> msgstats[msgnum] & SELECTED) 302: if (burst (smsgs, msgnum, inplace, quietsw, verbosw) != OK) 303: break; 304: 305: free ((char *) smsgs); 306: 307: if (inplace) 308: m_setcur (mp, mp -> lowsel); 309: else 310: if (hi <= mp -> hghmsg) 311: m_setcur (mp, hi); 312: 313: mp -> msgflags |= MODIFIED; 314: modified++; 315: } 316: 317: /* */ 318: 319: static burst (smsgs, msgnum, inplace, quietsw, verbosw) 320: struct Msg *smsgs; 321: int msgnum, 322: inplace, 323: quietsw, 324: verbosw; 325: { 326: int i, 327: j, 328: ld3, 329: wasdlm, 330: msgp; 331: long pos; 332: char c, 333: buffer[BUFSIZ]; 334: register FILE *zp; 335: 336: ld3 = strlen (delim3); 337: 338: if (Msgs[msgnum].m_scanl) { 339: free (Msgs[msgnum].m_scanl); 340: Msgs[msgnum].m_scanl = NULL; 341: } 342: 343: pos = ftell (zp = msh_ready (msgnum, 1)); 344: for (msgp = 1; msgp <= MAXFOLDER;) { 345: while (fgets (buffer, sizeof buffer, zp) != NULL 346: && buffer[0] == '\n' 347: && pos < Msgs[msgnum].m_stop) 348: pos += (long) strlen (buffer); 349: if (feof (zp) || pos >= Msgs[msgnum].m_stop) 350: break; 351: (void) fseek (zp, pos, 0); 352: smsgs[msgp].m_start = pos; 353: 354: for (c = NULL; 355: fgets (buffer, sizeof buffer, zp) != NULL 356: && pos < Msgs[msgnum].m_stop; 357: c = buffer[0]) 358: if (strncmp (buffer, delim3, ld3) == 0 359: && peekc (zp) == '\n' 360: && (msgp == 1 || c == '\n')) 361: break; 362: else 363: pos += (long) strlen (buffer); 364: 365: wasdlm = strncmp (buffer, delim3, ld3) == 0; 366: if (smsgs[msgp].m_start != pos) 367: smsgs[msgp++].m_stop = c == '\n' && wasdlm ? pos - 1 : pos; 368: if (feof (zp) || pos >= Msgs[msgnum].m_stop) { 369: if (wasdlm) { 370: smsgs[msgp - 1].m_stop -= ((long) strlen (buffer) + 1); 371: msgp++; /* fake "End of XXX Digest" */ 372: } 373: break; 374: } 375: pos += (long) strlen (buffer); 376: } 377: 378: switch (--msgp) { /* toss "End of XXX Digest" */ 379: case 0: 380: adios (NULLCP, "burst() botch -- you lose big"); 381: 382: case 1: 383: if (!quietsw) 384: printf ("message %d not in digest format\n", msgnum); 385: return OK; 386: 387: default: 388: if (verbosw) 389: printf ("%d message%s exploded from digest %d\n", 390: msgp - 1, msgp - 1 != 1 ? "s" : "", msgnum); 391: if (msgp == 2) 392: msgp++; 393: break; 394: } 395: 396: msgp--; 397: if ((i = msgp + mp -> hghmsg) > MAXFOLDER) { 398: advise (NULLCP, "more than %d messages", MAXFOLDER); 399: return NOTOK; 400: } 401: if ((mp = m_remsg (mp, 0, i)) == NULL) 402: adios (NULLCP, "unable to allocate folder storage"); 403: 404: j = mp -> hghmsg; 405: mp -> hghmsg += msgp - 1; 406: mp -> nummsg += msgp - 1; 407: if (mp -> hghsel > msgnum) 408: mp -> hghsel += msgp - 1; 409: 410: if (inplace && msgp > 1) 411: for (i = mp -> hghmsg; j > msgnum; i--, j--) { 412: if (verbosw) 413: printf ("message %d becomes message %d\n", j, i); 414: 415: Msgs[i].m_bboard_id = Msgs[j].m_bboard_id; 416: Msgs[i].m_top = Msgs[j].m_top; 417: Msgs[i].m_start = Msgs[j].m_start; 418: Msgs[i].m_stop = Msgs[j].m_stop; 419: Msgs[i].m_scanl = NULL; 420: if (Msgs[j].m_scanl) { 421: free (Msgs[j].m_scanl); 422: Msgs[j].m_scanl = NULL; 423: } 424: mp -> msgstats[i] = mp -> msgstats[j]; 425: } 426: 427: if (Msgs[msgnum].m_bboard_id == 0) 428: (void) readid (msgnum); 429: 430: mp -> msgstats[msgnum] &= ~SELECTED; 431: i = inplace ? msgnum + msgp - 1 : mp -> hghmsg; 432: for (j = msgp; j >= (inplace ? 1 : 2); i--, j--) { 433: if (verbosw && i != msgnum) 434: printf ("message %d of digest %d becomes message %d\n", 435: j, msgnum, i); 436: 437: Msgs[i].m_bboard_id = Msgs[msgnum].m_bboard_id; 438: Msgs[i].m_top = Msgs[j].m_top; 439: Msgs[i].m_start = smsgs[j].m_start; 440: Msgs[i].m_stop = smsgs[j].m_stop; 441: Msgs[i].m_scanl = NULL; 442: mp -> msgstats[i] = mp -> msgstats[msgnum]; 443: } 444: 445: return OK; 446: } 447: 448: /* */ 449: 450: static struct swit fileswit[] = { 451: #define FIDRFT 0 452: "draft", 0, 453: #define FILINK 1 454: "link", 0, 455: #define FINLINK 2 456: "nolink", 0, 457: #define FIPRES 3 458: "preserve", 0, 459: #define FINPRES 4 460: "nopreserve", 0, 461: #define FISRC 5 462: "src +folder", 0, 463: #define FIFILE 6 464: "file file", 0, 465: #define FIHELP 7 466: "help", 4, 467: 468: NULL, NULL 469: }; 470: 471: /* */ 472: 473: filecmd (args) 474: char **args; 475: { 476: int linksw = 0, 477: msgp = 0, 478: vecp = 1, 479: i, 480: msgnum; 481: char *cp, 482: buf[BUFSIZ], 483: *msgs[MAXARGS], 484: *vec[MAXARGS]; 485: 486: if (fmsh) { 487: forkcmd (args, cmd_name); 488: return; 489: } 490: 491: while (cp = *args++) { 492: if (*cp == '-') 493: switch (i = smatch (++cp, fileswit)) { 494: case AMBIGSW: 495: ambigsw (cp, fileswit); 496: return; 497: case UNKWNSW: 498: fprintf (stderr, "-%s unknown\n", cp); 499: return; 500: case FIHELP: 501: (void) sprintf (buf, "%s +folder... [msgs] [switches]", 502: cmd_name); 503: help (buf, fileswit); 504: return; 505: 506: case FILINK: 507: linksw++; 508: continue; 509: case FINLINK: 510: linksw = 0; 511: continue; 512: 513: case FIPRES: 514: case FINPRES: 515: continue; 516: 517: case FISRC: 518: case FIDRFT: 519: case FIFILE: 520: advise (NULLCP, "sorry, -%s not allowed!", fileswit[i].sw); 521: return; 522: } 523: if (*cp == '+' || *cp == '@') 524: vec[vecp++] = cp; 525: else 526: msgs[msgp++] = cp; 527: } 528: 529: vec[0] = cmd_name; 530: vec[vecp++] = "-file"; 531: vec[vecp] = NULL; 532: if (!msgp) 533: msgs[msgp++] = "cur"; 534: for (msgnum = 0; msgnum < msgp; msgnum++) 535: if (!m_convert (mp, msgs[msgnum])) 536: return; 537: m_setseq (mp); 538: 539: interrupted = 0; 540: for (msgnum = mp -> lowsel; 541: msgnum <= mp -> hghsel && !interrupted; 542: msgnum++) 543: if (mp -> msgstats[msgnum] & SELECTED) 544: if (process (msgnum, fileproc, vecp, vec)) { 545: mp -> msgstats[msgnum] &= ~SELECTED; 546: mp -> numsel--; 547: } 548: 549: if (mp -> numsel != mp -> nummsg || linksw) 550: m_setcur (mp, mp -> hghsel); 551: if (!linksw) 552: rmm (); 553: } 554: 555: /* */ 556: 557: int filehak (args) 558: char **args; 559: { 560: int result, 561: vecp = 0; 562: char *cp, 563: *cwd, 564: *vec[MAXARGS]; 565: 566: while (cp = *args++) { 567: if (*cp == '-') 568: switch (smatch (++cp, fileswit)) { 569: case AMBIGSW: 570: case UNKWNSW: 571: case FIHELP: 572: return NOTOK; 573: 574: case FILINK: 575: case FINLINK: 576: case FIPRES: 577: case FINPRES: 578: continue; 579: 580: case FISRC: 581: case FIDRFT: 582: case FIFILE: 583: return NOTOK; 584: } 585: if (*cp == '+' || *cp == '@') 586: vec[vecp++] = cp; 587: } 588: vec[vecp] = NULL; 589: 590: result = NOTOK; 591: cwd = NULL; 592: for (vecp = 0; (cp = vec[vecp]) && result == NOTOK; vecp++) { 593: if (cwd == NULL) 594: cwd = getcpy (pwd ()); 595: (void) chdir (m_maildir ("")); 596: cp = path (cp + 1, *cp == '+' ? TFOLDER : TSUBCWF); 597: if (access (m_maildir (cp), 0) == NOTOK) 598: result = OK; 599: free (cp); 600: } 601: if (cwd) 602: (void) chdir (cwd); 603: 604: return result; 605: } 606: 607: /* */ 608: 609: static struct swit foldswit[] = { 610: #define FLALSW 0 611: "all", 0, 612: #define FLFASW 1 613: "fast", 0, 614: #define FLNFASW 2 615: "nofast", 0, 616: #define FLHDSW 3 617: "header", 0, 618: #define FLNHDSW 4 619: "noheader", 0, 620: #define FLPKSW 5 621: "pack", 0, 622: #define FLNPKSW 6 623: "nopack", 0, 624: #define FLRCSW 7 625: "recurse", 0, 626: #define FLNRCSW 8 627: "norecurse", 0, 628: #define FLTLSW 9 629: "total", 0, 630: #define FLNTLSW 10 631: "nototal", 0, 632: #define FLPRSW 11 633: "print", 0, 634: #define FLPUSW 12 635: "push", 0, 636: #define FLPOSW 13 637: "pop", 0, 638: #define FLLISW 14 639: "list", 0, 640: #define FLHELP 15 641: "help", 4, 642: 643: NULL, NULL 644: }; 645: 646: /* */ 647: 648: foldcmd (args) 649: char **args; 650: { 651: int fastsw = 0, 652: headersw = 0, 653: packsw = 0, 654: hole, 655: msgnum; 656: char *cp, 657: *folder = NULL, 658: *msg = NULL, 659: buf[BUFSIZ], 660: **vec = args; 661: 662: if (args == NULL) 663: goto fast; 664: 665: while (cp = *args++) { 666: if (*cp == '-') 667: switch (smatch (++cp, foldswit)) { 668: case AMBIGSW: 669: ambigsw (cp, foldswit); 670: return; 671: case UNKWNSW: 672: fprintf (stderr, "-%s unknown\n", cp); 673: return; 674: case FLHELP: 675: (void) sprintf (buf, "%s [+folder] [msg] [switches]", 676: cmd_name); 677: help (buf, foldswit); 678: return; 679: 680: case FLALSW: /* not implemented */ 681: case FLRCSW: 682: case FLNRCSW: 683: case FLTLSW: 684: case FLNTLSW: 685: case FLPRSW: 686: case FLPUSW: 687: case FLPOSW: 688: case FLLISW: 689: continue; 690: 691: case FLFASW: 692: fastsw++; 693: continue; 694: case FLNFASW: 695: fastsw = 0; 696: continue; 697: case FLHDSW: 698: headersw++; 699: continue; 700: case FLNHDSW: 701: headersw = 0; 702: continue; 703: case FLPKSW: 704: packsw++; 705: continue; 706: case FLNPKSW: 707: packsw = 0; 708: continue; 709: } 710: if (*cp == '+' || *cp == '@') 711: if (folder) { 712: advise (NULLCP, "only one folder at a time!\n"); 713: return; 714: } 715: else 716: folder = fmsh ? path (cp + 1, *cp == '+' ? TFOLDER : TSUBCWF) 717: : cp + 1; 718: else 719: if (msg) { 720: advise (NULLCP, "only one message at a time!\n"); 721: return; 722: } 723: else 724: msg = cp; 725: } 726: 727: if (folder) { 728: if (*folder == NULL) { 729: advise (NULLCP, "null folder names are not permitted"); 730: return; 731: } 732: if (fmsh) { 733: if (access (m_maildir (folder), 04) == NOTOK) { 734: advise (folder, "unable to read"); 735: return; 736: } 737: } 738: else { 739: (void) strcpy (buf, folder); 740: if (expand (buf) == NOTOK) 741: return; 742: folder = buf; 743: if (access (folder, 04) == NOTOK) { 744: advise (folder, "unable to read"); 745: return; 746: } 747: } 748: m_reset (); 749: 750: if (fmsh) 751: fsetup (folder); 752: else 753: setup (folder); 754: readids (0); 755: display_info (0); 756: } 757: 758: if (msg) { 759: if (!m_convert (mp, msg)) 760: return; 761: m_setseq (mp); 762: 763: if (mp -> numsel > 1) { 764: advise (NULLCP, "only one message at a time!"); 765: return; 766: } 767: m_setcur (mp, mp -> hghsel); 768: } 769: 770: if (packsw) { 771: if (fmsh) { 772: forkcmd (vec, cmd_name); 773: return; 774: } 775: 776: if (mp -> lowmsg > 1 && (mp = m_remsg (mp, 1, mp -> hghmsg)) == NULL) 777: adios (NULLCP, "unable to allocate folder storage"); 778: for (msgnum = mp -> lowmsg, hole = 1; msgnum <= mp -> hghmsg; msgnum++) 779: if (mp -> msgstats[msgnum] & EXISTS) { 780: if (msgnum != hole) { 781: Msgs[hole].m_bboard_id = Msgs[msgnum].m_bboard_id; 782: Msgs[hole].m_top = Msgs[msgnum].m_top; 783: Msgs[hole].m_start = Msgs[msgnum].m_start; 784: Msgs[hole].m_stop = Msgs[msgnum].m_stop; 785: Msgs[hole].m_scanl = NULL; 786: if (Msgs[msgnum].m_scanl) { 787: free (Msgs[msgnum].m_scanl); 788: Msgs[msgnum].m_scanl = NULL; 789: } 790: mp -> msgstats[hole] = mp -> msgstats[msgnum]; 791: if (mp -> curmsg == msgnum) 792: m_setcur (mp, hole); 793: } 794: hole++; 795: } 796: if (mp -> nummsg > 0) { 797: mp -> lowmsg = 1; 798: mp -> hghmsg = hole - 1; 799: } 800: mp -> msgflags |= MODIFIED; 801: modified++; 802: } 803: 804: fast: ; 805: if (fastsw) 806: printf ("%s\n", fmsh ? fmsh : mp -> foldpath); 807: else { 808: if (headersw) 809: printf ("\t\tFolder %*s# of messages (%*srange%*s); cur%*smsg\n", 810: DMAXFOLDER, "", DMAXFOLDER - 2, "", DMAXFOLDER - 2, "", 811: DMAXFOLDER - 2, ""); 812: printf (args ? "%22s " : "%s ", fmsh ? fmsh : mp -> foldpath); 813: if (mp -> hghmsg == 0) 814: printf ("has no messages%*s", 815: mp -> msgflags & OTHERS ? DMAXFOLDER * 2 + 4 : 0, ""); 816: else { 817: printf ("has %*d message%s (%*d-%*d)", 818: DMAXFOLDER, mp -> nummsg, mp -> nummsg != 1 ? "s" : "", 819: DMAXFOLDER, mp -> lowmsg, DMAXFOLDER, mp -> hghmsg); 820: if (mp -> curmsg >= mp -> lowmsg 821: && mp -> curmsg <= mp -> hghmsg) 822: printf ("; cur=%*d", DMAXFOLDER, mp -> curmsg); 823: } 824: printf (".\n"); 825: } 826: } 827: 828: /* */ 829: 830: static struct swit forwswit[] = { 831: #define FOANSW 0 832: "annotate", 0, 833: #define FONANSW 1 834: "noannotate", 0, 835: #define FODFSW 2 836: "draftfolder +folder", 0, 837: #define FODMSW 3 838: "draftmessage msg", 0, 839: #define FONDFSW 4 840: "nodraftfolder", 0, 841: #define FOEDTSW 5 842: "editor editor", 0, 843: #define FONEDSW 6 844: "noedit", 0, 845: #define FOFTRSW 7 846: "filter filterfile", 0, 847: #define FOFRMSW 8 848: "form formfile", 0, 849: #define FOFTSW 9 850: "format", 5, 851: #define FONFTSW 10 852: "noformat", 7, 853: #define FOINSW 11 854: "inplace", 0, 855: #define FONINSW 12 856: "noinplace", 0, 857: #define FOWHTSW 13 858: "whatnowproc program", 0, 859: #define FONWTSW 14 860: "nowhatnow", 0, 861: #define FOHELP 15 862: "help", 4, 863: 864: NULL, NULL 865: }; 866: 867: /* */ 868: 869: forwcmd (args) 870: char **args; 871: { 872: int msgp = 0, 873: vecp = 1, 874: msgnum; 875: char *cp, 876: *filter = NULL, 877: buf[BUFSIZ], 878: *msgs[MAXARGS], 879: *vec[MAXARGS]; 880: 881: if (fmsh) { 882: forkcmd (args, cmd_name); 883: return; 884: } 885: 886: while (cp = *args++) { 887: if (*cp == '-') 888: switch (smatch (++cp, forwswit)) { 889: case AMBIGSW: 890: ambigsw (cp, forwswit); 891: return; 892: case UNKWNSW: 893: fprintf (stderr, "-%s unknown\n", cp); 894: return; 895: case FOHELP: 896: (void) sprintf (buf, "%s [msgs] [switches]", cmd_name); 897: help (buf, forwswit); 898: return; 899: 900: case FOANSW: /* not implemented */ 901: case FONANSW: 902: case FOINSW: 903: case FONINSW: 904: continue; 905: 906: case FONDFSW: 907: case FONEDSW: 908: case FONWTSW: 909: vec[vecp++] = --cp; 910: continue; 911: 912: case FOEDTSW: 913: case FOFRMSW: 914: case FODFSW: 915: case FODMSW: 916: case FOWHTSW: 917: vec[vecp++] = --cp; 918: if (!(cp = *args++) || *cp == '-') { 919: advise (NULLCP, "missing argument to %s", args[-2]); 920: return; 921: } 922: vec[vecp++] = cp; 923: continue; 924: case FOFTRSW: 925: if (!(filter = *args++) || *filter == '-') { 926: advise (NULLCP, "missing argument to %s", args[-2]); 927: return; 928: } 929: continue; 930: case FOFTSW: 931: if (access (filter = myfilter, 04) == NOTOK) { 932: advise (filter, "unable to read default filter file"); 933: return; 934: } 935: continue; 936: case FONFTSW: 937: filter = NULL; 938: continue; 939: } 940: if (*cp == '+' || *cp == '@') { 941: advise (NULLCP, "sorry, no folders allowed!"); 942: return; 943: } 944: else 945: msgs[msgp++] = cp; 946: } 947: 948: /* foil search of .mh_profile */ 949: (void) sprintf (buf, "%sXXXXXX", invo_name); 950: vec[0] = mktemp (buf); 951: vec[vecp++] = "-file"; 952: vec[vecp] = NULL; 953: if (!msgp) 954: msgs[msgp++] = "cur"; 955: for (msgnum = 0; msgnum < msgp; msgnum++) 956: if (!m_convert (mp, msgs[msgnum])) 957: return; 958: m_setseq (mp); 959: 960: if (filter) { 961: (void) strcpy (buf, filter); 962: if (expand (buf) == NOTOK) 963: return; 964: if (access (filter = getcpy (libpath (buf)), 04) == NOTOK) { 965: advise (filter, "unable to read"); 966: free (filter); 967: return; 968: } 969: } 970: forw (cmd_name, filter, vecp, vec); 971: m_setcur (mp, mp -> hghsel); 972: if (filter) 973: free (filter); 974: } 975: 976: /* */ 977: 978: static forw (proc, filter, vecp, vec) 979: int vecp; 980: char *proc, 981: *filter, 982: **vec; 983: { 984: int i, 985: child_id, 986: msgnum, 987: msgcnt; 988: char tmpfil[80], 989: *args[MAXARGS]; 990: FILE *out; 991: 992: (void) strcpy (tmpfil, m_tmpfil (invo_name)); 993: interrupted = 0; 994: if (filter) 995: switch (child_id = fork ()) { 996: case NOTOK: 997: advise ("fork", "unable to"); 998: return; 999: 1000: case OK: /* "trust me" */ 1001: if (freopen (tmpfil, "w", stdout) == NULL) { 1002: fprintf (stderr, "unable to create "); 1003: perror (tmpfil); 1004: _exit (1); 1005: } 1006: args[0] = r1bindex (mhlproc, '/'); 1007: i = 1; 1008: args[i++] = "-forwall"; 1009: args[i++] = "-form"; 1010: args[i++] = filter; 1011: for (msgnum = mp -> lowsel; msgnum <= mp -> hghsel; msgnum++) 1012: if (mp -> msgstats[msgnum] & SELECTED) 1013: args[i++] = getcpy (m_name (msgnum)); 1014: args[i] = NULL; 1015: (void) mhlsbr (i, args, mhl_action); 1016: m_eomsbr ((int (*) ()) 0); 1017: (void) fclose (stdout); 1018: _exit (0); 1019: 1020: default: 1021: if (pidXwait (child_id, NULLCP)) 1022: interrupted++; 1023: break; 1024: } 1025: else { 1026: if ((out = fopen (tmpfil, "w")) == NULL) { 1027: advise (tmpfil, "unable to create temporary file"); 1028: return; 1029: } 1030: 1031: msgcnt = 1; 1032: for (msgnum = mp -> lowsel; 1033: msgnum <= mp -> hghsel && !interrupted; 1034: msgnum++) 1035: if (mp -> msgstats[msgnum] & SELECTED) { 1036: fprintf (out, "\n\n-------"); 1037: if (msgnum == mp -> lowsel) 1038: fprintf (out, " Forwarded Message%s", 1039: mp -> numsel > 1 ? "s" : ""); 1040: else 1041: fprintf (out, " Message %d", msgcnt); 1042: fprintf (out, "\n\n"); 1043: copy_digest (msgnum, out); 1044: msgcnt++; 1045: } 1046: 1047: fprintf (out, "\n\n------- End of Forwarded Message%s\n", 1048: mp -> numsel > 1 ? "s" : ""); 1049: (void) fclose (out); 1050: } 1051: 1052: (void) fflush (stdout); 1053: if (!interrupted) 1054: switch (child_id = fork ()) { 1055: case NOTOK: 1056: advise ("fork", "unable to"); 1057: break; 1058: 1059: case OK: 1060: closefds (3); 1061: (void) signal (SIGINT, istat); 1062: (void) signal (SIGQUIT, qstat); 1063: 1064: vec[vecp++] = tmpfil; 1065: vec[vecp] = NULL; 1066: 1067: execvp (proc, vec); 1068: fprintf (stderr, "unable to exec "); 1069: perror (proc); 1070: _exit (1); 1071: 1072: default: 1073: (void) pidXwait (child_id, NULLCP); 1074: break; 1075: } 1076: 1077: (void) unlink (tmpfil); 1078: } 1079: 1080: /* */ 1081: 1082: static char *hlpmsg[] = { 1083: "The %s program emulates many of the commands found in the Rand MH", 1084: "system. Instead of operating on MH folders, commands to %s concern", 1085: "a single file.", 1086: "", 1087: "To see the list of commands available, just type a ``?'' followed by", 1088: "the RETURN key. To find out what switches each command takes, type", 1089: "the name of the command followed by ``-help''. To leave %s, use the", 1090: "``quit'' command.", 1091: "", 1092: "Although a lot of MH commands are found in %s, not all are fully", 1093: "implemented. %s will always recognize all legal switches for a", 1094: "given command though, and will let you know when you ask for an", 1095: "option that it is unable to perform.", 1096: "", 1097: "Running %s is fun, but using MH from your shell is far superior.", 1098: "After you have familiarized yourself with the MH style by using %s,", 1099: "you should try using MH from the shell. You can still use %s for", 1100: "message files that aren't in MH format, such as BBoard files.", 1101: NULL 1102: }; 1103: 1104: 1105: /* ARGSUSED */ 1106: 1107: helpcmd (args) 1108: char **args; 1109: { 1110: int i; 1111: 1112: for (i = 0; hlpmsg[i]; i++) { 1113: printf (hlpmsg[i], invo_name); 1114: (void) putchar ('\n'); 1115: } 1116: } 1117: 1118: /* */ 1119: 1120: static struct swit markswit[] = { 1121: #define MADDSW 0 1122: "add", 0, 1123: #define MDELSW 1 1124: "delete", 0, 1125: #define MLSTSW 2 1126: "list", 0, 1127: #define MSEQSW 3 1128: "sequence name", 0, 1129: #define MPUBSW 4 1130: "public", 0, 1131: #define MNPUBSW 5 1132: "nopublic", 0, 1133: #define MZERSW 6 1134: "zero", 0, 1135: #define MNZERSW 7 1136: "nozero", 0, 1137: #define MHELP 8 1138: "help", 4, 1139: #define MDBUGSW 9 1140: "debug", -5, 1141: 1142: NULL, NULL 1143: }; 1144: 1145: /* */ 1146: 1147: markcmd (args) 1148: char **args; 1149: { 1150: int addsw = 0, 1151: deletesw = 0, 1152: debugsw = 0, 1153: listsw = 0, 1154: zerosw = 0, 1155: seqp = 0, 1156: msgp = 0, 1157: i, 1158: msgnum; 1159: char *cp, 1160: buf[BUFSIZ], 1161: *seqs[NATTRS + 1], 1162: *msgs[MAXARGS]; 1163: 1164: while (cp = *args++) { 1165: if (*cp == '-') 1166: switch (smatch (++cp, markswit)) { 1167: case AMBIGSW: 1168: ambigsw (cp, markswit); 1169: return; 1170: case UNKWNSW: 1171: fprintf (stderr, "-%s unknown\n", cp); 1172: return; 1173: case MHELP: 1174: (void) sprintf (buf, "%s [msgs] [switches]", cmd_name); 1175: help (buf, markswit); 1176: return; 1177: 1178: case MADDSW: 1179: addsw++; 1180: deletesw = listsw = 0; 1181: continue; 1182: case MDELSW: 1183: deletesw++; 1184: addsw = listsw = 0; 1185: continue; 1186: case MLSTSW: 1187: listsw++; 1188: addsw = deletesw = 0; 1189: continue; 1190: 1191: case MSEQSW: 1192: if (!(cp = *args++) || *cp == '-') { 1193: advise (NULLCP, "missing argument to %s", args[-2]); 1194: return; 1195: } 1196: if (seqp < NATTRS) 1197: seqs[seqp++] = cp; 1198: else { 1199: advise (NULLCP, "only %d sequences allowed!", NATTRS); 1200: return; 1201: } 1202: continue; 1203: 1204: case MPUBSW: /* not implemented */ 1205: case MNPUBSW: 1206: continue; 1207: 1208: case MDBUGSW: 1209: debugsw++; 1210: continue; 1211: 1212: case MZERSW: 1213: zerosw++; 1214: continue; 1215: case MNZERSW: 1216: zerosw = 0; 1217: continue; 1218: } 1219: if (*cp == '+' || *cp == '@') { 1220: advise (NULLCP, "sorry, no folders allowed!"); 1221: return; 1222: } 1223: else 1224: msgs[msgp++] = cp; 1225: } 1226: 1227: if (!addsw && !deletesw && !listsw) 1228: if (seqp) 1229: addsw++; 1230: else 1231: if (debugsw) 1232: listsw++; 1233: else { 1234: seqs[seqp++] = "unseen"; 1235: deletesw++; 1236: zerosw = 0; 1237: if (!msgp) 1238: msgs[msgp++] = "all"; 1239: } 1240: 1241: if (!msgp) 1242: msgs[msgp++] = listsw ? "all" :"cur"; 1243: for (msgnum = 0; msgnum < msgp; msgnum++) 1244: if (!m_convert (mp, msgs[msgnum])) 1245: return; 1246: 1247: if (debugsw) { 1248: printf ("invo_name=%s mypath=%s defpath=%s\n", 1249: invo_name, mypath, defpath); 1250: printf ("ctxpath=%s context flags=%s\n", 1251: ctxpath, sprintb (buf, (unsigned) ctxflags, DBITS)); 1252: printf ("foldpath=%s flags=%s\n", 1253: mp -> foldpath, 1254: sprintb (buf, (unsigned) mp -> msgflags, FBITS)); 1255: printf ("hghmsg=%d lowmsg=%d nummsg=%d curmsg=%d\n", 1256: mp -> hghmsg, mp -> lowmsg, mp -> nummsg, mp -> curmsg); 1257: printf ("lowsel=%d hghsel=%d numsel=%d\n", 1258: mp -> lowsel, mp -> hghsel, mp -> numsel); 1259: #ifndef MTR 1260: printf ("lowoff=%d hghoff=%d\n", 1261: mp -> lowoff, mp -> hghoff); 1262: #else MTR 1263: printf ("lowoff=%d hghoff=%d msgbase=0x%x msgstats=0x%x\n", 1264: mp -> lowoff, mp -> hghoff, mp -> msgbase, mp -> msgstats); 1265: #endif MTR 1266: } 1267: 1268: if (seqp == 0 && (addsw || deletesw)) { 1269: advise (NULLCP, "-%s requires at least one -sequence argument", 1270: addsw ? "add" : "delete"); 1271: return; 1272: } 1273: seqs[seqp] = NULL; 1274: 1275: if (addsw) 1276: for (seqp = 0; seqs[seqp]; seqp++) { 1277: if (zerosw && !m_seqnew (mp, seqs[seqp], 0)) 1278: return; 1279: for (msgnum = mp -> lowsel; msgnum <= mp -> hghsel; msgnum++) 1280: if (mp -> msgstats[msgnum] & SELECTED) 1281: if (!m_seqadd (mp, seqs[seqp], msgnum, 0)) 1282: return; 1283: } 1284: 1285: if (deletesw) 1286: for (seqp = 0; seqs[seqp]; seqp++) { 1287: if (zerosw) 1288: for (msgnum = mp -> lowmsg; msgnum <= mp -> hghmsg; msgnum++) 1289: if (mp -> msgstats[msgnum] & EXISTS) 1290: if (!m_seqadd (mp, seqs[seqp], msgnum, 0)) 1291: return; 1292: for (msgnum = mp -> lowsel; msgnum <= mp -> hghsel; msgnum++) 1293: if (mp -> msgstats[msgnum] & SELECTED) 1294: if (!m_seqdel (mp, seqs[seqp], msgnum)) 1295: return; 1296: } 1297: 1298: if (listsw) { 1299: int bits = FFATTRSLOT; 1300: 1301: if (seqp == 0) 1302: for (i = 0; mp -> msgattrs[i]; i++) 1303: printf ("%s%s: %s\n", mp -> msgattrs[i], 1304: mp -> attrstats & (1 << (bits + i)) 1305: ? " (private)" : "", 1306: m_seq (mp, mp -> msgattrs[i])); 1307: else 1308: for (seqp = 0; seqs[seqp]; seqp++) 1309: printf ("%s%s: %s\n", seqs[seqp], m_seq (mp, seqs[seqp])); 1310: 1311: interrupted = 0; 1312: if (debugsw) 1313: for (msgnum = mp -> lowsel; 1314: msgnum <= mp -> hghsel && !interrupted; 1315: msgnum++) 1316: if (mp -> msgstats[msgnum] & SELECTED) { 1317: printf ("%*d: id=%d top=%d start=%ld stop=%ld %s\n", 1318: DMAXFOLDER, msgnum, 1319: Msgs[msgnum].m_bboard_id, Msgs[msgnum].m_top, 1320: Msgs[msgnum].m_start, Msgs[msgnum].m_stop, 1321: sprintb (buf, (unsigned) mp -> msgstats[msgnum], 1322: m_seqbits (mp))); 1323: if (Msgs[msgnum].m_scanl) 1324: printf ("%s", Msgs[msgnum].m_scanl); 1325: } 1326: } 1327: } 1328: 1329: /* */ 1330: 1331: static struct swit packswit[] = { 1332: #define PAFISW 0 1333: "file name", 0, 1334: 1335: #define PAHELP 1 1336: "help", 4, 1337: 1338: NULL, NULL 1339: }; 1340: 1341: /* */ 1342: 1343: packcmd (args) 1344: char **args; 1345: { 1346: int msgp = 0, 1347: md, 1348: msgnum; 1349: char *cp, 1350: *file = NULL, 1351: buf[BUFSIZ], 1352: *msgs[MAXARGS]; 1353: struct stat st; 1354: 1355: if (fmsh) { 1356: forkcmd (args, cmd_name); 1357: return; 1358: } 1359: 1360: while (cp = *args++) { 1361: if (*cp == '-') 1362: switch (smatch (++cp, packswit)) { 1363: case AMBIGSW: 1364: ambigsw (cp, packswit); 1365: return; 1366: case UNKWNSW: 1367: fprintf (stderr, "-%s unknown\n", cp); 1368: return; 1369: case PAHELP: 1370: (void) sprintf (buf, "%s [msgs] [switches]", cmd_name); 1371: help (buf, packswit); 1372: return; 1373: 1374: case PAFISW: 1375: if (!(file = *args++) || *file == '-') { 1376: advise (NULLCP, "missing argument to %s", args[-2]); 1377: return; 1378: } 1379: continue; 1380: } 1381: if (*cp == '+' || *cp == '@') { 1382: advise (NULLCP, "sorry, no folders allowed!"); 1383: return; 1384: } 1385: else 1386: msgs[msgp++] = cp; 1387: } 1388: 1389: if (!file) 1390: file = "./msgbox"; 1391: file = path (file, TFILE); 1392: if (stat (file, &st) == NOTOK) { 1393: if (errno != ENOENT) { 1394: advise (file, "error on file"); 1395: goto done_pack; 1396: } 1397: md = getanswer (cp = concat ("Create file \"", file, "\"? ", NULLCP)); 1398: free (cp); 1399: if (!md) 1400: goto done_pack; 1401: } 1402: 1403: if (!msgp) 1404: msgs[msgp++] = "all"; 1405: for (msgnum = 0; msgnum < msgp; msgnum++) 1406: if (!m_convert (mp, msgs[msgnum])) 1407: goto done_pack; 1408: m_setseq (mp); 1409: 1410: if ((md = mbx_open (file, getuid (), getgid (), m_gmprot ())) == NOTOK) { 1411: advise (file, "unable to open"); 1412: goto done_pack; 1413: } 1414: for (msgnum = mp -> lowsel; msgnum <= mp -> hghsel; msgnum++) 1415: if (mp -> msgstats[msgnum] & SELECTED) 1416: if (pack (file, md, msgnum) == NOTOK) 1417: break; 1418: (void) mbx_close (file, md); 1419: 1420: if (mp -> hghsel != mp -> curmsg) 1421: m_setcur (mp, mp -> lowsel); 1422: 1423: done_pack: ; 1424: free (file); 1425: } 1426: 1427: /* */ 1428: 1429: int pack (mailbox, md, msgnum) 1430: char *mailbox; 1431: int md, 1432: msgnum; 1433: { 1434: register FILE *zp; 1435: 1436: if (Msgs[msgnum].m_bboard_id == 0) 1437: (void) readid (msgnum); 1438: 1439: zp = msh_ready (msgnum, 1); 1440: return mbx_write (mailbox, md, zp, Msgs[msgnum].m_bboard_id, 1441: ftell (zp), Msgs[msgnum].m_stop, 1, 1); 1442: } 1443: 1444: /* */ 1445: 1446: int packhak (args) 1447: char **args; 1448: { 1449: int result; 1450: char *cp, 1451: *file = NULL; 1452: 1453: while (cp = *args++) { 1454: if (*cp == '-') 1455: switch (smatch (++cp, packswit)) { 1456: case AMBIGSW: 1457: case UNKWNSW: 1458: case PAHELP: 1459: return NOTOK; 1460: 1461: case PAFISW: 1462: if (!(file = *args++) || *file == '-') 1463: return NOTOK; 1464: continue; 1465: } 1466: if (*cp == '+' || *cp == '@') 1467: return NOTOK; 1468: } 1469: 1470: file = path (file ? file : "./msgbox", TFILE); 1471: result = access (file, 0) == NOTOK ? OK : NOTOK; 1472: free (file); 1473: 1474: return result; 1475: } 1476: 1477: /* */ 1478: 1479: static struct swit pickswit[] = { 1480: #define PIANSW 0 1481: "and", 0, 1482: #define PIORSW 1 1483: "or", 0, 1484: #define PINTSW 2 1485: "not", 0, 1486: #define PILBSW 3 1487: "lbrace", 0, 1488: #define PIRBSW 4 1489: "rbrace", 0, 1490: 1491: #define PICCSW 5 1492: "cc pattern", 0, 1493: #define PIDASW 6 1494: "date pattern", 0, 1495: #define PIFRSW 7 1496: "from pattern", 0, 1497: #define PISESW 8 1498: "search pattern", 0, 1499: #define PISUSW 9 1500: "subject pattern", 0, 1501: #define PITOSW 10 1502: "to pattern", 0, 1503: #define PIOTSW 11 1504: "-othercomponent pattern", 15, 1505: #define PIAFSW 12 1506: "after date", 0, 1507: #define PIBFSW 13 1508: "before date", 0, 1509: #define PIDFSW 14 1510: "datefield field", 5, 1511: #define PISQSW 15 1512: "sequence name", 0, 1513: #define PIPUSW 16 1514: "public", 0, 1515: #define PINPUSW 17 1516: "nopublic", 0, 1517: #define PIZRSW 18 1518: "zero", 0, 1519: #define PINZRSW 19 1520: "nozero", 0, 1521: #define PILISW 20 1522: "list", 0, 1523: #define PINLISW 21 1524: "nolist", 0, 1525: #define PIHELP 22 1526: "help", 4, 1527: 1528: NULL, NULL 1529: }; 1530: 1531: /* */ 1532: 1533: pickcmd (args) 1534: char **args; 1535: { 1536: int zerosw = 1, 1537: msgp = 0, 1538: seqp = 0, 1539: vecp = 0, 1540: hi, 1541: lo, 1542: msgnum; 1543: char *cp, 1544: buf[BUFSIZ], 1545: *msgs[MAXARGS], 1546: *seqs[NATTRS], 1547: *vec[MAXARGS]; 1548: register FILE *zp; 1549: 1550: while (cp = *args++) { 1551: if (*cp == '-') { 1552: if (*++cp == '-') { 1553: vec[vecp++] = --cp; 1554: goto pattern; 1555: } 1556: switch (smatch (cp, pickswit)) { 1557: case AMBIGSW: 1558: ambigsw (cp, pickswit); 1559: return; 1560: case UNKWNSW: 1561: fprintf (stderr, "-%s unknown\n", cp); 1562: return; 1563: case PIHELP: 1564: (void) sprintf (buf, "%s [msgs] [switches]", cmd_name); 1565: help (buf, pickswit); 1566: return; 1567: 1568: case PICCSW: 1569: case PIDASW: 1570: case PIFRSW: 1571: case PISUSW: 1572: case PITOSW: 1573: case PIDFSW: 1574: case PIAFSW: 1575: case PIBFSW: 1576: case PISESW: 1577: vec[vecp++] = --cp; 1578: pattern: ; 1579: if (!(cp = *args++)) {/* allow -xyz arguments */ 1580: advise (NULLCP, "missing argument to %s", args[-2]); 1581: return; 1582: } 1583: vec[vecp++] = cp; 1584: continue; 1585: case PIOTSW: 1586: advise (NULLCP, "internal error!"); 1587: return; 1588: case PIANSW: 1589: case PIORSW: 1590: case PINTSW: 1591: case PILBSW: 1592: case PIRBSW: 1593: vec[vecp++] = --cp; 1594: continue; 1595: 1596: case PISQSW: 1597: if (!(cp = *args++) || *cp == '-') { 1598: advise (NULLCP, "missing argument to %s", args[-2]); 1599: return; 1600: } 1601: if (seqp < NATTRS) 1602: seqs[seqp++] = cp; 1603: else { 1604: advise (NULLCP, "only %d sequences allowed!", NATTRS); 1605: return; 1606: } 1607: continue; 1608: case PIZRSW: 1609: zerosw++; 1610: continue; 1611: case PINZRSW: 1612: zerosw = 0; 1613: continue; 1614: 1615: case PIPUSW: /* not implemented */ 1616: case PINPUSW: 1617: case PILISW: 1618: case PINLISW: 1619: continue; 1620: } 1621: } 1622: if (*cp == '+' || *cp == '@') { 1623: advise (NULLCP, "sorry, no folders allowed!"); 1624: return; 1625: } 1626: else 1627: msgs[msgp++] = cp; 1628: } 1629: vec[vecp] = NULL; 1630: 1631: if (!msgp) 1632: msgs[msgp++] = "all"; 1633: for (msgnum = 0; msgnum < msgp; msgnum++) 1634: if (!m_convert (mp, msgs[msgnum])) 1635: return; 1636: m_setseq (mp); 1637: 1638: interrupted = 0; 1639: if (!pcompile (vec, NULLCP)) 1640: return; 1641: 1642: lo = mp -> lowsel; 1643: hi = mp -> hghsel; 1644: 1645: for (msgnum = mp -> lowsel; 1646: msgnum <= mp -> hghsel && !interrupted; 1647: msgnum++) 1648: if (mp -> msgstats[msgnum] & SELECTED) { 1649: zp = msh_ready (msgnum, 1); 1650: if (pmatches (zp, msgnum, fmsh ? 0L : Msgs[msgnum].m_start, 1651: fmsh ? 0L : Msgs[msgnum].m_stop)) { 1652: if (msgnum < lo) 1653: lo = msgnum; 1654: if (msgnum > hi) 1655: hi = msgnum; 1656: } 1657: else { 1658: mp -> msgstats[msgnum] &= ~SELECTED; 1659: mp -> numsel--; 1660: } 1661: } 1662: 1663: if (interrupted) 1664: return; 1665: 1666: mp -> lowsel = lo; 1667: mp -> hghsel = hi; 1668: 1669: if (mp -> numsel <= 0) { 1670: advise (NULLCP, "no messages match specification"); 1671: return; 1672: } 1673: 1674: seqs[seqp] = NULL; 1675: for (seqp = 0; seqs[seqp]; seqp++) { 1676: if (zerosw && !m_seqnew (mp, seqs[seqp], 0)) 1677: return; 1678: for (msgnum = mp -> lowsel; msgnum <= mp -> hghsel; msgnum++) 1679: if (mp -> msgstats[msgnum] & SELECTED) 1680: if (!m_seqadd (mp, seqs[seqp], msgnum, 0)) 1681: return; 1682: } 1683: 1684: printf ("%d hit%s\n", mp -> numsel, mp -> numsel == 1 ? "" : "s"); 1685: } 1686: 1687: /* */ 1688: 1689: static struct swit replswit[] = { 1690: #define REANSW 0 1691: "annotate", 0, 1692: #define RENANSW 1 1693: "noannotate", 0, 1694: #define RECCSW 2 1695: "cc type", 0, 1696: #define RENCCSW 3 1697: "nocc type", 0, 1698: #define REDFSW 4 1699: "draftfolder +folder", 0, 1700: #define REDMSW 5 1701: "draftmessage msg", 0, 1702: #define RENDFSW 6 1703: "nodraftfolder", 0, 1704: #define REEDTSW 7 1705: "editor editor", 0, 1706: #define RENEDSW 8 1707: "noedit", 0, 1708: #define REFCCSW 9 1709: "fcc +folder", 0, 1710: #define REFLTSW 10 1711: "filter filterfile", 0, 1712: #define REFRMSW 11 1713: "form formfile", 0, 1714: #define REFRSW 12 1715: "format", 5, 1716: #define RENFRSW 13 1717: "noformat", 7, 1718: #define REINSW 14 1719: "inplace", 0, 1720: #define RENINSW 15 1721: "noinplace", 0, 1722: #define REQUSW 16 1723: "query", 0, 1724: #define RENQUSW 17 1725: "noquery", 0, 1726: #define REWHTSW 18 1727: "whatnowproc program", 0, 1728: #define RENWTSW 19 1729: "nowhatnow", 0, 1730: #define REWIDSW 20 1731: "width columns", 0, 1732: #define REHELP 21 1733: "help", 4, 1734: 1735: NULL, NULL 1736: }; 1737: 1738: /* */ 1739: 1740: replcmd (args) 1741: char **args; 1742: { 1743: int vecp = 1; 1744: char *cp, 1745: *msg = NULL, 1746: buf[BUFSIZ], 1747: *vec[MAXARGS]; 1748: 1749: if (fmsh) { 1750: forkcmd (args, cmd_name); 1751: return; 1752: } 1753: 1754: while (cp = *args++) { 1755: if (*cp == '-') 1756: switch (smatch (++cp, replswit)) { 1757: case AMBIGSW: 1758: ambigsw (cp, replswit); 1759: return; 1760: case UNKWNSW: 1761: fprintf (stderr, "-%s unknown\n", cp); 1762: return; 1763: case REHELP: 1764: (void) sprintf (buf, "%s [msgs] [switches]", cmd_name); 1765: help (buf, replswit); 1766: return; 1767: 1768: case REANSW: /* not implemented */ 1769: case RENANSW: 1770: case REINSW: 1771: case RENINSW: 1772: continue; 1773: 1774: case REFRSW: 1775: case RENFRSW: 1776: case REQUSW: 1777: case RENQUSW: 1778: case RENDFSW: 1779: case RENEDSW: 1780: case RENWTSW: 1781: vec[vecp++] = --cp; 1782: continue; 1783: 1784: case RECCSW: 1785: case RENCCSW: 1786: case REEDTSW: 1787: case REFCCSW: 1788: case REFLTSW: 1789: case REFRMSW: 1790: case REWIDSW: 1791: case REDFSW: 1792: case REDMSW: 1793: case REWHTSW: 1794: vec[vecp++] = --cp; 1795: if (!(cp = *args++) || *cp == '-') { 1796: advise (NULLCP, "missing argument to %s", args[-2]); 1797: return; 1798: } 1799: vec[vecp++] = cp; 1800: continue; 1801: } 1802: if (*cp == '+' || *cp == '@') { 1803: advise (NULLCP, "sorry, no folders allowed!"); 1804: return; 1805: } 1806: else 1807: if (msg) { 1808: advise (NULLCP, "only one message at a time!"); 1809: return; 1810: } 1811: else 1812: msg = cp; 1813: } 1814: 1815: vec[0] = cmd_name; 1816: vec[vecp++] = "-file"; 1817: vec[vecp] = NULL; 1818: if (!msg) 1819: msg = "cur"; 1820: if (!m_convert (mp, msg)) 1821: return; 1822: m_setseq (mp); 1823: 1824: if (mp -> numsel > 1) { 1825: advise (NULLCP, "only one message at a time!"); 1826: return; 1827: } 1828: (void) process (mp -> hghsel, cmd_name, vecp, vec); 1829: m_setcur (mp, mp -> hghsel); 1830: } 1831: 1832: /* */ 1833: 1834: static struct swit rmmswit[] = { 1835: #define RMHELP 0 1836: "help", 4, 1837: 1838: NULL, NULL 1839: }; 1840: 1841: /* */ 1842: 1843: rmmcmd (args) 1844: char **args; 1845: { 1846: int msgp = 0, 1847: msgnum; 1848: char *cp, 1849: buf[BUFSIZ], 1850: *msgs[MAXARGS]; 1851: 1852: while (cp = *args++) { 1853: if (*cp == '-') 1854: switch (smatch (++cp, rmmswit)) { 1855: case AMBIGSW: 1856: ambigsw (cp, rmmswit); 1857: return; 1858: case UNKWNSW: 1859: fprintf (stderr, "-%s unknown\n", cp); 1860: return; 1861: case RMHELP: 1862: (void) sprintf (buf, "%s [msgs] [switches]", cmd_name); 1863: help (buf, rmmswit); 1864: return; 1865: } 1866: if (*cp == '+' || *cp == '@') { 1867: advise (NULLCP, "sorry, no folders allowed!"); 1868: return; 1869: } 1870: else 1871: msgs[msgp++] = cp; 1872: } 1873: 1874: if (!msgp) 1875: msgs[msgp++] = "cur"; 1876: for (msgnum = 0; msgnum < msgp; msgnum++) 1877: if (!m_convert (mp, msgs[msgnum])) 1878: return; 1879: m_setseq (mp); 1880: 1881: rmm (); 1882: } 1883: 1884: /* */ 1885: 1886: static rmm () { 1887: register int msgnum, 1888: vecp; 1889: register char *cp; 1890: char buffer[BUFSIZ], 1891: *vec[MAXARGS]; 1892: 1893: if (fmsh) { 1894: if (rmmproc) { 1895: if (mp -> numsel > MAXARGS - 1) { 1896: advise (NULLCP, "more than %d messages for %s exec", 1897: MAXARGS - 1, rmmproc); 1898: return; 1899: } 1900: vecp = 0; 1901: for (msgnum = mp -> lowsel; msgnum <= mp -> hghsel; msgnum++) 1902: if (mp -> msgstats[msgnum] & SELECTED) 1903: vec[vecp++] = getcpy (m_name (msgnum)); 1904: vec[vecp] = NULL; 1905: forkcmd (vec, rmmproc); 1906: for (vecp = 0; vec[vecp]; vecp++) 1907: free (vec[vecp]); 1908: } 1909: else 1910: for (msgnum = mp -> lowsel; msgnum <= mp -> hghsel; msgnum++) 1911: if (mp -> msgstats[msgnum] & SELECTED) { 1912: (void) strcpy (buffer, m_backup (cp = m_name (msgnum))); 1913: if (rename (cp, buffer) == NOTOK) 1914: admonish (buffer, "unable to rename %s to", cp); 1915: } 1916: } 1917: 1918: for (msgnum = mp -> lowsel; msgnum <= mp -> hghsel; msgnum++) 1919: if (mp -> msgstats[msgnum] & SELECTED) { 1920: mp -> msgstats[msgnum] |= DELETED; 1921: mp -> msgstats[msgnum] &= ~EXISTS; 1922: } 1923: 1924: if ((mp -> nummsg -= mp -> numsel) <= 0) { 1925: if (fmsh) 1926: admonish (NULLCP, "no messages remaining in +%s", fmsh); 1927: else 1928: admonish (NULLCP, "no messages remaining in %s", mp -> foldpath); 1929: mp -> lowmsg = mp -> hghmsg = mp -> nummsg = 0; 1930: } 1931: if (mp -> lowsel == mp -> lowmsg) { 1932: for (msgnum = mp -> lowmsg + 1; msgnum <= mp -> hghmsg; msgnum++) 1933: if (mp -> msgstats[msgnum] & EXISTS) 1934: break; 1935: mp -> lowmsg = msgnum; 1936: } 1937: if (mp -> hghsel == mp -> hghmsg) { 1938: for (msgnum = mp -> hghmsg - 1; msgnum >= mp -> lowmsg; msgnum--) 1939: if (mp -> msgstats[msgnum] & EXISTS) 1940: break; 1941: mp -> hghmsg = msgnum; 1942: } 1943: 1944: mp -> msgflags |= MODIFIED; 1945: modified++; 1946: } 1947: 1948: /* */ 1949: 1950: static struct swit scanswit[] = { 1951: #define SCCLR 0 1952: "clear", 0, 1953: #define SCNCLR 1 1954: "noclear", 0, 1955: #define SCFORM 2 1956: "form formatfile", 0, 1957: #define SCFMT 3 1958: "format string", 5, 1959: #define SCHEAD 4 1960: "header", 0, 1961: #define SCNHEAD 5 1962: "noheader", 0, 1963: #define SCWID 6 1964: "width columns", 0, 1965: #define SCHELP 7 1966: "help", 4, 1967: 1968: NULL, NULL 1969: }; 1970: 1971: /* */ 1972: 1973: scancmd (args) 1974: char **args; 1975: { 1976: #define equiv(a,b) (a ? b && !strcmp (a, b) : !b) 1977: 1978: int clearsw = 0, 1979: headersw = 0, 1980: width = 0, 1981: msgp = 0, 1982: msgnum, 1983: optim, 1984: state; 1985: char *cp, 1986: *form = NULL, 1987: *format = NULL, 1988: buf[BUFSIZ], 1989: *nfs, 1990: *msgs[MAXARGS]; 1991: register FILE *zp; 1992: static int s_optim = 0; 1993: static char *s_form = NULL, 1994: *s_format = NULL; 1995: 1996: while (cp = *args++) { 1997: if (*cp == '-') 1998: switch (smatch (++cp, scanswit)) { 1999: case AMBIGSW: 2000: ambigsw (cp, scanswit); 2001: return; 2002: case UNKWNSW: 2003: fprintf (stderr, "-%s unknown\n", cp); 2004: return; 2005: case SCHELP: 2006: (void) sprintf (buf, "%s [msgs] [switches]", cmd_name); 2007: help (buf, scanswit); 2008: return; 2009: 2010: case SCCLR: 2011: clearsw++; 2012: continue; 2013: case SCNCLR: 2014: clearsw = 0; 2015: continue; 2016: case SCHEAD: 2017: headersw++; 2018: continue; 2019: case SCNHEAD: 2020: headersw = 0; 2021: continue; 2022: case SCFORM: 2023: if (!(form = *args++) || *form == '-') { 2024: advise (NULLCP, "missing argument to %s", args[-2]); 2025: return; 2026: } 2027: format = NULL; 2028: continue; 2029: case SCFMT: 2030: if (!(format = *args++) || *format == '-') { 2031: advise (NULLCP, "missing argument to %s", args[-2]); 2032: return; 2033: } 2034: form = NULL; 2035: continue; 2036: case SCWID: 2037: if (!(cp = *args++) || *cp == '-') { 2038: advise (NULLCP, "missing argument to %s", args[-2]); 2039: return; 2040: } 2041: width = atoi (cp); 2042: continue; 2043: } 2044: if (*cp == '+' || *cp == '@') { 2045: advise (NULLCP, "sorry, no folders allowed!"); 2046: return; 2047: } 2048: else 2049: msgs[msgp++] = cp; 2050: } 2051: 2052: if (!msgp) 2053: msgs[msgp++] = "all"; 2054: for (msgnum = 0; msgnum < msgp; msgnum++) 2055: if (!m_convert (mp, msgs[msgnum])) 2056: return; 2057: m_setseq (mp); 2058: 2059: nfs = new_fs (form, format, FORMAT); 2060: if (scanl) { /* force scansbr to (re)compile format */ 2061: (void) free (scanl); 2062: scanl = NULL; 2063: } 2064: 2065: if (s_optim == 0) { 2066: s_optim = optim = 1; 2067: s_form = form ? getcpy (form) : NULL; 2068: s_format = format ? getcpy (format) : NULL; 2069: } 2070: else 2071: optim = equiv (s_form, form) && equiv (s_format, format); 2072: 2073: interrupted = 0; 2074: for (msgnum = mp -> lowsel; 2075: msgnum <= mp -> hghsel && !interrupted; 2076: msgnum++) 2077: if (mp -> msgstats[msgnum] & SELECTED) { 2078: if (optim && Msgs[msgnum].m_scanl) 2079: printf ("%s", Msgs[msgnum].m_scanl); 2080: else { 2081: zp = msh_ready (msgnum, 0); 2082: switch (state = scan (zp, msgnum, 0, nfs, width, 2083: msgnum == mp -> curmsg, headersw, 2084: fmsh ? 0L : (long) (Msgs[msgnum].m_stop - Msgs[msgnum].m_start), 2085: 1)) { 2086: case SCNMSG: 2087: case SCNERR: 2088: if (optim) 2089: Msgs[msgnum].m_scanl = getcpy (scanl); 2090: break; 2091: 2092: default: 2093: advise (NULLCP, "scan() botch (%d)", state); 2094: return; 2095: 2096: case SCNEOF: 2097: printf ("%*d empty\n", DMAXFOLDER, msgnum); 2098: break; 2099: } 2100: } 2101: headersw = 0; 2102: } 2103: 2104: if (clearsw) 2105: clear_screen (); 2106: } 2107: 2108: /* */ 2109: 2110: static struct swit showswit[] = { 2111: #define SHDRAFT 0 2112: "draft", 5, 2113: #define SHFORM 1 2114: "form formfile", 4, 2115: #define SHPROG 2 2116: "moreproc program", 4, 2117: #define SHNPROG 3 2118: "nomoreproc", 3, 2119: #define SHLEN 4 2120: "length lines", 4, 2121: #define SHWID 5 2122: "width columns", 4, 2123: #define SHSHOW 6 2124: "showproc program", 4, 2125: #define SHNSHOW 7 2126: "noshowproc", 3, 2127: #define SHHEAD 8 2128: "header", 4, 2129: #define SHNHEAD 9 2130: "noheader", 3, 2131: #define SHHELP 10 2132: "help", 4, 2133: 2134: NULL, NULL 2135: }; 2136: 2137: /* */ 2138: 2139: showcmd (args) 2140: char **args; 2141: { 2142: int headersw = 1, 2143: nshow = 0, 2144: msgp = 0, 2145: vecp = 1, 2146: mhl = 0, 2147: seen = 0, 2148: mode = 0, 2149: i, 2150: msgnum; 2151: char *cp, 2152: *proc = showproc, 2153: buf[BUFSIZ], 2154: *msgs[MAXARGS], 2155: *vec[MAXARGS]; 2156: 2157: if (uleq (cmd_name, "next")) 2158: mode = 1; 2159: else 2160: if (uleq (cmd_name, "prev")) 2161: mode = -1; 2162: while (cp = *args++) { 2163: if (*cp == '-') 2164: switch (i = smatch (++cp, showswit)) { 2165: case AMBIGSW: 2166: ambigsw (cp, showswit); 2167: return; 2168: case UNKWNSW: 2169: case SHNPROG: 2170: vec[vecp++] = --cp; 2171: continue; 2172: case SHHELP: 2173: (void) sprintf (buf, 2174: "%s %s[switches] [switches for showproc]", 2175: cmd_name, mode ? NULL : "[msgs] "); 2176: help (buf, showswit); 2177: return; 2178: 2179: case SHFORM: 2180: case SHPROG: 2181: case SHLEN: 2182: case SHWID: 2183: vec[vecp++] = --cp; 2184: if (!(cp = *args++) || *cp == '-') { 2185: advise (NULLCP, "missing argument to %s", args[-2]); 2186: return; 2187: } 2188: vec[vecp++] = cp; 2189: continue; 2190: case SHHEAD: 2191: headersw++; 2192: continue; 2193: case SHNHEAD: 2194: headersw = 0; 2195: continue; 2196: case SHSHOW: 2197: if (!(proc = *args++) || *proc == '-') { 2198: advise (NULLCP, "missing argument to %s", args[-2]); 2199: return; 2200: } 2201: nshow = 0; 2202: continue; 2203: case SHNSHOW: 2204: nshow++; 2205: continue; 2206: 2207: case SHDRAFT: 2208: advise (NULLCP, "sorry, -%s not allowed!", showswit[i].sw); 2209: return; 2210: } 2211: if (*cp == '+' || *cp == '@') { 2212: advise (NULLCP, "sorry, no folders allowed!"); 2213: return; 2214: } 2215: else 2216: if (mode) { 2217: fprintf (stderr, 2218: "usage: %s [switches] [switches for showproc]\n", 2219: cmd_name); 2220: return; 2221: } 2222: else 2223: msgs[msgp++] = cp; 2224: } 2225: vec[vecp] = NULL; 2226: 2227: if (!msgp) 2228: msgs[msgp++] = mode > 0 ? "next" : mode < 0 ? "prev" : "cur"; 2229: for (msgnum = 0; msgnum < msgp; msgnum++) 2230: if (!m_convert (mp, msgs[msgnum])) 2231: return; 2232: m_setseq (mp); 2233: 2234: if (nshow) 2235: proc = "cat"; 2236: else 2237: if (strcmp (showproc, "mhl") == 0) { 2238: proc = mhlproc; 2239: mhl++; 2240: } 2241: 2242: seen = m_seqflag (mp, "unseen"); 2243: vec[0] = r1bindex (proc, '/'); 2244: if (mhl) { 2245: msgp = vecp; 2246: for (msgnum = mp -> lowsel; msgnum <= mp -> hghsel; msgnum++) 2247: if (mp -> msgstats[msgnum] & SELECTED) { 2248: vec[vecp++] = getcpy (m_name (msgnum)); 2249: if (seen) 2250: (void) m_seqdel (mp, "unseen", msgnum); 2251: } 2252: vec[vecp] = NULL; 2253: if (mp -> numsel == 1 && headersw) 2254: show (mp -> lowsel); 2255: (void) mhlsbr (vecp, vec, mhl_action); 2256: m_eomsbr ((int (*)()) 0); 2257: while (msgp < vecp) 2258: free (vec[msgp++]); 2259: } 2260: else { 2261: interrupted = 0; 2262: for (msgnum = mp -> lowsel; 2263: msgnum <= mp -> hghsel && !interrupted; 2264: msgnum++) 2265: if (mp -> msgstats[msgnum] & SELECTED) { 2266: switch (ask (msgnum)) { 2267: case NOTOK: /* QUIT */ 2268: break; 2269: 2270: case OK: /* INTR */ 2271: continue; 2272: 2273: default: 2274: if (mp -> numsel == 1 && headersw) 2275: show (msgnum); 2276: if (nshow) 2277: copy_message (msgnum, stdout); 2278: else 2279: (void) process (msgnum, proc, vecp, vec); 2280: 2281: if (seen) 2282: (void) m_seqdel (mp, "unseen", msgnum); 2283: continue; 2284: } 2285: break; 2286: } 2287: } 2288: 2289: m_setcur (mp, mp -> hghsel); 2290: } 2291: 2292: /* */ 2293: 2294: static show (msgnum) 2295: int msgnum; 2296: { 2297: if (Msgs[msgnum].m_bboard_id == 0) 2298: (void) readid (msgnum); 2299: 2300: printf ("(Message %d", msgnum); 2301: if (Msgs[msgnum].m_bboard_id > 0) 2302: printf (", %s: %d", BBoard_ID, Msgs[msgnum].m_bboard_id); 2303: printf (")\n"); 2304: } 2305: 2306: 2307: /* ARGSUSED */ 2308: 2309: static int eom_action (c) 2310: int c; 2311: { 2312: return (ftell (mhlfp) >= Msgs[mhlnum].m_stop); 2313: } 2314: 2315: 2316: static FP mhl_action (name) 2317: char *name; 2318: { 2319: int msgnum; 2320: 2321: if ((msgnum = m_atoi (name)) < mp -> lowmsg 2322: || msgnum > mp -> hghmsg 2323: || !(mp -> msgstats[msgnum] & EXISTS)) 2324: return NULL; 2325: mhlnum = msgnum; 2326: 2327: mhlfp = msh_ready (msgnum, 1); 2328: if (!fmsh) 2329: m_eomsbr (eom_action); 2330: 2331: return mhlfp; 2332: } 2333: 2334: 2335: /* */ 2336: 2337: static ask (msgnum) 2338: int msgnum; 2339: { 2340: char buf[BUFSIZ]; 2341: 2342: if (mp -> numsel == 1 || !interactive || redirected) 2343: return DONE; 2344: 2345: if (SOprintf ("Press <return> to list \"%d\"...", msgnum)) { 2346: if (mp -> lowsel != msgnum) 2347: printf ("\n\n\n"); 2348: printf ("Press <return> to list \"%d\"...", msgnum); 2349: } 2350: (void) fflush (stdout); 2351: buf[0] = NULL; 2352: #ifndef BSD42 2353: (void) read (fileno (stdout), buf, sizeof buf); 2354: #else BSD42 2355: switch (setjmp (sigenv)) { 2356: case OK: 2357: should_intr = 1; 2358: (void) read (fileno (stdout), buf, sizeof buf);/* fall... */ 2359: 2360: default: 2361: should_intr = 0; 2362: break; 2363: } 2364: #endif BSD42 2365: if (index (buf, '\n') == NULL) 2366: (void) putchar ('\n'); 2367: 2368: if (told_to_quit) { 2369: told_to_quit = interrupted = 0; 2370: return NOTOK; 2371: } 2372: if (interrupted) { 2373: interrupted = 0; 2374: return OK; 2375: } 2376: 2377: return DONE; 2378: } 2379: 2380: /* */ 2381: 2382: static struct swit sortswit[] = { 2383: #define SODATE 0 2384: "datefield field", 0, 2385: #define SOVERB 1 2386: "verbose", 0, 2387: #define SONVERB 2 2388: "noverbose", 0, 2389: #define SOHELP 3 2390: "help", 4, 2391: 2392: NULL, NULL 2393: }; 2394: 2395: /* */ 2396: 2397: sortcmd (args) 2398: char **args; 2399: { 2400: int msgp = 0, 2401: msgnum; 2402: char *cp, 2403: *datesw = NULL, 2404: buf[BUFSIZ], 2405: *msgs[MAXARGS]; 2406: struct tws tb, 2407: *tw; 2408: 2409: if (fmsh) { 2410: forkcmd (args, cmd_name); 2411: return; 2412: } 2413: 2414: while (cp = *args++) { 2415: if (*cp == '-') 2416: switch (smatch (++cp, sortswit)) { 2417: case AMBIGSW: 2418: ambigsw (cp, sortswit); 2419: return; 2420: case UNKWNSW: 2421: fprintf (stderr, "-%s unknown\n", cp); 2422: return; 2423: case SOHELP: 2424: (void) sprintf (buf, "%s [msgs] [switches]", cmd_name); 2425: help (buf, sortswit); 2426: return; 2427: 2428: case SODATE: 2429: if (datesw) { 2430: advise (NULLCP, "only one date field at a time!"); 2431: return; 2432: } 2433: if (!(datesw = *args++) || *datesw == '-') { 2434: advise (NULLCP, "missing argument to %s", args[-2]); 2435: return; 2436: } 2437: continue; 2438: 2439: case SOVERB: /* not implemented */ 2440: case SONVERB: 2441: continue; 2442: } 2443: if (*cp == '+' || *cp == '@') { 2444: advise (NULLCP, "sorry, no folders allowed!"); 2445: return; 2446: } 2447: else 2448: msgs[msgp++] = cp; 2449: } 2450: 2451: if (!msgp) 2452: msgs[msgp++] = "all"; 2453: if (!datesw) 2454: datesw = "Date"; 2455: for (msgnum = 0; msgnum < msgp; msgnum++) 2456: if (!m_convert (mp, msgs[msgnum])) 2457: return; 2458: m_setseq (mp); 2459: 2460: twscopy (&tb, dtwstime ()); 2461: 2462: for (msgnum = mp -> lowsel; msgnum <= mp -> hghsel; msgnum++) { 2463: if (Msgs[msgnum].m_scanl) { 2464: free (Msgs[msgnum].m_scanl); 2465: Msgs[msgnum].m_scanl = NULL; 2466: } 2467: if (mp -> msgstats[msgnum] & SELECTED) { 2468: if ((tw = getws (datesw, msgnum)) == NULL) 2469: tw = msgnum != mp -> lowsel ? &Msgs[msgnum - 1].m_tb : &tb; 2470: } 2471: else 2472: tw = &tb; 2473: twscopy (&Msgs[msgnum].m_tb, tw); 2474: Msgs[msgnum].m_stats = mp -> msgstats[msgnum]; 2475: if (mp -> curmsg == msgnum) 2476: Msgs[msgnum].m_stats |= CUR; 2477: } 2478: 2479: qsort ((char *) &Msgs[mp -> lowsel], mp -> hghsel - mp -> lowsel + 1, 2480: sizeof (struct Msg), msgsort); 2481: 2482: for (msgnum = mp -> lowsel; msgnum <= mp -> hghsel; msgnum++) { 2483: mp -> msgstats[msgnum] = Msgs[msgnum].m_stats & ~CUR; 2484: if (Msgs[msgnum].m_stats & CUR) 2485: m_setcur (mp, msgnum); 2486: } 2487: 2488: mp -> msgflags |= MODIFIED; 2489: modified++; 2490: } 2491: 2492: /* */ 2493: 2494: static struct tws *getws (datesw, msgnum) 2495: char *datesw; 2496: int msgnum; 2497: { 2498: int state; 2499: char *bp, 2500: buf[BUFSIZ], 2501: name[NAMESZ]; 2502: struct tws *tw; 2503: register FILE *zp; 2504: 2505: zp = msh_ready (msgnum, 0); 2506: for (state = FLD;;) 2507: switch (state = m_getfld (state, name, buf, sizeof buf, zp)) { 2508: case FLD: 2509: case FLDEOF: 2510: case FLDPLUS: 2511: if (uleq (name, datesw)) { 2512: bp = getcpy (buf); 2513: while (state == FLDPLUS) { 2514: state = m_getfld (state, name, buf, sizeof buf, zp); 2515: bp = add (buf, bp); 2516: } 2517: if ((tw = dparsetime (bp)) == NULL) 2518: admonish (NULLCP, 2519: "unable to parse %s field in message %d", 2520: datesw, msgnum); 2521: free (bp); 2522: return tw; 2523: } 2524: while (state == FLDPLUS) 2525: state = m_getfld (state, name, buf, sizeof buf, zp); 2526: if (state != FLDEOF) 2527: continue; 2528: 2529: case BODY: 2530: case BODYEOF: 2531: case FILEEOF: 2532: admonish (NULLCP, "no %s field in message %d", datesw, msgnum); 2533: return NULL; 2534: 2535: case LENERR: 2536: case FMTERR: 2537: admonish (NULLCP, "format error in message %d", msgnum); 2538: return NULL; 2539: 2540: default: 2541: adios (NULLCP, "internal error -- you lose"); 2542: } 2543: } 2544: 2545: 2546: static int msgsort (a, b) 2547: struct Msg *a, 2548: *b; 2549: { 2550: return twsort (&a -> m_tb, &b -> m_tb); 2551: } 2552: 2553: /* */ 2554: 2555: static int process (msgnum, proc, vecp, vec) 2556: int msgnum, 2557: vecp; 2558: char *proc, 2559: **vec; 2560: { 2561: int child_id, 2562: status; 2563: char tmpfil[80]; 2564: FILE *out; 2565: 2566: if (fmsh) { 2567: (void) strcpy (tmpfil, m_name (msgnum)); 2568: (void) m_delete (pfolder); 2569: m_replace (pfolder, fmsh); 2570: m_sync (mp); 2571: m_update (); 2572: goto ready; 2573: } 2574: 2575: (void) strcpy (tmpfil, m_scratch ("", invo_name)); 2576: if ((out = fopen (tmpfil, "w")) == NULL) { 2577: int olderr; 2578: extern int errno; 2579: char newfil[80]; 2580: 2581: olderr = errno; 2582: (void) strcpy (newfil, m_tmpfil (invo_name)); 2583: if ((out = fopen (newfil, "w")) == NULL) { 2584: errno = olderr; 2585: advise (tmpfil, "unable to create temporary file"); 2586: return NOTOK; 2587: } 2588: else 2589: (void) strcpy (tmpfil, newfil); 2590: } 2591: copy_message (msgnum, out); 2592: (void) fclose (out); 2593: 2594: ready: ; 2595: (void) fflush (stdout); 2596: switch (child_id = fork ()) { 2597: case NOTOK: 2598: advise ("fork", "unable to"); 2599: status = NOTOK; 2600: break; 2601: 2602: case OK: 2603: closefds (3); 2604: (void) signal (SIGINT, istat); 2605: (void) signal (SIGQUIT, qstat); 2606: 2607: vec[vecp++] = tmpfil; 2608: vec[vecp] = NULL; 2609: 2610: execvp (proc, vec); 2611: fprintf (stderr, "unable to exec "); 2612: perror (proc); 2613: _exit (1); 2614: 2615: default: 2616: status = pidXwait (child_id, NULLCP); 2617: break; 2618: } 2619: 2620: if (!fmsh) 2621: (void) unlink (tmpfil); 2622: return status; 2623: } 2624: 2625: /* */ 2626: 2627: static copy_message (msgnum, out) 2628: int msgnum; 2629: FILE * out; 2630: { 2631: long pos; 2632: static char buffer[BUFSIZ]; 2633: register FILE * zp; 2634: 2635: zp = msh_ready (msgnum, 1); 2636: if (fmsh) { 2637: while (fgets (buffer, sizeof buffer, zp) != NULL) { 2638: fputs (buffer, out); 2639: if (interrupted && out == stdout) 2640: break; 2641: } 2642: } 2643: else { 2644: pos = ftell (zp); 2645: while (fgets (buffer, sizeof buffer, zp) != NULL 2646: && pos < Msgs[msgnum].m_stop) { 2647: fputs (buffer, out); 2648: pos += (long) strlen (buffer); 2649: if (interrupted && out == stdout) 2650: break; 2651: } 2652: } 2653: } 2654: 2655: 2656: static copy_digest (msgnum, out) 2657: int msgnum; 2658: FILE * out; 2659: { 2660: char c; 2661: long pos; 2662: static char buffer[BUFSIZ]; 2663: register FILE *zp; 2664: 2665: c = '\n'; 2666: zp = msh_ready (msgnum, 1); 2667: if (!fmsh) 2668: pos = ftell (zp); 2669: while (fgets (buffer, sizeof buffer, zp) != NULL 2670: && !fmsh && pos < Msgs[msgnum].m_stop) { 2671: if (c == '\n' && *buffer == '-') 2672: (void) fputc (' ', out); 2673: fputs (buffer, out); 2674: c = buffer[strlen (buffer) - 1]; 2675: if (!fmsh) 2676: pos += (long) strlen (buffer); 2677: if (interrupted && out == stdout) 2678: break; 2679: } 2680: }