/*	$CoreSDI: attr_regex.c,v 1.8 2001/10/05 19:38:31 claudio Exp $	*/

/*
 *   Copyright (c) 2000, 2001, Core SDI S.A., Argentina
 *   All rights reserved
 *  
 *   Redistribution and use in source and binary forms, with or without
 *   modification, are permitted provided that the following conditions
 *   are met:
 *  
 *   1. Redistributions of source code must retain the above copyright
 *      notice, this list of conditions and the following disclaimer.
 *   2. 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.
 *   3. Neither name of the Core SDI S.A. 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 AUTHOR ``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 THE AUTHOR 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.
 */

/*
 * Regex attribute module - Compatibility with msyslog-1.xx
 * Author: Claudio Castiglia
 */

#include <sys/param.h>

#ifdef __linux__
#include <netinet/in.h>		/* in_addr_t */
#endif

#include <errno.h>
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include "sysdep.h"
#include "resource.h"
#include "packet.h"
#include "modtypes.h"
#include "iaargs.h"
#include "log.h"

#define ATTR_REGEX	"attr regex: "

typedef enum {
	REGEX_MESSAGE,
	REGEX_HOST,
	REGEX_DATE,
	REGEX_TIME,
	REGEX_INVALID
} regex_type;

static char *_type_strings[] = {
	"message",
	"host",
	"date",
	"time"
};

typedef struct _regex_ctx {
	int		 invert;		/* Inverted match	*/
	regex_type	 type;			/* Type of filter	*/
	char		 expr[BUFSIZ];		/* Regular expression	*/
} REGEX_CTX;


/*
 * _get_logset_name():
 *	Return logset name (regex attribute knows nothing about logset name).
 */
static void
_get_logset_name(ATTRCON *context, struct attrargs_ret *args)
{
	args->size = 0;
}


/*
 * _info():
 *	Return regex information coded as a string:
 *	"regex
 *	     [[ message <regular expression> ] |
 *	      [	host <regular expression>    ] |
 *	      [ date <regular expression>    ] |
 *	      [ time <regular expression>    ]]
 *	      [	invert match ]"
 *	If the regex specification is invalid the following message is coded:
 *	"regex		invalid specification"
 */
static void
_info(ATTRCON *context, struct attrargs_ret *args)
{
	REGEX_CTX	*rc;

	rc = (REGEX_CTX *) (context + 1);
	if (rc->type == REGEX_INVALID)
		snprintf(args->data, args->size,
		    "regex\n\tinvalid specification\n");
	else
		snprintf(args->data, args->size, "regex\n\t%s\t%s\n%s",
		    _type_strings[rc->type], rc->expr,
		    rc->invert ? "\tinverted match\n" : "");
}


/*
 * init():
 *	Initialize regex module.
 */
ATTRCON *
init(struct attrargs_init *args)
{
	ATTRCON			*context;
	REGEX_CTX		*rc;
	int			 i;

	log_debug(ATTR_REGEX "Initializing.");

	if (args->argc < 1) {
		errno = EINVAL;
		log_err(ATTR_REGEX "Can't initialize: %s.", strerror(errno));
		return (NULL);
	}

	context = (ATTRCON *) calloc(1, sizeof(ATTRCON) + sizeof(REGEX_CTX));
	if (context == NULL) {
		log_err(ATTR_REGEX "Can't create context: %s.",
		    strerror(errno));
		return (NULL);
	}

	rc = (REGEX_CTX *) (context + 1);

	/* Incorrect regex command line */
	if (args->argc > 4 || args->argc < 3)
		rc->type = REGEX_INVALID;
	else {
		/* Correct regex command line */
		for (i = 1; i < args->argc; i++) {
			if (!strcmp(args->argv[i], "-v")) {
				rc->invert = 1;
				continue;
			}
			if (!strcmp(args->argv[i], "-m"))
				rc->type = REGEX_MESSAGE;
			else if (!strcmp(args->argv[i], "-h"))
				rc->type = REGEX_HOST;
			else if (!strcmp(args->argv[i], "-d"))
				rc->type = REGEX_DATE;
			else if (!strcmp(args->argv[i], "-t"))
				rc->type = REGEX_TIME;
			if (i + 1 == args->argc) {
				rc->type = REGEX_INVALID;
				break;
			}
			snprintf(rc->expr, sizeof(rc->expr), "%s",
			    args->argv[++i]);
		}

	}

	return (context);
}


/*
 * proc_entry()
 */
int
proc_entry(int opcode, ATTRCON *context, void *args)
{
	switch(opcode) {
	case ATTR_GET_LOGSET_NAME:
		_get_logset_name(context, args);
		return (0);
	case ATTR_INFO:
		_info(context, args);
	case ATTR_FREEZE:
	case ATTR_GET:
	case ATTR_ZAP:
	case ATTR_ROTATE:
	case ATTR_SIGN:
		return (0);
	default:
		errno = EINVAL;
	}

	log_err(ATTR_REGEX "Invalid '%d' command.", opcode);
	return (-1);
}

