ilya1725
ilya1725

Reputation: 4968

Handle exit command executed by embedded Tcl runtime

I have a small shell application that embeds Tcl to execute some set of Tcl code. The Tcl interpreter is initialized using Tcl_CreateInterp. Everything is very simple:

  1. user types Tcl command
  2. the command gets passed to Tcl_Eval for evaluation
  3. repeat

But if a user types 'exit', which is a valid Tcl command, the whole thing - Tcl interpreter and my shell application - exit automatically.

Q: is there any way I can catch this exit signal coming from Tcl interpreter. I really would like not to check every user command. I tried Tcl_CreateExitHandler, but it didn't work.

Thanks so much.

Upvotes: 6

Views: 1198

Answers (3)

ilya1725
ilya1725

Reputation: 4968

Using Tcl_CreateExitHandler works fine. The problem was that I added a printf into the handler implementation and the output didn't show up on the terminal. So I thought it hasn't been called. However, by the time this handler is executed there is no stdout any more. Running strace on the application shows that the handler is being executed fine.

Another solution to this problem can be to use atexit and process the exit event there.

Upvotes: 0

Hai Vu
Hai Vu

Reputation: 40773

Rename the exit command:

rename exit __exit

proc exit {args} {
    puts -nonewline "Do you really want to exit? (y/n) "
    flush stdout
    gets stdin answer
    if {$answer == "y"} {
        __exit [lindex $args 0]
    }
}

This way, when the user type exit, he/she will execute your custom exit command, in which you can do anything you like.

Upvotes: 2

RHSeeger
RHSeeger

Reputation: 16282

Get rid of the command

rename exit ""

Or redefine it to let the user know it's disabled:

proc exit {args} { error "The exit command is not available in this context" }

Also worth considering is running the user's code in a safe interp instead of in the main shell. Doing so would allow you to control exactly what the user has access to.

You might also be able to create a child interp (non-safe) and just disable the exit command for that interp.

Lastly, you could just rename exit to something else, if you're only trying to avoid users typing it by mistake:

namespace eval ::hidden {}
rename exit ::hidden::exit

Upvotes: 9

Related Questions