Пример #1
0
static pid_t
reap_act(int options)
{
        pid_t wpid = 0;

        if (act_pid != 0) {
            int status = 0;

#ifdef HAVE_WAITPID
            wpid = waitpid(act_pid, &status, options);
#else
            if(options == 0)
                    wpid = wait(&status);
            /* customize here for older systems, use wait3 or whatever */
#endif
            if(wpid == -1)
            {
                    if(!(errno == ECHILD && act_pid == -1))
                    {
                             /* Only complain if relevant */
                            serror("waitpid");
                    }
                    return -1;
            }
            /* else */

            if(wpid != 0) 
            {
                    /* tag_pid_entry(wpid); */

#ifdef HAVE_WAITPID
                    if(WIFSTOPPED(status))
                    {
                            unotice("child %d stopped by signal %d",
                                    wpid, WSTOPSIG(status));
                    }
                    else if(WIFSIGNALED(status))
                    {
                            unotice("child %d terminated by signal %d",
                                    wpid, WTERMSIG(status));
                            /* DEBUG */
                            switch(WTERMSIG(status)) {
                            /*
                             * If a child dumped core,
                             * shut everything down.
                             */
                            case SIGQUIT:
                            case SIGILL:
                            case SIGTRAP: /* ??? */
                            case SIGABRT:
#if defined(SIGEMT)
                            case SIGEMT: /* ??? */
#endif
                            case SIGFPE: /* ??? */
                            case SIGBUS:
                            case SIGSEGV:
#if defined(SIGSYS)
                            case SIGSYS: /* ??? */
#endif
#ifdef SIGXCPU
                            case SIGXCPU:
#endif
#ifdef SIGXFSZ
                            case SIGXFSZ:
#endif
                                    act_pid = -1;
                                    exit(1);
                                    break;
                            }
                    }
                    else if(WIFEXITED(status))
                    {
                            if(WEXITSTATUS(status) != 0)
                                    unotice("child %d exited with status %d",
                                            wpid, WEXITSTATUS(status));
                            else
                                    udebug("child %d exited with status %d",
                                            wpid, WEXITSTATUS(status));
                            act_pid = -1;
                            exit(WEXITSTATUS(status));
                    }
#endif
            }
        }

        return wpid;
}
Пример #2
0
static void alarm_handler()
{
    unotice("SIGALRM: no data, returning EOF");
    timeout_flag++;
}
Пример #3
0
/**
 * Executes a product-maker.
 *
 * This function is thread-compatible but not thread-safe.
 *
 * @retval (void*)0    The FIFO was closed.
 * @retval (void*)1    Usage failure. \c log_start() called.
 * @retval (void*)2    O/S failure. \c log_start() called.
 * @retval (void*)-1   Retransmission failure. \c log_start() called.
 */
