Subject: [clisp-list] CGI & binary i/o with stdio

From: "Hoehle, Joerg-Cyril" <[email-masked]>
Date: Wed May 7 00:44:05 2003

Hi,

What do you expect to read from the following stream?
(ext:make-pipe-io-stream "clisp -x '(describe *standard-output*)(exit)'")

I believe sometimes you want interactive mode in the subprocess CLISP (e.g. running inside Emacs), sometimes not (e.g. running as CGI). It all depends on your application.

Sam wrote:
>some users want to be able to do binary i/o on *standard-input* and
>*standard-output* (CGI pretty much requires this).
I understand this.
>There appears to be no portable way to do this in CLISP.
I'm not sure...

What I mean is that I think CLISP auto-discovers whether stdin/stdout (or rather fd=0, fd1 and fd2) are interactive streams or not.

If they are not interactive, CLISP associates regular file streams with them.

One can then (setf stream-element-type) on one of those.
(defun main ()
  (unwind-protect
      (progn
        (setf (stream-element-type *standard-output*) '(unsigned-byte 8))
        (write-byte 123 *standard-output*))
    (setf (stream-element-type *standard-output*) 'character)))
>clisp -q -i /tmp/foo.lisp -x '(main)(exit)' >/tmp/foo

So the question amounts to: should the mechanisms by which clisp discovers whether to use either interactive or file/pipe/socket streams for *standard-in/out-put* be refined?
Apparently.

If yes, how should they be refined?

It looks to me like a command line option would do, since we have a problem with invocation and the external environment, not execution.

Of course, another solution path would be not to care about letting the user enter binary mode even on a tty and just have (setf stream-element-type '(unsigned-byte 8)) work on the #<terminal-io> object. This would not need another command line option.
While this approach may seem more natural at first sight, it breaks internal assumptions about "shall the program use *query-io* interactively?", "can CLISP output a message to stdout and expect a reaction on stdin?", "if CLISP outputs a #\newline, will input be at beginning of line?" or "shall CLISP call clear-input or finish-output in the typical places (like entering a REP loop)?" which a command line option can control.

Like /bin/sh/csh and others, it looks like CLISP needs an option to force interactive or non-interactive standard-input/output. This will be much easier to implement portably (it's almost there already) than to try to figure out how to dup filehandles, sockets or whatever on all the supported OSes.

This shows how *standard-output* can map to a regular file stream:
build> clisp -q -x '(describe *standard-output*)' >/tmp/foo
build> cat /tmp/foo
#<OUTPUT BUFFERED FILE-STREAM CHARACTER #P"/dev/fd/1" @1> is an output-stream.
or, on MS-Windows:
#<OUTPUT BUFFERED FILE-STREAM CHARACTER @1> is an output-stream.

Regards,
	Jorg Hohle.