|
|
1.1 ! root 1: /* scansbr.c - routines to help scan along... */ ! 2: ! 3: #include "../h/mh.h" ! 4: #include "../h/addrsbr.h" ! 5: #include "../h/formatsbr.h" ! 6: #include "../h/scansbr.h" ! 7: #include "../zotnet/tws.h" ! 8: #include <stdio.h> ! 9: #include <ctype.h> ! 10: #include <sys/types.h> ! 11: #include <sys/stat.h> ! 12: ! 13: ! 14: #define MAXSCANL 510 /* longest possible scan line */ ! 15: #define SBUFSIZ 256 ! 16: /* buffer size for content part of header ! 17: * fields. We want this to be large ! 18: * enough so that we don't do a lot of ! 19: * extra FLDPLUS calls on m_getfld but ! 20: * small enough so that we don't snarf ! 21: * the entire message body when we're ! 22: * only going to display 30 characters ! 23: * of it. ! 24: */ ! 25: ! 26: /* */ ! 27: ! 28: static struct format *fmt; ! 29: ! 30: static struct comp *datecomp; /* pntr to "date" comp */ ! 31: static struct comp *bodycomp; /* pntr to "body" pseudo-comp (if referenced) */ ! 32: static int ncomps = 0; /* # of interesting components */ ! 33: static char **compbuffers = 0; /* buffers for component text */ ! 34: static struct comp **used_buf = 0; /* stack for comp that use buffers */ ! 35: ! 36: char *scanl = 0; /* text of most recent scanline */ ! 37: ! 38: static int dat[4]; /* aux. data for format routine */ ! 39: ! 40: #ifdef RPATHS ! 41: char *unixline(); /* info from UNIX From: line */ ! 42: #endif RPATHS ! 43: ! 44: #define FPUTS(buf) {\ ! 45: if (fputs(buf,scnout) == EOF)\ ! 46: adios (scnmsg, "write error on");\ ! 47: } ! 48: ! 49: /* */ ! 50: ! 51: /* ARGSUSED */ ! 52: ! 53: scan(inb, innum, outnum, nfs, width, curflg, header, size, noisy, aud) ! 54: register FILE *inb; ! 55: char *nfs; ! 56: int innum, outnum, width, curflg, header; ! 57: long size; ! 58: int noisy, aud; ! 59: { ! 60: int compnum, encrypted, state; ! 61: register int i; ! 62: register struct comp *cptr; ! 63: register char *tmpbuf; ! 64: register char **nxtbuf; ! 65: register struct comp **savecomp; ! 66: char *scnmsg; ! 67: FILE *scnout; ! 68: char name[NAMESZ]; ! 69: static int slwidth; ! 70: #ifdef RPATHS ! 71: char *cp; ! 72: #endif RPATHS ! 73: ! 74: /* first-time only initialization */ ! 75: if (scanl == NULLCP) { ! 76: if (width == 0) { ! 77: if ((width = sc_width()) < WIDTH / 2) ! 78: width = WIDTH / 2; ! 79: else if (width > MAXSCANL) ! 80: width = MAXSCANL; ! 81: } ! 82: dat[3] = slwidth = width; ! 83: scanl = (char *) malloc((unsigned)MAXSCANL+2); ! 84: if (outnum) ! 85: (void) umask(~m_gmprot()); ! 86: ! 87: ncomps = fmt_compile(nfs, &fmt) + 1; ! 88: FINDCOMP(bodycomp, "body"); ! 89: FINDCOMP(datecomp, "date"); ! 90: FINDCOMP(cptr, "encrypted"); ! 91: if (!cptr) ! 92: if (cptr = (struct comp *) calloc(1, sizeof *cptr)) { ! 93: cptr->c_name = "encrypted"; ! 94: cptr->c_next = ! 95: wantcomp[i = CHASH(cptr->c_name)]; ! 96: wantcomp[i] = cptr; ! 97: ncomps++; ! 98: } ! 99: nxtbuf = compbuffers = (char **) ! 100: calloc((unsigned) ncomps, sizeof(char *)); ! 101: if (nxtbuf == NULL) ! 102: adios(NULLCP, "unable to allocate component buffers"); ! 103: used_buf = (struct comp **) ! 104: calloc((unsigned) (ncomps + 1), sizeof(struct comp *)); ! 105: if (used_buf == NULL) ! 106: adios(NULLCP, "unable to allocate component buffer stack"); ! 107: used_buf += ncomps + 1; ! 108: *--used_buf = 0; ! 109: for (i = ncomps; i--;) ! 110: if ((*nxtbuf++ = malloc(SBUFSIZ)) == NULL) ! 111: adios(NULLCP, ! 112: "unable to allocate component buffer"); ! 113: } ! 114: /* each-message initialization */ ! 115: nxtbuf = compbuffers; ! 116: savecomp = used_buf; ! 117: tmpbuf = *nxtbuf++; ! 118: dat[0] = innum ? innum : outnum; ! 119: dat[1] = curflg; ! 120: ! 121: /* ! 122: * get the first field. If the msg is non-empty and we're doing ! 123: * an "inc", open the output file. ! 124: */ ! 125: if ((state = m_getfld(FLD, name, tmpbuf, SBUFSIZ, inb)) == FILEEOF) ! 126: return SCNEOF; ! 127: ! 128: if (outnum) { ! 129: if (outnum > 0) { ! 130: scnmsg = m_name(outnum); ! 131: if (*scnmsg == '?') /* msg num out of range */ ! 132: return SCNNUM; ! 133: } else ! 134: scnmsg = "/dev/null"; ! 135: if ((scnout = fopen(scnmsg, "w")) == NULL) ! 136: adios(scnmsg, "unable to write"); ! 137: #ifdef RPATHS ! 138: if ((cp = unixline()) && *cp != '\n') { ! 139: FPUTS("Return-Path: "); ! 140: FPUTS(cp); ! 141: } ! 142: #endif RPATHS ! 143: } ! 144: /* scan - main loop */ ! 145: for (compnum = 1;; ! 146: state = m_getfld(state, name, tmpbuf, SBUFSIZ, inb)) { ! 147: switch (state) { ! 148: case FLD: ! 149: case FLDPLUS: ! 150: compnum++; ! 151: if (outnum) { ! 152: FPUTS(name); ! 153: (void) putc(':', scnout); ! 154: FPUTS(tmpbuf); ! 155: } ! 156: /* ! 157: * If we're interested in this component, save a ! 158: * pointer to the component text, then start using ! 159: * our next free buffer as the component temp buffer ! 160: * (buffer switching saves an extra copy of the ! 161: * component text). ! 162: */ ! 163: if (cptr = wantcomp[CHASH(name)]) ! 164: do { ! 165: if (uleq(name, cptr->c_name)) { ! 166: if (!cptr->c_text) { ! 167: cptr->c_text = tmpbuf; ! 168: *--savecomp = cptr; ! 169: tmpbuf = *nxtbuf++; ! 170: } ! 171: break; ! 172: } ! 173: } while (cptr = cptr->c_next); ! 174: ! 175: while (state == FLDPLUS) { ! 176: state = ! 177: m_getfld(state, name, tmpbuf, SBUFSIZ, inb); ! 178: if (outnum) ! 179: FPUTS(tmpbuf); ! 180: } ! 181: break; ! 182: ! 183: case BODY: ! 184: compnum = -1; ! 185: if (!outnum) { ! 186: state = FILEEOF; /* stop now if scan cmd */ ! 187: goto finished; ! 188: } ! 189: (void) putc('\n', scnout); ! 190: FPUTS(tmpbuf); ! 191: /* ! 192: * Performance hack: some people like to run "inc" on ! 193: * things like net.sources or large digests. We do a ! 194: * copy directly into the output buffer rather than ! 195: * going through an intermediate buffer. ! 196: * ! 197: * We need the amount of data m_getfld found & don't ! 198: * want to do a strlen on the long buffer so there's ! 199: * a hack in m_getfld to save the amount of data it ! 200: * returned in the global "msg_count". ! 201: */ ! 202: body: ! 203: while (state == BODY) { ! 204: if (scnout->_cnt <= 0) { ! 205: if (fflush(scnout) == EOF) ! 206: adios(scnmsg, "write error on"); ! 207: } ! 208: state = m_getfld(state, name, ! 209: scnout->_ptr, -(scnout->_cnt), inb); ! 210: scnout->_cnt -= msg_count; ! 211: scnout->_ptr += msg_count; ! 212: } ! 213: goto finished; ! 214: ! 215: case LENERR: ! 216: case FMTERR: ! 217: fprintf(stderr, ! 218: innum ? "??Format error (message %d) in " ! 219: : "??Format error in ", ! 220: outnum ? outnum : innum); ! 221: fprintf(stderr, "component %d\n", compnum); ! 222: ! 223: if (outnum) { ! 224: FPUTS("\n\nBAD MSG:\n"); ! 225: FPUTS(name); ! 226: (void) putc('\n', scnout); ! 227: state = BODY; ! 228: goto body; ! 229: } ! 230: /* fall through */ ! 231: ! 232: case FILEEOF: ! 233: goto finished; ! 234: ! 235: default: ! 236: adios(NULLCP, "getfld() returned %d", state); ! 237: } ! 238: } ! 239: /* format and output the scan line. */ ! 240: finished: ! 241: if (noisy || aud) { ! 242: char *saved_c_text; ! 243: ! 244: if (bodycomp) { ! 245: /* Save and restore buffer so we don't trash our ! 246: dynamic pool! */ ! 247: saved_c_text = bodycomp->c_text; ! 248: bodycomp->c_text = tmpbuf; ! 249: } ! 250: if (size) ! 251: dat[2] = size; ! 252: else if (outnum > 0) ! 253: dat[2] = ftell(scnout); ! 254: ! 255: if ((datecomp && !datecomp->c_text) || (!size && !outnum)) { ! 256: struct stat st; ! 257: (void) fstat(fileno(inb), &st); ! 258: if (!size && !outnum) ! 259: dat[2] = st.st_size; ! 260: if (datecomp) { ! 261: if (!datecomp->c_text) { ! 262: if (datecomp->c_tws == NULL) ! 263: datecomp->c_tws = (struct tws *) ! 264: calloc((unsigned) 1, ! 265: sizeof(*datecomp->c_tws)); ! 266: if (datecomp->c_tws == NULL) ! 267: adios(NULLCP, ! 268: "unable to allocate tws buffer"); ! 269: *datecomp->c_tws = ! 270: *dlocaltime((long *) &st.st_mtime); ! 271: datecomp->c_flags = -1; ! 272: } else { ! 273: datecomp->c_flags = 0; ! 274: } ! 275: } ! 276: } ! 277: (void) fmtscan(fmt, scanl, slwidth, dat); ! 278: if (aud) ! 279: (void) fputs(scanl, aud); ! 280: if (noisy) ! 281: (void) fputs(scanl, stdout); ! 282: ! 283: if (bodycomp) ! 284: bodycomp->c_text = saved_c_text; ! 285: } ! 286: FINDCOMP(cptr, "encrypted"); ! 287: encrypted = cptr && cptr->c_text; ! 288: /* return dynamically allocated buffers to pool */ ! 289: while (cptr = *savecomp++) { ! 290: *--nxtbuf = cptr->c_text; ! 291: cptr->c_text = NULLCP; ! 292: } ! 293: *--nxtbuf = tmpbuf; ! 294: ! 295: if (outnum && fclose(scnout) == EOF) ! 296: adios(scnmsg, "write error on"); ! 297: ! 298: return (state != FILEEOF ? SCNERR : encrypted ? SCNENC : SCNMSG); ! 299: } ! 300: ! 301: /* */ ! 302: ! 303: /* ! 304: * Cheat: we are loaded with adrparse, which wants a routine called ! 305: * OfficialName(). We call adrparse:getm() with the correct arguments ! 306: * to prevent OfficialName() from being called. Hence, the following ! 307: * is to keep the loader happy. ! 308: */ ! 309: ! 310: /* XXX don't bother if linking with the shared library */ ! 311: #ifndef SHARED ! 312: char * ! 313: OfficialName(name) ! 314: register char *name; ! 315: { ! 316: return name; ! 317: } ! 318: ! 319: #endif
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.