Check output device is a terminal: Difference between revisions

(→‎{{header|Julia}}: A new entry for Julia)
imported>Regattaguru
 
(44 intermediate revisions by 25 users not shown)
Line 1:
{{draft task}} [[Category:Hardware]] [[Category:Terminal control]] [[Category:Initialization]]
[[Category:Terminal control]]
[[Category:Initialization]]
{{task}}
 
;Task:
The task is to demonstrate how to check whether the output device is a terminal or not.
Demonstrate how to check whether the output device is a terminal or not.
 
See also: [[Check input device is a terminal]]
 
;Related task:
*   [[Check input device is a terminal]]
<br><br>
=={{header|6502 Assembly}}==
{{works with|Commodore 64}}
<syntaxhighlight lang="6502asm">LDA $D011 ;screen control register 1
AND #%00100000 ;bit 5 clear = text mode, bit 5 set = gfx mode
BEQ isTerminal</syntaxhighlight>
=={{header|Ada}}==
{{works with|GNAT}}
We use the interface to C library functions <code>isatty()</code> and <code>fileno()</code>.
 
<langsyntaxhighlight lang="ada">with Ada.Text_IO; use Ada.Text_IO;
with Interfaces.C_Streams; use Interfaces.C_Streams;
 
Line 19 ⟶ 32:
Put_Line(Standard_Error, "stdout is a tty.");
end if;
end Test_tty;</langsyntaxhighlight>
 
{{out}}
Line 33 ⟶ 46:
Use <code>isatty()</code> on file descriptor to determine if it's a TTY. To get the file descriptor from a <code>FILE*</code> pointer, use <code>fileno</code>:
 
<langsyntaxhighlight lang="c">#include <unistd.h> // for isatty()
#include <stdio.h> // for fileno()
 
Line 42 ⟶ 55:
: "stdout is not tty");
return 0;
}</langsyntaxhighlight>
 
