/* * The contents of this file are subject to the AOLserver Public License * Version 1.1 (the "License"); you may not use this file except in * compliance with the License. You may obtain a copy of the License at * http://aolserver.com/. * * Software distributed under the License is distributed on an "AS IS" * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See * the License for the specific language governing rights and limitations * under the License. * * The Original Code is AOLserver Code and related documentation * distributed by AOL. * * The Initial Developer of the Original Code is America Online, * Inc. Portions created by AOL are Copyright (C) 1999 America Online, * Inc. All Rights Reserved. * * Alternatively, the contents of this file may be used under the terms * of the GNU General Public License (the "GPL"), in which case the * provisions of GPL are applicable instead of those above. If you wish * to allow use of your version of this file only under the terms of the * GPL and not to allow others to use your version of this file under the * License, indicate your decision by deleting the provisions above and * replace them with the notice and other provisions required by the GPL. * If you do not delete the provisions above, a recipient may use your * version of this file under either the License or the GPL. */ /* * adpcmds.c -- * * ADP commands. */ static const char *RCSID = "@(#) $Header: /cvsroot/aolserver/aolserver/nsd/adpcmds.c,v 1.28 2006/06/26 00:28:02 jgdavidson Exp $, compiled: " __DATE__ " " __TIME__; #include "nsd.h" static int ExceptionObjCmd(NsInterp *itPtr, int objc, Tcl_Obj **objv, int exception); static int EvalObjCmd(NsInterp *itPtr, int objc, Tcl_Obj **objv, int flags); static int GetFrame(ClientData arg, AdpFrame **framePtrPtr); static int GetOutput(ClientData arg, Tcl_DString **dsPtrPtr); /* *---------------------------------------------------------------------- * * NsTclAdpIdentObjCmd -- * * Set RCS/CVS ident string for current file. * * Results: * A standard Tcl result. * * Side effects: * Depends on subcommand. * *---------------------------------------------------------------------- */ int NsTclAdpIdentObjCmd(ClientData arg, Tcl_Interp *interp, int objc, Tcl_Obj **objv) { AdpFrame *framePtr; if (objc != 1 && objc != 2) { Tcl_WrongNumArgs(interp, 1, objv, "ident"); return TCL_ERROR; } if (GetFrame(arg, &framePtr) != TCL_OK) { return TCL_ERROR; } if (objc == 2) { if (framePtr->ident != NULL) { Tcl_DecrRefCount(framePtr->ident); } framePtr->ident = objv[1]; Tcl_IncrRefCount(framePtr->ident); } if (framePtr->ident != NULL) { Tcl_SetObjResult(interp, framePtr->ident); } return TCL_OK; } /* *---------------------------------------------------------------------- * * NsTclAdpCtlObjCmd -- * * ADP processing control. * * Results: * A standard Tcl result. * * Side effects: * Depends on subcommand. * *---------------------------------------------------------------------- */ int NsTclAdpCtlObjCmd(ClientData arg, Tcl_Interp *interp, int objc, Tcl_Obj **objv) { Tcl_Channel chan; NsInterp *itPtr = arg; char *id; static CONST char *opts[] = { "bufsize", "channel", "autoabort", "detailerror", "displayerror", "expire", "gzip", "nocache", "safe", "singlescript", "stricterror", "trace", "trimspace", NULL }; enum { CBufSizeIdx, CChanIdx, CAbortIdx, CDetailIdx, CDispIdx, CExpireIdx, CGzipIdx, CNoCacheIdx, CSafeIdx, CSingleIdx, CStrictIdx, CTraceIdx, CTrimIdx }; int opt, flag, old, new; if (objc < 2) { Tcl_WrongNumArgs(interp, 1, objv, "option ?arg ...?"); return TCL_ERROR; } if (Tcl_GetIndexFromObj(interp, objv[1], opts, "option", 0, &opt) != TCL_OK) { return TCL_ERROR; } switch (opt) { case CBufSizeIdx: if (objc != 2 && objc !=3 ) { Tcl_WrongNumArgs(interp, 2, objv, "?size?"); return TCL_ERROR; } old = itPtr->adp.bufsize; if (objc == 3) { if (Tcl_GetIntFromObj(interp, objv[2], &new) != TCL_OK) { return TCL_ERROR; } if (new < 0) { new = 0; } itPtr->adp.bufsize = new; } Tcl_SetIntObj(Tcl_GetObjResult(interp), old); break; case CChanIdx: if (objc != 3) { Tcl_WrongNumArgs(interp, 2, objv, "channel"); return TCL_ERROR; } id = Tcl_GetString(objv[2]); if (*id == '\0') { if (itPtr->adp.chan != NULL) { if (NsAdpFlush(itPtr, 0) != TCL_OK) { return TCL_ERROR; } itPtr->adp.chan = NULL; } } else { if (Ns_TclGetOpenChannel(interp, id, 1, 1, &chan) != TCL_OK) { return TCL_ERROR; } itPtr->adp.chan = chan; } break; default: /* * Query or update an ADP option. */ if (objc != 2 && objc !=3 ) { Tcl_WrongNumArgs(interp, 2, objv, "?bool?"); return TCL_ERROR; } flag = 0; switch (opt) { case CAbortIdx: flag = ADP_AUTOABORT; break; case CDetailIdx: flag = ADP_DETAIL; break; case CDispIdx: flag = ADP_DISPLAY; break; case CExpireIdx: flag = ADP_EXPIRE; break; case CGzipIdx: flag = ADP_GZIP; break; case CNoCacheIdx: flag = ADP_NOCACHE; break; case CSafeIdx: flag = ADP_SAFE; break; case CSingleIdx: flag = ADP_SINGLE; break; case CStrictIdx: flag = ADP_STRICT; break; case CTraceIdx: flag = ADP_TRACE; break; case CTrimIdx: flag = ADP_TRIM; break; } old = (itPtr->adp.flags & flag); if (objc == 3) { if (Tcl_GetBooleanFromObj(interp, objv[2], &new) != TCL_OK) { return TCL_ERROR; } if (new) { itPtr->adp.flags |= flag; } else { itPtr->adp.flags &= ~flag; } } Tcl_SetBooleanObj(Tcl_GetObjResult(interp), old); break; } return TCL_OK; } /* *---------------------------------------------------------------------- * * NsTclAdpCompressObjCmd -- * * Process the Tcl ns_adp_compress command to enable on-the-fly * gzip compression of ADP response. * * Results: * A standard Tcl result. * * Side effects: * None. * *---------------------------------------------------------------------- */ int NsTclAdpCompressObjCmd(ClientData arg, Tcl_Interp *interp, int objc, Tcl_Obj **objv) { NsInterp *itPtr = arg; int compress = 1; if (objc != 1 && objc != 2) { Tcl_WrongNumArgs(interp, 1, objv, "?boolean?"); return TCL_ERROR; } if (objc >= 2 && Tcl_GetBooleanFromObj(interp, objv[1], &compress) != TCL_OK) { return TCL_ERROR; } if (compress) { itPtr->adp.flags |= ADP_GZIP; } else { itPtr->adp.flags &= ~ADP_GZIP; } return TCL_OK; } /* *---------------------------------------------------------------------- * * NsTclAdpEvalObjCmd, NsTclAdpSafeEvalObjCmd -- * * (Safe) Evaluate an ADP string. * * Results: * A standard Tcl result. * * Side effects: * Page string is parsed and evaluated at current Tcl level in a * new ADP call frame. * *---------------------------------------------------------------------- */ int NsTclAdpEvalObjCmd(ClientData arg, Tcl_Interp *interp, int objc, Tcl_Obj **objv) { return EvalObjCmd(arg, objc, objv, 0); } int NsTclAdpSafeEvalObjCmd(ClientData arg, Tcl_Interp *interp, int objc, Tcl_Obj **objv) { return EvalObjCmd(arg, objc, objv, ADP_SAFE); } static int EvalObjCmd(NsInterp *itPtr, int objc, Tcl_Obj **objv, int flags) { if (objc < 2) { Tcl_WrongNumArgs(itPtr->interp, 1, objv, "page ?args ...?"); return TCL_ERROR; } return NsAdpEval(itPtr, objc-1, objv+1, flags, NULL); } /* *---------------------------------------------------------------------- * * NsTclAdpIncludeObjCmd -- * * Process the Tcl _ns_adp_include commands to evaluate an * ADP. * * Results: * A standard Tcl result. * * Side effects: * File evaluated with output going to ADP buffer. * *---------------------------------------------------------------------- */ int NsTclAdpIncludeObjCmd(ClientData arg, Tcl_Interp *interp, int objc, Tcl_Obj **objv) { NsInterp *itPtr = arg; Tcl_DString *dsPtr; int i, skip, cache; Ns_Time *ttlPtr, ttl; char *file; if (objc < 2) { badargs: Tcl_WrongNumArgs(interp, 1, objv, "?-cache ttl | -nocache? " "file ?args ...?"); return TCL_ERROR; } ttlPtr = NULL; skip = cache = 1; file = Tcl_GetString(objv[1]); if (STREQ(file, "-nocache")) { if (objc < 3) { goto badargs; } cache = 0; skip = 2; } else if (STREQ(file, "-cache")) { if (objc < 4) { goto badargs; } if (Ns_TclGetTimeFromObj(interp, objv[2], &ttl) != TCL_OK) { return TCL_ERROR; } Ns_AdjTime(&ttl); if (ttl.sec < 0) { Tcl_AppendResult(interp, "invalid ttl: ", Tcl_GetString(objv[2]), NULL); return TCL_ERROR; } ttlPtr = &ttl; skip = 3; } file = Tcl_GetString(objv[skip]); objc -= skip; objv += skip; /* * In cache refresh mode, append include command to the output * buffer. It will be compiled into the cached result. */ if (!cache && itPtr->adp.refresh > 0) { if (GetOutput(arg, &dsPtr) != TCL_OK) { return TCL_ERROR; } Tcl_DStringAppend(dsPtr, "<% ns_adp_include", -1); for (i = 0; i < objc; ++i) { Tcl_DStringAppendElement(dsPtr, Tcl_GetString(objv[i])); } Tcl_DStringAppend(dsPtr, "%>", 2); return TCL_OK; } return NsAdpInclude(arg, objc, objv, file, ttlPtr); } /* *---------------------------------------------------------------------- * * NsTclAdpParseObjCmd -- * * Process the ns_adp_parse command to evaluate strings or * ADP files at the current call frame level. * * Results: * A standard Tcl result. * * Side effects: * ADP string or file output is return as Tcl result. * *---------------------------------------------------------------------- */ int NsTclAdpParseObjCmd(ClientData arg, Tcl_Interp *interp, int objc, Tcl_Obj **objv) { NsInterp *itPtr = arg; int isfile, i, flags, result; char *opt; char *resvar = NULL; char *cwd = NULL, *savecwd = NULL; if (objc < 2) { badargs: Tcl_WrongNumArgs(interp, 1, objv, "?-file|-string? ?-savedresult varname? ?-cwd path? " "arg ?arg ...?"); return TCL_ERROR; } isfile = flags = 0; for (i = 1; i < objc; ++i) { opt = Tcl_GetString(objv[i]); if (STREQ(opt, "-global")) { Tcl_SetResult(interp, "option -global unsupported", TCL_STATIC); return TCL_ERROR; } else if (STREQ(opt, "-file")) { isfile = 1; } else if (STREQ(opt, "-savedresult")) { if (++i < objc) { resvar = Tcl_GetString(objv[i]); } else { goto badargs; } } else if (STREQ(opt, "-cwd")) { if (++i < objc) { cwd = Tcl_GetString(objv[i]); } else { goto badargs; } } else if (STREQ(opt, "-safe")) { flags |= ADP_SAFE; } else if (!STREQ(opt, "-string") && !STREQ(opt, "-local")) { break; } } if (objc == i) { goto badargs; } objc -= i; objv += i; /* * Check the adp field in the nsInterp, and construct any support * Also, set the cwd. */ if (cwd != NULL) { savecwd = itPtr->adp.cwd; itPtr->adp.cwd = cwd; } if (isfile) { result = NsAdpSource(arg, objc, objv, flags, resvar); } else { result = NsAdpEval(arg, objc, objv, flags, resvar); } if (cwd != NULL) { itPtr->adp.cwd = savecwd; } return result; } /* *---------------------------------------------------------------------- * * NsTclAdpAppendObjCmd, NsTclAdpPutsObjCmd -- * * Process the ns_adp_append and ns_adp_puts commands to append * output. * * Results: * A standard Tcl result. * * Side effects: * Output buffer is extended with given text, including a newline * with ns_adp_puts. * *---------------------------------------------------------------------- */ int NsTclAdpAppendObjCmd(ClientData arg, Tcl_Interp *interp, int objc, Tcl_Obj **objv) { NsInterp *itPtr = arg; int i, len; char *s; if (objc < 2) { Tcl_WrongNumArgs(interp, 1, objv, "string ?string ...?"); return TCL_ERROR; } for (i = 1; i < objc; ++i) { s = Tcl_GetStringFromObj(objv[i], &len); if (NsAdpAppend(itPtr, s, len) != TCL_OK) { return TCL_ERROR; } } return TCL_OK; } int NsTclAdpPutsObjCmd(ClientData arg, Tcl_Interp *interp, int objc, Tcl_Obj **objv) { NsInterp *itPtr = arg; char *s; int len; if (objc != 2 && objc != 3) { Tcl_WrongNumArgs(interp, 1, objv, "?-nonewline? string"); return TCL_ERROR; } if (objc == 3) { s = Tcl_GetString(objv[1]); if (!STREQ(s, "-nonewline")) { Tcl_AppendResult(interp, "invalid flag \"", s, "\": expected -nonewline", NULL); return TCL_ERROR; } } s = Tcl_GetStringFromObj(objv[objc-1], &len); if (NsAdpAppend(itPtr, s, len) != TCL_OK) { return TCL_ERROR; } if (objc == 2 && NsAdpAppend(itPtr, "\n", 1) != TCL_OK) { return TCL_ERROR; } return TCL_OK; } /* *---------------------------------------------------------------------- * * NsTclAdpDirObjCmd -- * * Process the Tcl ns_adp_dir command to return the current ADP * directory. * * Results: * A standard Tcl result. * * Side effects: * None. * *---------------------------------------------------------------------- */ int NsTclAdpDirObjCmd(ClientData arg, Tcl_Interp *interp, int objc, Tcl_Obj **objv) { NsInterp *itPtr = arg; if (objc != 1) { Tcl_WrongNumArgs(interp, 1, objv, NULL); return TCL_ERROR; } Tcl_SetResult(interp, itPtr->adp.cwd, TCL_VOLATILE); return TCL_OK; } /* *---------------------------------------------------------------------- * * NsTclAdpReturnObjCmd, NsTclAdpBreakObjCmd, NsTclAdpAbortObjCmd -- * * Process the Tcl ns_adp_return, ns_adp_break and ns_adp_abort * commands to halt page generation. * * Results: * A standard Tcl result. * * Side effects: * Break or abort exception is noted and will be handled in * AdpProc. * *---------------------------------------------------------------------- */ int NsTclAdpReturnObjCmd(ClientData arg, Tcl_Interp *interp, int objc, Tcl_Obj **objv) { return ExceptionObjCmd(arg, objc, objv, ADP_RETURN); } int NsTclAdpBreakObjCmd(ClientData arg, Tcl_Interp *interp, int objc, Tcl_Obj **objv) { return ExceptionObjCmd(arg, objc, objv, ADP_BREAK); } int NsTclAdpAbortObjCmd(ClientData arg, Tcl_Interp *interp, int objc, Tcl_Obj **objv) { return ExceptionObjCmd(arg, objc, objv, ADP_ABORT); } static int ExceptionObjCmd(NsInterp *itPtr, int objc, Tcl_Obj **objv, int exception) { if (objc != 1 && objc != 2) { Tcl_WrongNumArgs(itPtr->interp, 1, objv, "?retval?"); return TCL_ERROR; } itPtr->adp.exception = exception; if (objc == 2) { Tcl_SetObjResult(itPtr->interp, objv[1]); } return TCL_ERROR; } /* *---------------------------------------------------------------------- * * NsTclAdpTellObjCmd -- * * Process the Tcl ns_adp_tell commands to return the current * offset within the output buffer. * * Results: * A standard Tcl result. * * Side effects: * None. * *---------------------------------------------------------------------- */ int NsTclAdpTellObjCmd(ClientData arg, Tcl_Interp *interp, int objc, Tcl_Obj **objv) { Tcl_DString *dsPtr; if (objc != 1) { Tcl_WrongNumArgs(interp, 1, objv, NULL); return TCL_ERROR; } if (GetOutput(arg, &dsPtr) != TCL_OK) { return TCL_ERROR; } Tcl_SetObjResult(interp, Tcl_NewIntObj(dsPtr->length)); return TCL_OK; } /* *---------------------------------------------------------------------- * * NsTclAdpTruncObjCmd -- * * Process the Tcl ns_adp_trunc commands to truncate the output * buffer to the given length. * * Results: * A standard Tcl result. * * Side effects: * Output buffer is truncated. * *---------------------------------------------------------------------- */ int NsTclAdpTruncObjCmd(ClientData arg, Tcl_Interp *interp, int objc, Tcl_Obj **objv) { Tcl_DString *dsPtr; int length; if (objc != 1 && objc != 2) { Tcl_WrongNumArgs(interp, 1, objv, "?length?"); return TCL_ERROR; } if (objc == 1) { length = 0; } else { if (Tcl_GetIntFromObj(interp, objv[1], &length) != TCL_OK) { return TCL_ERROR; } if (length < 0) { Tcl_AppendResult(interp, "invalid length: ", Tcl_GetString(objv[1]), NULL); return TCL_ERROR; } } if (GetOutput(arg, &dsPtr) != TCL_OK) { return TCL_ERROR; } Ns_DStringTrunc(dsPtr, length); return TCL_OK; } /* *---------------------------------------------------------------------- * * NsTclAdpDumpObjCmd -- * * Process the Tcl ns_adp_dump commands to return the entire text * of the output buffer. * * Results: * A standard Tcl result. * * Side effects: * None. * *---------------------------------------------------------------------- */ int NsTclAdpDumpObjCmd(ClientData arg, Tcl_Interp *interp, int objc, Tcl_Obj **objv) { Tcl_DString *dsPtr; if (objc != 1) { Tcl_WrongNumArgs(interp, 1, objv, NULL); return TCL_ERROR; } if (GetOutput(arg, &dsPtr) != TCL_OK) { return TCL_ERROR; } Tcl_SetResult(interp, dsPtr->string, TCL_VOLATILE); return TCL_OK; } /* *---------------------------------------------------------------------- * * NsTclAdpArgcObjCmd -- * * Process the Tcl ns_adp_args commands to return the number of * arguments in the current ADP frame. * * Results: * A standard Tcl result. * * Side effects: * None. * *---------------------------------------------------------------------- */ int NsTclAdpArgcObjCmd(ClientData arg, Tcl_Interp *interp, int objc, Tcl_Obj **objv) { AdpFrame *framePtr; if (objc != 1) { Tcl_WrongNumArgs(interp, 1, objv, NULL); return TCL_ERROR; } if (GetFrame(arg, &framePtr) != TCL_OK) { return TCL_ERROR; } Tcl_SetObjResult(interp, Tcl_NewIntObj(framePtr->objc)); return TCL_OK; } /* *---------------------------------------------------------------------- * * NsTclAdpArgvObjCmd -- * * Process the Tcl ns_adp_args commands to return an argument (or * the entire list of arguments) within the current ADP frame. * * Results: * A standard Tcl result. * * Side effects: * None. * *---------------------------------------------------------------------- */ int NsTclAdpArgvObjCmd(ClientData arg, Tcl_Interp *interp, int objc, Tcl_Obj **objv) { AdpFrame *framePtr; int i; if (objc > 3) { Tcl_WrongNumArgs(interp, 1, objv, "?index? ?default?"); return TCL_ERROR; } if (GetFrame(arg, &framePtr) != TCL_OK) { return TCL_ERROR; } if (objc == 1) { Tcl_SetListObj(Tcl_GetObjResult(interp), framePtr->objc, framePtr->objv); } else { if (Tcl_GetIntFromObj(interp, objv[1], &i) != TCL_OK) { return TCL_ERROR; } if ((i + 1) <= framePtr->objc) { Tcl_SetObjResult(interp, framePtr->objv[i]); } else { if (objc == 3) { Tcl_SetObjResult(interp, objv[2]); } } } return TCL_OK; } /* *---------------------------------------------------------------------- * * NsTclAdpBindArgsObjCmd -- * * Process the Tcl ns_adp_bind_args commands to copy arguements * from the current frame into local variables. * * Results: * A standard Tcl result. * * Side effects: * One or more local variables are created. * *---------------------------------------------------------------------- */ int NsTclAdpBindArgsObjCmd(ClientData arg, Tcl_Interp *interp, int objc, Tcl_Obj **objv) { AdpFrame *framePtr; int i; if (objc < 2) { Tcl_WrongNumArgs(interp, 1, objv, "varName ?varName ...?"); return TCL_ERROR; } if (GetFrame(arg, &framePtr) != TCL_OK) { return TCL_ERROR; } if (objc != framePtr->objc) { Tcl_AppendResult(interp, "invalid #variables", NULL); return TCL_ERROR; } for (i = 1; i < objc; ++i) { if (Tcl_ObjSetVar2(interp, objv[i], NULL, framePtr->objv[i], TCL_LEAVE_ERR_MSG) == NULL) { return TCL_ERROR; } } return TCL_OK; } /* *---------------------------------------------------------------------- * * NsTclAdpExcepetionObjCmd -- * * Process the Tcl ns_adp_exception commands to return the current * exception state, ok, abort, or break. * * Results: * A standard Tcl result. * * Side effects: * None. * *---------------------------------------------------------------------- */ int NsTclAdpExceptionObjCmd(ClientData arg, Tcl_Interp *interp, int objc, Tcl_Obj **objv) { NsInterp *itPtr = arg; char *exception; int bool; if (objc != 1 && objc != 2) { Tcl_WrongNumArgs(interp, 1, objv, "?varName?"); return TCL_ERROR; } if (itPtr->adp.exception == ADP_OK) { bool = 0; } else { bool = 1; } Tcl_SetBooleanObj(Tcl_GetObjResult(interp), bool); if (objc == 2) { switch (itPtr->adp.exception) { case ADP_OK: exception = "ok"; break; case ADP_BREAK: exception = "break"; break; case ADP_ABORT: exception = "abort"; break; case ADP_RETURN: exception = "return"; break; default: exception = "unknown"; break; } if (Tcl_ObjSetVar2(interp, objv[1], NULL, Tcl_NewStringObj(exception, -1), TCL_LEAVE_ERR_MSG) == NULL) { return TCL_ERROR; } } return TCL_OK; } /* *---------------------------------------------------------------------- * * NsTclAdpFlushObjCmd, NsTclAdpCloseObjCmd -- * * Flush or close the current ADP output. * * Results: * A standard Tcl result. * * Side effects: * Output will flush to client immediately. * *---------------------------------------------------------------------- */ static int AdpFlushObjCmd(ClientData arg, Tcl_Interp *interp, int objc, Tcl_Obj **objv, int stream) { NsInterp *itPtr = arg; if (objc != 1) { Tcl_WrongNumArgs(interp, 1, objv, NULL); return TCL_ERROR; } return NsAdpFlush(itPtr, stream); } int NsTclAdpFlushObjCmd(ClientData arg, Tcl_Interp *interp, int objc, Tcl_Obj **objv) { return AdpFlushObjCmd(arg, interp, objc, objv, 1); } int NsTclAdpCloseObjCmd(ClientData arg, Tcl_Interp *interp, int objc, Tcl_Obj **objv) { return AdpFlushObjCmd(arg, interp, objc, objv, 0); } /* *---------------------------------------------------------------------- * * NsTclAdpStreamObjCmd -- * * Set ADP buffer size to 0, forcing all content to be sent to the * client immediately on each append. * * Results: * A standard Tcl result. * * Side effects: * See NsTclAdpFlushObjCmd. * *---------------------------------------------------------------------- */ int NsTclAdpStreamObjCmd(ClientData arg, Tcl_Interp *interp, int objc, Tcl_Obj **objv) { NsInterp *itPtr = arg; if (objc != 1) { Tcl_WrongNumArgs(interp, 1, objv, NULL); return TCL_ERROR; } itPtr->adp.bufsize = 0; return NsTclAdpFlushObjCmd(arg, interp, objc, objv); } /* *---------------------------------------------------------------------- * * NsTclAdpDebugCmd -- * * Process the Tcl ns_adp_debug command to connect to the TclPro * debugger if not already connected. * * Results: * A standard Tcl result. * * Side effects: * See comments for DebugInit(). * *---------------------------------------------------------------------- */ int NsTclAdpDebugCmd(ClientData arg, Tcl_Interp *interp, int argc, char **argv) { NsInterp *itPtr = arg; char *host, *port, *procs, buf[20]; if (argc > 4) { Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], " ?procs? ?host? ?port?\"", NULL); return TCL_ERROR; } procs = (argc > 1) ? argv[1] : NULL; host = (argc > 2) ? argv[2] : NULL; port = (argc > 3) ? argv[3] : NULL; if (NsAdpDebug(itPtr, host, port, procs) != TCL_OK) { Tcl_SetResult(interp, "could not initialize debugger", TCL_STATIC); return TCL_ERROR; } sprintf(buf, "%d", itPtr->adp.debugLevel); Tcl_SetResult(interp, buf, TCL_VOLATILE); return TCL_OK; } /* *---------------------------------------------------------------------- * * NsTclAdpMimeTypeCmd -- * * Process the ns_adp_mimetype command to set or get the mime type * returned upon completion of the parsed file. * * Results: * A standard Tcl result. * * Side effects: * Potentially updates the mime type for this adp page. * *---------------------------------------------------------------------- */ int NsTclAdpMimeTypeObjCmd(ClientData arg, Tcl_Interp *interp, int objc, Tcl_Obj **objv) { NsInterp *itPtr = arg; Ns_Conn *conn = itPtr->conn; if (objc != 1 && objc != 2) { Tcl_WrongNumArgs(interp, 1, objv, "?mimetype?"); return TCL_ERROR; } if (conn != NULL) { if (objc == 2) { Ns_ConnSetType(conn, Tcl_GetString(objv[1])); } Tcl_SetResult(interp, Ns_ConnGetType(conn), TCL_VOLATILE); } return TCL_OK; } /* *---------------------------------------------------------------------- * * NsAdpAppend -- * * Append content to the ADP output buffer, flushing the content * if necessary. * * Results: * TCL_ERROR if append and/or flush failed, TCL_OK otherwise. * * Side effects: * Will set ADP error flag and leave an error message in * the interp on flush failure. * *---------------------------------------------------------------------- */ int NsAdpAppend(NsInterp *itPtr, char *buf, int len) { Tcl_DString *bufPtr; if (GetOutput(itPtr, &bufPtr) != TCL_OK) { return TCL_ERROR; } Ns_DStringNAppend(bufPtr, buf, len); if (bufPtr->length > (int) itPtr->adp.bufsize && NsAdpFlush(itPtr, 1) != TCL_OK) { return TCL_ERROR; } return TCL_OK; } /* *---------------------------------------------------------------------- * * GetFrame -- * * Validate and return the current execution frame. * * Results: * TCL_ERROR if no active frame, TCL_OK otherwise. * * Side effects: * Will update given framePtrPtr with current frame. * *---------------------------------------------------------------------- */ static int GetFrame(ClientData arg, AdpFrame **framePtrPtr) { NsInterp *itPtr = arg; if (itPtr->adp.framePtr == NULL) { Tcl_SetResult(itPtr->interp, "no active adp", TCL_STATIC); return TCL_ERROR; } *framePtrPtr = itPtr->adp.framePtr; return TCL_OK; } /* *---------------------------------------------------------------------- * * GetOutput -- * * Validates and returns current output buffer. * * Results: * TCL_ERROR if GetFrame fails, TCL_OK otherwise. * * Side effects: * Will update given dsPtrPtr with buffer. * *---------------------------------------------------------------------- */ static int GetOutput(ClientData arg, Tcl_DString **dsPtrPtr) { AdpFrame *framePtr; if (GetFrame(arg, &framePtr) != TCL_OK) { return TCL_ERROR; } *dsPtrPtr = framePtr->outputPtr; return TCL_OK; }