Ejemplo n.º 1
0
/**
 * Locks a read/write lock for writing. Waits until the lock is available.
 * Reentrant.
 *
 * @retval RWL_SUCCESS  Success
 * @retval RWL_INVALID  Lock structure is invalid. log_add() called.
 * @retval RWL_EXIST    Lock is locked for reading and the current process is
 *                      the one that created it. log_add() called.
 * @retval RWL_SYSTEM   System error. See "errno". log_add() called. Resulting
 *                      state of the lock is unspecified.
 */
srwl_Status srwl_writeLock(
        srwl_Lock* const lock /**< [in/out] the lock to be locked */)
{
    srwl_Status status = vet(lock);

    if (RWL_SUCCESS == status) {
        if (0 < lock->numReadLocks) {
            LOG_ADD1("Lock is locked for reading; semId=%d", lock->semId);
            status = RWL_EXIST;
        }
        else if (0 < lock->numWriteLocks) {
            lock->numWriteLocks++;
            status = RWL_SUCCESS;
        }
        else {
            if (semop(lock->semId, writeLockOps,
                    sizeof(writeLockOps) / sizeof(writeLockOps[0])) == -1) {
                LOG_SERROR1("Couldn't lock for writing: semId=%d", lock->semId);
                status = RWL_SYSTEM;
            }
            else {
                lock->numWriteLocks = 1;
                status = RWL_SUCCESS;
            }
        }
    }

    return status;
}
Ejemplo n.º 2
0
static void
closeSocket(
    void* const arg)
{
    int sock = *(int*)arg;

    if (close(sock))
        LOG_SERROR1("Couldn't close socket %d", sock);
}
Ejemplo n.º 3
0
/**
 * Deletes a semaphore set.
 *
 * @retval RWL_SUCCESS  Success.
 * @retval RWL_SYSTEM   System error. See "errno". log_add() called.
 */
static srwl_Status deleteSemSet(
        const int semId /**< [in] semaphore set identifier */)
{
    if (semctl(semId, 0, IPC_RMID) == 0)
        return RWL_SUCCESS;

    LOG_SERROR1("Couldn't delete semaphore set: semId=%d", semId);
    return RWL_SYSTEM;
}
Ejemplo n.º 4
0
/**
 * Locks a read/write lock for reading. Waits until the lock is available.
 * Reentrant.
 *
 * @retval RWL_SUCCESS  Success
 * @retval RWL_INVALID  Lock structure is invalid. log_add() called.
 * @retval RWL_EXIST    Lock is locked for writing and the current process is
 *                      the one that created it. log_add() called.
 * @retval RWL_SYSTEM   System error. See "errno". log_add() called. Resulting
 *                      state of the lock is unspecified.
 */
srwl_Status srwl_readLock(
        srwl_Lock* const lock /**< [in/out] the lock to be locked */)
{
    srwl_Status status = vet(lock);

    if (RWL_SUCCESS == status) {
        if (0 < lock->numWriteLocks) {
            LOG_ADD1("Lock is locked for writing; semId=%d", lock->semId);
            status = RWL_EXIST;
        }
        else if (0 < lock->numReadLocks) {
            lock->numReadLocks++;
            status = RWL_SUCCESS;
        }
        else {
            /*
             * A read-lock is obtained in two steps because the semop(2)
             * specification doesn't indicate that the operations array is
             * executed sequentially.
             */
            if (semop(lock->semId, readLockOps,
                    sizeof(readLockOps) / sizeof(readLockOps[0])) == -1) {
                LOG_SERROR1("Couldn't lock for reading: semId=%d", lock->semId);
                status = RWL_SYSTEM;
            }
            else if (semop(lock->semId, shareOps,
                    sizeof(shareOps) / sizeof(shareOps[0])) == -1) {
                LOG_SERROR1("Couldn't share read-lock: semId=%d", lock->semId);
                status = RWL_SYSTEM;
            }
            else {
                lock->numReadLocks = 1;
                status = RWL_SUCCESS;
            }
        }
    }

    return status;
}
Ejemplo n.º 5
0
/**
 * Unlocks a read/write lock. Must be called as many times as the lock was
 * locked before the lock will be truly unlocked.
 *
 * @retval RWL_SUCCESS  Success
 * @retval RWL_INVALID  Lock structure is invalid. log_add() called.
 * @retval RWL_SYSTEM   System error. See "errno". log_add() called. Resulting
 *                      state of the lock is unspecified.
 */
