Not able to read input from stdin/STDIN_FILENO in C? - c

I have this command line argument -
cat file_name | ./a.out
The problem is not reading from the cat command inside the C program as we can do that with read(), fgets(), fgetc() but the actual problem I am facing is after reading the data from cat I am not able to take input from user using fgets.
Here is my sample code
while(fgets(buffer, BUFSIZ, stdin ) != NULL )
puts( buffer ); // Here I have tried strtok( buffer, "\n" ) too.
memset( buffer, 0, BUFSIZ );`
The problem is after this line, it is not asking for the input like the below is not working-
puts("Name: ");
fgets( buffer, BUFSIZ, stdin );
Help me with what's wrong happening here?

When you do cat file_name | ./a.out the standard input of your program is tied to a pipe linking it to the output of cat. Your program will never get to see the user input - the very stream from where it would arrive has been replaced by the aforementioned pipe.
Mind you, I suspect that with some horrible POSIX-specific trickery you may be able to reopen it going straight for the tty device, but it's just bad design. If you need to both read from a file and accept interactive user input just accept the file as a command line argument and use stdin to interact with the user.
Edit
This is an example of the Unix-specific kludges that one can attempt, assuming that the process still has a controlling terminal. After reading all the original stdin, I'm opening /dev/tty (which is the controlling terminal of the process) and re-linking stdin to it.
Disclaimer: this is for entertainment purposes only, don't do this for real.
#include <stdio.h>
#include <stdlib.h>
void die(const char *msg) {
fprintf(stderr, "%s\n", msg);
fputs(msg, stderr);
exit(1);
}
int main() {
/* Read all of stdin and count the bytes read (just to do something with it) */
int ch;
unsigned long count = 0;
while((ch = getchar())!=EOF) {
count++;
}
printf("Read %lu bytes from stdin\n", count);
/* Open the controlling terminal and re-link it to the relevant C library FILE *
* Notice that the UNIX fd for stdin is still the old one (it's
* surprisingly complex to "reset" stdio stdin to a new UNIX fd) */
if(freopen("/dev/tty", "r", stdin) == NULL) {
die("Failed freopen");
}
/* Do something with this newly gained console */
puts("How old are you?");
fflush(stdout);
int age = -1;
if(scanf("%d", &age)!=1) {
die("Bad input");
}
printf("You are %d years old\n", age);
return 0;
}
(previously I had a solution that checked if stderr or stdout were still consoles, which was even more of a kludge; thanks #rici for reminding me of the fact that POSIX has the concept of "controlling terminal", which is accessible through /dev/tty)

If you need to use stdin for user interaction, then you need to use a different file descriptor for reading the input stream.
You could use a specific pre-opened file descriptor and document that (e.g. "the input stream should be connected to fd 3"), but the usual approach is to accept a file name as a command-line argument. You can then provide a named pipe as the argument; shells such as Bash provide process substitution to make that easy:
./a.out <(cat file_name)
When that is run interactively like that, stdin is still connected to the terminal, and can be used at the same time as the stream from the connected command.
(Obviously, if the command actually is cat with a single argument, then you could just provide the filename itself as the argument, but I'm assuming that's a placeholder for a more involved pipeline).

Related

Can I access stdin without keyboard?

I have compiled the following code with gcc
int main() {
int a = 0;
fprintf( stdin, "%d", 123 );
fscanf( stdin, "%d", &a );
printf( "%d\n", a );
return 0;
}
In my expectation, the program should executes straightly (i.e., the program never pause and wait for user input). But it still stop, and wait for my input.
I want to know what happen when I try to write something to stdin and how to modify this code and it can execute straightly?
stdin is for input only, stdout is for output. (4566976's answer shows you what happens when you try to output to stdin) See for example the glibc documentation on standard streams
(in short, writing to stdin makes no sense at all)
If you print out the return value of fprintf(stdin you can see that the function call fails.
In the shell you can pipe something into the stdin of the process.
#include <stdio.h>
int main(void) {
int a = 0, ret;
printf("%d\n", ret = fprintf( stdin, "%d", 123 ));
if (ret < 0) perror("fprintf");
fscanf( stdin, "%d", &a );
printf( "%d\n", a );
return 0;
}
$ echo 123 | ./a.out
-1
fprintf: Bad file descriptor
123
$
In addition of the fprintf(stdin, bug you also forgot that stdin is not the keyboard. The latest C11 standard does not know about the keyboard. On a Linux graphical desktop, only the X11 server is reading from the physical keyboard.
Practically speaking, on POSIX systems notably such as Linux, stdin can be a pipe(7) (using pipelines in your shell is very common), a fifo(7), a socket(7), a plain file (thru redirection) or even /dev/null, and of course also a terminal.
The funny thing these days is that terminals are very often virtual emulated devices (I did not see any real physical terminal in this century, outside of museums), read about pseudotty. The details are quite arcane for historical reasons. Read the tty demystified page. See also ANSI escape code wikipage & console_codes(4) and tty(4) (so consider /dev/tty and perhaps /dev/console)
You can check (with isatty(3)) that stdin is a terminal (actually a pseudotty) using isatty(STDIN_FILENO)...
Practically speaking, when you really want to use the terminal, I strongly recommend using a library like ncurses or GNU readline (both are using termios(3))
Don't forget that I/O is generally buffered, and use fflush(3) wisely.
BTW, you should have compiled with all warnings & debug info (gcc -Wall -Wextra -g) then use the gdb debugger. And strace(1) would have been very useful too.
Maybe you wanted to pipe to your own program (but that is weird, and often wrong, unless you take great care about all the implications; it is however a very useful trick for handling signal(7) in event oriented programs, notably those with some GUI). Beware that pipes have a limited buffer size (so avoid deadlocks, probably by having your event loop with poll(2)) and read about PIPE_BUF and write. You might have tried:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
int main() {
int pfd[2] = {-1,-1};
int a= 0;
if (pipe(pfd)) { perror("pipe"); exit (EXIT_FAILURE); };
if (dup2(pfd[0],STDIN_FILENO)<0)
{ perror("dup2 stdin"); exit(EXIT_FAILURE);};
if (dup2(pfd[1],STDOUT_FILENO)<0)
{ perror("dup2 stdout"); exit(EXIT_FAILURE);};
if (printf("%d\n", 123)<=0) { perror("printf"); exit(EXIT_FAILURE); };
if (fflush(stdout)) { perror("fflush"); exit(EXIT_FAILURE); };
if (scanf("%d", &a)<1) { perror("scanf"); exit(EXIT_FAILURE); };
if (a != 123) { fprintf(stderr, "impossible happened a=%d\n", a); };
fprintf(stderr, "done...got a=%d\n", a);
}
You should read Advanced Linux Programming and learn more about syscalls(2); it has several chapters related to this. Read carefully pipe(2) and dup2(2) and be aware that the above program would be wrong for a larger output (bigger that PIPE_BUF, which on my system is several kilobytes)
BTW, you can get a readable FILE* from a memory buffer using fmemopen(3). For writing (e.g. with fprintf) to an output buffer, consider open_memstream and don't forget to fflush it before accessing the output buffer.
You can ungetc() a few characters and then read them with fscanf().
#include <stdio.h>
int main()
{
int value = 0;
ungetc ( '\n', stdin);//reverse order. newline first here but last from fscanf
ungetc ( '3', stdin);
ungetc ( '2', stdin);
ungetc ( '1', stdin);
fscanf ( stdin, "%d", &value);
printf ( "value is %d\n", value);
return 0;
}
output: value is 123
You're simply incorrect thinking that fscanf(stdin, "format", ...); does not block and wait for input, because it does.

Read file without fopen() (C language)

I am working on a school project in which we have to do some operations (select, min, max) on a table saved in .txt file.
The problem is that we can't use common functions such as fopen, fscanf, fclose.
The program will be launched from command line like this: .\project.exe select parameters <table.txt
Do you have some ideas how to get content of the .txt file to stdin without using fopen?
Thanks.
You do not need to open the file - the operating environment will do it for you.
When your program is called with <table.txt, your standard input is switched to read from that file instead of the keyboard. You can use scanf to read the data, and do not worry about opening and closing the file.
Same goes for the output of your program and the >table_out.txt redirection: rather than printing to the screen, printfs in your program would be writing to a file, which would be automatically closed upon your program's exit. Of course if you need to print something to the screen when your output is redirected, you can do so by printing to stderr (e.g. fprintf(stderr, "Invalid table format\n").
There are few ways to acomplish this.
Reading STDIN
I guess the teacher wants this method in particular. The idea is reading standard input rather than particular file.
In C++ you can simply read the stdin object. Here's an example:
#include <stdio.h>
#include <string.h>
int main(void)
{
char str[80];
int i;
printf("Enter a string: ");
fgets(str, 10, stdin);
/* remove newline, if present */
i = strlen(str)-1;
if( str[ i ] == '\n')
str[i] = '\0';
printf("This is your string: %s", str);
return 0;
}
Source: http://www.java2s.com/Code/C/Console/Usefgetstoreadstringfromstandardinput.htm
Using system utils
You can call "type" util # Windows (not sure about it) or "cat" util in Linux as a subprocess to read some partticular file. But this is rather a "hack", so I do not recommend using this one.

How do I read file into a command line?

Basically what I want to do is have a program with int main(argc, *argv[]) and instead of writing chars into command line, I want to have my program read those words from a file. How could I accomplish this? Is there a special command in Linux for that?
You can use standard redirect operations in a *nix shell to pass files as input:
./myprogram < inputfile.txt
This statement executes your program (myprogram) and pumps the data inside of inputfile.txt to your program
You can also redirect the output of program to a file in a similar fashion:
./myprogram > outputfile.txt
Instead of doing
for(int i = 1; i < argc; i++)
{
insert(&trie, argv[i]);
}
you could doing something like
FILE *input;
char *line;
....
while (fscanf(input, "%ms", &line) != EOF) {
insert(&trie, line);
/* If you make a copy of line in `insert()`, you should
* free `line` at here; if you do not, free it later. */
free(line);
}
Use redirection
yourprogram < youtextfile
will offer the content of yourtextfile as standard input (stdin) to yourprogram. Likewise
yourprogram > yourothertextfile
will send everything the program writes to standard output (stdout) to yourothertextfile
You'll notice when reading man pages that most system calls have a version that works directly with stdin or stdout
For example consider the printf family:
printf ("hello world\n");
is a shorter version of
fprintf (stdout,"hello world\n");
and the same goes for scanf and stdin.
This is only the most basic usage of redirection, which in my opinion is one of the key aspects of "the unix way of doing things". As such, you'll find lots of articles and tutorials that show examples that are a lot more advanced than what I wrote here. Have a look at this Linux Documentation Project page on redirection to get started.
EDIT: getting fed input via redirection ior interactively "looks" the same to the program, so it will react the same to redirected input as it does to console input. This means that if your program expects data line-wise (eg because it uses gets() to read lines), the input text file should be organized in lines.
By default, every program you execute on POSIX-compliant systems has three file descriptors open (see <unistd.h> for the macros' definition): the standard input (STDOUT_FILENO), the standard output (STDOUT_FILENO), and the error output (STDERR_FILENO), which is tied to the console.
Since you said you want read lines, I believe the ssize_t getline(char **lineptr, size_t *n, FILE *stream) function can do the job. It takes a stream (FILE pointer) as a third argument, so you must either use fopen(3) to open a file, or a combination of open(2) and fdopen(3).
Getting inspiration from man 3 getline, here is a program demonstrating what you want:
#define _GNU_SOURCE
#include <stddef.h>
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char *argv[])
{
FILE *fp;
size_t len;
char *line;
ssize_t bytes_read;
len = 0;
line = NULL;
if (argc > 1)
{
fp = fopen(argv[1], "r");
if (fp == NULL)
{
perror(*argv);
exit(EXIT_FAILURE);
}
}
else
fp = stdin;
while ((bytes_read = getline(&line, &len, fp)) != -1)
printf("[%2zi] %s", bytes_read, line);
free(line);
exit(EXIT_SUCCESS);
}
Without arguments, this program reads lines from the standard input: you can either feed it lines like echo "This is a line of 31 characters" | ./a.out or execute it directly and write your input from there (finish with ^D).
With a file as an argument, it will output every line from the file, and then exit.
You can have your executable read its arguments on the command line and use xargs, the special Linux command for passing the contents of a file to a command as arguments.
An alternative to xargs is parallel.

Reading in a filename from echo command in C

I was wondering what's the best way to read in a filename in C when the name is echoed on the command line, as in: if I type in
echo test.txt | a1
how would I access the test.txt using
fopen(fname, "r");?
When you pipe data from one program to another it's as if you typed the output of the first into the second. In this case the file name can be read from stdin, and one way to read it is with the fgets function.
Read data from the standard input.
Process the data.
#include <stdio.h>
char buf[1024];
while (fgets(buf, sizeof buf, stdin))
{
printf("Read line: '%s'\n", buf);
FILE * fp = fopen(buf, "r");
if (fp)
{
// process the file
fclose(fp);
}
else
{
printf("No such file: %s\n", buf);
}
}
The obvious caveat is that the file name may be longer than 1023 characters; read the manual for fgets for details on how to detect this.
The way it's written, you'll do one processing attempt per line, and the program stops when the input stream ends.
You're trying to read from stdin, which means you could use fread (man 3 fread on *nix, here if you aren't.) to read from it.
stdin is just a name for a standard file-descriptor, so you can read from it like any other file.

understanding fputc

I am trying to get a basic understanding on how to use fputc in C. I have read some documentation that is out there and believed I had it right. But every time I try to use the script I wrote by executing ./fputc > test.txt where text.txt is a text file with one line of text.
This is my script:
int
main(int argc, char **argv){
int ch;
FILE *input;
input = fopen("text.txt", "w+");
while ((ch = getchar()) != EOF){
fputc(ch, input);
}
fclose(input);
return 0;
}
I get no errors on compilation and for some reason the script does not reach EOF at the end of the text file. Shouldn't the getchar return EOF when it reached the end of the text file?
The text (text.txt) file does not appear to be edited, although it is created. So somewhere in my while loop something is going wrong.
I am new to C programming (if you couldn't tell) and this little script has me befuddled.
Any help would be appreciated, or any links to sites with further detail would also be great.
Cheers,
S.
What you in essence say is:
Console: Run my_program and write anything it outputs to test.txt.
Program: Open text.txt and write any input to stdin to that file.
Your console normally have three standard streams stdin, stdout and stderr. These streams you can redirect. If you are on Windows also look at i.e. redirection.
When you say ./my_prog > test.txt, what you tell your console, (not my_prog), is to write anything my_prog writes to stdout to the file test.txt.
If you in your code say i.e. printf("Hello");, then Hello would be written to the file test.txt.
If you had turned your redirection around by saying ./my_prog < test.txt instead, would be; stream the file test.txt to my_prog. Which, in turn, if there was any text in test.txt would result in a copy of test.txt to text.txt.
Now in your code you say:
int main(void)
{
int ch;
FILE *input;
/* Here you open a handle to the file text.txt for reading and writing */
input = fopen("text.txt", "w+");
while ((ch = getchar()) != EOF) { /* get next char from stdin */
fputc(ch, input); /* write that char to the handle input */
}
fclose(input); /* close the handle */
return 0;
}
So what happens, the way you run it, is:
In your code:
Open text.txt
Wait for input (data entered to stdin) - typically user entering text to console, passed to program when Enter is pressed.
In console:
Redirect anything from my_prog to test.txt.
You say:
the script does not reach EOF
Well, as it reads from stdin it will only (not without exception) get EOF under two conditions.
If you redirect a file to your program. I.e. ./my_prog < foo.txt (notice <, not >).
- What would happen then is that my_prog would read the data from the file foo.txt and when that file ends your program would receive a EOF. And, hence quit.
If you manually enter EOF to stdin.
- On Linux and OSX Ctrl-D, on Windows Ctrl-Z
Now, if you test this by typing text to console remember that write actions like fputc()is buffered. What this mean is that the data is not written to the file right away, but only when a given amount of data is in buffer, fflush() is called, stream is closed, you turn off buffering, etc.
Also; if you run your program. Enter text, enter some more text, and then hit Ctrl-C to abort the program it is a big chance you end with no data in your text.txt.
The reason for this is that the program is killed and thereby fclose() never called, and hence no flush to file.
On your further endeavors in programming it would be a very good idea to make a habit of not presuming anything. I.e. do not presume fopen() is OK.
FILE *fh;
char *outfile = "foo.txt";
if ((fh = fopen(outfile, "w")) == NULL) {
fprintf(stderr,
"Unable to open file %s\n --",
outfile);
perror(" fopen() ");
return 1;
}
Most functions has a way to check if operation was a success. I.e:
if (fputc(ch, fh) != ch) { err ...
This will make your code a lot safer, give you hints on where it fails etc.
Some links:
Look at redirection links at top of post.
Look at the functions in stdio.h (good overview), stdio.h (examples etc.). I.e.:
stdin
stdout
stderr
fopen()
fflush()
setvbuf()
setbuf()
...
getchar returns the next character from the standard input (stdin).
It is equivalent to getc with stdin as its argument.
Hence, your code reads from standard input instead of FILE* input.
Use fgetc here.
fgetc returns the character currently pointed by the internal file position indicator of the specified stream. The internal file position indicator is then advanced by one character to point to the next character.
So, Use fgetc to read from a file:
while ((ch = fgetc(input)) != EOF)
your program and the shell are both writing the same file. you should remove the output redirection > test.txt from your command line

Resources