/*
 * tnmSyslog.c --
 *
 *	A command to access the system logging facility.
 *
 * Copyright (c) 1993-1996 Technical University of Braunschweig.
 * Copyright (c) 1996-1997 University of Twente.
 * Copyright (c) 1997-1999 Technical University of Braunschweig.
 *
 * See the file "license.terms" for information on usage and redistribution
 * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
 */

#include "tnmInt.h"
#include "tnmPort.h"

TnmTable tnmLogTable[] = {
    { TNM_LOG_EMERG,	"emergency" },
    { TNM_LOG_ALERT,	"alert" },
    { TNM_LOG_CRIT,	"critical" },
    { TNM_LOG_ERR,	"error" },
    { TNM_LOG_WARNING,	"warning" },
    { TNM_LOG_NOTICE,	"notice" },
    { TNM_LOG_INFO,	"info" },
    { TNM_LOG_DEBUG,	"debug" },
    { 0, NULL }
};

/*
 * Every Tcl interpreter has an associated DnsControl record. It
 * keeps track of the default settings for this interpreter.
 */

static char tnmSyslogControl[] = "tnmSyslogControl";

typedef struct SyslogControl {
    char *ident;		/* Identification of the event source. */
} SyslogControl;

/*
 * Forward declarations for procedures defined later in this file:
 */

static void
AssocDeleteProc	_ANSI_ARGS_((ClientData clientData, Tcl_Interp *interp));


/*
 *----------------------------------------------------------------------
 *
 * AssocDeleteProc --
 *
 *	This procedure is called when a Tcl interpreter gets destroyed
 *	so that we can clean up the data associated with this interpreter.
 *
 * Results:
 *	None.
 *
 * Side effects:
 *	None.
 *
 *----------------------------------------------------------------------
 */

static void
AssocDeleteProc(clientData, interp)
    ClientData clientData;
    Tcl_Interp *interp;
{
    SyslogControl *control = (SyslogControl *) clientData;

    if (control) {
	if (control->ident) {
	    ckfree(control->ident);
	}
	ckfree((char *) control);
    }
}

/*
 *----------------------------------------------------------------------
 *
 * Tnm_SyslogCmd --
 *
 *	This procedure is invoked to process the "syslog" command.
 *	See the user documentation for details on what it does.
 *
 * Results:
 *	A standard Tcl result.
 *
 * Side effects:
 *	See the user documentation.
 *
 *----------------------------------------------------------------------
 */

int
Tnm_SyslogCmd(clientData, interp, argc, argv)
    ClientData clientData;
    Tcl_Interp *interp;
    int argc;
    char **argv;
{
    char *argv0 = argv[0];
    int level, code;
    char *ident = NULL;

    SyslogControl *control = (SyslogControl *)
	Tcl_GetAssocData(interp, tnmSyslogControl, NULL);

    if (! control) {
	control = (SyslogControl *) ckalloc(sizeof(SyslogControl));
	control->ident = ckstrdup("scotty");
	Tcl_SetAssocData(interp, tnmSyslogControl, AssocDeleteProc, 
			 (ClientData) control);
    }

    argc--; argv++;
    
    if (argc == 0) {
    wrongArgs:
	Tcl_AppendResult(interp, "wrong # args: should be \"", argv0, 
			 " ?-ident string? level message\"", (char *) NULL);
	return TCL_ERROR;
    }

    /*
     * Parse optional parameters:
     */

    while ((argc > 0) && (*argv[0] == '-')) {
	if (strcmp(argv[0], "-ident") == 0) {
	    argc--, argv++;
	    if (argc <= 0) {
		Tcl_SetResult(interp, control->ident, TCL_STATIC);
		return TCL_OK;
	    }
	    ident = argv[0];
	    argc--, argv++;
	} else {
	    Tcl_AppendResult(interp, "unknown option \"", argv[0], "\"",
			     (char *) NULL);
	    return TCL_ERROR;
	}
    }

    if (argc == 0) {
	if (ident) {
	    if (control->ident) {
		ckfree(control->ident);
	    }
	    control->ident = ckstrdup(ident);
	}
	return TCL_OK;
    }

    if (argc != 2) {
	goto wrongArgs;
    }

    if (! ident) {
	ident = control->ident;
    }

    level = TnmGetTableKey(tnmLogTable, argv[0]);

    if (level < 0) {
	Tcl_AppendResult(interp, "bad level \"", argv[0],
			 "\": should be ", TnmGetTableValues(tnmLogTable),
			 (char *) NULL);
	return TCL_ERROR;
    }

    code = TnmWriteLogMessage(ident, level, argv[1]);
    if (code != 0) {
	Tcl_SetResult(interp, "error while accessing system logging facility",
		      TCL_STATIC);
	return TCL_ERROR;
    }

    return TCL_OK;
}
