[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

if STREAM.isatty():

On 8/29/19, Terry Reedy <tjreedy at udel.edu> wrote:
> On 8/29/2019 10:16 AM, Eryk Sun wrote:
>> In Windows, isatty() is true for any character-type file.
> Does that mean one that can either send or receive data a character at a
> time, as opposed to a block at a time?

Yes, any number of bytes can be written to a character device, whereas
a block device will require some fixed number of bytes such as a
512-byte disk sector.

WINAPI GetFileType classifies files for all of the following NT device
types as FILE_TYPE_CHAR (akin to Unix S_IFCHR):


FILE_DEVICE_CONSOLE is for the ConDrv console device, which was added
in Windows 8. In previous versions, GetFileType special cases console

GetFileType classifies files for all of the following NT device types
as FILE_TYPE_DISK (akin to Unix S_IFBLK):


> Aha.  So this is why
> https://pubs.opengroup.org/onlinepubs/009695399/functions/isatty.html
> follows the doc for isatty, which says 'associated with a terminal
> device', with an information section that contradicts that with
> "The isatty() function does not necessarily indicate that a human being
> is available for interaction via fildes. It is quite possible that
> non-terminal devices are connected to the communications line."

As far as I know, only the Windows CRT classifies any character device
as a TTY. Linux doesn't. "/dev/null" is a character device, but not a

I think the CRT's _isatty implementation is wrong, though I'm not
certain what the right answer looks like. Windows doesn't have any
notion of a tty/pty terminal. I suppose it can just check for a
console. For older versions of Windows that would be based on checking
for a console pseudohandle. In Windows 8+, we can query
NtQueryVolumeInformationFile: FileFsDeviceInformation to check for
FILE_DEVICE_CONSOLE. (It would be useful if they exposed this in the
Windows API, maybe as GetVolumeInformationByHandleEx, like what they
did for GetFileInformationByHandleEx.)

> What makes a pipe on Windows not a character file?  Is data sent between
> processes a block at a time?  Are posix pipes different?

FILE_TYPE_PIPE (akin to Unix S_IFIFO) is a type that accesses a
section of shared memory that's used as an inter-process communication
channel. Requesting a read on an empty pipe blocks until at least one
byte is available. Requesting a write on a pipe blocks until there's
available space for the write to complete, which may require multiple
reads at the other end. (Note that Windows also classifies sockets as
'pipes', but Unix has a dedicated S_IFSOCK type for sockets.)

A pipe channel can be inbound (client-write, server-read), outbound
(server-write, client-read), or duplex (read-write on both ends).
Anonymous pipes are in duplex mode but they're opened with access on
each end that makes them effectively inbound mode. Windows also
supports message-mode pipes, which handles each write as a message. A
message-mode pipe can be configured to be read in either byte mode or
message mode. (Pipes in most Unix systems do not support duplex and
message modes.)

In principle, a pipe can be used as the IPC channel for an interactive
terminal. For example, MSYS2 does this with specially named pipes that
its isatty() function special cases as a TTYs. But in general we
expect pipes to be non-interactive, and for performance we default to
full buffering with pipes instead of line buffering. Full buffering is
incompatible with interactive usage.

> I don't understand the following.
> ---
> C:\Users\Terry>python -c "print('hello\n') | python
> hello
> Traceback (most recent call last):
>    File "<string>", line 1, in <module>
> NameError: name 'python' is not defined

The command line is missing the closing double quote around
"print('hello\n')". In this case, CMD acts as if the whole statement
is quoted, so the vertical bar is not interpreted as a pipe to a
`python` command. Let's print the command line for the python.exe
process in order to demonstrate this:

    C:\>python -c "import win32api;print(win32api.GetCommandLine()) | python
    python  -c "import win32api;print(win32api.GetCommandLine()) | python
    Traceback (most recent call last):
      File "<string>", line 1, in <module>
    NameError: name 'python' is not defined