Check input device is a terminal

You are encouraged to solve this task according to the task description, using any language you may know.
- Task
Demonstrate how to check whether the input device is a terminal or not.
- Related task
We use the interface to C library functions isatty() and fileno().
with Ada.Text_IO; use Ada.Text_IO;
with Interfaces.C_Streams; use Interfaces.C_Streams;
procedure Test_tty is
begin
if Isatty(Fileno(Stdin)) = 0 then
Put_Line(Standard_Error, "stdin is not a tty.");
else
Put_Line(Standard_Error, "stdin is a tty.");
end if;
end Test_tty;
- Output:
$ ./test_tty stdin is a tty. $ ./test_tty < /dev/null stdin is not a tty.
terminal = isatty(0)
PRINT terminal
- Output:
prompt$ bacon -q istty.bac Converting 'istty.bac'... done, 4 lines were processed in 0.002 seconds. Compiling 'istty.bac'... cc -c istty.bac.c cc -o istty istty.bac.o -lm Done, program 'istty' ready. prompt$ ./istty 1 prompt$ ./istty <<<"testing" 0
Open Cons For Input As #1
' Open Cons abre los flujos de entrada (stdin) o salida (stdout) estándar
' de la consola para leer o escribir.
If Err Then
Print "Input doesn't come from tt."
Else
Print "Input comes from tty."
End If
Close #1
Sleep
Source: siberia-man from dostips - https://www.dostips.com/forum/viewtopic.php?p=10672#p57997
(timeout /t 0 >nul 2>nul && echo Stdin is a terminal || echo Stdin is not a terminal) <nul
- Output:
Stdin is not a terminal
Use isatty() on file descriptor to determine if it's a TTY. To get the file descriptor from a FILE* pointer, use fileno:
#include <unistd.h> //for isatty()
#include <stdio.h> //for fileno()
int main(void)
{
puts(isatty(fileno(stdin))
? "stdin is tty"
: "stdin is not tty");
return 0;
}
- Output:
$ ./a.out stdin is tty $ ./a.out < /dev/zero stdin is not tty $ echo "" | ./a.out stdin is not tty
Works with GnuCOBOL.
*>
*> istty, check id fd 0 is a tty
*> Tectonics: cobc -xj istty.cob
*> echo "test" | ./istty
*>
identification division.
program-id. istty.
data division.
working-storage section.
01 rc usage binary-long.
procedure division.
sample-main.
call "isatty" using by value 0 returning rc
display "fd 0 tty: " rc
call "isatty" using by value 1 returning rc
display "fd 1 tty: " rc upon syserr
call "isatty" using by value 2 returning rc
display "fd 2 tty: " rc
goback.
end program istty.
DISPLAY for fd 1 is directed to SYSERR to get some output during the various trials.
- Output:
prompt$ cobc -xj istty.cob fd 0 tty: +0000000001 fd 1 tty: +0000000001 fd 2 tty: +0000000001 prompt$ echo "test" | ./istty fd 0 tty: +0000000000 fd 1 tty: +0000000001 fd 2 tty: +0000000001 prompt$ echo "test" | ./istty >/dev/null fd 1 tty: +0000000000 prompt$ echo "test" | ./istty 2>/dev/tty fd 0 tty: +0000000000 fd 1 tty: +0000000001 fd 2 tty: +0000000001 prompt$ echo "test" | ./istty 2>/dev/null fd 0 tty: +0000000000 fd 2 tty: +0000000000
(with-open-stream (s *standard-input*)
(format T "stdin is~:[ not~;~] a terminal~%"
(interactive-stream-p s)))
- Output:
$ sbcl --script rc.lisp stdin is a terminal $ sbcl --script rc.lisp < /dev/zero stdin is not a terminal $ echo "" | sbcl --script rc.lisp stdin is not a terminal
File.new("testfile").tty? #=> false
File.new("/dev/tty").tty? #=> true
STDIN.tty? #=> true
import std.stdio;
extern(C) int isatty(int);
void main() {
if (isatty(0))
writeln("Input comes from tty.");
else
writeln("Input doesn't come from tty.");
}
- Output:
C:\test Input comes from tty. C:\test < in.txt Input doesn't come from tty.
Givent that ed is a non-graphical editor that's almost exclusively run in terminal, the program only needs to highlight this fact.
# by Artyom Bologov
H
a
Input from terminal!
.
p
Q
In Gforth, the word "source-id" is used to determine the program source.
If you got a program file "source.f":
: ?tty source-id if ." not " then ." from terminal" ; ?tty bye
Then,
gforth source.f
in the shell will display:
- Output:
not from terminal
Then,
gforth -e ': ?tty source-id if ." not " then ." from terminal" ; ?tty bye'
will display:
- Output:
not from terminal
At Gforth prompt,
: ?tty source-id if ." not " then ." from terminal" ; ?tty bye
will display:
- Output:
from terminal
In Fortran, all I/O is done using logical unit numbers. Units number 5 and 6 are usually reserved for standard input and standard output. If these are not redirected to read from or write to a file, the running program reads from and writes to the console resp. the command window that started the program..
However, Fortran offers no portable, standardized way to find out if a unit is connected to a file or a terminal.
Both Intel IFX and GNU gfortran compilers have the function "isatty(unitNumber)", documented as non-standard extensions.
Other compilers on other platforms may or may not have this feature.
!
!Check input device is a terminal
! tested with Intel ifx (IFX) 2025.2.1 20250806 on Kubuntu 25.10
! GNU Fortran (Ubuntu 15.2.0-4ubuntu4) 15.2.0 on Kubuntu 25.10
!
! This is completely non-standard. It relies on the function isatty(lun)
! which is documented as compiler-specific extension to both ifx and Gnu gfortran.
!
! U.B., January 2026
!==============================================================================
program checkTTY
implicit none
integer :: unit
logical :: isatty
! expect units 5 (standard input) and 6 (standard output) to be terminals,
! unless it redirected to a file
! ./checktty will write that units 5 and 6 are Terminals,
! ./checktty <a.out will give 5 is not a terminal but 6 is
! ./checktty >b.out will write to b.out, and this contains unit 5 is a terminal but unit 6 ism't
! ./checktty < a.out >b.out will write to b.out, and both units 5 and 6 are not terminals.
!
! Check units 1...10 if they are connected to a terminal.
do unit=1,10
if (isatty (unit)) then
write (*, '("Unit ", i2, " is a Terminal")') unit
else
write (*, '("Unit ", i2, " is NOT a Terminal")') unit
endif
enddo
end program checkTTY
- Output:
Unit 1 is NOT a Terminal Unit 2 is NOT a Terminal Unit 3 is NOT a Terminal Unit 4 is NOT a Terminal Unit 5 is a Terminal Unit 6 is a Terminal Unit 7 is NOT a Terminal Unit 8 is NOT a Terminal Unit 9 is NOT a Terminal Unit 10 is NOT a Terminal
With redirected standard input:
Unit 1 is NOT a Terminal Unit 2 is NOT a Terminal Unit 3 is NOT a Terminal Unit 4 is NOT a Terminal Unit 5 is NOT a Terminal Unit 6 is a Terminal Unit 7 is NOT a Terminal Unit 8 is NOT a Terminal Unit 9 is NOT a Terminal Unit 10 is NOT a Terminal
With standard output redirected to a file:
Unit 1 is NOT a Terminal Unit 2 is NOT a Terminal Unit 3 is NOT a Terminal Unit 4 is NOT a Terminal Unit 5 is a Terminal Unit 6 is NOT a Terminal Unit 7 is NOT a Terminal Unit 8 is NOT a Terminal Unit 9 is NOT a Terminal Unit 10 is NOT a Terminal
And finally, with both standard input and output redirected:
Unit 1 is NOT a Terminal Unit 2 is NOT a Terminal Unit 3 is NOT a Terminal Unit 4 is NOT a Terminal Unit 5 is NOT a Terminal Unit 6 is NOT a Terminal Unit 7 is NOT a Terminal Unit 8 is NOT a Terminal Unit 9 is NOT a Terminal Unit 10 is NOT a Terminal
include "NSLog.incl"
BeginCCode
if (isatty(fileno(stdin)))
NSLog( @"stdin is connected to a terminal" );
else
NSLog( @"stdin is NOT connected to a terminal" );
EndC
HandleEvents- Output:
stdin is NOT connected to a terminal
package main
import (
"golang.org/x/crypto/ssh/terminal"
"fmt"
"os"
)
func main() {
if terminal.IsTerminal(int(os.Stdin.Fd())) {
fmt.Println("Hello terminal")
} else {
fmt.Println("Who are you? You're not a terminal.")
}
}
- Output:
> hello Hello terminal > hello </dev/null Who are you? You're not a terminal.
Example uses unix package:
module Main (main) where
import System.Posix.IO (stdInput)
import System.Posix.Terminal (queryTerminal)
main :: IO ()
main = do
isTTY <- queryTerminal stdInput
putStrLn $ if isTTY
then "stdin is TTY"
else "stdin is not TTY"
(if (os/isatty stdin)
(print "The input device is a terminal.")
(print "The input device is not a terminal."))
/* Check input device is a terminal, in Jsish */
;Interp.conf().subOpts.istty;
/*
=!EXPECTSTART!=
Interp.conf().subOpts.istty ==> false
=!EXPECTEND!=
*/
- Output:
prompt$ jsish Jsish interactive: see 'help [cmd]' or 'history'. \ cancels > input. ctrl-c aborts running script. jsi> Interp.conf().subOpts.istty; true jsi> prompt$ jsish --U checkInputDevice.jsi Interp.conf().subOpts.istty ==> false
if isa(STDIN, Base.TTY)
println("This program sees STDIN as a TTY.")
else
println("This program does not see STDIN as a TTY.")
end
- Output:
This program sees STDIN as a TTY.
// Kotlin Native version 0.5
import platform.posix.*
fun main(args: Array<String>) {
if (isatty(STDIN_FILENO) != 0)
println("stdin is a terminal")
else
println("stdin is not a terminal")
}
- Output:
stdin is a terminal
You can get isatty from lua posix
local posix = require"posix"
print(
posix.unistd.isatty(posix.stdio.fileno(io.stdin))
and "stdin is a terminal"
or "stdin is not a terminal"
)
There is no explicit way (ie isatty())to do this; however, if we assume that standard input is a terminal, we can check if the input stream has been redirected (presumably to something other than a terminal).
def isTerm = System.Console.IsInputRedirected;
Using function "isatty" of standard module "terminal" which accepts a File as argument.
import terminal
echo if stdin.isatty: "stdin is a terminal" else: "stdin is not a terminal"
- Output:
Command: ./check_input_dev Result: stdin is a terminal
Command: ./check_input_dev <somefile Result: stdin is not a terminal
$'stdin is a terminal: (is-terminal -i)'let () =
print_endline (
if Unix.isatty Unix.stdin
then "Input comes from tty."
else "Input doesn't come from tty."
)
Testing in interpreted mode:
$ ocaml unix.cma istty.ml Input comes from tty. $ echo "foo" | ocaml unix.cma istty.ml Input doesn't come from tty.
(define (isatty? fd) (syscall 16 fd 19))
(print (if (isatty? stdin)
"Input comes from tty."
"Input doesn't come from tty."))
##
uses system;
system.Console.IsInputRedirected.println;
- Output:
C:\PABCWork.NET\Output>checkinput.exe False C:\PABCWork.NET\Output>echo test | checkinput.exe True
use strict;
use warnings;
use 5.010;
if (-t) {
say "Input comes from tty.";
}
else {
say "Input doesn't come from tty.";
}
$ perl istty.pl Input comes from tty. $ true | perl istty.pl Input doesn't come from tty.
without js -- (no input redirection in a browser!)
printf(1,"stdin:%t, stdout:%t, stderr:%t\n",{isatty(0),isatty(1),isatty(2)})
- Output:
C:\Program Files (x86)\Phix>p test stdin:true, stdout:true, stderr:true C:\Program Files (x86)\Phix>echo hello | p test stdin:false, stdout:true, stderr:true
void main()
{
if(Stdio.Terminfo.is_tty())
write("Input comes from tty.\n");
else
write("Input doesn't come from tty.\n");
}
- Output:
$ ./istty.pike Input comes from tty. $ echo | ./istty.pike Input doesn't come from tty.
Works with Bash shell on Linux but can't vouch for anything else.
os.execute("test -t 0 ; echo $? > tmp")
os.sleep(1)
local res = io.contents("tmp"):rstrip()
print($"Input device is a terminal? {res == "0"}")
os.remove("tmp")
- Output:
Input device is a terminal? true
Alternatively, for POSIX systems only:
local ffi = require "pluto:ffi"
local lib = ffi.open("libc.so.6")
lib:cdef[[ int isatty(int fd); ]]
local res = lib.isatty(0)
print($"Input device is a terminal? {res == 1}")
- Output:
Same as before.
from sys import stdin
if stdin.isatty():
print("Input comes from tty.")
else:
print("Input doesn't come from tty.")
$ python istty.py Input comes from tty. $ true | python istty.py Input doesn't come from tty.
[ $ |from sys import stdin
to_stack( 1 if stdin.isatty() else 0)|
python ] is ttyin ( --> b )
ttyin if
[ say "Looks like a teletype." ]
else
[ say "Not a teletype." ]- Output:
Looks like a teletype.
(terminal-port? (current-input-port))
(formerly Perl 6)
say $*IN.t ?? "Input comes from tty." !! "Input doesn't come from tty.";
$ raku istty.raku Input comes from tty. $ true | raku istty.raku Input doesn't come from tty.
So far this detection is not available. User input is not expected, when Rebol is started with `--cgi` flag, which may be detected in a script like:
either system/options/flags/cgi [
print "CGI mode - no terminal"
;; get input data
probe data: read system/ports/input
][ print "not CGI mode" ]
Since version 3.21.13 one can use `tty?` function.
/*REXX program determines if input comes from terminal or standard input*/
if queued() then say 'input comes from the terminal.'
else say 'input comes from the (stacked) terminal queue.'
/*stick a fork in it, we're done.*/
# Project : Check input device is a terminal
load "stdlib.ring"
if isWindows()
write("mycmd.bat","
@echo off
timeout 1 2>nul >nul
if errorlevel 1 (
echo input redirected
) else (
echo input is console
)
")
see SystemCmd("mycmd.bat")
okOutput:
input redirected
Example from the docs.
File.new("testfile").isatty #=> false
File.new("/dev/tty").isatty #=> true
/* Uses C library interface */
extern crate libc;
fn main() {
let istty = unsafe { libc::isatty(libc::STDIN_FILENO as i32) } != 0;
if istty {
println!("stdout is tty");
} else {
println!("stdout is not tty");
}
}
import org.fusesource.jansi.internal.CLibrary._
object IsATty extends App {
var enabled = true
def apply(enabled: Boolean): Boolean = {
// We must be on some unix variant..
try {
enabled && isatty(STDIN_FILENO) == 1
}
catch {
case ignore: Throwable =>
ignore.printStackTrace()
false
}
}
println("tty " + apply(true))
}
val stdinRefersToTerminal : bool = Posix.ProcEnv.isatty Posix.FileSys.stdin
Tcl automatically detects whether stdin is coming from a terminal (or a socket) and sets up the channel to have the correct type. One of the configuration options of a terminal channel is -mode (used to configure baud rates on a real serial terminal) so we simply detect whether the option is present.
if {[catch {fconfigure stdin -mode}]} {
puts "Input doesn't come from tty."
} else {
puts "Input comes from tty."
}
Demonstrating:
$ tclsh8.5 istty.tcl Input comes from tty. $ tclsh8.5 istty.tcl </dev/null Input doesn't come from tty.
#!/bin/sh
if [ -t 0 ]
then echo "Input is a terminal"
else echo "Input is NOT a terminal"
fi
import "io" for Stdin
System.print("Input device is a terminal? %(Stdin.isTerminal ? "Yes" : "No")")
- Output:
Input device is a terminal? Yes
POSIX only.
import "unistd.h"
fn main() {
let res = isatty(fileno(stdin)) ? "true" : "false";
println "Input device is a terminal? {res}";
}
- Output:
Input device is a terminal? true
On Unix, check to see if stdin's st_mode is a character device.
const S_IFCHR=0x2000;
fcn S_ISCHR(f){ f.info()[4].bitAnd(S_IFCHR).toBool() }
S_ISCHR(File.stdin).println();- Output:
$ zkl bbb # from the command line True $ zkl bbb < bbb.zkl False $ cat bbb.zkl | zkl bbb False
- Terminal control
- Hardware
- Initialization
- Programming Tasks
- Solutions by Programming Task
- Ada
- BASIC
- BaCon
- FreeBASIC
- Batch File
- C
- COBOL
- Common Lisp
- Crystal
- D
- Ed
- Forth
- Fortran
- FutureBasic
- Go
- Go sub-repositories
- Haskell
- Janet
- Jsish
- Julia
- Kotlin
- Lua
- Nemerle
- Nim
- Nu
- OCaml
- Ol
- PascalABC.NET
- Perl
- Phix
- Pike
- Pluto
- Python
- Quackery
- Racket
- Raku
- Rebol
- REXX
- Ring
- Ruby
- Rust
- Scala
- Standard ML
- Tcl
- UNIX Shell
- Wren
- Zen C
- Zkl
- Clojure/Omit
- GUISS/Omit
- Java/Omit
- Processing/Omit
- TI-83 BASIC/Omit
- ZX Spectrum Basic/Omit