Example #1
0
static int timeRegister(void)
{
    /* If TIMEZONE not defined, set it from EPICS_TIMEZONE */
    if (getenv("TIMEZONE") == NULL) {
        const char *timezone = envGetConfigParamPtr(&EPICS_TIMEZONE);
        if (timezone == NULL) {
            printf("timeRegister: No Time Zone Information\n");
        } else {
            epicsEnvSet("TIMEZONE", timezone);
        }
    }

    // Define EPICS_TS_FORCE_NTPTIME to force use of NTPTime provider
    bool useNTP = getenv("EPICS_TS_FORCE_NTPTIME") != NULL;

    if (!useNTP &&
        (taskNameToId(sntp_sync_task) != ERROR ||
         taskNameToId(ntp_daemon) != ERROR)) {
        // A VxWorks 6 SNTP/NTP sync task is running
        struct timespec clockNow;

        useNTP = clock_gettime(CLOCK_REALTIME, &clockNow) != OK ||
            clockNow.tv_sec < BUILD_TIME;
            // Assumes VxWorks and the host OS have the same epoch
    }

    if (useNTP) {
        // Start NTP first so it can be used to sync SysTime
        NTPTime_Init(100);
        ClockTime_Init(CLOCKTIME_SYNC);
    } else {
        ClockTime_Init(CLOCKTIME_NOSYNC);
    }
    return 1;
}
/*
 *  caPutLogClientInit()
 */
int epicsShareAPI caPutLogClientInit (const char *addr_str)
{
    int status;
    struct sockaddr_in saddr;
    long default_port = 7011;

    if (caPutLogClient!=NULL) {
        return caPutLogSuccess;
    }

    if (!addr_str || !addr_str[0]) {
        addr_str = envGetConfigParamPtr(&EPICS_CA_PUT_LOG_ADDR);
    }

    status = aToIPAddr (addr_str, default_port, &saddr);
    if (status<0) {
        fprintf (stderr, "caPutLog: bad address or host name\n");
        return caPutLogError;
    }

    caPutLogClient = logClientCreate (saddr.sin_addr, ntohs(saddr.sin_port));

    if (!caPutLogClient) {
        return caPutLogError;
    }
    else {
        return caPutLogSuccess;
    }
}
string SystemConfigurationImpl::getPropertyAsString(const string &name, const string &defaultValue)
{
	strncpy(_envParam.name,name.c_str(),name.length() + 1);
	const char* val = envGetConfigParamPtr(&_envParam);
	if(val != NULL)
	{
		return _properties->getProperty(name, string(val));
	}
	return _properties->getProperty(name, defaultValue);
}
Example #4
0
/*+/subr**********************************************************************
* NAME	envPrtConfigParam - print value of a configuration parameter
*
* DESCRIPTION
*	Prints the value of a configuration parameter.
*
* RETURNS
*	0
*
* EXAMPLE
* 1.	Print the value for the EPICS-defined environment parameter
*	EPICS_TS_NTP_INET.
*
*	#include "envDefs.h"
*
*	envPrtConfigParam(&EPICS_TS_NTP_INET);
*
*-*/
long epicsShareAPI envPrtConfigParam(
const ENV_PARAM *pParam)	/* pointer to config param structure */
{
    const char *pVal;

    pVal = envGetConfigParamPtr(pParam);
    if (pVal == NULL)
	fprintf(stdout, "%s is undefined\n", pParam->name);
    else
	fprintf(stdout,"%s: %s\n", pParam->name, pVal);
    return 0;
}
Example #5
0
void osdNTPInit(void)
{
    pserverAddr = envGetConfigParamPtr(&EPICS_TS_NTP_INET);
    if (!pserverAddr) { /* use the boot host */
        BOOT_PARAMS bootParms;
        static char host_addr[BOOT_ADDR_LEN];

        bootStringToStruct(sysBootLine, &bootParms);
        /* bootParms.had = host IP address */
        strncpy(host_addr, bootParms.had, BOOT_ADDR_LEN);
        pserverAddr = host_addr;
    }
}
Example #6
0
/*
 * Create a command-line context
 */
void * epicsShareAPI
epicsReadlineBegin(FILE *in)
{
    struct readlineContext *readlineContext = calloc(1, sizeof(*readlineContext));

    if (readlineContext) {
        readlineContext->in = in;
        readlineContext->line = NULL;
        if (!envGetConfigParamPtr(&IOCSH_HISTEDIT_DISABLE))
            osdReadlineBegin(readlineContext);
    }
    return readlineContext;
}
Example #7
0
/*+/subr**********************************************************************
* NAME	envGetConfigParam - get value of a configuration parameter
*
* DESCRIPTION
*	Gets the value of a configuration parameter and copies it
*	into the caller's buffer.  If the configuration parameter
*	isn't found in the environment, then the default value for
*	the parameter is copied.  If no parameter is found and there
*	is no default, then '\0' is copied and NULL is returned.
*
* RETURNS
*	pointer to callers buffer, or
*	NULL if no parameter value or default value was found
*
* EXAMPLES
* 1.	Get the value for the EPICS-defined environment parameter
*	EPICS_TS_NTP_INET.
*
*	#include "envDefs.h"
*	char       temp[80];
*
*	printf("NTP time server is: %s\n",
*			envGetConfigParam(&EPICS_TS_NTP_INET, sizeof(temp), temp));
*
* 2.	Get the value for the DISPLAY environment parameter under UNIX.
*
*	#include "envDefs.h"
*	char       temp[80];
*	ENV_PARAM  display={"DISPLAY",""}
*
*	if (envGetConfigParam(&display, sizeof(temp), temp) == NULL)
*	    printf("DISPLAY isn't defined\n");
*	else
*	    printf("DISPLAY is %s\n", temp);
*
*-*/
char * epicsShareAPI envGetConfigParam(
const ENV_PARAM *pParam,/* I pointer to config param structure */
int	bufDim,		/* I dimension of parameter buffer */
char	*pBuf		/* I pointer to parameter buffer  */
)
{
    const char *pEnv;		/* pointer to environment string */

    pEnv = envGetConfigParamPtr(pParam);
    if (!pEnv) {
	return NULL;
    }

    strncpy(pBuf, pEnv, bufDim-1);
    pBuf[bufDim-1] = '\0';

    return pBuf;
}
Example #8
0
/*
 * addAddrToChannelAccessAddressList ()
 */
