(unix/C) "stty: stdin isn't a terminal" when using system() function - c

We're reading a file from stdin into file_buffer, and then stepping into a method more.
As soon as we use system("stty cbreak -echo");, the output prints "stty: stdin isn't a terminal" and doesn't set our terminal to the settings we asked for.
This problem only exists when we use standard in. If we use a file argument, the program works fine -- the terminal settings get set, and there is no error message.
So, this is okay: myprogram file1.txt
But this is not: myprogram < file1.txt
Either way the contents are being read into file_buffer before being used at all. What the heck is wrong with using stty if we're taking input from stdin??

When the standard input is a file, it isn't a terminal, so setting terminal attributes on stty's standard input won't work.
It sounds daft at first, but you will probably find that you can use either stdout or stderr as the input for stty and it will adjust the terminal. Therefore:
system("stty cbreak -echo <&2");
is likely to set the terminal characteristics. If you have a GNU version of stty, you could also use:
system("stty -F /dev/stderr cbreak -echo");
or substitute /dev/stdout or /dev/tty for /dev/stderr. You could also use any of the named devices instead of the &2 in the redirection in the first variant.

If you use input redirection or pipes, then stdin is not a TTY.
You can use isatty to check for that.

Related

Explaining the use of "stdin" in the end of fgets() function [duplicate]

