int Web_LogDest()

in src/generic/log.c [467:763]


int Web_LogDest(ClientData clientData,
		Tcl_Interp * interp, int objc, Tcl_Obj * CONST objv[])
{

    LogData *logData = NULL;
    int idx;
    int iCurArg;

    static TCLCONST char *params[] = { "-maxchar",
	"-format",
	NULL
    };
    enum params
    { MAXCHAR, FORMAT };
    static TCLCONST char *subCommands[] = {
      WEB_LOG_SUBCMD_ADD,
      WEB_LOG_SUBCMD_DELETE,
      WEB_LOG_SUBCMD_NAMES,
      WEB_LOG_SUBCMD_LEVELS,
      NULL
    };
    enum subCommands
    { ADD, DELETE, NAMES, LEVELS };

    /* --------------------------------------------------------------------------
     * check for internal data
     * ----------------------------------------------------------------------- */
    WebAssertData(interp, clientData, "Web_LogDest", TCL_ERROR)
	logData = (LogData *) clientData;

    /* --------------------------------------------------------------------------
     * check arguments
     * ----------------------------------------------------------------------- */
    if (objc < 2) {
	Tcl_WrongNumArgs(interp, 1, objv, "option arg ?arg ...?");
	return TCL_ERROR;
    }

    /* --------------------------------------------------------------------------
     * scan for options
     * ----------------------------------------------------------------------- */
    if (Tcl_GetIndexFromObj(interp, objv[1], subCommands, "option", 0, &idx)
	!= TCL_OK)
	return TCL_ERROR;

    /* --------------------------------------------------------------------------
     * switch on subcommand
     * ----------------------------------------------------------------------- */

    switch ((enum subCommands) idx) {

    case ADD:{

	    /* ------------------------------------------------------------------------
	     * ok, add sytnax is as follows:
	     * web::logdest add [-format bla -maxchar 100] level {type specific stuff}
	     * 0            1   2                          j     j+1
	     * --------------------------------------------------------------------- */

	    char *name = NULL;
	    char *format = NULL;
	    LogLevel *logLevel = NULL;
	    LogPlugIn *logPlugIn = NULL;
	    ClientData logPlugInData = NULL;
	    LogDest *logDest = NULL;
	    Tcl_Obj *tcloTmp;
	    long maxCharInMsg = -1;
	    int iUnknown = 0;

	    /* argdbg(objc,objv,stdout); */

	    iCurArg =
		argIndexOfFirstArg(objc - 1, &(objv[1]), params, NULL) + 1;

	    /* check for known options */
	    iUnknown =
		argHasOnlyAccepted(objc - 1, &(objv[1]), params, iCurArg - 1);
	    if (iUnknown > 0) {
		/* let Tcl format the error message */
		Tcl_GetIndexFromObj(interp, objv[iUnknown + 1], params,
				    "option", 0, &idx);
		return TCL_ERROR;
	    }

	    /* check for -format */
	    if ((tcloTmp = argValueOfKey(objc, objv, (char *)params[FORMAT])) != NULL) {
		format = allocAndSet(Tcl_GetString(tcloTmp));
	    }
	    else {
		format = allocAndSet(WEB_LOG_DEFAULTFORMAT);
	    }

	    /* check for -maxchar */
	    if ((tcloTmp =
		 argValueOfKey(objc, objv, (char *)params[MAXCHAR])) != NULL) {
		if (Tcl_GetLongFromObj(interp, tcloTmp, &maxCharInMsg) ==
		    TCL_ERROR) {
		    LOG_MSG(interp, WRITE_LOG | SET_RESULT, __FILE__,
			    __LINE__, "web::logdest", WEBLOG_INFO,
			    "cannot read long from -maxchar \"",
			    Tcl_GetString(tcloTmp), "\"", NULL);
		    return TCL_ERROR;
		}
	    }

	    /* ------------------------------------------------------------------------
	     * now iCurArg is level, iCurArg+1 is type, (+2 is type specific)
	     * --------------------------------------------------------------------- */
	    if ((iCurArg + 1) >= objc) {
		Tcl_WrongNumArgs(interp, 1, objv, WEB_LOG_USAGE_LOGDEST_ADD);
		WebFreeIfNotNull(format);
		return TCL_ERROR;
	    }

	    /* ------------------------------------------------------------------------
	     * get handler for type
	     * --------------------------------------------------------------------- */
	    logPlugIn = (LogPlugIn *) getFromHashTable(logData->listOfPlugIns,
						       Tcl_GetString(objv
								     [iCurArg
								      + 1]));
	    if (logPlugIn == NULL) {
		Tcl_SetResult(interp, "no log handler of type \"", NULL);
		Tcl_AppendResult(interp, Tcl_GetString(objv[iCurArg + 1]),
				 "\" registered", NULL);
		WebFreeIfNotNull(format);
		return TCL_ERROR;
	    }

	    /* ------------------------------------------------------------------------
	     * parse level
	     * --------------------------------------------------------------------- */
	    logLevel =
		parseLogLevel(interp, Tcl_GetString(objv[iCurArg]), "user",
			      -1);
	    if (logLevel == NULL) {
		WebFreeIfNotNull(format);
		return TCL_ERROR;
	    }

	    /* ------------------------------------------------------------------------
	     * call constructor
	     * --------------------------------------------------------------------- */
	    if ((logPlugInData =
		 logPlugIn->constructor(interp,
					clientData, objc - (iCurArg + 1),
					&(objv[iCurArg + 1]))) == NULL) {
		destroyLogLevel(logLevel, NULL);
		WebFreeIfNotNull(name);
		WebFreeIfNotNull(format);
		return TCL_ERROR;
	    }

	    /* ------------------------------------------------------------------------
	     * ok, make the logDest
	     * --------------------------------------------------------------------- */
	    logDest = createLogDest();
	    if (logDest == NULL) {
		Tcl_SetResult(interp, "cannot create log destination", NULL);
		destroyLogLevel(logLevel, NULL);
		WebFreeIfNotNull(name);
		WebFreeIfNotNull(format);
		return TCL_ERROR;
	    }
	    logDest->filter = logLevel;
	    logDest->format = format;
	    logDest->plugIn = logPlugIn;
	    logDest->plugInData = logPlugInData;
	    logDest->maxCharInMsg = maxCharInMsg;
	    logDest->keep = logData->keep;

	    /* ----------------------------------------------------------
	     * and add to list
	     * ---------------------------------------------------------- */
	    
	    name = insertIntoDestList(logData, logDest);
	    if (name == NULL) {
		Tcl_SetResult(interp, "cannot append new log destination to list", NULL);
		destroyLogDest(logDest, interp);
		destroyLogLevel(logLevel, NULL);
		WebFreeIfNotNull(format);
		return TCL_ERROR;
	    }
	    Tcl_SetResult(interp, name, Tcl_Free);
	    return TCL_OK;
	}
    case NAMES:{

	    Tcl_ResetResult(interp);

	    if (logData->listOfDests != NULL) {
	      int i;
	      LogDest ** logDests = logData->listOfDests;
	      for (i = 0; i < logData->destSize; i++) {
		if (logDests[i] != NULL) {
		  char *name = createLogName(LOG_DEST_PREFIX, i);
		  if  (name != NULL) {
		    Tcl_AppendElement(interp, name);
		    Tcl_Free(name);
		  }
		}
	      }
	    }
	    return TCL_OK;
	}
    case LEVELS:{

	    int namesIsFirst = TCL_OK;
	    LogDest *logDest = NULL;

	    Tcl_SetResult(interp, "", NULL);

	    if (logData->listOfDests != NULL) {

	      int i;
	      LogDest ** logDests = logData->listOfDests;
	      for (i = 0; i < logData->destSize; i++) {
		if (logDests[i] != NULL) {
		  char * name = createLogName(LOG_DEST_PREFIX, i);
		    if (namesIsFirst == TCL_ERROR)
			Tcl_AppendResult(interp, "\n", NULL);
		    else
			namesIsFirst = TCL_ERROR;
		    logDest = logDests[i];
		    Tcl_AppendResult(interp,
				     name, " ",
				     logDest->filter->facility, ".",
				     getSeverityName(logDest->filter->
						     minSeverity), "-",
				     getSeverityName(logDest->filter->
						     maxSeverity), NULL);
		    Tcl_Free(name);
		}
	      }
	    }
	    return TCL_OK;
	}
    case DELETE:{

	    /*      0               1      2 */
	    /*      web::loglogDest delete logDest1 */

	    switch (objc) {
	    case 3: {
	      LogDest ** logDests = logData->listOfDests;
	      if (!strcmp("-requests", Tcl_GetString(objv[2]))) {
		/* special case: delete all destinations NOT created during web::initializer */
		int i;
		for (i = 0; i < logData->destSize; i++) {
		  if (logDests[i] != NULL && !logDests[i]->keep) {
		    destroyLogDest(logDests[i], interp);
		    logDests[i] = NULL;
		  }
		}
		return TCL_OK;
	      } else {
		int inx = getIndexFromLogName(LOG_DEST_PREFIX"%d", Tcl_GetString(objv[2]));
		if (inx < 0 
		    || inx >= logData->destSize
		    || logDests[inx] == NULL) {
		  Tcl_SetResult(interp, "no such log destination \"", NULL);
		  Tcl_AppendResult(interp, Tcl_GetString(objv[2]), "\"",
				   NULL);
		  return TCL_ERROR;
		}
		destroyLogDest(logDests[inx], interp);
		logDests[inx] = NULL;
		return TCL_OK;
		break;
	      }
	    }
	    case 2:
		/* --------------------------------------------------------
		 * no argument --> resets the list
		 * -------------------------------------------------------- */
		if (logData->listOfDests != NULL) {
		  int i;
		  LogDest ** logDests = logData->listOfDests;
		  for (i = 0; i < logData->destSize; i++) {
		    if (logDests[i] != NULL) {
		      destroyLogDest(logDests[i], interp);
		      logDests[i] = NULL;
		    }
		  }
		}
		return TCL_OK;
		break;
	    default:
		Tcl_WrongNumArgs(interp, 1, objv, "delete ?destname?");
		return TCL_ERROR;
	    }
	    break;
	}
    default:
	return TCL_OK;
    }
}