how to accept pathname from stdin for open() system call? - c

I need to accept the pathname when I run my C script on linux from stdin.
I have tried doing:-
int file = open(STDIN_FILENO, O_RDONLY)
"file" is always assigned to -1 ( file not opened).
I expect running
./myScript < test.txt
to pass "test.txt" to open
open("test.txt", O_RDONLY); // expected after running the previous command

I expect running
./myScript < test.txt
to pass "test.txt" to open
That's an incorrect expectation. When you use shell's redirection operator <, it opens the file text.txt and assigns the file descriptor to your program's standard input i.e., file descriptor 0 (STDIN_FILENO). So there's no need to open the file again - it's been done already.
If you want to expect your program to receive the filename as an argument then don't use < and pass it as an argument:
./myScript test.txt
Now you would be able to receive the filename in argv[1] of your program and use it in the call to open system call.
NB: C isn't a scripting but a compiled language, so you'd better get the terminology correct (such as "C program" instead of "C script").

Related

how to get the file name in C program, that i had given in input redirection?

steps:
Let's say I have a C program inputFileName.c
I run inputFileName with input redirection such as ./inputFileName < file
How can I print the name of the file in my C program that I have typed in the terminal as an input redirection file?
The input redirection is a function of the shell. Your inputFileName executable see this as standard input. Depending on the exact operating system, you may be able to use system-specific functions to get the information you want, but there is not a standard means of doing so.
Input redirection can be achieved not only with the '<' symbol, but also with '|'.
program < filename
is equivalent to
cat filename | program
From there, one could go to
cat file1 file2 file3 | program
You begin to see why the initial 'stdin' for an executable cannot and does not have a "filename" associated with it.
If input comes from a pipe, there can't be an associated filename. Also if the file has been deleted or moved before closing the file descriptor, there is no associated filename. A file can have multiple names. In that case there are multiple filenames.
Given that, the "associated filename" of a file descriptor doesn't really make much sense. And even if you could get that info, using the filename in any way might make race conditions an issue.
The linux kernel does try to track an associated filename if a file descriptor was created by opening a file. But the keyword here is "tries".
If you are running Linux, you can find the filenname for standard input as a symlink under "/proc/self/fd/0". Just remember that you should not rely on that name for anything more than debug or display purposes.

Giving 5 Arguments but getting just 3 in terminal

I want to pass a file into a c program.
If I am doing it in the IDE this arguments
./test string string < test.txt
return argc = 5, but on the terminal I am just getting argc = 3.
It seems, that its because of the "<" - symbol, I wanted to use this, to indicate that I am passing a file.
What does < mean? I am using Ubuntu with Tilix terminal
Redirection is performed by the shell, and is not (directly) visible to your program.
./test string string < test.txt
means,
Open test.txt for reading on file descriptor 1
Run ./test with the arguments string and string
The program run in point 2 will inherit the parent's file descriptors, so its standard input will be connected to the opened file handle (rather than the shell's current standard input, which could be your terminal, or a different file handle).
As an aside, you probably want to avoid calling your programs test, though as long as you don't forget to invoke it with an explicit path, this is harmless.
The < symbol will insert information from somewhere (a text file) as if you typed it yourself. It's often used with commands that are designed to get information from standard input only.
For example (using tr):
tr '[A-Z]' '[a-z]' < fileName.txt > fileNameNew.txt
The example above would insert the contents of fileName.txt into the input of tr and output the results to fileNameNew.txt.
Answer adapted from this page.
For similar information about all symbols, use this page

execlp command doesn't take into account the asterisk wildcard

this little command :
execlp("/bin/echo", "echo", "*", ">", "toto", 0)
prints * > toto in the terminal, but I want it to print the result of echo * in the file toto.
The command : system("echo * > toto")  works well, but I want to use the execlp command, what I am doing wrong?
Thank you in advance.
The angle bracket ('>') redirection is shell specific.
You could do, for example:
execlp("/bin/sh", "/bin/sh", "-c", "/bin/echo * > toto", NULL);
Note that this invokes 2 specific behaviors that are shell related:
* wildcard: the asterisk wildcard will be expanded (by the shell, very important) to all files in current directory; and
> redirection: the stdout of the echo command will be redirected to file (or pipe) toto.
If you want to do the same kind of redirection in C (i.e. without resorting to executing the shell) you must:
// open the file
int fd = open("toto", "w");
// reassign your file descriptor to stdout (file descriptor 1):
dup2(fd, 1); // this will first close file descriptor, if already open
// optionally close the original file descriptor (as it were duplicated in fd 1 and is not needed anymore):
close(fd);
// finally substitute the running image for another one:
execlp("/bin/echo", "echo", "*" 0);
Note that you'll still get '*' written to the file.
Edit: the first argument to execlp is really the executable to run, file image that will substitute the currently running process. After this first argument comes the full argv array, which must include argv[0]. I've edited the code above to reflect this. Some programs use this argv[0] to change its personality (for example, busybox is a single executable that implements ls, echo, cat and many other unix command line utilities); that surely is the case with bash and whatever is linked from /bin/sh.

