Detect if stdin is a terminal or pipe?
Use isatty
:
#include <stdio.h>
#include <io.h>
...
if (isatty(fileno(stdin)))
printf( "stdin is a terminal\n" );
else
printf( "stdin is a file or a pipe\n");
(On windows they're prefixed with underscores: _isatty
, _fileno
)
How to check if stdin is from the terminal or a pipe in a shell script?
If I get the question right, you may try the following:
#!/bin/sh
if [ -t 0 ]; then
echo running interactivelly
else
while read -r line ; do
echo $line
done
fi
C - How to check if user has sent text file to stdin
You might use isatty(3) to detect if your stdin is a terminal.
You could use fstat(2) on STDIN_FILENO
, e.g. to detect redirection or pipelines.
Or (on Linux) readlink(2) /proc/self/fd/0
, see proc(5)
I recommend accepting some program argument to override such an auto-detection. Read this.
Be aware that redirection and globbing is done by the shell, see this.
Detect if a command is piped or not
You can do this using os.Stdin.Stat()
.
package main
import (
"fmt"
"os"
)
func main() {
fi, _ := os.Stdin.Stat()
if (fi.Mode() & os.ModeCharDevice) == 0 {
fmt.Println("data is from pipe")
} else {
fmt.Println("data is from terminal")
}
}
(Adapted from https://www.socketloop.com/tutorials/golang-check-if-os-stdin-input-data-is-piped-or-from-terminal)
Detect if stdin is a tty device (terminal) or pipe in PHP?
Use posix_isatty
.
This function accepts both a file descriptor (an integer) and a PHP stream. If it receives a PHP stream, it automatically attempts to cast it in order to obtain a file descriptor and use it instead.
How can I detect if my shell script is running through a pipe?
In a pure POSIX shell,
if [ -t 1 ] ; then echo terminal; else echo "not a terminal"; fi
returns "terminal", because the output is sent to your terminal, whereas
(if [ -t 1 ] ; then echo terminal; else echo "not a terminal"; fi) | cat
returns "not a terminal", because the output of the parenthetic element is piped to cat
.
The -t
flag is described in man pages as
-t fd True if file descriptor fd is open and refers to a terminal.
... where fd
can be one of the usual file descriptor assignments:
- 0: standard input
- 1: standard output
- 2: standard error
how to tell if my stdin is coming from stdout or stderr of the piped-in process
No, it is not possible. You can differentiate stdin from a terminal by isatty()
but not what sort of stream the input came from in the way you want.
How do I determine if sys.stdin is redirected from a file vs. piped from another process?
You're looking for stat
macros:
import os, stat
mode = os.fstat(0).st_mode
if stat.S_ISFIFO(mode):
print "stdin is piped"
elif stat.S_ISREG(mode):
print "stdin is redirected"
else:
print "stdin is terminal"
How do I check if my program has data piped into it
Since you're using file pointers, you'll need both isatty()
and fileno()
to do this:
#include <unistd.h>
#include <stdio.h>
int main(int argc, char* argv[])
{
FILE* fp = stdin;
if(isatty(fileno(fp)))
{
fprintf(stderr, "A nice msg.\n");
exit(1);
}
/* carry on... */
return 0;
}
Actually, that's the long way. The short way is to not use file pointers:
#include <unistd.h>
int main(int argc, char* argv[])
{
if(isatty(STDIN_FILENO))
{
fprintf(stderr, "A nice msg.\n");
exit(1);
}
/* carry on... */
return 0;
}
Several standard Unix programs do this check to modify their behavior. For example, if you have ls
set up to give you pretty colors, it will turn the colors off if you pipe its stdout to another program.
Can not read from a pipe, and another stdin issue
Pipes don't have a size, and nor do terminals. The contents of the st_size
field is undefined for such files. (On my system it seems to always contain 0, but I don't think there is any cross-platform guarantee of that.)
So your plan of reading the entire file at one go and writing it all out again is not workable for non-regular files, and is risky even for them (the read is not guaranteed to return the full number of bytes requested). It's also an unnecessary memory hog if the file is large.
A better strategy is to read into a fixed-size buffer, and write out only the number of bytes you successfully read. You repeat this until end-of-file is reached, which is indicated by read()
returning 0. This is how you solve your second problem.
On a similar note, write()
is not guaranteed to write out the full number of bytes you asked it to, so you need to check its return value, and if it was short, try again to write out the remaining bytes.
Here's an example:
#define BUFSIZE 65536 // arbitrary choice, can be tuned for performance
ssize_t nread;
char buf[BUFSIZE]; // or char *buf = malloc(BUFSIZE);
while ((nread = read(filedes, buf, BUFSIZE)) > 0) {
ssize_t written = 0;
while (written < nread) {
ssize_t ret = write(STDOUT_FILENO, buf + written, nread - written);
if (ret <= 0)
// handle error
written += ret;
}
}
if (nread < 0)
// handle error
As a final comment, your program lacks error checking in general; e.g. if the file cannot be opened, it will proceed anyway with filedes == -1
. It is important to check the return value of every system call you issue, and handle errors accordingly. This would be essential for a program to be used in real life, and even for toy programs created just as an exercise, it will be very helpful in debugging them. (Error checking would probably have given you some clues in figuring out what was wrong with this program, for instance.)
Related Topics
Why Dereferencing a Null Pointer Is Undefined Behaviour
How to Use a C++ String in a Structure When Malloc()-Ing the Same Structure
How to Assert That a Constexpr If Else Clause Never Happen
"Invalid Use of Incomplete Type" Error With Partial Template Specialization
Reduce the Capacity of an Stl Vector
Cout Not Printing Unsigned Char
Downcasting Using the 'Static_Cast' in C++
No Default Constructor Exists For Class
Why Should the System() Function Be Avoided in C and C++
Why Is the Template Argument Deduction Not Working Here
Atomic Double Floating Point or Sse/Avx Vector Load/Store on X86_64
Define Bitset Size At Initialization
On Which Platforms Does Integer Divide by Zero Trigger a Floating Point Exception
What Is Special About Numbers Starting With Zero
Opengl - Index Buffers Difficulties
Registering a Cpp Dll into Com After Installation Using Wix Msi Installer
Sin and Cos Give Unexpected Results For Well-Known Angles
Why Is This Program Erroneously Rejected by Three C++ Compilers