CommandLine Arguments not working C - 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.

Related

how to transmit argv for main in bash

I am learning the redirect symbol in Unix.I want to use redirect symbol '<' to transmit parameter for main to automatically change argv[1] in main.
Code in main is shown below
`
int main(int argc, char* argv[])
{
switch (atoi(argv[1]))
{
case 1:
.....
break;
default:
break;
}
return 0;
}
`
If i type ./a.exe 1,the main function will work in case 1 and argv[1] is 1.However, if i create a script.txt,the content of which is 1 and type ./a.exe < script.txt,case 1 will not work.And i check the argv[1] is null,which is supposed to be 1.
My code is running under Windows10 msys2 and compiler is gcc. Could anyone tell me how can i use '<' or other method.
If my understanding of '<' is wrong or there is something special for use this way to send argv[1] of main
The redirect operator is different from arguments. Actually, the redirect operator moves the content of the given file into stdin or move the output into a file. Let me explain it more. Consider the following example:
./a.out > out.txt
This redirects your stdout (printf output written into stdout for example) and writes it into out.txt.
./a.out < in.txt
This redirects in.txt into your stdin (scanf reads from stdin for example).
As you can see, these are different thing and not related to your arguments. If you want, following script reads the arg.txt and put its content as arguments for your code.
./a.out $(cat hello.txt)

Why isn't redirected input considered a command line argument?

I'm trying to read command line arguments that have been redirected from a file. The command I'm using is ./a.out < test.txt
And the contents of test.txt is: Hello world.
But the output of my program below isn't printing Hello
world. Instead it is only showing ./a.out. Why is this?
int main(int argc, char* argv[], char* envp[]) {
for (int i = 1; i < argc; i++) {
printf("%s\n", argv[i]);
}
}
The shell intercepts the redirection commands before preparing the command line for the program:
myProg <infile -t >outfile
will pass to the program
myProg -t
with stdin and stdout already rerouted before the pogram starts. So the program never sees the rediretion.
There a lot of cases, besides simple derirection:
dir > myfile.txt
Especially you can pipe output from one program to another:
dir | more
It will send output if dir command to more command. Since program launch handled by OS shell, it handles a redirection too.
Because the language is defined that way. Suppose what you say is true —
All the user input will have to come from command line arguments, but text redirected from a file can satisfy input required in different functions. This can be achieved if the input appears as command line arguments.
Consider this program:
#include <stdio.h>
int is_dict(char *word)
{
/* code to look up a dictionary */
int result = 1;
return result;
}
int main(int argc, char *argv[])
{
if(argc == 2 && is_dict(argv[1]))
printf("%s found", argv[1]);
return 0;
}
If the program is written that way to accommodate it, then the input would have to come from the command line arguments. How would you take input when it is not redirected? It would require more program overhead to detect the missing inputs.
Moreover, imagine a text file containing a million words: it is unfeasible to expect each word to arrive as an argv[n].
There are other objections too. Suppose the program prints a series of prompts for responses. The user would have to know in advance what the prompts are, to supply the answers before the prompts appear.
Lastly, if the program is run from a GUI, then all the program's input will have to be edited into its properties before it is run.

C - popen not showing right output

anyone know how I can fix this?
char bash_cmd[256] = "curl";
char buffer[1000];
FILE *pipe;
int len;
pipe = popen(bash_cmd, "r");
if (NULL == pipe) {
perror("pipe");
exit(1);
}
fgets(buffer, sizeof(buffer), pipe);
printf("OUTPUT: %s", buffer);
pclose(pipe);
The above code snippit is returning the following:
OUTPUT: (�3B
instead of what it should be returning which is:
curl: try 'curl --help' or 'curl --manual' for more information
Something is wrong, I can't figure out what. When I replace "curl" with, say, "ls -la" it works fine, but for whatever reason only when I use curl, it doesn't properly save the output into buffer. What could I do to fix this?? thanks in advance
Also, replacing "curl" with the full path to curl, (/usr/bin/curl) doesn't work either. ;(
When I run your code, I find that the output is indeed approximately what you describe, but that the output you expect is also printed immediately previous. It seems highly likely, therefore, that curl is printing the usage message to its stderr rather than to its stdout, as indeed it should do.
You do not check the return value of fgets(); I suspect you would find that it is NULL, indicating that the end of the stream occurred before any data was read. In that case, I do not think fgets() modifies the provided buffer.
If you want to capture curl's stderr in addition to its stdout, then you can apply I/O redirection to the problem:
char bash_cmd[256] = "curl 2>&1";
That would not work (directly) with the execve()-family functions, but popen() runs the given command via a shell, which should handle the redirection operator just fine.
For general purposes, however, combining curl's output and error streams may not be what you want. If both real output and real diagnostics were emitted then they would be intermingled.
The output you expect from curl is going to stderr not stdout. In fact nothing is written to stdout. The output you are printing is the uninitialized contents of the buffer.
Your code should check the return value of fgets, which will be null if no characters were read (or if an error occurred).

Why doesn't printf work when piped in Bash?

I have a Bash script work.sh that get something from STDIN and echo it to STDOUT.
I also have a C programme, return_input, that also get something from STDIN and printf to STDOUT
But when I chain them this way:
./work.sh |./return_input
printf in return_input only output to screen when exiting. Why?
Simplified:
[root# test]# cat work.sh
#!/bin/bash
for i in {1..5}
do
echo test
read
done
Output of cat return_input.c,
#include <stdio.h>
void return_input (void){
char array[30];
gets (array);
printf("%s\n", array);
printf("%#p\n", *(long *)(array+40));
}
main() {
while(1 == 1)return_input();
return 0;
}
All I/O operations are usually buffered. This is why you get the output only after you program finishes if there are not much data to overflow the buffer and output during the execution.
You can use fflush function which forces to finish I/O operation and clear buffers if you want to see output in the "real time"
You should post some code.
Try making sure that the output is flushed (using fflush(stdout); in C after you've written to it), and/or that the text contains line-feeds since typically those force the output to be flushed.
Otherwise the output might be "stuck" in a buffer, which is an optimization rather than sending single bytes across the pipeline between the processes.

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