Hi,

I, for some reason, wanted to start a shell in Hemlock, and noticed
that it didn't work, since it couldn't find a pty. Some further search
of source showed me that RUN-PROGRAM with output to a pty didn't work
either; it seems that the approach that CMUCL takes in EXT::FIND-A-PTY
doesn't work on my system. (Neither does SBCL, which uses the same.)

I'm running Debian/unstable, currently on a 2.6.8.1 kernel; I do have
compatibility with "old" pty:s compiled in. I know precious little about
unix programming on this level, but looking in the info file for glibc
and run-program.lisp I came up with the following, which enables me to
run a shell in Hemlock (although there's an extra #\Return on the end
of each line, but I think that used to be there earlier as well), and
RUN-PROGRAM other stuff with :PTY T.

I'm not at all certain whether this is a correct approach, though; it
seems to be something that changed in (my installation of) Linux, not
in CMUCL.

---
(in-package :unix)
#+glibc2
(without-package-locks

(def-alien-type nil
  (struct sgttyb
    #+linux (sg-flags #+mach short #-mach int) ; mode flags       
    (sg-ispeed char)                    ; input speed.
    (sg-ospeed char)                    ; output speed
    (sg-erase char)                     ; erase character
    #-linux (sg-kill char)                      ; kill character
    #-linux (sg-flags #+mach short #-mach int) ; mode flags
    #+linux (sg-kill char)
    #+linux (t (struct termios))
    #+linux (check int)))
)
(in-package :ext)
(without-package-locks

(alien:def-alien-routine ("getpt" c-getpt) c-call:int
  (fildes c-call:int :out))
(alien:def-alien-routine ("ptsname" c-ptsname) c-call:c-string
  (fildes c-call:int))
(alien:def-alien-routine ("unlockpt" c-unlockpt) c-call:int
  (fildes c-call:int))
(alien:def-alien-routine ("grantpt" c-grantpt) c-call:int
  (fildes c-call:int))

(defun find-a-pty ()
  "Returns the master fd, the slave fd, and the name of the tty"
  (multiple-value-bind
      (master-fd errno)
      (c-getpt)
    (when (and (<= 0 (c-grantpt master-fd)) (<= 0 (c-unlockpt master-fd)))
      (let* ((slave-name (c-ptsname master-fd))
             (slave-fd (unix:unix-open slave-name
                                       unix:o_rdwr
                                       #o666)))
        (when (and slave-name (<= 0 slave-fd))
          (return-from find-a-pty
                       (values master-fd
                               slave-fd
                               slave-name)))))
    (unix:unix-close master-fd))
  (error "Could not find a pty."))
)
---

The versions of my packages are:

cmucl: 19a-release-20040728-7
sbcl: 1:0.8.14.24-1

Regards,

'mr

-- 
[Emacs] is written in Lisp, which is the only computer language that is
beautiful.  -- Neal Stephenson, _In the Beginning was the Command Line_

Reply via email to