int tclcommand_replacestdchannel(ClientData clientData, Tcl_Interp *interp, int argc, char **argv)
{
  Tcl_Channel channel=NULL;

  if (argc != 3){
    Tcl_AppendResult(interp,"Wrong # of args! Usage: ",argv[0]," [stdout|stderr|stdin] <pipename>",(char *)NULL);
    return TCL_ERROR;
  }

  if(access(argv[2],F_OK)<0){
    Tcl_AppendResult(interp,"File ",argv[2]," does not exist!",(char *) NULL);
    return TCL_ERROR;
  }

  if(strcmp(argv[1],"stdout")==0){
    if(access(argv[2],W_OK)<0){
      Tcl_AppendResult(interp,"You do not have permission to access ",argv[2],(char *) NULL);
      return TCL_ERROR;
    }
    Tcl_UnregisterChannel(interp,Tcl_GetStdChannel(TCL_STDOUT));
    channel = Tcl_OpenFileChannel(interp, argv[2], "WRONLY",0666);
    Tcl_RegisterChannel(interp,channel);
    Tcl_SetStdChannel(channel,TCL_STDOUT);
  }
  else if(strcmp(argv[1],"stderr")==0){
    if(access(argv[2],W_OK)<0){
      Tcl_AppendResult(interp,"You do not have permission to access ",argv[2],(char *) NULL);
      return TCL_ERROR;
    }
    Tcl_UnregisterChannel(interp,Tcl_GetStdChannel(TCL_STDERR));
    channel = Tcl_OpenFileChannel(interp, argv[2], "WRONLY",0666);
    Tcl_RegisterChannel(interp,channel);
    Tcl_SetStdChannel(channel,TCL_STDERR);
  }
  else if(strcmp(argv[1],"stdin")==0){
    if(access(argv[2],R_OK)<0){
      Tcl_AppendResult(interp,"You do not have permission to access ",argv[2],(char *) NULL);
      return TCL_ERROR;
    }
    Tcl_UnregisterChannel(interp,Tcl_GetStdChannel(TCL_STDIN));
    channel = Tcl_OpenFileChannel(interp, argv[2], "RDONLY",0666);
    Tcl_RegisterChannel(interp,channel);
    Tcl_SetStdChannel(channel,TCL_STDIN);
  }
  else{
    Tcl_AppendResult(interp,"invalid first argument (got: ",argv[1]," )",(char *) NULL);
    return TCL_ERROR;
  }

  if(channel == NULL)
    return TCL_ERROR;

  return TCL_OK;
}
示例#2
0
int
Pg_disconnect(ClientData cData, Tcl_Interp *interp, int argc, CONST84 char *argv[])
{
	PGconn	   *conn;
	Tcl_Channel conn_chan;

	if (argc != 2)
	{
		Tcl_AppendResult(interp, "Wrong # of arguments\n", "pg_disconnect connection", 0);
		return TCL_ERROR;
	}

	conn_chan = Tcl_GetChannel(interp, argv[1], 0);
	if (conn_chan == NULL)
	{
		Tcl_ResetResult(interp);
		Tcl_AppendResult(interp, argv[1], " is not a valid connection", 0);
		return TCL_ERROR;
	}

	/* Check that it is a PG connection and not something else */
	conn = PgGetConnectionId(interp, argv[1], (Pg_ConnectionId **) NULL);
	if (conn == (PGconn *) NULL)
		return TCL_ERROR;

	return Tcl_UnregisterChannel(interp, conn_chan);
}
示例#3
0
bool ecAdminDialog::EvalTclFile(int nargc, const wxString& Argv, const wxString& msg)
{
    wxProgressDialog dlgWait(msg, _("Please wait..."), 100, this);

    dlgWait.Update(50);

//TRACE (_T("Evaluating ecosadmin.tcl %s\n"), pszArgv);

    // set up the data structure which is passed to the Tcl thread

    wxString strArgc;
    strArgc.Printf (wxT("%d"), nargc);
    std::string argv0 = ecUtils::UnicodeToStdStr (m_strRepository) + "/ecosadmin.tcl";
    std::string argv = ecUtils::UnicodeToStdStr (Argv);
    std::string argc = ecUtils::UnicodeToStdStr (strArgc);

    Tcl_Interp * interp = Tcl_CreateInterp ();

#ifdef __WXMSW__
    Tcl_Channel outchan = Tcl_OpenFileChannel (interp, "nul", "a+", 777);
    Tcl_SetStdChannel (outchan, TCL_STDOUT); // direct standard output to NUL:
#endif

    const char * pszStatus = Tcl_SetVar (interp, "argv0", (char*) argv0.c_str(), 0);
    pszStatus = Tcl_SetVar (interp, "argv", (char*) argv.c_str(), 0);
    pszStatus = Tcl_SetVar (interp, "argc", (char*) argc.c_str(), 0);
    pszStatus = Tcl_SetVar (interp, "gui_mode", "1", 0); // return errors in result string
    int nStatus = Tcl_EvalFile (interp, (char*) argv0.c_str());
    const char* result = Tcl_GetStringResult (interp);

#ifdef __WXMSW__
    Tcl_SetStdChannel (NULL, TCL_STDOUT);
    Tcl_UnregisterChannel (interp, outchan);
#endif

    Tcl_DeleteInterp (interp);

    wxString strErrorMessage (result);

    // report any error
    if (! strErrorMessage.IsEmpty ())
    {
        wxString msg (_("Command execution error:\n\n") + strErrorMessage);
        wxMessageBox(msg, wxGetApp().GetSettings().GetAppName(), wxICON_EXCLAMATION|wxOK);
	return FALSE;
    }
    else if (TCL_OK != nStatus)
    {
        wxString msg (_("Command execution error"));
        wxMessageBox(msg, wxGetApp().GetSettings().GetAppName(), wxICON_EXCLAMATION|wxOK);
    return FALSE;
    }

    return TRUE;
}
	/* ARGSUSED */
