pps.c

Interaction with PPS control object of a simple window manager

/*
* $QNXLicenseC:
* Copyright 2012, QNX Software Systems Limited. All Rights Reserved.
*
* This software is QNX Confidential Information subject to
* confidentiality restrictions. DISCLOSURE OF THIS SOFTWARE
* IS PROHIBITED UNLESS AUTHORIZED BY QNX SOFTWARE SYSTEMS IN
* WRITING.
*
* You must obtain a written license from and pay applicable license
* fees to QNX Software Systems Limited before you may reproduce, modify
* or distribute this software, or any work that includes all or part
* of this software. For more information visit
* http://licensing.qnx.com or email licensing@qnx.com.
*
* This file may contain contributions from others.  Please review
* this entire file for other proprietary rights or license notices,
* as well as the QNX Development Suite License Guide at
* http://licensing.qnx.com/license-guide/ for other information.
* $
*/

#include "struct.h"

static int pps_parse(window_manager_t *winmgr, char* reqbuf);

/**
 * pps thread loop
 */
void* pps_thread(void *arg)
{
    window_manager_t *winmgr = (window_manager_t*)arg;

    char buf[1024];
    int fd = -1;
    int nread = -1;

    pthread_setname_np(winmgr->pps_tid = pthread_self(), "pps");

    while (1) {
        while (fd == -1) {

            if (winmgr->state & WINMGR_TERMINATE) {
                goto terminate;
            }

            if ((fd = open ("/pps/services/launcher/control?wait,delta", O_RDWR)) == -1 ) {
                sleep(1);
            } else {
                winmgr->pps_fd = fd;
            }
        }

        while (nread == -1) {

            if (winmgr->state & WINMGR_TERMINATE) {
                goto terminate;
            }

            nread = read(fd, buf, sizeof(buf)-1);
            if (nread > 1) {
                buf[nread] = '\0';

                // process received message
                if (pps_parse(winmgr, buf) == EOK
                        && !(winmgr->ptype == PPS_EVENT_OBJECT_CHANGED && !winmgr->numattrs)
                        && winmgr->ptype != PPS_EVENT_OBJECT_UNKNOWN) {
                    launcher_pps(winmgr);
                }
            }
        }

        if (nread == -1 && errno == EBADF) {
            fd = -1;
        }

        nread = -1;
    }

terminate:
    close(fd);
    pthread_exit(NULL);

    return NULL;
}

int pps_write(int pps_fd, const char *msgbuf, int msgsize)
{
    int ret = 0;

    ret = write(pps_fd, msgbuf, (unsigned)msgsize);

    return ret;
}

int pps_is_open(int pps_fd)
{
    int ret = 1;

    if (pps_fd == 0 || pps_fd == -1) {
        ret = 0;
    }

    return ret;
}

pps_attr_t* pps_lookup_attr(window_manager_t *winmgr, char *name)
{
    int i;

    for (i = 0; i < winmgr->numattrs; ++i)
        if (strcmp(winmgr->attrs[i].name, name) == 0)
            return &(winmgr->attrs[i]);
    return NULL;
}

char* pps_lookup(window_manager_t *winmgr, char *name)
{
    pps_attr_t* attr = pps_lookup_attr(winmgr, name);

    if (!attr)
        return NULL;

    if (attr->value)
        return attr->value;
    else
        return attr->name;
}

static int pps_parse_attr(window_manager_t *winmgr, const pps_attrib_t* info)
{
    if (winmgr->numattrs >= MAX_ATTRS) {
        SLOG_NOTICE("Too many attributes.");
        return E2BIG;
    } else {
        winmgr->attrs[winmgr->numattrs].name = info->attr_name;
        winmgr->attrs[winmgr->numattrs].encoding = info->encoding;
        winmgr->attrs[winmgr->numattrs++].value = info->value;
        return EOK;
    }
}

static int pps_parse(window_manager_t *winmgr, char* reqbuf)
{
    pps_attrib_t    info;
    pps_status_t    rc;

    // Clear the request structure
    winmgr->numattrs = 0;
    winmgr->objname = NULL;
    winmgr->ptype = PPS_EVENT_OBJECT_UNKNOWN;

    while ((rc = ppsparse(&reqbuf, NULL, NULL, &info, 0)) != PPS_END)
    {
        switch (rc) {
        case PPS_OBJECT_CREATED:
            winmgr->objname = info.obj_name;
            winmgr->ptype = PPS_EVENT_OBJECT_CREATED;
            break;

        case PPS_OBJECT_TRUNCATED:
        case PPS_OBJECT_DELETED:
            winmgr->objname = info.obj_name;
            winmgr->ptype = PPS_EVENT_OBJECT_DELETED;
            break;

        case PPS_OBJECT:
            if (info.obj_name[0] != '@') {
                return EOK;
            }
            winmgr->objname = info.obj_name;
            winmgr->ptype = PPS_EVENT_OBJECT_CHANGED;
            break;

        case PPS_ATTRIBUTE_DELETED: {
            --info.attr_name;
            int err = pps_parse_attr(winmgr, &info);
            if (err != EOK)
                return err;
            break;
        }

        case PPS_ATTRIBUTE: {
            int err = pps_parse_attr(winmgr, &info);
            if (err != EOK)
                return err;
            break;
        }

        case PPS_ERROR:
        default:
            SLOG_WARNING("We got a parsing error.");
            return EINVAL;
        }
    }

    return EOK;
}