A package that provides a simple interface to start programs and control them via a pty for Lua.
Author: Gunnar Zötl
Released under MIT/X11 license. See file LICENSE for details.
This is a simple interface to pty functionality, providing the ability to fork a process and run it under pty control. It does not try to mimic the posix API but instead focuses on the function of running and controlling a program. The interface is very bare bones, no additional functionality is provided, especially nothing like expect, which should be a different package.
This has been developed on Linux and tested on MacOS X. It should compile and run on any platform supporting the Unix 98 interface to pty's. Support for additional Unixen might follow in the future, depending on demand (especially my own ;) ). No support for windows is planned, as ptys are a Unix thing. It might work with cygwin.
This uses only stuff that comes with your system. Normally, calling
sudo luarocks install lpty
or when you have an unpacked source folder,
sudo luarocks make
should do the right thing.
There is also a Makefile in the distribution directory, which has been created for and on Linux, basically for special needs. You will have to edit it by hand, so the luarocks method is preferrable.
require "lpty"
pty = lpty.new([{[throw_errors = true|false], [no_local_echo = true|false]}])throw_errorsno_local_echopty:startproc("command", "arg1", "arg2", ...)pty:endproc([kill])pty:hasproc()pty:readok([timeout])pty:read([timeout])pty:sendok([timeout])pty:send(data [, timeout])the read() method reads its data ito a buffer. The size of this buffer determines how much data can be returned from an individual read. It is set by a #define at the start of the module source and by default is set to 4096. Considering the C-typical terminating zero, this will leave a maximum of 4095 bytes to be read in one go. In order to fetch all available data, just loop while pty:readok() and concatenate the results.
Similar things hold for send(). It may not send all data you gave it in one go. For small amounts of data this is quite improbable, but in industrial strength applications you should probably check the return value of the send() method against the length of the data you intended to send.
If you have a pty without a running child process, you can only read from it what you write to it (unless you specified no_local_echo=true for pty creation, in which case you can not read anything from it). This means that if you (or the last active child process) have nothing written to it, a read with timeout will always time out, and a read without timeout will block. However, if you later start a child process, anything you have written to the pty before that will be available as input to the child. Reading stuff back from the master side of a pty does not remove it from the slave side.
The startproc() method can not check whether running the command in the child process or basically anything that happens in the child process after the fork is successful. If startproc() returns true, this means that setting up the client side of the tty and fork()ing went well and yielded a running child process. You may want to check wether it is still running when you need it using the hasproc() method, especially if you're dealing with an interactive program. If the program the child was supposed to start is not running when you expect it to, you will have to check the contents of the pty for the reason.
When a lpty object is garbage collected, its master side pty handle is closed, and if it as a child process, that is terminated with a SIGKILL. So it is reasonably safe to let pty's with active processes become garbage, it just isn't very friendly towards the child processes.
See the samples folder in the distribution archive.
Read up on ptys on your local friendly linux system: man 7 pty and friends. This is linux specific, but as I use Unix 98 pseudo ttys, this holds whereever they're available.