From: ···········@gmail.com
Subject: Raw Terminal I/O in lisp
Date: 
Message-ID: <1149037508.042308.266790@g10g2000cwb.googlegroups.com>
Hi all,

I'd appreciate any help for c programmer like me who is new to lisp.

My platform is linux 2.6 (sbcl or lispworks). I'm trying to figure out
how to do terminal I/O in noncanonical mode with lisp.

Below is a simplied version of the example code in APUE.
Here's what I think I need to do:

1. Export the tty_raw function via FFI.

2. Build a console lisp program executable with LW's delivery function
or sbcl's (sb-ext:save-lisp-and-die :executable t)

But I am not quite sure how to write that "main" program in lisp, with
the standard file descriptor opened and pass that descriptor to the
tty_raw FFI function. (I assume that the C file number 0 1 2 doesn't
mean anything in lisp)

Any help would be appreciated!

TIA,
fungsin.



/* raw_term_io.c */
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <termios.h>

int tty_raw (int fd)     /* put terminal into a raw mode */
{
    int             err;
    struct termios  buf;

    /* Echo off, canonical mode off, extended input
       processing off, signal chars off. */
    buf.c_lflag &= ~(ECHO | ICANON | IEXTEN | ISIG);

    /* No SIGINT on BREAK, CR-to-NL off, input parity
       check off, don't strip 8th bit on input, output
       flow control off. */
    buf.c_iflag &= ~(BRKINT | ICRNL | INPCK | ISTRIP | IXON);

    /* Clear size bits, parity checking off. */
    buf.c_cflag &= ~(CSIZE | PARENB);

    /* Set 8 bits/char.*/
    buf.c_cflag |= CS8;

    /* Output processing off. */
    buf.c_oflag &= ~(OPOST);

     /* 1 byte at a time, no timer. */
    buf.c_cc[VMIN] = 1;
    buf.c_cc[VTIME] = 0;
    if (tcsetattr(fd, TCSAFLUSH, &buf) < 0)
        return(-1);

    return(0);
}

int main (int argc, char *argv[])
{
    int     i;
    char    c;

    if (tty_raw(STDIN_FILENO) < 0)
        exit(-1);
    printf("Enter raw mode characters, terminate with DELETE\n");
    while ((i = read(STDIN_FILENO, &c, 1)) == 1) {
        if ((c &= 255) == 0177)     /* 0177 = ASCII DELETE */
            break;
        printf("%o\n", c);
    }
    exit(0);
}
From: Nikodemus Siivola
Subject: Re: Raw Terminal I/O in lisp
Date: 
Message-ID: <1149078407.298391.260450@h76g2000cwa.googlegroups.com>
···········@gmail.com wrote:

> My platform is linux 2.6 (sbcl or lispworks). I'm trying to figure out
> how to do terminal I/O in noncanonical mode with lisp.

The easiest way is to write a C function that sets the terminal mode to
your specifications, and call it from Lisp.

(load-shared-object "my_terminal.so")
(define-alien-routine tty-raw int (fd int))

(tty-raw 0)

FD's 0-2 are standard in the sense that they are what you console talks
to. Which Lisp stream they are attached to is less-obvious, but I'd be
moderately surprised if STDIN wasn't what you want.

You may want to look at how Linedit deals with this (though there are
some things I would do differently if I was writing it now, but isn't
too horrible).

  http://common-lisp.net/project/linedit
 
Cheers,

 -- Nikodemus