Tag Archives: tcl

You can now write nbdkit plugins in Tcl

I have a soft spot for the Tcl programming language because Tcl/Tk was one of the earliest and best rapid GUI development environments available on Unix.

Well now you can write nbdkit plugins in Tcl.

Here’s an example:

# This is called from: nbdkit tcl example.tcl --dump-plugin
proc dump_plugin {} {
    puts "example_tcl=1"
}

# We expect a file=... parameter pointing to the file to serve.
proc config {key value} {
    global file

    if { $key == "file" } {
        set file $value
    } else {
        error "unknown parameter $key=$value"
    }
}

# Check the file parameter was passed.
proc config_complete {} {
    global file

    if { ![info exists file] } {
        error "file parameter missing"
    }
}

# Open a new client connection.
proc plugin_open {readonly} {
    global file

    # Open the file.
    if { $readonly } {
        set flags "r"
    } else {
        set flags "r+"
    }
    set fh [open $file $flags]

    # Stop Tcl from trying to convert to and from UTF-8.
    fconfigure $fh -translation binary

    # We can return any Tcl object as the handle.  In this
    # plugin it's convenient to return the file handle.
    return $fh
}

# Close a client connection.
proc plugin_close {fh} {
    close $fh
}

proc get_size {fh} {
    global file

    return [file size $file]
}

proc pread {fh count offset} {
    seek $fh $offset
    return [read $fh $count]
}

proc pwrite {fh buf offset} {
    seek $fh $offset
    puts -nonewline $fh $buf
}
Advertisements

1 Comment

Filed under Uncategorized

miniexpect: A small expect library for C

The rewrite of virt-p2v dumps the old system where the front end and the back end talked over a custom protocol. In the new version, virt-p2v ssh’es into the conversion server and runs commands directly.

However to do this I needed to be able to control the interactive ssh process from the program.

The classical way to do this is using Tcl’s expect tool. You can write expect scripts like this:

#!/usr/bin/expect  --
set timeout 30
spawn ssh user@remote
expect {           
    password: {
        send "secret\r"
    }
    "yes/no)?" {
        send "yes\r"
        set timeout -1
    }
    timeout {
        exit
    }
    eof {
        exit
    }
}

This doesn’t work so well from C, but luckily there is libexpect. Unfortunately the libexpect API isn’t thread-safe (we ❤ globals!), doesn’t adhere to modern C standards, and the library is quite buggy.

How hard would it be to write an expect replacement? At first glance it seems like it would be hard. libexpect has to contain a complete regular expression implementation (and a glob implementation too), because it has to be able to drive the regular expression parser over the incomplete data that it is reading from the subprocess.

However here is an observation: PCRE provides an implementation of partial pattern matching meaning that you can match on the incomplete data you’ve already received from the subprocess and decide whether you have a complete match or a partial match (in the partial match case you just wait for more data to arrive).

Using PCRE partial matches, I was able to write a pretty good mini-library for expect in just under 500 lines of code. The library is here:

http://git.annexia.org/?p=miniexpect.git;a=tree

Leave a comment

Filed under Uncategorized