int
Tcl_CloseObjCmd(
    ClientData clientData,	/* Not used. */
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* Argument objects. */
{
    Tcl_Channel chan;		/* The channel to close. */

    if (objc != 2) {
	Tcl_WrongNumArgs(interp, 1, objv, "channelId");
	return TCL_ERROR;
    }

    if (TclGetChannelFromObj(interp, objv[1], &chan, NULL, 0) != TCL_OK) {
	return TCL_ERROR;
    }

    if (Tcl_UnregisterChannel(interp, chan) != TCL_OK) {
	/*
	 * If there is an error message and it ends with a newline, remove the
	 * newline. This is done for command pipeline channels where the error
	 * output from the subprocesses is stored in interp's result.
	 *
	 * NOTE: This is likely to not have any effect on regular error
	 * messages produced by drivers during the closing of a channel,
	 * because the Tcl convention is that such error messages do not have
	 * a terminating newline.
	 */

	Tcl_Obj *resultPtr = Tcl_GetObjResult(interp);
	char *string;
	int len;

	if (Tcl_IsShared(resultPtr)) {
	    resultPtr = Tcl_DuplicateObj(resultPtr);
	    Tcl_SetObjResult(interp, resultPtr);
	}
	string = TclGetStringFromObj(resultPtr, &len);
	if ((len > 0) && (string[len - 1] == '\n')) {
	    Tcl_SetObjLength(resultPtr, len - 1);
	}
	return TCL_ERROR;
    }

    return TCL_OK;
}
示例#5
0
/*-----------------------------------------------------------------------------
 * CloseForError --
 *
 *   Close a file on error.  If the file is associated with a channel, close
 * it too. The error number will be saved and not lost.
 *
 * Parameters:
 *   o interp (I) - Current interpreter.
 *   o channel (I) - Channel to close if not NULL.
 *   o fileNum (I) - File number to close if >= 0.
 *-----------------------------------------------------------------------------
 */
static void
CloseForError (Tcl_Interp *interp,
               Tcl_Channel channel,
               int         fileNum)
{
    int saveErrNo = Tcl_GetErrno ();

    /*
     * Always close fileNum, even if channel close is done, as it doesn't
     * close stdin, stdout or stderr numbers.
     */
    if (channel != NULL)
        Tcl_UnregisterChannel (interp, channel);
    if (fileNum >= 0)
        close (fileNum);
     Tcl_SetErrno (saveErrNo);
}
示例#6
0
void
TnmDeleteSocketHandler(int sock)
{
    SocketHandler **shPtrPtr;

    for (shPtrPtr = &socketHandlerList; *shPtrPtr; ) {
	if ((*shPtrPtr)->sd == sock) {
	    Tcl_DeleteChannelHandler((*shPtrPtr)->channel,
				     (*shPtrPtr)->proc,
				     (*shPtrPtr)->clientData);
	    Tcl_UnregisterChannel((Tcl_Interp *) NULL, (*shPtrPtr)->channel);
	    *shPtrPtr = (*shPtrPtr)->nextPtr;
	} else {
	  shPtrPtr = &(*shPtrPtr)->nextPtr;
	}
    }
}
static void
AcceptCallbackProc(
    ClientData callbackData,	/* The data stored when the callback was
				 * created in the call to
				 * Tcl_OpenTcpServer. */
    Tcl_Channel chan,		/* Channel for the newly accepted
				 * connection. */
    char *address,		/* Address of client that was accepted. */
    int port)			/* Port of client that was accepted. */
{
    AcceptCallback *acceptCallbackPtr = (AcceptCallback *) callbackData;

    /*
     * Check if the callback is still valid; the interpreter may have gone
     * away, this is signalled by setting the interp field of the callback
     * data to NULL.
     */

    if (acceptCallbackPtr->interp != NULL) {
	char portBuf[TCL_INTEGER_SPACE];
	char *script = acceptCallbackPtr->script;
	Tcl_Interp *interp = acceptCallbackPtr->interp;
	int result;

	Tcl_Preserve(script);
	Tcl_Preserve(interp);

	TclFormatInt(portBuf, port);
	Tcl_RegisterChannel(interp, chan);

	/*
	 * Artificially bump the refcount to protect the channel from being
	 * deleted while the script is being evaluated.
	 */

	Tcl_RegisterChannel(NULL, chan);

	result = Tcl_VarEval(interp, script, " ", Tcl_GetChannelName(chan),
		" ", address, " ", portBuf, NULL);
	if (result != TCL_OK) {
	    TclBackgroundException(interp, result);
	    Tcl_UnregisterChannel(interp, chan);
	}

	/*
	 * Decrement the artificially bumped refcount. After this it is not
	 * safe anymore to use "chan", because it may now be deleted.
	 */

	Tcl_UnregisterChannel(NULL, chan);

	Tcl_Release(interp);
	Tcl_Release(script);
    } else {
	/*
	 * The interpreter has been deleted, so there is no useful way to
	 * utilize the client socket - just close it.
	 */

	Tcl_Close(NULL, chan);
    }
}
示例#8
0
文件: tclFCmd.c 项目: smh377/tcl
int
TclFileTemporaryCmd(
    ClientData clientData,
    Tcl_Interp *interp,
    int objc,
    Tcl_Obj *const objv[])
{
    Tcl_Obj *nameVarObj = NULL;	/* Variable to store the name of the temporary
				 * file in. */
    Tcl_Obj *nameObj = NULL;	/* Object that will contain the filename. */
    Tcl_Channel chan;		/* The channel opened (RDWR) on the temporary
				 * file, or NULL if there's an error. */
    Tcl_Obj *tempDirObj = NULL, *tempBaseObj = NULL, *tempExtObj = NULL;
				/* Pieces of template. Each piece is NULL if
				 * it is omitted. The platform temporary file
				 * engine might ignore some pieces. */

    if (objc < 1 || objc > 3) {
	Tcl_WrongNumArgs(interp, 1, objv, "?nameVar? ?template?");
	return TCL_ERROR;
    }

    if (objc > 1) {
	nameVarObj = objv[1];
	TclNewObj(nameObj);
    }
    if (objc > 2) {
	int length;
	Tcl_Obj *templateObj = objv[2];
	const char *string = TclGetStringFromObj(templateObj, &length);

	/*
	 * Treat an empty string as if it wasn't there.
	 */

	if (length == 0) {
	    goto makeTemporary;
	}

	/*
	 * The template only gives a directory if there is a directory
	 * separator in it.
	 */

	if (strchr(string, '/') != NULL
		|| (tclPlatform == TCL_PLATFORM_WINDOWS
		    && strchr(string, '\\') != NULL)) {
	    tempDirObj = TclPathPart(interp, templateObj, TCL_PATH_DIRNAME);

	    /*
	     * Only allow creation of temporary files in the native filesystem
	     * since they are frequently used for integration with external
	     * tools or system libraries. [Bug 2388866]
	     */

	    if (tempDirObj != NULL && Tcl_FSGetFileSystemForPath(tempDirObj)
		    != &tclNativeFilesystem) {
		TclDecrRefCount(tempDirObj);
		tempDirObj = NULL;
	    }
	}

	/*
	 * The template only gives the filename if the last character isn't a
	 * directory separator.
	 */

	if (string[length-1] != '/' && (tclPlatform != TCL_PLATFORM_WINDOWS
		|| string[length-1] != '\\')) {
	    Tcl_Obj *tailObj = TclPathPart(interp, templateObj,
		    TCL_PATH_TAIL);

	    if (tailObj != NULL) {
		tempBaseObj = TclPathPart(interp, tailObj, TCL_PATH_ROOT);
		tempExtObj = TclPathPart(interp, tailObj, TCL_PATH_EXTENSION);
		TclDecrRefCount(tailObj);
	    }
	}
    }

    /*
     * Convert empty parts of the template into unspecified parts.
     */

    if (tempDirObj && !TclGetString(tempDirObj)[0]) {
	TclDecrRefCount(tempDirObj);
	tempDirObj = NULL;
    }
    if (tempBaseObj && !TclGetString(tempBaseObj)[0]) {
	TclDecrRefCount(tempBaseObj);
	tempBaseObj = NULL;
    }
    if (tempExtObj && !TclGetString(tempExtObj)[0]) {
	TclDecrRefCount(tempExtObj);
	tempExtObj = NULL;
    }

    /*
     * Create and open the temporary file.
     */

  makeTemporary:
    chan = TclpOpenTemporaryFile(tempDirObj,tempBaseObj,tempExtObj, nameObj);

    /*
     * If we created pieces of template, get rid of them now.
     */

    if (tempDirObj) {
	TclDecrRefCount(tempDirObj);
    }
    if (tempBaseObj) {
	TclDecrRefCount(tempBaseObj);
    }
    if (tempExtObj) {
	TclDecrRefCount(tempExtObj);
    }

    /*
     * Deal with results.
     */

    if (chan == NULL) {
	if (nameVarObj) {
	    TclDecrRefCount(nameObj);
	}
	Tcl_SetObjResult(interp, Tcl_ObjPrintf(
		"can't create temporary file: %s", Tcl_PosixError(interp)));
	return TCL_ERROR;
    }
    Tcl_RegisterChannel(interp, chan);
    if (nameVarObj != NULL) {
	if (Tcl_ObjSetVar2(interp, nameVarObj, NULL, nameObj,
		TCL_LEAVE_ERR_MSG) == NULL) {
	    Tcl_UnregisterChannel(interp, chan);
	    return TCL_ERROR;
	}
    }
    Tcl_SetObjResult(interp, Tcl_NewStringObj(Tcl_GetChannelName(chan), -1));
    return TCL_OK;
}
示例#9
0
/*
 * Remove a connection Id from the hash table and
 * close all portals the user forgot.
 */
int
PgDelConnectionId(DRIVER_DEL_PROTO)
{
	Tcl_HashEntry *entry;
	Tcl_HashSearch hsearch;
	Pg_ConnectionId *connid;
	Pg_TclNotifies *notifies;
	int			i;

	connid = (Pg_ConnectionId *) cData;

	for (i = 0; i < connid->res_max; i++)
	{
		if (connid->results[i])
			PQclear(connid->results[i]);
	}
	ckfree((void *) connid->results);

	/* Release associated notify info */
	while ((notifies = connid->notify_list) != NULL)
	{
		connid->notify_list = notifies->next;
		for (entry = Tcl_FirstHashEntry(&notifies->notify_hash, &hsearch);
			 entry != NULL;
			 entry = Tcl_NextHashEntry(&hsearch))
			ckfree((char *) Tcl_GetHashValue(entry));
		Tcl_DeleteHashTable(&notifies->notify_hash);
		if (notifies->conn_loss_cmd)
			ckfree((void *) notifies->conn_loss_cmd);
		if (notifies->interp)
			Tcl_DontCallWhenDeleted(notifies->interp, PgNotifyInterpDelete,
									(ClientData) notifies);
		ckfree((void *) notifies);
	}

	/*
	 * Turn off the Tcl event source for this connection, and delete any
	 * pending notify and connection-loss events.
	 */
	PgStopNotifyEventSource(connid, true);

	/* Close the libpq connection too */
	PQfinish(connid->conn);
	connid->conn = NULL;

	/*
	 * Kill the notifier channel, too.	We must not do this until after
	 * we've closed the libpq connection, because Tcl will try to close
	 * the socket itself!
	 *
	 * XXX Unfortunately, while this works fine if we are closing due to
	 * explicit pg_disconnect, all Tcl versions through 8.4.1 dump core if
	 * we try to do it during interpreter shutdown.  Not clear why. For
	 * now, we kill the channel during pg_disconnect, but during interp
	 * shutdown we just accept leakage of the (fairly small) amount of
	 * memory taken for the channel state representation. (Note we are not
	 * leaking a socket, since libpq closed that already.) We tell the
	 * difference between pg_disconnect and interpreter shutdown by
	 * testing for interp != NULL, which is an undocumented but apparently
	 * safe way to tell.
	 */
#if TCL_MAJOR_VERSION >= 8
	if (connid->notifier_channel != NULL && interp != NULL)
		Tcl_UnregisterChannel(NULL, connid->notifier_channel);
#endif

	/*
	 * We must use Tcl_EventuallyFree because we don't want the connid
	 * struct to vanish instantly if Pg_Notify_EventProc is active for it.
	 * (Otherwise, closing the connection from inside a pg_listen callback
	 * could lead to coredump.)  Pg_Notify_EventProc can detect that the
	 * connection has been deleted from under it by checking connid->conn.
	 */
	Tcl_EventuallyFree((ClientData) connid, TCL_DYNAMIC);

	return 0;
}