Added ns_adp_ctl, ns_adp_flush, and ns_adp_close commands and simplified code with new NsAdpGetBuf API. Also, use of new Ns_ConnSetType and Ns_ConnGetType to factor out previous ADP-only code.
/*
* 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.17 2005/01/15 23:52:56 jgdavidson Exp $, compiled: " __DATE__ " " __TIME__;
#include "nsd.h"
static int ReturnObjCmd(NsInterp *itPtr, int objc, Tcl_Obj **objv,
int exception);
static int EvalObjCmd(NsInterp *itPtr, int objc, Tcl_Obj **objv,
int safe);
/*
*----------------------------------------------------------------------
*
* 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)
{
NsInterp *itPtr = arg;
static CONST char *opts[] = {
"bufsize", "nocache", "trace", "gzip", NULL
};
enum {
CBufSizeIdx, CNoCacheIdx, CTraceIdx, CGzipIdx
};
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 CNoCacheIdx:
case CTraceIdx:
case CGzipIdx:
if (objc != 2 && objc !=3 ) {
Tcl_WrongNumArgs(interp, 2, objv, "?bool?");
return TCL_ERROR;
}
switch (opt) {
case CTraceIdx:
flag = ADP_TRACE;
break;
case CNoCacheIdx:
flag = ADP_TRACE;
break;
case CGzipIdx:
flag = ADP_GZIP;
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;
}
/*
*----------------------------------------------------------------------
*
* 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, 1);
}
static int
EvalObjCmd(NsInterp *itPtr, int objc, Tcl_Obj **objv, int safe)
{
if (objc < 2) {
Tcl_WrongNumArgs(itPtr->interp, 1, objv, "page ?args ...?");
return TCL_ERROR;
}
return NsAdpEval(itPtr, objc-1, objv+1, safe, 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 (NsAdpGetBuf(itPtr, &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, file, objc, objv, 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)
{
int isfile, i, safe;
char *opt;
char *resvarname = NULL;
char *cwd = NULL;
NsInterp *itPtr = (NsInterp *)arg;
int result;
if (objc < 2) {
badargs:
Tcl_WrongNumArgs(interp, 1, objv,
"?-file|-string? ?-savedresult varname? ?-cwd path? arg ?arg ...?");
return TCL_ERROR;
}
isfile = safe = 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) {
resvarname = 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")) {
safe = 1;
} 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) {
itPtr->adp.cwd = cwd;
}
if (isfile) {
result = NsAdpSource(arg, objc, objv, resvarname);
} else {
result = NsAdpEval(arg, objc, objv, safe, resvarname);
}
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;
}
if (itPtr->adp.cwd != NULL && *itPtr->adp.cwd) {
Tcl_SetResult(interp, itPtr->adp.cwd, TCL_VOLATILE);
} else {
Tcl_SetResult(interp, "/", TCL_STATIC);
}
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 ReturnObjCmd(arg, objc, objv, ADP_RETURN);
}
int
NsTclAdpBreakObjCmd(ClientData arg, Tcl_Interp *interp, int objc,
Tcl_Obj **objv)
{
return ReturnObjCmd(arg, objc, objv, ADP_BREAK);
}
int
NsTclAdpAbortObjCmd(ClientData arg, Tcl_Interp *interp, int objc,
Tcl_Obj **objv)
{
return ReturnObjCmd(arg, objc, objv, ADP_ABORT);
}
static int
ReturnObjCmd(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)
{
NsInterp *itPtr = arg;
Tcl_DString *dsPtr;
if (objc != 1) {
Tcl_WrongNumArgs(interp, 1, objv, NULL);
return TCL_ERROR;
}
if (NsAdpGetBuf(itPtr, &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)
{
NsInterp *itPtr = arg;
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 (NsAdpGetBuf(itPtr, &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)
{
NsInterp *itPtr = arg;
Tcl_DString *dsPtr;
if (objc != 1) {
Tcl_WrongNumArgs(interp, 1, objv, NULL);
return TCL_ERROR;
}
if (NsAdpGetBuf(itPtr, &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)
{
NsInterp *itPtr = arg;
if (objc != 1) {
Tcl_WrongNumArgs(interp, 1, objv, NULL);
return TCL_ERROR;
}
Tcl_SetObjResult(interp, Tcl_NewIntObj(itPtr->adp.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)
{
NsInterp *itPtr = arg;
int i;
if (objc != 1 && objc != 2) {
Tcl_WrongNumArgs(interp, 1, objv, "?index?");
return TCL_ERROR;
}
if (objc == 1) {
Tcl_SetListObj(Tcl_GetObjResult(interp), itPtr->adp.objc,
itPtr->adp.objv);
} else {
if (Tcl_GetIntFromObj(interp, objv[1], &i) != TCL_OK) {
return TCL_ERROR;
}
if ((i + 1) <= itPtr->adp.objc) {
Tcl_SetObjResult(interp, itPtr->adp.objv[i]);
}
}
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)
{
NsInterp *itPtr = arg;
int i;
if (objc < 2) {
Tcl_WrongNumArgs(interp, 1, objv, "varName ?varName ...?");
return TCL_ERROR;
}
if (objc != itPtr->adp.objc) {
Tcl_AppendResult(interp, "invalid #variables", NULL);
return TCL_ERROR;
}
for (i = 1; i < objc; ++i) {
if (Tcl_ObjSetVar2(interp, objv[i], NULL, itPtr->adp.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;
}
|
Back to SourceForge.net Powered by ViewCVS 1.0-dev |