srwl_Status srwl_unlock(
        srwl_Lock* const lock /**< [in/out] the lock to be unlocked */)
{
    srwl_Status status = vet(lock);

    if (RWL_SUCCESS == status) {
        if (1 < lock->numWriteLocks) {
            lock->numWriteLocks--;
        }
        else if (1 == lock->numWriteLocks) {
            if (semop(lock->semId, writeUnlockOps,
                    sizeof(writeUnlockOps) / sizeof(writeUnlockOps[0])) == -1) {
                LOG_SERROR1("Couldn't unlock write-lock: semId=%d", lock->semId);
                status = RWL_SYSTEM;
            }
            else {
                lock->numWriteLocks--;
            }
        }
        else if (1 < lock->numReadLocks) {
            lock->numReadLocks--;
        }
        else if (1 == lock->numReadLocks) {
            if (semop(lock->semId, readUnlockOps,
                    sizeof(readUnlockOps) / sizeof(readUnlockOps[0])) == -1) {
                LOG_SERROR1("Couldn't unlock read-lock: semId=%d", lock->semId);
                status = RWL_SYSTEM;
            }
            else {
                lock->numReadLocks--;
            }
        }
    }

    return status;
}
Ejemplo n.º 6
0
/**
 * Unconditionally deletes a read/write lock by IPC key. The Semaphore on
 * which the lock is based is deleted.
 *
 * @param key           The IPC key
 * @retval RWL_SUCCESS  Success
 * @retval RWL_EXIST    The key has no associated read/write lock
 * @retval RWL_SYSTEM   System error. log_add() called.
 */
srwl_Status srwl_deleteByKey(
        const key_t key)
{
    int status = semget(key, 0, read_write);

    if (-1 == status) {
        LOG_SERROR0("Couldn't get semaphore set");
        status = (ENOENT == errno) ? RWL_EXIST : RWL_SYSTEM;
    }
    else if (semctl(status, 0, IPC_RMID)) {
        LOG_SERROR1("Couldn't delete existing semaphore set %d", status);
        status = RWL_SYSTEM;
    }
    else {
        status = RWL_SUCCESS;
    }

    return status;
}
Ejemplo n.º 7
0
/**
 * Creates a read/write lock based on creating a new semaphore set. Any previous
 * semaphore set will be deleted.
 *
 * @retval RWL_SUCCESS  Success
 * @retval RWL_SYSTEM   System error. See "errno". log_add() called.
 */
static srwl_Status createLock(
        const key_t key /**< [in] the key associated with the semaphore */,
        int* const semId /**< [out] pointer to the semaphore identifier */)
{
    srwl_Status status;
    int id;

    (void) deleteSemSet(semget(key, 0, read_write));
    log_clear();

    id = semget(key, SI_NUM_SEMS, IPC_CREAT | IPC_EXCL | read_write);

    if (-1 == id) {
        LOG_SERROR0("Couldn't create semaphore set");
        status = RWL_SYSTEM;
    }
    else {
        unsigned short semVal[SI_NUM_SEMS];
        union semun {
            int val; /* Value for SETVAL */
            struct semid_ds *buf; /* Buffer for IPC_STAT, IPC_SET */
            unsigned short *array; /* Array for GETALL, SETALL */
        } arg;

        semVal[SI_LOCK] = 1;
        semVal[SI_NUM_READERS] = 0;
        arg.array = semVal;

        if (semctl(id, 0, SETALL, arg) == -1) {
            LOG_SERROR1("Couldn't initialize semaphore set: semId=%d", id);
            (void) deleteSemSet(id);
            status = RWL_SYSTEM;
        }
        else {
            *semId = id;
            status = RWL_SUCCESS;
        }
    }

    return status;
}
Ejemplo n.º 8
0
/*
 * Adds an entry to a child-map.
 *
 * @retval 0    Success
 * @retval 1    Usage error. \c log_start() called.
 * @retval 2    O/S failure. \c log_start() called.
 */
