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

Defined functions

ask defined in line 2337; used 1 times
burst defined in line 319; used 1 times
copy_digest defined in line 2656; used 1 times
copy_message defined in line 2627; used 2 times
distcmd defined in line 118; used 1 times
eom_action defined in line 2309; used 2 times
explcmd defined in line 224; used 1 times
filecmd defined in line 473; used 1 times
filehak defined in line 557; used 1 times
foldcmd defined in line 648; used 2 times
forkcmd defined in line 41; used 10 times
forw defined in line 978; used 1 times
forwcmd defined in line 869; used 1 times
getws defined in line 2494; used 2 times
helpcmd defined in line 1107; used 1 times
markcmd defined in line 1147; used 1 times
mhl_action defined in line 2316; used 3 times
msgsort defined in line 2546; used 2 times
pack defined in line 1429; used 2 times
packcmd defined in line 1343; used 1 times
packhak defined in line 1446; used 1 times
pickcmd defined in line 1533; used 1 times
process defined in line 2555; used 4 times
replcmd defined in line 1740; used 1 times
rmm defined in line 1886; used 2 times
rmmcmd defined in line 1843; used 1 times
scancmd defined in line 1973; used 2 times
show defined in line 2294; used 2 times
showcmd defined in line 2139; used 1 times
sortcmd defined in line 2397; used 1 times

Defined variables

delim3 defined in line 23; used 3 times
distswit defined in line 85; used 3 times
explswit defined in line 203; used 3 times
fileswit defined in line 450; used 5 times
foldswit defined in line 609; used 3 times
forwswit defined in line 830; used 3 times
hlpmsg defined in line 1082; used 2 times
markswit defined in line 1120; used 3 times
mhlnum defined in line 27; used 2 times
packswit defined in line 1331; used 4 times
pickswit defined in line 1479; used 3 times
replswit defined in line 1689; used 3 times
rmmswit defined in line 1834; used 3 times
scanswit defined in line 1950; used 3 times
showswit defined in line 2110; used 4 times
sortswit defined in line 2382; used 3 times

Defined macros

