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