|
|
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: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.