Writing commands for input/ouput file redirection in custom shell

I am writing my own shell in C. It's fairly simple, but I want to implement three more commands. First being commands, with or without arguments, whose output is redirected to a file. Second being, a command, with or without arguments, whose output is appended to a file. Lastly, a command, with or without arguments, whose input is redirected from a file.
All of these commands can be implemented using the syscalls freopen(), dup() and dup2().
An example of the first command could be ls -l > fileName.txt.
This should take the output of the command and put it in fileName.txt.
An example of the second command could be ls -l >> fileName.txt.
This should take the output of the command and append it to whatever is in the file fileName.txt.
An example of the last command could be bc < file. This takes the output of the command and put it in the named file.
This shouldn't be too hard to implement, but for some reason I don't know how to do it and am having some serious trouble. Could someone help me out?
I'd stick to raw system calls. Forget freopen() and use open(). The stdio routines work with FILE* streams while the syscalls work with integer file descriptors. Mixing the two guarantees serious trouble. ;-)
Redirection goes in 4 steps
open() file to redirect to/from, returns an fd
close() file to redirect, 0 for stdin, 1 for stdout
dup(fd) fd was returned by open() in the 1st step
close(fd) you don't need it enymore
The trick is that dup() returns the lowest available integer for a new file descriptor. If you've just closed stdout 1, it will return 1, and suddenly your stdout is pointing to the previously opened file.

How to redirect the output of a c program to a file?

I am trying to redirect the output of a c program to file, even when it generates some errors because of problems with the input data. I can send the output but the error messages to a file.
Does somebody know how to do it?
From within C source code, you can redirect outputs using freopen():
General outputs:
freopen("myfile.txt", "w", stdout);
Errors:
freopen("myfile_err.txt", "w", stderr);
(This answer applies to bash shell, and similar flavors. You didn't specify your environment and this sort of question needs that detail.)
I assume you know about basic redirection with ">". To also capture STDERR in addition to STDOUT, use the following syntax:
command > file-name 2>&1
For some more background on standard streams and numbers:
http://en.wikipedia.org/wiki/Standard_streams#Standard_input_.28stdin.29
This depends on what you mean and what platform you are using. Very often you can accomplish this from the command line, which has been covered in another answer. If you use this method to accomplish this you should be aware that FILE * stderr is typically written immediately (unbuffered) while FILE * stdout may be buffered (usually line buffered) so you could end up with some of your error messages appearing to have been printed earlier than some other messages, but actually the other messages are just being printed late.
From within a C program you can also do something similar within the stdio system using freopen, which will effect the FILE *, so you could make fprintf(stderr, "fungus"); print to something besides what stderr normally would print to.
But if you want to know how to make a program redirect the actual file descriptors under a unix like system you need to learn about the dup and dup2 system calls. They allow you to duplicate a file descriptor.
int fd = open("some_file", O_WRONLY);
dup2(2,fd);
close(fd);
This code will make "some_file" the new stderr at the OS level. The dup2 call will close and replace file descriptor 2 (stderr, which is usually used by FILE * stderr but not necessarily if you call freopen(x,y,stderr) since that may make FILE *stderr use a different file descriptor).
This is how shell programs redirect input and output of programs. The open all of the files that the new program will need, fork, then the child uses dup2 to set up the files descriptors for the new program, then it closes any files that the new program won't need (usually just leaving 0, 1, and 2 open), and then uses one of the exec functions to become the program that the shell was told to run. (some of this isn't entirely accurate because some shells may rely on close on exe flags)
Using a simple linux command you can save the output into the file. here is a simple linux terminal command.
ls > file.txt
The output of this command will be stored into the file.
same as you can store the output of the program like this suppose, object file name is a, run the following command to save output in a file:
./a > file.txt

Resources