1: /* forw.c - forward messages */
   2: 
   3: #include "../h/mh.h"
   4: #include "../h/formatsbr.h"
   5: #include "../zotnet/tws.h"
   6: #include <stdio.h>
   7: #include <sys/types.h>
   8: #include <sys/stat.h>
   9: 
  10: 
  11: #define IFMT    "digest-issue-%s"
  12: #define VFMT    "digest-volume-%s"
  13: 
  14: /*  */
  15: 
  16: static struct swit switches[] = {
  17: #define ANNOSW  0
  18:     "annotate", 0,
  19: #define NANNOSW 1
  20:     "noannotate", 0,
  21: 
  22: #define DFOLDSW 2
  23:     "draftfolder +folder", 0,
  24: #define DMSGSW  3
  25:     "draftmessage msg", 0,
  26: #define NDFLDSW 4
  27:     "nodraftfolder", 0,
  28: 
  29: #define EDITRSW 5
  30:     "editor editor", 0,
  31: #define NEDITSW 6
  32:     "noedit", 0,
  33: 
  34: #define FILTSW  7
  35:     "filter filterfile", 0,
  36: #define FORMSW  8
  37:     "form formfile", 0,
  38: 
  39: #define FRMTSW  9
  40:     "format", 5,
  41: #define NFRMTSW 10
  42:     "noformat", 7,
  43: 
  44: #define INPLSW  11
  45:     "inplace", 0,
  46: #define NINPLSW 12
  47:     "noinplace", 0,
  48: 
  49: #define DGSTSW  13
  50:     "digest list", 0,
  51: #define ISSUESW 14
  52:     "issue number", 0,
  53: #define VOLUMSW 15
  54:     "volume number", 0,
  55: 
  56: #define WHATSW  16
  57:     "whatnowproc program", 0,
  58: #define NWHATSW 17
  59:     "nowhatnowproc", 0,
  60: 
  61: #define HELPSW  18
  62:     "help", 4,
  63: 
  64: #define FILESW  19
  65:     "file file", -4,        /* interface from msh */
  66: 
  67: #ifdef  MHE
  68: #define BILDSW  20
  69:     "build", -5,        /* interface from mhe */
  70: #endif	MHE
  71: 
  72:     NULL, NULL
  73: };
  74: 
  75: /*  */
  76: 
  77: static struct swit aqrnl[] = {
  78: #define NOSW    0
  79:     "quit", 0,
  80: #define YESW    1
  81:     "replace", 0,
  82: #define LISTDSW 2
  83:     "list", 0,
  84: #define REFILSW 3
  85:     "refile +folder", 0,
  86: #define NEWSW   4
  87:     "new", 0,
  88: 
  89:     NULL, NULL
  90: };
  91: 
  92: 
  93: static struct swit aqrl[] = {
  94:     "quit", 0,
  95:     "replace", 0,
  96:     "list", 0,
  97:     "refile +folder", 0,
  98: 
  99:     NULL, NULL
 100: };
 101: 
 102: /*  */
 103: 
 104: static char drft[BUFSIZ];
 105: 
 106: static char delim3[] =
 107:     "\n------------------------------------------------------------\n\n";
 108: static char delim4[] = "\n------------------------------\n\n";
 109: 
 110: 
 111: static struct msgs *mp = NULL;      /* used a lot */
 112: 
 113: 
 114: long    lseek (), time ();
 115: 
 116: /*  */
 117: 
 118: /* ARGSUSED */
 119: 
 120: main (argc, argv)
 121: int     argc;
 122: char   *argv[];
 123: {
 124:     int     msgp = 0,
 125:             anot = 0,
 126:             inplace = 0,
 127:         issue = 0,
 128:         volume = 0,
 129: #ifdef  MHE
 130:         buildsw = 0,
 131: #endif	MHE
 132:         nedit = 0,
 133:         nwhat = 0,
 134:         i,
 135:             in,
 136:             out,
 137:         isdf = 0,
 138:             msgnum;
 139:     char   *cp,
 140:        *cwd,
 141:            *maildir,
 142:        *dfolder = NULL,
 143:        *dmsg = NULL,
 144:        *digest = NULL,
 145:            *ed = NULL,
 146:            *file = NULL,
 147:        *filter = NULL,
 148:            *folder = NULL,
 149:            *form = NULL,
 150:             buf[100],
 151:         value[10],
 152:           **ap,
 153:           **argp,
 154:            *arguments[MAXARGS],
 155:            *msgs[MAXARGS];
 156:     struct stat st;
 157: 
 158:     invo_name = r1bindex (argv[0], '/');
 159:     if ((cp = m_find (invo_name)) != NULL) {
 160:     ap = brkstring (cp = getcpy (cp), " ", "\n");
 161:     ap = copyip (ap, arguments);
 162:     }
 163:     else
 164:     ap = arguments;
 165:     (void) copyip (argv + 1, ap);
 166:     argp = arguments;
 167: 
 168: /*  */
 169: 
 170:     while (cp = *argp++) {
 171:     if (*cp == '-')
 172:         switch (smatch (++cp, switches)) {
 173:         case AMBIGSW:
 174:             ambigsw (cp, switches);
 175:             done (1);
 176:         case UNKWNSW:
 177:             adios (NULLCP, "-%s unknown", cp);
 178:         case HELPSW:
 179:             (void) sprintf (buf, "%s [+folder] [msgs] [switches]",
 180:             invo_name);
 181:             help (buf, switches);
 182:             done (1);
 183: 
 184:         case ANNOSW:
 185:             anot++;
 186:             continue;
 187:         case NANNOSW:
 188:             anot = 0;
 189:             continue;
 190: 
 191:         case EDITRSW:
 192:             if (!(ed = *argp++) || *ed == '-')
 193:             adios (NULLCP, "missing argument to %s", argp[-2]);
 194:             nedit = 0;
 195:             continue;
 196:         case NEDITSW:
 197:             nedit++;
 198:             continue;
 199: 
 200:         case WHATSW:
 201:             if (!(whatnowproc = *argp++) || *whatnowproc == '-')
 202:             adios (NULLCP, "missing argument to %s", argp[-2]);
 203:             nwhat = 0;
 204:             continue;
 205: #ifdef  MHE
 206:         case BILDSW:
 207:             buildsw++;  /* fall... */
 208: #endif	MHE
 209:         case NWHATSW:
 210:             nwhat++;
 211:             continue;
 212: 
 213:         case FILESW:
 214:             if (file)
 215:             adios (NULLCP, "only one file at a time!");
 216:             if (!(cp = *argp++) || *cp == '-')
 217:             adios (NULLCP, "missing argument to %s", argp[-2]);
 218:             file = path (cp, TFILE);
 219:             continue;
 220:         case FILTSW:
 221:             if (!(cp = *argp++) || *cp == '-')
 222:             adios (NULLCP, "missing argument to %s", argp[-2]);
 223:             filter = getcpy (libpath (cp));
 224:             continue;
 225:         case FORMSW:
 226:             if (!(form = *argp++) || *form == '-')
 227:             adios (NULLCP, "missing argument to %s", argp[-2]);
 228:             continue;
 229: 
 230:         case FRMTSW:
 231:             filter = getcpy (libpath (mhlforward));
 232:             continue;
 233:         case NFRMTSW:
 234:             filter = NULL;
 235:             continue;
 236: 
 237:         case INPLSW:
 238:             inplace++;
 239:             continue;
 240:         case NINPLSW:
 241:             inplace = 0;
 242:             continue;
 243: 
 244:         case DGSTSW:
 245:             if (!(digest = *argp++) || *digest == '-')
 246:             adios (NULLCP, "missing argument to %s", argp[-2]);
 247:             continue;
 248:         case ISSUESW:
 249:             if (!(cp = *argp++) || *cp == '-')
 250:             adios (NULLCP, "missing argument to %s", argp[-2]);
 251:             if ((issue = atoi (cp)) < 1)
 252:             adios (NULLCP, "bad argument %s %s", argp[-2], cp);
 253:             continue;
 254:         case VOLUMSW:
 255:             if (!(cp = *argp++) || *cp == '-')
 256:             adios (NULLCP, "missing argument to %s", argp[-2]);
 257:             if ((volume = atoi (cp)) < 1)
 258:             adios (NULLCP, "bad argument %s %s", argp[-2], cp);
 259:             continue;
 260: 
 261:         case DFOLDSW:
 262:             if (dfolder)
 263:             adios (NULLCP, "only one draft folder at a time!");
 264:             if (!(cp = *argp++) || *cp == '-')
 265:             adios (NULLCP, "missing argument to %s", argp[-2]);
 266:             dfolder = path (*cp == '+' || *cp == '@' ? cp + 1 : cp,
 267:                     *cp != '@' ? TFOLDER : TSUBCWF);
 268:             continue;
 269:         case DMSGSW:
 270:             if (dmsg)
 271:             adios (NULLCP, "only one draft message at a time!");
 272:             if (!(dmsg = *argp++) || *dmsg == '-')
 273:             adios (NULLCP, "missing argument to %s", argp[-2]);
 274:             continue;
 275:         case NDFLDSW:
 276:             dfolder = NULL;
 277:             isdf = NOTOK;
 278:             continue;
 279:         }
 280:     if (*cp == '+' || *cp == '@') {
 281:         if (folder)
 282:         adios (NULLCP, "only one folder at a time!");
 283:         else
 284:         folder = path (cp + 1, *cp == '+' ? TFOLDER : TSUBCWF);
 285:     }
 286:     else
 287:         msgs[msgp++] = cp;
 288:     }
 289: 
 290: /*  */
 291: 
 292:     cwd = getcpy (pwd ());
 293: 
 294:     if (!m_find ("path"))
 295:     free (path ("./", TFOLDER));
 296:     if (file && (msgp || folder))
 297:     adios (NULLCP, "can't mix files and folders/msgs");
 298: 
 299: try_it_again: ;
 300: #ifndef MHE
 301:     (void) strcpy (drft, m_draft (dfolder, dmsg, NOUSE, &isdf));
 302:     if (stat (drft, &st) != NOTOK) {
 303: #else   MHE
 304:     (void) strcpy (drft, buildsw ? m_maildir ("draft")
 305:               : m_draft (dfolder, NULLCP, NOUSE, &isdf));
 306:     if (!buildsw && stat (drft, &st) != NOTOK) {
 307: #endif	MHE
 308:     printf ("Draft \"%s\" exists (%ld bytes).", drft, st.st_size);
 309:     for (i = LISTDSW; i != YESW;) {
 310:         if (!(argp = getans ("\nDisposition? ", isdf ? aqrnl : aqrl)))
 311:         done (1);
 312:         switch (i = smatch (*argp, isdf ? aqrnl : aqrl)) {
 313:         case NOSW:
 314:             done (0);
 315:         case NEWSW:
 316:             dmsg = NULL;
 317:             goto try_it_again;
 318:         case YESW:
 319:             break;
 320:         case LISTDSW:
 321:             (void) showfile (++argp, drft);
 322:             break;
 323:         case REFILSW:
 324:             if (refile (++argp, drft) == 0)
 325:             i = YESW;
 326:             break;
 327:         default:
 328:             advise (NULLCP, "say what?");
 329:             break;
 330:         }
 331:     }
 332:     }
 333: 
 334: /*  */
 335: 
 336:     if (file) {
 337:     anot = 0;
 338:     goto go_to_it;
 339:     }
 340: 
 341:     if (!msgp)
 342:     msgs[msgp++] = "cur";
 343:     if (!folder)
 344:     folder = m_getfolder ();
 345:     maildir = m_maildir (folder);
 346: 
 347:     if (chdir (maildir) == NOTOK)
 348:     adios (maildir, "unable to change directory to");
 349:     if (!(mp = m_gmsg (folder)))
 350:     adios (NULLCP, "unable to read folder %s", folder);
 351:     if (mp -> hghmsg == 0)
 352:     adios (NULLCP, "no messages in %s", folder);
 353: 
 354:     for (msgnum = 0; msgnum < msgp; msgnum++)
 355:     if (!m_convert (mp, msgs[msgnum]))
 356:         done (1);
 357:     m_setseq (mp);
 358: 
 359: /*  */
 360: 
 361: go_to_it: ;
 362:     if (filter && access (filter, 04) == NOTOK)
 363:     adios (filter, "unable to read");
 364: 
 365:     if (digest) {
 366:     if (issue == 0) {
 367:         (void) sprintf (buf, IFMT, digest);
 368:         if (volume == 0
 369:             && (cp = m_find (buf))
 370:             && ((issue = atoi (cp)) < 0))
 371:         issue = 0;
 372:         issue++;
 373:     }
 374:     if (volume == 0)
 375:         (void) sprintf (buf, VFMT, digest);
 376:         if ((cp = m_find (buf)) == NULL || (volume = atoi (cp)) <= 0)
 377:         volume = 1;
 378:     if (!form)
 379:         form = digestcomps;
 380:     in = build_form (form, digest, volume, issue);
 381:     }
 382:     else
 383:     if (form) {
 384:         if ((in = open (libpath (form), 0)) == NOTOK)
 385:         adios (form, "unable to open form file");
 386:     }
 387:     else {
 388:         if ((in = open (libpath (forwcomps), 0)) == NOTOK)
 389:         adios (forwcomps, "unable to open default components file");
 390:         form = forwcomps;
 391:     }
 392: 
 393:     if ((out = creat (drft, m_gmprot ())) == NOTOK)
 394:     adios (drft, "unable to create");
 395: 
 396:     cpydata (in, out, form, drft);
 397:     (void) close (in);
 398: 
 399: /*  */
 400: 
 401:     if (file) {
 402:     if ((in = open (file, 0)) == NOTOK)
 403:         adios (file, "unable to open");
 404:     cpydata (in, out, file, drft);
 405:     (void) close (in);
 406:     (void) close (out);
 407:     goto edit_it;
 408:     }
 409: 
 410:     if (filter)
 411:     mhl_draft (out, digest, drft, filter);
 412:     else
 413:     copy_draft (out, digest, drft);
 414:     (void) close (out);
 415: 
 416:     if (digest) {
 417:     (void) sprintf (buf, IFMT, digest);
 418:     (void) sprintf (value, "%d", issue);
 419:     m_replace (buf, getcpy (value));
 420:     (void) sprintf (buf, VFMT, digest);
 421:     (void) sprintf (value, "%d", volume);
 422:     m_replace (buf, getcpy (value));
 423:     }
 424: 
 425:     m_replace (pfolder, folder);
 426:     if (mp -> lowsel != mp -> curmsg)
 427:     m_setcur (mp, mp -> lowsel);
 428:     m_sync (mp);
 429:     m_update ();
 430: 
 431: edit_it: ;
 432:     if (nwhat)
 433:     done (0);
 434:     (void) m_whatnow (ed, nedit, NOUSE, drft, NULLCP, 0, mp,
 435:     anot ? "Forwarded" : NULLCP, inplace, cwd);
 436:     done (1);
 437: }
 438: 
 439: /*  */
 440: 
 441: static  mhl_draft  (out, digest, file, filter)
 442: int     out;
 443: register char   *digest,
 444:         *file,
 445:         *filter;
 446: {
 447:     int     i,
 448:             child_id,
 449:         msgnum,
 450:             pd[2];
 451:     char   *vec[MAXARGS];
 452: 
 453:     if (pipe (pd) == NOTOK)
 454:     adios ("pipe", "unable to create");
 455: 
 456:     vec[0] = r1bindex (mhlproc, '/');
 457: 
 458:     for (i = 0; (child_id = fork ()) == NOTOK && i < 5; i++)
 459:     sleep (5);
 460:     switch (child_id) {
 461:     case NOTOK:
 462:         adios ("fork", "unable to");
 463: 
 464:     case OK:
 465:         (void) close (pd[0]);
 466:         (void) dup2 (pd[1], 1);
 467:         (void) close (pd[1]);
 468: 
 469:         i = 1;
 470:         vec[i++] = "-forwall";
 471:         vec[i++] = "-form";
 472:         vec[i++] = filter;
 473:         if (digest) {
 474:         vec[i++] = "-digest";
 475:         vec[i++] = digest;
 476:         }
 477:         if (mp -> numsel >= MAXARGS - i)
 478:         adios (NULLCP, "more than %d messages for %s exec",
 479:             vec[0], MAXARGS - i);
 480:         for (msgnum = mp -> lowsel; msgnum <= mp -> hghsel; msgnum++)
 481:         if (mp -> msgstats[msgnum] & SELECTED)
 482:             vec[i++] = getcpy (m_name (msgnum));
 483:         vec[i] = NULL;
 484: 
 485:         execvp (mhlproc, vec);
 486:         fprintf (stderr, "unable to exec ");
 487:         perror (mhlproc);
 488:         _exit (-1);
 489: 
 490:     default:
 491:         (void) close (pd[1]);
 492:         cpydata (pd[0], out, vec[0], file);
 493:         (void) close (pd[0]);
 494:         (void) pidXwait (child_id, mhlproc);
 495:         break;
 496:     }
 497: }
 498: 
 499: /*  */
 500: 
 501: static  copy_draft (out, digest, file)
 502: int     out;
 503: register char   *digest,
 504:         *file;
 505: {
 506:     int     fd,i,
 507:             msgcnt,
 508:             msgnum;
 509:     register char  *bp,
 510:                    *msgnam;
 511:     char    buffer[BUFSIZ];
 512: 
 513:     msgcnt = 1;
 514:     for (msgnum = mp -> lowsel; msgnum <= mp -> hghsel; msgnum++)
 515:     if (mp -> msgstats[msgnum] & SELECTED) {
 516:         if (digest)
 517:         (void) strcpy (buffer,
 518:             msgnum == mp -> lowsel ? delim3 : delim4);
 519:         else {
 520:         (void) strcpy (bp = buffer, "\n-------"), bp += strlen (bp);
 521:         if (msgnum == mp -> lowsel)
 522:             (void) sprintf (bp, " Forwarded Message%s",
 523:                 mp -> numsel > 1 ? "s" : "");
 524:         else
 525:             (void) sprintf (bp, " Message %d", msgcnt);
 526:         bp += strlen (bp);
 527:         (void) strcpy (bp, "\n\n");
 528:         }
 529:         (void) write (out, buffer, strlen (buffer));
 530: 
 531:         if ((fd = open (msgnam = m_name (msgnum), 0)) == NOTOK) {
 532:         admonish (msgnam, "unable to read message");
 533:         continue;
 534:         }
 535:         cpydgst (fd, out, msgnam, file);
 536:         (void) close (fd);
 537: 
 538:         msgcnt++;
 539:     }
 540: 
 541:     if (digest)
 542:     (void) strcpy (buffer, delim4);
 543:     else
 544:     (void) sprintf (buffer, "\n------- End of Forwarded Message%s\n\n",
 545:         mp -> numsel > 1 ? "s" : "");
 546:     (void) write (out, buffer, strlen (buffer));
 547: 
 548:     if (digest) {
 549:     (void) sprintf (buffer, "End of %s Digest\n", digest);
 550:     i = strlen (buffer);
 551:     for (bp = buffer + i; i > 1; i--)
 552:         *bp++ = '*';
 553:     *bp++ = '\n';
 554:     *bp = NULL;
 555:     (void) write (out, buffer, strlen (buffer));
 556:     }
 557: }
 558: 
 559: /*  */
 560: 
 561: static int  build_form (form, digest, volume, issue)
 562: register char  *form,
 563:                *digest;
 564: int     volume,
 565:         issue;
 566: {
 567:     int     in;
 568:     int     fmtsize;
 569:     register char *nfs;
 570:     char   *line,
 571:             tmpfil[BUFSIZ];
 572:     register    FILE *tmp;
 573:     register struct comp *cptr;
 574:     struct format *fmt;
 575:     int     dat[4];
 576: 
 577:     nfs = new_fs (form, NULLCP, NULLCP);
 578:     fmtsize = strlen (nfs) + 256;
 579:     (void) fmt_compile (nfs, &fmt);
 580: 
 581:     FINDCOMP (cptr, "digest");
 582:     if (cptr)
 583:     cptr->c_text = digest;
 584:     FINDCOMP (cptr, "date");
 585:     if (cptr)
 586:     cptr->c_text = getcpy(dtimenow ());
 587: 
 588:     dat[0] = issue;
 589:     dat[1] = volume;
 590:     dat[2] = 0;
 591:     dat[3] = fmtsize;
 592: 
 593:     (void) strcpy (tmpfil, m_tmpfil (invo_name));
 594:     if ((tmp = fopen (tmpfil, "w+")) == NULL)
 595:     adios (tmpfil, "unable to create");
 596:     (void) unlink (tmpfil);
 597:     if ((in = dup (fileno (tmp))) == NOTOK)
 598:     adios ("dup", "unable to");
 599: 
 600:     if ((line = malloc ((unsigned) fmtsize)) == NULLCP)
 601:     adios (NULLCP, "unable to allocate format line storage");
 602:     (void) fmtscan (fmt, line, fmtsize, dat);
 603:     (void) fputs (line, tmp);
 604:     (void) free (line);
 605:     if (fclose (tmp))
 606:     adios (tmpfil, "error writing");
 607: 
 608:     (void) lseek (in, 0L, 0);
 609:     return in;
 610: }

Defined functions

build_form defined in line 561; used 1 times
copy_draft defined in line 501; used 1 times
main defined in line 120; never used
mhl_draft defined in line 441; used 1 times

Defined variables

aqrl defined in line 93; used 2 times
aqrnl defined in line 77; used 2 times
delim3 defined in line 106; used 1 times
delim4 defined in line 108; used 2 times
drft defined in line 104; used 14 times
mp defined in line 111; used 21 times
switches defined in line 16; used 3 times

Defined macros

ANNOSW defined in line 17; never used
BILDSW defined in line 68; never used
DFOLDSW defined in line 22; never used
DGSTSW defined in line 49; never used
DMSGSW defined in line 24; never used
EDITRSW defined in line 29; never used
FILESW defined in line 64; never used
FILTSW defined in line 34; never used
FORMSW defined in line 36; never used
FRMTSW defined in line 39; never used
HELPSW defined in line 61; never used
IFMT defined in line 11; used 2 times
INPLSW defined in line 44; never used
ISSUESW defined in line 51; never used
LISTDSW defined in line 82; used 1 times
NANNOSW defined in line 19; never used
NDFLDSW defined in line 26; never used
NEDITSW defined in line 31; never used
NEWSW defined in line 86; never used
NFRMTSW defined in line 41; never used
NINPLSW defined in line 46; never used
NOSW defined in line 78; never used
NWHATSW defined in line 58; never used
REFILSW defined in line 84; never used
VFMT defined in line 12; used 2 times
VOLUMSW defined in line 53; never used
WHATSW defined in line 56; never used
YESW defined in line 80; used 2 times
Last modified: 1986-04-21
Generated: 2016-12-26
Generated by src2html V0.67
page hit count: 1702
Valid CSS Valid XHTML 1.0 Strict