Annotation of 43BSDReno/contrib/mh/uip/mhlsbr.c, revision 1.1.1.1

1.1       root        1: /* mhlsbr.c - implement the "nifty" message lister */
                      2: 
                      3: #include "../h/mh.h"
                      4: #include "../h/addrsbr.h"
                      5: #include "../h/formatsbr.h"
                      6: #include "../zotnet/tws.h"
                      7: #include <ctype.h>
                      8: #include <setjmp.h>
                      9: #include <signal.h>
                     10: #include <stdio.h>
                     11: #include <sys/types.h>
                     12: #include <sys/stat.h>
                     13: 
                     14: 
                     15: /* MAJOR BUG:
                     16:    for a component containing addresses, ADDRFMT, if COMPRESS is also
                     17:    set, then addresses get split wrong (not at the spaces between commas).
                     18:    To fix this correctly, putstr() should know about "atomic" strings that
                     19:    must NOT be broken across lines.  That's too difficult for right now
                     20:    (it turns out that there are a number of degernate cases), so in
                     21:    oneline(), instead of
                     22: 
                     23:                     (*onelp == '\n' && !onelp[1])
                     24: 
                     25:    being a terminating condition,
                     26: 
                     27:         (*onelp == '\n' && (!onelp[1] || (flags & ADDRFMT)))
                     28: 
                     29:    is used instead.  This cuts the line prematurely, and gives us a much
                     30:    better chance of getting things right.
                     31:  */
                     32: 
                     33: 
                     34: #define ONECOMP                0
                     35: #define TWOCOMP                1
                     36: #define        BODYCOMP        2
                     37: 
                     38: #define        adios   mhladios
                     39: 
                     40: #define        QUOTE   '\\'
                     41: 
                     42: /*  */
                     43: 
                     44: static struct swit mhlswitches[] = {
                     45: #define        BELLSW  0
                     46:     "bell", 0,
                     47: #define        NBELLSW 1
                     48:     "nobell", 0,
                     49: 
                     50: #define        CLRSW   2
                     51:     "clear", 0,
                     52: #define        NCLRSW  3
                     53:     "noclear", 0,
                     54: 
                     55: #define        FOLDSW  4
                     56:     "folder +folder", 0,
                     57: #define        FORMSW  5
                     58:     "form formfile", 0,
                     59: 
                     60: #define        PROGSW  6
                     61:     "moreproc program", 0,
                     62: #define        NPROGSW 7
                     63:     "nomoreproc", 0,
                     64: 
                     65: #define        LENSW   8
                     66:     "length lines", 0,
                     67: #define        WIDSW   9
                     68:     "width columns", 0,
                     69: 
                     70: #define        HELPSW  10
                     71:     "help", 4,
                     72: 
                     73: #define        FORW1SW 11
                     74:     "forward", -7,             /* interface from forw */
                     75: #define        FORW2SW 12
                     76:     "forwall", -7,             /*   .. */
                     77: 
                     78: #define        DASHSW  13
                     79:     "dashmunging", 4,
                     80: #define        NDASHSW 14
                     81:     "nodashmunging", 6,
                     82: 
                     83: #define        DGSTSW  15
                     84:     "digest list", -6,
                     85: 
                     86:     NULL, NULL
                     87: };
                     88: 
                     89: /*  */
                     90: 
                     91: struct mcomp {
                     92:     char   *c_name;            /* component name                       */
                     93:     char   *c_text;            /* component text                       */
                     94:     char   *c_ovtxt;           /* text overflow indicator              */
                     95:     char   *c_nfs;             /* iff FORMAT                           */
                     96:     struct format *c_fmt;      /*   ..                                 */
                     97: 
                     98:     int     c_offset;          /* left margin indentation              */
                     99:     int     c_ovoff;           /* overflow indentation                 */
                    100:     int     c_width;           /* width of field                       */
                    101:     int     c_cwidth;          /* width of component                   */
                    102:     int     c_length;          /* length in lines                      */
                    103: 
                    104:     short   c_flags;
                    105: #define NOCOMPONENT    0x0001  /* don't show component name            */
                    106: #define UPPERCASE       0x0002 /* display in all upper case            */
                    107: #define CENTER          0x0004 /* center line                          */
                    108: #define CLEARTEXT       0x0008 /* cleartext                            */
                    109: #define EXTRA          0x0010  /* an "extra" component                 */
                    110: #define HDROUTPUT      0x0020  /* already output                       */
                    111: #define CLEARSCR       0x0040  /* clear screen                         */
                    112: #define LEFTADJUST     0x0080  /* left justify multiple lines          */
                    113: #define COMPRESS       0x0100  /* compress text                        */
                    114: #define        ADDRFMT         0x0200  /* contains addresses                   */
                    115: #define        BELL            0x0400  /* sound bell at EOP                    */
                    116: #define        DATEFMT         0x0800  /* contains dates                       */
                    117: #define        FORMAT          0x1000  /* parse address/date                   */
                    118: #define        INIT            0x2000
                    119: #define        LBITS   "\020\01NOCOMPONENT\02UPPERCASE\03CENTER\04CLEARTEXT\05EXTRA\06HDROUTPUT\07CLEARSCR\010LEFTADJUST\011COMPRESS\012ADDRFMT\013BELL\014DATEFMT\015FORMAT\016INIT"
                    120: #define        GFLAGS  (NOCOMPONENT | UPPERCASE | CENTER | LEFTADJUST | COMPRESS)
                    121: 
                    122:     struct mcomp *c_next;
                    123: };
                    124: 
                    125: static struct mcomp *msghd = NULL;
                    126: static struct mcomp *msgtl = NULL;
                    127: static struct mcomp *fmthd = NULL;
                    128: static struct mcomp *fmttl = NULL;
                    129: 
                    130: static struct mcomp global = {
                    131:     NULL, NULL, "", NULL, NULL, 0, -1, 80, -1, 40, BELL, NULL
                    132: };
                    133: static struct mcomp  holder =
                    134: {
                    135:     NULL, NULL, NULL, NULL, NULL, 0, 0, 0, 0, 0, NOCOMPONENT, NULL
                    136: };
                    137: 
                    138: 
                    139: static struct pair {
                    140:     char   *p_name;
                    141:     short   p_flags;
                    142: }                   pairs[] = {
                    143:                        "Date", DATEFMT,
                    144:                         "From", ADDRFMT,
                    145:                         "Sender", ADDRFMT,
                    146:                         "Reply-To", ADDRFMT,
                    147:                         "To", ADDRFMT,
                    148:                         "cc", ADDRFMT,
                    149:                         "Bcc", ADDRFMT,
                    150:                        "Resent-Date", DATEFMT,
                    151:                         "Resent-From", ADDRFMT,
                    152:                         "Resent-Sender", ADDRFMT,
                    153:                         "Resent-Reply-To", ADDRFMT,
                    154:                         "Resent-To", ADDRFMT,
                    155:                         "Resent-cc", ADDRFMT,
                    156:                         "Resent-Bcc", ADDRFMT,
                    157: 
                    158:                         NULL
                    159: };
                    160: 
                    161: static struct triple {
                    162:     char   *t_name;
                    163:     short   t_on;
                    164:     short   t_off;
                    165: }                       triples[] = {
                    166:                            "nocomponent", NOCOMPONENT, 0,
                    167:                             "uppercase", UPPERCASE, 0,
                    168:                             "nouppercase", 0, UPPERCASE,
                    169:                             "center", CENTER, 0,
                    170:                             "nocenter", 0, CENTER,
                    171:                             "clearscreen", CLEARSCR, 0,
                    172:                             "noclearscreen", 0, CLEARSCR,
                    173:                             "noclear", 0, CLEARSCR,
                    174:                             "leftadjust", LEFTADJUST, 0,
                    175:                             "noleftadjust", 0, LEFTADJUST,
                    176:                             "compress", COMPRESS, 0,
                    177:                             "nocompress", 0, COMPRESS,
                    178:                             "addrfield", ADDRFMT, DATEFMT,
                    179:                             "bell", BELL, 0,
                    180:                             "nobell", 0, BELL,
                    181:                             "datefield", DATEFMT, ADDRFMT,
                    182: 
                    183:                             NULL
                    184: };
                    185: 
                    186: /*  */
                    187: 
                    188: static int  bellflg = 0;
                    189: static int  clearflg = 0;
                    190: static int  forwflg = 0;
                    191: static int  forwall = 0;
                    192: static int  dashflg = 1;
                    193: 
                    194: static char *digest = NULL;
                    195: 
                    196: static int  exitstat = 0;
                    197: static int  mhldebug = 0;
                    198: 
                    199: #define        PITTY   (-1)
                    200: #define        NOTTY   0
                    201: #define        ISTTY   1
                    202: static int  ontty = NOTTY;
                    203: 
                    204: static int  row;
                    205: static int  column;
                    206: 
                    207: static int  lm;
                    208: static int  llim;
                    209: static int  ovoff;
                    210: static int  term;
                    211: static int  wid;
                    212: 
                    213: 
                    214: static char *ovtxt;
                    215: 
                    216: static char *onelp;
                    217: 
                    218: 
                    219: static char *parptr;
                    220: static char *ignores[MAXARGS];
                    221: 
                    222: 
                    223: static  jmp_buf env;
                    224: static  jmp_buf mhlenv;
                    225: 
                    226: 
                    227: static char delim3[] =         /* from forw.c */
                    228:     "\n------------------------------------------------------------\n\n";
                    229: static char delim4[] = "\n------------------------------\n\n";
                    230: 
                    231: 
                    232: static  FP (*mhl_action) () = (FP (*) ()) 0;
                    233: 
                    234: void clear_screen(), mhldone();
                    235: 
                    236: static int evalvar(), ptoi(), ptos(), mcomp_flags();
                    237: static char *parse(), *mcomp_add(), *oneline();
                    238: static void mhl_format(), process(), mhlfile(), mcomp_format(),
                    239:     free_queue(), putcomp(), putstr(), putch(), mhladios(),
                    240:     m_popen();
                    241: static struct mcomp *add_queue();
                    242: static SIGDECL intrser(), pipeser(), quitser();
                    243: 
                    244: 
                    245: /*  */
                    246: 
                    247: /* ARGSUSED */
                    248: 
                    249: mhl(argc, argv)
                    250:        int argc;
                    251:        char *argv[];
                    252: {
                    253:     int     length = 0,
                    254:            nomore = 0,
                    255:             width = 0,
                    256:             vecp = 0,
                    257:             i;
                    258:     register char   *cp,
                    259:                    *folder = NULL,
                    260:                    *form = NULL,
                    261:                    **ap,
                    262:                    **argp;
                    263:     char    buf[80],
                    264:            *arguments[MAXARGS],
                    265:            *files[MAXARGS];
                    266: 
                    267:     invo_name = r1bindex (argv[0], '/');
                    268:     if ((cp = getenv ("MHLDEBUG")) && *cp)
                    269:        mhldebug++;
                    270:     if ((cp = m_find (invo_name)) != NULL) {
                    271:        ap = brkstring (getcpy (cp), " ", "\n");
                    272:        ap = copyip (ap, arguments);
                    273:     }
                    274:     else
                    275:        ap = arguments;
                    276:     (void) copyip (argv + 1, ap);
                    277:     argp = arguments;
                    278: 
                    279: /*  */
                    280: 
                    281:     vecp = 0;
                    282:     while (cp = *argp++) {
                    283:        if (*cp == '-')
                    284:            switch (smatch (++cp, mhlswitches)) {
                    285:                case AMBIGSW:
                    286:                    ambigsw (cp, mhlswitches);
                    287:                    mhldone (1);
                    288:                case UNKWNSW:
                    289:                    adios (NULLCP, "-%s unknown\n", cp);
                    290:                case HELPSW:
                    291:                    (void) sprintf (buf, "%s [switches] [files ...]",
                    292:                            invo_name);
                    293:                    help (buf, mhlswitches);
                    294:                    mhldone (1);
                    295: 
                    296:                case BELLSW:
                    297:                    bellflg = 1;
                    298:                    continue;
                    299:                case NBELLSW:
                    300:                    bellflg = -1;
                    301:                    continue;
                    302: 
                    303:                case CLRSW:
                    304:                    clearflg = 1;
                    305:                    continue;
                    306:                case NCLRSW:
                    307:                    clearflg = -1;
                    308:                    continue;
                    309: 
                    310:                case FOLDSW:
                    311:                    if (!(folder = *argp++) || *folder == '-')
                    312:                        adios (NULLCP, "missing argument to %s", argp[-2]);
                    313:                    continue;
                    314:                case FORMSW:
                    315:                    if (!(form = *argp++) || *form == '-')
                    316:                        adios (NULLCP, "missing argument to %s", argp[-2]);
                    317:                    continue;
                    318: 
                    319:                case PROGSW:
                    320:                    if (!(moreproc = *argp++) || *moreproc == '-')
                    321:                        adios (NULLCP, "missing argument to %s", argp[-2]);
                    322:                    continue;
                    323:                case NPROGSW:
                    324:                    nomore++;
                    325:                    continue;
                    326: 
                    327:                case LENSW:
                    328:                    if (!(cp = *argp++) || *cp == '-')
                    329:                        adios (NULLCP, "missing argument to %s", argp[-2]);
                    330:                    if ((length = atoi (cp)) < 1)
                    331:                        adios (NULLCP, "bad argument %s %s", argp[-2], cp);
                    332:                    continue;
                    333:                case WIDSW:
                    334:                    if (!(cp = *argp++) || *cp == '-')
                    335:                        adios (NULLCP, "missing argument to %s", argp[-2]);
                    336:                    if ((width = atoi (cp)) < 1)
                    337:                        adios (NULLCP, "bad argument %s %s", argp[-2], cp);
                    338:                    continue;
                    339: 
                    340:                case DGSTSW:
                    341:                    if (!(digest = *argp++) || *digest == '-')
                    342:                        adios (NULLCP, "missing argument to %s", argp[-2]);
                    343:                case FORW2SW:
                    344:                    forwall++;  /* fall */
                    345:                case FORW1SW:
                    346:                    forwflg++;
                    347:                    clearflg = -1;/* XXX */
                    348:                    continue;
                    349: 
                    350:                case DASHSW:
                    351:                    dashflg++;
                    352:                    continue;
                    353:                case NDASHSW:
                    354:                    dashflg = 0;
                    355:                    continue;
                    356:            }
                    357:        files[vecp++] = cp;
                    358:     }
                    359: 
                    360: /*  */
                    361: 
                    362:     if (!folder)
                    363:        folder = getenv ("mhfolder");
                    364: 
                    365:     if (isatty (fileno (stdout)))
                    366:        if (!nomore && moreproc && *moreproc) {
                    367:            if (mhl_action) {
                    368:                setsig (SIGINT, SIG_IGN);
                    369:                setsig (SIGQUIT, quitser);
                    370:            }
                    371:            m_popen (moreproc);
                    372:            ontty = PITTY;
                    373:        }
                    374:        else {
                    375:            setsig (SIGINT, SIG_IGN);
                    376:            setsig (SIGQUIT, quitser);
                    377:            ontty = ISTTY;
                    378:        }
                    379:     else
                    380:        ontty = NOTTY;
                    381: 
                    382:     mhl_format (form ? form : mhlformat, length, width);
                    383: 
                    384:     if (vecp == 0)
                    385:        process (folder, NULLCP, 1, vecp = 1);
                    386:     else
                    387:        for (i = 0; i < vecp; i++)
                    388:            process (folder, files[i], i + 1, vecp);
                    389: 
                    390:     if (forwall) {
                    391:        if (digest) {
                    392:            printf ("%s", delim4);
                    393:            (void) sprintf (buf, "End of %s Digest\n", digest);
                    394:            i = strlen (buf);
                    395:            for (cp = buf + i; i > 1; i--)
                    396:                *cp++ = '*';
                    397:            *cp++ = '\n';
                    398:            *cp = NULL;
                    399:            printf ("%s", buf);
                    400:        }
                    401:        else
                    402:            printf ("\n------- End of Forwarded Message%s\n\n",
                    403:                    vecp > 1 ? "s" : "");
                    404:     }
                    405: 
                    406:     if (clearflg > 0 && ontty == NOTTY)
                    407:        clear_screen ();
                    408: 
                    409:     if (ontty == PITTY)
                    410:        m_pclose ();
                    411: 
                    412:     return exitstat;
                    413: }
                    414: 
                    415: /*  */
                    416: 
                    417: static void
                    418: mhl_format(file, length, width)
                    419:        register char *file;
                    420:        int length, width;
                    421: {
                    422:     int     i;
                    423:     register char  *bp,
                    424:                   *cp,
                    425:                   **ip;
                    426:     char   *ap,
                    427:            buffer[BUFSIZ],
                    428:             name[NAMESZ];
                    429:     register struct mcomp   *c1;
                    430:     struct stat st;
                    431:     register    FILE *fp;
                    432:     static  dev_t dev = 0;
                    433:     static  ino_t ino = 0;
                    434:     static  time_t mtime = 0;
                    435: 
                    436:     if (fmthd != NULL)
                    437:        if (stat (libpath (file), &st) != NOTOK
                    438:                && mtime == st.st_mtime
                    439:                && dev == st.st_dev
                    440:                && ino == st.st_ino)
                    441:            goto out;
                    442:        else
                    443:            free_queue (&fmthd, &fmttl);
                    444: 
                    445:     if ((fp = fopen (libpath (file), "r")) == NULL)
                    446:        adios (file, "unable to open format file");
                    447: 
                    448:     if (fstat (fileno (fp), &st) != NOTOK)
                    449:        mtime = st.st_mtime, dev = st.st_dev, ino = st.st_ino;
                    450: 
                    451:     global.c_ovtxt = global.c_nfs = NULL;
                    452:     global.c_fmt = NULL;
                    453:     global.c_offset = 0;
                    454:     global.c_ovoff = -1;
                    455:     if ((i = sc_width ()) > 5)
                    456:        global.c_width = i;
                    457:     global.c_cwidth = -1;
                    458:     if ((i = sc_length ()) > 5)
                    459:        global.c_length = i - 1;
                    460:     global.c_flags = BELL;             /* BELL is default */
                    461:     *(ip = ignores) = NULL;
                    462: 
                    463:     while (vfgets (fp, &ap) == OK) {
                    464:        bp = ap;
                    465:        if (*bp == ';')
                    466:            continue;
                    467: 
                    468:        if (cp = index (bp, '\n'))
                    469:            *cp = NULL;
                    470: 
                    471:        if (*bp == ':') {
                    472:            c1 = add_queue (&fmthd, &fmttl, NULLCP, bp + 1, CLEARTEXT);
                    473:            continue;
                    474:        }
                    475: 
                    476:        parptr = bp;
                    477:        (void) strcpy (name, parse ());
                    478:        switch (*parptr) {
                    479:            case '\0':
                    480:            case ',':
                    481:            case '=':
                    482:                if (uleq (name, "ignores")) {
                    483:                    ip = copyip (brkstring (getcpy (++parptr), ",", NULLCP), ip);
                    484:                    continue;
                    485:                }
                    486:                parptr = bp;
                    487:                while (*parptr) {
                    488:                    if (evalvar (&global))
                    489:                        adios (NULLCP, "format file syntax error: %s", bp);
                    490:                    if (*parptr)
                    491:                        parptr++;
                    492:                }
                    493:                continue;
                    494: 
                    495:            case ':':
                    496:                c1 = add_queue (&fmthd, &fmttl, name, NULLCP, INIT);
                    497:                while (*parptr == ':' || *parptr == ',') {
                    498:                    parptr++;
                    499:                    if (evalvar (c1))
                    500:                        adios (NULLCP, "format file syntax error: %s", bp);
                    501:                }
                    502:                if (!c1 -> c_nfs && global.c_nfs)
                    503:                    if (c1 -> c_flags & DATEFMT) {
                    504:                        if (global.c_flags & DATEFMT)
                    505:                            c1 -> c_nfs = getcpy (global.c_nfs);
                    506:                    }
                    507:                    else
                    508:                        if (c1 -> c_flags & ADDRFMT) {
                    509:                            if (global.c_flags & ADDRFMT)
                    510:                                c1 -> c_nfs = getcpy (global.c_nfs);
                    511:                        }
                    512:                continue;
                    513: 
                    514:            default:
                    515:                adios (NULLCP, "format file syntax error: %s", bp);
                    516:        }
                    517:     }
                    518:     (void) fclose (fp);
                    519: 
                    520:     if (mhldebug)
                    521:        for (c1 = fmthd; c1; c1 = c1 -> c_next) {
                    522:            fprintf (stderr, "c1: name=\"%s\" text=\"%s\" ovtxt=\"%s\"\n",
                    523:                    c1 -> c_name, c1 -> c_text, c1 -> c_ovtxt);
                    524:            fprintf (stderr, "\tnfs=0x%x fmt=0x%x\n",
                    525:                    c1 -> c_nfs, c1 -> c_fmt);
                    526:            fprintf (stderr, "\toffset=%d ovoff=%d width=%d cwidth=%d length=%d\n",
                    527:                    c1 -> c_offset, c1 -> c_ovoff, c1 -> c_width,
                    528:                    c1 -> c_cwidth, c1 -> c_length);
                    529:            fprintf (stderr, "\tflags=%s\n",
                    530:                    sprintb (buffer, (unsigned) c1 -> c_flags, LBITS));
                    531:        }
                    532: 
                    533: out: ;
                    534:     if (clearflg == 1)
                    535:        global.c_flags |= CLEARSCR;
                    536:     else
                    537:        if (clearflg == -1)
                    538:            global.c_flags &= ~CLEARSCR;
                    539: 
                    540:     switch (bellflg) {         /* command line may override format file */
                    541:        case 1:
                    542:            global.c_flags |= BELL;
                    543:            break;
                    544:        case -1:
                    545:            global.c_flags &= ~BELL;
                    546:            break;
                    547:     }
                    548: 
                    549:     if (length)
                    550:        global.c_length = length;
                    551:     if (width)
                    552:        global.c_width = width;
                    553:     if (global.c_length < 5)
                    554:        global.c_length = 10000;
                    555:     if (global.c_width < 5)
                    556:        global.c_width = 10000;
                    557: }
                    558: 
                    559: /*  */
                    560: 
                    561: static int
                    562: evalvar(c1)
                    563:        register struct mcomp *c1;
                    564: {
                    565:     char   *cp,
                    566:             name[NAMESZ];
                    567:     register struct triple *ap;
                    568: 
                    569:     if (!*parptr)
                    570:        return 0;
                    571:     (void) strcpy (name, parse ());
                    572: 
                    573:     if (uleq (name, "component")) {
                    574:        if (ptos (name, &c1 -> c_text))
                    575:            return 1;
                    576:        c1 -> c_flags &= ~NOCOMPONENT;
                    577:        return 0;
                    578:     }
                    579:     if (uleq (name, "overflowtext"))
                    580:        return ptos (name, &c1 -> c_ovtxt);
                    581:     if (uleq (name, "formatfield")) {
                    582:        if (ptos (name, &cp))
                    583:            return 1;
                    584:        c1 -> c_nfs = getcpy (new_fs (NULLCP, NULLCP, cp));
                    585:        c1 -> c_flags |= FORMAT;
                    586:        return 0;
                    587:     }
                    588: 
                    589:     if (uleq (name, "offset"))
                    590:        return ptoi (name, &c1 -> c_offset);
                    591:     if (uleq (name, "overflowoffset"))
                    592:        return ptoi (name, &c1 -> c_ovoff);
                    593:     if (uleq (name, "width"))
                    594:        return ptoi (name, &c1 -> c_width);
                    595:     if (uleq (name, "compwidth"))
                    596:        return ptoi (name, &c1 -> c_cwidth);
                    597:     if (uleq (name, "length"))
                    598:        return ptoi (name, &c1 -> c_length);
                    599: 
                    600:     for (ap = triples; ap -> t_name; ap++)
                    601:        if (uleq (ap -> t_name, name)) {
                    602:            c1 -> c_flags |= ap -> t_on;
                    603:            c1 -> c_flags &= ~ap -> t_off;
                    604:            return 0;
                    605:        }
                    606: 
                    607:     return 1;
                    608: }
                    609: 
                    610: /*  */
                    611: 
                    612: static int
                    613: ptoi(name, i)
                    614:        register char *name;
                    615:        register int *i;
                    616: {
                    617:     char   *cp;
                    618: 
                    619:     if (*parptr++ != '=' || !*(cp = parse ())) {
                    620:        advise (NULLCP, "missing argument to variable %s", name);
                    621:        return 1;
                    622:     }
                    623: 
                    624:     *i = atoi (cp);
                    625:     return 0;
                    626: }
                    627: 
                    628: 
                    629: static int
                    630: ptos(name, s)
                    631:        register char *name, **s;
                    632: {
                    633:     char    c,
                    634:            *cp;
                    635: 
                    636:     if (*parptr++ != '=') {
                    637:        advise (NULLCP, "missing argument to variable %s", name);
                    638:        return 1;
                    639:     }
                    640: 
                    641:     if (*parptr != '"')
                    642:        for (cp = parptr;
                    643:                *parptr && *parptr != ':' && *parptr != ',';
                    644:                parptr++)
                    645:            continue;
                    646:     else
                    647:        for (cp = ++parptr; *parptr && *parptr != '"'; parptr++)
                    648:            if (*parptr == QUOTE)
                    649:                if (!*++parptr)
                    650:                    parptr--;
                    651:     c = *parptr;
                    652:     *parptr = NULL;
                    653:     *s = getcpy (cp);
                    654:     if ((*parptr = c) == '"')
                    655:        parptr++;
                    656:     return 0;
                    657: }
                    658: 
                    659: /*  */
                    660: 
                    661: static char *
                    662: parse()
                    663: {
                    664:     int     c;
                    665:     register char   *cp;
                    666:     static char result[NAMESZ];
                    667: 
                    668:     for (cp = result; c = *parptr; parptr++)
                    669:        if (isalnum (c)
                    670:                || c == '.'
                    671:                || c == '-'
                    672:                || c == '_'
                    673:                || c =='['
                    674:                || c == ']')
                    675:            *cp++ = c;
                    676:        else
                    677:            break;
                    678:     *cp = NULL;
                    679: 
                    680:     return result;
                    681: }
                    682: 
                    683: /*  */
                    684: 
                    685: static void
                    686: process(folder, fname, ofilen, ofilec)
                    687:        register char *folder, *fname;
                    688:        int ofilen, ofilec;
                    689: {
                    690:     register char  *cp;
                    691:     register struct mcomp  *c1;
                    692:     register FILE  *fp;
                    693: 
                    694:     switch (setjmp (env)) {
                    695:        case OK:
                    696:            if (fname) {
                    697:                fp = mhl_action ? (*mhl_action) (fname) : fopen (fname, "r");
                    698:                if (fp == NULL) {
                    699:                    advise (fname, "unable to open");
                    700:                    exitstat++;
                    701:                    return;
                    702:                }
                    703:            }
                    704:            else {
                    705:                fname = "(stdin)";
                    706:                fp = stdin;
                    707:            }
                    708:            cp = folder ? concat (folder, ":", fname, NULLCP) : getcpy (fname);
                    709:            if (ontty != PITTY)
                    710:                (void) signal (SIGINT, intrser);
                    711:            mhlfile (fp, cp, ofilen, ofilec);/* fall */
                    712: 
                    713:        default:
                    714:            if (ontty != PITTY)
                    715:                (void) signal (SIGINT, SIG_IGN);
                    716:            if (mhl_action == NULL && fp != stdin)
                    717:                (void) fclose (fp);
                    718:            free (cp);
                    719:            if (holder.c_text) {
                    720:                free (holder.c_text);
                    721:                holder.c_text = NULL;
                    722:            }
                    723:            free_queue (&msghd, &msgtl);
                    724:            for (c1 = fmthd; c1; c1 = c1 -> c_next)
                    725:                c1 -> c_flags &= ~HDROUTPUT;
                    726:            break;
                    727:     }
                    728: }
                    729: 
                    730: /*  */
                    731: 
                    732: static void
                    733: mhlfile(fp, mname, ofilen, ofilec)
                    734:        register FILE *fp;
                    735:        register char *mname;
                    736:        int ofilen, ofilec;
                    737: {
                    738:     int     state;
                    739:     register struct mcomp  *c1,
                    740:                            *c2;
                    741:     register char **ip;
                    742:     char    name[NAMESZ],
                    743:             buf[BUFSIZ];
                    744: 
                    745:     if (forwall) {
                    746:        if (digest)
                    747:            printf ("%s", ofilen == 1 ? delim3 : delim4);
                    748:        else {
                    749:            printf ("\n-------");
                    750:            if (ofilen == 1)
                    751:                printf (" Forwarded Message%s", ofilec > 1 ? "s" : "");
                    752:            else
                    753:                printf (" Message %d", ofilen);
                    754:            printf ("\n\n");
                    755:        }
                    756:     }
                    757:     else
                    758:        switch (ontty) {
                    759:            case PITTY:
                    760:                if (ofilec > 1) {
                    761:                    if (ofilen > 1) {
                    762:                        if ((global.c_flags & CLEARSCR))
                    763:                            clear_screen ();
                    764:                        else
                    765:                            printf ("\n\n\n");
                    766:                    }
                    767:                    printf (">>> %s\n\n", mname);
                    768:                }
                    769:                break;
                    770: 
                    771:            case ISTTY:
                    772:                (void) strcpy (buf, "\n");
                    773:                if (ofilec > 1) {
                    774:                    if (SOprintf ("Press <return> to list \"%s\"...", mname)) {
                    775:                        if (ofilen > 1)
                    776:                            printf ("\n\n\n");
                    777:                        printf ("Press <return> to list \"%s\"...", mname);
                    778:                    }
                    779:                    (void) fflush (stdout);
                    780:                    buf[0] = NULL;
                    781:                    (void) read (fileno (stdout), buf, sizeof buf);
                    782:                }
                    783:                if (index (buf, '\n')) {
                    784:                    if ((global.c_flags & CLEARSCR))
                    785:                        clear_screen ();
                    786:                }
                    787:                else
                    788:                    printf ("\n");
                    789:                break;
                    790: 
                    791:            default:
                    792:                if (ofilec > 1) {
                    793:                    if (ofilen > 1) {
                    794:                        printf ("\n\n\n");
                    795:                        if (clearflg > 0)
                    796:                            clear_screen ();
                    797:                    }
                    798:                    printf (">>> %s\n\n", mname);
                    799:                }
                    800:                break;
                    801:        }
                    802: 
                    803: /*  */
                    804: 
                    805:     for (state = FLD;;)
                    806:        switch (state = m_getfld (state, name, buf, sizeof buf, fp)) {
                    807:            case FLD:
                    808:            case FLDPLUS:
                    809:                for (ip = ignores; *ip; ip++)
                    810:                    if (uleq (name, *ip)) {
                    811:                        while (state == FLDPLUS)
                    812:                            state = m_getfld (state, name, buf, sizeof buf, fp);
                    813:                        break;
                    814:                    }
                    815:                if (*ip)
                    816:                    continue;
                    817: 
                    818:                for (c1 = msghd; c1; c1 = c1 -> c_next)
                    819:                    if (uleq (name, c1 -> c_name)) {
                    820:                        c1 -> c_text =
                    821:                            mcomp_add (c1 -> c_flags, buf, c1 -> c_text);
                    822:                        break;
                    823:                    }
                    824:                if (c1 == NULL)
                    825:                    c1 = add_queue (&msghd, &msgtl, name, buf, 0);
                    826:                while (state == FLDPLUS) {
                    827:                    state = m_getfld (state, name, buf, sizeof buf, fp);
                    828:                    c1 -> c_text = add (buf, c1 -> c_text);
                    829:                }
                    830: 
                    831:                for (c2 = fmthd; c2; c2 = c2 -> c_next)
                    832:                    if (uleq (c2 -> c_name, c1 -> c_name))
                    833:                        break;
                    834:                if (c2 == NULL)
                    835:                    c1 -> c_flags |= EXTRA;
                    836:                continue;
                    837: 
                    838:            case BODY:
                    839:            case FILEEOF:
                    840:                row = column = 0;
                    841:                for (c1 = fmthd; c1; c1 = c1 -> c_next) {
                    842:                    if (c1 -> c_flags & CLEARTEXT) {
                    843:                        putcomp (c1, c1, ONECOMP);
                    844:                        continue;
                    845:                    }
                    846:                    if (uleq (c1 -> c_name, "messagename")) {
                    847:                        holder.c_text = concat ("(Message ", mname, ")\n",
                    848:                                            NULLCP);
                    849:                        putcomp (c1, &holder, ONECOMP);
                    850:                        free (holder.c_text);
                    851:                        holder.c_text = NULL;
                    852:                        continue;
                    853:                    }
                    854:                    if (uleq (c1 -> c_name, "extras")) {
                    855:                        for (c2 = msghd; c2; c2 = c2 -> c_next)
                    856:                            if (c2 -> c_flags & EXTRA)
                    857:                                putcomp (c1, c2, TWOCOMP);
                    858:                        continue;
                    859:                    }
                    860:                    if (uleq (c1 -> c_name, "body")) {
                    861:                        if ((holder.c_text = malloc (sizeof buf)) == NULL)
                    862:                            adios (NULLCP, "unable to allocate buffer memory");
                    863:                        (void) strcpy (holder.c_text, buf);
                    864:                        while (state == BODY) {
                    865:                            putcomp (c1, &holder, BODYCOMP);
                    866:                            state = m_getfld (state, name, holder.c_text,
                    867:                                        sizeof buf, fp);
                    868:                        }
                    869:                        free (holder.c_text);
                    870:                        holder.c_text = NULL;
                    871:                        continue;
                    872:                    }
                    873:                    for (c2 = msghd; c2; c2 = c2 -> c_next)
                    874:                        if (uleq (c2 -> c_name, c1 -> c_name)) {
                    875:                            putcomp (c1, c2, ONECOMP);
                    876:                            break;
                    877:                        }
                    878:                }
                    879:                return;
                    880: 
                    881:            case LENERR:
                    882:            case FMTERR:
                    883:                advise (NULLCP, "format error in message %s", mname);
                    884:                exitstat++;
                    885:                return;
                    886: 
                    887:            default:
                    888:                adios (NULLCP, "getfld() returned %d", state);
                    889:        }
                    890: }
                    891: 
                    892: /*  */
                    893: 
                    894: static int
                    895: mcomp_flags(name)
                    896:        register char *name;
                    897: {
                    898:     register struct pair   *ap;
                    899: 
                    900:     for (ap = pairs; ap -> p_name; ap++)
                    901:        if (uleq (ap -> p_name, name))
                    902:            return (ap -> p_flags);
                    903: 
                    904:     return NULL;
                    905: }
                    906: 
                    907: 
                    908: static char *
                    909: mcomp_add(flags, s1, s2)
                    910:        short flags;
                    911:        register char *s1, *s2;
                    912: {
                    913:     register char   *dp;
                    914: 
                    915:     if (!(flags & ADDRFMT))
                    916:        return add (s1, s2);
                    917: 
                    918:     if (s2 && *(dp = s2 + strlen (s2) - 1) == '\n')
                    919:        *dp = NULL;
                    920: 
                    921:     return add (s1, add (",\n", s2));
                    922: }
                    923: 
                    924: /*  */
                    925: 
                    926: struct pqpair {
                    927:     char    *pq_text;
                    928:     char    *pq_error;
                    929:     struct pqpair *pq_next;
                    930: };
                    931: 
                    932: 
                    933: static void
                    934: mcomp_format(c1, c2)
                    935:        register struct mcomp *c1, *c2;
                    936: {
                    937:     int     dat[4];
                    938:     register char  *ap,
                    939:                    *cp;
                    940:     char    buffer[BUFSIZ],
                    941:             error[BUFSIZ];
                    942:     register struct comp   *cptr;
                    943:     register struct pqpair *p,
                    944:                            *q;
                    945:     struct pqpair   pq;
                    946:     register struct mailname   *mp;
                    947: 
                    948:     ap = c2 -> c_text;
                    949:     c2 -> c_text = NULL;
                    950:     dat[0] = dat[1] = dat[2] = 0;
                    951:     dat[3] = sizeof buffer - 1;
                    952:     (void) fmt_compile (c1 -> c_nfs, &c1 -> c_fmt);
                    953: 
                    954:     if (c1 -> c_flags & DATEFMT) {
                    955:        FINDCOMP (cptr, "text");
                    956:        if (cptr)
                    957:            cptr -> c_text = ap;
                    958: 
                    959:        (void) fmtscan (c1 -> c_fmt, buffer, sizeof buffer - 1, dat);
                    960:        /* Don't need to append a newline, dctime() already did */
                    961:        c2 -> c_text = getcpy (buffer);
                    962: 
                    963:        free (ap);
                    964:        return;
                    965:     }
                    966: 
                    967:     (q = &pq) -> pq_next = NULL;
                    968:     while (cp = getname (ap)) {
                    969:        if ((p = (struct pqpair *) calloc ((unsigned) 1, sizeof *p)) == NULL)
                    970:            adios (NULLCP, "unable to allocate pqpair memory");
                    971: 
                    972:        if ((mp = getm (cp, NULLCP, 0, AD_NAME, error)) == NULL) {
                    973:            p -> pq_text = getcpy (cp);
                    974:            p -> pq_error = getcpy (error);
                    975:        }
                    976:        else {
                    977:            p -> pq_text = getcpy (mp -> m_text);
                    978:            mnfree (mp);
                    979:        }
                    980:        q = (q -> pq_next = p);
                    981:     }
                    982: 
                    983:     for (p = pq.pq_next; p; p = q) {
                    984:        FINDCOMP (cptr, "text");
                    985:        if (cptr)
                    986:            cptr -> c_text = p -> pq_text;
                    987:        FINDCOMP (cptr, "error");
                    988:        if (cptr)
                    989:            cptr -> c_text = p -> pq_error;
                    990: 
                    991:        (void) fmtscan (c1 -> c_fmt, buffer, sizeof buffer - 1, dat);
                    992:        if (*buffer) {
                    993:            if (c2 -> c_text)
                    994:                c2 -> c_text = add (",\n", c2 -> c_text);
                    995:            if (*(cp = buffer + strlen (buffer) - 1) == '\n')
                    996:                *cp = NULL;
                    997:            c2 -> c_text = add (buffer, c2 -> c_text);
                    998:        }
                    999: 
                   1000:        free (p -> pq_text);
                   1001:        if (p -> pq_error)
                   1002:            free (p -> pq_error);
                   1003:        q = p -> pq_next;
                   1004:        free ((char *) p);
                   1005:     }
                   1006: 
                   1007:     c2 -> c_text = add ("\n", c2 -> c_text);
                   1008:     free (ap);
                   1009: }
                   1010: 
                   1011: /*  */
                   1012: 
                   1013: static struct mcomp *
                   1014: add_queue(head, tail, name, text, flags)
                   1015:        register struct mcomp **head, **tail;
                   1016:        register char *name, *text;
                   1017:        int flags;
                   1018: {
                   1019:     register struct mcomp  *c1;
                   1020: 
                   1021:     if ((c1 = (struct mcomp *) calloc ((unsigned) 1, sizeof *c1)) == NULL)
                   1022:        adios (NULLCP, "unable to allocate comp memory");
                   1023: 
                   1024:     c1 -> c_flags = flags & ~INIT;
                   1025:     if (c1 -> c_name = name ? getcpy (name) : NULL)
                   1026:        c1 -> c_flags |= mcomp_flags (c1 -> c_name);
                   1027:     c1 -> c_text = text ? getcpy (text) : NULL;
                   1028:     if (flags & INIT) {
                   1029:        if (global.c_ovtxt)
                   1030:            c1 -> c_ovtxt = getcpy (global.c_ovtxt);
                   1031:        c1 -> c_offset = global.c_offset;
                   1032:        c1 -> c_ovoff = global. c_ovoff;
                   1033:        c1 -> c_width = c1 -> c_length = 0;
                   1034:        c1 -> c_cwidth = global.c_cwidth;
                   1035:        c1 -> c_flags |= global.c_flags & GFLAGS;
                   1036:     }
                   1037:     if (*head == NULL)
                   1038:        *head = c1;
                   1039:     if (*tail != NULL)
                   1040:        (*tail) -> c_next = c1;
                   1041:     *tail = c1;
                   1042: 
                   1043:     return c1;
                   1044: }
                   1045: 
                   1046: 
                   1047: static void
                   1048: free_queue(head, tail)
                   1049:        register struct mcomp **head, **tail;
                   1050: {
                   1051:     register struct mcomp *c1,
                   1052:                          *c2;
                   1053: 
                   1054:     for (c1 = *head; c1; c1 = c2) {
                   1055:        c2 = c1 -> c_next;
                   1056:        if (c1 -> c_name)
                   1057:            free (c1 -> c_name);
                   1058:        if (c1 -> c_text)
                   1059:            free (c1 -> c_text);
                   1060:        if (c1 -> c_ovtxt)
                   1061:            free (c1 -> c_ovtxt);
                   1062:        if (c1 -> c_nfs)
                   1063:            free (c1 -> c_nfs);
                   1064:        if (c1 -> c_fmt)
                   1065:            free ((char *) c1 -> c_fmt);
                   1066:        free ((char *) c1);
                   1067:     }
                   1068: 
                   1069:     *head = *tail = NULL;
                   1070: }
                   1071: 
                   1072: /*  */
                   1073: 
                   1074: static void
                   1075: putcomp(c1, c2, flag)
                   1076:        register struct mcomp *c1, *c2;
                   1077:        int flag;
                   1078: {
                   1079:     int     count,
                   1080:             cchdr;
                   1081:     register char   *cp;
                   1082:     static int lastterm = '\n';                /* initial state */
                   1083: 
                   1084:     cchdr = 0;
                   1085:     lm = 0;
                   1086:     llim = c1 -> c_length ? c1 -> c_length : -1;
                   1087:     wid = c1 -> c_width ? c1 -> c_width : global.c_width;
                   1088:     ovoff = (c1 -> c_ovoff >= 0 ? c1 -> c_ovoff : global.c_ovoff)
                   1089:        + c1 -> c_offset;
                   1090:     if ((ovtxt = c1 -> c_ovtxt ? c1 -> c_ovtxt : global.c_ovtxt) == NULL)
                   1091:        ovtxt = "";
                   1092:     if (wid < ovoff + strlen (ovtxt) + 5)
                   1093:        adios (NULLCP, "component: %s width(%d) too small for overflow(%d)",
                   1094:                c1 -> c_name, wid, ovoff + strlen (ovtxt) + 5);
                   1095:     onelp = NULL;
                   1096: 
                   1097:     if (c1 -> c_flags & CLEARTEXT) {
                   1098:        putstr (c1 -> c_text);
                   1099:        putstr ("\n");
                   1100:        return;
                   1101:     }
                   1102: 
                   1103:     if (c1 -> c_nfs && (c1 -> c_flags & (ADDRFMT | DATEFMT)))
                   1104:        mcomp_format (c1, c2);
                   1105: 
                   1106:     if (c1 -> c_flags & CENTER) {
                   1107:        count = (c1 -> c_width ? c1 -> c_width : global.c_width)
                   1108:            - c1 -> c_offset - strlen (c2 -> c_text);
                   1109:        if (!(c1 -> c_flags & HDROUTPUT) && !(c1 -> c_flags & NOCOMPONENT))
                   1110:            count -= strlen (c1 -> c_text ? c1 -> c_text : c1 -> c_name) + 2;
                   1111:        lm = c1 -> c_offset + (count / 2);
                   1112:     }
                   1113:     else
                   1114:        if (c1 -> c_offset)
                   1115:            lm = c1 -> c_offset;
                   1116: 
                   1117:     if (!(c1 -> c_flags & HDROUTPUT) && !(c1 -> c_flags & NOCOMPONENT)) {
                   1118:         if (c1 -> c_flags & UPPERCASE)         /* uppercase component also */
                   1119:            for (cp = (c1 -> c_text ? c1 -> c_text : c1 -> c_name); *cp; cp++)
                   1120:                if (islower (*cp))
                   1121:                    *cp = toupper (*cp);
                   1122:        if (flag != BODYCOMP || lastterm == '\n')
                   1123:            putstr (c1 -> c_text ? c1 -> c_text : c1 -> c_name);
                   1124:        if (flag != BODYCOMP) {
                   1125:            putstr (": ");
                   1126:            c1 -> c_flags |= HDROUTPUT;
                   1127:        }
                   1128: 
                   1129:        cchdr++;
                   1130:        if ((count = c1 -> c_cwidth -
                   1131:                strlen (c1 -> c_text ? c1 -> c_text : c1 -> c_name) - 2) > 0)
                   1132:            while (count--)
                   1133:                putstr (" ");
                   1134:     }
                   1135: 
                   1136:     if (flag == TWOCOMP
                   1137:            && !(c2 -> c_flags & HDROUTPUT)
                   1138:            && !(c2 -> c_flags & NOCOMPONENT)) {
                   1139:         if (c1 -> c_flags & UPPERCASE)
                   1140:            for (cp = c2 -> c_name; *cp; cp++)
                   1141:                if (islower (*cp))
                   1142:                    *cp = toupper (*cp);
                   1143:        putstr (c2 -> c_name);
                   1144:        putstr (": ");
                   1145:        c2 -> c_flags |= HDROUTPUT;
                   1146:     }
                   1147:     if (c1 -> c_flags & UPPERCASE)
                   1148:        for (cp = c2 -> c_text; *cp; cp++)
                   1149:            if (islower (*cp))
                   1150:                *cp = toupper (*cp);
                   1151: 
                   1152:     count = 0;
                   1153:     if (cchdr)
                   1154:        count = (c1 -> c_cwidth >= 0) ? c1 -> c_cwidth
                   1155:                    : strlen (c1 -> c_text ? c1 -> c_text : c1 -> c_name) + 2;
                   1156:     count += c1 -> c_offset;
                   1157: 
                   1158:     putstr (oneline (c2 -> c_text, c1 -> c_flags));
                   1159:     if (term == '\n')
                   1160:        putstr ("\n");
                   1161:     lastterm = term;
                   1162:     while (cp = oneline (c2 -> c_text, c1 -> c_flags)) {
                   1163:        if (flag == BODYCOMP
                   1164:                && lastterm == '\n'
                   1165:                && !(c1 -> c_flags & HDROUTPUT)
                   1166:                && !(c1 -> c_flags & NOCOMPONENT))
                   1167:            putstr (c1 -> c_text ? c1 -> c_text : c1 -> c_name);
                   1168:        if (*cp) {
                   1169:            lm = count;
                   1170:            putstr (cp);
                   1171:        }
                   1172:        if (term == '\n')
                   1173:            putstr ("\n");
                   1174:        lastterm = term;
                   1175:     }
                   1176: }
                   1177: 
                   1178: /*  */
                   1179: 
                   1180: static char *
                   1181: oneline(stuff, flags)
                   1182:        register char *stuff;
                   1183:        short flags;
                   1184: {
                   1185:     int     spc;
                   1186:     register char   *cp,
                   1187:                    *ret;
                   1188: 
                   1189:     if (onelp == NULL)
                   1190:        onelp = stuff;
                   1191:     if (*onelp == NULL)
                   1192:        return (onelp = NULL);
                   1193: 
                   1194:     ret = onelp;
                   1195:     term = 0;
                   1196:     if (flags & COMPRESS) {
                   1197:        for (spc = 1, cp = ret; *onelp; onelp++)
                   1198:            if (isspace (*onelp)) {
                   1199:                if (*onelp == '\n' && (!onelp[1] || (flags & ADDRFMT))) {
                   1200:                    term = '\n';
                   1201:                    *onelp++ = NULL;
                   1202:                    break;
                   1203:                }
                   1204:                else
                   1205:                    if (!spc) {
                   1206:                        *cp++ = ' ';
                   1207:                        spc++;
                   1208:                    }
                   1209:            }
                   1210:            else {
                   1211:                *cp++ = *onelp;
                   1212:                spc = 0;
                   1213:            }
                   1214: 
                   1215:        *cp = NULL;
                   1216:     }
                   1217:     else {
                   1218:        while (*onelp && *onelp != '\n')
                   1219:            onelp++;
                   1220:        if (*onelp == '\n') {
                   1221:            term = '\n';
                   1222:            *onelp++ = NULL;
                   1223:        }
                   1224:        if (flags & LEFTADJUST)
                   1225:            while (*ret == ' ' || *ret == '\t')
                   1226:                ret++;
                   1227:     }
                   1228: 
                   1229:     return ret;
                   1230: }
                   1231: 
                   1232: /*  */
                   1233: 
                   1234: static void
                   1235: putstr(string)
                   1236:        register char *string;
                   1237: {
                   1238:     if (!column && lm > 0)
                   1239:        while (lm > 0)
                   1240:            if (lm >= 8) {
                   1241:                putch ('\t');
                   1242:                lm -= 8;
                   1243:            }
                   1244:            else {
                   1245:                putch (' ');
                   1246:                lm--;
                   1247:            }
                   1248:     lm = 0;
                   1249:     while (*string)
                   1250:        putch (*string++);
                   1251: }
                   1252: 
                   1253: /*  */
                   1254: 
                   1255: static void
                   1256: putch(ch)
                   1257:        register char ch;
                   1258: {
                   1259:     char    buf[BUFSIZ];
                   1260: 
                   1261:     if (llim == 0)
                   1262:        return;
                   1263: 
                   1264:     switch (ch) {
                   1265:        case '\n':
                   1266:            if (llim > 0)
                   1267:                llim--;
                   1268:            column = 0;
                   1269:            row++;
                   1270:            if (ontty != ISTTY || row != global.c_length)
                   1271:                break;
                   1272:            if (global.c_flags & BELL)
                   1273:                (void) putchar ('\007');
                   1274:            (void) fflush (stdout);
                   1275:            buf[0] = NULL;
                   1276:            (void) read (fileno (stdout), buf, sizeof buf);
                   1277:            if (index (buf, '\n')) {
                   1278:                if (global.c_flags & CLEARSCR)
                   1279:                    clear_screen ();
                   1280:                row = 0;
                   1281:            }
                   1282:            else {
                   1283:                (void) putchar ('\n');
                   1284:                row = global.c_length / 3;
                   1285:            }
                   1286:            return;
                   1287: 
                   1288:        case '\t':
                   1289:            column |= 07;
                   1290:            column++;
                   1291:            break;
                   1292: 
                   1293:        case '\b':
                   1294:            column--;
                   1295:            break;
                   1296: 
                   1297:        case '\r':
                   1298:            column = 0;
                   1299:            break;
                   1300: 
                   1301:        default:
                   1302:            if (column == 0 && forwflg && dashflg && ch == '-')
                   1303:                (void) putchar ('-'), putchar (' ');
                   1304:            if (ch >= ' ')
                   1305:                column++;
                   1306:            break;
                   1307:     }
                   1308: 
                   1309:     if (column >= wid) {
                   1310:        putch ('\n');
                   1311:        if (ovoff > 0)
                   1312:            lm = ovoff;
                   1313:        putstr (ovtxt ? ovtxt : "");
                   1314:        putch (ch);
                   1315:        return;
                   1316:     }
                   1317: 
                   1318:     (void) putchar (ch);
                   1319: }
                   1320: 
                   1321: /*  */
                   1322: 
                   1323: /* ARGSUSED */
                   1324: 
                   1325: static SIGDECL
                   1326: intrser(i)
                   1327:        int i;
                   1328: {
                   1329: #ifndef        BSD42
                   1330:     (void) signal (SIGINT, intrser);
                   1331: #endif BSD42
                   1332: 
                   1333:     discard (stdout);
                   1334:     (void) putchar ('\n');
                   1335: 
                   1336:     longjmp (env, DONE);
                   1337: }
                   1338: 
                   1339: 
                   1340: /* ARGSUSED */
                   1341: 
                   1342: static SIGDECL
                   1343: pipeser(i)
                   1344:        int i;
                   1345: {
                   1346: #ifndef        BSD42
                   1347:     (void) signal (SIGPIPE, pipeser);
                   1348: #endif BSD42
                   1349: 
                   1350:     mhldone (NOTOK);
                   1351: }
                   1352: 
                   1353: 
                   1354: /* ARGSUSED */
                   1355: 
                   1356: static SIGDECL
                   1357: quitser(i)
                   1358:        int i;
                   1359: {
                   1360: #ifndef        BSD42
                   1361:     (void) signal (SIGQUIT, quitser);
                   1362: #endif BSD42
                   1363: 
                   1364:     (void) putchar ('\n');
                   1365:     (void) fflush (stdout);
                   1366: 
                   1367:     mhldone (NOTOK);
                   1368: }
                   1369: 
                   1370: /*  */
                   1371: 
                   1372: #undef adios
                   1373: 
                   1374: mhlsbr(argc, argv, action)
                   1375:        int argc;
                   1376:        register char **argv;
                   1377:        register FP (*action)();
                   1378: {
                   1379:     SIGDECL (*istat)(), (*pstat)(), (*qstat)();
                   1380:     register char   *cp;
                   1381:     register struct mcomp  *c1;
                   1382: 
                   1383:     switch (setjmp (mhlenv)) {
                   1384:        case OK:
                   1385:            cp = invo_name;
                   1386:            bellflg = clearflg = forwflg = forwall = exitstat = 0;
                   1387:            digest = NULL;
                   1388:            ontty = NOTTY;
                   1389:            mhl_action = action;
                   1390:            if ((istat = signal (SIGINT, SIG_IGN)) != SIG_DFL)
                   1391:                (void) signal (SIGINT, istat);
                   1392:            if ((qstat = signal (SIGQUIT, SIG_IGN)) != SIG_DFL)
                   1393:                (void) signal (SIGQUIT, qstat);
                   1394:            pstat = signal (SIGPIPE, pipeser);
                   1395:            (void) mhl (argc, argv);    /* fall */
                   1396: 
                   1397:        default:
                   1398:            (void) signal (SIGINT, istat);
                   1399:            (void) signal (SIGQUIT, qstat);
                   1400:            (void) signal (SIGPIPE, SIG_IGN);/* XXX */
                   1401:            if (ontty == PITTY)
                   1402:                m_pclose ();
                   1403:            (void) signal (SIGPIPE, pstat);
                   1404:            invo_name = cp;
                   1405:            if (holder.c_text) {
                   1406:                free (holder.c_text);
                   1407:                holder.c_text = NULL;
                   1408:            }
                   1409:            free_queue (&msghd, &msgtl);
                   1410:            for (c1 = fmthd; c1; c1 = c1 -> c_next)
                   1411:                c1 -> c_flags &= ~HDROUTPUT;
                   1412:            return exitstat;
                   1413:     }
                   1414: }
                   1415: 
                   1416: /*  */
                   1417: 
                   1418: /* VARARGS2 */
                   1419: 
                   1420: static void
                   1421: mhladios(what, fmt, a, b, c, d, e, f)
                   1422:        char *what, *fmt, *a, *b, *c, *d, *e, *f;
                   1423: {
                   1424:     advise (what, fmt, a, b, c, d, e, f);
                   1425:     mhldone (1);
                   1426: }
                   1427: 
                   1428: 
                   1429: void
                   1430: mhldone(status)
                   1431:        int status;
                   1432: {
                   1433:     exitstat = status;
                   1434:     if (mhl_action)
                   1435:        longjmp (mhlenv, DONE);
                   1436:     else
                   1437:        done(exitstat);         /* call real done() */
                   1438: }
                   1439: 
                   1440: /*  */
                   1441: 
                   1442: static int m_pid = NOTOK;
                   1443: static  int sd = NOTOK;
                   1444: 
                   1445: 
                   1446: static void
                   1447: m_popen(name)
                   1448:        char *name;
                   1449: {
                   1450:     int     pd[2];
                   1451: 
                   1452:     if (mhl_action && (sd = dup (fileno (stdout))) == NOTOK)
                   1453:        adios ("standard output", "unable to dup()");
                   1454: 
                   1455:     if (pipe (pd) == NOTOK)
                   1456:        adios ("pipe", "unable to");
                   1457: 
                   1458:     switch (m_pid = vfork ()) {
                   1459:        case NOTOK:
                   1460:            adios ("fork", "unable to");
                   1461: 
                   1462:        case OK:
                   1463:            (void) signal (SIGINT, SIG_DFL);
                   1464:            (void) signal (SIGQUIT, SIG_DFL);
                   1465: 
                   1466:            (void) close (pd[1]);
                   1467:            if (pd[0] != fileno (stdin)) {
                   1468:                (void) dup2 (pd[0], fileno (stdin));
                   1469:                (void) close (pd[0]);
                   1470:            }
                   1471:            execlp (name, r1bindex (name, '/'), NULLCP);
                   1472:            fprintf (stderr, "unable to exec ");
                   1473:            perror (name);
                   1474:            _exit (-1);
                   1475: 
                   1476:        default:
                   1477:            (void) close (pd[0]);
                   1478:            if (pd[1] != fileno (stdout)) {
                   1479:                (void) dup2 (pd[1], fileno (stdout));
                   1480:                (void) close (pd[1]);
                   1481:            }
                   1482:     }
                   1483: }
                   1484: 
                   1485: 
                   1486: m_pclose()
                   1487: {
                   1488:     if (m_pid == NOTOK)
                   1489:        return;
                   1490: 
                   1491:     if (sd != NOTOK) {
                   1492:        (void) fflush (stdout);
                   1493:        if (dup2 (sd, fileno (stdout)) == NOTOK)
                   1494:            adios ("standard output", "unable to dup2()");
                   1495: 
                   1496:        clearerr (stdout);
                   1497:        (void) close (sd);
                   1498:        sd = NOTOK;
                   1499:     }
                   1500:     else
                   1501:        (void) fclose (stdout);
                   1502: 
                   1503:     (void) pidwait (m_pid, OK);
                   1504:     m_pid = NOTOK;
                   1505: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.