/** * Returns a data-structure for accessing a shared-memory FIFO. Creates the * FIFO is it doesn't already exist. * * @retval !NULL Pointer the data-structure for accessing the * shared-memory FIFO. * @retval NULL Failure. An error message is logged. */ struct shmhandle* shmfifo_create( const int npages, /**< size of the FIFO in pages */ const int privsz, /**< <size of the private portion of the FIFO in bytes */ const int nkey) /**< Partial key associated with the FIFO or \c -1 to obtain a private, shared-memory FIFO. */ { int shmSize = npages*getpagesize(); int shmid; struct shmhandle* shm = NULL; /* default failure */ key_t key; if (nkey == -1) { shmid = shmget(IPC_PRIVATE, shmSize, IPC_CREAT | IPC_EXCL | S_IRUSR | S_IWUSR); } else { key = (key_t)(DVBS_ID + nkey); /* * IPC_EXCL creates an error condition if the memory already exists... * we can use the existing memory if the program has not changed the * size of the segment or the private structure size */ shmid = shmget(key, shmSize, IPC_CREAT | S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP); } if (shmid == -1) { log_syserr("shmget() failure: npages=%d, nkey=%d", npages, nkey); } else { /* Temporarily attach to initialize the control structure. */ struct shmprefix* p = (struct shmprefix*)shmat(shmid, 0, 0); if (p == (void*)-1) { log_syserr("shmat() failure: id=%d", shmid); } else { int semid; p->read = p->write = sizeof(struct shmprefix) + privsz; p->sz = shmSize; p->privsz = privsz; (void)memset((char*)p + sizeof(struct shmprefix), 0, privsz); (void)shmdt(p); p = NULL; /* Get semaphore */ if (nkey == -1) { semid = semget(IPC_PRIVATE, SI_SEM_COUNT, IPC_CREAT | IPC_EXCL + 0600); } else { /* * IPC_EXCL not used in order to get existing semaphore if * possible. */ semid = semget(key, SI_SEM_COUNT, IPC_CREAT + 0660); } if (semid == -1) { log_syserr("semget() failure"); } else { unsigned short values[SI_SEM_COUNT]; union semun arg; log_debug("shmfifo_create(): Got semaphore: pid=%d, semid=%d", getpid(), semid); values[SI_LOCK] = 1; values[SI_WRITER] = 0; values[SI_READER] = 0; arg.array = values; if (semctl(semid, 0, SETALL, arg) == -1) { log_syserr("semctl() failure: semid=%d", semid); } else { shm = shmfifo_new(); if (NULL != shm) { shm->sid = shmid; shm->privsz = privsz; shm->sz = shmSize; shm->semid = semid; } } /* semaphore values set */ } /* got semaphore set */ } /* shared-memory was attached to "p" */ } /* got shared-memory segment ID */ return shm; }
/** * Reads NOAAPORT data from a shared-memory FIFO or a file, creates LDM * data-products, and inserts the data-products into an LDM product-queue. * * Usage: * * readnoaaport [-nvx] [-q <em>queue</em>] [-u <em>n</em>] [-m mcastAddr] [path]\n * * Where: * <dl> * <dt>-l <em>log</em></dt> * <dd>Log to \e log. if \e log is "-", then logging occurs to the * standard error stream; otherwise, \e log is the pathname of a file to * which logging will occur. If not specified, then log messages will go * to the system logging daemon. </dd> * * <dt>-m <em>mcastAddr</em></dt> * <dd>Use the shared-memory FIFO associated with the UDP * multicast address \e mcastAddr.</dd> * * <dt>-n</dt> * <dd>Log messages of level NOTICE and higher priority.</dd> * * <dt>-q <em>queue</em></dt> * <dd>Use \e queue as the pathname of the LDM product-queue. The default * is to use the default LDM pathname of the product-queue.</dd> * * <dt>-u <em>n</em></dt> * <dd>If logging is to the system logging daemon, then use facility * <b>local</b><em>n</em>. The default is to use the LDM facility. * * <dt>-v</dt> * <dd>Log messages of level INFO and higher priority. Each data-product * will generate a log message.</dd> * * <dt>-x</dt> * <dd>Log messages of level DEBUG and higher priority.</dd> * * <dt><em>path</em></dt> * <dd>Pathname of the file from which to read data. The default is to use * a shared-memory FIFO.</dd> * </dl> * * @retval 0 if successful. * @retval 1 if an error occurred. At least one error-message is logged. */ int main( const int argc, char* const argv[]) { #ifdef HAVE_GET_QUEUE_PATH const char* pqfname = getQueuePath(); #else const char* pqfname = DEFAULT_QUEUE; #endif int fd; char* prodmmap; char* memheap = NULL; size_t heapsize; size_t heapcount; unsigned char b1; int cnt, dataoff, datalen, deflen; int nscan; long IOFF; int NWSTG, GOES, PNGINIT = 0, PROD_COMPRESSED; long last_sbn_seqno = (-1); char PROD_NAME[1024]; int status; prodstore prod; sbn_struct* sbn; pdh_struct* pdh; psh_struct* psh; ccb_struct* ccb; pdb_struct* pdb; datastore* pfrag; extern int optind; extern int opterr; extern char* optarg; int ch; int logmask = LOG_MASK(LOG_ERR); const char* logfname = NULL; /* use system logging daemon */ unsigned logOptions = LOG_CONS | LOG_PID; unsigned logFacility = LOG_LDM; /* use default LDM facility */ const char* const progName = ubasename(argv[0]); MD5_CTX* md5ctxp = NULL; /*unsigned char *compr; long comprLen = 10000 * sizeof (int);*/ int pid_channel = -1; /*compr = (unsigned char *) calloc (comprLen, 1);*/ /* Initialize the logger. */ (void)setulogmask(logmask); (void)openulog(progName, logOptions, logFacility, logfname); opterr = 1; while ((ch = getopt(argc, argv, "nvxl:q:u:m:")) != EOF) { switch (ch) { case 'v': logmask |= LOG_MASK(LOG_INFO); (void)setulogmask(logmask); break; case 'x': logmask |= LOG_MASK(LOG_DEBUG); (void)setulogmask(logmask); break; case 'n': logmask |= LOG_MASK(LOG_NOTICE); (void)setulogmask(logmask); break; case 'l': if (optarg[0] == '-' && optarg[1] != 0) { nplError("logfile \"%s\" ??\n", optarg); usage(argv[0]); } /* else */ logfname = optarg; (void)openulog(progName, logOptions, logFacility, logfname); break; case 'q': pqfname = optarg; break; case 'u': { int i = atoi(optarg); if (0 <= i && 7 >= i) { static int logFacilities[] = {LOG_LOCAL0, LOG_LOCAL1, LOG_LOCAL2, LOG_LOCAL3, LOG_LOCAL4, LOG_LOCAL5, LOG_LOCAL6, LOG_LOCAL7}; logFacility = logFacilities[i]; (void)openulog(progName, logOptions, logFacility, logfname); } break; } case 'm': sscanf(optarg, "%*d.%*d.%*d.%d", &pid_channel); if ((pid_channel < 1) || (pid_channel > MAX_DVBS_PID)) { pid_channel = -1; } else { shm = shmfifo_new(); cnt = 0; while (((status = shmfifo_shm_from_key(shm, s_port[pid_channel - 1])) == -3) && (cnt < 30)) { nplInfo("Trying to get shared-memory FIFO"); cnt++; sleep(1); } if (0 != status) { nplError("Couldn't get shared-memory FIFO. " "Check associated dvbs_multicast(1) process."); shmfifo_free(shm); shm = NULL; } else { nplInfo("Got shared-memory FIFO"); } } break; case '?': usage(argv[0]); break; } } if (argc - optind < 0) usage(argv[0]); nplNotice("Starting Up %s", PACKAGE_VERSION); fd = ((argc - optind) == 0) ? fileno(stdin) : open(argv[optind], O_RDONLY, 0); if ((!shm) && (fd == -1)) { nplError("could not open input file"); exit(0); } /* * Set up signal handlers */ set_sigactions(); /* * Register atexit routine */ if (atexit(cleanup) != 0) { nplSerror("atexit"); exit(-1); } sbn = (sbn_struct*)malloc(sizeof(sbn_struct)); pdh = (pdh_struct*)malloc(sizeof(pdh_struct)); psh = (psh_struct*)malloc(sizeof(psh_struct)); ccb = (ccb_struct*)malloc(sizeof(ccb_struct)); pdb = (pdb_struct*)malloc(sizeof(pdb_struct)); prodmmap = (char*)malloc(10000); if (prodmmap == NULL) { nplError("could not allocate read buffer"); exit(-1); } md5ctxp = new_MD5_CTX(); prod.head = NULL; prod.tail = NULL; if (lpqGet(pqfname, &ldmProdQueue) != 0) { NPL_ADD1("Couldn't open LDM product-queue \"%s\"", pqfname); exit(1); } while (DONE == 0) { /* See if any stats need to be logged */ if (logstats) { logstats = 0; dump_stats(); } /* Look for first byte == 255 and a valid SBN checksum */ if ((status = bufread(fd, prodmmap, 1)) != 0) { if (-3 == status) break; abort(); } if ((b1 = (unsigned char)prodmmap[0]) != 255) { if (ulogIsVerbose()) nplInfo("trying to resync %u", b1); if (ulogIsDebug()) nplDebug("bufread loop"); continue; } if (bufread(fd, prodmmap + 1, 15) != 0) { if (ulogIsDebug()) nplDebug("couldn't read 16 bytes for sbn"); continue; } while ((status = readsbn(prodmmap, sbn)) != 0) { if (ulogIsDebug()) nplDebug("Not SBN start"); IOFF = 1; while ((IOFF < 16) && ((b1 = (unsigned char) prodmmap[IOFF]) != 255)) IOFF++; if (IOFF > 15) { break; } else { for (ch = IOFF; ch < 16; ch++) prodmmap[ch - IOFF] = prodmmap[ch]; if (bufread(fd, prodmmap + 16 - IOFF, IOFF) != 0) { if (ulogIsDebug()) nplDebug("Couldn't read bytes for SBN, resync"); break; } } } if (status != 0) { if (ulogIsDebug()) nplDebug("SBN status continue"); continue; } IOFF = 0; if (bufread(fd, prodmmap + 16, 16) != 0) { if (ulogIsDebug()) nplDebug("error reading Product Definition Header"); continue; } if (ulogIsDebug()) nplDebug("***********************************************"); if (last_sbn_seqno != -1) { if (sbn->seqno != last_sbn_seqno + 1) { nplNotice("Gap in SBN sequence number %ld to %ld [skipped %ld]", last_sbn_seqno, sbn->seqno, sbn->seqno - last_sbn_seqno - 1); if ( sbn->seqno > last_sbn_seqno ) nmissed = nmissed + (unsigned long)(sbn->seqno - last_sbn_seqno - 1); } } last_sbn_seqno = sbn->seqno; if (ulogIsVerbose()) nplInfo("SBN seqnumber %ld", sbn->seqno); if (ulogIsVerbose()) nplInfo("SBN datastream %d command %d", sbn->datastream, sbn->command); if (ulogIsDebug()) nplDebug("SBN version %d length offset %d", sbn->version, sbn->len); if (((sbn->command != 3) && (sbn->command != 5)) || (sbn->version != 1)) { nplError("Unknown sbn command/version %d PUNT", sbn->command); continue; } switch (sbn->datastream) { case 7: /* test */ case 6: /* was reserved...now nwstg2 */ case 5: NWSTG = 1; GOES = 0; break; case 1: case 2: case 4: NWSTG = 0; GOES = 1; break; default: nplError("Unknown NOAAport channel %d PUNT", sbn->datastream); continue; } /* End of SBN version low 4 bits */ if (readpdh(prodmmap + IOFF + sbn->len, pdh) == -1) { nplError("problem with pdh, PUNT"); continue; } if (pdh->len > 16) { bufread(fd, prodmmap + sbn->len + 16, pdh->len - 16); } if (ulogIsDebug()) nplDebug("Product definition header version %d pdhlen %d", pdh->version, pdh->len); if (pdh->version != 1) { nplError("Error: PDH transfer type %u, PUNT", pdh->transtype); continue; } else if (ulogIsDebug()) { nplDebug("PDH transfer type %u", pdh->transtype); } if ((pdh->transtype & 8) > 0) nplError("Product transfer flag error %u", pdh->transtype); if ((pdh->transtype & 32) > 0) nplError("Product transfer flag error %u", pdh->transtype); if ((pdh->transtype & 16) > 0) { PROD_COMPRESSED = 1; if (ulogIsDebug()) nplDebug("Product transfer flag compressed %u", pdh->transtype); } else { PROD_COMPRESSED = 0; } if (ulogIsDebug()) nplDebug("header length %ld [pshlen = %d]", pdh->len + pdh->pshlen, pdh->pshlen); if (ulogIsDebug()) nplDebug("blocks per record %ld records per block %ld\n", pdh->blocks_per_record, pdh->records_per_block); if (ulogIsDebug()) nplDebug("product seqnumber %ld block number %ld data block size " "%ld", pdh->seqno, pdh->dbno, pdh->dbsize); /* Stop here if no psh */ if ((pdh->pshlen == 0) && (pdh->transtype == 0)) { IOFF = IOFF + sbn->len + pdh->len; continue; } if (pdh->pshlen != 0) { if (bufread(fd, prodmmap + sbn->len + pdh->len, pdh->pshlen) != 0) { nplError("problem reading psh"); continue; } else { if (ulogIsDebug()) nplDebug("read psh %d", pdh->pshlen); } /* Timing block */ if (sbn->command == 5) { if (ulogIsDebug()) nplDebug("Timing block recieved %ld %ld\0", psh->olen, pdh->len); /* * Don't step on our psh of a product struct of prod in * progress. */ continue; } if (readpsh(prodmmap + IOFF + sbn->len + pdh->len, psh) == -1) { nplError("problem with readpsh"); continue; } if (psh->olen != pdh->pshlen) { nplError("ERROR in calculation of psh len %ld %ld", psh->olen, pdh->len); continue; } if (ulogIsDebug()) nplDebug("len %ld", psh->olen); if (ulogIsDebug()) nplDebug("product header flag %d, version %d", psh->hflag, psh->version); if (ulogIsDebug()) nplDebug("prodspecific data length %ld", psh->psdl); if (ulogIsDebug()) nplDebug("bytes per record %ld", psh->bytes_per_record); if (ulogIsDebug()) nplDebug("Fragments = %ld category %d ptype %d code %d", psh->frags, psh->pcat, psh->ptype, psh->pcode); if (psh->frags < 0) nplError("check psh->frags %d", psh->frags); if (psh->origrunid != 0) nplError("original runid %d", psh->origrunid); if (ulogIsDebug()) nplDebug("next header offset %ld", psh->nhoff); if (ulogIsDebug()) nplDebug("original seq number %ld", psh->seqno); if (ulogIsDebug()) nplDebug("receive time %ld", psh->rectime); if (ulogIsDebug()) nplDebug("transmit time %ld", psh->transtime); if (ulogIsDebug()) nplDebug("run ID %ld", psh->runid); if (ulogIsDebug()) nplDebug("original run id %ld", psh->origrunid); if (prod.head != NULL) { nplError("OOPS, start of new product [%ld ] with unfinished " "product %ld", pdh->seqno, prod.seqno); ds_free(); prod.head = NULL; prod.tail = NULL; if (PNGINIT != 0) { pngout_end(); PNGINIT = 0; } nplError("Product definition header version %d pdhlen %d", pdh->version, pdh->len); nplError("PDH transfer type %u", pdh->transtype); if ((pdh->transtype & 8) > 0) nplError("Product transfer flag error %u", pdh->transtype); if ((pdh->transtype & 32) > 0) nplError("Product transfer flag error %u", pdh->transtype); nplError("header length %ld [pshlen = %d]", pdh->len + pdh->pshlen, pdh->pshlen); nplError("blocks per record %ld records per block %ld", pdh->blocks_per_record, pdh->records_per_block); nplError("product seqnumber %ld block number %ld data block " "size %ld", pdh->seqno, pdh->dbno, pdh->dbsize); nplError("product header flag %d", psh->hflag); nplError("prodspecific data length %ld", psh->psdl); nplError("bytes per record %ld", psh->bytes_per_record); nplError("Fragments = %ld category %d", psh->frags, psh->pcat); if (psh->frags < 0) nplError("check psh->frags %d", psh->frags); if (psh->origrunid != 0) nplError("original runid %d", psh->origrunid); nplError("next header offset %ld", psh->nhoff); nplError("original seq number %ld", psh->seqno); nplError("receive time %ld", psh->rectime); nplError("transmit time %ld", psh->transtime); nplError("run ID %ld", psh->runid); nplError("original run id %ld", psh->origrunid); } prod.seqno = pdh->seqno; prod.nfrag = psh->frags; ds_init(prod.nfrag); /* NWSTG CCB = dataoff, WMO = dataoff + 24 */ if (bufread(fd, prodmmap + sbn->len + pdh->len + pdh->pshlen, pdh->dbsize) != 0) { nplError("problem reading datablock"); continue; } if (sbn->datastream == 4) { if (psh->pcat != 3) { GOES = 0; NWSTG = 1; } } heapcount = 0; MD5Init(md5ctxp); if (GOES == 1) { if (readpdb(prodmmap + IOFF + sbn->len + pdh->len + pdh->pshlen, psh, pdb, PROD_COMPRESSED, pdh->dbsize) == -1) { nplError("Error reading pdb, punt"); continue; } memcpy(PROD_NAME, psh->pname, sizeof(PROD_NAME)); if (ulogIsDebug()) nplDebug("Read GOES %d %d %d [%d] %d", sbn->len, pdh->len, pdh->pshlen, sbn->len + pdh->len + pdh->pshlen, pdb->len); /* Data starts at first block after pdb */ ccb->len = 0; heapsize = prodalloc(psh->frags, 5152, &memheap); } if (NWSTG == 1) { memset(psh->pname, 0, sizeof(psh->pname)); if (readccb(prodmmap + IOFF + sbn->len + pdh->len + pdh->pshlen, ccb, psh, pdh->dbsize) == -1) nplError("Error reading ccb, using default name"); if (ulogIsDebug()) nplDebug("look at ccb start %d %d", ccb->b1, ccb->len); /* cnt = 0; memset(psh->pname,0,sizeof(psh->pname)); while ((b1 = (unsigned char)prodmmap[ IOFF + sbn->len + pdh->len + pdh->pshlen + ccb->len + cnt]) >= 32) { psh->pname[cnt] = prodmmap[ IOFF + sbn->len + pdh->len + pdh->pshlen + ccb->len + cnt]; cnt++; } if(cnt > 0) */ if (ulogIsVerbose()) nplInfo("%s", psh->pname); memcpy(PROD_NAME, psh->pname, sizeof(PROD_NAME)); heapsize = prodalloc(psh->frags, 4000 + 15, &memheap); /* * We will only compute md5 checksum on the data, 11 FOS * characters at start */ /* * sprintf(memheap,"\001\015\015\012%04d\015\015\012", * ((int)pdh->seqno)%10000); */ sprintf(memheap, "\001\015\015\012%03d\040\015\015\012", ((int) pdh->seqno) % 1000); heapcount += 11; if (psh->metaoff > 0) psh->metaoff = psh->metaoff + 11; } } else { /* If a continuation record...don't let psh->pcat get missed */ if ((sbn->datastream == 4) && (psh->pcat != 3)) { GOES = 0; NWSTG = 1; } ccb->len = 0; if (ulogIsDebug()) nplDebug("continuation record"); if ((pdh->transtype & 4) > 0) { psh->frags = 0; } if (bufread(fd, prodmmap + sbn->len + pdh->len + pdh->pshlen, pdh->dbsize) != 0) { nplError("problem reading datablock (cont)"); continue; } if (prod.head == NULL) { if (ulogIsVerbose()) nplInfo("found data block before header, " "skipping sequence %d frag #%d", pdh->seqno, pdh->dbno); continue; } } /* Get the data */ dataoff = IOFF + sbn->len + pdh->len + pdh->pshlen + ccb->len; datalen = pdh->dbsize - ccb->len; if (ulogIsDebug()) nplDebug("look at datalen %d", datalen); pfrag = ds_alloc(); pfrag->seqno = pdh->seqno; pfrag->fragnum = pdh->dbno; pfrag->recsiz = datalen; pfrag->offset = heapcount; pfrag->next = NULL; /*memcpy(memheap+heapcount,prodmmap+dataoff,datalen); MD5Update(md5ctxp, (unsigned char *)(memheap+heapcount), datalen); test_deflate(compr,comprLen,(unsigned char *)(memheap+heapcount), datalen);*/ if (GOES == 1) { if (pfrag->fragnum > 0) { if ((pfrag->fragnum != prod.tail->fragnum + 1) || (pfrag->seqno != prod.seqno)) { nplError("Missing GOES fragment in sequence, " "last %d/%d this %d/%d\0", prod.tail->fragnum, prod.seqno, pfrag->fragnum, pfrag->seqno); ds_free(); prod.head = NULL; prod.tail = NULL; continue; } if ((PNGINIT != 1) && (!PROD_COMPRESSED)) { nplError("failed pnginit %d %d %s", sbn->datastream, psh->pcat, PROD_NAME); continue; } if (pdh->records_per_block < 1) { nplError("records_per_block %d blocks_per_record %d " "nx %d ny %d", pdh->records_per_block, pdh->blocks_per_record, pdb->nx, pdb->ny); nplError("source %d sector %d channel %d", pdb->source, pdb->sector, pdb->channel); nplError("nrec %d recsize %d date %02d%02d%02d %02d%02d " "%02d.%02d", pdb->nrec, pdb->recsize, pdb->year, pdb->month, pdb->day, pdb->hour, pdb->minute, pdb->second, pdb->sechunds); nplError("pshname %s", psh->pname); } if (!PROD_COMPRESSED) { for (nscan = 0; (nscan * pdb->nx) < pdh->dbsize; nscan++) { if (ulogIsDebug()) nplDebug("png write nscan %d", nscan); if (nscan >= pdh->records_per_block) { nplError("nscan exceeding records per block %d [%d " "%d %d]", pdh->records_per_block, nscan, pdb->nx, pdh->dbsize); } else { pngwrite(prodmmap + dataoff + (nscan * pdb->nx)); } } } else { memcpy(memheap + heapcount, prodmmap + dataoff, datalen); MD5Update(md5ctxp, (unsigned char *) (memheap + heapcount), datalen); heapcount += datalen; } } else { if (!PROD_COMPRESSED) { png_set_memheap(memheap, md5ctxp); png_header(prodmmap + dataoff, datalen); /* * Add 1 to number of scanlines, image ends with * f0f0f0f0... */ pngout_init(pdb->nx, pdb->ny + 1); PNGINIT = 1; } else { memcpy(memheap + heapcount, prodmmap + dataoff, datalen); MD5Update(md5ctxp, (unsigned char*)(memheap + heapcount), datalen); heapcount += datalen; } nplNotice("records_per_block %d blocks_per_record %d nx %d ny %d", pdh->records_per_block, pdh->blocks_per_record, pdb->nx, pdb->ny); nplNotice("source %d sector %d channel %d", pdb->source, pdb->sector, pdb->channel); nplNotice("nrec %d recsize %d date %02d%02d%02d %02d%02d " "%02d.%02d", pdb->nrec, pdb->recsize, pdb->year, pdb->month, pdb->day, pdb->hour, pdb->minute, pdb->second, pdb->sechunds); nplNotice("pshname %s", psh->pname); } deflen = 0; } else { /* * test_deflate(memheap+heapcount,heapsize-heapcount,(unsigned char * *)(prodmmap+dataoff),datalen,&deflen); */ /* If the product already has a FOS trailer, don't add * another....this will match what pqing(SDI) sees */ if ((prod.nfrag != 0) && (prod.tail != NULL)) { if ((pfrag->fragnum != prod.tail->fragnum + 1) || (pfrag->seqno != prod.seqno)) { nplError("Missing fragment in sequence, last %d/%d this " "%d/%d\0", prod.tail->fragnum, prod.seqno, pfrag->fragnum, pfrag->seqno); ds_free(); prod.head = NULL; prod.tail = NULL; continue; } } if ((prod.nfrag == 0) || (prod.nfrag == (pfrag->fragnum + 1))) { char testme[4]; while (datalen > 4) { memcpy(testme, prodmmap + (dataoff + datalen - 4), 4); if (memcmp(testme, FOS_TRAILER, 4) == 0) { datalen -= 4; if (ulogIsDebug()) nplDebug("removing FOS trailer from %s", PROD_NAME); } else { break; } } } if (heapcount + datalen > heapsize) { /* * this above wasn't big enough heapsize = * prodalloc(psh->frags,4000+15,&memheap); */ nplError("Error in heapsize %d product size %d [%d %d], Punt!\0", heapsize, (heapcount + datalen), heapcount, datalen); continue; } memcpy(memheap + heapcount, prodmmap + dataoff, datalen); deflen = datalen; MD5Update(md5ctxp, (unsigned char *) (memheap + heapcount), deflen); } pfrag->recsiz = deflen; /*heapcount += datalen;*/ heapcount += deflen; if (prod.head == NULL) { prod.head = pfrag; prod.tail = pfrag; } else { prod.tail->next = pfrag; prod.tail = pfrag; } if ((prod.nfrag == 0) || (prod.nfrag == (pfrag->fragnum + 1))) { if (GOES == 1) { if (PNGINIT == 1) { pngout_end(); heapcount = png_get_prodlen(); } else { if (ulogIsDebug()) nplDebug("GOES product already compressed %d", heapcount); } } if (ulogIsVerbose()) nplInfo("we should have a complete product %ld %ld/%ld %ld /heap " "%ld", prod.seqno, pfrag->seqno, prod.nfrag, pfrag->fragnum, (long) heapcount); if ((NWSTG == 1) && (heapcount > 4)) { cnt = 4; /* number of bytes to add for TRAILER */ /* * Do a DDPLUS vs HDS check for NWSTG channel only */ if (sbn->datastream == 5) { /* nwstg channel */ switch (psh->pcat) { case 1: case 7: /* Do a quick check for non-ascii text products */ if (!prod_isascii(PROD_NAME, memheap, heapcount)) psh->pcat += 100; /* call these HDS */ /* else { ** call these DDPLUS ** if (memheap[heapcount-1] == FOS_TRAILER[3]) ** ETX check ** cnt = 0; ** no need to add extra ETX pqing doesn't see it ** } */ break; } } if (cnt > 0) { memcpy(memheap + heapcount, FOS_TRAILER + 4 - cnt, cnt); MD5Update(md5ctxp, (unsigned char*)(memheap + heapcount), cnt); heapcount += cnt; } } process_prod(prod, PROD_NAME, memheap, heapcount, md5ctxp, ldmProdQueue, psh, sbn); ds_free(); prod.head = NULL; prod.tail = NULL; PNGINIT = 0; } else { if (ulogIsDebug()) nplDebug("processing record %ld [%ld %ld]", prod.seqno, prod.nfrag, pfrag->fragnum); if ((pdh->transtype & 4) > 0) { nplError("Hmmm....should call completed product %ld [%ld %ld]", prod.seqno, prod.nfrag, pfrag->fragnum); } } IOFF += (sbn->len + pdh->len + pdh->pshlen + pdh->dbsize); if (ulogIsDebug()) nplDebug("look IOFF %ld datalen %ld (deflate %ld)", IOFF, datalen, deflen); } if (fd != -1) (void)close(fd); exit(0); }