extern "C" void epicsShareAPI addAddrToChannelAccessAddressList 
    ( ELLLIST *pList, const ENV_PARAM *pEnv, 
    unsigned short port, int ignoreNonDefaultPort )
{
    osiSockAddrNode *pNewNode;
    const char *pStr;
    const char *pToken;
    struct sockaddr_in addr;
    char buf[32u]; /* large enough to hold an IP address */
    int status;

    pStr = envGetConfigParamPtr (pEnv);
    if (!pStr) {
        return;
    }

    while ( ( pToken = getToken (&pStr, buf, sizeof (buf) ) ) ) {
        status = aToIPAddr ( pToken, port, &addr );
        if (status<0) {
            fprintf ( stderr, "%s: Parsing '%s'\n", __FILE__, pEnv->name);
            fprintf ( stderr, "\tBad internet address or host name: '%s'\n", pToken);
            continue;
        }

        if ( ignoreNonDefaultPort && ntohs ( addr.sin_port ) != port ) {
            continue;
        }

        pNewNode = (osiSockAddrNode *) calloc (1, sizeof(*pNewNode));
        if (pNewNode==NULL) {
            fprintf ( stderr, "addAddrToChannelAccessAddressList(): no memory available for configuration\n");
            return;
        }

        pNewNode->addr.ia = addr;

		/*
		 * LOCK applied externally
		 */
        ellAdd (pList, &pNewNode->node);
    }

    return;
}
Example #9
0
/*
 *
 *  req_server()
 *
 *  CA server task
 *
 *  Waits for connections at the CA port and spawns a task to
 *  handle each of them
 *
 */
static void req_server (void *pParm)
{
    unsigned priorityOfSelf = epicsThreadGetPrioritySelf ();
    unsigned priorityOfBeacons;
    epicsThreadBooleanStatus tbs;
    struct sockaddr_in serverAddr;  /* server's address */
    osiSocklen_t addrSize;
    int status;
    SOCKET clientSock;
    epicsThreadId tid;
    int portChange;

    epicsSignalInstallSigPipeIgnore ();

    taskwdInsert ( epicsThreadGetIdSelf (), NULL, NULL );
    
    rsrvCurrentClient = epicsThreadPrivateCreate ();

    if ( envGetConfigParamPtr ( &EPICS_CAS_SERVER_PORT ) ) {
        ca_server_port = envGetInetPortConfigParam ( &EPICS_CAS_SERVER_PORT, 
            (unsigned short) CA_SERVER_PORT );
    }
    else {
        ca_server_port = envGetInetPortConfigParam ( &EPICS_CA_SERVER_PORT, 
            (unsigned short) CA_SERVER_PORT );
    }

    if (IOC_sock != 0 && IOC_sock != INVALID_SOCKET) {
        epicsSocketDestroy ( IOC_sock );
    }
    
    /*
     * Open the socket. Use ARPA Internet address format and stream
     * sockets. Format described in <sys/socket.h>.
     */
    if ( ( IOC_sock = epicsSocketCreate (AF_INET, SOCK_STREAM, 0) ) == INVALID_SOCKET ) {
        errlogPrintf ("CAS: Socket creation error\n");
        epicsThreadSuspendSelf ();
    }

    epicsSocketEnableAddressReuseDuringTimeWaitState ( IOC_sock );

    /* Zero the sock_addr structure */
    memset ( (void *) &serverAddr, 0, sizeof ( serverAddr ) );
    serverAddr.sin_family = AF_INET;
    serverAddr.sin_addr.s_addr = htonl (INADDR_ANY); 
    serverAddr.sin_port = htons ( ca_server_port );

    /* get server's Internet address */
    status = bind ( IOC_sock, (struct sockaddr *) &serverAddr, sizeof ( serverAddr ) );
	if ( status < 0 ) {
		if ( SOCKERRNO == SOCK_EADDRINUSE ) {
			/*
			 * enable assignment of a default port
			 * (so the getsockname() call below will
			 * work correctly)
			 */
			serverAddr.sin_port = ntohs (0);
			status = bind ( IOC_sock, 
                (struct sockaddr *) &serverAddr, sizeof ( serverAddr ) );
		}
		if ( status < 0 ) {
            char sockErrBuf[64];
            epicsSocketConvertErrnoToString ( 
                sockErrBuf, sizeof ( sockErrBuf ) );
            errlogPrintf ( "CAS: Socket bind error was \"%s\"\n",
                sockErrBuf );
            epicsThreadSuspendSelf ();
		}
        portChange = 1;
	}
    else {
        portChange = 0;
    }

	addrSize = ( osiSocklen_t ) sizeof ( serverAddr );
	status = getsockname ( IOC_sock, 
			(struct sockaddr *)&serverAddr, &addrSize);
	if ( status ) {
        char sockErrBuf[64];
        epicsSocketConvertErrnoToString ( 
            sockErrBuf, sizeof ( sockErrBuf ) );
		errlogPrintf ( "CAS: getsockname() error %s\n", 
			sockErrBuf );
        epicsThreadSuspendSelf ();
	}

    ca_server_port = ntohs (serverAddr.sin_port);

    if ( portChange ) {
        errlogPrintf ( "cas warning: Configured TCP port was unavailable.\n");
        errlogPrintf ( "cas warning: Using dynamically assigned TCP port %hu,\n", 
            ca_server_port );
        errlogPrintf ( "cas warning: but now two or more servers share the same UDP port.\n");
        errlogPrintf ( "cas warning: Depending on your IP kernel this server may not be\n" );
        errlogPrintf ( "cas warning: reachable with UDP unicast (a host's IP in EPICS_CA_ADDR_LIST)\n" );
    }

    /* listen and accept new connections */
    if ( listen ( IOC_sock, 20 ) < 0 ) {
        errlogPrintf ("CAS: Listen error\n");
        epicsSocketDestroy (IOC_sock);
        epicsThreadSuspendSelf ();
    }

    tbs  = epicsThreadHighestPriorityLevelBelow ( priorityOfSelf, &priorityOfBeacons );
    if ( tbs != epicsThreadBooleanStatusSuccess ) {
        priorityOfBeacons = priorityOfSelf;
    }

    beacon_startStopEvent = epicsEventMustCreate(epicsEventEmpty);
    beacon_ctl = ctlPause;

    tid = epicsThreadCreate ( "CAS-beacon", priorityOfBeacons,
        epicsThreadGetStackSize (epicsThreadStackSmall),
        rsrv_online_notify_task, 0 );
    if ( tid == 0 ) {
        epicsPrintf ( "CAS: unable to start beacon thread\n" );
    }

    epicsEventMustWait(beacon_startStopEvent);
    epicsEventSignal(castcp_startStopEvent);

    while (TRUE) {
        struct sockaddr     sockAddr;
        osiSocklen_t        addLen = sizeof(sockAddr);

        while (castcp_ctl == ctlPause) {
            epicsThreadSleep(0.1);
        }

        clientSock = epicsSocketAccept ( IOC_sock, &sockAddr, &addLen );
        if ( clientSock == INVALID_SOCKET ) {
            char sockErrBuf[64];
            epicsSocketConvertErrnoToString ( 
                sockErrBuf, sizeof ( sockErrBuf ) );
            errlogPrintf("CAS: Client accept error was \"%s\"\n",
                sockErrBuf );
            epicsThreadSleep(15.0);
            continue;
        } 
        else {
            epicsThreadId id;
            struct client *pClient;

            /* socket passed in is closed if unsuccessful here */
            pClient = create_tcp_client ( clientSock );
            if ( ! pClient ) {
                epicsThreadSleep ( 15.0 );
                continue;
            }

            LOCK_CLIENTQ;
            ellAdd ( &clientQ, &pClient->node );
            UNLOCK_CLIENTQ;

            id = epicsThreadCreate ( "CAS-client", epicsThreadPriorityCAServerLow,
                    epicsThreadGetStackSize ( epicsThreadStackBig ),
                    camsgtask, pClient );
            if ( id == 0 ) {
                LOCK_CLIENTQ;
                ellDelete ( &clientQ, &pClient->node );
                UNLOCK_CLIENTQ;
                destroy_tcp_client ( pClient );
                errlogPrintf ( "CAS: task creation for new client failed\n" );
                epicsThreadSleep ( 15.0 );
                continue;
            }
        }
    }
}
Example #10
0
/*
 * RTEMS Startup task
 */
