/** * There is data available on the feed. Read it into the buffer * then deal with what we got. * * @param ifd [in] File-descriptor of the input data-feed * @retval 0 Success * @retval ENOMEM Out of memory * @retval ENODATA End of input data-feed */ int feedTheXbuf(const int ifd) { int status; size_t nn = 0; /* space available in buffer */ ptrdiff_t remaining = (ptrdiff_t)theBuf->bufsiz - (theBuf->get - theBuf->base); if (remaining <= CHUNKSIZE) { if (theBuf->bufsiz >= maxProductSize) { log_warning_q( "Data-product would exceed %lu bytes. Resetting input buffer.", maxProductSize); justify_xbuf(theBuf, 0); } log_info_q("Expanding input buffer size to %lu\n", (unsigned long)(2 * theBuf->bufsiz)); theBuf = expand_xbuf(theBuf, theBuf->bufsiz); if (theBuf == NULL) { status = errno == 0 ? ENOMEM : errno; log_add_syserr("expand_xbuf"); log_flush_error(); return status; } } status = (*read_feed)(ifd, (char *)theBuf->put, CHUNKSIZE, &nn); if(status != ENOERR) { log_add_errno(status, "read_feed"); log_flush_error(); return status; } /* else */ if(nn == 0) return ENODATA; /* end of file */ /* else */ /* usual case */ /* assert(nn > 0); */ theBuf->cnt += nn; theBuf->put += nn; return ENOERR; }
int scan_faa604 (xbuf * buf) { extern char *parity; int sent = 0; int ch; static enum state { SKIP, SEARCH, HEADER_SEEN } state = SEARCH; while ((ch = nextc (buf)) != EOB) { switch(ch) { case SOH: switch (state) { case SKIP: log_debug("Resync skipped %05ld bytes", (long) (buf->get - buf->base) - 1); break; case HEADER_SEEN: sohetx_missed++; log_error("Lone SOH error - %s", faa604_err_ident(buf)); break; } justify_xbuf (buf, 1); state = HEADER_SEEN; break; case ETX: switch (state) { case SKIP: #if 0 case SEARCH: #endif sohetx_missed++; log_error("Lone ETX error - %s", faa604_err_ident(buf)); break; case HEADER_SEEN: { const long plen = buf->get - buf->base; if(plen >= MIN_FAA604_MSG_LEN) { faa604_send_buf (buf); sent++; } else { not_faa604++; log_error("scan_faa604 - length %ld too short", plen); } justify_xbuf (buf, 0); state = SEARCH; } break; } justify_xbuf (buf, 0); state = SEARCH; break; #if defined(PARITY_ERR_CH) case 0: /* * Backward compatibility * except it can change file feeds */ if(state == HEADER_SEEN && (parity != NULL && *parity != 'n')) { *(buf->get -1) = PARITY_ERR_CH; } break; #endif default: if(state == SEARCH && isgraph(ch)) state = SKIP; break; } } /* input character loop */ return sent; }
scan_wmo_binary(xbuf *buf) #endif { int sent = 0; int ch; while ((ch = nextc(buf)) != EOB) { # if defined(SCAN_CHECK) unsigned prev_crc; static unsigned crc; static unsigned offset; # endif static enum state { START, SEARCH, SOH_, SOH_CR_, SOH_CR_CR_, HEADER_SEEN, CR_, CR_CR_, CR_CR_NL_ # if defined(SCAN_CHECK) , TRAILER_SEEN, CHECKBYTE_SEEN # endif } state = START; /* * Incrementing the checksum at this point is not always necessary * but is done to reduce the number of ADD_CRC() invocations and, * consequently and hopefully, to reduce problems with maintenance * and understanding. */ # if defined(SCAN_CHECK) prev_crc = crc; ADD_CRC(crc, ch); # endif switch (state) { case START: if (SOH == ch) { # if defined(SCAN_CHECK) RESET(offset, crc, ch); # endif state = SOH_; } else { if (CR != ch && NL != ch) { udebug("garbage encountered while searching for header"); } state = SEARCH; } break; case SEARCH: if (SOH == ch) { # if defined(SCAN_CHECK) RESET(offset, crc, ch); # endif state = SOH_; } break; case SOH_: # if defined(SCAN_CHECK) if (SOH == ch) { RESET(offset, crc, ch); } else # endif if (CR == ch) { state = SOH_CR_; } else { state = SEARCH; } break; case SOH_CR_: if (CR == ch) { state = SOH_CR_CR_; } else { state = SEARCH; } break; case SOH_CR_CR_: if (NL == ch) { justify_xbuf(buf, 4); state = HEADER_SEEN; } else if (CR != ch) { state = SEARCH; } break; case HEADER_SEEN: if (CR == ch) state = CR_; break; case CR_: state = CR == ch ? CR_CR_ : HEADER_SEEN; break; case CR_CR_: if (NL == ch) { state = CR_CR_NL_; } else if (CR != ch) { state = HEADER_SEEN; } break; case CR_CR_NL_: if (ETX == ch) { /* see if we can peek ahead, and if so, does it look like the start of a new product? */ if(! peek_ahead(buf)) { state = HEADER_SEEN; break; } } if (ETX == ch) { # if defined(SCAN_CHECK) state = TRAILER_SEEN; # else const long plen = buf->get - buf->base; if(plen >= MIN_WMO_MSG_LEN) { wmo_send_buf (buf, 0); sent++; } else { not_wmo++; uerror("scan_wmo_binary: length %ld too short", plen); } justify_xbuf(buf, 0); state = START; # endif } else if (CR == ch) { state = CR_; } else { if (ESC == ch) { xbuf_rubout(buf); # if defined(SCAN_CHECK) crc = prev_crc; # endif } state = HEADER_SEEN; } break; # if defined(SCAN_CHECK) case TRAILER_SEEN: state = CHECKBYTE_SEEN; break; case CHECKBYTE_SEEN: if (0 != crc) { uerror("Checksum (0x%04x) error %s", crc, wmo_err_ident(buf)); bad_cksum++; } else { const long plen = buf->get - buf->base; if(plen >= MIN_WMO_MSG_LEN) { wmo_send_buf (buf, 2); sent++; } else { not_wmo++; uerror("scan_wmo_binary_crc: length %ld too short", plen); } } justify_xbuf(buf, 0); state = START; break; # endif } /* state switch */ # if defined(SCAN_CHECK) offset++; # endif } /* input character loop */ return sent ; }
int scan_faa604_parity (xbuf * buf) { extern char *parity; int sent = 0; int ch; static enum state { SKIP, SEARCH, HEADER_SEEN, PARITY_PIP } state = SEARCH; while ((ch = nextc (buf)) != EOB) { switch(ch) { case SOH: switch (state) { case SKIP: log_debug("Resync skipped %05ld bytes", (long) (buf->get - buf->base) - 1); break; case HEADER_SEEN: sohetx_missed++; log_error("Lone SOH error - %s", faa604_err_ident(buf)); break; case PARITY_PIP: parity_errs++; log_error("Parity error - %s", faa604_err_ident(buf)); break; } justify_xbuf (buf, 1); state = HEADER_SEEN; break; case ETX: switch (state) { case SKIP: #if 0 case SEARCH: #endif sohetx_missed++; log_error("Lone ETX error - %s", faa604_err_ident(buf)); break; case HEADER_SEEN: { const long plen = buf->get - buf->base; if(plen >= MIN_FAA604_MSG_LEN) { faa604_send_buf (buf); sent++; } else { not_faa604++; log_error("scan_faa604 - length %ld too short", plen); } justify_xbuf (buf, 0); state = SEARCH; } break; case PARITY_PIP: parity_errs++; log_error("Parity error - %s", faa604_err_ident(buf)); break; } justify_xbuf (buf, 0); state = SEARCH; break; case 0: if(state == HEADER_SEEN /* && (parity != NULL && *parity != 'n') */ ) { state = PARITY_PIP; } break; default: if(state == SEARCH && isgraph(ch)) state = SKIP; break; } } /* input character loop */ return sent; }
scan_wmo_parity (xbuf * buf) #endif { extern char *parity; int sent = 0; int ch; static enum state { SKIP, SEARCH, HEADER_SEEN, PARITY_PIP } state = SEARCH; while ((ch = nextc (buf)) != EOB) { switch(ch) { case SOH: switch (state) { case SKIP: udebug ("Resync skipped %05ld bytes", (long) (buf->get - buf->base) - 1); break; #if 0 case SEARCH: udebug ("Search %05ld bytes", (long) (buf->get - buf->base) - 1); break; #endif case HEADER_SEEN: sohetx_missed++; uerror("Lone SOH error %s", wmo_err_ident(buf)); break; case PARITY_PIP: bad_cksum++; uerror("Parity error %s", wmo_err_ident(buf)); break; } justify_xbuf (buf, 1); state = HEADER_SEEN; break; case ETX: switch (state) { case SKIP: #if 0 case SEARCH: #endif sohetx_missed++; uerror("Lone ETX error %s", wmo_err_ident(buf)); break; case HEADER_SEEN: { const long plen = buf->get - buf->base; if(plen >= MIN_WMO_MSG_LEN) { wmo_send_buf (buf, 0); sent++; } else { not_wmo++; uerror("scan_wmo: length %ld too short", plen); } justify_xbuf (buf, 0); state = SEARCH; } break; case PARITY_PIP: bad_cksum++; uerror("Parity error %s", wmo_err_ident(buf)); break; } justify_xbuf (buf, 0); state = SEARCH; break; #if defined(SCAN_CHECK) case 0: if(state == HEADER_SEEN /* && (parity != NULL && *parity != 'n') */ ) { state = PARITY_PIP; } break; #elif defined(PARITY_ERR_CH) case 0: /* * Backward compatibility * except it can change file feeds */ if(state == HEADER_SEEN && (parity != NULL && *parity != 'n')) { *(buf->get -1) = PARITY_ERR_CH; } break; #endif default: if(state == SEARCH && isgraph(ch)) state = SKIP; break; } } /* input character loop */ return sent; }