How to accept file argument in C? - c

I know, if ran in bash, my program is supposed to able to handle arguments like (where a.out is the name of file):
$ a.out <inputFile
Does this mean that inputFile is argv[1]? If so, what is the data type of argv[1] in case I need to pass it in to some other function? Would I read it using something like:
FILE *fopen( const char * filename, const char * mode );
OR
Does that mean I have to accept input from user getchar() or something?
How do I deal with such situations?

There's two ways to receive input:
Via STDIN, which is a pre-defined filehandle (fd 0 or STDIN_FILENO) you can read from at any time.
Via command-line arguments passed by argv
The shell interprets redirection operators to adjust what STDIN actually is, so by the time the program runs the only arguments left are:
"a.out"
The redirection is gone. It's just "piped" into STDIN.
Shell operators like <, > and | are interpreted by the shell before your program is run. The same goes for interpolation like $ variables and other shell-specific functions.

The command
./a.out < inputFile
isn't passing arguments to the program, instead if does redirection.
That means the shell will set up standard input (stdin, which e.g. scanf reads from) in your program to read from the redirected file.
To pass an actual argument to the program you need to run it as:
./a.out inputFile
In this case argc will be equal to 2, and argv[1] will be the string "inputFile". Which you can then pass on to e.g. fopen.

You need to pass a path to the c program then use fopen()

Using "<" means you are redirecting standard input of your process to be read from inputFile. So, all the standard read routines (getchar(), cin << ...) can be used.
If you omit "<", then inputFile becomes command argument and it is passed as part of char* argv[] to your main. After checking argc, validating file exists etc., you can use file reading routines, like fopen.

Related

Use Cat command with C code

I'm using the cat command for a school project.
What i need is to give a txt file as input to my code and then evaluate the output (saved in a txt file).
So far i'm using this in my command line:
cat input_000.txt | ./main > my_output.txt
Where ./main is my C code.
The input_000.txt is structured like this:
0 a a R 3
1 a b L 4
4 c b R 1
ecc...
I have a certain number of lines made of 5 characters (with spaces between them).
How do i get the content of each line in my C code? I've been told so use standard input, but i've always used scanfonly from keyboard input.
Does it still work in this case?
And how should i save my output? I usually use fwrite, but in this case is everything managed by the cat command
That's how pipes works, it sets up so the output of the left-hand side of the pipe will be written to standard input for the right-hand side program.
In short if you can read input from stdin (like you do with plain scanf) then you won't have to do any changes at all.
Redirection works just about the same. Redirecting to a file (>) will make all writes to stdout go to the file. Redirecting from a file (<) will make all reads from stdin come from the file.
You can use getline (or scanf indeed) to read the stdin (fd = 0) and save it in a char* in your C code... Then you only need to write in the stdout (fd = 1) and your > will do the job to write in your file
What you need is something like this inside your function...
FILE *input = fopen("input.txt","rw"); //rw (read-write)
FILE *output= fopen("output.txt","rw"); //rw (read-write)
char inputArray[500];
char outputArray[500];
while(fscanf(input,"%s", inputArray) != EOF){
//read the line and save in 'inputArray'
//you can also use %c to find each caracter, in your case I think it's better...you can //save each caracter in a array position, or something like that
}
while(number of lines you need or the number of lines from your input file){
fprintf(output,"%s\n",output); //this will write the string saved in 'outputArray'
}
If you don't want to use it...then you can give your main.c the input using < and saving the output >
./main.o < input.txt > output.txt
(something like that, its not safer because the terminal could have the settings to use other type of charset...

Parse a argv in c to a command in unix

I am new to unix and require some help.
I have another program call projectc which is an suid program located on another user call userb . userb has a directory pass that only has permission for write and read for its owner (userb)
I am trying to use the printf to do a command printf(system("cat /home/userb/pass")) through the argv argument.
I am able to do it in the c code printf(system("cat /home/userb/pass")) directly but doing it in the argv argument, i am unable to do it).
Is there anyway to parse the argv[1] parameter into a command?
this is my c program that I was trying to run in unix.
int main( int argc, char **argv){
printf(argv[1]);
return 0;
}
printf(system("cat /home/userb/pass"))
The reason this seemed to work is because the spawned subprocess printed on the screen. The printf was not only unnecessary but actually a bug. The first parameter to printf is a string (char*), while the retrn value from systemis an int.
A correct call would be:
int success = system("cat /home/userb/pass");
If argv[1] is the command you want to run you can just call:
int status = system(argv[1]);
You could then run your program like this:
myprogram "cat /home/userb/pass"
Note the double quotes - they ensure that the entire command is passed as a single parameter. Without the quotes it would be divided into two parameters.
And please turn up your compiler warning level. printf(system("cat /home/userb/pass")) should give some big warnings/errors when you compile.

CommandLine Arguments not working C

