pty.tcl - a tcl extension for Posix pty support using critcl -
CMcC 18May2012
- a sloppy job, but it's a start
# pty - an extension to provide Posix pty support to Tcl
package provide Pty 1.0
if {[info commands ::_pty] ne ""} {
# pty - create a pty
# returns an open chan for the master pty, and the file name of the associated slave pty
#
# args to pty are in the form of a dict such that:
# rdwr $rdwr - boolean to indicate that the pty is (or is not) readable and writable
# noctty $noctty - boolean to indicate that the pty is not the controlling terminal for this process
#
proc pty {args} {
set rdwr 1
set noctty 1
dict with args {}
return [_pty $rdwr $noctty]
}
return
}
package require critcl
::critcl::tsources pty.tcl
critcl::ccode {
#include <stdlib.h>
#include <fcntl.h>
#include <tcl.h>
#include <errno.h>
#include <stdio.h>
}
critcl::cproc _pty {Tcl_Interp* interp int rdwr int noctty} ok {
int master;
static int pty_count = 0;
char slave[256];
Tcl_Channel masterC;
char masterChan[64];
Tcl_Obj *result;
Tcl_ChannelType *chanTypePtr;
int flags = 0;
if (rdwr) {
flags |= O_RDWR;
}
if (noctty) {
flags |= O_NOCTTY;
}
master = posix_openpt(flags);
if (master < 0) {
Tcl_AppendResult(interp,
"open pty failed \"", Tcl_ErrnoMsg(Tcl_GetErrno()), "\"",
(char *) NULL);
return TCL_ERROR;
}
if (ptsname_r(master, slave, sizeof(slave)) < 0) {
Tcl_AppendResult(interp,
"ptsname failed \"", Tcl_ErrnoMsg(Tcl_GetErrno()), "\"",
(char *) NULL);
return TCL_ERROR;
}
masterC = Tcl_MakeFileChannel(master,TCL_READABLE | TCL_WRITABLE);
if (masterC == (Tcl_Channel)NULL) {
return TCL_ERROR;
}
/*fprintf(stderr, "master: %x\n", masterC);*/
Tcl_RegisterChannel(interp, masterC);
result = Tcl_NewListObj(0, NULL);
Tcl_ListObjAppendElement(interp, result, Tcl_NewStringObj(Tcl_GetChannelName(masterC), -1));
Tcl_ListObjAppendElement(interp, result, Tcl_NewStringObj(slave, -1));
Tcl_SetObjResult(interp, result);
return TCL_OK;
}