{{out}}
Line 57 ⟶ 70:
stdout is not tty
</pre>
=={{header|C sharp|C#}}==
<syntaxhighlight lang="csharp">using System;
 
namespace CheckTerminal {
class Program {
static void Main(string[] args) {
Console.WriteLine("Stdout is tty: {0}", Console.IsOutputRedirected);
}
}
}</syntaxhighlight>
=={{header|C++}}==
{{trans|C}}
<syntaxhighlight lang="cpp">#if _WIN32
#include <io.h>
#define ISATTY _isatty
#define FILENO _fileno
#else
#include <unistd.h>
#define ISATTY isatty
#define FILENO fileno
#endif
 
#include <iostream>
 
int main() {
if (ISATTY(FILENO(stdout))) {
std::cout << "stdout is a tty\n";
} else {
std::cout << "stdout is not a tty\n";
}
 
return 0;
}</syntaxhighlight>
=={{header|COBOL}}==
Works with GnuCOBOL.
 
<syntaxhighlight 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.</syntaxhighlight>
 
DISPLAY for fd 1 is directed to SYSERR to get some output during the various trials.
 
{{out}}
<pre>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</pre>
=={{header|Common Lisp}}==
{{Works with|SBCL}}
<langsyntaxhighlight lang="lisp">(with-open-stream (s *standard-output*)
(format T "stdout is~:[ not~;~] a terminal~%"
(interactive-stream-p s)))</langsyntaxhighlight>
 
{{Out}}
Line 73 ⟶ 168:
stdout is not a terminal</pre>
 
{{Works with|ECL}}
We use the interface to C library functions <code>isatty()</code> and <code>fileno()</code>. It needs to be compiled to be executed.
 
<syntaxhighlight lang="lisp">(ffi:clines "
#include <sys/ioctl.h>
#include <unistd.h>
int ttyPredicate() {
return isatty(fileno(stdout));
}")
 
(ffi:def-function
("ttyPredicate" c-ttyp)
() :returning :int)
 
(defun tty-p()
(if (= 1 (c-ttyp))
t
nil))
 
(format T "stdout is~:[ not~;~] a terminal~%" (tty-p))
(quit)</syntaxhighlight>
 
Compilation can be done with the following commands :
 
<code>ecl --eval '(compile-file "file.lisp" :system-p t)' --eval '(quit)'</code>
 
<code>ecl --eval '(c:build-program "is-tty" :lisp-files (list "file.o"))' --eval '(quit)'</code>
 
{{Out}}
<pre>$ ./is-tty
stdout is a terminal
$ ./is-tty | cat -
stdout is not a terminal</pre>
=={{header|Crystal}}==
<langsyntaxhighlight lang="ruby">File.new("testfile").tty? #=> false
File.new("/dev/tty").tty? #=> true
STDOUT.tty? #=> true</langsyntaxhighlight>
=={{header|D}}==
<syntaxhighlight lang="d">import std.stdio;
 
extern(C) int isatty(int);
 
void main() {
writeln("Stdout is tty: ", stdout.fileno.isatty == 1);
}</syntaxhighlight>
 
{{out}}
<pre>
prompt>a.out
Stdout is tty: true
prompt>a.out > out.txt
Stdout is tty: false
</pre>
=={{header|Factor}}==
You have to know 1 is the correct file descriptor number:
<langsyntaxhighlight lang="factor">
IN: scratchpad USE: unix.ffi
IN: scratchpad 1 isatty
Line 86 ⟶ 229:
--- Data stack:
1
</syntaxhighlight>
</lang>
=={{header|FreeBASIC}}==
 
<syntaxhighlight lang="freebasic">
Open Cons For Output As #1
' Open Cons abre los flujos de entrada (stdin) o salida (stdout) estándar
' de la consola para leer o escribir.
 
If Err > 0 Then
Print #1, "stdout is not a tty."
Else
Print #1, "stdout is a tty."
End If
Close #1
Sleep
</syntaxhighlight>
=={{header|Go}}==
Tells a ''terminal'' apart from a ''pipe'' on Linux and Mac, which is probably exactly what you need.
{{libheader|Go sub-repositories}}
 
<lang go>package main
<syntaxhighlight lang="go">package main
 
import (
"os"
"fmt"
"golang.org/x/crypto/ssh/terminal"
)
 
func main() {
if terminal.IsTerminal(int(fileInfo, _ := os.Stdout.FdStat(); (fileInfo.Mode() & os.ModeCharDevice) != 0 {
fmt.Println("Hello terminal")
} else {
fmt.Println("Who are you? You're not a terminal.")
}
}</langsyntaxhighlight>
{{out}}
<pre>
Line 111 ⟶ 266:
Hello terminal
> hello | cat
Who are you? You're not a terminal.
</pre>
=={{header|Haskell}}==
 
<syntaxhighlight lang="haskell">module Main where
=={{header|Javascript/NodeJS}}==
<lang js>node -p -e "Boolean(process.stdout.isTTY)"
true</lang>
 
-- requires the unix package
-- https://hackage.haskell.org/package/unix
import System.Posix.Terminal (queryTerminal)
import System.Posix.IO (stdOutput)
 
main :: IO ()
main = do
istty <- queryTerminal stdOutput
putStrLn
(if istty
then "stdout is tty"
else "stdout is not tty")</syntaxhighlight>
{{Out}}
<pre>$ runhaskell istty.hs
stdout is tty
$ runhaskell istty.hs | cat
stdout is not tty
</pre>
=={{header|J}}==
 
<syntaxhighlight lang="j">3=nc<'wd'</syntaxhighlight>
 
Explanation:
 
J does not have a concept of an "output device", so we approximate that by seeing whether we have bothered to define a the code which typically does graphical output.
 
The use of the phrase "output device" suggests that we are thinking about something like the unix `isatty` command. Here, stdout might be a file or might be a terminal. But in J we are often hosting our own user interaction environment. It's not uncommon for a J user to be on a web page where hitting enter sends a form request to a J interpreter which in turn composes an updated html presentation of current state which it sends to the browser. Or, the J user might be talking to a Java program which similarly wraps the J session (though this is older technology at this point). Or, the J user might be interacting with Qt. Or, sure, we might be talking to a tty and J might be sending its output straight to the tty. (But we can't know if that tty is hosted in emacs, running under control of a script on a remote machine via ssh, talking directly to a human user who happens to be in direct control of the session, or whatever else...)
 
The point being that in the general case the J programmer cannot know whether the concept of "terminal" has any relevance to the user.
 
But, like everyone else, we can certainly use heuristics.
 
But, correctness requires us to keep in mind that these will only be heuristics, and will sometimes be incorrect (hopefully not often enough to matter a lot...).
=={{header|Javascript/NodeJS}}==
<syntaxhighlight lang="js">node -p -e "Boolean(process.stdout.isTTY)"
true</syntaxhighlight>
=={{header|Julia}}==
<syntaxhighlight lang="julia">
<lang Julia>
if isa(STDOUT, Base.TTY)
println("This program sees STDOUT as a TTY.")
Line 125 ⟶ 315:
println("This program does not see STDOUT as a TTY.")
end
</syntaxhighlight>
</lang>
 
{{out}}
Line 131 ⟶ 321:
This program sees STDOUT as a TTY.
</pre>
=={{header|Kotlin}}==
{{Works with|Ubuntu|14.04}}
<syntaxhighlight lang="scala">// Kotlin Native version 0.5
 
import platform.posix.*
 
fun main(args: Array<String>) {
if (isatty(STDOUT_FILENO) != 0)
println("stdout is a terminal")
else
println("stdout is not a terminal")
}</syntaxhighlight>
 
{{out}}
<pre>
stdout is a terminal
</pre>
=={{header|Lua}}==
{{works with|Lua|5.1+}}
Using pure Lua, assuming a *NIX-like runtime environment ...
<syntaxhighlight lang="lua">local function isTTY ( fd )
fd = tonumber( fd ) or 1
local ok, exit, signal = os.execute( string.format( "test -t %d", fd ) )
return (ok and exit == "exit") and signal == 0 or false
end
 
print( "stdin", isTTY( 0 ) )
print( "stdout", isTTY( 1 ) )
print( "stderr", isTTY( 2 ) )</syntaxhighlight>
 
{{out}}
<pre>
$ lua istty.lua
stdin true
stdout true
stderr true
$ cat /dev/null | lua istty.lua
stdin false
stdout true
stderr true
$ lua istty.lua | tee
stdin true
stdout false
stderr true
$ lua istty.lua 2>&1 | tee
stdin true
stdout false
stderr false
</pre>
 
{{works with|Lua|5.1+}}
{{libheader|posix}}
 
You can accomplish the same results using the luaposix [https://github.com/luaposix/luaposix] library:
<syntaxhighlight lang="lua">local unistd = require( "posix.unistd" )
 
local function isTTY ( fd )
fd = tonumber( fd ) or 1
local ok, err, errno = unistd.isatty( fd )
return ok and true or false
end
 
print( "stdin", isTTY( 0 ) )
print( "stdout", isTTY( 1 ) )
print( "stderr", isTTY( 2 ) )</syntaxhighlight>
 
The output of this version is identical to the output of the first version.
=={{header|Nemerle}}==
There is no explicit way (ie <tt>isatty()</tt>)to do this; however, if we ''assume'' that standard out ''is'' a terminal, we can check if the output stream has been redirected (presumably to something other than a terminal).
<langsyntaxhighlight Nemerlelang="nemerle">def isTerm = System.Console.IsOutputRedirected;</langsyntaxhighlight>
=={{header|Nim}}==
Using function "isatty" of standard module "terminal" which accepts a File as argument.
As we want to redirect stdout, we write the messages on stderr.
 
<syntaxhighlight lang="nim">import terminal
 
stderr.write if stdout.isatty: "stdout is a terminal\n" else: "stdout is not a terminal\n"</syntaxhighlight>
 
{{out}}
<pre>Command: ./check_output_dev
Result: stdout is a terminal</pre>
 
<pre>Command: ./check_output_dev >somefile
Result: stdout is not a terminal</pre>
=={{header|OCaml}}==
 
<langsyntaxhighlight lang="ocaml">let () =
print_endline (
if Unix.isatty Unix.stdout
then "Output goes to tty."
else "Output doesn't go to tty."
)</langsyntaxhighlight>
 
Testing in interpreted mode:
Line 157 ⟶ 426:
Output doesn't go to tty.
</pre>
=={{header|Ol}}==
 
<syntaxhighlight lang="scheme">
(define (isatty? fd) (syscall 16 fd 19))
(print (if (isatty? stdout)
"stdout is a tty."
"stdout is not a tty."))
</syntaxhighlight>
=={{header|Perl}}==
The -t function on a filehandle tells you whether it's a terminal.
 
<langsyntaxhighlight lang="bash">$ perl -e "warn -t STDOUT ? 'Terminal' : 'Other'"
Terminal
$ perl -e "warn -t STDOUT ? 'Terminal' : 'Other'" > x.tmp
Other
</syntaxhighlight>
</lang>
=={{header|Phix}}==
<!--<syntaxhighlight lang="phix">(notonline)-->
<span style="color: #008080;">without</span> <span style="color: #008080;">js</span> <span style="color: #000080;font-style:italic;">-- (no input or output redirection in a browser!)</span>
<span style="color: #7060A8;">printf</span><span style="color: #0000FF;">(</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"stdin:%t, stdout:%t, stderr:%t\n"</span><span style="color: #0000FF;">,{</span><span style="color: #000000;">isatty</span><span style="color: #0000FF;">(</span><span style="color: #000000;">0</span><span style="color: #0000FF;">),</span><span style="color: #000000;">isatty</span><span style="color: #0000FF;">(</span><span style="color: #000000;">1</span><span style="color: #0000FF;">),</span><span style="color: #000000;">isatty</span><span style="color: #0000FF;">(</span><span style="color: #000000;">2</span><span style="color: #0000FF;">)})</span>
<!--</syntaxhighlight>-->
{{out}}
<pre>
C:\Program Files (x86)\Phix>p test
stdin:true, stdout:true, stderr:true
 
C:\Program Files (x86)\Phix>p test > test.txt; type test.txt
=={{header|Perl 6}}==
stdin:true, stdout:false, stderr:true
The .t method on a filehandle tells you whether it's going to the terminal. Here we use the note function to emit our result to standard error rather than standard out.
<pre>$ perl6 -e 'note $*OUT.t'
True
$ perl6 -e 'note $*OUT.t' >/dev/null
False</pre>
 
C:\Program Files (x86)\Phix>p test 2> test.txt
stdin:true, stdout:true, stderr:false
 
C:\Program Files (x86)\Phix>type test.txt | p test
stdin:false, stdout:true, stderr:true
</pre>
=={{header|PHP}}==
<syntaxhighlight lang="php">
if(posix_isatty(STDOUT)) {
echo "The output device is a terminal".PHP_EOL;
} else {
echo "The output device is NOT a terminal".PHP_EOL;
}
</syntaxhighlight>
=={{header|Python}}==
Pretty much the same as [[Check input device is a terminal#Python]].
<syntaxhighlight lang="python">from sys import stdout
if stdout.isatty():
print 'The output device is a teletype. Or something like a teletype.'
else:
print 'The output device isn\'t like a teletype.'</syntaxhighlight>
=={{header|Quackery}}==
 
{{trans|Python}}
 
<syntaxhighlight lang="quackery"> [ $ |from sys import stdout
to_stack( 1 if stdout.isatty() else 0)|
python ] is ttyout ( --> b )
 
ttyout if
[ say "Looks like a teletype." ]
else
[ say "Not a teletype." ]</syntaxhighlight>
 
{{out}}
 
<pre>Looks like a teletype.</pre>
=={{header|Racket}}==
<langsyntaxhighlight lang="racket">
(terminal-port? (current-output-port))
</syntaxhighlight>
</lang>
=={{header|Raku}}==
(formerly Perl 6)
{{works with|Rakudo|2015.12}}
The .t method on a filehandle tells you whether it's going to the terminal. Here we use the note function to emit our result to standard error rather than standard out.
<pre>$ raku -e 'note $*OUT.t'
True
$ raku -e 'note $*OUT.t' >/dev/null
False</pre>
=={{header|REXX}}==
{{works with|PC/REXX under DOS or in a DOS window under MS Windows}}
{{works with|Personal REXX under DOS or in a DOS window under MS Windows}}
{{works with|Regina in a DOS window under MS Windows}}
 
 
Programming note: &nbsp; The comment about the REXX statements have to be on one line isn't quite true,
<br>but because the REXX special variable '''SIGL''' is defined where it's executed, it makes coding simpler.
 
<br><br>'''SIGL''' &nbsp; is set to the REXX statment number where:
 
'''SIGL''' &nbsp; is set to the REXX statement number where:
:::* &nbsp; a '''CALL''' statement is used
:::* &nbsp; a ''function'' is invoked
:::* &nbsp; a '''SIGNAL''' statement is used
 
Method used: &nbsp; since REXX has no direct way of determining if the STDIN is a terminal or not, the REXX code (below)
<br>actually &nbsp; ''raises'' &nbsp; (which is no way to run a railroad) &nbsp; a syntax error when attempting to read the 2<sup>nd</sup> line from &nbsp; STDIN,
<br>which causes a routine &nbsp; (named '''syntax:''') &nbsp; to get control, &nbsp; determines where the syntax error occurred, &nbsp; and returns an
<br>an appropriate string indicating if STDIN is a '''terminal''' &nbsp; (or '''other''').
<br><br>Note that under VM/CMS, this can be accomplished with a (host) command within REXX and then examining the results.
<br>On IBM mainframes, a user can have STDIN defined, but the terminal can be ''disconnected''.
<lang rexx>/*REXX program determines if the STDIN is a terminal or other. */
signal on syntax /*if syntax error, jump──► SYNTAX*/
say 'output device:' testSTDIN() /*displays terminal ──or── other */
exit /*stick a fork in it, we're done.*/
/*──────────────────────────────────TESTSTDIN subroutine────────────────*/
testSTDIN: syntax.=1; signal .; .: z.=sigl; call linein ,2; ..: syntax.=0
return z.. /* [↑] must all be on one line.*/
/*──────────────────────────────────SYNTAX subroutine───────────────────*/
syntax: z..='other' /*when SYNTAX occur, come here. */
if syntax. then do /*handling STDIN thingy error? */
if sigl==z. then z..='terminal'; signal .. /*stdin ?*/
end /* [↑] can't use a RETURN here.*/
 
<syntaxhighlight lang="rexx">/*REXX program determines if the STDIN is a terminal device or other. */
/* ··· handle other REXX syntax errors here ··· */</lang>
signal on syntax /*if syntax error, then jump ──► SYNTAX*/
'''output'''
say 'output device:' testSTDIN() /*displays terminal ──or── other */
exit 0 /*stick a fork in it, we're all done. */
/*──────────────────────────────────────────────────────────────────────────────────────*/
testSTDIN: syntax.=1; signal .; .: z.= sigl; call linein ,2; ..: syntax.= 0; return z..
/* [↑] must/should be all on one line.*/
/*──────────────────────────────────────────────────────────────────────────────────────*/
syntax: z..= 'other' /*when a SYNTAX error occurs, come here*/
if syntax. then do /*are we handling STDIN thingy error?*/
if sigl==z. then z..= 'terminal'; signal .. /*is this a stdin ?*/
end /* [↑] can't use a RETURN here. */
 
/* ··· handle other REXX syntax errors here ··· */</syntaxhighlight>
{{out|output|text=&nbsp; when using the default input:}}
<pre>
output device: terminal
</pre>
 
 
 
 
{{works with|R4 REXX under DOS or in a DOS window under MS Windows}}
 
 
The following is the output when used with '''R4''' REXX:
 
{{out|output|text=&nbsp; when using the default input:}}
<pre>
Reading console input (Press Ctrl-Z to quit):
◄■■■■■■■■ user input (pressed ENTER)
◄■■■■■■■■ user input (pressed ENTER a 2nd time)
output device: 6
</pre>
=={{header|Ruby}}==
<langsyntaxhighlight lang="rust">f = File.open("test.txt")
p f.isatty # => false
p STDOUT.isatty # => true
</syntaxhighlight>
</lang>
=={{header|Rust}}==
<syntaxhighlight lang ="rust">/* Rust 0.9 version. Uses C library interface */
 
extern mod std;
useextern crate std::libc;
 
fn main() {
let istty = unsafe { libc::isatty(libc::STDOUT_FILENO as i32) } != 0;
if (istty) {
println!("stdout is tty");
} else {
println!("stdout is not tty");
}
}</langsyntaxhighlight>
=={{header|Scala}}==
{{Works with|Ubuntu|14.04}}
<syntaxhighlight 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(STDOUT_FILENO) == 1
}
catch {
case ignore: Throwable =>
ignore.printStackTrace()
false
 
}
}
 
println("tty " + apply(true))
}</syntaxhighlight>
=={{header|Standard ML}}==
<syntaxhighlight lang="sml">val stdoutRefersToTerminal : bool = Posix.ProcEnv.isatty Posix.FileSys.stdout</syntaxhighlight>
=={{header|Swift}}==
<syntaxhighlight lang="swift">print(isatty(STDOUT_FILENO) != 0 ? "TTY" : "Not TTY" )</syntaxhighlight>
 
=={{header|Tcl}}==
To detect whether output is going to a terminal in Tcl, you check whether the <code>stdout</code> channel looks like a serial line (as those are indistinguishable from terminals). The simplest way of doing that is to see whether you can read the <tt>-mode</tt> or <code>-xchar</code> channel options, which are only present on serial channels:
<langsyntaxhighlight lang="tcl">set toTTY [dict exists [fconfigure stdout] -mode]
puts [expr {$toTTY ? "Output goes to tty" : "Output doesn't go to tty"}]</langsyntaxhighlight>
At the system call level, when Tcl is setting up the channels that correspond to the underlying <tt>stdout</tt> (and <tt>stdin</tt> and <tt>stderr</tt>) file descriptors, it checks whether the channels are network sockets (with <code>getsockname()</code>) or serial lines (with <code>isatty()</code>). This allows Tcl scripts to find out information about their calling environment (e.g., when they are run from <tt>inetd</tt>) with minimal code.
{{out|Demonstrating}}
Line 245 ⟶ 618:
===Channel type discovery with older Tcl versions===
Before Tcl 8.4, this discovery process is impossible; <code>stdout</code> always looks like it is going to a file. With 8.4, you can discover the channel type but you need slightly different (and less efficient, due to the thrown error in the non-tty case) code to do it.
<langsyntaxhighlight lang="tcl">set toTTY [expr {![catch {fconfigure stdout -mode}]}]</langsyntaxhighlight>
 
=={{header|UNIX Shell}}==
<langsyntaxhighlight lang="sh">#!/bin/sh
 
if [ -t 1 ]
Line 255 ⟶ 627:
else
echo "Output is NOT a terminal" >/dev/tty
fi</langsyntaxhighlight>
=={{header|Visual Basic .NET}}==
{{trans|C#}}
<syntaxhighlight lang="vbnet">Module Module1
 
Sub Main()
Console.WriteLine("Stdout is tty: {0}", Console.IsOutputRedirected)
End Sub
 
End Module</syntaxhighlight>
=={{header|Wren}}==
{{trans|C}}
As there is currently no way to obtain this information via Wren CLI, we instead embed a Wren script in a C application and ask the host program to get it for us.
<syntaxhighlight lang="wren">/* Check_output_device_is_a_terminal.wren */
 
class C {
foreign static isOutputDeviceTerminal
}
 
System.print("Output device is a terminal = %(C.isOutputDeviceTerminal)")</syntaxhighlight>
<br>
We now embed this Wren script in the following C program, compile and run it.
<syntaxhighlight lang="c">#include <stdlib.h>
#include <unistd.h>
#include <stdio.h>
#include <string.h>
#include "wren.h"
 
void C_isOutputDeviceTerminal(WrenVM* vm) {
bool isTerminal = (bool)isatty(fileno(stdout));
wrenSetSlotBool(vm, 0, isTerminal);
}
 
WrenForeignMethodFn bindForeignMethod(
WrenVM* vm,
const char* module,
const char* className,
bool isStatic,
const char* signature) {
if (strcmp(module, "main") == 0) {
if (strcmp(className, "C") == 0) {
if (isStatic && strcmp(signature, "isOutputDeviceTerminal") == 0) {
return C_isOutputDeviceTerminal;
}
}
}
return NULL;
}
 
static void writeFn(WrenVM* vm, const char* text) {
printf("%s", text);
}
 
void errorFn(WrenVM* vm, WrenErrorType errorType, const char* module, const int line, const char* msg) {
switch (errorType) {
case WREN_ERROR_COMPILE:
printf("[%s line %d] [Error] %s\n", module, line, msg);
break;
case WREN_ERROR_STACK_TRACE:
printf("[%s line %d] in %s\n", module, line, msg);
break;
case WREN_ERROR_RUNTIME:
printf("[Runtime Error] %s\n", msg);
break;
}
}
 
char *readFile(const char *fileName) {
FILE *f = fopen(fileName, "r");
fseek(f, 0, SEEK_END);
long fsize = ftell(f);
rewind(f);
char *script = malloc(fsize + 1);
fread(script, 1, fsize, f);
fclose(f);
script[fsize] = 0;
return script;
}
 
int main() {
WrenConfiguration config;
wrenInitConfiguration(&config);
config.writeFn = &writeFn;
config.errorFn = &errorFn;
config.bindForeignMethodFn = &bindForeignMethod;
WrenVM* vm = wrenNewVM(&config);
const char* module = "main";
const char* fileName = "Check_output_device_is_a_terminal.wren";
char *script = readFile(fileName);
WrenInterpretResult result = wrenInterpret(vm, module, script);
switch (result) {
case WREN_RESULT_COMPILE_ERROR:
printf("Compile Error!\n");
break;
case WREN_RESULT_RUNTIME_ERROR:
printf("Runtime Error!\n");
break;
case WREN_RESULT_SUCCESS:
break;
}
wrenFreeVM(vm);
free(script);
return 0;
}</syntaxhighlight>
 
{{out}}
<pre>
$ ./Check_output_device_is_a_terminal
Output device is a terminal = true
 
$ ./Check_output_device_is_a_terminal > tmp
$ cat tmp
Output device is a terminal = false
 
$ ./Check_output_device_is_a_terminal | cat
Output device is a terminal = false
</pre>
 
=={{header|zkl}}==
On Unix, check to see if stdout's st_mode is a character device.
<langsyntaxhighlight lang="zkl">const S_IFCHR=0x2000;
fcn S_ISCHR(f){ f.info()[4].bitAnd(S_IFCHR).toBool() }
S_ISCHR(File.stdout).println();</langsyntaxhighlight>
{{out}}
<pre>
Line 272 ⟶ 760:
False
</pre>
{{omit from|TI-83 BASIC|Output device is always either a terminal or created by the program}}
Anonymous user