void* pmStart(
    void* const         arg)          /**< [in/out] Pointer to the
                                        *  product-maker to be executed */
{
    ProductMaker* const productMaker = (ProductMaker*)arg;
    int                 status;
    Fifo* const         fifo = productMaker->fifo;
    unsigned char*      buf = productMaker->buf;
    sbn_struct*         sbn = &productMaker->sbn;
    pdh_struct*         pdh = &productMaker->pdh;
    psh_struct*         psh = &productMaker->psh;
    pdb_struct*         pdb = &productMaker->pdb;
    ccb_struct*         ccb = &productMaker->ccb;
    unsigned long       last_sbn_seqno;
    unsigned long       last_sbn_runno = ULONG_MAX;
    int                 PNGINIT = 0;
    char*               memheap = NULL;
    MD5_CTX*            md5ctxp = productMaker->md5ctxp;
    int                 logResync = 1;
    prodstore           prod;

#ifdef RETRANS_SUPPORT
    long cpio_addr_tmp;
    int cpio_fd_tmp;
 /*   char transfer_type[10]={0};*/
    int retrans_val,idx;
    long retrans_tbl_size;
    time_t orig_arrive_time;
    int new_key; /* shm key */
    ACQ_TABLE *acq_tbl = NULL;
    long num_prod_discards=0;
    int save_prod = 1;
    int discard_prod = 0;
    long proc_orig_prod_seqno_last_save=0;
#endif


    prod.head = NULL;
    prod.tail = NULL;

	/*** For Retranmission Purpose  ***/
#ifdef RETRANS_SUPPORT
	if (ulogIsDebug())
         udebug(" retrans_xmit_enable = %d   transfer_type = %s sbn_channel_name=%s \n",retrans_xmit_enable,transfer_type,sbn_channel_name);

       if((retrans_xmit_enable == OPTION_ENABLE) && (!strcmp(transfer_type,"MHS") || !strcmp(transfer_type,"mhs"))){
                idx = get_cpio_addr(mcastAddr);
                if( idx >= 0 && idx < NUM_CPIO_ENTRIES){
                    global_cpio_fd = cpio_tbl[idx].cpio_fd;
                    global_cpio_addr = cpio_tbl[idx].cpio_addr;
	            if (ulogIsDebug())
 	              udebug("Global cpio_addr  = 0x%x Global cpio_fd = %d \n",global_cpio_addr,global_cpio_fd);
                }else{
                    uerror("Invalid multicast address provided");
	  	    return (void*)-1;
                 }

		 retrans_tbl_size = sizeof(PROD_RETRANS_TABLE);

		/** Modified to setup retrans table on per channel basis - Sathya - 14-Mar'2013 **/

		 retrans_tbl_size += (sizeof(PROD_RETRANS_ENTRY) * GET_RETRANS_CHANNEL_ENTRIES(sbn_type));

                /****   
		 retrans_tbl_size += (sizeof(PROD_RETRANS_ENTRY) * DEFAULT_RETRANS_ENTRIES_NMC);
		 retrans_tbl_size += (sizeof(PROD_RETRANS_ENTRY) * DEFAULT_RETRANS_ENTRIES_NMC1);
		 retrans_tbl_size += (sizeof(PROD_RETRANS_ENTRY) * DEFAULT_RETRANS_ENTRIES_NMC2);
		 retrans_tbl_size += (sizeof(PROD_RETRANS_ENTRY) * DEFAULT_RETRANS_ENTRIES_NMC3);
		 retrans_tbl_size += (sizeof(PROD_RETRANS_ENTRY) * DEFAULT_RETRANS_ENTRIES_GOES_EAST);
		 retrans_tbl_size += (sizeof(PROD_RETRANS_ENTRY) * DEFAULT_RETRANS_ENTRIES_NOAAPORT_OPT);
		****/


		p_prod_retrans_table = (PROD_RETRANS_TABLE *) malloc (retrans_tbl_size);
		if(p_prod_retrans_table == NULL){
		   uerror("Unable to allocate memory for retrans table..Quitting.\n");
	  	   return (void*)-1;
		}

		if( init_retrans(&p_prod_retrans_table) < 0 ){
		  uerror("Error in initializing retrans table \n");
		  if(p_prod_retrans_table)
			free(p_prod_retrans_table);
	  	  return (void*)-1;
		}	

       GET_SHMPTR(global_acq_tbl,ACQ_TABLE,ACQ_TABLE_SHMKEY,DEBUGGETSHM);

	if (ulogIsDebug())
	  udebug("Global acquisition table = 0x%x cpio_fd = %d \n",global_acq_tbl,global_cpio_fd);
	acq_tbl = &global_acq_tbl[global_cpio_fd];

	if (ulogIsDebug())
	    udebug("Obtained acquisition table = 0x%x \n",acq_tbl);

	/* ACQ_TABLE already initialized in acq_ldm_getshm */
	/*
	if(init_acq_table(acq_tbl) < 0){
		uerror("Unable to initialize acq table\n");
		exit(-1);
	}
	*/
	
	 buff_hdr = (BUFF_HDR *) malloc(sizeof(BUFF_HDR));
	 if(init_buff_hdr(buff_hdr) < 0){
		uerror("Unalbe to initialize buffer header \n");
		if(acq_tbl)
			free(acq_tbl);
		if(p_prod_retrans_table)
		  free(p_prod_retrans_table);
	  	return (void*)-1;
	 }

	 acq_tbl->pid = getpid();
	 acq_tbl->link_id = global_cpio_fd;
	 acq_tbl->link_addr = global_cpio_addr;
	 if(ulogIsVerbose()){
 	  uinfo("Initialized acq_tbl  = 0x%x & buff_hdr = 0x%x pid = %d \n",acq_tbl,buff_hdr,acq_tbl->pid);
	  uinfo("Global link id = %d  Global link addr = %ld \n",acq_tbl->link_id,acq_tbl->link_addr);
	  uinfo("acq_tbl->read_distrib_enable = 0x%x \n",acq_tbl->read_distrib_enable);
	 }
    }
	   /*** For Retranmission Purpose  ***/
#endif

    for (;;) {
        unsigned char       b1;
        long                IOFF;
        int                 NWSTG;
        int                 GOES;
        int                 PROD_COMPRESSED;
        size_t              heapcount;
        size_t              heapsize;
        char                PROD_NAME[1024];
        int                 dataoff;
        int                 datalen;
        datastore*          pfrag;
        int                 nscan;
        int                 deflen;
        static const char*  FOS_TRAILER = "\015\015\012\003";
        int                 cnt;

        /* Look for first byte == 255  and a valid SBN checksum */
        if ((status = fifoRead(fifo, buf, 1)) != 0) {
            if (3 == status)
                status = 0;
            break;
        }
        if ((b1 = (unsigned char)buf[0]) != 255) {
            if (logResync) {
                uinfo("Trying to resync %u", b1);
                logResync = 0;
            }
            continue;
        }
        logResync = 1;

        if (fifoRead(fifo, buf + 1, 15) != 0) {
            if (ulogIsDebug())
                udebug("couldn't read 16 bytes for sbn");
            continue;
        }

        while ((status = readsbn(buf, sbn)) != 0) {
            if (ulogIsDebug())
                udebug("Not SBN start");

            IOFF = 1;

            while ((IOFF < 16) && 
                    ((b1 = (unsigned char) buf[IOFF]) != 255))
                IOFF++;

            if (IOFF > 15) {
                break;
            }
            else {
                int ch;

                for (ch = IOFF; ch < 16; ch++)
                    buf[ch - IOFF] = buf[ch];

                if (fifoRead(fifo, buf + 16 - IOFF, IOFF)
                        != 0) {
                    if (ulogIsDebug())
                        udebug("Couldn't read bytes for SBN, resync");
                    break;
                }
            }
        }

        if (status != 0) {
            if (ulogIsDebug())
                udebug("SBN status continue");
            continue;
        }

        IOFF = 0;

        if (fifoRead(fifo, buf + 16, 16) != 0) {
            if (ulogIsDebug())
                udebug("error reading Product Definition Header");
            continue;
        }

#ifdef RETRANS_SUPPORT
		/* Update acq table stats - Begin */
		if(retrans_xmit_enable == OPTION_ENABLE){
			buff_hdr->read_channel_type = sbn->datastream;
		}
		/* Update acq table stats - End */
#endif

        if (ulogIsDebug())
            udebug("***********************************************");
        if (last_sbn_runno != sbn->runno) {
            last_sbn_runno = sbn->runno;
        }
        else {
            unsigned long   delta = sbn->seqno - last_sbn_seqno;
#           define          MAX_SEQNO 0xFFFFFFFFu

            if (0 == delta || MAX_SEQNO/2 < delta) {
                uwarn("Retrograde packet number: previous=%lu, latest=%lu, "
                        "difference=%lu", last_sbn_seqno, sbn->seqno, 
                        0 == delta ? 0ul : MAX_SEQNO - delta + 1);
            }
            else {
                if (1 != delta) {
                    unsigned long   gap = delta - 1;

                    uwarn("Gap in packet sequence: %lu to %lu [skipped %lu]",
                             last_sbn_seqno, sbn->seqno, gap);

                    (void)pthread_mutex_lock(&productMaker->mutex);
                    productMaker->nmissed += gap;
                    (void)pthread_mutex_unlock(&productMaker->mutex);
                }

                (void)pthread_mutex_lock(&productMaker->mutex);
                productMaker->npackets++;
                (void)pthread_mutex_unlock(&productMaker->mutex);
            }                           /* non-retrograde packet number */
        }                               /* "last_sbn_seqno" initialized */
        last_sbn_seqno = sbn->seqno;

        if (ulogIsVerbose())
            uinfo("SBN seqnumber %ld", sbn->seqno);
        if (ulogIsVerbose())
            uinfo("SBN datastream %d command %d", sbn->datastream,
                sbn->command);
        if (ulogIsDebug())
            udebug("SBN version %d length offset %d", sbn->version, sbn->len);
        if (((sbn->command != 3) && (sbn->command != 5)) || 
                (sbn->version != 1)) {
            uerror("Unknown sbn command/version %d PUNT", sbn->command);
            continue;
        }

        switch (sbn->datastream) {
        case 5:       /* nwstg */
        case 6:       /* nwtg2 */
        case 7:       /* polarsat */
        case 8:       /* NOAA Weather Wire Service (NWWS) */
        case 9:
        case 10:
        case 11:
        case 12:      /* GOES-R */
        case 13:      /* GOES-R */
            NWSTG = 1;
            GOES = 0;
            break;
        case 1:       /* GINI GOES */
        case 2:       /* GINI GOES */
        case 4:       /* OCONUS */
            NWSTG = 0;
            GOES = 1;
            break;
        default:
            uerror("Unknown NOAAport channel %d PUNT", sbn->datastream);
            continue;
        }

        /* End of SBN version low 4 bits */

        if (readpdh(buf + IOFF + sbn->len, pdh) == -1) {
            uerror("problem with pdh, PUNT");
            continue;
        }
        if (pdh->len > 16) {
            if (fifoRead(fifo, buf + sbn->len + 16,
                        pdh->len - 16) != 0)
                continue;
        }

        if (ulogIsDebug())
            udebug("Product definition header version %d pdhlen %d",
                pdh->version, pdh->len);

        if (pdh->version != 1) {
            uerror("Error: PDH transfer type %u, PUNT", pdh->transtype);
            continue;
        }
        else if (ulogIsDebug()) {
            udebug("PDH transfer type %u", pdh->transtype);
        }

        if ((pdh->transtype & 8) > 0)
            uerror("Product transfer flag error %u", pdh->transtype);
        if ((pdh->transtype & 32) > 0)
            uerror("Product transfer flag error %u", pdh->transtype);

        if ((pdh->transtype & 16) > 0) {
            PROD_COMPRESSED = 1;

            if (ulogIsDebug())
                udebug("Product transfer flag compressed %u", pdh->transtype);
        }
        else {
            PROD_COMPRESSED = 0;
        }

        if (ulogIsDebug())
            udebug("header length %ld [pshlen = %d]", pdh->len + pdh->pshlen,
                pdh->pshlen);
        if (ulogIsDebug())
            udebug("blocks per record %ld records per block %ld\n",
                pdh->blocks_per_record, pdh->records_per_block);
        if (ulogIsDebug())
            udebug("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;
        }

#ifdef RETRANS_SUPPORT
		/** Update acquisition table statistics  **/
		if(retrans_xmit_enable == OPTION_ENABLE){
				acq_tbl->read_tot_buff_read++;
		}
#endif
        if (pdh->pshlen != 0) {
            if (fifoRead(fifo, buf + sbn->len + pdh->len,
                        pdh->pshlen) != 0) {
                uerror("problem reading psh");
                continue;
            }
            else {
                if (ulogIsDebug())
                    udebug("read psh %d", pdh->pshlen);
            }

            /* Timing block */
            if (sbn->command == 5) {
                if (ulogIsDebug())
                    udebug("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(buf + IOFF + sbn->len + pdh->len, psh) == -1) {
                uerror("problem with readpsh");
                continue;
            }
            if (psh->olen != pdh->pshlen) {
                uerror("ERROR in calculation of psh len %ld %ld", psh->olen,
                    pdh->len);
                continue;
            }
            if (ulogIsDebug())
                udebug("len %ld", psh->olen);
            if (ulogIsDebug())
                udebug("product header flag %d, version %d", psh->hflag,
                    psh->version);
            if (ulogIsDebug())
                udebug("prodspecific data length %ld", psh->psdl);
            if (ulogIsDebug())
                udebug("bytes per record %ld", psh->bytes_per_record);
            if (ulogIsDebug())
                udebug("Fragments = %ld category %d ptype %d code %d",
                    psh->frags, psh->pcat, psh->ptype, psh->pcode);
            if (psh->frags < 0)
                uerror("check psh->frags %d", psh->frags);
            if (psh->origrunid != 0)
                uerror("original runid %d", psh->origrunid);
            if (ulogIsDebug())
                udebug("next header offset %ld", psh->nhoff);
            if (ulogIsDebug())
                udebug("original seq number %ld", psh->seqno);
            if (ulogIsDebug())
                udebug("receive time %ld", psh->rectime);
            if (ulogIsDebug())
                udebug("transmit time %ld", psh->transtime);
            if (ulogIsDebug())
                udebug("run ID %ld", psh->runid);
            if (ulogIsDebug())
                udebug("original run id %ld", psh->origrunid);

#ifdef RETRANS_SUPPORT
				/* Update acq table stats - Begin */
			if(retrans_xmit_enable == OPTION_ENABLE){
			
				buff_hdr->buff_data_length = pdh->dbsize;
				if(pdh->dbno == 0) {
						/* Assume first block */
					acq_tbl->proc_base_prod_type_last = psh->ptype;
					acq_tbl->proc_base_prod_cat_last = psh->pcat;
					acq_tbl->proc_base_prod_code_last = psh->pcode;
					acq_tbl->proc_prod_NCF_rcv_time = (time_t)psh->rectime;
					acq_tbl->proc_prod_NCF_xmit_time = (time_t)psh->transtime;
					if(psh->hflag & XFR_PROD_RETRANSMIT){
					   acq_tbl->proc_orig_prod_seqno_last = psh->seqno;
					   acq_tbl->proc_orig_prod_run_id = psh->origrunid;
					   if(ulogIsDebug())
					     udebug("ORIG SEQ# = %ld	CURR SEQ#: %ld \n",acq_tbl->proc_orig_prod_seqno_last,pdh->seqno);
						}else{
						   acq_tbl->proc_orig_prod_seqno_last = 0;
						   acq_tbl->proc_orig_prod_run_id = 0;
						}
					acq_tbl->proc_prod_run_id = psh->runid;
					buff_hdr->buff_datahdr_length = psh->psdl;
					time(&acq_tbl->proc_prod_start_time);
					acq_tbl->proc_tot_prods_handled++;
				}else{
						buff_hdr->buff_datahdr_length = 0;
				 }
				buff_hdr->proc_prod_seqno= pdh->seqno;
				buff_hdr->proc_blkno = pdh->dbno;
				buff_hdr->proc_sub_code = 0;
				buff_hdr->proc_prod_flag = pdh->transtype;
					
				acq_tbl->proc_base_channel_type_last = buff_hdr->read_channel_type;
				buff_hdr->proc_prod_type = acq_tbl->proc_base_prod_type_last;
				buff_hdr->proc_prod_code = acq_tbl->proc_base_prod_code_last;
				buff_hdr->proc_prod_cat = acq_tbl->proc_base_prod_cat_last;
					
				acq_tbl->proc_prod_bytes_read = buff_hdr->buff_data_length;
						
				/* Check prod_seqno for lost products */
				if((buff_hdr->proc_prod_seqno - acq_tbl->proc_base_prod_seqno_last) != 1){
					do_prod_lost(buff_hdr,acq_tbl);
				}
				retrans_val = prod_retrans_ck(acq_tbl, buff_hdr, &orig_arrive_time);
				log_buff[0] = '\0'; 		
				if((retrans_val == PROD_DUPLICATE_DISCARD) ||
					((retrans_val == PROD_DUPLICATE_MATCH) &&
					(acq_tbl->proc_retransmit_ctl_flag & ENABLE_RETRANS_DUP_MATCH_DISCARD)) ||
					((retrans_val == PROD_DUPLICATE_NOMATCH) &&
					(acq_tbl->proc_retransmit_ctl_flag & ENABLE_RETRANS_DUP_NOMATCH_DISCARD))){
						/* Log product details and discard the product */
						strcpy(log_buff,"DISCARD");
						if(acq_tbl->proc_orig_prod_seqno_last != 0){
							strcat(log_buff, "/RETRANS");
						}
								
						log_prod_end(log_buff, acq_tbl->proc_orig_prod_seqno_last,
									buff_hdr->proc_prod_seqno,buff_hdr->proc_blkno,
									buff_hdr->proc_prod_code, acq_tbl->proc_prod_bytes_read,orig_arrive_time);
						save_prod = 0;
						acq_tbl->proc_base_prod_seqno_last = buff_hdr->proc_prod_seqno;
						/* Current prod discarded and continue with next */
						/*continue; */
					}else{
						if(retrans_val == PROD_DUPLICATE_NOMATCH){
							strcpy(log_buff,"SAVE RETRANS");
							log_prod_end(log_buff, acq_tbl->proc_orig_prod_seqno_last,
							buff_hdr->proc_prod_seqno,buff_hdr->proc_blkno,
							buff_hdr->proc_prod_code, acq_tbl->proc_prod_bytes_read,acq_tbl->proc_prod_start_time);
					  }
				   }
			  }
#endif

            if (prod.head != NULL) {
                uerror("OOPS, start of new product [%ld ] with unfinished "
                    "product %ld", pdh->seqno, prod.seqno);

#ifdef RETRANS_SUPPORT
				/* Request retrans when prod is partially received but before completion */
				/* if there is frame error and continue with different prod then, we need */
				/* to abort the old prod and clear retrans table. */
				if((retrans_xmit_enable == OPTION_ENABLE) /*&& (pdh->dbno != 0)*/){
				 acq_tbl->proc_acqtab_prodseq_errs++;
				 if(proc_orig_prod_seqno_last_save != acq_tbl->proc_orig_prod_seqno_last){
				 /* Clear retrans table for the orig prod if the previous prod is retrans */
				 /* of original prod  */
				   prod_retrans_abort_entry(acq_tbl, proc_orig_prod_seqno_last_save, RETRANS_RQST_CAUSE_RCV_ERR);
				 }
				 prod_retrans_abort_entry(acq_tbl, prod.seqno, RETRANS_RQST_CAUSE_RCV_ERR);
				 /* Update Statistics */
				 acq_tbl->proc_tot_prods_lost_errs++;
				  /* For now, generate retrans request only for non-imagery products */
				 if(!((buff_hdr->proc_prod_cat == PROD_CAT_IMAGE) && 
					   (PROD_TYPE_NESDIS_HDR_TRUE(buff_hdr->proc_prod_type)))){
				       generate_retrans_rqst(acq_tbl,prod.seqno , prod.seqno, RETRANS_RQST_CAUSE_RCV_ERR);
				 }
				   acq_tbl->proc_base_prod_seqno_last = buff_hdr->proc_prod_seqno;
				}
#endif
                ds_free();

                prod.head = NULL;
                prod.tail = NULL;

                if (PNGINIT != 0) {
                    pngout_end();
                    PNGINIT = 0;
                }

                uerror("Product definition header version %d pdhlen %d",
                        pdh->version, pdh->len);
                uerror("PDH transfer type %u", pdh->transtype);

                if ((pdh->transtype & 8) > 0)
                    uerror("Product transfer flag error %u", pdh->transtype);
                if ((pdh->transtype & 32) > 0)
                    uerror("Product transfer flag error %u", pdh->transtype);

                uerror("header length %ld [pshlen = %d]",
                    pdh->len + pdh->pshlen, pdh->pshlen);
                uerror("blocks per record %ld records per block %ld",
                    pdh->blocks_per_record, pdh->records_per_block);
                uerror("product seqnumber %ld block number %ld data block "
                    "size %ld", pdh->seqno, pdh->dbno, pdh->dbsize);
                uerror("product header flag %d", psh->hflag);
                uerror("prodspecific data length %ld", psh->psdl);
                uerror("bytes per record %ld", psh->bytes_per_record);
                uerror("Fragments = %ld category %d", psh->frags, psh->pcat);

                if (psh->frags < 0)
                    uerror("check psh->frags %d", psh->frags);
                if (psh->origrunid != 0)
                    uerror("original runid %d", psh->origrunid);

                uerror("next header offset %ld", psh->nhoff);
                uerror("original seq number %ld", psh->seqno);
                uerror("receive time %ld", psh->rectime);
                uerror("transmit time %ld", psh->transtime);
                uerror("run ID %ld", psh->runid);
                uerror("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 (fifoRead(fifo, buf + sbn->len + pdh->len + 
                        pdh->pshlen, pdh->dbsize) != 0) {
                uerror("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(buf + IOFF + sbn->len + pdh->len + 
                            pdh->pshlen,
                        psh, pdb, PROD_COMPRESSED, pdh->dbsize) == -1) {
                    uerror("Error reading pdb, punt");
                    continue;
                }

                (void)memcpy(PROD_NAME, psh->pname, sizeof(PROD_NAME));

                if (ulogIsDebug())
                    udebug("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(buf + IOFF + sbn->len + pdh->len + 
                            pdh->pshlen,
                        ccb, psh, pdh->dbsize) == -1)
                    uerror("Error reading ccb, using default name");
                if (ulogIsDebug())
                    udebug("look at ccb start %d %d", ccb->b1, ccb->len);

                if (ulogIsVerbose())
                    uinfo("%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%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())
                udebug("continuation record");

#ifdef RETRANS_SUPPORT
			if(retrans_xmit_enable == OPTION_ENABLE){
					 buff_hdr->buff_data_length = pdh->dbsize;
					 buff_hdr->buff_datahdr_length = 0;
					 buff_hdr->proc_prod_seqno= pdh->seqno;
					 buff_hdr->proc_blkno = pdh->dbno;
					 buff_hdr->proc_sub_code = 0;
					 buff_hdr->proc_prod_flag = pdh->transtype;
					 
					 acq_tbl->proc_base_channel_type_last = buff_hdr->read_channel_type;
					 buff_hdr->proc_prod_type = acq_tbl->proc_base_prod_type_last;
					 buff_hdr->proc_prod_code = acq_tbl->proc_base_prod_code_last;
					 buff_hdr->proc_prod_cat = acq_tbl->proc_base_prod_cat_last;
				 
					 acq_tbl->proc_prod_bytes_read += buff_hdr->buff_data_length;
					 
			  }
#endif

            if ((pdh->transtype & 4) > 0) {
                psh->frags = 0;
            }
            if (fifoRead(fifo, buf + sbn->len + pdh->len + 
                        pdh->pshlen, pdh->dbsize) != 0) {
                uerror("problem reading datablock (cont)");
                continue;
            }
            if (prod.head == NULL) {
                if (ulogIsVerbose())
                    uinfo("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())
            udebug("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;

        if (GOES == 1) {
            if (pfrag->fragnum > 0) {
                if ((pfrag->fragnum != prod.tail->fragnum + 1) || 
                        (pfrag->seqno != prod.seqno)) {
                    uerror("Missing GOES fragment in sequence, "
                        "last %d/%d this %d/%d\0", prod.tail->fragnum,
                        prod.seqno, pfrag->fragnum, pfrag->seqno);

#ifdef RETRANS_SUPPORT
					if(retrans_xmit_enable == OPTION_ENABLE){
					  acq_tbl->proc_acqtab_prodseq_errs++;
					  do_prod_mismatch(acq_tbl,buff_hdr);
					  acq_tbl->proc_base_prod_seqno_last = buff_hdr->proc_prod_seqno;
					}
#endif

					ds_free();

                    prod.head = NULL;
                    prod.tail = NULL;

                    continue;
                }

                if ((PNGINIT != 1) && (!PROD_COMPRESSED)) {
                    uerror("failed pnginit %d %d %s", sbn->datastream,
                            psh->pcat, PROD_NAME);
                    continue;
                }
                if (pdh->records_per_block < 1) {
                    uerror("records_per_block %d blocks_per_record %d "
                        "nx %d ny %d", pdh->records_per_block,
                        pdh->blocks_per_record, pdb->nx, pdb->ny);
                    uerror("source %d sector %d channel %d", pdb->source,
                        pdb->sector, pdb->channel);
                    uerror("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);
                    uerror("pshname %s", psh->pname);
                }
                if (!PROD_COMPRESSED) {
                    for (nscan = 0; (nscan * pdb->nx) < pdh->dbsize; nscan++) {
                        if (ulogIsDebug())
                            udebug("png write nscan %d", nscan);
                        if (nscan >= pdh->records_per_block) {
                            uerror("nscan exceeding records per block %d [%d "
                                "%d %d]", pdh->records_per_block, nscan,
                                pdb->nx, pdh->dbsize);
                        }
                        else {
                          pngwrite(buf + dataoff + (nscan * pdb->nx));
                        }
                    }
                }
                else {
                    memcpy(memheap + heapcount, buf + dataoff, datalen);
                    MD5Update(md5ctxp, (unsigned char *) (memheap + heapcount),
                        datalen);
                    heapcount += datalen;
                }
            }
            else {
                if (!PROD_COMPRESSED) {
                    png_set_memheap(memheap, md5ctxp);
                    png_header(buf + 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, buf + dataoff, datalen);
                    MD5Update(md5ctxp, (unsigned char*)(memheap + heapcount),
                        datalen);
                    heapcount += datalen;
                }
                unotice("records_per_block %d blocks_per_record %d nx %d ny %d",
                    pdh->records_per_block, pdh->blocks_per_record, pdb->nx,
                    pdb->ny);
                unotice("source %d sector %d channel %d", pdb->source,
                    pdb->sector, pdb->channel);
                unotice("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);
                unotice("pshname %s", psh->pname);
            }
            deflen = 0;
#ifdef RETRANS_SUPPORT
			if(retrans_xmit_enable == OPTION_ENABLE){
			   if(buff_hdr->proc_blkno != 0){
		          /*acq_tbl->proc_prod_bytes_read += buff_hdr->buff_data_length;*/
				  acq_tbl->proc_prod_bytes_read += datalen;
	           }
            }
#endif
       	}
        else {
            /* 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)) {
                    uerror("Missing fragment in sequence, last %d/%d this "
                        "%d/%d\0", prod.tail->fragnum, prod.seqno,
                        pfrag->fragnum, pfrag->seqno);

#ifdef RETRANS_SUPPORT
                                      if(retrans_xmit_enable == OPTION_ENABLE){
                                         acq_tbl->proc_acqtab_prodseq_errs++;
                                         if(ulogIsDebug())
                                            udebug("do_prod_mismatch() proc_base_prod_seqno_last = %d \n",
					                                    acq_tbl->proc_base_prod_seqno_last);
                                            do_prod_mismatch(acq_tbl,buff_hdr);
                                            acq_tbl->proc_base_prod_seqno_last = buff_hdr->proc_prod_seqno;
                                      }
#endif

                    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, buf + (dataoff + datalen - 4), 4);

                    if (memcmp(testme, FOS_TRAILER, 4) == 0) {
                        datalen -= 4;

                        if (ulogIsDebug())
                            udebug("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);
                 */
                uerror("Error in heapsize %d product size %d [%d %d], Punt!\0",
                    heapsize, (heapcount + datalen), heapcount, datalen);
				
#ifdef RETRANS_SUPPORT
				if(retrans_xmit_enable == OPTION_ENABLE){ 	
			      /* Update Statistics */
					acq_tbl->proc_tot_prods_lost_errs++;
					/*  Abort entry and request retransmission */
					prod_retrans_abort_entry(acq_tbl, prod.seqno, RETRANS_RQST_CAUSE_RCV_ERR);
					generate_retrans_rqst(acq_tbl, prod.seqno, prod.seqno, RETRANS_RQST_CAUSE_RCV_ERR);
					if(acq_tbl->proc_orig_prod_seqno_last != 0){
						strcpy(log_buff, "RETRANS");
					}
					log_prod_end(log_buff, acq_tbl->proc_orig_prod_seqno_last,
								 buff_hdr->proc_prod_seqno,buff_hdr->proc_blkno,
								 buff_hdr->proc_prod_code, acq_tbl->proc_prod_bytes_read,
								 acq_tbl->proc_prod_start_time);

		      		acq_tbl->proc_base_prod_seqno_last = buff_hdr->proc_prod_seqno;
	      		}
#endif

                continue;
            }

            memcpy(memheap + heapcount, buf + dataoff, datalen);

            deflen = datalen;

            MD5Update(md5ctxp, (unsigned char *) (memheap + heapcount),
                deflen);

#ifdef RETRANS_SUPPORT
			if(retrans_xmit_enable == OPTION_ENABLE){
	  		  if(buff_hdr->proc_blkno != 0){
				/*acq_tbl->proc_prod_bytes_read += buff_hdr->buff_data_length;*/
				acq_tbl->proc_prod_bytes_read += datalen;
			  }
	  		}
#endif
        }

        pfrag->recsiz = deflen;
        heapcount += deflen;

        if (prod.head == NULL) {
            prod.head = pfrag;
            prod.tail = pfrag;
        }
        else {
            prod.tail->next = pfrag;
            prod.tail = pfrag;
        }
 
#ifdef RETRANS_SUPPORT
		 if(((prod.nfrag == 0) || (prod.nfrag >= (pfrag->fragnum +1))) && (save_prod == 0)){
		   if(ulogIsVerbose())
			  uinfo("Do not save prod [seqno=%ld] as its retrans dup fragnum/total fragments =[%d of %d] save_prod=[%d] \n",
			   prod.seqno,pfrag->fragnum,prod.nfrag,save_prod);
		   ds_free ();
		   prod.head = NULL;
		   prod.tail = NULL;
		   PNGINIT = 0;
		}else{
#endif
          if ((prod.nfrag == 0) || (prod.nfrag == (pfrag->fragnum + 1))) {
            if (GOES == 1) {
                if (PNGINIT == 1) {
                    pngout_end();
                    heapcount = png_get_prodlen();
                }
                else {
                    if (ulogIsDebug())
                        udebug("GOES product already compressed %d", heapcount);
                }
            }
            if (ulogIsVerbose())
              uinfo("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 */
                      break;
                    }
                }

                if (cnt > 0) {
                    memcpy(memheap + heapcount, FOS_TRAILER + 4 - cnt, cnt);
                    MD5Update(md5ctxp, (unsigned char*)(memheap + heapcount),
                        cnt);
                    heapcount += cnt;
                }
            }

#ifdef RETRANS_SUPPORT
			if((retrans_xmit_enable == OPTION_ENABLE) && (acq_tbl->read_distrib_enable & READ_CTL_DISCARD)){
						num_prod_discards++;
						/* Set discard_prod to 1; Otherwise already stored prod may be requested for retransmit */
						discard_prod=1;
						if(ulogIsVerbose())
						  uinfo("No of products discarded = %ld prod.seqno=%ld \n ",num_prod_discards,prod.seqno);
						prod_retrans_abort_entry(acq_tbl, prod.seqno, RETRANS_RQST_CAUSE_RCV_ERR);
						acq_tbl->proc_base_prod_seqno_last = buff_hdr->proc_prod_seqno -1 ;
						ds_free ();
						prod.head = NULL;
						prod.tail = NULL;
						PNGINIT = 0;
			}else{
				/* Do not insert prod into queue if its a duplicate product */
				if(save_prod != 0)
#endif
                                   process_prod(prod, PROD_NAME, memheap, heapcount,
                                                md5ctxp, productMaker->ldmProdQueue, psh, sbn);
#ifdef RETRANS_SUPPORT
				/* Update acq table with last processed seqno -Begin */
				if(retrans_xmit_enable == OPTION_ENABLE){
					acq_tbl->proc_base_prod_seqno_last = buff_hdr->proc_prod_seqno;
					uinfo(" prod with seqno processed = %ld\n",acq_tbl->proc_base_prod_seqno_last);
				}
				/* Update acq table with last processed seqno -End */
#endif

            ds_free();

            prod.head = NULL;
            prod.tail = NULL;
            PNGINIT = 0;

            (void)pthread_mutex_lock(&productMaker->mutex);
            productMaker->nprods++;
            (void)pthread_mutex_unlock(&productMaker->mutex);
#ifdef RETRANS_SUPPORT
        }
#endif
       }
        else {
            if (ulogIsDebug())
                udebug("processing record %ld [%ld %ld]", prod.seqno,
                    prod.nfrag, pfrag->fragnum);
            if ((pdh->transtype & 4) > 0) {
                uerror("Hmmm....should call completed product %ld [%ld %ld]",
                    prod.seqno, prod.nfrag, pfrag->fragnum);
            }
        }

#ifdef RETRANS_SUPPORT
	   if(retrans_xmit_enable == OPTION_ENABLE){
	     if(!(acq_tbl->read_distrib_enable & READ_CTL_DISCARD))
	   	  if(!discard_prod){
		    acq_tbl->proc_base_prod_seqno_last = buff_hdr->proc_prod_seqno;
		    discard_prod = 0;
	      }
	   }  
#endif
		
#ifdef RETRANS_SUPPORT
	}

        save_prod = 1;
#endif
        IOFF += (sbn->len + pdh->len + pdh->pshlen + pdh->dbsize);

        if (ulogIsDebug())
            udebug("look IOFF %ld datalen %ld (deflate %ld)", IOFF, datalen,
                deflen);
#ifdef RETRANS_SUPPORT
		if(retrans_xmit_enable == OPTION_ENABLE){
		  total_prods_retrans_rcvd = acq_tbl->proc_tot_prods_retrans_rcvd;     /* prods retrans rcvd by proc */
		  total_prods_retrans_rcvd_lost = acq_tbl->proc_tot_prods_retrans_rcvd_lost; /* prods retrans rcvd lost */
		  total_prods_retrans_rcvd_notlost = acq_tbl->proc_tot_prods_retrans_rcvd_notlost; /* prods rcvd not lost */
		  total_prods_retrans_rqstd = acq_tbl->proc_tot_prods_retrans_rqstd;    /* prods retrans requested */
		  total_prods_handled = acq_tbl->proc_tot_prods_handled;    /* prods retrans requested */
		  total_prods_lost_err = acq_tbl->proc_tot_prods_lost_errs;    /* prods retrans requested */
		  total_frame_cnt = acq_tbl->read_tot_buff_read;
		  total_frame_err = acq_tbl->read_frame_tot_lost_errs;
		  proc_orig_prod_seqno_last_save = acq_tbl->proc_orig_prod_seqno_last;
        }
#endif
    }

    if (NULL != memheap)
        free(memheap);

    productMaker->status = status;

    return NULL;
}
Пример #4
0
Файл: ldmd.c Проект: dgaer/LDM
/*
 * Create a TCP socket, bind it to a port, call 'listen' (we are a
 * server), and inform the portmap (rpcbind) service.  Does _not_ create
 * an RPC SVCXPRT or do the xprt_register() or svc_fds() stuff.
 *
 * Arguments:
 *      sockp           Pointer to socket (file) descriptor.  Set on and only on
 *                      success.
 *      localIpAddr     The IP address, in network byte order, of the 
 *                      local interface to use.  May be htonl(INADDR_ANY).
 *      localPort       The number of the local port on which the LDM server
 *                      should listen.
 * Returns:
 *      0               Success.
 *      EACCES          The process doesn't have appropriate privileges.
 *      EADDRINUSE      The local address is already in use.
 *      EADDRNOTAVAIL   The specified address is not available from the local
 *                      machine.
 *      EAFNOSUPPORT    The system doesn't support IP.
 *      EMFILE          No more file descriptors are available for this process.
 *      ENFILE          No more file descriptors are available for the system.
 *      ENOBUFS         Insufficient resources were available in the system.
 *      ENOMEM          Insufficient memory was available.
 *      ENOSR           There were insufficient STREAMS resources available.
 *      EOPNOTSUPP      The socket protocol does not support listen().
 *      EPROTONOSUPPORT The system doesn't support TCP.
 */
static int create_ldm_tcp_svc(
        int* sockp,
        in_addr_t localIpAddr,
        unsigned localPort)
{
    int error = 0; /* success */
    int sock;

    /*
     * Get a TCP socket.
     */
    udebug("create_ldm_tcp_svc(): Getting TCP socket");
    sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
    if (sock < 0) {
        error = errno;

        serror("Couldn't get socket for server");
    }
    else {
        unsigned short port = (unsigned short) localPort;
        struct sockaddr_in addr;
        socklen_t len = sizeof(addr);

        /*
         * Eliminate problem with EADDRINUSE for reserved socket.
         * We get this if an upstream data source hasn't tried to
         * write on the other end and we are in FIN_WAIT_2
         */
        udebug("create_ldm_tcp_svc(): Eliminating EADDRINUSE problem.");
        {
            int on = 1;

            (void) setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (char *) &on,
                    sizeof(on));
        }

        (void) memset(&addr, 0, len);
        addr.sin_family = AF_INET;
        addr.sin_addr.s_addr = localIpAddr;
        addr.sin_port = (short) htons((short) port);

        /*
         * If privilege available, set it so we can bind to the port for LDM
         * services.  Also needed for the pmap_set() call.
         */
        udebug("create_ldm_tcp_svc(): Getting root privs");
        rootpriv();

        udebug("create_ldm_tcp_svc(): Binding socket");
        if (bind(sock, (struct sockaddr *) &addr, len) < 0) {
            error = errno;

            serror("Couldn't obtain local address %s:%u for server",
                    inet_ntoa(addr.sin_addr), (unsigned) port);

            if (error == EACCES) {
                error = 0;
                addr.sin_port = 0; /* let system assign port */

                if (bind(sock, (struct sockaddr *) &addr, len) < 0) {
                    error = errno;

                    serror("Couldn't obtain local address %s:* for server",
                            inet_ntoa(addr.sin_addr));
                }
            } /* requested port is reserved */
        } /* couldn't bind to requested port */

        if (!error) {
            /*
             * Get the local address associated with the bound socket.
             */
            udebug("create_ldm_tcp_svc(): Calling getsockname()");
            if (getsockname(sock, (struct sockaddr *) &addr, &len) < 0) {
                error = errno;

                serror("Couldn't get local address of server's socket");
            }
            else {
                port = (short) ntohs((short) addr.sin_port);

                unotice("Using local address %s:%u", inet_ntoa(addr.sin_addr),
                        (unsigned) port);

                udebug("create_ldm_tcp_svc(): Calling listen()");
                if (listen(sock, 32) != 0) {
                    error = errno;

                    serror("Couldn't listen() on server's socket");
                }
                else {
                    /*
                     * Register with the portmapper if it's running.  The
                     * check to see if it's running is made because on a
                     * FreeBSD 4.7-STABLE system, a pmap_set() call takes
                     * one minute even if the portmapper isn't running.
                     */
                    udebug("create_ldm_tcp_svc(): Checking portmapper");
                    if (local_portmapper_running()) {
                        udebug("create_ldm_tcp_svc(): Registering");

                        if (pmap_set(LDMPROG, 6, IPPROTO_TCP, port) == 0) {
                            uwarn("Can't register TCP service %lu on "
                                    "port %u", LDMPROG, (unsigned) port);
                            uwarn("Downstream LDMs won't be able to "
                                    "connect via the RPC portmapper daemon "
                                    "(rpcbind(8), portmap(8), etc.)");
                        }
                        else {
                            portIsMapped = 1;

                            (void) pmap_set(LDMPROG, 5, IPPROTO_TCP, port);
                        }
                    } /* a local portmapper is running */

                    /*
                     * Done with the need for privilege.
                     */
                    udebug("create_ldm_tcp_svc(): Releasing root privs");
                    unpriv();

                    *sockp = sock;
                } /* listen() success */
            } /* getsockname() success */
        } /* "sock" is bound to local address */

        if (error)
            (void) close(sock);
    } /* "sock" is open */

    return error;
}
Пример #5
0
int
main(int ac, char *av[])
{
        int logfd;
        int width;
        int ready;
        unsigned long idle;
        fd_set readfds;
        fd_set exceptfds;
        struct timeval timeo;
        const char* const progname = ubasename(av[0]);
        unsigned logopts = LOG_CONS|LOG_PID;
        int logmask = LOG_UPTO(LOG_NOTICE);
        unsigned long maxProductSize = DEFAULT_MAX_PRODUCT_SIZE;

        /*
         * Setup default logging before anything else.
         */
        logfd = openulog(progname, logopts, LOG_LDM, logpath);
        (void) setulogmask(logmask);

        feedtype = whatami(av[0]);

        {
            extern int optind;
            extern int opterr;
            extern char *optarg;
            int ch;

            opterr = 0; /* stops getopt() from printing to stderr */
            usePil = 1;
            useNex = 1;
            pqpath = getQueuePath();

            while ((ch = getopt(ac, av, ":vxcni5Nl:b:p:P:T:q:r:f:s:")) != 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 'c':
                            chkflag = CHK_CHECK;
                            break;
                    case 'n':
                            chkflag = CHK_DONT;
                            break;
                    case 'i':
                            usePil = 0;
                            break;
                    case 'N':
                            useNex = 0;
                            break;
                    case '5':
                            skipLeadingCtlString = 0;
                            break;
                    case 'l': {
                            logpath = optarg;
                            if (strcmp(logpath, "-") == 0) {
                                logopts = LOG_NOTIME;
                            }
                            else {
                                logopts = LOG_CONS | LOG_PID;
                                (void) fclose(stderr);
                            }
                            logfd = openulog(progname, logopts, LOG_LDM, logpath);
                            break;
                    }
                    case 'b':
                            baud = optarg;
                            break;
                    case 'p':
                            parity = optarg;
                            break;
    #if NET
                    case 'P':
                            *((int *)&server_port) = atoi(optarg); /* cast away const */
                            if(server_port <= 0 || server_port > 65536)
                            {
                                    LOG_ADD1("Invalid server port: \"%s\"", optarg);
                                    log_log(LOG_ERR);
                                    usage(progname);
                            }
                            break;
                    case 'T':
                            reset_secs = atoi(optarg);
                            if(reset_secs < 0)
                            {
                                    LOG_ADD1("Invalid timeout: \"%s\"", optarg);
                                    usage(progname);
                            }
                            break;
    #endif /* NET */
                    case 's': {
                            unsigned long size;
                            int           nbytes;

                            if (sscanf(optarg, "%lu %n", &size, &nbytes) != 1 ||
                                    optarg[nbytes] != 0 || 1 > size) {
                                LOG_ADD1("Invalid maximum data-product size: \"%s\"",
                                        optarg);
                                log_log(LOG_ERR);
                                usage(progname);
                            }

                            maxProductSize = size;
                            break;
                    }
                    case 'q':
                            pqpath = optarg;
                            break;
                    case 'r':
                            rawfname = optarg;
                            break;
                    case 'f':
                            {
                                    feedtypet type;
                                    type = atofeedtypet(optarg);
                                    if(type != NONE)
                                    {
                                            feedtype = type;
                                            if(!parity && !baud)
                                                    setFeedDefaults(type);
                                    }
                            }
                            break;
                    case '?': {
                            LOG_ADD1("Unknown option: \"%c\"", optopt);
                            usage(progname);
                            break;
                    }
                    case ':':
                    /*FALLTHROUGH*/
                    default:
                            LOG_ADD1("Missing argument for option: \"%c\"", optopt);
                            usage(progname);
                            break;
                    }

            /* last arg, feedfname, is required */
            if(ac - optind != 1) {
                    LOG_ADD1("Wrong number of operands: %d", ac - optind);
                    usage(progname);
            }
            (void)strncat(feedfname, av[optind], sizeof(feedfname)-6);
        }

        unotice("Starting Up");
        udebug(PACKAGE_VERSION);

        if(logpath == NULL || !(*logpath == '-' && logpath[1] == 0))
        {
                if (logfd < 0) {
                    uerror("logfd < 0");
                    return 1;
                }
                setbuf(fdopen(logfd, "a"), NULL);
        }       

        /*
         * register exit handler
         */
        if(atexit(cleanup) != 0)
        {
                serror("atexit");
                return 1;
        }

        /*
         * set up signal handlers
         */
        set_sigactions();

        /*
         * open the product queue, unless we were invoked as "feedtest"
         */
        if(strcmp(progname, "feedtest") != 0)
        {
                if((ready = pq_open(pqpath, PQ_DEFAULT, &pq)))
                {
                        if (PQ_CORRUPT == ready) {
                            uerror("The product-queue \"%s\" is inconsistent\n",
                                    pqpath);
                        }
                        else {
                            uerror("pq_open: \"%s\" failed: %s",
                                    pqpath, strerror(ready));
                        }
                        return 1;
                }
        }

        /*
         * who am i, anyway
         */
        (void) strncpy(myname, ghostname(), sizeof(myname));
        myname[sizeof(myname)-1] = 0;

        /*
         * open the feed
         */
        if(!(*feedfname == '-' && feedfname[1] == 0) && logfd != 0)
                (void) close(0);

        if(open_feed(feedfname, &ifd, maxProductSize) != ENOERR)
                return 1;

        if(usePil == 1)
           {
           if ((feedtype & DDS)||(feedtype & PPS)||(feedtype & IDS)||
                (feedtype & HRS))
              {
              usePil = 1;
              uinfo("Creating AFOS-like pil tags\0");
              }
           else
              {
              usePil = 0;
              }
           }

        if (feedtype & HDS)
        {
                if(chkflag == CHK_CHECK
                                || (isatty(ifd) && chkflag != CHK_DONT))
                        setTheScanner(scan_wmo_binary_crc);
                else
                        setTheScanner(scan_wmo_binary);
        }
        else if (feedtype == ( DDPLUS | IDS ) ) 
        { 
                /* this is the combined NOAAPORT fos-alike. We know these have the
                   4 byte start and end sequences. Using the binary scanner
                   ensures that we don't stop on an arbitray embedded CTRL-C */
                unotice("Note: Using the wmo_binary scanner for SDI ingest\0");
                setTheScanner (scan_wmo_binary); 
        }
        else if (feedtype & (NMC2 | NMC3))
        {
                setTheScanner(scan_wmo_binary);
        }
        else if (feedtype == AFOS)
        {
                prod_stats = afos_stats;
                setTheScanner(scan_afos);
        }
        else if (feedtype == FAA604)
        {
                prod_stats = faa604_stats;
                if(chkflag == CHK_CHECK
                        || (isatty(ifd)
                                 && chkflag != CHK_DONT
                                 && parity != NULL
                                 && *parity != 'n')
                        )
                {
                        setTheScanner(scan_faa604_parity);
                }
                else
                {
                        setTheScanner(scan_faa604);
                }
        }
        else
        {
                if(chkflag == CHK_CHECK
                        || (isatty(ifd)
                                 && chkflag != CHK_DONT
                                 && parity != NULL
                                 && *parity != 'n')
                        )
                {
                        setTheScanner(scan_wmo_parity);
                }
                else
                {
                        setTheScanner(scan_wmo);
                }
        }

        /*
         * Allocate an MD5 context
         */
        md5ctxp = new_MD5_CTX();
        if(md5ctxp == NULL)
        {
                serror("new_md5_CTX failed");
                return 1;
        }


        /*
         * Main Loop
         */
        idle = 0;
        while(exitIfDone(0))
        {
#if NET
if (INPUT_IS_SOCKET)
{
                if (port_error)
                {
                        /*
                         * lost connection => close
                         */
                        if (ifd >= 0)
                        {
                                if(feed_close)
                                        (*feed_close)(ifd);
                                ifd = -1;
                        }
                        port_error = 0;
                        sleep (2);      /* allow things to settle down */
                        continue;
                }
}
#endif
                if(stats_req)
                {
                        unotice("Statistics Request"); 
                        if(pq != NULL)
                        {
                                off_t highwater = 0;
                                size_t maxregions = 0;
                                (void) pq_highwater(pq, &highwater,
                                         &maxregions);
                                unotice("  Queue usage (bytes):%8ld",
                                                        (long)highwater);
                                unotice("           (nregions):%8ld",
                                                        (long)maxregions);
                        }
                        unotice("       Idle: %8lu seconds", idle);
#if NET
if (INPUT_IS_SOCKET)
{
                        unotice("    Timeout: %8d", reset_secs);
}
#endif
                        unotice("%21s: %s", "Status",
                                (ifd < 0) ?
                                "Not connected or input not open." :
                                "Connected.");
                        (*prod_stats)();
                        (*feed_stats)();
                        stats_req = 0;
                }
#if NET
if (INPUT_IS_SOCKET)
{
                if (ifd < 0)
                {
                        /* Attempt reconnect */
                        static int retries = 0;
                        if (retries > MAX_RETRIES)
                        {
                                uerror ("maximum retry attempts %d, aborting",
                                        MAX_RETRIES);
                                done = !0;
                                continue;
                        }
                        /* Try to reopen on tcp read errors */
                        unotice("Trying to re-open connection on port %d", 
                                server_port);
                        ++retries;
                        if(open_feed(feedfname, &ifd, maxProductSize) != ENOERR)
                        {
                                unotice ("sleeping %d seconds before retry %d",
                                         retries * RETRY_DELAY, retries+1);
                                sleep (retries * RETRY_DELAY);
                                continue;
                        }
                        retries = 0;
                }
}
#endif /* NET */
                timeo.tv_sec = 3;
                timeo.tv_usec = 0;
                FD_ZERO(&readfds);
                FD_ZERO(&exceptfds);
                FD_SET(ifd, &readfds);
                FD_SET(ifd, &exceptfds);
                width =  ifd + 1;
                ready = select(width, &readfds, 0, &exceptfds, &timeo);
                if(ready < 0 )
                {
                        /* handle EINTR as a special case */
                        if(errno == EINTR)
                        {
                                errno = 0;
                                continue;
                        }
                        serror("select");
                        return 1;
                }
                /* else */
#if 0
                if (FD_ISSET(ifd, &exceptfds))
                {
                        uerror("Exception on input fd %d, select returned %d",
                               ifd, ready);
                }
#endif
                if(ready > 0)
                {
                        /* do some work */
                        if(FD_ISSET(ifd, &readfds) || 
                           FD_ISSET(ifd, &exceptfds))
                        {
                                idle = 0;
                                if(feedTheXbuf(ifd) != ENOERR)
                                {
#if NET
if (INPUT_IS_SOCKET)
{
                                        port_error = !0;
                                        continue;
}                                       /* else */
#endif /* NET */
                                        done = !0;
                                }
                                FD_CLR(ifd, &readfds);
                                FD_CLR(ifd, &exceptfds);
                        }
                        else
                        {
                                uerror("select returned %d but ifd not set",
                                        ready);
                                idle += timeo.tv_sec;
                        }
                }
                else    /* ready == 0 */
                {
                        idle += timeo.tv_sec;
#if NET
if (INPUT_IS_SOCKET)
{
                        /* VOODOO
                         * This is necessary to stimulate
                         * 'Connection reset by peer'
                         * when the Portmaster goes down and comes
                         * back up.
                         */
                        static char zed[1] = {0};
                        if(write(ifd, zed, sizeof(zed)) < 0)
                        {
                                port_error = !0;
                                continue;
                        }

}
#endif
                }
#if NET
if (INPUT_IS_SOCKET)
{
                if ((reset_secs > 0) && (idle >= reset_secs))
                {
                        unotice("Idle for %ld seconds, reconnecting",
                                idle);
                        /* force reconnect */
                        port_error = !0;
                        idle = 0;
                        continue;
                }
}
#endif /* NET */
                (void) scanTheXbuf();
        }

        return 0;
}
Пример #6
0
static pid_t reap(
        pid_t pid,
        int options)
{
    pid_t wpid = 0;
    int status = 0;

#ifdef HAVE_WAITPID
    wpid = waitpid(pid, &status, options);
#else
    if(options == 0) {
        wpid = wait(&status);
    }
    /* customize here for older systems, use wait3 or whatever */
#endif
    if (wpid == -1) {
        if (!(errno == ECHILD && pid == -1)) /* Only complain when relevant */
            serror("waitpid");
        return -1;
    }
    /* else */

    if (wpid != 0) {
        char command[512];

#if !defined(WIFSIGNALED) && !defined(WIFEXITED)
#error "Can't decode wait status"
#endif

#if defined(WIFSTOPPED)
        if (WIFSTOPPED(status)) {
            int n = exec_getCommandLine(wpid, command, sizeof(command));

            if (n == -1) {
                log_add("Couldn't get command-line of EXEC process "
                        "%ld", wpid);
                log_log(LOG_ERR);
            }

            unotice(
                    n <= 0 ?
                            "child %d stopped by signal %d" :
                            "child %d stopped by signal %d: %*s", wpid,
                    WSTOPSIG(status), n, command);
        }
        else
#endif /*WIFSTOPPED*/
#if defined(WIFSIGNALED)
        if (WIFSIGNALED(status)) {
            int n = exec_getCommandLine(wpid, command, sizeof(command));

            cps_remove(wpid); /* upstream LDM processes */

            exec_free(wpid); /* EXEC processes */

            if (n == -1) {
                log_add("Couldn't get command-line of EXEC process "
                        "%ld", wpid);
                log_log(LOG_ERR);
            }

            unotice(
                    n <= 0 ?
                            "child %d terminated by signal %d" :
                            "child %d terminated by signal %d: %*s", wpid,
                    WTERMSIG(status), n, command);

            /* DEBUG */
            switch (WTERMSIG(status)) {
            /*
             * If a child dumped core,
             * shut everything down.
             */
            case SIGQUIT:
            case SIGILL:
            case SIGTRAP: /* ??? */
            case SIGABRT:
#if defined(SIGEMT)
                case SIGEMT: /* ??? */
#endif
            case SIGFPE: /* ??? */
            case SIGBUS:
            case SIGSEGV:
#if defined(SIGSYS)
            case SIGSYS: /* ??? */
#endif
#ifdef SIGXCPU
            case SIGXCPU:
#endif
#ifdef SIGXFSZ
            case SIGXFSZ:
#endif
                unotice("Killing (SIGTERM) process group");
                (void) kill(0, SIGTERM);
                break;
            }
        }
        else
#endif /*WIFSIGNALED*/
#if defined(WIFEXITED)
        if (WIFEXITED(status)) {
            int exitStatus = WEXITSTATUS(status);
            int n = exec_getCommandLine(wpid, command, sizeof(command));

            cps_remove(wpid); /* upstream LDM processes */
            exec_free(wpid); /* EXEC processes */

            if (n == -1) {
                log_add("Couldn't get command-line of EXEC process "
                        "%ld", wpid);
                log_log(LOG_ERR);
            }

            log_start(
                    n <= 0 ?
                            "child %d exited with status %d" :
                            "child %d exited with status %d: %*s", wpid,
                    exitStatus, n, command);
            log_log(exitStatus ? LOG_NOTICE : LOG_INFO);
        }
#endif /*WIFEXITED*/

    }

    return wpid;
}
Пример #7
0
hiya_reply_t*
hiya_6_svc(
        prod_class_t *offered,
        struct svc_req *rqstp)
{
    const char* const pqfname = getQueuePath();
    static hiya_reply_t reply;
    SVCXPRT * const xprt = rqstp->rq_xprt;
    struct sockaddr_in *upAddr = (struct sockaddr_in*) svc_getcaller(xprt);
    const char *upName = hostbyaddr(upAddr);
    int error;
    int isPrimary;
    unsigned int maxHereis;
    static prod_class_t *accept;

    /*
     * Open the product-queue for writing.  It will be closed by cleanup()
     * during process termination.
     */
    if (pq) {
        (void) pq_close(pq);
        pq = NULL;
    }
    error = pq_open(pqfname, PQ_DEFAULT, &pq);
    if (error) {
        err_log_and_free(ERR_NEW2(error, NULL,
                "Couldn't open product-queue \"%s\" for writing: %s",
                pqfname,
                PQ_CORRUPT == error
                ? "The product-queue is inconsistent"
                : strerror(error)), ERR_FAILURE);
        svcerr_systemerr(xprt);
        svc_destroy(xprt);
        exit(error);
    }

    /* else */

    error = down6_init(upName, upAddr, pqfname, pq);
    if (error) {
        uerror("Couldn't initialize downstream LDM");
        svcerr_systemerr(xprt);
        svc_destroy(xprt);
        exit(error);
    }
    else {
        uinfo("Downstream LDM initialized");
    }

    /*
     * The previous "accept" is freed here -- rather than freeing the
     * soon-to-be-allocated "accept" at the end of its block -- because it can
     * be used in the reply.
     */
    if (accept) {
        free_prod_class(accept); /* NULL safe */
        accept = NULL;
    }

    error = lcf_reduceToAcceptable(upName, inet_ntoa(upAddr->sin_addr), offered,
            &accept, &isPrimary);

    maxHereis = isPrimary ? UINT_MAX : 0;

    if (error) {
        serror("Couldn't validate HIYA");
        svcerr_systemerr(xprt);
        svc_destroy(xprt);
        exit(error);
    }
    else {
        if (ulogIsDebug())
            udebug("intersection: %s", s_prod_class(NULL, 0, accept));

        if (accept->psa.psa_len == 0) {
            uwarn("Empty intersection of HIYA offer from %s (%s) and ACCEPT "
                    "entries", upName, s_prod_class(NULL, 0, offered));
            svcerr_weakauth(xprt);
            svc_destroy(xprt);
            exit(0);
        }
        else {
            error = down6_set_prod_class(accept);

            if (error) {
                if (DOWN6_SYSTEM_ERROR == error) {
                    serror("Couldn't set product class: %s",
                            s_prod_class(NULL, 0, accept));
                }
                else {
                    uerror("Couldn't set product class: %s",
                            s_prod_class(NULL, 0, accept));
                }

                svcerr_systemerr(xprt);
                svc_destroy(xprt);
                exit(EXIT_FAILURE);
            }

            /* else */

            if (clss_eq(offered, accept)) {
                unotice("hiya6: %s", s_prod_class(NULL, 0, offered));

                reply.code = OK;
                reply.hiya_reply_t_u.max_hereis = maxHereis;
            }
            else {
                if (ulogIsVerbose()) {
                    char off[512];
                    char acc[512];

                    (void) s_prod_class(off, sizeof(off), offered), (void) s_prod_class(
                            acc, sizeof(acc), accept);

                    uinfo("hiya6: RECLASS: %s -> %s", off, acc);
                }

                reply.code = RECLASS;
                reply.hiya_reply_t_u.feedPar.prod_class = accept;
                reply.hiya_reply_t_u.feedPar.max_hereis = maxHereis;
            }
        } /* product-intersection != empty set */
    } /* successful acl_check_hiya() */

    return &reply;
}
Пример #8
0
/* init_retrans - Routine to initialize retransmission table */
int init_retrans(PROD_RETRANS_TABLE **pp_prod_retrans_table)
{

	static char FNAME[] = "init_retrans";
	long int	entry_base;		/* base of entry */
	long int	ii,iii;			/* loop counter */
	int	 flags, rtn_val;
	static const char *utc_time = "UTC";

	/* Pointer to prod_retrans table */
	PROD_RETRANS_ENTRY *p_retrans_entry;
	PROD_RETRANS_ENTRY_INFO *p_retrans_entry_info;

	/* pointer to prod_retrans_table */
	PROD_RETRANS_TABLE	*pl_prod_retrans_table;

	pl_prod_retrans_table = *pp_prod_retrans_table;

	if(ulogIsDebug())
		udebug("%s Begin init retrans_table   base=0x%x\n", FNAME, pl_prod_retrans_table);

	global_time_zone = (char *) utc_time;

	if (pl_prod_retrans_table != NULL){
		/* IMPORTANT, special init for local prod_retrans_table */

		/* Assume entries directly follow the entry info for all links */
		/*  and each is variable size */
		/* IMPORTANT, these must be initialized in order of their index value */
		/*   ie, GOES_EAST(0), NMC2(1), NMC(2), NOAAPORT_OPT(3), NMC3(4), NMC1(5) */
		/*    note NMC2 was GOES_WEST */
		/*   as per RETRANS_TBL_TYP_xxxxxxx */
		entry_base = (long)pl_prod_retrans_table + sizeof(PROD_RETRANS_TABLE);

		ii = 0; /* For now set to 0; Later can setup retrans table depending on the channel type */
		pl_prod_retrans_table->entry_info[GET_RETRANS_TABLE_TYP(sbn_type)].
			numb_entries = GET_RETRANS_CHANNEL_ENTRIES(sbn_type);
	if(ulogIsDebug()){
		udebug("%s Total retrans numb_entries for channel %s of sbn_type (%d) = %d \n", 
                               FNAME, sbn_channel_name,sbn_type,pl_prod_retrans_table->entry_info[ii].numb_entries);
	}

		pl_prod_retrans_table->entry_info[GET_RETRANS_TABLE_TYP(sbn_type)].
			retrans_entry_base_offset = (long)entry_base -
				(long)(&pl_prod_retrans_table->entry_info[GET_RETRANS_TABLE_TYP(sbn_type)].
					retrans_entry_base_offset);

		entry_base += 
			(long) (pl_prod_retrans_table->entry_info[GET_RETRANS_TABLE_TYP(sbn_type)].
				numb_entries * (sizeof(PROD_RETRANS_ENTRY)));

		/*ii = GET_RETRANS_TABLE_TYP(sbn_type);*/
			p_prod_retrans_table->entry_info[ii].entry_bytes = 
				sizeof(PROD_RETRANS_ENTRY);
			pl_prod_retrans_table->entry_info[ii].index_last = 0;
			pl_prod_retrans_table->entry_info[ii].run_id_last = 0;
			pl_prod_retrans_table->entry_info[ii].tot_prods_rcvd = 0;
			pl_prod_retrans_table->entry_info[ii].tot_prods_lost = 0;
			pl_prod_retrans_table->entry_info[ii].tot_prods_lost_seqno = 0;
			pl_prod_retrans_table->entry_info[ii].tot_prods_lost_abort = 0;
			pl_prod_retrans_table->entry_info[ii].tot_prods_lost_other = 0;
			pl_prod_retrans_table->entry_info[ii].tot_prods_retrans_rcvd = 0;
			pl_prod_retrans_table->entry_info[ii].tot_prods_retrans_rcvd_lost = 0;
			pl_prod_retrans_table->entry_info[ii].tot_prods_retrans_rcvd_notlost=0;
			pl_prod_retrans_table->entry_info[ii].tot_prods_retrans_rqstd = 0;
			pl_prod_retrans_table->entry_info[ii].len_wmo_hdr_max = 
				MAX_WMO_ENTRY_LEN;
			pl_prod_retrans_table->entry_info[ii].len_wmo_hdr_abbrev_max = 
				MAX_RETRANS_LEN_WMO_HDR_ABBREV;
			pl_prod_retrans_table->entry_info[ii].last_wmo_hdr[0] = '\0'; 
			pl_prod_retrans_table->entry_info[ii].last_wmo_loghdr_info[0] = '\0'; 

			p_retrans_entry_info =
				&pl_prod_retrans_table->entry_info[ii];

			p_retrans_entry =
				(PROD_RETRANS_ENTRY *)(((long)&p_retrans_entry_info->
					retrans_entry_base_offset) +
					(long)p_retrans_entry_info->retrans_entry_base_offset);
	
			/* Now clear each entry */
			for(iii=0;
				iii < pl_prod_retrans_table->entry_info[ii].numb_entries; iii++) {
				p_retrans_entry[iii].prod_arrive_time = (long) 0;
				p_retrans_entry[iii].prod_seqno = (long) 0;
				p_retrans_entry[iii].prod_run_id = 0;
				p_retrans_entry[iii].prod_type = 0;
				p_retrans_entry[iii].prod_cat = 0;
				p_retrans_entry[iii].prod_code = 0;
				p_retrans_entry[iii].prod_sub_code = 0;
				p_retrans_entry[iii].prod_status = 0;
				p_retrans_entry[iii].prod_err_cause = 0;
				p_retrans_entry[iii].prod_link_id = 0;
				p_retrans_entry[iii].entry_flag = 0;
				p_retrans_entry[iii].WMO_hdr_abbrev[0] = '\0';
			} /* end for each numb entries */
		if(ulogIsDebug()){
			udebug("%s  OK init retrans_table for channel [%s] numb_entries = %d\n",FNAME,
						sbn_channel_name,pl_prod_retrans_table->entry_info[ii].numb_entries);
		}

	} /* end if pl_prod_retrans_table != NULL */


	/*Open retransmit pipe */
	if((global_retransmitpipe_fd = open(DEFAULT_RETRANSMIT_PIPENAME, O_RDWR,0)) <= 0){
		uerror("Fail to open %s pipe errno=%d \n",DEFAULT_RETRANSMIT_PIPENAME,errno);
		perror("pipe open err");
		return (-1);
	}

	if((flags = fcntl(global_retransmitpipe_fd, F_GETFL)) < 0){
		uerror("Fail fcntl(F_GETFL) %s pipe\n",DEFAULT_RETRANSMIT_PIPENAME);
		/* Continue for now */
	}else{

		flags |= DONT_BLOCK;
		if((rtn_val = fcntl(global_retransmitpipe_fd, F_SETFL, flags)) < 0){
			uerror("Fail fcntl(F_SETFL) %s pipe \n",DEFAULT_RETRANSMIT_PIPENAME);
		}

		unotice(" OK open pipe[%d] for %s\n", global_retransmitpipe_fd,DEFAULT_RETRANSMIT_PIPENAME);
	}

	if(ulogIsDebug())
		udebug("%s Exiting  init retrans_table   base=0x%lx\n", FNAME,(unsigned long) pl_prod_retrans_table);
	return(0);

} /* end init_retrans */
Пример #9
0
int log_prod_end(char *end_msg, 
		long	in_orig_prod_seqno,
		long 	in_prod_seqno,
		int	 	in_prod_blkno,
		int 	in_prod_code,
		int	 	in_prod_bytes,
		long	in_prod_start_time)

{
	static const char FNAME[40+1]="log_prod_end";
#define MAX_WMO_HDR_NAME_LEN 64 /* max wmo hdr name len */

	char	prod_log_buff[256];	/* prod log buffer */
	time_t	now_time;			/* current time */
	struct tm *tmtime;          /* time */
	int		ii;					/* loop counter */
	long	log_ratio;			/* log ratio of compr to total */
static long log_eop_count;  /* counter to track number of log EOP entries */


#define LOG_DH_PROC_STATUS_CNT_INTERVAL 50  /* log status every 50 entries */

	log_eop_count++;

	prod_log_buff[0] = '\0';
	time(&now_time);

	tmtime = (struct tm *)gmtime(&now_time);   /* time */
	sprintf(prod_log_buff, "%s %s", "END",
			get_date_time(tmtime, global_time_zone));


	if(in_orig_prod_seqno != 0) {
		/* Assume have an original SBN prod seqno */
		sprintf(prod_log_buff, "%s #%ld/%d orig(#%ld)", 
				prod_log_buff,
				in_prod_seqno,
				in_prod_blkno,
				in_orig_prod_seqno);
	} else {
		sprintf(prod_log_buff, "%s #%ld/%d", 
				prod_log_buff,
				in_prod_seqno,
				in_prod_blkno);
	}

	sprintf(prod_log_buff, "%s bytes(%d)", 
			prod_log_buff,
			in_prod_bytes);
	
	sprintf(prod_log_buff, "%s c(%d)",
			prod_log_buff, in_prod_code);

	if((now_time - in_prod_start_time) > 0){
		sprintf(prod_log_buff, "%s +%lds", 
			prod_log_buff, (now_time - in_prod_start_time));
		
	}

	if(end_msg[0] != '\0') {
		sprintf(prod_log_buff, "%s %s", 
			prod_log_buff, end_msg);
	}

	/* Finally do the brief product logging */
	unotice("%s \n", prod_log_buff);

    	return(0);
} /* end acqpro_log_prod_end */
Пример #10
0
static int
my_hiya_6(CLIENT *clnt, prod_class_t **clsspp)
{
    static hiya_reply_t* reply;
    int                  error;
    
    reply = hiya_6(*clsspp, clnt);

    if (NULL == reply) {
        uerror("%s: HIYA_6 failure: %s", remote, clnt_errmsg(clnt));

        error = ECONNABORTED;
    }
    else {
        switch (reply->code) {
            case OK:
                max_hereis = reply->hiya_reply_t_u.max_hereis;
                error = 0;
                break;

            case SHUTTING_DOWN:
                uerror("%s: LDM shutting down", remote);
                error = ECONNABORTED;
                break;

            case BADPATTERN:
                uerror("%s: Bad product-class pattern", remote);
                error = ECONNABORTED;
                break;

            case DONT_SEND:
                uerror("%s: LDM says don't send", remote);
                error = ECONNABORTED;
                break;

            case RESEND:
                uerror("%s: LDM says resend (ain't gonna happen)", remote);
                error = ECONNABORTED;
                break;

            case RESTART:
                uerror("%s: LDM says restart (ain't gonna happen)", remote);
                error = ECONNABORTED;
                break;

            case REDIRECT:
                uerror("%s: LDM says redirect (ain't gonna happen)", remote);
                error = ECONNABORTED;
                break;

            case RECLASS:
                *clsspp = reply->hiya_reply_t_u.feedPar.prod_class;
                max_hereis = reply->hiya_reply_t_u.feedPar.max_hereis;
                clss_regcomp(*clsspp);
                /* N.B. we use the downstream patterns */
                unotice("%s: reclass: %s",
                        remote, s_prod_class(NULL, 0, *clsspp));
                error = 0;
                break;
        }

        if (!error)
            udebug("max_hereis = %u", max_hereis);
    }

    return error;
}
Пример #11
0
int prod_retrans_ck(ACQ_TABLE *p_acqtable, BUFF_HDR *p_buffhdr, time_t *orig_arrive_time)
{

	char FNAME[] = "prod_retrans_ck";

	int index_value;
	int match_value;
	int retrans_table_type;
	PROD_RETRANS_ENTRY *p_retrans_entry;
	PROD_RETRANS_ENTRY_INFO *p_retrans_entry_info;
	long orig_prod_seqno;
	long now_prod_seqno;
	long	delta_prod_seqno;	/* delta for prod seqno */
	int		valid_retrans_flag;	/* valid retrans flag for table */


	match_value = PROD_NODUPLICATE;
	*orig_arrive_time = 0;
	
	if(prod_retrans_get_addr(p_acqtable->proc_base_channel_type_last,
		p_prod_retrans_table, &p_retrans_entry_info, &p_retrans_entry, 
		&retrans_table_type) < 0) {
		unotice("%s ignore retrans_ck\n",	FNAME);
		return(match_value);
	}

	if(p_acqtable->proc_orig_prod_seqno_last != 0) {

		if (ulogIsDebug ())/* Debug only */
		{
			udebug("%s ok retrans channel_typ=%d tbl[%d] so ck more\n",
				FNAME,
				p_acqtable->proc_base_channel_type_last,
				retrans_table_type);
		}

		/* Assume have retransmitted product do following */
		p_acqtable->proc_tot_prods_retrans_rcvd++,
		p_retrans_entry_info->tot_prods_retrans_rcvd++;

		/* If is retransmission, need to see if original product was OK */
		/*  and ignore the product, else process the product */
		index_value = p_acqtable->proc_orig_prod_seqno_last % 
			p_retrans_entry_info->numb_entries;
		if(index_value < 0) {
			index_value = -index_value;
		}
		if(index_value >= p_retrans_entry_info->numb_entries) {
			index_value = 0;
		}

		/* Check if already have product in table */
		if((p_retrans_entry[index_value].prod_seqno ==
			p_acqtable->proc_orig_prod_seqno_last) &&
			(p_retrans_entry[index_value].prod_run_id ==
				p_acqtable->proc_orig_prod_run_id) &&
			(p_retrans_entry[index_value].entry_flag != 
				RETRANS_ENTRY_FLAG_AVAIL)) {
			/* Assume product matched */	
			match_value = PROD_DUPLICATE_MATCH;
			p_acqtable->proc_tot_prods_retrans_rcvd_notlost++;
			p_retrans_entry_info->tot_prods_retrans_rcvd_notlost++;
			*orig_arrive_time = p_retrans_entry[index_value].prod_arrive_time;
		} else {
			match_value = PROD_DUPLICATE_NOMATCH;
			p_acqtable->proc_tot_prods_retrans_rcvd_lost++;
			p_retrans_entry_info->tot_prods_retrans_rcvd_lost++;
			
		}

		if (ulogIsDebug ()){
			udebug("%s %s duplicate run(%d) prod|orig(%ld|%ld) tbl[%d]=%ld\n",
			FNAME,
			(match_value==PROD_DUPLICATE_MATCH)?"OK MATCH":"NO MATCH",
			p_acqtable->proc_orig_prod_run_id,
			p_buffhdr->proc_prod_seqno,
			p_acqtable->proc_orig_prod_seqno_last,
			index_value,
			p_retrans_entry[index_value].prod_seqno);
	
			}
		/* Check if retransmit prod is within range of table entries */
		orig_prod_seqno = (long)p_acqtable->proc_orig_prod_seqno_last;
		now_prod_seqno = (long)p_buffhdr->proc_prod_seqno;

		valid_retrans_flag = 0;
		delta_prod_seqno = now_prod_seqno - orig_prod_seqno;

		if((match_value == PROD_DUPLICATE_MATCH) ||
			(match_value == PROD_DUPLICATE_NOMATCH)) {
			if((delta_prod_seqno > 0) && 
				(delta_prod_seqno < p_retrans_entry_info->numb_entries)) {
				valid_retrans_flag = 1;
			}
		}
		if((match_value == PROD_DUPLICATE_MATCH) ||
			(match_value == PROD_DUPLICATE_NOMATCH)) {
			if((delta_prod_seqno < 0) && 
				(now_prod_seqno < p_retrans_entry_info->numb_entries)) {
					valid_retrans_flag = 1;
			}
		}


		/* Now if the original is within the number of active entries */
		/*  go ahead and update the match table entry */
		/* Note, that p_acqtable->proc_base_prod_seqno is not yet set */
		if((match_value == PROD_DUPLICATE_NOMATCH) &&
			(valid_retrans_flag == 1)){
			/* Now update the prod_retrans_entry */
			prod_retrans_update_entry(p_acqtable, p_buffhdr,
				p_retrans_entry_info,
				&p_retrans_entry[index_value], 
				index_value,
				p_acqtable->proc_orig_prod_seqno_last, 
				p_acqtable->proc_orig_prod_run_id, 
				RETRANS_ENTRY_FLAG_RETRANS_VALID, 0);
			p_retrans_entry_info->index_last = index_value;
			p_retrans_entry_info->run_id_last = 
				p_acqtable->proc_prod_run_id; 
		} else {
			/* Check if retransmit prod is within range of table entries */
			if((match_value == PROD_DUPLICATE_MATCH) &&
				(valid_retrans_flag == 1)){
				/* Now update the prod_retrans_entry */
				/*  to tell other product is ok but duplicate */
				prod_retrans_update_entry(p_acqtable, p_buffhdr,
					p_retrans_entry_info,
					&p_retrans_entry[index_value], 
					index_value,
					p_acqtable->proc_orig_prod_seqno_last, 
					p_acqtable->proc_orig_prod_run_id, 
					RETRANS_ENTRY_FLAG_RETRANS_DUP, 0);

			} else {
				if(p_retrans_entry[index_value].prod_run_id ==
					p_acqtable->proc_orig_prod_run_id) {
					/* Possibly orig prod_seqno greater than current prod_seqno */
					/*  so discard */
				}
			}

			/* Note, prod is possibly too old to fit in table */
			/* Always, set product for discard */
			match_value = PROD_DUPLICATE_DISCARD;

		}

	} else {
		/* If this a new (not retransmitted) product do following */
		match_value = PROD_NODUPLICATE;

	} /* end if-else retransmitted product */


	/* In either case need to update entry for new product */
	index_value = p_buffhdr->proc_prod_seqno % 
			p_retrans_entry_info->numb_entries;
	if(index_value < 0) {
		index_value = -index_value;
	}
	if(index_value >= p_retrans_entry_info->numb_entries) {
		index_value = 0;
	}

	/* IMPORTANT, this value will be removed later if product in error */
	/* Now update the prod_retrans_entry */
	/*  and also indicate if was a retransmission product */
	prod_retrans_update_entry(p_acqtable, p_buffhdr,
		p_retrans_entry_info,
		&p_retrans_entry[index_value], 
		index_value,
		p_buffhdr->proc_prod_seqno,
		p_acqtable->proc_prod_run_id, 
		RETRANS_ENTRY_FLAG_NEW_VALID|
		((p_acqtable->proc_orig_prod_seqno_last != 0)?
			RETRANS_ENTRY_FLAG_NEW_W_DUP:0), 0);

	p_retrans_entry_info->index_last = index_value;
	p_retrans_entry_info->run_id_last = 
		p_acqtable->proc_prod_run_id; 

/* Debug only */

	if(ulogIsDebug()) {
		if(match_value & PROD_NODUPLICATE) {
	    	udebug(" %s %s entry(%d) prod(%ld) code=%d %s[%d]\n",
				FNAME,
				GET_PROD_TYPE_NAME(p_buffhdr->proc_prod_type),
				index_value,
				p_buffhdr->proc_prod_seqno, 
				p_buffhdr->proc_prod_code,
				(match_value & PROD_NODUPLICATE)?"NO_DUPL":
				(match_value & PROD_DUPLICATE_MATCH)?"DUPL_MATCH":
				(match_value & PROD_DUPLICATE_NOMATCH)?"DUPL_NOMATCH":
					"UNKNOWN",
				match_value);
		} else {
	    	udebug("%s %s entry(%d) prod|orig(%ld|%ld) code=%d %s[%d]\n",
				FNAME,
				GET_PROD_TYPE_NAME(p_buffhdr->proc_prod_type),
				index_value,
				p_buffhdr->proc_prod_seqno, 
				p_acqtable->proc_orig_prod_seqno_last, 
				p_buffhdr->proc_prod_code,
				(match_value & PROD_NODUPLICATE)?"NO_DUPL":
				(match_value & PROD_DUPLICATE_MATCH)?"DUPL_MATCH":
				(match_value & PROD_DUPLICATE_NOMATCH)?"DUPL_NOMATCH":
					"UNKNOWN",
				match_value);
		}
	}
/* Debug only */

	return(match_value);

}
Пример #12
0
int readccb(char *buf,ccb_struct *ccb, psh_struct *psh, int blen)
{
    int iret=0;
    unsigned char b1,b2;
    char wmohead[256];
    int wmolen, metaoff=-1;
    char redbook_title[45];
    char wmometa[256];

    redbook_title[0] = '\0';
    wmometa[0] = '\0';

    b1 = (unsigned char)buf[0];
    b2 = (unsigned char)buf[1];

    ccb->b1 = b1;
    ccb->len = 2 * (int)(((b1 & 63) << 8) + b2);

    if ( ccb->len > blen ) /* A rouge product missing its CCB, reported to NWS DM 3/10/05 by Chiz */
    {
        uerror ("invalid ccb length = %d %d %d, blen %d\n",ccb->len,b1,b2,blen);

        /* try a failsafe header, otherwise use our own! */
        wmolen = 0;
        while ( ( (int)buf[wmolen] >= 32) && ( wmolen < 256 ) ) wmolen++;
        if ( wmolen > 0 )
            strncat(psh->pname,buf,wmolen);
        else
            sprintf(psh->pname,"Unidentifiable product\0");
        ccb->len = 0;
        return(-1);
    }


    b1 = (unsigned char)buf[10];
    b2 = (unsigned char)buf[11];
    psh->ccbmode = b1;
    psh->ccbsubmode = b2;
    udebug("ccb mode %d ccb submode %d\0",psh->ccbmode,psh->ccbsubmode);
    psh->hasccb = 1;

    b1 = (unsigned char)buf[12];
    b2 = (unsigned char)buf[13];
    ccb->user1 = b1;
    ccb->user2 = b1;
    udebug("ccb user1 %d ccb user2 %d\0",ccb->user1,ccb->user2);
    psh->ccbdtype[0] = '\0';     /* Initialize ccbdtype...eventually used to identify data type */

    /* see if this looks like a WMO header, if so canonicalize */
    if(wmo_header(buf+ccb->len,blen - ccb->len,wmohead,wmometa,&metaoff)==0)
    {
        if(strlen(wmohead) > 0)
        {
            strcat(psh->pname,wmohead);
            if (metaoff > 0) psh->metaoff = metaoff;
        }
        else
        {
            wmolen = 0;
            while ( ( (int)buf[wmolen + ccb->len] >= 32) && ( wmolen < 256 ) )
                wmolen++;

            strncat(psh->pname,buf+ccb->len,wmolen);
        }
    }
    else
    {
        wmolen = 0;
        while ( ( (int)buf[wmolen + ccb->len] >= 32) && ( wmolen < 256 ) )
            wmolen++;
        if ( wmolen > 0 )
            strncat(psh->pname,buf+ccb->len,wmolen);
        else
            sprintf(psh->pname,"Unidentifiable product\0");

        unotice("Non-wmo product type %s ccbmode %d ccbsubmode %d\0",
                psh->pname, psh->ccbmode, psh->ccbsubmode);
    }


    /* for now, since NEXRAD is not identified as a separate PTYPE, use WMO header check */
    if((psh->ccbmode == 2)&&(psh->ccbsubmode == 0))
    {
        if((memcmp(buf+ccb->len,"SDUS5",5) == 0)||
                (memcmp(buf+ccb->len,"SDUS2",5) == 0)||
                (memcmp(buf+ccb->len,"SDUS3",5) == 0)||
                (memcmp(buf+ccb->len,"SDUS7",5) == 0)||
                (memcmp(buf+ccb->len,"SDUS8",5) == 0) )
        {
            /* uncompressed nids check */
            if(ccb->user1 != 'F') sprintf(psh->ccbdtype,"nids/\0");
            psh->pcat = 99;
        }
    }
    /*
    unfortunately, NWS isn't using CCB mode for all product types
    else if((psh->pcat == 4)&&(psh->ccbmode == 2)&&(psh->ccbsubmode == 1))
       sprintf(psh->ccbdtype,"grib/\0");
    else if(psh->pcat == 5)
       sprintf(psh->ccbdtype,"bufr/\0");
    */
    else if (psh->pcat == 2)
    {
        /* see if this is recognizeable as a redbook graphic */
        redbook_header(buf+ccb->len,blen - ccb->len, redbook_title);
        if(strlen(redbook_title) > 0)
            sprintf(psh->ccbdtype,"redbook %d_%d/\0", ccb->user1, ccb->user2);
        else
            sprintf(psh->ccbdtype,"graph %d_%d/\0",  ccb->user1, ccb->user2);
    }



    /* create metadata */
    sprintf(psh->metadata," !\0");

    if ( psh->ccbdtype[0] != '\0')
        strcat ( psh->metadata, psh->ccbdtype);

    if ( redbook_title[0] != '\0' )
        strcat( psh->metadata, redbook_title);

    if ( wmometa[0] != '\0' )
        strcat( psh->metadata, wmometa);

    if ( psh->metadata[2] == '\0' ) psh->metadata[0] = '\0';


    /* restore meta data to PROD NAME
    strcat(psh->pname,psh->metadata); */

    return(iret);
}
Пример #13
0
static void
cleanup(void)
{
        unotice("Exiting"); 
        (void) closeulog();
}
Пример #14
0
/*
 * Returns:
 *      0       Success.  Write-count of product-queue is zero.
 *      1       System failure.  See error-message.
 *      2       Product-queue doesn't support a writer-counter.  Not possible
 *              if "-F" option used.
 *      3       Write-count of product-queue is greater than zero.  Not possible
 *              if "-F" option used.
 *      4       The product-queue is internally inconsistent.
 */
int main(int ac, char *av[])
{
        const char *progname = ubasename(av[0]);
        char *logfname;
        int status = 0;
        int logoptions = (LOG_CONS|LOG_PID) ;
        unsigned write_count;
        int force = 0;

        logfname = "";

        if(isatty(fileno(stderr)))
        {
                /* set interactive defaults */
                logfname = "-" ;
                logoptions = 0 ;
        }

        {
            extern int opterr;
            extern char *optarg;
            int ch;
            int logmask = (LOG_MASK(LOG_ERR) | LOG_MASK(LOG_WARNING) |
                LOG_MASK(LOG_NOTICE));

            opterr = 1;
            pqfname = getQueuePath();

            while ((ch = getopt(ac, av, "Fvxl:q:")) != EOF)
                    switch (ch) {
                    case 'F':
                            force = 1;
                            break;
                    case 'v':
                            logmask |= LOG_MASK(LOG_INFO);
                            break;
                    case 'x':
                            logmask |= LOG_MASK(LOG_DEBUG);
                            break;
                    case 'l':
                            logfname = optarg;
                            break;
                    case 'q':
                            pqfname = optarg;
                            break;
                    case '?':
                            usage(progname);
                            break;
                    }

            (void) setulogmask(logmask);
        }

        /*
         * Set up error logging.
         */
        (void) openulog(progname,
                logoptions, LOG_LDM, logfname);
        unotice("Starting Up (%d)", getpgrp());

        /*
         * register exit handler
         */
        if(atexit(cleanup) != 0)
        {
                serror("atexit");
                return 1;
        }

        /*
         * set up signal handlers
         */
        set_sigactions();

        if (force) {
            /*
             * Add writer-counter capability to the file, if necessary, and set
             * the writer-counter to zero.
             */
            status = pq_clear_write_count(pqfname);
            if (status) {
                if (PQ_CORRUPT == status) {
                    uerror("The product-queue \"%s\" is inconsistent", pqfname);
                    return 4;
                }
                else {
                    uerror("pq_clear_write_count() failure: %s: %s",
                            pqfname, strerror(status));
                    return 1;
                }
            }
            write_count = 0;
        }
        else {
            /*
             * Get the writer-counter of the product-queue.
             */
            status = pq_get_write_count(pqfname, &write_count);
            if (status) {
                if (ENOSYS == status) {
                    uerror("Product-queue \"%s\" doesn't have a writer-counter",
                        pqfname);
                    return 2;
                }
                else if (PQ_CORRUPT == status) {
                    uerror("Product-queue \"%s\" is inconsistent", pqfname);
                    return 4;
                }
                else {
                    uerror("pq_get_write_count() failure: %s: %s",
                        pqfname, strerror(status));
                    return 1;
                }
            }
        }

        uinfo("The writer-counter of the product-queue is %u", write_count);

        return write_count == 0 ? 0 : 3;
}
Пример #15
0
int main(int ac, char *av[])
{
        const char* pqfname = getQueuePath();
        const char *opqfname = getSurfQueuePath();
        const char *progname = ubasename(av[0]);
        char *logfname;
        prod_class_t clss;
        prod_spec spec;
        int status = 0;
        unsigned interval = DEFAULT_INTERVAL;
        int logoptions = (LOG_CONS|LOG_PID);
        double age = DEFAULT_AGE;
        /* these are containers for the pqact args */
        char *argv[16];
        int argc = 0;
        int toffset = TOFFSET_NONE;

        logfname = "";

        if(set_timestamp(&clss.from) != ENOERR) /* corrected by toffset below */
        {
                int errnum = errno;
                fprintf(stderr, "Couldn't set timestamp: %s", 
                        strerror(errnum));
                exit(1);
        }
        clss.to = TS_ENDT;
        clss.psa.psa_len = 1;
        clss.psa.psa_val = &spec;
        
        spec.feedtype = DEFAULT_FEEDTYPE;
        spec.pattern = DEFAULT_PATTERN;

        memset(argv, 0, sizeof(argv));
        argv[0] = "pqact";
        argc++;

        {
        extern int optind;
        extern int opterr;
        extern char *optarg;
        int ch;
        int logmask = (LOG_MASK(LOG_ERR) | LOG_MASK(LOG_WARNING) |
            LOG_MASK(LOG_NOTICE));
        int fterr;
        const char *conffilename = getPqsurfConfigPath();
        const char *datadir = getPqsurfDataDirPath();

        usePil = 1;
        opterr = 1;

        while ((ch = getopt(ac, av, "vxl:d:f:p:q:Q:o:i:a:t:")) != EOF)
                switch (ch) {
                case 'v':
                        argv[argc++] = "-v";
                        logmask |= LOG_MASK(LOG_INFO);
                        break;
                case 'x':
                        argv[argc++] = "-x";
                        logmask |= LOG_MASK(LOG_DEBUG);
                        break;
                case 'l':
                        argv[argc++] = "-l";
                        argv[argc++] = optarg;
                        logfname = optarg;
                        break;
                case 'd':
                        datadir = optarg;
                        break;
                case 'f':
                        fterr = strfeedtypet(optarg, &spec.feedtype);
                        if(fterr != FEEDTYPE_OK)
                        {
                                fprintf(stderr, "%s: %s: \"%s\"\n",
                                        av[0], strfeederr(fterr), optarg);
                                usage(progname);        
                        }
                        argv[argc++] = "-f";
                        argv[argc++] = optarg;
                        break;
                case 'p':
                        spec.pattern = optarg;
                        /* compiled below */
                        break;
                case 'q':
                        pqfname = optarg;
                        break;
                case 'Q':
                        opqfname = optarg;
                        break;
                case 'o':
                        toffset = atoi(optarg);
                        if(toffset == 0 && *optarg != '0')
                        {
                                fprintf(stderr, "%s: invalid offset %s\n",
                                         av[0], optarg);
                                usage(av[0]);   
                        }
                        argv[argc++] = "-o";
                        argv[argc++] = optarg;
                        break;
                case 'i':
                        interval = atoi(optarg);
                        if(interval == 0 && *optarg != '0')
                        {
                                fprintf(stderr, "%s: invalid interval \"%s\"\n",
                                        av[0], optarg);
                                usage(av[0]);
                        }
                        /* N.B. -i just used for input queue. */
                        break;
                case 'a':
                        age = atof(optarg);
                        if(age < 0.)
                        {
                            (void) fprintf(stderr,
                                        "age (%s) must be non negative\n",
                                        optarg);
                                usage(av[0]);   
                        }
                        break;
                case 't':
                        /* pipe_timeo */
                        argv[argc++] = "-t";
                        argv[argc++] = optarg;
                        break;
                case '?':
                        usage(progname);
                        break;
                }

        (void) setulogmask(logmask);

        if (re_isPathological(spec.pattern))
        {
                fprintf(stderr, "Adjusting pathological regular-expression: "
                    "\"%s\"\n", spec.pattern);
                re_vetSpec(spec.pattern);
        }
        status = regcomp(&spec.rgx,
                spec.pattern,
                REG_EXTENDED|REG_NOSUB);
        if(status != 0)
        {
                fprintf(stderr, "Bad regular expression \"%s\"\n",
                        spec.pattern);
                usage(av[0]);
        }

        if(ac - optind == 1)
                conffilename = av[optind];

        argv[argc++] = "-d";
        argv[argc++] = (char*)datadir;
        argv[argc++] = "-q";
        argv[argc++] = (char*)opqfname;
        argv[argc++] = (char*)conffilename;

        age *= 3600.;

        }

        if(toffset != TOFFSET_NONE)
        {
                clss.from.tv_sec -= toffset;
        }
        else
        {
                clss.from.tv_sec -= (age - interval);
        }


        /*
         * Set up error logging.
         * N.B. log ident is the remote
         */
        (void) openulog(progname,
                logoptions, LOG_LDM, logfname);
        unotice("Starting Up (%d)", getpgrp());

        /*
         * register exit handler
         */
        if(atexit(cleanup) != 0)
        {
                serror("atexit");
                exit(1);
        }

        /*
         * set up signal handlers
         */
        set_sigactions();


        /*
         * Open the output product queue
         */
        status = pq_open(opqfname, PQ_DEFAULT, &opq);
        if(status)
        {
                if (PQ_CORRUPT == status) {
                    uerror("The output product-queue \"%s\" is inconsistent\n",
                            opqfname);
                }
                else {
                    uerror("pq_open failed: %s: %s\n",
                            opqfname, strerror(status));
                }
                exit(1);
        }


        act_pid = run_child(argc, argv);
        if(act_pid == (pid_t)-1)
                exit(1);

        /*
         * Open the input product queue
         */
        status = pq_open(pqfname, PQ_READONLY, &pq);
        if(status)
        {
                if (PQ_CORRUPT == status) {
                    uerror("The product-queue \"%s\" is inconsistent\n",
                            pqfname);
                }
                else {
                    uerror("pq_open failed: %s: %s\n",
                            pqfname, strerror(status));
                }
                exit(1);
        }
        if(toffset == TOFFSET_NONE)
        {
                /* Jump to the end of the queue */
                timestampt sav;
                sav = clss.from;
                clss.from = TS_ZERO;
                (void) pq_last(pq, &clss, NULL);
                clss.from = sav;
        }
        else
        {
                pq_cset(pq, &clss.from);
        }

        if(ulogIsVerbose())
        {
                char buf[1984];
                uinfo("%s",
                         s_prod_class(buf, sizeof(buf), &clss));
        }

        while(exitIfDone(0))
        {
                if(stats_req)
                {
                        dump_stats();
                        stats_req = 0;
                }

                status = pq_sequence(pq, TV_GT, &clss, split_prod, NULL);

                switch(status) {
                case 0: /* no error */
                        continue; /* N.B., other cases sleep */
                case PQUEUE_END:
                        udebug("surf: End of Queue");
                        break;
                case EAGAIN:
                case EACCES:
                        udebug("Hit a lock");
                        break;
                default:
                        uerror("pq_sequence failed: %s (errno = %d)",
                                strerror(status), status);
                        exit(1);
                        break;
                }

                if(interval == 0)
                {
                        break;
                }


                (void) expire(opq, interval, age);

                pq_suspend(interval);

                (void) reap_act(WNOHANG);
        }

        /*
         * TODO: how can we determine that pqact has finished
         *       the work in opq?
         */
        sleep(5);

        exit(0);
}
Пример #16
0
void gb2_param ( char *wmovartbl, char *lclvartbl, Gribmsg *cmsg, 
                char *param, int *scal, float *msng, int *iret )
/************************************************************************
 * gb2_param								*
 *									*
 * This routine gets the parameter values                               *
 * from the GRIB2 PDS, and obtains the GEMPAK parameter information     *
 * from the appropriate GRIB2 parameter table.                          *
 *									*
 * If either wmovartbl or lclvartbl are NULL, the default tables are    *
 * read.                                                                *
 *									*
 * gb2_param ( wmovartbl, lclvartbl, cmsg, param, scal, msng, iret )	*
 *									*
 * Input parameters:							*
 *      *wmovartbl      char            WMO parameter table             *
 *      *lclvartbl      char            Local parameter table           *
 *	*cmsg  	    struct Gribmsg      GRIB2  message structure        *
 *									*
 * Output parameters:							*
 *      *param          char            12 character parameter name.    *
 *	*scal		int		scale factor associated with    *
 *                                      current parameter               *
 *	*msng		float		missing value associated with   *
 *                                      current parameter               *
 *	*iret		int		return code			*
 *                                          1 = No gempak param name    *
 *                                              defined for this grid   *
 **									*
 * Log:									*
 * S. Gilbert/NCEP      12/04                                           *
 * S. Gilbert/NCEP      10/05		Fix null character location     *
 * S. Gilbert/NCEP      10/05		Use new routines to read tables *
 ***********************************************************************/
{
    int     ier, disc, cat, id, pdtn, iver, lclver, len;
    const char* filename;
    G2Vinfo  g2var;
    G2vars_t  *g2vartbl;

/*---------------------------------------------------------------------*/

    *iret = 0;
    strncpy( param, "UNKNOWN", 12);

    /* 
     *  Get Parameter information from Parameter table(s).
     */
    iver=cmsg->gfld->idsect[2];
    lclver=cmsg->gfld->idsect[3];
    disc=cmsg->gfld->discipline;
    cat=cmsg->gfld->ipdtmpl[0];
    id=cmsg->gfld->ipdtmpl[1];
    pdtn=cmsg->gfld->ipdtnum;

#if 0
    /*
     * Some GRIB2 messages from NCEP *don't* have the Master Table Version
     * number set to 255 (which is wrong). Consequently, the following hack sets
     * things right.
     */
    if (iver != 255 && strcmp(cmsg->origcntr, "wmo")) {
        unotice("Setting Master Table Version to 255 for non-WMO originating center: "
                    "iver=%d, disc=%d, cat=%d, id=%d, pdtn=%d, "
                    "center=%.*s, lclver=%d",
                iver, disc, cat, id, pdtn,
                (int)sizeof(cmsg->origcntr), cmsg->origcntr, lclver);
        cmsg->gfld->idsect[2] = iver = 255;
    }
#endif

    if ((iver != 255) &&
        ((disc < 192   || disc == 255  ) && 
         (cat  < 192   || cat  == 255  ) &&
         (id   < 192   || id   == 255  ) &&
         (pdtn < 32768 || pdtn == 65535))) {
       /* 
        *  Get WMO Parameter table.
        */
        gb2_gtvartbl(wmovartbl, "wmo", iver, &g2vartbl, &filename, &ier);
    }
    else {
       /* 
        *  Get Local Parameter table.
        */
        gb2_gtvartbl(lclvartbl, cmsg->origcntr, lclver, &g2vartbl, &filename,
                &ier);
    }
    if (ier != 0) {
        unotice("Couldn't get parameter table: iver=%d, disc=%d, cat=%d, "
                "id=%d, pdtn=%d, center=%.*s, lclver=%d", iver, disc, cat, id,
                pdtn, (int)sizeof(cmsg->origcntr), cmsg->origcntr, lclver);
        *iret = 1;
        return;
    }
   /*
    *  Get parameter information from table.
    */
    gb2_skvar(disc, cat, id, pdtn, g2vartbl, &g2var, &ier);

    if (ier != 0) {
        unotice("Couldn't get parameter info: iver=%d, disc=%d, cat=%d, id=%d, "
                "pdtn=%d, center=%.*s, lclver=%d, file=%s", iver, disc, cat, id,
                pdtn, (int)sizeof(cmsg->origcntr), cmsg->origcntr, lclver,
                filename);
        *iret = 1;
        return;
    }
    
    /* 
     *  Insert time range period in parameter abbreviation,
     *  if necessary.
     */
    gb2_ctim ( cmsg->tmrange, g2var.gemname );

    /* 
     *  Adjust ensemble information in parameter abbreviation,
     *  if necessary.
     *        NOT DESIRED AT THIS TIME
    gb2_ens ( cmsg->gfld, g2var.gemname );
     */

    /* 
     *  Adjust probability information in parameter abbreviation,
     *  if necessary.
     */
    gb2_prob ( cmsg->gfld, g2var.gemname );

    /*
     * Add generating process information in parameter abbreviation
     * if necessary.
     */
    gb2_proc ( cmsg->gfld, g2var.gemname );

    len = strlen(g2var.gemname);
    strncpy( param, g2var.gemname, 12);
    if ( len > 12 ) param[12]='\0';
    if ( len < 12 )  {     /*  pad gempak parameter name with blanks  */
       char    blanks[13]="            ";

       strncat( param, blanks, 12-len );
    }
    *scal = g2var.scale;
    *msng = g2var.missing;

}
Пример #17
0
int main(int ac, char *av[])
{
        char *logfname = 0;
        unsigned timeo = DEFAULT_TIMEO; 
        unsigned interval = DEFAULT_TIMEO; 
        unsigned TotalTimeo = DEFAULT_TOTALTIMEO;
        prod_spec spec;
        int status;
        prod_class_t *clssp;
        unsigned        port = 0;

        if(set_timestamp(&clss.from) != 0)
        {
                fprintf(stderr, "Couldn't set timestamp\n");
                exit(1);
        }
        clss.to = TS_ENDT;
        clss.psa.psa_len = 1;
        clss.psa.psa_val = &spec;
        spec.feedtype = DEFAULT_FEEDTYPE;
        spec.pattern = DEFAULT_PATTERN;

        { /* Begin getopt block */
        extern int optind;
        extern int opterr;
        extern char *optarg;
        int ch;
        int logmask = (LOG_MASK(LOG_ERR) | LOG_MASK(LOG_WARNING) |
            LOG_MASK(LOG_NOTICE));
        int fterr;

        opterr = 1;

        while ((ch = getopt(ac, av, "vxl:f:o:t:h:P:p:T:")) != EOF)
                switch (ch) {
                case 'v':
                        logmask |= LOG_MASK(LOG_INFO);
                        break;
                case 'x':
                        logmask |= LOG_MASK(LOG_DEBUG);
                        break;
                case 'l':
                        logfname = optarg;
                        break;
                case 'h':
                        remote = optarg;
                        break;
                case 'P': {
                    char*       suffix = "";
                    long        p;

                    errno = 0;
                    p = strtol(optarg, &suffix, 0);

                    if (0 != errno || 0 != *suffix ||
                        0 >= p || 0xffff < p) {

                        (void)fprintf(stderr, "%s: invalid port %s\n",
                             av[0], optarg);
                        usage(av[0]);   
                    }
                    else {
                        port = p;
                    }

                    break;
                }
                case 'p':
                        spec.pattern = optarg;
                        /* compiled below */
                        break;
                case 'f':
                        fterr = strfeedtypet(optarg, &spec.feedtype);
                        if(fterr != FEEDTYPE_OK)
                        {
                                fprintf(stderr, "Bad feedtype \"%s\", %s\n",
                                        optarg, strfeederr(fterr));
                                usage(av[0]);   
                        }
                        break;
                case 'o':
                        clss.from.tv_sec -= atoi(optarg);
                        break;
                case 'T':
                        TotalTimeo = atoi(optarg);
                        if(TotalTimeo == 0)
                        {
                                fprintf(stderr, "%s: invalid TotalTimeo %s", av[0], optarg);
                                usage(av[0]);   
                        }
                        break;
                case 't':
                        timeo = (unsigned)atoi(optarg);
                        if(timeo == 0 || timeo > 32767)
                        {
                                fprintf(stderr, "%s: invalid timeout %s", av[0], optarg);
                                usage(av[0]);   
                        }
                        break;
                case '?':
                        usage(av[0]);
                        break;
                }

        if(ac - optind > 0)
                usage(av[0]);

        if (re_isPathological(spec.pattern))
        {
                fprintf(stderr, "Adjusting pathological regular-expression: "
                    "\"%s\"\n", spec.pattern);
                re_vetSpec(spec.pattern);
        }
        status = regcomp(&spec.rgx,
                spec.pattern,
                REG_EXTENDED|REG_NOSUB);
        if(status != 0)
        {
                fprintf(stderr, "Bad regular expression \"%s\"\n",
                        spec.pattern);
                usage(av[0]);
        }

        (void) setulogmask(logmask);

        if(TotalTimeo < timeo)
        {
                fprintf(stderr, "TotalTimeo %u < timeo %u\n",
                         TotalTimeo, timeo);
                usage(av[0]);
        }

        } /* End getopt block */

        /*
         * initialize logger
         */
        (void) openulog(ubasename(av[0]),
                (LOG_CONS|LOG_PID), LOG_LDM, logfname);
        unotice("Starting Up: %s: %s",
                        remote,
                        s_prod_class(NULL, 0, &clss));

        /*
         * register exit handler
         */
        if(atexit(cleanup) != 0)
        {
                serror("atexit");
                exit(1);
        }

        /*
         * set up signal handlers
         */
        set_sigactions();


        /*
         * Try forever.
         */
        while (exitIfDone(0))
        {
                clssp = &clss;
                status = forn5(NOTIFYME, remote, &clssp,
                                timeo, TotalTimeo, notifymeprog_5);

                (void)exitIfDone(0);

                switch(status) {
                        /* problems with remote, retry */       
                case ECONNABORTED:
                case ECONNRESET:
                case ETIMEDOUT:
                case ECONNREFUSED:
                        sleep(interval);
                        break;
                case 0:
                        /* assert(done); */
                        break;
                default:
                        /* some wierd error */
                        done = 1;
                        exit(1);
                }
        }

        exit(0);
        /*NOTREACHED*/
}
Пример #18
0
/**
 * Notifies the LDM of the class of data-products that will be sent via LDM-6
 * protocols.
 *
 * Arguments:
 *      proxy           Pointer to the LDM proxy data-structure.
 *      offer           Pointer to the data-product class structure which will
 *                      be offered to the LDM.
 *      want            Pointer to a pointer to a data-product class structure.
 *                      "*want" will be set the data-product class structure
 *                      that the LDM wants. The client should call
 *                      "free_prod_class(*want)" when the product-class is no
 *                      longer needed.
 * Returns:
 *      0               Success. "*clsspp" might be modified.
 *      LP_RPC_ERROR    RPC error. "log_start()" called.
 *      LP_LDM_ERROR    LDM error. "log_start()" called.
 */
static LdmProxyStatus
my_hiya_6(
    LdmProxy* const             proxy,
    prod_class_t* const         offer,
    prod_class_t** const        want)
{
    CLIENT* const       clnt = proxy->clnt;
    hiya_reply_t*       reply;
    LdmProxyStatus      status;
    
    reply = hiya_6(offer, clnt);

    if (NULL == reply) {
        status = getStatus(proxy, "HIYA_6", NULL);
    }
    else {
        switch (reply->code) {
            case OK:
                *want = (prod_class_t*)PQ_CLASS_ALL;
                proxy->max_hereis = reply->hiya_reply_t_u.max_hereis;
                status = 0;
                break;

            case SHUTTING_DOWN:
                LOG_START1("%s: LDM shutting down", proxy->host);
                status = LP_LDM_ERROR;
                break;

            case BADPATTERN:
                LOG_START1("%s: Bad product-class pattern", proxy->host);
                status = LP_LDM_ERROR;
                break;

            case DONT_SEND:
                LOG_START1("%s: LDM says don't send", proxy->host);
                status = LP_LDM_ERROR;
                break;

            case RESEND:
                LOG_START1("%s: LDM says resend (ain't gonna happen)",
                        proxy->host);
                status = LP_LDM_ERROR;
                break;

            case RESTART:
                LOG_START1("%s: LDM says restart (ain't gonna happen)",
                        proxy->host);
                status = LP_LDM_ERROR;
                break;

            case REDIRECT:
                LOG_START1("%s: LDM says redirect (ain't gonna happen)",
                        proxy->host);
                status = LP_LDM_ERROR;
                break;

            case RECLASS:
                *want = reply->hiya_reply_t_u.feedPar.prod_class;
                proxy->max_hereis = reply->hiya_reply_t_u.feedPar.max_hereis;
                clss_regcomp(*want);
                /* N.B. we use the downstream patterns */
                /* Use of "buf" added to prevent SIGSEGV on 64-bit RHEL 6 */
                (void)s_prod_class(buf, sizeof(buf)-1, *want);
                unotice("%s: reclass: %s", proxy->host, buf);
                status = 0;
                break;
        }

        if (LP_OK != status)
            udebug("max_hereis = %u", proxy->max_hereis);
    }

    return status;
}
Пример #19
0
int main(
        int ac,
        char* av[])
{
    const char* pqfname = getQueuePath();
    int sock = -1;
    int status;
    int doSomething = 1;
    in_addr_t locIpAddr = (in_addr_t) htonl(INADDR_ANY );
    unsigned ldmPort = LDM_PORT;

    ensureDumpable();

    /*
     * deal with the command line, set options
     */
    {
        extern int optind;
        extern int opterr;
        extern char *optarg;
        int ch;
        int logmask = LOG_MASK(LOG_ERR) | LOG_MASK(LOG_WARNING)
                | LOG_MASK(LOG_NOTICE);

        opterr = 1;

        while ((ch = getopt(ac, av, "I:vxl:nq:o:P:M:m:t:")) != EOF) {
            switch (ch) {
            case 'I': {
                in_addr_t ipAddr = inet_addr(optarg);

                if ((in_addr_t) -1 == ipAddr) {
                    (void) fprintf(stderr, "Interface specification \"%s\" "
                            "isn't an IP address\n", optarg);
                    exit(1);
                }

                locIpAddr = ipAddr;

                break;
            }
            case 'v':
                logmask |= LOG_MASK(LOG_INFO);
                break;
            case 'x':
                logmask |= LOG_MASK(LOG_DEBUG);
                break;
            case 'l':
                logfname = optarg;
                break;
            case 'q':
                pqfname = optarg;
                setQueuePath(optarg);
                break;
            case 'o':
                toffset = atoi(optarg);
                if (toffset == 0 && *optarg != '0') {
                    (void) fprintf(stderr, "%s: invalid offset %s\n", av[0],
                            optarg);
                    usage(av[0]);
                }
                break;
            case 'P': {
                char* suffix = "";
                long port;

                errno = 0;
                port = strtol(optarg, &suffix, 0);

                if (0 != errno || 0 != *suffix || 0 >= port || 0xffff < port) {

                    (void) fprintf(stderr, "%s: invalid port %s\n", av[0],
                            optarg);
                    usage(av[0]);
                }

                ldmPort = (unsigned) port;

                break;
            }
            case 'M': {
                int max = atoi(optarg);
                if (max < 0) {
                    (void) fprintf(stderr,
                            "%s: invalid maximum number of clients %s\n", av[0],
                            optarg);
                    usage(av[0]);
                }
                maxClients = max;
                break;
            }
            case 'm':
                max_latency = atoi(optarg);
                if (max_latency <= 0) {
                    (void) fprintf(stderr, "%s: invalid max_latency %s\n",
                            av[0], optarg);
                    usage(av[0]);
                }
                break;
            case 'n':
                doSomething = 0;
                break;
            case 't':
                rpctimeo = (unsigned) atoi(optarg);
                if (rpctimeo == 0 || rpctimeo > 32767) {
                    (void) fprintf(stderr, "%s: invalid timeout %s", av[0],
                            optarg);
                    usage(av[0]);
                }
                break;
            case '?':
                usage(av[0]);
                break;
            } /* "switch" statement */
        } /* argument loop */

        if (ac - optind == 1)
            setLdmdConfigPath(av[optind]);
        (void) setulogmask(logmask);

        if (toffset != TOFFSET_NONE && toffset > max_latency) {
            (void) fprintf(stderr,
                    "%s: invalid toffset (%d) > max_latency (%d)\n", av[0],
                    toffset, max_latency);
            usage(av[0]);
        }
    } /* command-line argument decoding */

#ifndef DONTFORK
    /* 
     * daemon behavior
     *
     * Background the process unless we are logging to stderr, in which
     * case we assume interactive.
     */
    if (logfname == NULL || *logfname != '-') {
        /* detach */
        pid_t pid;
        pid = ldmfork();
        if (pid == -1) {
            log_add("Couldn't fork LDM daemon");
            log_log(LOG_ERR);
            exit(2);
        }

        if (pid > 0) {
            /* parent */
            (void) printf("%ld\n", (long) pid);
            exit(0);
        }

        /* detach the child from parents process group ?? */
        (void) setsid();
    }
#endif

    /*
     * Initialize logger.
     * (Close fd 2 to remap stderr to the logfile, when
     * appropriate. I know, this is anal.)
     */
    if (logfname == NULL )
        (void) fclose(stderr);
    else if (!(logfname[0] == '-' && logfname[1] == 0))
        (void) close(2);
    (void) openulog(ubasename(av[0]), (LOG_CONS | LOG_PID), LOG_LDM, logfname);
    unotice("Starting Up (version: %s; built: %s %s)", PACKAGE_VERSION,
            __DATE__, __TIME__);

    /*
     * register exit handler
     */
    if (atexit(cleanup) != 0) {
        serror("atexit");
        unotice("Exiting");
        exit(1);
    }

    /*
     * set up signal handlers
     */
    set_sigactions();

    /*
     * Close the standard input and standard output streams because they won't
     * be used (more anality :-)
     */
    (void) fclose(stdout);
    (void) fclose(stdin);

    if (!doSomething) {
        /*
         * Vet the configuration file.
         */
        udebug("main(): Vetting configuration-file");
        if (read_conf(getLdmdConfigPath(), doSomething, ldmPort) != 0) {
            log_log(LOG_ERR);
            exit(1);
        }
    }
    else {
        /*
         * Create a service portal. This should be done before anything is
         * created because this is the function that relinquishes superuser
         * privileges.
         */
        udebug("main(): Creating service portal");
        if (create_ldm_tcp_svc(&sock, locIpAddr, ldmPort) != ENOERR) {
            /* error reports are emitted from create_ldm_tcp_svc() */
            exit(1);
        }
        udebug("tcp sock: %d", sock);

        /*
         * Verify that the product-queue can be open for writing.
         */
        udebug("main(): Opening product-queue");
        if (status = pq_open(pqfname, PQ_DEFAULT, &pq)) {
            if (PQ_CORRUPT == status) {
                uerror("The product-queue \"%s\" is inconsistent", pqfname);
            }
            else {
                uerror("pq_open failed: %s: %s", pqfname, strerror(status));
            }
            exit(1);
        }
        (void) pq_close(pq);
        pq = NULL;

        /*
         * Create the sharable database of upstream LDM metadata.
         */
        udebug("main(): Creating shared upstream LDM database");
        if (status = uldb_delete(NULL)) {
            if (ULDB_EXIST == status) {
                log_clear();
            }
            else {
                LOG_ADD0(
                        "Couldn't delete existing shared upstream LDM database");
                log_log(LOG_ERR);
                exit(1);
            }
        }
        if (uldb_create(NULL, maxClients * 1024)) {
            LOG_ADD0("Couldn't create shared upstream LDM database");
            log_log(LOG_ERR);
            exit(1);
        }

        /*
         * Read the configuration file (downstream LDM-s are started).
         */
        udebug("main(): Reading configuration-file");
        if (read_conf(getLdmdConfigPath(), doSomething, ldmPort) != 0) {
            log_log(LOG_ERR);
            exit(1);
        }

        /*
         * Serve
         */
        udebug("main(): Serving socket");
        sock_svc(sock);
    } /* "doSomething" is true */

    return (0);
}
Пример #20
0
int main(int ac, char *av[])
{
        const char* const       pqfname = getQueuePath();
        const char* const       progname = ubasename(av[0]);
        char *logfname = NULL; /* log to syslogd(8) */
        int logoptions = LOG_CONS | LOG_PID;
        int logmask = LOG_UPTO(LOG_NOTICE);
        prod_class_t clss;
        prod_spec spec;
        int status = 0;
        int interval = DEFAULT_INTERVAL;
        int toffset = TOFFSET_NONE;
        extern const char *remote;
        char* hostname = ghostname();

        /*
         * Setup default logging before anything else.
         */
        (void) openulog(progname, logoptions, LOG_LDM, logfname);
        (void) setulogmask(logmask);

        remote = "localhost";

        if(set_timestamp(&clss.from) != ENOERR) /* corrected by toffset below */
        {
                int errnum = errno;
                fprintf(stderr, "Couldn't set timestamp: %s", 
                        strerror(errnum));
                exit(1);
        }
        clss.to = TS_ENDT;
        clss.psa.psa_len = 1;
        clss.psa.psa_val = &spec;
        spec.feedtype = DEFAULT_FEEDTYPE;
        spec.pattern = ".*";
        
        /*
         * Sigh, in order to read back from existing stats files,
         * we call mktime(3). Since the stats are in UTC,
         * and mktime uses "local" time, the local time for
         * this program must be UTC.
         */
        if(setenv("TZ", "UTC0",1))
        {
                int errnum = errno;
                uerror("setenv: Couldn't set TZ: %s", strerror(errnum));
                exit(1);        
        }

        {
            int ch;

            opterr = 0; /* stops getopt() from printing to stderr */

            while ((ch = getopt(ac, av, ":vxl:p:f:q:o:i:H:h:P:")) != 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 'l':
                        logfname = optarg;
                        if (strcmp(logfname, "") == 0)
                            logfname = NULL;
                        logoptions = (logfname == NULL)
                                ? (LOG_CONS|LOG_PID)
                                : LOG_NOTIME;
                        openulog(progname, logoptions, LOG_LDM, logfname);
                        break;
                    case 'H':
                        hostname = optarg;
                        break;
                    case 'h':
                        remote = optarg;
                        break;
                    case 'p':
                        spec.pattern = optarg;
                        if (re_isPathological(spec.pattern)) {
                            unotice("Adjusting pathological regular-expression \"%s\"",
                                    spec.pattern);
                            re_vetSpec(spec.pattern);
                        }
                        break;
                    case 'f': {
                        int fterr = strfeedtypet(optarg, &spec.feedtype) ;
                        if (fterr != FEEDTYPE_OK) {
                            uerror("Bad feedtype \"%s\", %s", optarg,
                                    strfeederr(fterr)) ;
                            usage(progname);
                        }
                        break;
                    }
                    case 'q':
                        setQueuePath(optarg);
                        break;
                    case 'o':
                        toffset = atoi(optarg);
                        if(toffset == 0 && *optarg != '0') {
                            uerror("Invalid offset %s", optarg);
                            usage(progname);
                        }
                        break;
                    case 'P': {
                        char*       suffix = "";
                        long        port;

                        errno = 0;
                        port = strtol(optarg, &suffix, 0);

                        if (0 != errno || 0 != *suffix ||
                            0 >= port || 0xffff < port) {

                            uerror("Invalid port %s", optarg);
                            usage(progname);
                        }

                        remotePort = (unsigned)port;

                        break;
                    }
                    case 'i':
                        interval = atoi(optarg);
                        if (interval == 0 && *optarg != '0') {
                            uerror("Invalid interval %s", optarg);
                            usage(progname);
                        }
                        break;
                    case '?':
                        uerror("Invalid option \"%c\"", optopt);
                        usage(progname);
                        break;
                    case ':':
                        uerror("No argument for option \"%c\"", optopt);
                        usage(progname);
                        break;
                }
            } /* getopt() loop */

            if (optind != ac) {
                uerror("Invalid operand: \"%s\"", av[optind]);
                usage(progname);
            }
        } /* command-line decoding block */

        if (regcomp(&spec.rgx, spec.pattern, REG_EXTENDED|REG_NOSUB)) {
            uerror("Bad regular expression \"%s\"\n", spec.pattern);
            usage(progname);
        }

        unotice("Starting Up (%d)", getpgrp());

        /*
         * register exit handler
         */
        if(atexit(cleanup) != 0)
        {
                serror("atexit");
                exit(1);
        }

        /*
         * set up signal handlers
         */
        set_sigactions();


        /*
         * Open the product queue
         */
        status = pq_open(pqfname, PQ_READONLY, &pq);
        if(status)
        {
                if (PQ_CORRUPT == status) {
                    uerror("The product-queue \"%s\" is inconsistent\n",
                            pqfname);
                }
                else {
                    uerror("pq_open failed: %s: %s\n",
                            pqfname, strerror(status));
                }
                exit(1);
        }

        if(toffset == TOFFSET_NONE)
        {
                /*
                 * Be permissive with the time filter,
                 * jump now to the end of the queue.
                 */
                clss.from = TS_ZERO;
                (void) pq_last(pq, &clss, NULL);
        }
        else
        {
                /*
                 * Filter and queue position set by
                 * toffset.
                 */
                clss.from.tv_sec -= toffset;
                pq_cset(pq, &clss.from);
        }

        while(exitIfDone(0))
        {
                if(stats_req)
                {
                        dump_statsbins();
                        stats_req = 0;
                }

                status = pq_sequence(pq, TV_GT, &clss, addtostats, 0);

                switch(status) {
                case 0: /* no error */
                        continue; /* N.B., other cases sleep */
                case PQUEUE_END:
                        udebug("End of Queue");
                        break;
                case EAGAIN:
                case EACCES:
                        udebug("Hit a lock");
                        break;
                default:
                        uerror("pq_sequence failed: %s (errno = %d)",
                                strerror(status), status);
                        exit(1);
                        break;
                }

                syncbinstats(hostname);

                if(interval == 0)
                {
                        done = 1;
                        break;
                }

                pq_suspend(interval);
        }

        return 0;
}
Пример #21
0
Файл: ldmd.c Проект: dgaer/LDM
/*
 * Called at exit.
 * This callback routine registered by atexit().
 */
static void cleanup(
        void)
{
    const char* const pqfname = getQueuePath();

    unotice("Exiting");

    lcf_savePreviousProdInfo();

    free_remote_clss();

    /*
     * Ensure release of COMINGSOON-reserved space in product-queue.
     */
    clr_pip_5();
    down6_destroy();

    /*
     * Close product-queue.
     */
    if (pq) {
        (void) pq_close(pq);
        pq = NULL;
    }

    /*
     * Ensure that this process has no entry in the upstream LDM database and
     * that the database is closed.
     */
    (void) uldb_remove(getpid());
    (void) uldb_close();
    log_clear();

    if (getpid() == getpgrp()) {
        /*
         * This process is the process group leader (i.e., the top-level
         * LDM server).
         */
        if (portIsMapped) {
            int vers;

            /*
             * Superuser privileges might be required to unmap the
             * port on which the LDM is listening.
             */
            rootpriv();

            for (vers = MIN_LDM_VERSION; vers <= MAX_LDM_VERSION; vers++) {
                if (!pmap_unset(LDMPROG, vers))
                    uerror("pmap_unset(LDMPROG %lu, LDMVERS %lu) "
                            "failed", LDMPROG, vers);
                else
                    portIsMapped = 0;
            }

            unpriv();
        }

        /*
         * Terminate all child processes.
         */
        {
            /*
             * Ignore the signal I'm about to send my process group.
             */
            struct sigaction sigact;

            (void) sigemptyset(&sigact.sa_mask);
            sigact.sa_flags = 0;
            sigact.sa_handler = SIG_IGN;
            (void) sigaction(SIGTERM, &sigact, NULL );
        }

        /*
         * Signal my process group.
         */
        unotice("Terminating process group");
        (void) kill(0, SIGTERM);

        while (reap(-1, 0) > 0)
            ; /*empty*/

        /*
         * Delete the upstream LDM database.
         */
        (void) uldb_delete(NULL);

#if WANT_MULTICAST
        /*
         * Destroy the multicast LDM sender map.
         */
        msm_destroy();
#endif
    }

    /*
     * Free access-control-list resources.
     */
    lcf_free();

    /*
     * Close registry.
     */
    if (reg_close())
        log_log(LOG_ERR);

    /*
     * Terminate logging.
     */
    (void) closeulog();
}
Пример #22
0
static void
null_stats(void)
{
        unotice("  No feed statistics: never opened feed");
}
Пример #23
0
Файл: ldmd.c Проект: dgaer/LDM
/*
 * Handles an incoming RPC connection on a socket.  This method will fork(2)
 * a copy of this program, if appropriate, for handling incoming RPC messages.
 *
 * sock           The socket with the incoming RPC connection.
 */
static void handle_connection(
        int sock)
{
    struct sockaddr_in raddr;
    socklen_t len;
    int xp_sock;
    pid_t pid;
    SVCXPRT *xprt;
    int status = 1; /* EXIT_FAILURE assumed unless one_svc_run() success */
    peer_info* remote = get_remote();

    again: len = sizeof(raddr);
    (void) memset(&raddr, 0, len);

    xp_sock = accept(sock, (struct sockaddr *) &raddr, &len);

    (void) exitIfDone(0);

    if (xp_sock < 0) {
        if (errno == EINTR) {
            errno = 0;
            goto again;
        }
        /* else */
        serror("accept");
        return;
    }

    /*
     * Don't bother continuing if no more clients are allowed.
     */
    if (cps_count() >= maxClients) {
        setremote(&raddr, xp_sock);
        unotice("Denying connection from [%s] because too many clients",
                remote->astr);
        (void) close(xp_sock);
        return;
    }

    pid = ldmfork();
    if (pid == -1) {
        log_add("Couldn't fork process to handle incoming connection");
        log_log(LOG_ERR);
        /* TODO: try again?*/
        (void) close(xp_sock);
        return;
    }

    if (pid > 0) {
        /* parent */
        /* unotice("child %d", pid); */
        (void) close(xp_sock);

        if (cps_add(pid))
            serror("Couldn't add child PID to set");

        return;
    }
    /* else child */

    setremote(&raddr, xp_sock);

    /* Access control */
    if (!lcf_isHostOk(remote)) {
        ensureRemoteName(&raddr);
        if (!lcf_isHostOk(remote)) {
            if (remote->printname == remote->astr) {
                unotice("Denying connection from [%s] because not "
                        "allowed", remote->astr);
            }
            else {
                unotice("Denying connection from \"%s\" because not "
                        "allowed", remote_name());
            }

            /*
             * Try to tell the other guy.
             * TODO: Why doesn't this work?
             */
            xprt = svcfd_create(xp_sock, remote->sendsz, remote->recvsz);
            if (xprt != NULL ) {
                xprt->xp_raddr = raddr;
                xprt->xp_addrlen = (int) len;
                svcerr_weakauth(xprt);
                svc_destroy(xprt);
            }

            goto unwind_sock;
        }
    }
    /* else */

    endpriv();
    portIsMapped = 0; /* don't call pmap_unset() from child */

    (void) close(sock);

    /* Set the ulog identifier, optional. */
    set_abbr_ident(remote_name(), NULL );

    uinfo("Connection from %s", remote_name());

    xprt = svcfd_create(xp_sock, remote->sendsz, remote->recvsz);
    if (xprt == NULL ) {
        uerror("Can't create fd service.");
        goto unwind_sock;
    }
    /* hook up the remote address to the xprt. */
    /* xprt->xp_raddr = raddr; */
    xprt->xp_raddr = raddr;
    xprt->xp_addrlen = (int) len;

    if (!svc_register(xprt, LDMPROG, 4, ldmprog_4, 0)) {
        uerror("unable to register LDM-4 service.");
        svc_destroy(xprt);
        goto unwind_sock;
    }

    if (!svc_register(xprt, LDMPROG, FIVE, ldmprog_5, 0)) {
        uerror("unable to register LDM-5 service.");
        svc_destroy(xprt);
        goto unwind_sock;
    }

    if (!svc_register(xprt, LDMPROG, SIX, ldmprog_6, 0)) {
        uerror("unable to register LDM-6 service.");
        svc_destroy(xprt);
        goto unwind_sock;
    }

#if WANT_MULTICAST
    if (!svc_register(xprt, LDMPROG, SEVEN, ldmprog_7, 0)) {
        uerror("unable to register LDM-7 service.");
        svc_destroy(xprt);
        goto unwind_sock;
    }
#endif

    /*
     *  handle rpc requests
     */
    {
        const unsigned  TIMEOUT = 2*interval;

        status = one_svc_run(xp_sock, TIMEOUT);

        (void) exitIfDone(0);

        if (status == 0) {
            log_add("Done");
            log_log(LOG_INFO);
        }
        else if (status == ETIMEDOUT) {
            log_add("Connection from client LDM silent for %u seconds",
                    TIMEOUT);
            log_log(LOG_NOTICE);
        }
        else { /* connection to client lost */
            log_add("Connection with client LDM closed");
            log_log(LOG_INFO);
            status = 0; /* EXIT_SUCCESS */
        }
    }

    /* svc_destroy(xprt);  done by svc_getreqset() */

    unwind_sock: (void) close(xp_sock);

    exit(status);
}
Пример #24
0
/**
 * Reads a NOAAPORT data stream, creates LDM data-products from the stream, and
 * inserts the data-products into an LDM product-queue.  The NOAAPORT data
 * stream can take the form of multicast UDP packets from (for example) a
 * Novra S300 DVB-S2 receiver or the standard input stream.
 *
 * Usage:
 *     noaaportIngester [-l <em>log</em>] [-n|-v|-x] [-q <em>queue</em>] [-u <em>n</em>] [-m <em>mcastAddr</em>] [-I <em>iface</em>] [-b <em>npages</em>]\n
 *
 * Where:
 * <dl>
 *      <dt>-b <em>npages</em></dt>
 *      <dd>Allocate \e npages pages of memory for the internal buffer.</dd>
 *
 *      <dt>-I <em>iface</em></dt>
 *      <dd>Listen for multicast packets on interface \e iface.</dd>
 *
 *      <dt>-l <em>log</em></dt>
 *      <dd>Log to file \e log. The default is to use the system logging daemon
 *      if the current process is a daemon; otherwise, the standard error
 *      stream is used.</dd>
 *
 *      <dt>-m <em>mcastAddr</em></dt>
 *      <dd>Use the multicast address \e mcastAddr. The default is to
 *      read from the standard input stream.</dd>
 *
 *      <dt>-n</dt>
 *      <dd>Log messages of level NOTE and higher priority. Each data-product
 *      will generate a log message.</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.</dd>
 *
 *      <dt>-v</dt>
 *      <dd>Log messages of level INFO and higher priority.</dd>
 *
 *      <dt>-x</dt>
 *      <dd>Log messages of level DEBUG and higher priority.</dd>
 * </dl>
 *
 * If neither -n, -v, nor -x is specified, then logging will be restricted to
 * levels ERROR and WARN only.
 *
 * @retval 0 if successful.
 * @retval 1 if an error occurred. At least one error-message will be logged.
 */
int main(
    const int           argc,           /**< [in] Number of arguments */
    char* const         argv[])         /**< [in] Arguments */
{
    int                 status = 0;     /* default success */
    extern int          optind;
    extern int          opterr;
    int                 ch;
    const char* const   progName = ubasename(argv[0]);
    const char*         interface = NULL;
    int                 logmask = LOG_UPTO(LOG_WARNING);
    const unsigned      logOptions = LOG_CONS | LOG_PID;
    const char*         mcastSpec = NULL;
    const char*         prodQueuePath = NULL;
    size_t              npages = DEFAULT_NPAGES;
    Fifo*               fifo;
    int                 ttyFd = open("/dev/tty", O_RDONLY);
    int                 processPriority = 0;
    int                 idx;
    const char*         logPath = (-1 == ttyFd)
        ? NULL                          /* log to system logging daemon */
        : "-";                          /* log to standard error stream */

    (void)close(ttyFd);
    (void)setulogmask(logmask);

    status = initLogging(progName, logOptions, logFacility, logPath);
    opterr = 0;                         /* no error messages from getopt(3) */

    while (0 == status && (ch = getopt(argc, argv, "b:I:l:m:np:q:r:s:t:u:vx")) != -1)
    {
        switch (ch) {
            extern char*    optarg;
            extern int      optopt;

            case 'b': {
                unsigned long   n;

                if (sscanf(optarg, "%lu", &n) != 1) {
                    LOG_SERROR1("Couldn't decode FIFO size in pages: \"%s\"",
                            optarg);
                    status = 1;
                }
                else {
                    npages = n;
                }
                break;
            }
            case 'I':
                interface = optarg;
                break;
            case 'l':
                logPath = optarg;
                status = initLogging(progName, logOptions, logFacility,
                        logPath);
                break;
            case 'm':
                mcastSpec = optarg;
                break;
            case 'n':
                logmask |= LOG_MASK(LOG_NOTICE);
                (void)setulogmask(logmask);
                break;
            case 'p': {
                char* cp;

                errno = 0;
                processPriority = (int)strtol(optarg, &cp, 0);

                if (0 != errno) {
                    LOG_SERROR1("Couldn't decode priority \"%s\"", optarg);
                    log_log(LOG_ERR);
                }
                else {
                    if (processPriority < -20)
                        processPriority = -20;
                    else if (processPriority > 20)
                        processPriority = 20;
                }

                break;
            }
            case 'q':
                prodQueuePath = optarg;
                break;
            case 'r':
#ifdef RETRANS_SUPPORT
                retrans_xmit_enable = atoi(optarg);
                if(retrans_xmit_enable == 1)
                  retrans_xmit_enable = OPTION_ENABLE;
                else
                  retrans_xmit_enable = OPTION_DISABLE;
#endif
                break;
           case 's': {
#ifdef RETRANS_SUPPORT
			strcpy(sbn_channel_name, optarg);
                        if(!strcmp(optarg,NAME_SBN_TYP_GOES)) {
                                sbn_type = SBN_TYP_GOES;
                                break;
                        }
                        if(!strcmp(optarg,NAME_SBN_TYP_NOAAPORT_OPT)) {
                                sbn_type = SBN_TYP_NOAAPORT_OPT;
                                break;
                        }
                        if(!strcmp(optarg,"NWSTG")) {
                                sbn_type = SBN_TYP_NMC;
                                break;
                        }
                        if(!strcmp(optarg,NAME_SBN_TYP_NMC)) {
                                sbn_type = SBN_TYP_NMC;
                                break;
                        }
                        if(!strcmp(optarg,NAME_SBN_TYP_NMC2)) {
                                sbn_type = SBN_TYP_NMC2;
                                break;
                        }
                        if(!strcmp(optarg,NAME_SBN_TYP_NMC3)) {
                                sbn_type = SBN_TYP_NMC3;
                                break;
                        }
                        if(!strcmp(optarg,NAME_SBN_TYP_NWWS)) {
                                sbn_type = SBN_TYP_NWWS;
                                break;
                        }
                        if(!strcmp(optarg,NAME_SBN_TYP_ADD)) {
                                sbn_type = SBN_TYP_ADD;
                                break;
                        }
                        if(!strcmp(optarg,NAME_SBN_TYP_ENC)) {
                                sbn_type = SBN_TYP_ENC;
                                break;
                        }
                        if(!strcmp(optarg,NAME_SBN_TYP_EXP)) {
                                sbn_type = SBN_TYP_EXP;
                                break;
                        }
                        if(!strcmp(optarg,NAME_SBN_TYP_GRW)) {
                                sbn_type = SBN_TYP_GRW;
                                break;
                        }
                        if(!strcmp(optarg,NAME_SBN_TYP_GRE)) {
                                sbn_type = SBN_TYP_GRE;
                                break;
                        }
                        printf("Operator input: UNKNOWN type must be\n");
                        printf(" %s, %s, %s, %s, %s, %s, %s, %s, %s, %s  or %s \n",
                                NAME_SBN_TYP_NMC,
                                NAME_SBN_TYP_GOES,
                                NAME_SBN_TYP_NOAAPORT_OPT,
                                NAME_SBN_TYP_NMC2,
                                NAME_SBN_TYP_NMC3,
                                NAME_SBN_TYP_NWWS,
                                NAME_SBN_TYP_ADD,
                                NAME_SBN_TYP_ENC,
                                NAME_SBN_TYP_EXP,
                                NAME_SBN_TYP_GRW,
                                NAME_SBN_TYP_GRE);
#endif
                break;
              }
            case 't':
#ifdef RETRANS_SUPPORT
                strcpy(transfer_type, optarg);
                if(!strcmp(transfer_type,"MHS") || !strcmp(transfer_type,"mhs")){
                     /** Using MHS for communication with NCF  **/
                }else{
                     uerror("No other mechanism other than MHS is currently supported\n");
                     status  = 1;
                 }
#endif
                break;
            case 'u': {
                int         i = atoi(optarg);

                if (0 > i || 7 < i) {
                    LOG_START1("Invalid logging facility number: %d", i);
                    status = 1;
                }
                else {
                    static int  logFacilities[] = {LOG_LOCAL0, LOG_LOCAL1,
                        LOG_LOCAL2, LOG_LOCAL3, LOG_LOCAL4, LOG_LOCAL5,
                        LOG_LOCAL6, LOG_LOCAL7};

                    logFacility = logFacilities[i];

                    status = initLogging(progName, logOptions, logFacility,
                            logPath);
                }

                break;
            }
            case 'v':
                logmask |= LOG_MASK(LOG_INFO);
                (void)setulogmask(logmask);
                break;
            case 'x':
                logmask |= LOG_MASK(LOG_DEBUG);
                (void)setulogmask(logmask);
                break;
            default:
                optopt = ch;
                /*FALLTHROUGH*/
                /* no break */
            case '?': {
                uerror("Unknown option: \"%c\"", optopt);
                status = 1;
                break;
            }
        }                               /* option character switch */
    }                                   /* getopt() loop */

    if (0 == status) {
        if (optind < argc) {
            uerror("Extraneous command-line argument: \"%s\"",
                    argv[optind]);
            status = 1;
        }
    }

    if (0 != status) {
        uerror("Error decoding command-line");
        usage(progName);
    }
    else {
        unotice("Starting Up %s", PACKAGE_VERSION);
        unotice("%s", COPYRIGHT_NOTICE);

        if ((status = fifoNew(npages, &fifo)) != 0) {
            LOG_ADD0("Couldn't create FIFO");
            log_log(LOG_ERR);
        }
        else {
            LdmProductQueue*    prodQueue;

            if ((status = lpqGet(prodQueuePath, &prodQueue)) != 0) {
                LOG_ADD0("Couldn't open LDM product-queue");
                log_log(LOG_ERR);
            }
            else {
                if (NULL == mcastSpec) {
                    if (0 == (status = spawnProductMaker(NULL, fifo, prodQueue,
                                    &productMaker, &productMakerThread))) {
                        status = spawnFileReader(NULL, NULL, fifo, &reader,
                                &readerThread);
                    }
                }                               /* reading file */
                else {
                    pthread_attr_t  attr;

                    if (0 != (status = pthread_attr_init(&attr))) {
                        LOG_ERRNUM0(status,
                                "Couldn't initialize thread attribute");
                    }
                    else {
#ifndef _POSIX_THREAD_PRIORITY_SCHEDULING
                        uwarn("Can't adjust thread priorities due to lack of "
                                "necessary support from environment");
#else
                        /*
                         * In order to not miss any data, the reader thread
                         * should preempt the product-maker thread as soon as
                         * data is available and run as long as data is
                         * available.
                         */
                        const int           SCHED_POLICY = SCHED_FIFO;
                        struct sched_param  param;

                        param.sched_priority =
                            sched_get_priority_max(SCHED_POLICY) - 1;

                        (void)pthread_attr_setinheritsched(&attr,
                                PTHREAD_EXPLICIT_SCHED);
                        (void)pthread_attr_setschedpolicy(&attr, SCHED_POLICY);
                        (void)pthread_attr_setschedparam(&attr, &param);
                        (void)pthread_attr_setscope(&attr,
                                PTHREAD_SCOPE_SYSTEM);
#endif
#ifdef RETRANS_SUPPORT
                        if (retrans_xmit_enable == OPTION_ENABLE){
                         /* Copy mcastAddress needed to obtain the cpio entries */
                         strcpy(mcastAddr, mcastSpec);
                        }
#endif
                        if (0 == (status = spawnProductMaker(&attr, fifo,
                                        prodQueue, &productMaker,
                                        &productMakerThread))) {
#ifdef _POSIX_THREAD_PRIORITY_SCHEDULING
                            param.sched_priority++;
                            (void)pthread_attr_setschedparam(&attr, &param);
#endif
                            status = spawnMulticastReader(&attr, mcastSpec,
                                    interface, fifo, &reader, &readerThread);

                        }                       /* product-maker spawned */
                    }                           /* "attr" initialized */
                }                               /* reading multicast packets */

                if (0 != status) {
                    log_log(LOG_ERR);
                    status = 1;
                }
                else {
                    pthread_t   statThread;

                    (void)gettimeofday(&startTime, NULL);
                    reportTime = startTime;

                    (void)pthread_create(&statThread, NULL,
                            reportStatsWhenSignaled, NULL);

                    set_sigactions();

                    (void)pthread_join(readerThread, NULL);

                    status = readerStatus(reader);

                    (void)pthread_cancel(statThread);
                    (void)pthread_join(statThread, NULL);
                    (void)fifoCloseWhenEmpty(fifo);
                    (void)pthread_join(productMakerThread, NULL);

                    if (0 != status)
                        status = pmStatus(productMaker);

                    reportStats();
                    readerFree(reader);
#ifdef RETRANS_SUPPORT
					/** Release buffer allocated for retransmission **/
					if(retrans_xmit_enable == OPTION_ENABLE){
					  freeRetransMem();
					}
#endif
                }               /* "reader" spawned */

                (void)lpqClose(prodQueue);
            }                       /* "prodQueue" open */
        }                           /* "fifo" created */
    }                               /* command line decoded */

    return status;
}