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; }