Check input device is a terminal

From Rosetta Code
Check input device is a terminal is a draft programming task. It is not yet considered ready to be promoted as a complete task, for reasons that should be found in its talk page.
Task

Demonstrate how to check whether the input device is a terminal or not.


Related task



Ada

Works with: GNAT

We use the interface to C library functions isatty() and fileno().

<lang ada>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;</lang>

Output:
$ ./test_tty 
stdin is a tty.
$ ./test_tty < /dev/null
stdin is not a tty.

BaCon

<lang freebasic>terminal = isatty(0) PRINT terminal</lang>

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

C

Use isatty() on file descriptor to determine if it's a TTY. To get the file descriptor from a FILE* pointer, use fileno: <lang c>#include <unistd.h> //for isatty()

  1. include <stdio.h> //for fileno()

int main(void) { puts(isatty(fileno(stdin)) ? "stdin is tty" : "stdin is not tty"); return 0; }</lang>

Output:
$ ./a.out
stdin is tty
$ ./a.out < /dev/zero
stdin is not tty
$ echo "" | ./a.out
stdin is not tty

COBOL

Works with GnuCOBOL.

<lang cobol> *>

     *> 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.</lang>

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

Common Lisp

Works with: SBCL

<lang lisp>(with-open-stream (s *standard-input*)

 (format T "stdin is~:[ not~;~] a terminal~%" 
         (interactive-stream-p s)))</lang>
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

Crystal

<lang ruby>File.new("testfile").tty? #=> false File.new("/dev/tty").tty? #=> true STDIN.tty? #=> true</lang>

D

<lang d>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.");

}</lang>

Output:
C:\test
Input comes from tty.
C:\test < in.txt
Input doesn't come from tty.

Go

<lang go>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.")
   }

}</lang>

Output:
> hello
Hello terminal
> hello </dev/null
Who are you?  You're not a terminal.

Haskell

Example uses unix package:

<lang haskell>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"</lang>

Jsish

<lang javascript>/* Check input device is a terminal, in Jsish */

Interp.conf().subOpts.istty;

/*

!EXPECTSTART!

Interp.conf().subOpts.istty ==> false

!EXPECTEND!

  • /</lang>
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

Julia

<lang Julia> 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 </lang>

Output:
This program sees STDIN as a TTY.

Kotlin

Works with: Ubuntu version 14.04

<lang scala>// 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") 

} </lang>

Output:
stdin is a terminal

Nemerle

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). <lang Nemerle>def isTerm = System.Console.IsInputRedirected;</lang>

OCaml

<lang ocaml>let () =

 print_endline (
   if Unix.isatty Unix.stdin
   then "Input comes from tty."
   else "Input doesn't come from tty."
 )</lang>

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.

Perl

<lang perl>use strict; use warnings; use 5.010; if (-t) {

   say "Input comes from tty.";

} else {

   say "Input doesn't come from tty.";

}</lang>

$ perl istty.pl
Input comes from tty.
$ true | perl istty.pl
Input doesn't come from tty.

Phix

Requires 0.8.2+ <lang Phix>printf(1,"stdin:%t, stdout:%t, stderr:%t\n",{isatty(0),isatty(1),isatty(2)})</lang>

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

Pike

<lang pike>void main() {

   if(Stdio.Terminfo.is_tty())

write("Input comes from tty.\n");

   else
       write("Input doesn't come from tty.\n");

}</lang>

Output:
$ ./istty.pike
Input comes from tty.
$ echo | ./istty.pike
Input doesn't come from tty.

Python

<lang python>from sys import stdin if stdin.isatty():

   print("Input comes from tty.")

else:

   print("Input doesn't come from tty.")</lang>
$ python istty.py
Input comes from tty.
$ true | python istty.py
Input doesn't come from tty.

Racket

<lang racket> (terminal-port? (current-input-port)) </lang>

Raku

(formerly Perl 6)

Works with: Rakudo version 2015.12

<lang perl6>say $*IN.t ?? "Input comes from tty." !! "Input doesn't come from tty.";</lang>

$ raku istty.raku
Input comes from tty.
$ true | raku istty.raku
Input doesn't come from tty.

REXX

<lang rexx>/*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.*/

</lang>

Ring

<lang ring>

  1. 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")

ok </lang> Output:

input redirected

Ruby

Example from the docs. <lang ruby>File.new("testfile").isatty #=> false File.new("/dev/tty").isatty #=> true</lang>

Rust

<lang rust>/* 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");
   }

}</lang>

Scala

Works with: Ubuntu version 14.04

<lang scala>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))

}</lang>

Tcl

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. <lang tcl>if {[catch {fconfigure stdin -mode}]} {

   puts "Input doesn't come from tty."

} else {

   puts "Input comes from tty."

}</lang> Demonstrating:

$ tclsh8.5 istty.tcl 
Input comes from tty.
$ tclsh8.5 istty.tcl </dev/null
Input doesn't come from tty.

UNIX Shell

<lang sh>#!/bin/sh

if [ -t 0 ] then

  echo "Input is a terminal"

else

  echo "Input is NOT a terminal"

fi</lang>

Wren

<lang ecmascript>import "io" for Stdin

System.print("Input device is a terminal? %(Stdin.isTerminal ? "Yes" : "No")")</lang>

Output:
Input device is a terminal? Yes

zkl

On Unix, check to see if stdin's st_mode is a character device. <lang zkl>const S_IFCHR=0x2000; fcn S_ISCHR(f){ f.info()[4].bitAnd(S_IFCHR).toBool() } S_ISCHR(File.stdin).println();</lang>

Output:
$ zkl bbb  # from the command line
True
$ zkl bbb < bbb.zkl
False
$ cat bbb.zkl | zkl bbb
False