int cm_add_argv(
    ChildMap* const map,    /**< [in/out] Pointer to the child-map */
    const pid_t     pid,    /**< [in] Process ID of the child.
                             *   Must not already exist in map. */
    char** const    argv)   /**< [in] Command-line of the child in
                             *   argument vector form. Last pointer
                             *   must be NULL. The strings are
                             *   defensively copied. */
{
    int                 status = 0;     /* success */

    if (NULL == map || NULL == argv) {
        status = 1;
    }
    else {
        int     i;

        (void)strBuf_clear(map->buf);

        for (i = 0; NULL != argv[i]; i++) {
            if (0 < i)
                (void)strBuf_appendString(map->buf, " ");
            if (0 != strBuf_appendString(map->buf, argv[i])) {
                LOG_SERROR1(
                        "Couldn't append to command-line buffer: \"%s\"",
                        argv[i]);
                status = 2;
                break;
            }
        }

        if (0 == status) {
            const char* command = strBuf_toString(map->buf);

            status = cm_add_string(map, pid, command);
        }
    }                                   /* argv != NULL */

    return status;
}
Ejemplo n.º 9
0
/**
 * Initializes a lock.
 *
 * @retval RWL_SUCCESS  Success.
 * @retval RWL_EXIST    "create" is false and the semaphore set doesn't exist.
 *                      log_add() called.
 * @retval RWL_SYSTEM   System error. log_add() called.
 */
static srwl_Status initLock(
        const int create /**< [in] Whether to create the lock. If true, then
         any previous lock will be deleted. */,
        int key /**< [in] IPC key for the semaphore */,
        srwl_Lock** const lock /**< [out] address of pointer to lock */)
{
    srwl_Status status;
    srwl_Lock* lck;

    if (!isInitialized) {
        struct sembuf acquireLock;
        struct sembuf releaseLock;

        acquireLock.sem_num = SI_LOCK;
        acquireLock.sem_op = -1;
        acquireLock.sem_flg = SEM_UNDO; /* release lock upon exit */

        releaseLock.sem_num = SI_LOCK;
        releaseLock.sem_op = 1;
        releaseLock.sem_flg = SEM_UNDO; /* undo acquireLock undo */

        writeLockOps[0] = acquireLock;
        writeLockOps[1].sem_num = SI_NUM_READERS;
        writeLockOps[1].sem_op = 0;
        writeLockOps[1].sem_flg = 0;

        readLockOps[0] = acquireLock;
        readLockOps[1].sem_num = SI_NUM_READERS;
        readLockOps[1].sem_op = 1;
        readLockOps[1].sem_flg = SEM_UNDO; /* decrement #readers upon exit */

        shareOps[0] = releaseLock;

        writeUnlockOps[0] = releaseLock;

        readUnlockOps[0].sem_num = SI_NUM_READERS;
        readUnlockOps[0].sem_op = -1;
        readUnlockOps[0].sem_flg = SEM_UNDO; /* undo readLockOps[1] undo */

        {
            mode_t um = umask(0);

            umask(um);

            read_write = 0666 & ~um;
        }

        isInitialized = 1;
    }

    lck = (srwl_Lock*) malloc(sizeof(srwl_Lock));

    if (NULL == lck) {
        LOG_SERROR1("Couldn't allocate %lu bytes for lock",
                (unsigned long) sizeof(srwl_Lock));
        status = RWL_SYSTEM;
    }
    else {
        int semId;

        status = create ? createLock(key, &semId) : getLock(key, &semId);

        if (RWL_SUCCESS != status) {
            free(lck);
        }
        else {
            lck->semId = semId;
            lck->pid = getpid();
            lck->isValid = VALID_STRING;
            lck->numReadLocks = 0;
            lck->numWriteLocks = 0;
            *lock = lck;
        }
    } /* "lck" allocated */

    return status;
}
Ejemplo n.º 10
0
/*ARGSUSED*/
static int
exec_prodput(
     const product*     prod,
     int                argc,
     char**             argv,
     const void*        xprod,
     size_t             xlen)
{
    pid_t       pid = 0;

    if (NULL == execMap) {
        execMap = cm_new();

        if (NULL == execMap) {
            LOG_ADD0("Couldn't create child-process map for EXEC entries");
            log_log(LOG_ERR);
            pid = -1;
        }
    }                                   /* child-process map not allocated */

    if (0 == pid) {
        int     waitOnChild = 0;        /* default is not to wait */

        if (strcmp(argv[0], "-wait") == 0) {
            waitOnChild = 1;            /* => wait for child */
            argc--; argv++;
        }

        pid = ldmfork();
        if (-1 == pid) {
            LOG_SERROR0("Couldn't fork EXEC process");
            log_log(LOG_ERR);
        }
        else {
            if (0 == pid) {
                /*
                 * Child process.
                 *
                 * Detach the child process from the parents process group??
                 *
                 * (void) setpgid(0,0);
                 */
                const unsigned  ulogOptions = ulog_get_options();
                const char*     ulogIdent = getulogident();
                const unsigned  ulogFacility = getulogfacility();
                const char*     ulogPath = getulogpath();

                (void)signal(SIGTERM, SIG_DFL);
                (void)pq_close(pq);

                /*
                 * It is assumed that the standard input, output, and error
                 * streams are correctly established and should not be
                 * modified.
                 */

                /*
                 * Don't let the child process get any inappropriate privileges.
                 */
                endpriv();

                (void) execvp(argv[0], argv);
                openulog(ulogIdent, ulogOptions, ulogFacility, ulogPath);
                LOG_SERROR1("Couldn't execute command \"%s\"", argv[0]);
                log_log(LOG_ERR);
                exit(EXIT_FAILURE);
            }                           /* child process */
            else {
                /*
                 * Parent process.
                 */
                (void)cm_add_argv(execMap, pid, argv);

                if (!waitOnChild) {
                    udebug("    exec %s[%d]", argv[0], pid);
                }
                else {
                    udebug("    exec -wait %s[%d]", argv[0], pid);
                    (void)reap(pid, 0);
                }
            }
        }                               /* child-process forked */
    }                                   /* child-process map allocated */

    return -1 == pid ? -1 : 1;
}
Ejemplo n.º 11
0
/*
 * Returns a new instance of an LDM proxy. Can take a while because it
 * establishes a connection to the LDM.
 *
 * Arguments:
 *      host            Identifier of the host on which an LDM server is
 *                      running.
 *      instance        Pointer to a pointer to the new instance. "*instance"
 *                      is set upon successful return.
 * Returns:
 *      0               Success. "*instance" is set.
 *      LP_SYSTEM       System error. "log_start()" called.
 *      LP_TIMEDOUT     Connection attempt timed-out. "log_start()" called.
 *      LP_HOSTUNREACH  Host is unreachable. "log_start()" called.
 *      LP_RPC_ERROR    RPC error. "log_start()" called.
 *      LP_LDM_ERROR    LDM error. "log_start()" called.
 */