I am trying to pass File1.txt ">" File2.txt as terminal arguments to my program in order to override the cat command. But for some reason, the program is not working. Although the argc is 4 in above defined case but still the condition in the program is not getting true. Here is the code:
int main(int argc, char *argv[])
{
int readbytes,fp;
char buf[1024];
if(argc==2)
{
fp=open(argv[1],O_RDONLY);
dup2(0,fp);
close(fp);
readbytes=read(STDIN_FILENO,buf,1024);
write(STDOUT_FILENO,buf,readbytes);
}
if(argc==4)
{
printf("inside4");
fp=open(argv[1],O_RDONLY);
dup2(fp,0);
close(fp);
fp=open(argv[3],O_WRONLY|O_CREAT|O_TRUNC,S_IRWXU);
dup2(fp,1);
close(fp);
readbytes=read(STDIN_FILENO,buf,1024);
//printf("%c",buf);
write(STDOUT_FILENO,buf,readbytes);
}
return 0;
}
I couldn't find a solution to this issue so I leave it to experts now.What is the reason for this problem?
NOTE:
For some reason when I send ./prog File1.txt > File2.txt to program, argc==2 condition is selected, however argc is 4. Why is that?
Regards
This is likely being caused by how you are running your program. Typing
./myProg foo > bar
will instruct most shells to run myProg with argument foo and save whatever is printed to stdout in a file named bar. To pass foo, >, and bar as command line arguments, use
./myProg foo \> bar
or
./myProg 'foo' '>' 'bar'
Side note: Because piping output into a file using > is part of the shell, not a program like cat itself, you likely shouldn't have to worry about it. Just write to stdout and the shell will handle the rest.
What do you mean by the condition in the program is not getting true? Are you saying that you don't see "inside4" printed to the terminal? There are a few things to consider. First, you do no error checking. We will have to assume that all of your open and dup2 calls succeed. I would expect that "inside4" is getting printed to the end of the output file. The reason for that is simply that printf does not actually write anything. It just stores the string "inside4" in a buffer, but that buffer is not written to the output until your program exits, and by that time the underlying file descriptor has been changed to the output file. The simplest fix is to append a newline to the output, and write printf( "inside4\n" ); In the normal setup, printing a newline causes the internal buffer to be flushed. You can also explicitly flush the buffer after calling printf by calling fflush.

output redirection in Unix and C

I am trying to run a script inside my C program using system() command. Inside main(), I run the script and it returns the results. How can I put the result of the script in some string and check for conditions? I know I can do it with files but was wondering if its possible to put the result into a string.
Sample would be like:
main()
{
system("my_script_sh"); // How can I get the result of the my_script_sh
}
You can't use the system command for that. The best thing to do is use popen:
FILE *stream;
char buffer[150];
stream = popen("ls", "r");
while ( fgets(buffer, 150, stream) != NULL ){
// Copy the buffer to your output string etc.
}
pclose(stream);
Use popen() and read the stream into a char * buffer.
Well the easiest thing to do would be to take system("my_script_sh") out of your program and invoke the program from the shell with a pipe -- e.g.: my_script_sh | ./your_c_program and then your C program just reads from stdin (file descriptor 0).
If that is not possible, then have a look at man 3 popen. Basically, you use popen instead of system and it gives you a file handle that you can read from to get the output of the program.
Here are a few links that might be useful:
http://pubs.opengroup.org/onlinepubs/009695399/functions/popen.html
http://www.crasseux.com/books/ctutorial/Programming-with-pipes.html
http://www.metalshell.com/source_code/23/Popen.html
http://tldp.org/LDP/lpg/node12.html

Reading command line arguments after '<' in C

Let me start by saying this is associated with a homework assignment. However, this is a very small and relatively insignificant part of the assignment.
The C program receives input via command line arguments but it needs to be in the form:
$ ./program < input
How, would I go about receiving that input as a string? Each time I try to print out the 3rd argument from argv I receive this message:
input: No such file or directory.
< is a shell redirect - it is handled outside your program. What you'll see is the contents of the file name 'input' being send to your standard input stream. This is a common way for programs to operate, although they usually also handle being given a file name e.g. sed.
If I had to guess I would think the:
input: No such file or directory.
is coming from the shell, as it is unable to open the file specified: "input".
On the other hand, if you actually want the < input as arguments to your program, you can escape or quote them so the shell won't interpret them. (Escaping left as an exercise for the reader :-)).
The ./program < input syntax is a special shell syntax saying "Redirects everything in the file named input to the standard entry of the program".
To read the input, your program just have to use standard input reading functions, line fgets or scanf.
On *nix systems, there won't be a third element of argv. If you execute that command on almost any Unix-like shell, it will be similar to doing this:
cat input | ./program
So your ./program has only one element in argv, but it's stdin is the file input, so to read the file you would just read from stdin. Note that this is a perfectly valid way to design your program. Many Unix programs read from standard input if no files are given, so that you may pipe in input from other programs (or in this case, from files).
What comes after the < is not a command-line argument. The contents of the file will be piped into your program by the shell.
All you need to do is read from stdin and you'll get the contents of the file.
You need to escape the '<', otherwise shell will parse it, and program won't receive it in command-line.
If you're using bash, then:
./program '<' input
or
./program \< input
Other shells might do it differently (e.g. Windows' default, cmd.exe, uses ^ as escape character, not \).
This is a Unix shell thing. The form someprogram < somefile tells someprogram to run using somefile as its input. If you want to do something different involving the < symbol, you'll need to quote it.
The < means that the program will read it's standard input (stdin) from the named file (input). So just read from stdin (using fgets, fread, etc).
Leave off the '<'. You want command line arguments do this:
$ ./program -Dflag seven=ixnay FromDinger
In your application, try this:
int main( int argc, char **argv )
{
int i;
for( i = 0 ; i < argc ; ++i )
printf( "Arg %d = %s\n", i, argv[i] );
return 0;
}
You'll notice that the first argument is the name of the executable (at index 0), and your second argument (at index 1) will be "-Dflag"
Actually, this is a very common technique used in programming tournaments. The data your program needs is stored in a file, let's say data.txt , and then redirected to your application using the "<" on the shell, like this: ./program < data.txt
So, in your source code, what you need to do is something like this:
#include <iostream>
#include <string>
using namespace std;
int main(void)
{
string tmp;
string full_content;
while (cin >> tmp)
full_content += " "+tmp;
cout << full_content << endl;
}
.. and you'll get all the data from the file on a string (and separated by spaces).
That's one way to do it, I hope it helps.
[]'s
You can get it by reading stdin.

Resources