DIANSW defined in line 86; never used
DIDFSW defined in line 90; never used
DIDMSW defined in line 92; never used
DIEDTSW defined in line 96; never used
DIFRMSW defined in line 100; never used
DIHELP defined in line 110; never used
DIINSW defined in line 102; never used
DINANSW defined in line 88; never used
DINDFSW defined in line 94; never used
DINEDSW defined in line 98; never used
DININSW defined in line 104; never used
DINWTSW defined in line 108; never used
DIWHTSW defined in line 106; never used
EXHELP defined in line 216; never used
EXINSW defined in line 204; never used
EXNINSW defined in line 206; never used
EXNQISW defined in line 210; never used
EXNVBSW defined in line 214; never used
EXQISW defined in line 208; never used
EXVBSW defined in line 212; never used
FIDRFT defined in line 451; never used
FIFILE defined in line 463; never used
FIHELP defined in line 465; never used
FILINK defined in line 453; never used
FINLINK defined in line 455; never used
FINPRES defined in line 459; never used
FIPRES defined in line 457; never used
FISRC defined in line 461; never used
FLALSW defined in line 610; never used
FLFASW defined in line 612; never used
FLHDSW defined in line 616; never used
FLHELP defined in line 640; never used
FLLISW defined in line 638; never used
FLNFASW defined in line 614; never used
FLNHDSW defined in line 618; never used
FLNPKSW defined in line 622; never used
FLNRCSW defined in line 626; never used
FLNTLSW defined in line 630; never used
FLPKSW defined in line 620; never used
FLPOSW defined in line 636; never used
FLPRSW defined in line 632; never used
FLPUSW defined in line 634; never used
FLRCSW defined in line 624; never used
FLTLSW defined in line 628; never used
FOANSW defined in line 831; never used
FODFSW defined in line 835; never used
FODMSW defined in line 837; never used
FOEDTSW defined in line 841; never used
FOFRMSW defined in line 847; never used
FOFTRSW defined in line 845; never used
FOFTSW defined in line 849; never used
FOHELP defined in line 861; never used
FOINSW defined in line 853; never used
FONANSW defined in line 833; never used
FONDFSW defined in line 839; never used
FONEDSW defined in line 843; never used
FONFTSW defined in line 851; never used
FONINSW defined in line 855; never used
FONWTSW defined in line 859; never used
FOWHTSW defined in line 857; never used
MADDSW defined in line 1121; never used
MDBUGSW defined in line 1139; never used
MDELSW defined in line 1123; never used
MHELP defined in line 1137; never used
MLSTSW defined in line 1125; never used
MNPUBSW defined in line 1131; never used
MNZERSW defined in line 1135; never used
MPUBSW defined in line 1129; never used
MSEQSW defined in line 1127; never used
MZERSW defined in line 1133; never used
PAFISW defined in line 1332; never used
PAHELP defined in line 1335; never used
PIAFSW defined in line 1505; never used
PIANSW defined in line 1480; never used
PIBFSW defined in line 1507; never used
PICCSW defined in line 1491; never used
PIDASW defined in line 1493; never used
PIDFSW defined in line 1509; never used
PIFRSW defined in line 1495; never used
PIHELP defined in line 1525; never used
PILBSW defined in line 1486; never used
PILISW defined in line 1521; never used
PINLISW defined in line 1523; never used
PINPUSW defined in line 1515; never used
PINTSW defined in line 1484; never used
PINZRSW defined in line 1519; never used
PIORSW defined in line 1482; never used
PIOTSW defined in line 1503; never used
PIPUSW defined in line 1513; never used
PIRBSW defined in line 1488; never used
PISESW defined in line 1497; never used
PISQSW defined in line 1511; never used
PISUSW defined in line 1499; never used
PITOSW defined in line 1501; never used
PIZRSW defined in line 1517; never used
REANSW defined in line 1690; never used
RECCSW defined in line 1694; never used
REDFSW defined in line 1698; never used
REDMSW defined in line 1700; never used
REEDTSW defined in line 1704; never used
REFCCSW defined in line 1708; never used
REFLTSW defined in line 1710; never used
REFRMSW defined in line 1712; never used
REFRSW defined in line 1714; never used
REHELP defined in line 1732; never used
REINSW defined in line 1718; never used
RENANSW defined in line 1692; never used
RENCCSW defined in line 1696; never used
RENDFSW defined in line 1702; never used
RENEDSW defined in line 1706; never used
RENFRSW defined in line 1716; never used
RENINSW defined in line 1720; never used
RENQUSW defined in line 1724; never used
RENWTSW defined in line 1728; never used
REQUSW defined in line 1722; never used
REWHTSW defined in line 1726; never used
REWIDSW defined in line 1730; never used
RMHELP defined in line 1835; never used
SCCLR defined in line 1951; never used
SCFMT defined in line 1957; never used
SCFORM defined in line 1955; never used
SCHEAD defined in line 1959; never used
SCHELP defined in line 1965; never used
SCNCLR defined in line 1953; never used
SCNHEAD defined in line 1961; never used
SCWID defined in line 1963; never used
SHDRAFT defined in line 2111; never used
SHFORM defined in line 2113; never used
SHHEAD defined in line 2127; never used
SHHELP defined in line 2131; never used
SHLEN defined in line 2119; never used
SHNHEAD defined in line 2129; never used
SHNPROG defined in line 2117; never used
SHNSHOW defined in line 2125; never used
SHPROG defined in line 2115; never used
SHSHOW defined in line 2123; never used
SHWID defined in line 2121; never used
SODATE defined in line 2383; never used
SOHELP defined in line 2389; never used
SONVERB defined in line 2387; never used
SOVERB defined in line 2385; never used
equiv defined in line 1976; used 2 times
Last modified: 1986-04-21
Generated: 2016-12-26
Generated by src2html V0.67
page hit count: 7938
Valid CSS Valid XHTML 1.0 Strict