OpenSolaris_b135/cmd/lms/glue.cpp

/*******************************************************************************
 * Copyright (C) 2004-2008 Intel Corp. All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 *  - Redistributions of source code must retain the above copyright notice,
 *    this list of conditions and the following disclaimer.
 *
 *  - Redistributions in binary form must reproduce the above copyright notice,
 *    this list of conditions and the following disclaimer in the documentation
 *    and/or other materials provided with the distribution.
 *
 *  - Neither the name of Intel Corp. nor the names of its
 *    contributors may be used to endorse or promote products derived from this
 *    software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS''
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED. IN NO EVENT SHALL Intel Corp. OR THE CONTRIBUTORS
 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 *******************************************************************************/

#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include <cstdlib>
#include <cstdio>
#include <cstring>
#include <sys/types.h>
#include <dlfcn.h>
#include "glue.h"

#ifdef __sun
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#endif	// __sun

#define PARSER_MAX 32

typedef struct parser_s {
	unsigned int count;
	char *line[PARSER_MAX];
} parser_t;


static void parser_init(parser_t *cfg)
{
	if (!cfg) {
		return;
	}

	cfg->count = 0;
}

static int parser_add(parser_t *cfg, char *buf)
{
	if ((!cfg) || (cfg->count > PARSER_MAX)) {
		return -1;
	}

	cfg->line[cfg->count] = strdup(buf);
	if (cfg->line[cfg->count]) {
		cfg->count ++;
	}

	return 0;
}

static int parser_length(parser_t *cfg)
{
	if (!cfg) {
		return 0;
	}

	return cfg->count;
}

static char *parser_get(parser_t *cfg, unsigned int index)
{
	if ((!cfg) || (index >= cfg->count)) {
		return NULL;
	}

	return (cfg->line[index]);
}


static int parser_read(parser_t *cfg, FILE *fp)
{
	char line[512];
	char *head, *tail;
	int len;

	if ((!fp) || (!cfg)) {
		return -1;
	}

	while (fgets(line, 511, fp)) {
		head = line;
		while (*head == 0x20 || *head == '\t') {
			head ++;
		}
		if ((*head == '#') || (*head == '\n') ||
		    (*head == '\r') || (*head == '\0')) {
			continue;
		}
		len = strlen(head);
		tail = head + len - 1;
		if (tail <= head) {
			continue;
		}
		while ((*tail == '\r') || (*tail == '\n')) {
			tail --;
		}
		*(tail + 1) = '\0';

		parser_add(cfg, head);
	}
	return 0;
}

static void parser_free(parser_t *cfg)
{
	unsigned int i;

	for (i = 0; i < cfg->count; i ++) {
		free(cfg->line[i]);
	}
}


/*   glue functions */

void glue::handle_init(int index, const char *file)
{
	int i = index;

	if (!file) {
		return;
	}
	printf("file:%s\n", file);

	funcs[i].handle = dlopen(file, RTLD_NOW);
	if (!funcs[i].handle) {
		printf("can't open:%s, %s\n", file, dlerror());
		return;
	}

	funcs[i].init_funcs = (lms_init_t)dlsym(funcs[i].handle,
					LMS_INIT_FUNC_NAME);
	if (!funcs[i].init_funcs) {
		printf("dl error:%s\n", dlerror());
		return;
	}

	if (LMS_OK != funcs[i].init_funcs()) {
		return;
	}

	funcs[i].version_funcs = (lms_version_t)dlsym(funcs[i].handle,
					LMS_VERSION_FUNC_NAME);
	funcs[i].pre_funcs = (lms_pre_t)dlsym(funcs[i].handle,
					LMS_PRE_FUNC_NAME);
	funcs[i].retry_funcs = (lms_retry_t)dlsym(funcs[i].handle,
					LMS_RETRY_FUNC_NAME);
	funcs[i].post_funcs = (lms_post_t)dlsym(funcs[i].handle,
					LMS_POST_FUNC_NAME);
	funcs[i].deinit_funcs = (lms_deinit_t)dlsym(funcs[i].handle,
					LMS_DEINIT_FUNC_NAME);
}

int glue::mem_init(void)
{
	int i;

	funcs = new glue_funcs[cnt];
	if (!funcs) {
		return LMS_ERROR;
	}

	for (i = 0;i < cnt; i++) {
		funcs[i].handle = NULL;
		funcs[i].init_funcs = NULL;
		funcs[i].version_funcs = NULL;
		funcs[i].pre_funcs = NULL;
		funcs[i].retry_funcs = NULL;
		funcs[i].post_funcs = NULL;
		funcs[i].deinit_funcs = NULL;
	}

	return LMS_OK;
}

glue::glue() : funcs(NULL)
{
}

glue::~glue()
{
}


int glue::init(void)
{
	FILE *fp;
	parser_t cfg;
	int i;

	parser_init(&cfg);

	fp = fopen(LMS_PLUGIN_CONFIG_FILE, "rb");
	if ((!fp) || (parser_read(&cfg, fp) != 0)) {
		cnt = 0;
		if (fp) {
			fclose(fp);
		}
		return LMS_OK;
	}

	do {
		cnt = parser_length(&cfg);
		if (0 == cnt) {
			break;
		}
		if (mem_init()) {
			break;
		}
		for (i = 0; i < cnt; i++) {
			handle_init(i, parser_get(&cfg, i));
		}
	} while (0);

	fclose(fp);
	parser_free(&cfg);
	return LMS_OK;
}

void glue::deinit(void)
{
	int i;

	if (!funcs) {
		return;
	}

	for (i = 0; i < cnt; i++) {
		if (funcs[i].deinit_funcs) {
			funcs[i].deinit_funcs();
		}
		if (funcs[i].handle) {
			dlclose(funcs[i].handle);
		}
	}

	delete[] funcs;
}

void glue::version(unsigned char version)
{
	int i;

	if (!funcs) {
		return;
	}

	for (i = 0; i < cnt; i++) {
		if (!funcs[i].version_funcs) {
			continue;
		}
		funcs[i].version_funcs(version);
	}
}

int glue::preprocess(unsigned char *buff, int len)
{
	int i;
	int ret = LMS_ACCEPTED;

	if (!funcs) {
		return ret;
	}

	for (i = 0; i < cnt; i++) {
		if (!funcs[i].pre_funcs) {
			continue;
		}
		ret = funcs[i].pre_funcs(buff, len);
		if (ret != LMS_ACCEPTED) {
			return ret;
		}
	}

	return LMS_ACCEPTED;
}

int glue::retry(unsigned char *buff, int len)
{
	int i;
	int ret = LMS_ACCEPTED;

	if (!funcs) {
		return ret;
	}

	for (i = 0; i < cnt; i++) {
		if (!funcs[i].retry_funcs) {
			continue;
		}
		ret = funcs[i].retry_funcs(buff, len);
		if (ret != LMS_ACCEPTED) {
			return ret;
		}
	}

	return LMS_ACCEPTED;
}


int glue::postprocess(unsigned char *buff, int len, int status)
{
	int i;
	int ret = LMS_ACCEPTED;

	if (!funcs) {
		return ret;
	}

	for (i = 0; i < cnt; i++) {
		if (!funcs[i].post_funcs) {
			continue;
		}
		ret = funcs[i].post_funcs(buff, len, status);
		if (ret != LMS_ACCEPTED) {
			return ret;
		}
	}

	return LMS_ACCEPTED;
}