TIP #83: AUGMENT TCL_EVALFILE WITH TCL_EVALCHANNEL AND TCL_EVALURL ==================================================================== Version: $Revision: 1.6 $ Author: Marian Szczepkowski State: Withdrawn Type: Project Tcl-Version: 8.5 Vote: Pending Created: Thursday, 24 January 2002 URL: https://tip.tcl-lang.org83.html Post-History: ------------------------------------------------------------------------- ABSTRACT ========== This TIP adds the ability to load Tcl files directly from URLs to the core, together with a basic mechanism to simply evaluate a stream of characters from a channel. PROPOSAL ========== I propose to split the /Tcl_EvalFile/ function into two components to enable the [source] command to use URL's to obtain source material. This will mean splitting /Tcl_EvalFile/ into /Tcl_EvalFile/ and /Tcl_EvalChannel/ which are the two logical entities. Maintaining /Tcl_EvalFile/ will preserve backward compatability. Creating /Tcl_EvalChannel/ will provide generic functionality for future use. Adding /Tcl_EvalUrl/ will enable handling standard URL format strings. This would enable this [source ] to be used. Code will also need to be added to /Tcl_SourceObjCmd/ to select functionality requested. PRO. ====== In a corporate environment where scripts are subject to change but the interface is not, this allows scripts to be stored remotely on a central server. This also allows Tcl to interwork in a networked environment. CON. ====== Security!!!! This may mean in the long run adding a signing layer, but don't use it if you don't want to. SAMPLE ======== I figure it looking something like this. Snipped from 8.3 source. TCL_SOURCEOBJCMD ================== int Tcl_SourceObjCmd(dummy, interp, objc, objv) ClientData dummy; /* Not used. */ Tcl_Interp *interp; /* Current interpreter. */ int objc; /* Number of arguments. */ Tcl_Obj *CONST objv[]; /* Argument objects. */ { char *bytes; int result; if (objc != 2) { Tcl_WrongNumArgs(interp, 1, objv, "fileName"); return TCL_ERROR; } bytes = Tcl_GetString(objv[1]); if (strstr(ptr,"://")) { result = Tcl_EvalFile(interp, bytes); } else { result = Tcl_EvalUrl(interp, bytes); } return result; } TCL_EVALFILE ============== int Tcl_EvalFile(interp, fileName) Tcl_Interp *interp; /* Interpreter in which to process file. */ char *fileName; /* Name of file to process. Tilde-substitution * will be performed on this name. */ { int result, length; struct stat statBuf; Interp *iPtr; Tcl_DString nameString; char *name, *string; Tcl_Channel chan; Tcl_Obj *objPtr; name = Tcl_TranslateFileName(interp, fileName, &nameString); if (name == NULL) { return TCL_ERROR; } result = TCL_ERROR; if (TclStat(name, &statBuf) == -1) { Tcl_SetErrno(errno); Tcl_AppendResult(interp, "couldn't read file \"", fileName, "\": ", Tcl_PosixError(interp), (char *) NULL); goto end; } chan = Tcl_OpenFileChannel(interp, name, "r", 0644); if (chan == (Tcl_Channel) NULL) { Tcl_ResetResult(interp); Tcl_AppendResult(interp, "couldn't read file \"", fileName, "\": ", Tcl_PosixError(interp), (char *) NULL); goto end; } result = Tcl_EvalChannel(interp, chan); end: Tcl_DStringFree(&nameString); return result; } TCL_EVALURL ============= int Tcl_EvalUrl(interp, fileName) Tcl_Interp *interp; /* Interpreter in which to process file. */ char *fileName; /* Name of URL to process. */ { return TCL_ERROR; } TCL_EVALCHANNEL ================= int Tcl_EvalChannel(interp, chan) Tcl_Interp *interp; /* Interpreter in which to process file. */ Tcl_Channel chan; /* Name of file to process. */ { int result, length; struct stat statBuf; char *oldScriptFile; Interp *iPtr; char *name, *string; Tcl_Obj *objPtr; result = TCL_ERROR; objPtr = Tcl_NewObj(); if (Tcl_ReadChars(chan, objPtr, -1, 0) < 0) { Tcl_Close(interp, chan); Tcl_AppendResult(interp, "couldn't read file \"", fileName, "\": ", Tcl_PosixError(interp), (char *) NULL); goto end; } if (Tcl_Close(interp, chan) != TCL_OK) { goto end; } iPtr = (Interp *) interp; oldScriptFile = iPtr->scriptFile; iPtr->scriptFile = fileName; string = Tcl_GetStringFromObj(objPtr, &length); result = Tcl_EvalEx(interp, string, length, 0); iPtr->scriptFile = oldScriptFile; if (result == TCL_RETURN) { result = TclUpdateReturnInfo(iPtr); } else if (result == TCL_ERROR) { char msg[200 + TCL_INTEGER_SPACE]; /* * Record information telling where the error occurred. */ sprintf(msg, "\n (file \"%.150s\" line %d)", fileName, interp->errorLine); Tcl_AddErrorInfo(interp, msg); } end: Tcl_DecrRefCount(objPtr); return result; } COMMENTS ========== The VFS extension interface of Tcl 8.4 plus the tclvfs and vfs::http packages provide the ability to [source] an URL. I believe that makes this proposal out of date. COPYRIGHT =========== This document has been placed in the public domain. ------------------------------------------------------------------------- TIP AutoGenerator - written by Donal K. Fellows