[comp.lang.c] How do you tell if stdin/stdout is a terminal?

gg10@prism.gatech.EDU (GALLOWAY) (08/05/90)

I have seen programs which pipe binary data back and forth.  These programs
are usually "filters" for image data, etc.  Some are smart enough not to try
and read stdin, or write to stdout if the user has not added the proper 
redirections.  This can be quite useful if this binary data might be 
interpreted as terminal setup commands.

So, how do they do it on a generic unix box?

If I have a program named "foo" which can accept standard input if no file
name exists on the command line, and the user just types "foo", I want to
display usage.  If they type "foo < file" or "bar | foo" then I want to process
stdin.  Novice users see to be incredibly confused by typing "foo" and just
having it hang waiting for them to type in a binary image file, etc.

It would also be nice, if the output of "foo" was no ASCII to display a message
like "foo: output must not be terminal".  Again, so the novice user doesn't 
get blown away be several screenfulls of garbarge.  It seems most people like
to figure out how an unknown program works by just typing its name and waiting
for the old familar "usage: foo [ options ] arguments" line to pop up.

Thanks in advance,
Greg Galloway
gg10@prism.gatech.edu

kfir@bimacs.BITNET (Yuval Kfir) (08/06/90)

In article <12210@hydra.gatech.EDU> gg10@prism.gatech.EDU (GALLOWAY) writes:
(stuff deleted)
>It would also be nice, if the output of "foo" was no ASCII to display a message
>like "foo: output must not be terminal".  Again, so the novice user doesn't
>get blown away be several screenfulls of garbarge.  It seems most people like
>to figure out how an unknown program works by just typing its name and waiting
>for the old familar "usage: foo [ options ] arguments" line to pop up.

I seem to remember a function called isatty(stdin). I am not sure it is
standard. I hope this helps.

---------------------------------------------------------------------------
Yuval Kfir              kfir@bimacs.bitnet
                        kfir@bimacs.biu.ac.il

"If you can lead it to water and force it to drink then it isn't a horse."
--
---------------------------------------------------------------------------
Yuval Kfir              kfir@bimacs.bitnet
                        kfir@bimacs.biu.ac.il

"If you can lead it to water and force it to drink then it isn't a horse."

amoss@huji.ac.il (Amos Shapira) (08/06/90)

Hello,

gg10@prism.gatech.EDU (GALLOWAY) writes:

>So, how do they do it on a generic unix box?

Simple, don't know how much compatible it is, but there should be a routine
in the standard C library called "isatty(fd)" which will return 1 if fd
(a file descriptor) is a terminal and 0 otherwise.

If you don't have isatty(), it's way of operation is simple, it just does
an ioctl that only a terminal will accept without an error, like
"ioctl(fd, TIOGETP, &junk)" and if it returns a value less than a 0 then
fd is not a tty, otherwise it is. Not that it does a "GET*" operation, so
it doesn't brake anything.

Just for the sake of completeness, to convert from a file pointer (FILE *)
to a file descriptor (int), use fileno(fp).

Hope this helps,
Amos Shapira.
amoss@batata.huji.ac.il

brad@SSD.CSD.HARRIS.COM (Brad Appleton) (08/06/90)

In article <2072@bimacs.BITNET> kfir@bimacs.biu.ac.il.UUCP (Yuval Kfir) writes:

(stuff deleted)

>I seem to remember a function called isatty(stdin). I am not sure it is
>standard. I hope this helps.                ^^^^^
>

Thats almost correct, the usage should be:

	isatty(STDIN);

where you have the following #defines

	#define STDIN  0
	#define STDOUT 1
	#define STDERR 2

You need to give it the file-descriptor number, not the file pointer!

Some compilers have the above #defines in their standard header files,
some dont! Also, On some Unix implementations (you will have to check yours),
calling isatty() can set errno to a non-zero value if isatty() returns FALSE.
This is due to the fact that some implementations of isatty() use ioctl()
to make a terminal-specific setting, if ioctl() fails, the file-descriptor
is NOT connected to a terminal.

Anyway, if you are on UNIX, isatty() is the way to go. If you are on another
system - look through your C-Compiler manual! Hope this helps!!

Just for the record - Peter Da Silva helped me figure out why errno
was being set!
______________________ "And miles to go before I sleep." ______________________
 Brad Appleton        brad@travis.ssd.csd.harris.com   Harris Computer Systems
                          ...!uunet!hcx1!brad          Fort Lauderdale, FL USA
~~~~~~~~~~~~~~~~~~~~ Disclaimer: I said it, not my company! ~~~~~~~~~~~~~~~~~~~

peter@ficc.ferranti.com (Peter da Silva) (08/07/90)

This is touched on in the latest FAQ for comp.unix.questions, under "how
do I tell if my program is running in the background". It is not a C
problem, but a UNIX problem. However, here are the answers.

In article <12210@hydra.gatech.EDU> gg10@prism.gatech.EDU (GALLOWAY) writes:
> If I have a program named "foo" which can accept standard input if no file
> name exists on the command line, and the user just types "foo", I want to
> display usage.

	if(isatty(fileno(stdin))) {
		usage();
		exit(0);
	}

> It would also be nice, if the output of "foo" was no ASCII to display a
> message like "foo: output must not be terminal".

	if(isatty(fileno(stdout))) {
		user_error();
		usage();
		exit(2);
	}
-- 
Peter da Silva.   `-_-'
+1 713 274 5180.   'U`
<peter@ficc.ferranti.com>

andrew@alice.UUCP (Andrew Hume) (08/15/90)

	i am admittedly feeling ornery tonight but anyone asking am
i connected to a terminal is probably asking the wrong question.
isatty is pretty unreliable over network connections.
(unreliable in that typically it always says no for network
connections regardless of teh state on the far side.)