rtems_task
Init (rtems_task_argument ignored)
{
    int                 i;
    char               *argv[3]         = { NULL, NULL, NULL };
    char               *cp;
    rtems_task_priority newpri;
    rtems_status_code   sc;
    rtems_time_of_day   now;

    /*
     * Explain why we're here
     */
    logReset();

    /*
     * Architecture-specific hooks
     */
    if (epicsRtemsInitPreSetBootConfigFromNVRAM(&rtems_bsdnet_config) != 0)
        delayedPanic("epicsRtemsInitPreSetBootConfigFromNVRAM");
    if (rtems_bsdnet_config.bootp == NULL) {
        extern void setBootConfigFromNVRAM(void);
        setBootConfigFromNVRAM();
    }
    if (epicsRtemsInitPostSetBootConfigFromNVRAM(&rtems_bsdnet_config) != 0)
        delayedPanic("epicsRtemsInitPostSetBootConfigFromNVRAM");

    /*
     * Override RTEMS configuration
     */
    rtems_task_set_priority (
                     RTEMS_SELF,
                     epicsThreadGetOssPriorityValue(epicsThreadPriorityIocsh),
                     &newpri);

    /*
     * Create a reasonable environment
     */
    initConsole ();
    putenv ("TERM=xterm");
    putenv ("IOCSH_HISTSIZE=20");

    /*
     * Display some OS information
     */
    printf("\n***** RTEMS Version: %s *****\n",
        rtems_get_version_string());

    /*
     * Start network
     */
    if ((cp = getenv("EPICS_TS_NTP_INET")) != NULL)
        rtems_bsdnet_config.ntp_server[0] = cp;
    if (rtems_bsdnet_config.network_task_priority == 0)
    {
        unsigned int p;
        if (epicsThreadHighestPriorityLevelBelow(epicsThreadPriorityScanLow, &p)
                                            == epicsThreadBooleanStatusSuccess)
        {
            rtems_bsdnet_config.network_task_priority = epicsThreadGetOssPriorityValue(p);
        }
    }
    printf("\n***** Initializing network *****\n");
    rtems_bsdnet_initialize_network();
    initialize_remote_filesystem(argv, initialize_local_filesystem(argv));

    /*
     * More environment: iocsh prompt and hostname
     */
    {
        char hostname[1024];
        gethostname(hostname, 1023);
        char *cp = mustMalloc(strlen(hostname)+3, "iocsh prompt");
        sprintf(cp, "%s> ", hostname);
        epicsEnvSet ("IOCSH_PS1", cp);
        epicsEnvSet("IOC_NAME", hostname);
    }

    /*
     * Use BSP-supplied time of day if available otherwise supply default time.
     * It is very likely that other time synchronization facilities in EPICS
     * will soon override this value.
     */
    if (rtems_clock_get(RTEMS_CLOCK_GET_TOD,&now) != RTEMS_SUCCESSFUL) {
        now.year = 2001;
        now.month = 1;
        now.day = 1;
        now.hour = 0;
        now.minute = 0;
        now.second = 0;
        now.ticks = 0;
        if ((sc = rtems_clock_set (&now)) != RTEMS_SUCCESSFUL)
            printf ("***** Can't set time: %s\n", rtems_status_text (sc));
    }
    if (getenv("TZ") == NULL) {
        const char *tzp = envGetConfigParamPtr(&EPICS_TIMEZONE);
        if (tzp == NULL) {
            printf("Warning -- no timezone information available -- times will be displayed as GMT.\n");
        }
        else {
            char tz[10];
            int minWest, toDst = 0, fromDst = 0;
            if(sscanf(tzp, "%9[^:]::%d:%d:%d", tz, &minWest, &toDst, &fromDst) < 2) {
                printf("Warning: EPICS_TIMEZONE (%s) unrecognizable -- times will be displayed as GMT.\n", tzp);
            }
            else {
                char posixTzBuf[40];
                char *p = posixTzBuf;
                p += sprintf(p, "%cST%d:%.2d", tz[0], minWest/60, minWest%60);
                if (toDst != fromDst)
                    p += sprintf(p, "%cDT", tz[0]);
                epicsEnvSet("TZ", posixTzBuf);
            }
        }
    }
    tzset();
    osdTimeRegister();

    /*
     * Run the EPICS startup script
     */
    printf ("***** Starting EPICS application *****\n");
    iocshRegisterRTEMS ();
    set_directory (argv[1]);
    epicsEnvSet ("IOC_STARTUP_SCRIPT", argv[1]);
    atexit(exitHandler);
    i = main ((sizeof argv / sizeof argv[0]) - 1, argv);
    printf ("***** IOC application terminating *****\n");
    epicsThreadSleep(1.0);
    epicsExit(0);
}
Example #11
0
/*
 * The body of the command interpreter
 */
