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: }

Defined functions

OfficialName defined in line 277; never used

Defined variables

bodycomp defined in line 30; used 5 times
compbuffers defined in line 33; used 2 times
dat defined in line 38; used 7 times
datecomp defined in line 29; used 8 times
fmt defined in line 27; used 2 times
ncomps defined in line 32; used 5 times
scanl defined in line 36; used 4 times
used_buf defined in line 34; used 4 times

Defined macros

FPUTS defined in line 44; used 8 times
MAXSCANL defined in line 14; used 2 times
SBUFSIZ defined in line 15; used 4 times
Last modified: 1986-04-21
Generated: 2016-12-26
Generated by src2html V0.67
page hit count: 1629
Valid CSS Valid XHTML 1.0 Strict