My goal is to have a program that can take user input from a file redirection in C.
$ ./hello < input.txt
But when there is no redirection or arguments the program will output a message :
$ ./hello
There is nothing to read!
Since file redirection goes directly into stdin, I'm using scanf to read the contents of the file. However when I start the program without a redirection scanf waits for input and my goal is to get it ONLY from the redirection on the command line if there's nothing it outputs the message
CodePudding user response:
Up to non-portably checking if stdin is a tty or not, the shell cannot tell where the input is coming from, it can only tell if it is already there or not. You don't say what platform you're on, and I am assuming what you really want is just /for the read to not block/ - you can achieve this by polling stdin in a non-blocking fashion:
#include <sys/select.h>
#include <stdio.h>
#include <unistd.h>
int poll_stdin() {
struct timeval tv;
fd_set fds;
tv.tv_sec = 0;
tv.tv_usec = 0;
FD_ZERO(&fds);
FD_SET(STDIN_FILENO, &fds);
select(STDIN_FILENO 1, &fds, NULL, NULL, &tv);
return FD_ISSET(STDIN_FILENO, &fds);
}
size_t read_stdin(char *buf, size_t max) {
size_t n = 0;
while ((n < max) && (poll_stdin())) {
read(STDIN_FILENO, &buf[n ], 1);
}
if (n < max-1) buf[n] = '\0';
return n;
}
int main(int argc, char *argv[]) {
char buf[255];
size_t len;
buf[255] = '\0';
len = read_stdin(buf, 255);
if (len == 0) printf("No input!\n");
else printf(">%s\n", buf);
return 0;
}
Output:
dtrombley@squall:~$ echo 'Hello, world!' > hello.txt
dtrombley@squall:~$ ./main
No input!
dtrombley@squall:~$ ./main < hello.txt
>Hello, world!
CodePudding user response:
Use isatty()
That is exactly what it is for.
Be aware that not all systems provide a sane isatty(), but any *nixen that claims POSIX compliance will work properly. Here is my current go-to code for *nixen (adapted to C):
#include <stdbool.h>
#include <unistd.h>
bool my_isatty( int id )
{
return (0 <= id) and (id <= 2) and isatty( id );
}
There are all kinds of wrinkles on Windows, particularly if you are using the MSYS2 shell (which implements the command window using pipes, LOL, so you have to play with some low-level OS stuff to check that).
