Annotation of 43BSD/contrib/mh/uip/replsbr.c, revision 1.1.1.1

1.1       root        1: /* replsbr.c - routines to help repl along... */
                      2: 
                      3: #include "../h/mh.h"
                      4: #include "../h/addrsbr.h"
                      5: #include "../h/formatsbr.h"
                      6: #include <ctype.h>
                      7: #include <stdio.h>
                      8: 
                      9: 
                     10: extern short    ccto,          /* from repl.c */
                     11:                 cccc,
                     12:                 ccme,
                     13:                 format,
                     14:                 outputlinelen,
                     15:                querysw;
                     16: extern char *fcc,
                     17:            *filter,
                     18:             *form;
                     19: 
                     20: static int   dftype;
                     21: 
                     22: static char *badaddrs = NULL;
                     23: static char *dfhost;
                     24: 
                     25: static struct mailname  mq;
                     26: 
                     27: 
                     28: #define SBUFSIZ 256            /* buffer size for content part of header
                     29:                                 * fields.  We want this to be large
                     30:                                 * enough so that we don't do a lot of
                     31:                                 * extra FLDPLUS calls on m_getfld but
                     32:                                 * small enough so that we don't snarf
                     33:                                 * the entire message body when we're
                     34:                                 * not going to use any of it.
                     35:                                 */
                     36: 
                     37: static struct format *fmt;
                     38: 
                     39: static int     ncomps = 0;             /* # of interesting components */
                     40: static char    **compbuffers = 0;      /* buffers for component text */
                     41: static struct comp **used_buf = 0;     /* stack for comp that use buffers */
                     42: 
                     43: static int dat[4];                     /* aux. data for format routine */
                     44: 
                     45: /*  */
                     46: 
                     47: /* ARGSUSED */
                     48: 
                     49: replout (inb, msg, drft)
                     50:     register FILE *inb;
                     51:     char    *msg;
                     52:     char    *drft;
                     53: {
                     54:     register int  state;
                     55:     register int  i;
                     56:     register struct comp *cptr;
                     57:     register char *tmpbuf;
                     58:     register char **nxtbuf;
                     59:     register struct comp **savecomp;
                     60:     FILE    *out;
                     61:     char    name[NAMESZ];
                     62:     char    *scanl;
                     63:     int            char_read = 0;
                     64:     char    *cp;
                     65:     int      format_len;
                     66: 
                     67:     (void) umask( ~ m_gmprot() );
                     68:     if ((out = fopen (drft, "w")) == NULL)
                     69:        adios (drft, "unable to create");
                     70: 
                     71:     cp = new_fs (form ? form : replcomps, NULLCP, NULLCP);
                     72:     format_len = strlen (cp);
                     73:     ncomps = fmt_compile (cp, &fmt) + 1;
                     74:     nxtbuf = compbuffers = (char **)calloc((unsigned)ncomps,sizeof(char *));
                     75:     if (nxtbuf == NULL)
                     76:        adios (NULLCP, "unable to allocate component buffers");
                     77:     used_buf = (struct comp **)calloc((unsigned)(ncomps+1),sizeof(struct comp *));
                     78:     if (used_buf == NULL)
                     79:        adios (NULLCP, "unable to allocate component buffer stack");
                     80:     used_buf += ncomps+1; *--used_buf = 0;
                     81:     for (i = ncomps; i--; )
                     82:        if ((*nxtbuf++ = malloc( SBUFSIZ )) == NULL)
                     83:            adios (NULLCP, "unable to allocate component buffer");
                     84: 
                     85:     nxtbuf = compbuffers;
                     86:     savecomp = used_buf;
                     87:     tmpbuf = *nxtbuf++;
                     88: 
                     89:     /* ignore any components killed by command line switches */
                     90:     if (!ccto) {
                     91:        FINDCOMP (cptr, "to");
                     92:        if (cptr)
                     93:            cptr->c_name = "";
                     94:     }
                     95:     if (!cccc) {
                     96:        FINDCOMP (cptr, "cc");
                     97:        if (cptr)
                     98:            cptr->c_name = "";
                     99:     }
                    100:     /* set up the "fcc" pseudo-component */
                    101:     if (fcc) {
                    102:        FINDCOMP (cptr, "fcc");
                    103:        if (cptr)
                    104:            cptr->c_text = getcpy (fcc);
                    105:     }
                    106:     if (!ccme)
                    107:        (void) ismymbox ((struct mailname *)0); /* XXX */
                    108: 
                    109:     /* pick any interesting stuff out of msg "inb" */
                    110:     for (state = FLD;;) {
                    111:        state = m_getfld (state, name, tmpbuf, SBUFSIZ, inb);
                    112:        switch (state) {
                    113:            case FLD: 
                    114:            case FLDPLUS: 
                    115:                /*
                    116:                 * if we're interested in this component, save a pointer
                    117:                 * to the component text, then start using our next free
                    118:                 * buffer as the component temp buffer (buffer switching
                    119:                 * saves an extra copy of the component text).
                    120:                 */
                    121:                if (cptr = wantcomp[CHASH(name)])
                    122:                    do {
                    123:                        if (uleq(name, cptr->c_name)) {
                    124:                            char_read += msg_count;
                    125:                            if (! cptr->c_text) {
                    126:                                cptr->c_text = tmpbuf;
                    127:                                *--savecomp = cptr;
                    128:                                tmpbuf = *nxtbuf++;
                    129:                            } else {
                    130:                                i = strlen (cp = cptr->c_text) - 1;
                    131:                                if (cp[i] == '\n')
                    132:                                    if (cptr->c_type & CT_ADDR) {
                    133:                                        cp[i] = '\0';
                    134:                                        cp = add (",\n\t", cp);
                    135:                                    } else {
                    136:                                        cp = add ("\t", cp);
                    137:                                    }
                    138:                                cptr->c_text = add (tmpbuf, cp);
                    139:                            }
                    140:                            while (state == FLDPLUS) {
                    141:                                state = m_getfld (state, name, tmpbuf,
                    142:                                                  SBUFSIZ, inb);
                    143:                                cptr->c_text = add (tmpbuf, cptr->c_text);
                    144:                                char_read += msg_count;
                    145:                            }
                    146:                            break;
                    147:                        }
                    148:                    } while (cptr = cptr->c_next);
                    149: 
                    150:                while (state == FLDPLUS)
                    151:                    state = m_getfld (state, name, tmpbuf, SBUFSIZ, inb);
                    152:                break;
                    153: 
                    154:            case LENERR: 
                    155:            case FMTERR: 
                    156:            case BODY: 
                    157:            case FILEEOF:
                    158:                goto finished;
                    159: 
                    160:            default: 
                    161:                adios (NULLCP, "m_getfld() returned %d", state);
                    162:        }
                    163:     }
                    164:     /*
                    165:      * format and output the header lines.
                    166:      */
                    167: finished:
                    168:     /* if there's a "subject" component, strip any "re:"s off it */
                    169:     FINDCOMP (cptr, "subject")
                    170:     if (cptr && (cp = cptr->c_text)) {
                    171:        register char *sp = cp;
                    172: 
                    173:        for (;;) {
                    174:            while (isspace(i = *cp++))
                    175:                ;
                    176:            if ((i | 0x20) != 'r' || (*cp++ | 0x20) != 'e' || *cp++ != ':')
                    177:                break;
                    178:            sp = cp;
                    179:        }
                    180:        if (sp != cptr->c_text) {
                    181:            cp = cptr->c_text;
                    182:            cptr->c_text = getcpy (sp);
                    183:            free (cp);
                    184:        }
                    185:     }
                    186:     i = format_len + char_read + 256;
                    187:     scanl = malloc ((unsigned)i + 2);
                    188:     dat[0] = dat[1] = dat[2] = 0;
                    189:     dat[3] = outputlinelen;
                    190:     (void) fmtscan (fmt, scanl, i, dat);
                    191:     fputs (scanl, out);
                    192:     if (badaddrs) {
                    193:        fputs ("\nrepl: bad addresses:\n", out);
                    194:        fputs ( badaddrs, out);
                    195:     }
                    196:     if (filter)
                    197:        replfilter (inb, out);
                    198: 
                    199:     if (ferror (out))
                    200:        adios (drft, "error writing");
                    201:     (void) fclose (out);
                    202: 
                    203:     /* return dynamically allocated buffers */
                    204:     free (scanl);
                    205:     while ( cptr = *savecomp++ )
                    206:        free (cptr->c_text);
                    207:     while ( cp = *nxtbuf++)
                    208:        free (cp);
                    209:     free (tmpbuf);
                    210:     free ((char *) compbuffers);
                    211:     free ((char *) used_buf);
                    212: }
                    213: 
                    214: /*  */
                    215: 
                    216: static char *buf;              /* our current working buffer */
                    217: static char *bufend;           /* end of working buffer */
                    218: static char *last_dst;         /* buf ptr at end of last call */
                    219: static unsigned int bufsiz;    /* current size of buf */
                    220: 
                    221: #define BUFINCR 512            /* how much to expand buf when if fills */
                    222: 
                    223: #define CPY(s) { cp = (s); while (*dst++ = *cp++) ; --dst; }
                    224: 
                    225: /* check if there's enough room in buf for str.  add more mem if needed */
                    226: #define CHECKMEM(str) \
                    227:            if ((len = strlen (str)) >= bufend - dst) {\
                    228:                bufsiz += ((dst + len - bufend) / BUFINCR + 1) * BUFINCR;\
                    229:                buf = realloc (buf, bufsiz);\
                    230:                if (! buf)\
                    231:                    adios (NULLCP, "formataddr: couldn't get buffer space");\
                    232:                bufend = buf + bufsiz;\
                    233:            }
                    234: 
                    235: 
                    236: /* fmtscan will call this routine if the user includes the function
                    237:  * "(formataddr {component})" in a format string.  "orig" is the
                    238:  * original contents of the string register.  "str" is the address
                    239:  * string to be formatted and concatenated onto orig.  This routine
                    240:  * returns a pointer to the concatenated address string.
                    241:  *
                    242:  * We try to not do a lot of malloc/copy/free's (which is why we
                    243:  * don't call "getcpy") but still place no upper limit on the
                    244:  * length of the result string.
                    245:  */
                    246: char *formataddr (orig, str)
                    247:     char *orig;
                    248:     char *str;
                    249: {
                    250:     register int  len;
                    251:     char    baddr[BUFSIZ];
                    252:     register int  isgroup;
                    253:     register char  *dst;
                    254:     register char  *cp;
                    255:     register char  *sp;
                    256:     register struct mailname *mp = NULL;
                    257: 
                    258:     /* if we don't have a buffer yet, get one */
                    259:     if (bufsiz == 0) {
                    260:        buf = malloc (BUFINCR);
                    261:        if (! buf)
                    262:            adios (NULLCP, "formataddr: couldn't allocate buffer space");
                    263:        bufsiz = BUFINCR - 6;  /* leave some slop */
                    264:        bufend = buf + bufsiz;
                    265:     }
                    266:     /*
                    267:      * If "orig" points to our buffer we can just pick up where we
                    268:      * left off.  Otherwise we have to copy orig into our buffer.
                    269:      */
                    270:     if (orig == buf)
                    271:        dst = last_dst;
                    272:     else if (!orig || !*orig) {
                    273:        dst = buf;
                    274:        *dst = '\0';
                    275:     } else {
                    276:        CHECKMEM (orig);
                    277:        CPY (orig);
                    278:     }
                    279: 
                    280:     /* concatenate all the new addresses onto 'buf' */
                    281:     for (isgroup = 0; cp = getname (str); ) {
                    282:        if ((mp = getm (cp, dfhost, dftype, AD_NAME, NULLCP)) == NULL) {
                    283:            (void) sprintf (baddr, "\tBAD ADDRRESS: %s\n", cp);
                    284:            badaddrs = add (baddr, badaddrs);
                    285:            continue;
                    286:        }
                    287:        if (isgroup && (mp->m_gname || !mp->m_ingrp)) {
                    288:            *dst++ = ';';
                    289:            isgroup = 0;
                    290:        }
                    291:        if (insert (mp)) {
                    292:            /* if we get here we're going to add an address */
                    293:            if (dst != buf) {
                    294:                *dst++ = ',';
                    295:                *dst++ = ' ';
                    296:            }
                    297:            if (mp->m_gname) {
                    298:                CHECKMEM (mp->m_gname);
                    299:                CPY (mp->m_gname);
                    300:                isgroup++;
                    301:            }
                    302:            sp = adrformat (mp);
                    303:            CHECKMEM (sp);
                    304:            CPY (sp);
                    305:        }
                    306:     }
                    307: 
                    308:     if (isgroup)
                    309:        *dst++ = ';';
                    310: 
                    311:     *dst = '\0';
                    312:     last_dst = dst;
                    313:     return (buf);
                    314: }
                    315: /*  */
                    316: 
                    317: static insert (np)
                    318: register struct mailname *np;
                    319: {
                    320:     char    buffer[BUFSIZ];
                    321:     register struct mailname *mp;
                    322: 
                    323:     if (np -> m_mbox == NULL)
                    324:        return 0;
                    325: 
                    326:     for (mp = &mq; mp -> m_next; mp = mp -> m_next) {
                    327: #ifdef BERK
                    328:        if (uleq (np -> m_mbox, mp -> m_next -> m_mbox))
                    329:            return 0;
                    330: #else not BERK
                    331:        if (uleq (np -> m_host, mp -> m_next -> m_host)
                    332:                && uleq (np -> m_mbox, mp -> m_next -> m_mbox))
                    333:            return 0;
                    334: #endif BERK
                    335:     }
                    336:     if (!ccme && ismymbox (np))
                    337:        return 0;
                    338: 
                    339:     if (querysw) {
                    340:        (void) sprintf (buffer, "Reply to %s? ", adrformat (np));
                    341:        if (!gans (buffer, anoyes))
                    342:        return 0;
                    343:     }
                    344:     mp -> m_next = np;
                    345: #ifdef ISI
                    346:     if (ismymbox (np))
                    347:        ccme = 0;
                    348: #endif ISI
                    349:     return 1;
                    350: }
                    351: 
                    352: /*  */
                    353: 
                    354: static replfilter (in, out)
                    355: register FILE *in,
                    356:              *out;
                    357: {
                    358:     int            pid;
                    359:     char   *mhl;
                    360: 
                    361:     if (filter == NULL)
                    362:        return;
                    363: 
                    364:     if (access (filter, 04) == NOTOK)
                    365:        adios (filter, "unable to read");
                    366: 
                    367:     mhl = r1bindex (mhlproc, '/');
                    368: 
                    369:     rewind (in);
                    370:     (void) fflush (out);
                    371: 
                    372:     switch (pid = vfork ()) {
                    373:        case NOTOK: 
                    374:            adios ("fork", "unable to");
                    375: 
                    376:        case OK: 
                    377:            (void) dup2 (fileno (in), fileno (stdin));
                    378:            (void) dup2 (fileno (out), fileno (stdout));
                    379:            closefds (3);
                    380: 
                    381:            execlp (mhlproc, mhl, "-form", filter, "-noclear", NULLCP);
                    382:            fprintf (stderr, "unable to exec ");
                    383:            perror (mhlproc);
                    384:            _exit (-1);
                    385: 
                    386:        default: 
                    387:            if (pidXwait (pid, mhl))
                    388:                done (1);
                    389:            (void) fseek (out, 0L, 2);
                    390:            break;
                    391:     }
                    392: }

unix.superglobalmegacorp.com

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