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