/*
** SellaNMS
** $Id: script.cxx,v 1.11 2005/03/31 18:57:12 sella Exp $
** Copyright (c) 2001-2005 Digital Genesis Software, LLC. All Rights Reserved.
** Released under the GPL Version 2 License.
** http://www.digitalgenesis.com
*/

#ifdef HAVE_CONFIG_H
	#include "config.h"
#endif

#include "script.h"
#include "debug.h"
#include <stdio.h>
#include <pthread.h>

#define BUF_SIZE 1024

Script::Script() {
	this->name.append(" script");
	
	has_scheduler = false;
	has_execute = true;
}

RESULT Script::execute() {
	RESULT result = SUCCESS;
	pthread_t thread_id = pthread_self();

	if ((result = readOutput("script")) != SUCCESS) {
		LMSG("NOTICE: Script failed to read output from storage.");
		result = FAILURE;
	} else {
		while (!outputEmpty()) {
			/* Default policy_input. */
			polInput.clear();
			polOutput.clear();

			/* Get next policy_input */
			if (result = policyInputNext(polInput) != SUCCESS) {
				LMSG("NOTICE: Failed to obtain next policy input.");
				break;
			}

			/* Insert default values. */
			polInput["command"] = this->command.c_str();

			/* Run policy on input data. */
			if (outputPolicy.evaluate(polOutput, polInput) == ACTION_REJECT) {
				LMSG("NOTICE: Failed to evaluate policy.");
				result = FAILURE;
				break;
			}

			processPolicyOutput(polOutput);
		}
	}

	return result;
}

RESULT Script::readConfig() {
	RESULT result = SUCCESS;

  vector<string> v;

	/* Add and compile input policy. */
	if (config->assignValues("policy input", v)) {
		LMSG("NOTICE: Input policies are not implemented yet.");
		if (inputPolicy.addPolicies(config, v) == FAILURE) {
			LMSG("NOTICE: Failed to add/compile input policies.");
			result = FAILURE;
		}
	}

	/* Add and compile output policy. */
	if (config->assignValues("policy output", v)) {
		if (outputPolicy.addPolicies(config, v) == FAILURE) {
			LMSG("NOTICE: Failed to add/compile output policies.");
			result = FAILURE;
		}
	}

	/* Large queue-depth results in increased RAM usage, during high event periods. An overwhelmed system could grow out of control. */
	if (config->assignValue("queue-depth", queueDepth, MODULE_OUTPUT_SCRIPT_QUEUEDEPTH_DEFAULT)) {
		if (queueDepth < 1) {
			queueDepth = MODULE_OUTPUT_SCRIPT_QUEUEDEPTH_DEFAULT;
		}
	}

	config->assignValue("command", command);

	/* Configure Storage */
	storage.setConfig(*config);

	return result;
}

RESULT Script::printConfig() {
	LMSG("queue-depth: %lu", this->queueDepth);
	LMSG("command: %s", this->command.c_str());

	return Output::printConfig();
}

RESULT Script::processPolicyOutput(variable_binding_t &policy_output) {
	RESULT result = SUCCESS;

	int ret_val;
	FILE *fp;
	string command, arguments;
	char buf[BUF_SIZE];

	if (policy_output.find("command") != policy_output.end()) {
		command = policy_output["command"];
	}

	LMSG("command: %s, arguments: %s", command.c_str(), arguments.c_str());

	if ((fp = popen(command.c_str(), "r")) == NULL) {
		LMSG("WARNING: Call to popen failed.");

		result = FAILURE;
	} else {
		while (!feof(fp)) {
			fread(buf, BUF_SIZE, 1, fp);
			if (trace.debug) {
				LMSG("Script output: %s", buf);
			}
		}
		pclose(fp);
	}
	
	return result;
}

/*
** Local Variables:
** c-basic-offset: 3
** tab-width: 3
** End:
** vim600: 
** vim: noet ts=3 sw=3
*/
