Shell Redirection

Project:JNode Core
Component:Code
Category:feature request
Priority:minor
Assigned:Unassigned
Status:active
Description

On IRC Josh Stratton asked some questions about the shell. He wanted to know if a command can check if it is reading or writing from/to a pipe, file or stdin/stdout. He brought up one interessting example, the linux command ls.

If you type "ls" you get multiple files per line but if you type "ls|grep ." you get one file per line. The code of ls indeed checks if it's writing to a tty or not.
I think we can agree that this is no good practice and that you could also type "ls -1" if you want one file per line. I also think it would be bad to do stuff like that in JNode. But in case we want to directly execute bash-scripts this is a problem and there might be further linux-commands that "behave strange" in that regard.

Stephen, what do you think about that?

Getting terminal width and height

peda recommended I post that I wanted to know the width and height of a given terminal in characters. He recommended using:

  • TextConsole tc = (TextConsole) shell.getConsole();
  • tc.getWidth/getHeight();

He also recommended posting this so Crawley would know I plan to use this functionality.

Possible issues with what you are suggesting

Thank you for letting me know. We do indeed need a standard pattern for getting the console dimensions for an application to use, and your approach looks reasonable.

AFAIK, it should work for now, though there may be issues in the future. For a start, it means that we would need to figure out how to implement TextConsole for terminals / terminal emulators.

There is also the issue of how to get the TextConsole when an application doesn't know its shell. ShellUtils.getCurrentShell() is not the answer! A robust mechanism for getting the underlying TextConsole from a "tty" stream is needed.

#1

I think this is a good question.

First, let us be clear that UNIX applications are not testing whether the stream has been redirected. Rather they are testing whether it "is a tty". IIRC, there is a C library function for this, and there will be an underlying syscall or syscalls that allow it to find this out.

We currently don't have a standard way to make an "is a tty" test, and we don't have syscalls to make this determination. Instead, a JNode application has just got Java *Stream (or Reader/Writer) objects to look at. And there are wrappers and proxies in the way. (At a minimum, a Command.exeute method will see any OutputStream wrapped as a PrintStream ... and the standard PrintStream API does not allow you to find out the wrapped OutputStream.)

I can think of three approaches:

  1. Create a Helper class that makes use of reflection, etc to expose the internals of the stream classes and figure out if a given stream is a "tty" stream.
  2. Rejig the Command.execute method so that in/out/err use interface types. (Reader/Writer is one option, but that means the command only gets stream-of-char. Another would be to invent our own stream-of-byte interfaces modeled on *Stream, but done better.) Then we add an interface that exposes a method to test for "tty-ness".
  3. Extend the Command API with methods for asking if the in/out/err streams are "tty", and implement them by having the shell, etc remember how the streams were set up.

Note that whichever way we implement this, we need to be able to cope with "tty" streams that come from physical TTY ports or remote network connections and possibly even from input scripting systems.