static int
iocshBody (const char *pathname, const char *commandLine)
{
    FILE *fp = NULL;
    const char *filename = NULL;
    int icin, icout;
    char c;
    int quote, inword, backslash;
    const char *raw = NULL;;
    char *line = NULL;
    int lineno = 0;
    int argc;
    char **argv = NULL;
    int argvCapacity = 0;
    struct iocshRedirect *redirects = NULL;
    struct iocshRedirect *redirect = NULL;
    int sep;
    const char *prompt = NULL;
    const char *ifs = " \t(),\r";
    iocshArgBuf *argBuf = NULL;
    int argBufCapacity = 0;
    struct iocshCommand *found;
    void *readlineContext = NULL;
    int wasOkToBlock;
    
    /*
     * See if command interpreter is interactive
     */
    if (commandLine == NULL) {
        if ((pathname == NULL) || (strcmp (pathname, "<telnet>") == 0)) {
            if ((prompt = envGetConfigParamPtr(&IOCSH_PS1)) == NULL)
                prompt = "epics> ";
        }
        else {
            fp = fopen (pathname, "r");
            if (fp == NULL) {
                fprintf(epicsGetStderr(), "Can't open %s: %s\n", pathname,
                    strerror (errno));
                return -1;
            }
            if ((filename = strrchr (pathname, '/')) == NULL)
                filename = pathname;
            else
                filename++;
            prompt = NULL;
        }

        /*
         * Create a command-line input context
         */
        if ((readlineContext = epicsReadlineBegin(fp)) == NULL) {
            fprintf(epicsGetStderr(), "Can't allocate command-line object.\n");
            if (fp)
                fclose(fp);
            return -1;
        }
    }

    /*
     * Set up redirection
     */
    redirects = (struct iocshRedirect *)calloc(NREDIRECTS, sizeof *redirects);
    if (redirects == NULL) {
        fprintf(epicsGetStderr(), "Out of memory!\n");
        return -1;
    }

    /*
     * Read commands till EOF or exit
     */
    argc = 0;
    wasOkToBlock = epicsThreadIsOkToBlock();
    epicsThreadSetOkToBlock(1);
    for (;;) {
        /*
         * Read a line
         */
        if (commandLine) {
            if (raw != NULL)
                break;
            raw = commandLine;
        }
        else {
            if ((raw = epicsReadline(prompt, readlineContext)) == NULL)
                break;
        }
        lineno++;

        /*
         * Skip leading white-space
         */
        icin = 0;
        while ((c = raw[icin]) && isspace(c)) {
            icin++;
        }

        /*
         * Ignore comment lines other than to echo
         * them if they came from a script.  This
         * avoids macLib errors from comments.
         */
        if (c == '#') {
            if ((prompt == NULL) && (commandLine == NULL))
                puts(raw);
            continue;
        }

        /*
         * Expand macros
         */
        free(line);
        if ((line = macEnvExpand(raw)) == NULL)
            continue;

        /*
         * Skip leading white-space coming from a macro
         */
        while ((c = line[icin]) && isspace(c)) {
            icin++;
        }

        /*
         * Echo non-empty lines read from a script
         */
        if ((prompt == NULL) && *line && (commandLine == NULL))
            puts(line);

        /*
         * Ignore lines that became a comment or empty after macro expansion
         */
        if (!c || c == '#')
            continue;

        /*
         * Break line into words
         */
        icout = 0;
        inword = 0;
        argc = 0;
        quote = EOF;
        backslash = 0;
        redirect = NULL;
        for (;;) {
            if (argc >= argvCapacity) {
                char **av;
                argvCapacity += 50;
                av = (char **)realloc (argv, argvCapacity * sizeof *argv);
                if (av == NULL) {
                    fprintf (epicsGetStderr(), "Out of memory!\n");
                    argc = -1;
                    break;
                }
                argv = av;
            }
            c = line[icin++];
            if (c == '\0')
                break;
            if ((quote == EOF) && !backslash && (strchr (ifs, c)))
                sep = 1;
            else
                sep = 0;
            if ((quote == EOF) && !backslash) {
                int redirectFd = 1;
                if (c == '\\') {
                    backslash = 1;
                    continue;
                }
                if (c == '<') {
                    if (redirect != NULL) {
                        break;
                    }
                    redirect = &redirects[0];
                    sep = 1;
                    redirect->mode = "r";
                }
                if ((c >= '1') && (c <= '9') && (line[icin] == '>')) {
                    redirectFd = c - '0';
                    c = '>';
                    icin++;
                }
                if (c == '>') {
                    if (redirect != NULL)
                        break;
                    if (redirectFd >= NREDIRECTS) {
                        redirect = &redirects[1];
                        break;
                    }
                    redirect = &redirects[redirectFd];
                    sep = 1;
                    if (line[icin] == '>') {
                        icin++;
                        redirect->mode = "a";
                    }
                    else {
                        redirect->mode = "w";
                    }
                }
            }
            if (inword) {
                if (c == quote) {
                    quote = EOF;
                }
                else {
                    if ((quote == EOF) && !backslash) {
                        if (sep) {
                            inword = 0;
                            line[icout++] = '\0';
                        }
                        else if ((c == '"') || (c == '\'')) {
                            quote = c;
                        }
                        else {
                            line[icout++] = c;
                        }
                    }
                    else {
                        line[icout++] = c;
                    }
                }
            }
            else {
                if (!sep) {
                    if (((c == '"') || (c == '\'')) && !backslash)
                        quote = c;
                    if (redirect != NULL) {
                        if (redirect->name != NULL) {
                            argc = -1;
                            break;
                        }
                        redirect->name = line + icout;
                        redirect = NULL;
                    }
                    else {
                        argv[argc++] = line + icout;
                    }
                    if (quote == EOF)
                        line[icout++] = c;
                    inword = 1;
                }
            }
            backslash = 0;
        }
        if (redirect != NULL) {
            showError(filename, lineno, "Illegal redirection.");
            continue;
        }
        if (argc < 0)
            break;
        if (quote != EOF) {
            showError(filename, lineno, "Unbalanced quote.");
            continue;
        }
        if (backslash) {
            showError(filename, lineno, "Trailing backslash.");
            continue;
        }
        if (inword)
            line[icout++] = '\0';
        argv[argc] = NULL;

        /*
         * Special case -- Redirected input but no command
         * Treat as if 'iocsh filename'.
         */
        if ((argc == 0) && (redirects[0].name != NULL)) {
            const char *commandFile = redirects[0].name;
            redirects[0].name = NULL;
            if (openRedirect(filename, lineno, redirects) < 0)
                continue;
            startRedirect(filename, lineno, redirects);
            iocshBody(commandFile, NULL);
            stopRedirect(filename, lineno, redirects);
            continue;
        }

        /*
         * Special command?
         */
        if ((argc > 0) && (strcmp(argv[0], "exit") == 0))
            break;

        /*
         * Set up redirection
         */
        if ((openRedirect(filename, lineno, redirects) == 0) && (argc > 0)) {
            /*
             * Look up command
             */
            found = (iocshCommand *)registryFind (iocshCmdID, argv[0]);
            if (found) {
                /*
                 * Process arguments and call function
                 */
                struct iocshFuncDef const *piocshFuncDef = found->pFuncDef;
                for (int iarg = 0 ; ; ) {
                    if (iarg == piocshFuncDef->nargs) {
                        startRedirect(filename, lineno, redirects);
                        (*found->func)(argBuf);
                        break;
                    }
                    if (iarg >= argBufCapacity) {
                        void *np;

                        argBufCapacity += 20;
                        np = realloc (argBuf, argBufCapacity * sizeof *argBuf);
                        if (np == NULL) {
                            fprintf (epicsGetStderr(), "Out of memory!\n");
                            argBufCapacity -= 20;
                            break;
                        }
                        argBuf = (iocshArgBuf *)np;
                    }
                    if (piocshFuncDef->arg[iarg]->type == iocshArgArgv) {
                        argBuf[iarg].aval.ac = argc-iarg;
                        argBuf[iarg].aval.av = argv+iarg;
                        iarg = piocshFuncDef->nargs;
                    }
                    else {
                        if (!cvtArg (filename, lineno,
                                ((iarg < argc) ? argv[iarg+1] : NULL),
                                &argBuf[iarg], piocshFuncDef->arg[iarg]))
                            break;
                        iarg++;
                    }
                }
                if ((prompt != NULL) && (strcmp(argv[0], "epicsEnvSet") == 0)) {
                    const char *newPrompt;
                    if ((newPrompt = envGetConfigParamPtr(&IOCSH_PS1)) != NULL)
                        prompt = newPrompt;
                }
            }
            else {
                showError(filename, lineno, "Command %s not found.", argv[0]);
            }
        }
        stopRedirect(filename, lineno, redirects);
    }
    if (fp && (fp != stdin))
        fclose (fp);
    if (redirects != NULL) {
        stopRedirect(filename, lineno, redirects);
        free (redirects);
    }
    free(line);
    free (argv);
    free (argBuf);
    errlogFlush();
    if (readlineContext)
        epicsReadlineEnd(readlineContext);
    epicsThreadSetOkToBlock( wasOkToBlock);
    return 0;
}
bool SystemConfigurationImpl::hasProperty(const string &key)
{
	strncpy(_envParam.name,key.c_str(),key.length() + 1);
	const char* val = envGetConfigParamPtr(&_envParam);
    return (val != NULL) || _properties->hasProperty(key);
}
Example #13
0
//
// udpiiu::udpiiu ()
//
udpiiu::udpiiu ( 
    epicsGuard < epicsMutex > & cacGuard,
    epicsTimerQueueActive & timerQueue, 
    epicsMutex & cbMutexIn, 
    epicsMutex & cacMutexIn,
    cacContextNotify & ctxNotifyIn,
    cac & cac,
    unsigned port,
    tsDLList < SearchDest > & searchDestListIn ) :
    recvThread ( *this, ctxNotifyIn, cbMutexIn, "CAC-UDP", 
        epicsThreadGetStackSize ( epicsThreadStackMedium ),
        cac::lowestPriorityLevelAbove (
            cac::lowestPriorityLevelAbove (
                cac.getInitializingThreadsPriority () ) ) ),
    m_repeaterTimerNotify ( *this ),
    repeaterSubscribeTmr (
        m_repeaterTimerNotify, timerQueue, cbMutexIn, ctxNotifyIn ),
    govTmr ( *this, timerQueue, cacMutexIn ),
    maxPeriod ( maxSearchPeriodDefault ),
    rtteMean ( minRoundTripEstimate ),
    rtteMeanDev ( 0 ),
    cacRef ( cac ),
    cbMutex ( cbMutexIn ),
    cacMutex ( cacMutexIn ),
    nBytesInXmitBuf ( 0 ),
    nTimers ( 0 ),
    beaconAnomalyTimerIndex ( 0 ),
    sequenceNumber ( 0 ),
    lastReceivedSeqNo ( 0 ),
    sock ( 0 ),
    repeaterPort ( 0 ),
    serverPort ( port ),
    localPort ( 0 ),
    shutdownCmd ( false ),
    lastReceivedSeqNoIsValid ( false )
{
    cacGuard.assertIdenticalMutex ( cacMutex );
    
    if ( envGetConfigParamPtr ( & EPICS_CA_MAX_SEARCH_PERIOD ) ) {
        long longStatus = envGetDoubleConfigParam ( 
            & EPICS_CA_MAX_SEARCH_PERIOD, & this->maxPeriod );
        if ( ! longStatus ) {
            if ( this->maxPeriod < maxSearchPeriodLowerLimit ) {
                epicsPrintf ( "\"%s\" out of range (low)\n",
                                EPICS_CA_MAX_SEARCH_PERIOD.name );
                this->maxPeriod = maxSearchPeriodLowerLimit;
                epicsPrintf ( "Setting \"%s\" = %f seconds\n",
                    EPICS_CA_MAX_SEARCH_PERIOD.name, this->maxPeriod );
            }
        }
        else {
            epicsPrintf ( "EPICS \"%s\" wasnt a real number\n",
                            EPICS_CA_MAX_SEARCH_PERIOD.name );
            epicsPrintf ( "Setting \"%s\" = %f seconds\n",
                EPICS_CA_MAX_SEARCH_PERIOD.name, this->maxPeriod );
        }
    }

    double powerOfTwo = log ( this->maxPeriod / minRoundTripEstimate ) / log ( 2.0 );
    this->nTimers = static_cast < unsigned > ( powerOfTwo + 1.0 );
    if ( this->nTimers > channelNode::getMaxSearchTimerCount () ) {
        this->nTimers = channelNode::getMaxSearchTimerCount ();
        epicsPrintf ( "\"%s\" out of range (high)\n",
                        EPICS_CA_MAX_SEARCH_PERIOD.name );
        epicsPrintf ( "Setting \"%s\" = %f seconds\n",
            EPICS_CA_MAX_SEARCH_PERIOD.name, 
            (1<<(this->nTimers-1)) * minRoundTripEstimate );
    }

    powerOfTwo = log ( beaconAnomalySearchPeriod / minRoundTripEstimate ) / log ( 2.0 );
    this->beaconAnomalyTimerIndex = static_cast < unsigned > ( powerOfTwo + 1.0 );
    if ( this->beaconAnomalyTimerIndex >= this->nTimers ) {
        this->beaconAnomalyTimerIndex = this->nTimers - 1;
    }

    this->ppSearchTmr.reset ( new epics_auto_ptr < class searchTimer > [ this->nTimers ] );
    for ( unsigned i = 0; i < this->nTimers; i++ ) {
        this->ppSearchTmr[i].reset ( 
            new searchTimer ( *this, timerQueue, i, cacMutexIn, 
                i > this->beaconAnomalyTimerIndex ) ); 
    }

    this->repeaterPort = 
        envGetInetPortConfigParam ( &EPICS_CA_REPEATER_PORT,
                                    static_cast <unsigned short> (CA_REPEATER_PORT) );

    this->sock = epicsSocketCreate ( AF_INET, SOCK_DGRAM, IPPROTO_UDP );
    if ( this->sock == INVALID_SOCKET ) {
        char sockErrBuf[64];
        epicsSocketConvertErrnoToString ( 
            sockErrBuf, sizeof ( sockErrBuf ) );
        errlogPrintf ("CAC: unable to create datagram socket because = \"%s\"\n",
            sockErrBuf );
        throwWithLocation ( noSocket () );
    }

    int boolValue = true;
    int status = setsockopt ( this->sock, SOL_SOCKET, SO_BROADCAST, 
                (char *) &boolValue, sizeof ( boolValue ) );
    if ( status < 0 ) {
        char sockErrBuf[64];
        epicsSocketConvertErrnoToString ( 
            sockErrBuf, sizeof ( sockErrBuf ) );
        errlogPrintf ("CAC: IP broadcasting enable failed because = \"%s\"\n",
            sockErrBuf );
    }

#if 0
    {
        /*
         * some concern that vxWorks will run out of mBuf's
         * if this change is made joh 11-10-98
         *
         * bump up the UDP recv buffer
         */
        int size = 1u<<15u;
        status = setsockopt ( this->sock, SOL_SOCKET, SO_RCVBUF,
                (char *)&size, sizeof (size) );
        if (status<0) {
            char sockErrBuf[64];
            epicsSocketConvertErrnoToString ( sockErrBuf, sizeof ( sockErrBuf ) );
            errlogPrintf ( "CAC: unable to set socket option SO_RCVBUF because \"%s\"\n",
                sockErrBuf );
        }
    }
#endif

    // force a bind to an unconstrained address so we can obtain
    // the local port number below
    static const unsigned short PORT_ANY = 0u;
    osiSockAddr addr;
    memset ( (char *)&addr, 0 , sizeof (addr) );
    addr.ia.sin_family = AF_INET;
    addr.ia.sin_addr.s_addr = htonl ( INADDR_ANY ); 
    addr.ia.sin_port = htons ( PORT_ANY );
    status = bind (this->sock, &addr.sa, sizeof (addr) );
    if ( status < 0 ) {
        char sockErrBuf[64];
        epicsSocketConvertErrnoToString ( 
            sockErrBuf, sizeof ( sockErrBuf ) );
        epicsSocketDestroy (this->sock);
        errlogPrintf ( "CAC: unable to bind to an unconstrained address because = \"%s\"\n",
            sockErrBuf );
        throwWithLocation ( noSocket () );
    }
    
    {
        osiSockAddr tmpAddr;
        osiSocklen_t saddr_length = sizeof ( tmpAddr );
        status = getsockname ( this->sock, &tmpAddr.sa, &saddr_length );
        if ( status < 0 ) {
            char sockErrBuf[64];
            epicsSocketConvertErrnoToString ( 
                sockErrBuf, sizeof ( sockErrBuf ) );
            epicsSocketDestroy ( this->sock );
            errlogPrintf ( "CAC: getsockname () error was \"%s\"\n", sockErrBuf );
            throwWithLocation ( noSocket () );
        }
        if ( tmpAddr.sa.sa_family != AF_INET) {
            epicsSocketDestroy ( this->sock );
            errlogPrintf ( "CAC: UDP socket was not inet addr family\n" );
            throwWithLocation ( noSocket () );
        }
        this->localPort = ntohs ( tmpAddr.ia.sin_port );
    }

    /*
     * load user and auto configured
     * broadcast address list
     */
    ELLLIST dest;
    ellInit ( & dest );
    configureChannelAccessAddressList ( & dest, this->sock, this->serverPort );
    while ( osiSockAddrNode * 
        pNode = reinterpret_cast < osiSockAddrNode * > ( ellGet ( & dest ) ) ) {
        SearchDestUDP & searchDest = * 
            new SearchDestUDP ( pNode->addr, *this );
        _searchDestList.add ( searchDest );
        free ( pNode );
    }

    /* add list of tcp name service addresses */
    _searchDestList.add ( searchDestListIn );
    
    caStartRepeaterIfNotInstalled ( this->repeaterPort );

    this->pushVersionMsg ();

    // start timers and receive thread
    for ( unsigned j =0; j < this->nTimers; j++ ) {
        this->ppSearchTmr[j]->start ( cacGuard ); 
    }
    this->govTmr.start ();
    this->repeaterSubscribeTmr.start ();
    this->recvThread.start ();
}
Example #14
0
/*
 *  RSRV_ONLINE_NOTIFY_TASK
 */