I was tasked with creating a test program in C that reads the contents of the standard input and then prints them.
But I have a little doubt: what is exactly standard input?
Is it what I type in the keyboard? Is it a file I have to read?
Both of them?
And the same goes for standard output: is it the console? a file?
The C standard (e.g. C99 or C11) defines what should be expected from the standard <stdio.h> header (after having suitably #include-d it). See stdio(3) man page.
Then you have the stdin and stdout and stderr file handles (pointers to some FILE which is an abstract data type).
The fact that stdin is related to some device (e.g. a keyboard) is implementation specific.
You could (but that would be unethical and/or inefficient) implement the C standard with e.g. a room of human slaves (that is unethical, if you use paid workers that would be just inefficient), instead of using a computer. Often, computers gives your some implementation of the C standard thru the help of some operating system.
You may want to know, inside your C program, if stdin is a "keyboard" or redirected from some "file". Unfortunately, AFAIK, there is no C99-standard way to know that.
As you mention, stdin, stdout and stderr should be available in your program at startup (i.e. after entering main ....). Hence, unless you fclose the stdin stream, you can read it (with getchar, scanf, getline, fgets, fscanf ... and friends) without any prior care (so you don't need to fopen it yourself).
On Linux or most Posix systems, you might use as an approximation isatty(STDIN_FILENO) - see isatty(3) for more - to test if stdin "is" the "keyboard" (by testing if it is some tty). See also this & that.
Yes, standard input (stdin) is input exepected from the keyboard. So, could be in the form of user input from a basic program or from a command line argument. Standard output (stdout) is the output of the code, usually to the terminal window. You could output your code almost anywhere, i.e. to a file, to a textbox, browser, but the standard is the stdout which is the terminal.
Hope that helps.
Normally, the standard input is the keyboard and the standard output the screen. However, you can redirect this in the command line using the "<" and ">" symbols. A command line like
dir /s > "Tree.txt"
will change the standard output for the dir command to be the specified file. So all output goes to that file. The called application or command itself doesn't normally even notice the difference.
stdin is file descriptor 0, you can get a file to stdin by:
cat file |yourprog
#or
yourprog <file
likewise for stdout (file descriptor 1)
yourprog | someotherprog #pipe your stdout to the stdin of another program
yourprog > somefile #save stdout to a file
yourprog >> somefile #append stdout to a file
and stderr (fd 2)
yourprog 2> errlogfile
if you have a program that takes a file but doesn't handle stdin, you can use the above formats by doing this (assuming -f if the input file argument)
myprog -f /dev/stdin
//and a horrible example of how not to read from stdin and write to stdout
char buf[4096];
while(write(1,buf,read(0,buf,4096)));
standard output (or stdout) refers to the standardized streams of data that are produced by command line programs (i.e., all-text mode programs) in Linux and other Unix-like operating systems.

Input from a file (using command line) and then normal stdin keyboard input (C)

Is there a possible way to use a *.txt file as an input for certain things using command below -
a.out<input.txt
And then use normal inputs from the user?
One option is to use:
$ ./a.out input.txt # No shell I/O redirection
You then open (each of) the command line argument(s) for reading, read it, and close it. When you're done, you can read from stdin until EOF.
On a Unix-like system, you could also support:
$ ./a.out < input.txt # Shell I/O redirection
and read from standard input to EOF, and then do one of a number of things to read from the keyboard:
Open /dev/tty and read from that.
Open /dev/tty and duplicate it to stdin (freopen()).
There are some less kosher possibilities too; one is to use the standard output or standard error file descriptor as an input file descriptor, using fdopen(). This will often work if the streams are connected to a terminal. The classic way to start a shell is to open /dev/tty for reading and writing, and then duplicate the read/write descriptor to standard input, output and error. If the output is piped to another program, or redirected to a file, this won't work, of course. You could use isatty() to check whether the file descriptors are associated with a terminal or not.
There are probably other ways to do it too — different ones if you're on Windows.
Personally, I'd go with the 'read command line arguments as files, then read standard input' option, but YMMV.

How to tail stdout or any of the standard streams?

I'm trying to understand how standard streams work in Linux, specifically how I can capture say, stdout directly from my terminal with something like tail. Since everything in Linux is a file, isn't it possible to simply do a tail -f /dev/stdout?
So to test this, I wrote a trivial program:
int main(int argc, char * argv[]) {
while (1) {
printf("This takes advantage of stdout\n");
sleep(1);
}
return 0;
}
Then in a separate terminal I did a tail -f stdout, but nothing is printed. Am I doing something wrong?
Each process has its own stdout. So you need to capture the standard output of some running process. The usual way is to make a pipeline, but you may also redirect the stdout to some file.
Learn more about tee(1). Read some bash scripting tutorial
A typical use might be thru batch(1) and a here document; I often do
batch << EOJ
make >& _make.out
EOJ
the >& is a bash-ism or a zsh-ism redirecting both stdout and stderr.
Then in a separate terminal -or even in the same terminal, after the batch sequence above- (in the same current directory)
tail -f _make.out
This enables me to see the progression of e.g. a long-lasting compilation (of course I can interrupt with Ctrl C the tail -f command without harming the compilation). YMMV.
Read also advanced bash scripting guide
Actually, /dev/stdout (notice that stdout alone means nothing particular to the shell) is a symlink to /proc/self/fd/1 . Read proc(5)
BTW, in your C code, take the habit of calling fflush(3) before any important syscall like sleep or fork (your code don't need it because stdout on terminal is line buffered but might be differently buffered when stdout is not a tty). Read stdout(3). Terminals are weird beasts, read tty demystified
addenda
To test in your C or C++ code if stdout is a terminal, use isatty(3), i.e.
if (isatty(STDOUT_FILENO))
stdout_is_a_terminal();
Notice that stdout could be a pipe or a file (then of course the above test would fail).
To write to the terminal, use /dev/tty (see tty(4)). To write on the console use /dev/console (see console(4)...). For system logging, learn about syslog(3) and e.g. rsyslogd(8).

How to interrupt standard input stream for another

This problem maybe a little bit hard to state. For example, a program receive a string from stdin, but it need a interactive input from user, like this:
echo "Some text to handle later after command is specified" | a.out
And in the beginning of the program:
printf("Please input command first");
scanf("%s", &cmd);
/* Some Code Here */
/* process "Some text to handle later after command is specified" */
Is there a way to "suspend" previous input stream and wait for the scanf's ones?
The standard does not specify any way to get interactive user input besides reading from stdin. Since your stdin is occupied with a pipe, you need to tread an implementation-specific path.
For Unix-like systems that would be a special file named /dev/tty. fopen it and use normal stdio functions.
On Windows you probably need to call Console API.
Threre's no guarantee a program is attached to any interactive device, so prepare to fail.
Note that it's considered bad style to write programs this way. If there's any user input expected, a well-witten program should just use stdin. All other input streams should then be passed as filenames via command-line arguments.
When using pipes, the shell sets up the programs stdin to be from the output of the previous command. So reading should not be a problem.
The problem here is that you should not print any output if the input is from a pipe (or redirection). This can be done by checking the result of the isatty function:
if (isatty(fileno(stdin)))
{
/* Only print prompt if input is an interactive terminal */
printf(...);
}
scanf(...);
Or am I misreading you, in that you want to read both from the user, and from the pipe? Then you probably have to open a direct connection to the terminal.
For this you could use ttyname to get the name of the TTY device of stdout and open that device for input to read the user input. That won't work if the stdout is leading to a pipe (or is being redirected) as well.

What is “standard input”?

I was tasked with creating a test program in C that reads the contents of the standard input and then prints them.
But I have a little doubt: what is exactly standard input?
Is it what I type in the keyboard? Is it a file I have to read?
Both of them?
And the same goes for standard output: is it the console? a file?
The C standard (e.g. C99 or C11) defines what should be expected from the standard <stdio.h> header (after having suitably #include-d it). See stdio(3) man page.
Then you have the stdin and stdout and stderr file handles (pointers to some FILE which is an abstract data type).
The fact that stdin is related to some device (e.g. a keyboard) is implementation specific.
You could (but that would be unethical and/or inefficient) implement the C standard with e.g. a room of human slaves (that is unethical, if you use paid workers that would be just inefficient), instead of using a computer. Often, computers gives your some implementation of the C standard thru the help of some operating system.
You may want to know, inside your C program, if stdin is a "keyboard" or redirected from some "file". Unfortunately, AFAIK, there is no C99-standard way to know that.
As you mention, stdin, stdout and stderr should be available in your program at startup (i.e. after entering main ....). Hence, unless you fclose the stdin stream, you can read it (with getchar, scanf, getline, fgets, fscanf ... and friends) without any prior care (so you don't need to fopen it yourself).
On Linux or most Posix systems, you might use as an approximation isatty(STDIN_FILENO) - see isatty(3) for more - to test if stdin "is" the "keyboard" (by testing if it is some tty). See also this & that.
Yes, standard input (stdin) is input exepected from the keyboard. So, could be in the form of user input from a basic program or from a command line argument. Standard output (stdout) is the output of the code, usually to the terminal window. You could output your code almost anywhere, i.e. to a file, to a textbox, browser, but the standard is the stdout which is the terminal.
Hope that helps.
Normally, the standard input is the keyboard and the standard output the screen. However, you can redirect this in the command line using the "<" and ">" symbols. A command line like
dir /s > "Tree.txt"
will change the standard output for the dir command to be the specified file. So all output goes to that file. The called application or command itself doesn't normally even notice the difference.
stdin is file descriptor 0, you can get a file to stdin by:
cat file |yourprog
#or
yourprog <file
likewise for stdout (file descriptor 1)
yourprog | someotherprog #pipe your stdout to the stdin of another program
yourprog > somefile #save stdout to a file
yourprog >> somefile #append stdout to a file
and stderr (fd 2)
yourprog 2> errlogfile
if you have a program that takes a file but doesn't handle stdin, you can use the above formats by doing this (assuming -f if the input file argument)
myprog -f /dev/stdin
//and a horrible example of how not to read from stdin and write to stdout
char buf[4096];
while(write(1,buf,read(0,buf,4096)));
standard output (or stdout) refers to the standardized streams of data that are produced by command line programs (i.e., all-text mode programs) in Linux and other Unix-like operating systems.

Resources