/*++
/* NAME
/*	dict_static 3
/* SUMMARY
/*	dictionary manager interface to static variables
/* SYNOPSIS
/*	#include <dict_static.h>
/*
/*	DICT	*dict_static_open(name, name, dict_flags)
/*	const char *name;
/*	int	dummy;
/*	int	dict_flags;
/* DESCRIPTION
/*	dict_static_open() implements a dummy dictionary that returns
/*	as lookup result the dictionary name, regardless of the lookup
/*	key value.
/* SEE ALSO
/*	dict(3) generic dictionary manager
/* LICENSE
/* .ad
/* .fi
/*	The Secure Mailer license must be distributed with this software.
/* AUTHOR(S)
/*	jeffm
/*	ghostgun.com
/*
/*	Wietse Venema
/*	Google, Inc.
/*	111 8th Avenue
/*	New York, NY 10011, USA
/*--*/

/* System library. */

#include "sys_defs.h"
#include <stdio.h>			/* sprintf() prototype */
#include <stdlib.h>
#include <unistd.h>
#include <string.h>

/* Utility library. */

#include "mymalloc.h"
#include "msg.h"
#include "stringops.h"
#include "dict.h"
#include "dict_static.h"

 /*
  * Subclass of DICT.
  */
typedef struct {
    DICT    dict;			/* parent class */
    char   *value;
} DICT_STATIC;

#define STR(x)	vstring_str(x)

/* dict_static_lookup - access static value*/

static const char *dict_static_lookup(DICT *dict, const char *unused_name)
{
    DICT_STATIC *dict_static = (DICT_STATIC *) dict;

    DICT_ERR_VAL_RETURN(dict, DICT_ERR_NONE, dict_static->value);
}

/* dict_static_close - close static dictionary */

static void dict_static_close(DICT *dict)
{
    DICT_STATIC *dict_static = (DICT_STATIC *) dict;

    if (dict_static->value)
	myfree(dict_static->value);
    if (dict->fold_buf)
	vstring_free(dict->fold_buf);
    dict_free(dict);
}

/* dict_static_open - make association with static variable */

DICT   *dict_static_open(const char *name, int open_flags, int dict_flags)
{
    DICT_STATIC *dict_static;
    char   *err = 0;
    char   *cp, *saved_name = 0;
    const char *value;
    VSTRING *base64_buf;

    /*
     * Let the optimizer worry about eliminating redundant code.
     */
#define DICT_STATIC_OPEN_RETURN(d) do { \
        DICT *__d = (d); \
        if (saved_name != 0) \
            myfree(saved_name); \
	if (err != 0) \
	    myfree(err); \
        return (__d); \
    } while (0)

    /*
     * Optionally strip surrounding braces and whitespace.
     */
    if (name[0] == CHARS_BRACE[0]) {
	saved_name = cp = mystrdup(name);
	if ((err = extpar(&cp, CHARS_BRACE, EXTPAR_FLAG_STRIP)) != 0)
	    DICT_STATIC_OPEN_RETURN(dict_surrogate(DICT_TYPE_STATIC, name,
						   open_flags, dict_flags,
						   "bad %s:name syntax: %s",
						   DICT_TYPE_STATIC,
						   err));
	value = cp;
    } else {
	value = name;
    }

    /*
     * Bundle up the preliminary result.
     */
    dict_static = (DICT_STATIC *) dict_alloc(DICT_TYPE_STATIC, name,
					     sizeof(*dict_static));
    dict_static->dict.lookup = dict_static_lookup;
    dict_static->dict.close = dict_static_close;
    dict_static->dict.flags = dict_flags | DICT_FLAG_FIXED;
    dict_static->dict.owner.status = DICT_OWNER_TRUSTED;
    dict_static->value = 0;

    /*
     * Optionally replace the value with file contents.
     */
    if (dict_flags & DICT_FLAG_SRC_RHS_IS_FILE) {
	if ((base64_buf = dict_file_to_b64(&dict_static->dict, value)) == 0) {
	    err = dict_file_get_error(&dict_static->dict);
	    dict_close(&dict_static->dict);
	    DICT_STATIC_OPEN_RETURN(dict_surrogate(DICT_TYPE_STATIC, name,
						   open_flags, dict_flags,
						   "%s", err));
	}
	value = vstring_str(base64_buf);
    }

    /*
     * Finalize the result.
     */
    dict_static->value = mystrdup(value);
    dict_file_purge_buffers(&dict_static->dict);

    DICT_STATIC_OPEN_RETURN(&(dict_static->dict));
}