void rsrv_online_notify_task(void *pParm)
{
    unsigned                    priorityOfSelf = epicsThreadGetPrioritySelf ();
    osiSockAddrNode             *pNode;
    double                      delay;
    double                      maxdelay;
    long                        longStatus;
    double                      maxPeriod;
    caHdr                       msg;
    int                         status;
    SOCKET                      sock;
    int                         intTrue = TRUE;
    unsigned short              port;
    ca_uint32_t                 beaconCounter = 0;
    char                        * pStr;
    int                         autoBeaconAddr;
    ELLLIST                     autoAddrList;
    char                        buf[16];
    unsigned                    priorityOfUDP;
    epicsThreadBooleanStatus    tbs;
    epicsThreadId               tid;
    
    taskwdInsert (epicsThreadGetIdSelf(),NULL,NULL);
    
    if ( envGetConfigParamPtr ( & EPICS_CAS_BEACON_PERIOD ) ) {
        longStatus = envGetDoubleConfigParam ( & EPICS_CAS_BEACON_PERIOD, & maxPeriod );
    }
    else {
        longStatus = envGetDoubleConfigParam ( & EPICS_CA_BEACON_PERIOD, & maxPeriod );
    }
    if (longStatus || maxPeriod<=0.0) {
        maxPeriod = 15.0;
        epicsPrintf ("EPICS \"%s\" float fetch failed\n",
                        EPICS_CAS_BEACON_PERIOD.name);
        epicsPrintf ("Setting \"%s\" = %f\n",
            EPICS_CAS_BEACON_PERIOD.name, maxPeriod);
    }
    
    delay = 0.02; /* initial beacon period in sec */
    maxdelay = maxPeriod;
    
    /* 
     *  Open the socket.
     *  Use ARPA Internet address format and datagram socket.
     *  Format described in <sys/socket.h>.
     */
    if ( (sock = epicsSocketCreate (AF_INET, SOCK_DGRAM, 0)) == INVALID_SOCKET) {
        errlogPrintf ("CAS: online socket creation error\n");
        epicsThreadSuspendSelf ();
    }
    
    status = setsockopt (sock, SOL_SOCKET, SO_BROADCAST, 
                (char *)&intTrue, sizeof(intTrue));
    if (status<0) {
        errlogPrintf ("CAS: online socket set up error\n");
        epicsThreadSuspendSelf ();
    }

    {
        /*
         * this connect is to supress a warning message on Linux
         * when we shutdown the read side of the socket. If it
         * fails (and it will on old ip kernels) we just ignore 
         * the failure.
         */
        osiSockAddr sockAddr;
        sockAddr.ia.sin_family = AF_UNSPEC;
        sockAddr.ia.sin_port = htons ( 0 );
        sockAddr.ia.sin_addr.s_addr = htonl (0);
        connect ( sock, & sockAddr.sa, sizeof ( sockAddr.sa ) );
        shutdown ( sock, SHUT_RD );
    }
    
    memset((char *)&msg, 0, sizeof msg);
    msg.m_cmmd = htons (CA_PROTO_RSRV_IS_UP);
    msg.m_count = htons (ca_server_port);
    msg.m_dataType = htons (CA_MINOR_PROTOCOL_REVISION);
    
    ellInit ( & beaconAddrList );
    ellInit ( & autoAddrList );

    pStr = envGetConfigParam(&EPICS_CAS_AUTO_BEACON_ADDR_LIST, sizeof(buf), buf);
    if ( ! pStr ) {
	    pStr = envGetConfigParam(&EPICS_CA_AUTO_ADDR_LIST, sizeof(buf), buf);
    }
	if (pStr) {
		if (strstr(pStr,"no")||strstr(pStr,"NO")) {
			autoBeaconAddr = FALSE;
		}
		else if (strstr(pStr,"yes")||strstr(pStr,"YES")) {
			autoBeaconAddr = TRUE;
		}
		else {
			fprintf(stderr, 
		"CAS: EPICS_CA(S)_AUTO_ADDR_LIST = \"%s\"? Assuming \"YES\"\n", pStr);
			autoBeaconAddr = TRUE;
		}
	}
	else {
		autoBeaconAddr = TRUE;
	}

    /*
     * load user and auto configured
     * broadcast address list
     */
    if (envGetConfigParamPtr(&EPICS_CAS_BEACON_PORT)) {
        port = envGetInetPortConfigParam (&EPICS_CAS_BEACON_PORT, 
            (unsigned short) CA_REPEATER_PORT );
    }
    else {
        port = envGetInetPortConfigParam (&EPICS_CA_REPEATER_PORT, 
            (unsigned short) CA_REPEATER_PORT );
    }

    /*
     * discover beacon addresses associated with this interface
     */
    if ( autoBeaconAddr ) {
        osiSockAddr addr;
		ELLLIST tmpList;

		ellInit ( &tmpList );
        addr.ia.sin_family = AF_UNSPEC;
        osiSockDiscoverBroadcastAddresses (&tmpList, sock, &addr); 
        forcePort ( &tmpList, port );
		removeDuplicateAddresses ( &autoAddrList, &tmpList, 1 );
    }
            
    /*
     * by default use EPICS_CA_ADDR_LIST for the
     * beacon address list
     */
    {
        const ENV_PARAM *pParam;
        
        if (envGetConfigParamPtr(&EPICS_CAS_INTF_ADDR_LIST) || 
            envGetConfigParamPtr(&EPICS_CAS_BEACON_ADDR_LIST)) {
            pParam = &EPICS_CAS_BEACON_ADDR_LIST;
        }
        else {
            pParam = &EPICS_CA_ADDR_LIST;
        }
    
        /* 
         * add in the configured addresses
         */
        addAddrToChannelAccessAddressList (
            &autoAddrList, pParam, port,  pParam == &EPICS_CA_ADDR_LIST );
    }
 
    removeDuplicateAddresses ( &beaconAddrList, &autoAddrList, 0 );

    if ( ellCount ( &beaconAddrList ) == 0 ) {
        errlogPrintf ("The CA server's beacon address list was empty after initialization?\n");
    }
  
#   ifdef DEBUG
        printChannelAccessAddressList (&beaconAddrList);
#   endif

    tbs  = epicsThreadHighestPriorityLevelBelow ( priorityOfSelf, &priorityOfUDP );
    if ( tbs != epicsThreadBooleanStatusSuccess ) {
        priorityOfUDP = priorityOfSelf;
    }

    casudp_startStopEvent = epicsEventMustCreate(epicsEventEmpty);
    casudp_ctl = ctlPause;

    tid = epicsThreadCreate ( "CAS-UDP", priorityOfUDP,
        epicsThreadGetStackSize (epicsThreadStackMedium),
        cast_server, 0 );
    if ( tid == 0 ) {
        epicsPrintf ( "CAS: unable to start UDP daemon thread\n" );
    }

    epicsEventMustWait(casudp_startStopEvent);
    epicsEventSignal(beacon_startStopEvent);

    while (TRUE) {
        pNode = (osiSockAddrNode *) ellFirst (&beaconAddrList);
        while (pNode) {
            char buf[64];

            status = connect (sock, &pNode->addr.sa, 
                sizeof(pNode->addr.sa));
            if (status<0) {
                char sockErrBuf[64];
                epicsSocketConvertErrnoToString ( 
                    sockErrBuf, sizeof ( sockErrBuf ) );
                ipAddrToDottedIP (&pNode->addr.ia, buf, sizeof(buf));
                errlogPrintf ( "%s: CA beacon routing (connect to \"%s\") error was \"%s\"\n",
                    __FILE__, buf, sockErrBuf);
            }
            else {
                struct sockaddr_in if_addr;

                osiSocklen_t size = sizeof (if_addr);
                status = getsockname (sock, (struct sockaddr *) &if_addr, &size);
                if (status<0) {
                    char sockErrBuf[64];
                    epicsSocketConvertErrnoToString ( sockErrBuf, sizeof ( sockErrBuf ) );
                    errlogPrintf ( "%s: CA beacon routing (getsockname) error was \"%s\"\n",
                        __FILE__, sockErrBuf);
                }
                else if (if_addr.sin_family==AF_INET) {
                    msg.m_available = if_addr.sin_addr.s_addr;
                    msg.m_cid = htonl ( beaconCounter );

                    status = send (sock, (char *)&msg, sizeof(msg), 0);
                    if (status < 0) {
                        char sockErrBuf[64];
                        epicsSocketConvertErrnoToString ( sockErrBuf, sizeof ( sockErrBuf ) );
                        ipAddrToDottedIP (&pNode->addr.ia, buf, sizeof(buf));
                        errlogPrintf ( "%s: CA beacon (send to \"%s\") error was \"%s\"\n",
                            __FILE__, buf, sockErrBuf);
                    }
                    else {
                        assert (status == sizeof(msg));
                    }
                }
            }
            pNode = (osiSockAddrNode *) pNode->node.next;
        }

        epicsThreadSleep(delay);
        if (delay<maxdelay) {
            delay *= 2.0;
            if (delay>maxdelay) {
                delay = maxdelay;
            }
        }

        beaconCounter++; /* expected to overflow */

        while (beacon_ctl == ctlPause) {
            epicsThreadSleep(0.1);
            delay = 0.02; /* Restart beacon timing if paused */
        }
    }
}
Example #15
0
/*
 * CAST_SERVER
 *
 * service UDP messages
 * 
 */
