reading file in C with fopen() - c

I am writing a program in C that needs to read lines from a file. I am using fopen() for that purpose currently.
This works fine with my program.
./myProgram /path/to/file
However, I am having trouble reading inputs like this:
./myProgram - <<END
This
is
some
nameless
file
END
So I am guessing - is the nameless file that has the contents between the 2 END's, but my program will given an error related to file not found in that case, which means that fopen() returned a null pointer.
I am wondering what is going on here?

You are correct. According to fopen's man, fopen requires a const char* to open the file. If you are just passing your argv into fopen, "This is some nameless file" is not a file path, and so fopen won't be able to find your file.
If you want to read from the stdin, you can use fgets or any other reading function that takes a FILE *stream argument, to which you can pass the stdin file stream.

Related

Dynamic file stream handling in C with freopen

I am trying to write a program that ideally accepts arguments that specify both a source file (to read from) and a destination file (to write to).
The program replaces specified characters in source file, with other specified characters, then writes the output to the destination file.
There are 3 special cases I want to handle, though:
Only a source file to read from is provided.
Desired Behavior: Display the result of replacing the text to the standard output (terminal)
Only a destination file to write to is provided.
Desired Behavior: Read from standard input, replacing desired letters and writing result to destination file name provided.
Neither the source file nor the destination file are provided.
Desired Behavior: Read from the standard in, replace characters, write to standard out.
I believe the way to do this is using freopen(), but I cannot wrap my head around the logic of when the file gets opened or how freopen() 3rd argument (stream) works.
What is the traditional way of handling this problem? Is freopen() even the function I am looking for to do this? Or is there some great lesser known function made for situations like these?
Some pseudo code would be really appreciated.
The third argument is which of the standard file streams you want to replace with a file.
So the logic will be something like:
const char *input_file = NULL;
const char *output_file = NULL;
// parse arguments, setting the above variables to the appropriate arguments if supplied
if (input_file) {
freopen(input_file, "r", stdin);
}
if (output_file) {
freopen(output_file, "w", stdout);
}
Then the rest of the program uses stdin and stdout normally.
The traditional (unixoid) way is to use only stdin and stdout.
If you want to provide an input file, use input redirection:
your_program < input_file
If you want to provide an output file, use output redirection:
your_program > output_file
If you want to provide an input file and an output file, use both ways of redirection:
your_program < input_file > output_file
And you could even add your program to a chain of commands, using pipes:
run_before | your_program | run_after
This gives you a maximum of flexibility.
It is still possible to provide options to your program.

Redirecting file contents into another program in C

Making a basic shell and I need to handle file redirection. Specifically I am stumped on how I can feed data into a program like sort for example from a file.
Something on the command line would look like this:
$ sort < test.txt
How do I accomplish this kind of functionality in my own mini shell made in C?
I thought that maybe sort read from stdin but I guess I can't really write the contents of a file to stdin due to the read only aspect so I'm wondering how I actually get this data into something like sort for example? I am currently using forks and then using execvp() to execute programs.
You need to use freopen.
It works similarly to fopen. The first argument is the filename, the second argument is the mode, and the third argument is the file pointer to redirect. The return value is the new file pointer. So if you want to redirect stdin:
FILE *fp = freopen("input.txt", "r", stdin);
It returns a NULL pointer on failure, just like fopen.

Can I pass text file as an argument in a main function in C?

I am wondering if I could pass file as an argument in a main function? I mean not a name of the file but file itself.
Not unless something external (e.g. a bash script) reads in the file and adds it as an argument. If there is a binary 0 in the file, that would be interpreted as the end of string.
You can achieve something similar using input redirection, where the contents of a file is redirected to stdin, e.g.
myprogram < myTextFile
You would then be able to read the contents of the file by reading from stdin.
You could, as long as there's no 0 bytes in the file.
Also, you shouldn't.
If you want to know how to do that, it depends on the operating system.

executing a command and getting o/p to a variable

popen stores o/p of the specified command into a file. How can I get similar functionality but o/p into a variable (i.e. in a char*) ?
No, popen() does not store output into a file. It specifies a stream, which might represent to a file on disk but which might also be at e.g. a pipe or socket. Streams are more abstract than files.
To have a pipe, you would open the pipe using e.g. pipe() and then call fdopen() on the proper end of the resulting pipe.
I could not find anything that returns o/p in a variable. It kind of makes sense as some commands' o/p can be large so to make the behavior consistent, o/p is stored in the file. I actually ended up reading from file returned by popen.
Thanks for all the help.
you can replace STDOUT and STDERR for the launched command with a stream that you control
Do you want to run a unix command from a C program, and store the output?
If so, then the sequence is to call FILE* pipe = popen("wc -l filename", "r"); and then read from the FILE* pipe just as you would read from a file opened using fopen. That is, you use functions like fgets or fscanf to read the output, just as you would if the output of the command were in a file.

Reading input from a particular file descriptor

If I know that input to my program will come from a file descriptor with a (non standard) ID, how do I read from it?
For example, if I need to read from a file descriptor with the ID of 3, how do I do it?
Also, is there an easy way to test this in BASH without having to create another program and piping?
This is what I've got so far:
char buffer[100];
FILE* fd = fdopen(3, "r");
fgets(buffer, sizeof buffer, fd);
sscanf(buffer, "%d", &whatever);
It compiles but gets a segmentation error when I run it. I looked at it in gdb and it gets stuck at the fgets, so I guess I'm doing something wrong? Possibly cause there's no end of file coming in on file descriptor 3 when I'm testing (again, would be nice if I could properly test this in BASH).
In bash, assuming your executable is "a.out", do
./a.out 3< testfile
to have testfile assigned to file descriptor 3
The same invocation works in bash, sh, zsh, ...
It does not work in csh, tcsh, ...
If you don't previously open it, there is no file with file descriptor 3. fdopen() fails and hence fd is NULL, resulting in a segmentation fault when trying fgets() on it.
Always check the return value of your function calls.

Resources