2N/A/*
2N/A * CDDL HEADER START
2N/A *
2N/A * The contents of this file are subject to the terms of the
2N/A * Common Development and Distribution License, Version 1.0 only
2N/A * (the "License"). You may not use this file except in compliance
2N/A * with the License.
2N/A *
2N/A * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
2N/A * or http://www.opensolaris.org/os/licensing.
2N/A * See the License for the specific language governing permissions
2N/A * and limitations under the License.
2N/A *
2N/A * When distributing Covered Code, include this CDDL HEADER in each
2N/A * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
2N/A * If applicable, add the following below this CDDL HEADER, with the
2N/A * fields enclosed by brackets "[]" replaced with your own identifying
2N/A * information: Portions Copyright [yyyy] [name of copyright owner]
2N/A *
2N/A * CDDL HEADER END
2N/A */
2N/A/*
2N/A * Copyright (c) 2002-2003, Network Appliance, Inc. All rights reserved.
2N/A */
2N/A
2N/A/*
2N/A * Copyright 2004 Sun Microsystems, Inc. All rights reserved.
2N/A * Use is subject to license terms.
2N/A */
2N/A
2N/A#pragma ident "%Z%%M% %I% %E% SMI"
2N/A
2N/A
2N/A/*
2N/A *
2N/A * MODULE: dat_sr_parser.c
2N/A *
2N/A * PURPOSE: static registry parser
2N/A *
2N/A * $Id: udat_sr_parser.c,v 1.1 2003/07/31 14:04:19 jlentini Exp $
2N/A */
2N/A
2N/A
2N/A#include "udat_sr_parser.h"
2N/A#include "dat_sr.h"
2N/A
2N/A
2N/A/*
2N/A *
2N/A * Constants
2N/A *
2N/A */
2N/A
2N/A#define DAT_SR_CONF_ENV "DAT_OVERRIDE"
2N/A#define DAT_SR_CONF_DEFAULT "/etc/dat/dat.conf"
2N/A
2N/A#define DAT_SR_TOKEN_THREADSAFE "threadsafe"
2N/A#define DAT_SR_TOKEN_NONTHREADSAFE "nonthreadsafe"
2N/A#define DAT_SR_TOKEN_DEFAULT "default"
2N/A#define DAT_SR_TOKEN_NONDEFAULT "nondefault"
2N/A
2N/A#define DAT_SR_CHAR_NEWLINE '\n'
2N/A#define DAT_SR_CHAR_COMMENT '#'
2N/A#define DAT_SR_CHAR_QUOTE '"'
2N/A#define DAT_SR_CHAR_BACKSLASH '\\'
2N/A
2N/A
2N/A/*
2N/A *
2N/A * Enumerations
2N/A *
2N/A */
2N/A
2N/Atypedef enum
2N/A{
2N/A DAT_SR_TOKEN_STRING, /* text field (both quoted or unquoted) */
2N/A DAT_SR_TOKEN_EOR, /* end of record (newline) */
2N/A DAT_SR_TOKEN_EOF /* end of file */
2N/A} DAT_SR_TOKEN_TYPE;
2N/A
2N/Atypedef enum
2N/A{
2N/A DAT_SR_API_UDAT,
2N/A DAT_SR_API_KDAT
2N/A} DAT_SR_API_TYPE;
2N/A
2N/A
2N/A/*
2N/A *
2N/A * Structures
2N/A *
2N/A */
2N/A
2N/Atypedef struct
2N/A{
2N/A DAT_SR_TOKEN_TYPE type;
2N/A char *value; /* valid if type is DAT_SR_TOKEN_STRING */
2N/A DAT_OS_SIZE value_len;
2N/A} DAT_SR_TOKEN;
2N/A
2N/Atypedef struct DAT_SR_STACK_NODE
2N/A{
2N/A DAT_SR_TOKEN token;
2N/A struct DAT_SR_STACK_NODE *next;
2N/A} DAT_SR_STACK_NODE;
2N/A
2N/Atypedef struct
2N/A{
2N/A DAT_UINT32 major;
2N/A DAT_UINT32 minor;
2N/A} DAT_SR_VERSION;
2N/A
2N/Atypedef struct
2N/A{
2N/A char *id;
2N/A DAT_SR_VERSION version;
2N/A} DAT_SR_PROVIDER_VERSION;
2N/A
2N/Atypedef struct
2N/A{
2N/A DAT_SR_API_TYPE type;
2N/A DAT_SR_VERSION version;
2N/A} DAT_SR_API_VERSION;
2N/A
2N/Atypedef struct
2N/A{
2N/A char *ia_name;
2N/A DAT_SR_API_VERSION api_version;
2N/A DAT_BOOLEAN is_thread_safe;
2N/A DAT_BOOLEAN is_default;
2N/A char *lib_path;
2N/A DAT_SR_PROVIDER_VERSION provider_version;
2N/A char *ia_params;
2N/A char *platform_params;
2N/A} DAT_SR_CONF_ENTRY;
2N/A
2N/A
2N/A/*
2N/A *
2N/A * Internal Function Declarations
2N/A *
2N/A */
2N/A
2N/Astatic DAT_RETURN
2N/Adat_sr_load_entry(
2N/A DAT_SR_CONF_ENTRY *entry);
2N/A
2N/Astatic DAT_BOOLEAN
2N/Adat_sr_is_valid_entry(
2N/A DAT_SR_CONF_ENTRY *entry);
2N/A
2N/Astatic char *
2N/Adat_sr_type_to_str(
2N/A DAT_SR_TOKEN_TYPE type);
2N/A
2N/Astatic DAT_RETURN
2N/Adat_sr_parse_eof(
2N/A DAT_OS_FILE *file);
2N/A
2N/Astatic DAT_RETURN
2N/Adat_sr_parse_entry(
2N/A DAT_OS_FILE *file);
2N/A
2N/Astatic DAT_RETURN
2N/Adat_sr_parse_ia_name(
2N/A DAT_OS_FILE *file,
2N/A DAT_SR_CONF_ENTRY *entry);
2N/A
2N/Astatic DAT_RETURN
2N/Adat_sr_parse_api(
2N/A DAT_OS_FILE *file,
2N/A DAT_SR_CONF_ENTRY *entry);
2N/A
2N/Astatic DAT_RETURN
2N/Adat_sr_parse_thread_safety(
2N/A DAT_OS_FILE *file,
2N/A DAT_SR_CONF_ENTRY *entry);
2N/A
2N/Astatic DAT_RETURN
2N/Adat_sr_parse_default(
2N/A DAT_OS_FILE *file,
2N/A DAT_SR_CONF_ENTRY *entry);
2N/A
2N/Astatic DAT_RETURN
2N/Adat_sr_parse_lib_path(
2N/A DAT_OS_FILE *file,
2N/A DAT_SR_CONF_ENTRY *entry);
2N/A
2N/Astatic DAT_RETURN
2N/Adat_sr_parse_provider_version(
2N/A DAT_OS_FILE *file,
2N/A DAT_SR_CONF_ENTRY *entry);
2N/A
2N/Astatic DAT_RETURN
2N/Adat_sr_parse_ia_params(
2N/A DAT_OS_FILE *file,
2N/A DAT_SR_CONF_ENTRY *entry);
2N/A
2N/Astatic DAT_RETURN
2N/Adat_sr_parse_platform_params(
2N/A DAT_OS_FILE *file,
2N/A DAT_SR_CONF_ENTRY *entry);
2N/A
2N/Astatic DAT_RETURN
2N/Adat_sr_parse_eoe(
2N/A DAT_OS_FILE *file,
2N/A DAT_SR_CONF_ENTRY *entry);
2N/A
2N/Astatic DAT_RETURN
2N/Adat_sr_convert_api(
2N/A char *str,
2N/A DAT_SR_API_VERSION *api_version);
2N/A
2N/Astatic DAT_RETURN
2N/Adat_sr_convert_thread_safety(
2N/A char *str,
2N/A DAT_BOOLEAN *is_thread_safe);
2N/A
2N/Astatic DAT_RETURN
2N/Adat_sr_convert_default(
2N/A char *str,
2N/A DAT_BOOLEAN *is_default);
2N/A
2N/Astatic DAT_RETURN
2N/Adat_sr_convert_provider_version(
2N/A char *str,
2N/A DAT_SR_PROVIDER_VERSION *provider_version);
2N/A
2N/Astatic DAT_RETURN
2N/Adat_sr_get_token(
2N/A DAT_OS_FILE *file,
2N/A DAT_SR_TOKEN *token);
2N/A
2N/Astatic DAT_RETURN
2N/Adat_sr_put_token(
2N/A DAT_OS_FILE *file,
2N/A DAT_SR_TOKEN *token);
2N/A
2N/Astatic DAT_RETURN
2N/Adat_sr_read_token(
2N/A DAT_OS_FILE *file,
2N/A DAT_SR_TOKEN *token);
2N/A
2N/Astatic DAT_RETURN
2N/Adat_sr_read_str(
2N/A DAT_OS_FILE *file,
2N/A DAT_SR_TOKEN *token,
2N/A DAT_OS_SIZE token_len);
2N/A
2N/Astatic DAT_RETURN
2N/Adat_sr_read_quoted_str(
2N/A DAT_OS_FILE *file,
2N/A DAT_SR_TOKEN *token,
2N/A DAT_OS_SIZE token_len,
2N/A DAT_COUNT num_escape_seq);
2N/A
2N/Astatic void
2N/Adat_sr_read_comment(
2N/A DAT_OS_FILE *file);
2N/A
2N/A
2N/A/*
2N/A *
2N/A * Global Variables
2N/A *
2N/A */
2N/A
2N/Astatic DAT_SR_STACK_NODE *g_token_stack = NULL;
2N/A
2N/A
2N/A/*
2N/A *
2N/A * External Function Definitions
2N/A *
2N/A */
2N/A
2N/A/*
2N/A * Function: dat_sr_load
2N/A */
2N/A
2N/ADAT_RETURN
2N/Adat_sr_load(void)
2N/A{
2N/A char *sr_path;
2N/A DAT_OS_FILE *sr_file;
2N/A
2N/A sr_path = dat_os_getenv(DAT_SR_CONF_ENV);
2N/A if (sr_path == NULL) {
2N/A sr_path = DAT_SR_CONF_DEFAULT;
2N/A }
2N/A
2N/A dat_os_dbg_print(DAT_OS_DBG_TYPE_SR,
2N/A "DAT Registry: static registry file <%s> \n", sr_path);
2N/A
2N/A sr_file = dat_os_fopen(sr_path);
2N/A if (sr_file == NULL) {
2N/A return (DAT_INTERNAL_ERROR);
2N/A }
2N/A
2N/A for (;;) {
2N/A if (DAT_SUCCESS == dat_sr_parse_eof(sr_file)) {
2N/A break;
2N/A } else if (DAT_SUCCESS == dat_sr_parse_entry(sr_file)) {
2N/A continue;
2N/A } else {
2N/A dat_os_assert(!"unable to parse static registry file");
2N/A break;
2N/A }
2N/A }
2N/A
2N/A if (0 != dat_os_fclose(sr_file)) {
2N/A return (DAT_INTERNAL_ERROR);
2N/A }
2N/A
2N/A return (DAT_SUCCESS);
2N/A}
2N/A
2N/A
2N/A/*
2N/A *
2N/A * Internal Function Definitions
2N/A *
2N/A */
2N/A
2N/A/*
2N/A * Function: dat_sr_is_valid_entry
2N/A */
2N/A
2N/ADAT_BOOLEAN
2N/Adat_sr_is_valid_entry(
2N/A DAT_SR_CONF_ENTRY *entry)
2N/A{
2N/A if ((DAT_SR_API_UDAT == entry->api_version.type) &&
2N/A (entry->is_default)) {
2N/A return (DAT_TRUE);
2N/A } else {
2N/A return (DAT_FALSE);
2N/A }
2N/A}
2N/A
2N/A
2N/A/*
2N/A * Function: dat_sr_load_entry
2N/A */
2N/A
2N/ADAT_RETURN
2N/Adat_sr_load_entry(
2N/A DAT_SR_CONF_ENTRY *conf_entry)
2N/A{
2N/A DAT_SR_ENTRY entry;
2N/A
2N/A if (DAT_NAME_MAX_LENGTH < (strlen(conf_entry->ia_name) + 1)) {
2N/A dat_os_dbg_print(DAT_OS_DBG_TYPE_SR,
2N/A "DAT Registry: ia name %s is longer than "
2N/A "DAT_NAME_MAX_LENGTH (%i)\n",
2N/A conf_entry->ia_name, DAT_NAME_MAX_LENGTH);
2N/A
2N/A return (DAT_INSUFFICIENT_RESOURCES);
2N/A }
2N/A
2N/A (void) dat_os_strncpy(entry.info.ia_name, conf_entry->ia_name,
2N/A DAT_NAME_MAX_LENGTH);
2N/A entry.info.dapl_version_major = conf_entry->api_version.version.major;
2N/A entry.info.dapl_version_minor = conf_entry->api_version.version.minor;
2N/A entry.info.is_thread_safe = conf_entry->is_thread_safe;
2N/A entry.lib_path = conf_entry->lib_path;
2N/A entry.ia_params = conf_entry->ia_params;
2N/A entry.lib_handle = NULL;
2N/A entry.ref_count = 0;
2N/A
2N/A dat_os_dbg_print(DAT_OS_DBG_TYPE_SR,
2N/A "DAT Registry: loading provider for %s\n",
2N/A conf_entry->ia_name);
2N/A
2N/A return (dat_sr_insert(&entry.info, &entry));
2N/A}
2N/A
2N/A
2N/A/*
2N/A * Function: dat_sr_type_to_str
2N/A */
2N/A
2N/Achar *
2N/Adat_sr_type_to_str(
2N/A DAT_SR_TOKEN_TYPE type)
2N/A{
2N/A static char *str_array[] = { "string", "eor", "eof" };
2N/A
2N/A if ((type < 0) || (2 < type)) {
2N/A return ("error: invalid token type");
2N/A }
2N/A
2N/A return (str_array[type]);
2N/A}
2N/A
2N/A
2N/A/*
2N/A * Function: dat_sr_parse_eof
2N/A */
2N/A
2N/ADAT_RETURN
2N/Adat_sr_parse_eof(
2N/A DAT_OS_FILE *file)
2N/A{
2N/A DAT_SR_TOKEN token;
2N/A
2N/A if (DAT_SUCCESS != dat_sr_get_token(file, &token)) {
2N/A return (DAT_INTERNAL_ERROR);
2N/A }
2N/A
2N/A if (DAT_SR_TOKEN_EOF == token.type) {
2N/A return (DAT_SUCCESS);
2N/A } else {
2N/A (void) dat_sr_put_token(file, &token);
2N/A return (DAT_INTERNAL_ERROR);
2N/A }
2N/A}
2N/A
2N/A
2N/A/*
2N/A * Function: dat_sr_parse_ia_name
2N/A */
2N/A
2N/ADAT_RETURN
2N/Adat_sr_parse_entry(
2N/A DAT_OS_FILE *file)
2N/A{
2N/A DAT_SR_CONF_ENTRY entry;
2N/A DAT_RETURN status;
2N/A
2N/A (void) dat_os_memset(&entry, 0, sizeof (DAT_SR_CONF_ENTRY));
2N/A
2N/A if ((DAT_SUCCESS == dat_sr_parse_ia_name(file, &entry)) &&
2N/A (DAT_SUCCESS == dat_sr_parse_api(file, &entry)) &&
2N/A (DAT_SUCCESS == dat_sr_parse_thread_safety(file, &entry)) &&
2N/A (DAT_SUCCESS == dat_sr_parse_default(file, &entry)) &&
2N/A (DAT_SUCCESS == dat_sr_parse_lib_path(file, &entry)) &&
2N/A (DAT_SUCCESS == dat_sr_parse_provider_version(file, &entry)) &&
2N/A (DAT_SUCCESS == dat_sr_parse_ia_params(file, &entry)) &&
2N/A (DAT_SUCCESS == dat_sr_parse_platform_params(file, &entry)) &&
2N/A (DAT_SUCCESS == dat_sr_parse_eoe(file, &entry))) {
2N/A dat_os_dbg_print(DAT_OS_DBG_TYPE_SR,
2N/A "\n"
2N/A "DAT Registry: entry \n"
2N/A " ia_name %s\n"
2N/A " api_version\n"
2N/A " type 0x%X\n"
2N/A " major.minor %d.%d\n"
2N/A " is_thread_safe %d\n"
2N/A " is_default %d\n"
2N/A " lib_path %s\n"
2N/A " provider_version\n"
2N/A " id %s\n"
2N/A " major.minor %d.%d\n"
2N/A " ia_params %s\n"
2N/A "\n",
2N/A entry.ia_name,
2N/A entry.api_version.type,
2N/A entry.api_version.version.major,
2N/A entry.api_version.version.minor,
2N/A entry.is_thread_safe,
2N/A entry.is_default,
2N/A entry.lib_path,
2N/A entry.provider_version.id,
2N/A entry.provider_version.version.major,
2N/A entry.provider_version.version.minor,
2N/A entry.ia_params);
2N/A
2N/A if (DAT_TRUE == dat_sr_is_valid_entry(&entry)) {
2N/A /*
2N/A * The static registry configuration file may have
2N/A * multiple entries with the same IA name. The first
2N/A * entry will be installed in the static registry
2N/A * causing subsequent attempts to register the same IA
2N/A * name to fail. Therefore the return code from
2N/A * dat_sr_load_entry() is ignored.
2N/A */
2N/A (void) dat_sr_load_entry(&entry);
2N/A }
2N/A
2N/A status = DAT_SUCCESS;
2N/A } else { /* resync */
2N/A DAT_SR_TOKEN token;
2N/A
2N/A /*
2N/A * The static registry format is specified in the DAT
2N/A * specification. While the registry file's contents may change
2N/A * between revisions of the specification, there is no way to
2N/A * determine the specification version to which the
2N/A * configuration file conforms. If an entry is found that does
2N/A * not match the expected format, the entry is discarded
2N/A * and the parsing of the file continues. There is no way to
2N/A * determine if the entry was an error or an entry confirming
2N/A * to an alternate version of specification.
2N/A */
2N/A
2N/A for (;;) {
2N/A if (DAT_SUCCESS != dat_sr_get_token(file, &token)) {
2N/A status = DAT_INTERNAL_ERROR;
2N/A break;
2N/A }
2N/A
2N/A if (DAT_SR_TOKEN_STRING != token.type) {
2N/A status = DAT_SUCCESS;
2N/A break;
2N/A } else {
2N/A dat_os_free(token.value,
2N/A (sizeof (char) *
2N/A dat_os_strlen(token.value)) + 1);
2N/A continue;
2N/A }
2N/A }
2N/A }
2N/A
2N/A /* free resources */
2N/A if (NULL != entry.ia_name) {
2N/A dat_os_free(entry.ia_name,
2N/A sizeof (char) * (dat_os_strlen(entry.ia_name) + 1));
2N/A }
2N/A if (NULL != entry.lib_path) {
2N/A dat_os_free(entry.lib_path,
2N/A sizeof (char) * (dat_os_strlen(entry.lib_path) + 1));
2N/A }
2N/A
2N/A if (NULL != entry.provider_version.id) {
2N/A dat_os_free(entry.provider_version.id,
2N/A sizeof (char) *
2N/A (dat_os_strlen(entry.provider_version.id) + 1));
2N/A }
2N/A
2N/A if (NULL != entry.ia_params) {
2N/A dat_os_free(entry.ia_params,
2N/A sizeof (char) * (dat_os_strlen(entry.ia_params) + 1));
2N/A }
2N/A
2N/A return (status);
2N/A}
2N/A
2N/A
2N/A/*
2N/A * Function: dat_sr_parse_ia_name
2N/A */
2N/A
2N/ADAT_RETURN
2N/Adat_sr_parse_ia_name(
2N/A DAT_OS_FILE *file,
2N/A DAT_SR_CONF_ENTRY *entry)
2N/A{
2N/A DAT_SR_TOKEN token;
2N/A DAT_RETURN status;
2N/A
2N/A if (DAT_SUCCESS != dat_sr_get_token(file, &token)) {
2N/A return (DAT_INTERNAL_ERROR);
2N/A }
2N/A
2N/A if (DAT_SR_TOKEN_STRING != token.type) {
2N/A status = DAT_INTERNAL_ERROR;
2N/A } else {
2N/A entry->ia_name = token.value;
2N/A
2N/A status = DAT_SUCCESS;
2N/A }
2N/A
2N/A if (DAT_SUCCESS != status) {
2N/A DAT_RETURN status_success;
2N/A
2N/A status_success = dat_sr_put_token(file, &token);
2N/A dat_os_assert(DAT_SUCCESS == status_success);
2N/A }
2N/A
2N/A return (status);
2N/A}
2N/A
2N/A
2N/A/*
2N/A * Function: dat_sr_parse_ia_name
2N/A */
2N/A
2N/ADAT_RETURN
2N/Adat_sr_parse_api(
2N/A DAT_OS_FILE *file,
2N/A DAT_SR_CONF_ENTRY *entry)
2N/A{
2N/A DAT_SR_TOKEN token;
2N/A DAT_RETURN status;
2N/A
2N/A if (DAT_SUCCESS != dat_sr_get_token(file, &token)) {
2N/A return (DAT_INTERNAL_ERROR);
2N/A }
2N/A
2N/A if (DAT_SR_TOKEN_STRING != token.type) {
2N/A status = DAT_INTERNAL_ERROR;
2N/A } else if (DAT_SUCCESS != dat_sr_convert_api(
2N/A token.value, &entry->api_version)) {
2N/A status = DAT_INTERNAL_ERROR;
2N/A } else {
2N/A dat_os_free(token.value,
2N/A (sizeof (char) * dat_os_strlen(token.value)) + 1);
2N/A
2N/A status = DAT_SUCCESS;
2N/A }
2N/A
2N/A if (DAT_SUCCESS != status) {
2N/A DAT_RETURN status_success;
2N/A
2N/A status_success = dat_sr_put_token(file, &token);
2N/A dat_os_assert(DAT_SUCCESS == status_success);
2N/A }
2N/A
2N/A return (status);
2N/A}
2N/A
2N/A
2N/A/*
2N/A * Function: dat_sr_parse_thread_safety
2N/A */
2N/A
2N/Astatic DAT_RETURN
2N/Adat_sr_parse_thread_safety(
2N/A DAT_OS_FILE *file,
2N/A DAT_SR_CONF_ENTRY *entry)
2N/A{
2N/A DAT_SR_TOKEN token;
2N/A DAT_RETURN status;
2N/A
2N/A if (DAT_SUCCESS != dat_sr_get_token(file, &token)) {
2N/A return (DAT_INTERNAL_ERROR);
2N/A }
2N/A
2N/A if (DAT_SR_TOKEN_STRING != token.type) {
2N/A status = DAT_INTERNAL_ERROR;
2N/A } else if (DAT_SUCCESS != dat_sr_convert_thread_safety(
2N/A token.value, &entry->is_thread_safe)) {
2N/A status = DAT_INTERNAL_ERROR;
2N/A } else {
2N/A dat_os_free(token.value,
2N/A (sizeof (char) * dat_os_strlen(token.value)) + 1);
2N/A
2N/A status = DAT_SUCCESS;
2N/A }
2N/A
2N/A if (DAT_SUCCESS != status) {
2N/A DAT_RETURN status_success;
2N/A
2N/A status_success = dat_sr_put_token(file, &token);
2N/A dat_os_assert(DAT_SUCCESS == status_success);
2N/A }
2N/A
2N/A return (status);
2N/A}
2N/A
2N/A
2N/A/*
2N/A * Function: dat_sr_parse_default
2N/A */
2N/A
2N/ADAT_RETURN
2N/Adat_sr_parse_default(
2N/A DAT_OS_FILE *file,
2N/A DAT_SR_CONF_ENTRY *entry)
2N/A{
2N/A DAT_SR_TOKEN token;
2N/A DAT_RETURN status;
2N/A
2N/A if (DAT_SUCCESS != dat_sr_get_token(file, &token)) {
2N/A return (DAT_INTERNAL_ERROR);
2N/A }
2N/A
2N/A if (DAT_SR_TOKEN_STRING != token.type) {
2N/A status = DAT_INTERNAL_ERROR;
2N/A } else if (DAT_SUCCESS != dat_sr_convert_default(
2N/A token.value, &entry->is_default)) {
2N/A status = DAT_INTERNAL_ERROR;
2N/A } else {
2N/A dat_os_free(token.value,
2N/A (sizeof (char) * dat_os_strlen(token.value)) + 1);
2N/A
2N/A status = DAT_SUCCESS;
2N/A }
2N/A
2N/A if (DAT_SUCCESS != status) {
2N/A DAT_RETURN status_success;
2N/A
2N/A status_success = dat_sr_put_token(file, &token);
2N/A dat_os_assert(DAT_SUCCESS == status_success);
2N/A }
2N/A
2N/A return (status);
2N/A}
2N/A
2N/A
2N/A/*
2N/A * Function: dat_sr_parse_lib_path
2N/A */
2N/A
2N/ADAT_RETURN
2N/Adat_sr_parse_lib_path(
2N/A DAT_OS_FILE *file,
2N/A DAT_SR_CONF_ENTRY *entry)
2N/A{
2N/A DAT_SR_TOKEN token;
2N/A DAT_RETURN status;
2N/A
2N/A if (DAT_SUCCESS != dat_sr_get_token(file, &token)) {
2N/A return (DAT_INTERNAL_ERROR);
2N/A }
2N/A
2N/A if (DAT_SR_TOKEN_STRING != token.type) {
2N/A status = DAT_INTERNAL_ERROR;
2N/A } else {
2N/A entry->lib_path = token.value;
2N/A
2N/A status = DAT_SUCCESS;
2N/A }
2N/A
2N/A if (DAT_SUCCESS != status) {
2N/A DAT_RETURN status_success;
2N/A
2N/A status_success = dat_sr_put_token(file, &token);
2N/A dat_os_assert(DAT_SUCCESS == status_success);
2N/A }
2N/A
2N/A return (status);
2N/A}
2N/A
2N/A/*
2N/A * Function: dat_sr_parse_provider_version
2N/A */
2N/A
2N/ADAT_RETURN
2N/Adat_sr_parse_provider_version(
2N/A DAT_OS_FILE *file,
2N/A DAT_SR_CONF_ENTRY *entry)
2N/A{
2N/A DAT_SR_TOKEN token;
2N/A DAT_RETURN status;
2N/A
2N/A if (DAT_SUCCESS != dat_sr_get_token(file, &token)) {
2N/A return (DAT_INTERNAL_ERROR);
2N/A }
2N/A
2N/A if (DAT_SR_TOKEN_STRING != token.type) {
2N/A status = DAT_INTERNAL_ERROR;
2N/A } else if (DAT_SUCCESS != dat_sr_convert_provider_version(
2N/A token.value, &entry->provider_version)) {
2N/A status = DAT_INTERNAL_ERROR;
2N/A } else {
2N/A dat_os_free(token.value,
2N/A (sizeof (char) * dat_os_strlen(token.value)) + 1);
2N/A
2N/A status = DAT_SUCCESS;
2N/A }
2N/A
2N/A if (DAT_SUCCESS != status) {
2N/A DAT_RETURN status_success;
2N/A
2N/A status_success = dat_sr_put_token(file, &token);
2N/A dat_os_assert(DAT_SUCCESS == status_success);
2N/A }
2N/A
2N/A return (status);
2N/A}
2N/A
2N/A
2N/A/*
2N/A * Function: dat_sr_parse_ia_params
2N/A */
2N/A
2N/ADAT_RETURN
2N/Adat_sr_parse_ia_params(
2N/A DAT_OS_FILE *file,
2N/A DAT_SR_CONF_ENTRY *entry)
2N/A{
2N/A DAT_SR_TOKEN token;
2N/A DAT_RETURN status;
2N/A
2N/A if (DAT_SUCCESS != dat_sr_get_token(file, &token)) {
2N/A return (DAT_INTERNAL_ERROR);
2N/A }
2N/A
2N/A if (DAT_SR_TOKEN_STRING != token.type) {
2N/A status = DAT_INTERNAL_ERROR;
2N/A } else {
2N/A entry->ia_params = token.value;
2N/A
2N/A status = DAT_SUCCESS;
2N/A }
2N/A
2N/A if (DAT_SUCCESS != status) {
2N/A DAT_RETURN status_success;
2N/A
2N/A status_success = dat_sr_put_token(file, &token);
2N/A dat_os_assert(DAT_SUCCESS == status_success);
2N/A }
2N/A
2N/A return (status);
2N/A}
2N/A
2N/A
2N/A/*
2N/A * Function: dat_sr_parse_platform_params
2N/A */
2N/A
2N/ADAT_RETURN
2N/Adat_sr_parse_platform_params(
2N/A DAT_OS_FILE *file,
2N/A DAT_SR_CONF_ENTRY *entry)
2N/A{
2N/A DAT_SR_TOKEN token;
2N/A DAT_RETURN status;
2N/A
2N/A if (DAT_SUCCESS != dat_sr_get_token(file, &token)) {
2N/A return (DAT_INTERNAL_ERROR);
2N/A }
2N/A
2N/A if (DAT_SR_TOKEN_STRING != token.type) {
2N/A status = DAT_INTERNAL_ERROR;
2N/A } else {
2N/A entry->platform_params = token.value;
2N/A
2N/A status = DAT_SUCCESS;
2N/A }
2N/A
2N/A if (DAT_SUCCESS != status) {
2N/A DAT_RETURN status_success;
2N/A
2N/A status_success = dat_sr_put_token(file, &token);
2N/A dat_os_assert(DAT_SUCCESS == status_success);
2N/A }
2N/A
2N/A return (status);
2N/A}
2N/A
2N/A
2N/A/*
2N/A * Function: dat_sr_parse_eoe
2N/A */
2N/A
2N/ADAT_RETURN
2N/Adat_sr_parse_eoe(
2N/A DAT_OS_FILE *file,
2N/A DAT_SR_CONF_ENTRY *entry) /*ARGSUSED*/
2N/A{
2N/A DAT_SR_TOKEN token;
2N/A DAT_RETURN status;
2N/A
2N/A if (DAT_SUCCESS != dat_sr_get_token(file, &token)) {
2N/A return (DAT_INTERNAL_ERROR);
2N/A }
2N/A
2N/A if ((DAT_SR_TOKEN_EOF != token.type) &&
2N/A (DAT_SR_TOKEN_EOR != token.type)) {
2N/A status = DAT_INTERNAL_ERROR;
2N/A } else {
2N/A status = DAT_SUCCESS;
2N/A }
2N/A
2N/A if (DAT_SUCCESS != status) {
2N/A DAT_RETURN status_success;
2N/A
2N/A status_success = dat_sr_put_token(file, &token);
2N/A dat_os_assert(DAT_SUCCESS == status_success);
2N/A }
2N/A
2N/A return (status);
2N/A}
2N/A
2N/A
2N/A/*
2N/A * Function: dat_sr_convert_api
2N/A */
2N/A
2N/ADAT_RETURN
2N/Adat_sr_convert_api(
2N/A char *str,
2N/A DAT_SR_API_VERSION *api_version)
2N/A{
2N/A int i;
2N/A int minor_i;
2N/A
2N/A dat_os_assert(0 < dat_os_strlen(str));
2N/A
2N/A if ('u' == str[0]) {
2N/A api_version->type = DAT_SR_API_UDAT;
2N/A } else if ('k' == str[0]) {
2N/A api_version->type = DAT_SR_API_KDAT;
2N/A } else {
2N/A return (DAT_INTERNAL_ERROR);
2N/A }
2N/A
2N/A for (i = 1 /* move past initial [u|k] */; '\0' != str[i]; i++) {
2N/A if ('.' == str[i]) {
2N/A break;
2N/A } else if (DAT_TRUE != dat_os_isdigit(str[i])) {
2N/A return (DAT_INTERNAL_ERROR);
2N/A }
2N/A }
2N/A
2N/A api_version->version.major = (DAT_UINT32)dat_os_strtol(str + 1, NULL,
2N/A 10);
2N/A
2N/A /* move past '.' */
2N/A minor_i = ++i;
2N/A
2N/A for (; '\0' != str[i]; i++) {
2N/A if (DAT_TRUE != dat_os_isdigit(str[i])) {
2N/A return (DAT_INTERNAL_ERROR);
2N/A }
2N/A }
2N/A
2N/A api_version->version.minor = (DAT_UINT32)dat_os_strtol(str + minor_i,
2N/A NULL, 10);
2N/A
2N/A if ('\0' != str[i]) {
2N/A return (DAT_INTERNAL_ERROR);
2N/A }
2N/A
2N/A return (DAT_SUCCESS);
2N/A}
2N/A
2N/A
2N/A/*
2N/A * Function: dat_sr_convert_thread_safety
2N/A */
2N/A
2N/Astatic DAT_RETURN
2N/Adat_sr_convert_thread_safety(
2N/A char *str,
2N/A DAT_BOOLEAN *is_thread_safe)
2N/A{
2N/A if (!dat_os_strncmp(str,
2N/A DAT_SR_TOKEN_THREADSAFE,
2N/A dat_os_strlen(DAT_SR_TOKEN_THREADSAFE))) {
2N/A *is_thread_safe = DAT_TRUE;
2N/A return (DAT_SUCCESS);
2N/A } else if (!dat_os_strncmp(str,
2N/A DAT_SR_TOKEN_NONTHREADSAFE,
2N/A dat_os_strlen(DAT_SR_TOKEN_NONTHREADSAFE))) {
2N/A *is_thread_safe = DAT_FALSE;
2N/A return (DAT_SUCCESS);
2N/A } else {
2N/A return (DAT_INTERNAL_ERROR);
2N/A }
2N/A}
2N/A
2N/A
2N/A/*
2N/A * Function: dat_sr_convert_default
2N/A */
2N/A
2N/Astatic DAT_RETURN
2N/Adat_sr_convert_default(
2N/A char *str,
2N/A DAT_BOOLEAN *is_default)
2N/A{
2N/A if (!dat_os_strncmp(str,
2N/A DAT_SR_TOKEN_DEFAULT,
2N/A dat_os_strlen(DAT_SR_TOKEN_DEFAULT))) {
2N/A *is_default = DAT_TRUE;
2N/A return (DAT_SUCCESS);
2N/A } else if (!dat_os_strncmp(str,
2N/A DAT_SR_TOKEN_NONDEFAULT,
2N/A dat_os_strlen(DAT_SR_TOKEN_NONDEFAULT))) {
2N/A *is_default = DAT_FALSE;
2N/A return (DAT_SUCCESS);
2N/A } else {
2N/A return (DAT_INTERNAL_ERROR);
2N/A }
2N/A}
2N/A
2N/A
2N/A/*
2N/A * Function: dat_sr_convert_provider_version
2N/A */
2N/A
2N/ADAT_RETURN
2N/Adat_sr_convert_provider_version(
2N/A char *str,
2N/A DAT_SR_PROVIDER_VERSION *provider_version)
2N/A{
2N/A DAT_RETURN status;
2N/A int i;
2N/A int decimal_i;
2N/A
2N/A dat_os_assert(0 < dat_os_strlen(str));
2N/A dat_os_assert(NULL == provider_version->id);
2N/A
2N/A status = DAT_SUCCESS;
2N/A
2N/A for (i = 0; '\0' != str[i]; i++) {
2N/A if ('.' == str[i]) {
2N/A break;
2N/A }
2N/A }
2N/A
2N/A /* if no id value was found */
2N/A if (0 == i) {
2N/A status = DAT_INTERNAL_ERROR;
2N/A goto exit;
2N/A }
2N/A
2N/A if (NULL == (provider_version->id = dat_os_alloc(sizeof (char) *
2N/A (i + 1)))) {
2N/A status = DAT_INSUFFICIENT_RESOURCES | DAT_RESOURCE_MEMORY;
2N/A goto exit;
2N/A }
2N/A
2N/A (void) dat_os_strncpy(provider_version->id, str, i);
2N/A provider_version->id[i] = '\0';
2N/A
2N/A /* move past '.' */
2N/A decimal_i = ++i;
2N/A
2N/A for (; '\0' != str[i]; i++) {
2N/A if ('.' == str[i]) {
2N/A break;
2N/A } else if (DAT_TRUE != dat_os_isdigit(str[i])) {
2N/A status = DAT_INTERNAL_ERROR;
2N/A goto exit;
2N/A }
2N/A }
2N/A
2N/A /* if no version value was found */
2N/A if (decimal_i == i) {
2N/A status = DAT_INTERNAL_ERROR;
2N/A goto exit;
2N/A }
2N/A
2N/A provider_version->version.major = (DAT_UINT32)
2N/A dat_os_strtol(str + decimal_i, NULL, 10);
2N/A
2N/A /* move past '.' */
2N/A decimal_i = ++i;
2N/A
2N/A for (; '\0' != str[i]; i++) {
2N/A if (DAT_TRUE != dat_os_isdigit(str[i])) {
2N/A status = DAT_INTERNAL_ERROR;
2N/A goto exit;
2N/A }
2N/A }
2N/A
2N/A /* if no version value was found */
2N/A if (decimal_i == i) {
2N/A status = DAT_INTERNAL_ERROR;
2N/A goto exit;
2N/A }
2N/A
2N/A provider_version->version.minor = (DAT_UINT32)
2N/A dat_os_strtol(str + decimal_i, NULL, 10);
2N/A
2N/A if ('\0' != str[i]) {
2N/A status = DAT_INTERNAL_ERROR;
2N/A goto exit;
2N/A }
2N/A
2N/Aexit:
2N/A if (DAT_SUCCESS != status) {
2N/A if (NULL != provider_version->id) {
2N/A dat_os_free(provider_version->id,
2N/A sizeof (char) *
2N/A (dat_os_strlen(provider_version->id) + 1));
2N/A provider_version->id = NULL;
2N/A }
2N/A }
2N/A
2N/A return (status);
2N/A}
2N/A
2N/A
2N/A/*
2N/A * Function: dat_sr_get_token
2N/A */
2N/A
2N/ADAT_RETURN
2N/Adat_sr_get_token(
2N/A DAT_OS_FILE *file,
2N/A DAT_SR_TOKEN *token)
2N/A{
2N/A if (NULL == g_token_stack) {
2N/A return (dat_sr_read_token(file, token));
2N/A } else {
2N/A DAT_SR_STACK_NODE *top;
2N/A
2N/A top = g_token_stack;
2N/A
2N/A *token = top->token;
2N/A g_token_stack = top->next;
2N/A
2N/A dat_os_free(top, sizeof (DAT_SR_STACK_NODE));
2N/A
2N/A return (DAT_SUCCESS);
2N/A }
2N/A}
2N/A
2N/A
2N/A/*
2N/A * Function: dat_sr_put_token
2N/A */
2N/A
2N/ADAT_RETURN
2N/Adat_sr_put_token(
2N/A DAT_OS_FILE *file,
2N/A DAT_SR_TOKEN *token) /*ARGSUSED*/
2N/A{
2N/A DAT_SR_STACK_NODE *top;
2N/A
2N/A if (NULL == (top = dat_os_alloc(sizeof (DAT_SR_STACK_NODE)))) {
2N/A return (DAT_INSUFFICIENT_RESOURCES | DAT_RESOURCE_MEMORY);
2N/A }
2N/A
2N/A top->token = *token;
2N/A top->next = g_token_stack;
2N/A g_token_stack = top;
2N/A
2N/A return (DAT_SUCCESS);
2N/A}
2N/A
2N/A
2N/A/*
2N/A * Function: dat_sr_read_token
2N/A */
2N/A
2N/ADAT_RETURN
2N/Adat_sr_read_token(
2N/A DAT_OS_FILE *file,
2N/A DAT_SR_TOKEN *token)
2N/A{
2N/A DAT_OS_FILE_POS pos;
2N/A DAT_OS_SIZE token_len;
2N/A DAT_COUNT num_escape_seq;
2N/A DAT_BOOLEAN is_quoted_str;
2N/A DAT_BOOLEAN is_prev_char_backslash;
2N/A
2N/A /*
2N/A * The DAT standard does not specify a maximum size for quoted strings.
2N/A * Therefore the tokenizer must be able to read in a token of arbitrary
2N/A * size. Instead of allocating a fixed length buffer, the tokenizer
2N/A * first scans the input a single character at a time looking for the
2N/A * begining and end of the token. Once the these positions are found,
2N/A * the entire token is read into memory. By using this algorithm, the
2N/A * implementation does not place an arbitrary maximum on the token size.
2N/A */
2N/A
2N/A token_len = 0;
2N/A num_escape_seq = 0;
2N/A is_quoted_str = DAT_FALSE;
2N/A is_prev_char_backslash = DAT_FALSE;
2N/A
2N/A for (;;) {
2N/A DAT_OS_FILE_POS cur_pos;
2N/A int c;
2N/A
2N/A /* if looking for start of the token */
2N/A if (0 == token_len) {
2N/A if (DAT_SUCCESS != dat_os_fgetpos(file, &cur_pos)) {
2N/A return (DAT_INTERNAL_ERROR);
2N/A }
2N/A }
2N/A
2N/A c = dat_os_fgetc(file);
2N/A
2N/A /* if looking for start of the token */
2N/A if (0 == token_len) {
2N/A if (EOF == c) {
2N/A token->type = DAT_SR_TOKEN_EOF;
2N/A token->value = NULL;
2N/A token->value_len = 0;
2N/A goto success;
2N/A } else if (DAT_SR_CHAR_NEWLINE == c) {
2N/A token->type = DAT_SR_TOKEN_EOR;
2N/A token->value = NULL;
2N/A token->value_len = 0;
2N/A goto success;
2N/A } else if (dat_os_isblank(c)) {
2N/A continue;
2N/A } else if (DAT_SR_CHAR_COMMENT == c) {
2N/A dat_sr_read_comment(file);
2N/A continue;
2N/A } else {
2N/A if (DAT_SR_CHAR_QUOTE == c) {
2N/A is_quoted_str = DAT_TRUE;
2N/A }
2N/A
2N/A pos = cur_pos;
2N/A token_len++;
2N/A }
2N/A } else { /* looking for the end of the token */
2N/A if (EOF == c) {
2N/A break;
2N/A } else if (DAT_SR_CHAR_NEWLINE == c) {
2N/A /* put back the newline */
2N/A (void) dat_os_fungetc(file);
2N/A break;
2N/A } else if (!is_quoted_str && dat_os_isblank(c)) {
2N/A break;
2N/A } else {
2N/A token_len++;
2N/A
2N/A if ((DAT_SR_CHAR_QUOTE == c) &&
2N/A !is_prev_char_backslash) {
2N/A break;
2N/A } else if ((DAT_SR_CHAR_BACKSLASH == c) &&
2N/A !is_prev_char_backslash) {
2N/A is_prev_char_backslash = DAT_TRUE;
2N/A num_escape_seq++;
2N/A } else {
2N/A is_prev_char_backslash = DAT_FALSE;
2N/A }
2N/A }
2N/A }
2N/A }
2N/A
2N/A /* the token was a string */
2N/A if (DAT_SUCCESS != dat_os_fsetpos(file, &pos)) {
2N/A return (DAT_INTERNAL_ERROR);
2N/A }
2N/A
2N/A if (is_quoted_str) {
2N/A if (DAT_SUCCESS != dat_sr_read_quoted_str(file,
2N/A token,
2N/A token_len,
2N/A num_escape_seq)) {
2N/A return (DAT_INTERNAL_ERROR);
2N/A }
2N/A } else {
2N/A if (DAT_SUCCESS != dat_sr_read_str(file,
2N/A token,
2N/A token_len)) {
2N/A return (DAT_INTERNAL_ERROR);
2N/A }
2N/A }
2N/A
2N/Asuccess:
2N/A dat_os_dbg_print(DAT_OS_DBG_TYPE_SR,
2N/A "\n"
2N/A "DAT Registry: token\n"
2N/A " type %s\n"
2N/A " value <%s>\n"
2N/A "\n",
2N/A dat_sr_type_to_str(token->type),
2N/A ((DAT_SR_TOKEN_STRING == token->type) ? token->value : ""));
2N/A
2N/A return (DAT_SUCCESS);
2N/A}
2N/A
2N/A
2N/A/*
2N/A * Function: dat_sr_read_str
2N/A */
2N/A
2N/ADAT_RETURN
2N/Adat_sr_read_str(
2N/A DAT_OS_FILE *file,
2N/A DAT_SR_TOKEN *token,
2N/A DAT_OS_SIZE token_len)
2N/A{
2N/A token->type = DAT_SR_TOKEN_STRING;
2N/A /* +1 for null termination */
2N/A token->value_len = sizeof (char) * (token_len + 1);
2N/A if (NULL == (token->value = dat_os_alloc(token->value_len))) {
2N/A return (DAT_INSUFFICIENT_RESOURCES | DAT_RESOURCE_MEMORY);
2N/A }
2N/A
2N/A if (token_len != dat_os_fread(file, token->value, token_len)) {
2N/A dat_os_free(token->value, token->value_len);
2N/A token->value = NULL;
2N/A
2N/A return (DAT_INTERNAL_ERROR);
2N/A }
2N/A
2N/A token->value[token->value_len - 1] = '\0';
2N/A
2N/A return (DAT_SUCCESS);
2N/A}
2N/A
2N/A
2N/A/*
2N/A * Function: dat_sr_read_quoted_str
2N/A */
2N/A
2N/ADAT_RETURN
2N/Adat_sr_read_quoted_str(
2N/A DAT_OS_FILE *file,
2N/A DAT_SR_TOKEN *token,
2N/A DAT_OS_SIZE token_len,
2N/A DAT_COUNT num_escape_seq)
2N/A{
2N/A DAT_OS_SIZE str_len;
2N/A DAT_OS_SIZE i;
2N/A DAT_OS_SIZE j;
2N/A int c;
2N/A DAT_RETURN status;
2N/A DAT_BOOLEAN is_prev_char_backslash;
2N/A
2N/A str_len = token_len - 2; /* minus 2 " characters */
2N/A is_prev_char_backslash = DAT_FALSE;
2N/A status = DAT_SUCCESS;
2N/A
2N/A token->type = DAT_SR_TOKEN_STRING;
2N/A /* +1 for null termination */
2N/A token->value_len = sizeof (char) * (str_len - num_escape_seq + 1);
2N/A
2N/A if (NULL == (token->value = dat_os_alloc(token->value_len))) {
2N/A status = DAT_INSUFFICIENT_RESOURCES | DAT_RESOURCE_MEMORY;
2N/A goto exit;
2N/A }
2N/A
2N/A /* throw away " */
2N/A if (DAT_SR_CHAR_QUOTE != dat_os_fgetc(file)) {
2N/A status = DAT_INTERNAL_ERROR;
2N/A goto exit;
2N/A }
2N/A
2N/A for (i = 0, j = 0; i < str_len; i++) {
2N/A c = dat_os_fgetc(file);
2N/A
2N/A if (EOF == c) {
2N/A status = DAT_INTERNAL_ERROR;
2N/A goto exit;
2N/A } else if ((DAT_SR_CHAR_BACKSLASH == c) &&
2N/A !is_prev_char_backslash) {
2N/A is_prev_char_backslash = DAT_TRUE;
2N/A } else {
2N/A token->value[j] = c;
2N/A j++;
2N/A
2N/A is_prev_char_backslash = DAT_FALSE;
2N/A }
2N/A }
2N/A
2N/A /* throw away " */
2N/A if (DAT_SR_CHAR_QUOTE != dat_os_fgetc(file)) {
2N/A status = DAT_INTERNAL_ERROR;
2N/A goto exit;
2N/A }
2N/A
2N/A token->value[token->value_len - 1] = '\0';
2N/A
2N/Aexit:
2N/A if (DAT_SUCCESS != status) {
2N/A if (NULL != token->value) {
2N/A dat_os_free(token->value, token->value_len);
2N/A token->value = NULL;
2N/A }
2N/A }
2N/A
2N/A return (status);
2N/A}
2N/A
2N/A
2N/A/*
2N/A * Function: dat_sr_read_comment
2N/A */
2N/A
2N/Avoid
2N/Adat_sr_read_comment(
2N/A DAT_OS_FILE *file)
2N/A{
2N/A int c;
2N/A
2N/A /* read up to an EOR or EOF to move past the comment */
2N/A do {
2N/A c = dat_os_fgetc(file);
2N/A } while ((DAT_SR_CHAR_NEWLINE != c) && (EOF != c));
2N/A
2N/A /* put back the newline */
2N/A (void) dat_os_fungetc(file);
2N/A}