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);
}
···········@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