void cast_server(void *pParm)
{
    struct sockaddr_in  sin;    
    int                 status;
    int                 count=0;
    struct sockaddr_in  new_recv_addr;
    osiSocklen_t        recv_addr_size;
    unsigned short      port;
    osiSockIoctl_t      nchars;

    if ( envGetConfigParamPtr ( &EPICS_CAS_SERVER_PORT ) ) {
        port = envGetInetPortConfigParam ( &EPICS_CAS_SERVER_PORT, 
            (unsigned short) CA_SERVER_PORT );
    }
    else {
        port = envGetInetPortConfigParam ( &EPICS_CA_SERVER_PORT, 
            (unsigned short) CA_SERVER_PORT );
    }

    recv_addr_size = sizeof(new_recv_addr);

    if( IOC_cast_sock!=0 && IOC_cast_sock!=INVALID_SOCKET ) {
        epicsSocketDestroy ( IOC_cast_sock );
    }

    /* 
     *  Open the socket.
     *  Use ARPA Internet address format and datagram socket.
     */

    if ( ( IOC_cast_sock = epicsSocketCreate (AF_INET, SOCK_DGRAM, 0) ) == INVALID_SOCKET ) {
        epicsPrintf ("CAS: cast socket creation error\n");
        epicsThreadSuspendSelf ();
    }

    /*
     * some concern that vxWorks will run out of mBuf's
     * if this change is made
     *
     * joh 11-10-98
     */
#if 0
    {
        /*
         *
         * this allows for faster connects by queuing
         * additional incomming UDP search frames
         *
         * this allocates a 32k buffer
         * (uses a power of two)
         */
        int size = 1u<<15u;
        status = setsockopt (IOC_cast_sock, SOL_SOCKET,
                        SO_RCVBUF, (char *)&size, sizeof(size));
        if (status<0) {
            epicsPrintf ("CAS: unable to set cast socket size\n");
        }
    }
#endif

    epicsSocketEnableAddressUseForDatagramFanout ( IOC_cast_sock );
    
    /*  Zero the sock_addr structure */
    memset((char *)&sin, 0, sizeof(sin));
    sin.sin_family = AF_INET;
    sin.sin_addr.s_addr = htonl(INADDR_ANY);
    sin.sin_port = htons(port);
    
    /* get server's Internet address */
    if( bind(IOC_cast_sock, (struct sockaddr *)&sin, sizeof (sin)) < 0){
        char sockErrBuf[64];
        epicsSocketConvertErrnoToString ( 
            sockErrBuf, sizeof ( sockErrBuf ) );
        epicsPrintf ("CAS: UDP server port bind error was \"%s\"\n", sockErrBuf );
        epicsSocketDestroy ( IOC_cast_sock );
        epicsThreadSuspendSelf ();
    }

    /*
     * setup new client structure but reuse old structure if
     * possible
     *
     */
    while ( TRUE ) {
        prsrv_cast_client = create_client ( IOC_cast_sock, IPPROTO_UDP );
        if ( prsrv_cast_client ) {
            break;
        }
        epicsThreadSleep(300.0);
    }

    casAttachThreadToClient ( prsrv_cast_client );

    /*
     * add placeholder for the first version message should it be needed
     */
    rsrv_version_reply ( prsrv_cast_client );

    epicsEventSignal(casudp_startStopEvent);

    while (TRUE) {
        status = recvfrom (
            IOC_cast_sock,
            prsrv_cast_client->recv.buf,
            prsrv_cast_client->recv.maxstk,
            0,
            (struct sockaddr *)&new_recv_addr, 
            &recv_addr_size);
        if (status < 0) {
            if (SOCKERRNO != SOCK_EINTR) {
                char sockErrBuf[64];
                epicsSocketConvertErrnoToString ( 
                    sockErrBuf, sizeof ( sockErrBuf ) );
                epicsPrintf ("CAS: UDP recv error (errno=%s)\n",
                        sockErrBuf);
                epicsThreadSleep(1.0);
            }
        }
        else if (casudp_ctl == ctlRun) {
            prsrv_cast_client->recv.cnt = (unsigned) status;
            prsrv_cast_client->recv.stk = 0ul;
            epicsTimeGetCurrent(&prsrv_cast_client->time_at_last_recv);

            prsrv_cast_client->minor_version_number = 0;
            prsrv_cast_client->seqNoOfReq = 0;

            /*
             * If we are talking to a new client flush to the old one 
             * in case we are holding UDP messages waiting to 
             * see if the next message is for this same client.
             */
            if (prsrv_cast_client->send.stk>sizeof(caHdr)) {
                status = memcmp( (void *)&prsrv_cast_client->addr, (void *)&new_recv_addr, recv_addr_size);
                if(status){     
                    /* 
                     * if the address is different 
                     */
                    cas_send_dg_msg(prsrv_cast_client);
                    prsrv_cast_client->addr = new_recv_addr;
                }
            }
            else {
                prsrv_cast_client->addr = new_recv_addr;
            }

            if (CASDEBUG>1) {
                char    buf[40];
    
                ipAddrToDottedIP (&prsrv_cast_client->addr, buf, sizeof(buf));
                errlogPrintf ("CAS: cast server msg of %d bytes from addr %s\n", 
                    prsrv_cast_client->recv.cnt, buf);
            }

            if (CASDEBUG>2)
                count = ellCount (&prsrv_cast_client->chanList);

            status = camessage ( prsrv_cast_client );
            if(status == RSRV_OK){
                if(prsrv_cast_client->recv.cnt != 
                    prsrv_cast_client->recv.stk){
                    char buf[40];
        
                    ipAddrToDottedIP (&prsrv_cast_client->addr, buf, sizeof(buf));

                    epicsPrintf ("CAS: partial (damaged?) UDP msg of %d bytes from %s ?\n",
                        prsrv_cast_client->recv.cnt-prsrv_cast_client->recv.stk, buf);
                }
            }
            else {
                char buf[40];
    
                ipAddrToDottedIP (&prsrv_cast_client->addr, buf, sizeof(buf));

                epicsPrintf ("CAS: invalid (damaged?) UDP request from %s ?\n", buf);
            }

            if (CASDEBUG>2) {
                if ( ellCount (&prsrv_cast_client->chanList) ) {
                    errlogPrintf ("CAS: Fnd %d name matches (%d tot)\n",
                        ellCount(&prsrv_cast_client->chanList)-count,
                        ellCount(&prsrv_cast_client->chanList));
                }
            }
        }

        /*
         * allow messages to batch up if more are comming
         */
        nchars = 0; /* supress purify warning */
        status = socket_ioctl(IOC_cast_sock, FIONREAD, &nchars);
        if (status<0) {
            errlogPrintf ("CA cast server: Unable to fetch N characters pending\n");
            cas_send_dg_msg (prsrv_cast_client);
            clean_addrq ();
        }
        else if (nchars == 0) {
            cas_send_dg_msg (prsrv_cast_client);
            clean_addrq ();
        }
    }
}