LdmProxyStatus
lp_new(
    const char* const   host,
    LdmProxy** const    instance)
{
    LdmProxyStatus      status = 0;     /* success */
    size_t              nbytes = sizeof(LdmProxy);
    LdmProxy*           proxy = (LdmProxy*)malloc(nbytes);

    if (NULL == proxy) {
        log_serror("Couldn't allocate %lu bytes for new LdmProxy", nbytes);
        status = LP_SYSTEM;
    }
    else {
        proxy->host = strdup(host);

        if (NULL == proxy->host) {
            LOG_SERROR1("Couldn't duplicate string \"%s\"", host);
            status = LP_SYSTEM;
        }
        else {
            CLIENT*         clnt = NULL;
            ErrorObj*       error = ldm_clnttcp_create_vers(host, LDM_PORT, 6,
                    &clnt, NULL, NULL);

            if (!error) {
                proxy->version = 6;
                proxy->hiya = my_hiya_6;
                proxy->send = my_send_6;
                proxy->flush = my_flush_6;
            }
            else if (LDM_CLNT_BAD_VERSION == err_code(error)) {
                /* Couldn't connect due to protocol version. */
                err_free(error);

                error = ldm_clnttcp_create_vers(host, LDM_PORT, 5,
                        &clnt, NULL, NULL);

                if (!error) {
                    proxy->version = 5;
                    proxy->hiya = my_hiya_5;
                    proxy->send = my_send_5;
                    proxy->flush = my_flush_5;
                }
            }

            if (error) {
                LOG_START1("%s", err_message(error));
                err_free(error);
                free(proxy->host);
                status = convertStatus(error);
            }
            else {
                proxy->clnt = clnt;
                proxy->rpcTimeout = rpcTimeout;
            }
        }                                       /* "proxy->host" allocated */

        if (LP_OK == status) {
            *instance = proxy;
        }
        else {
            free(proxy);
        }
    }                                           /* "proxy" allocated */

    return status;
}
Ejemplo n.º 12
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;
}