using exec to sort a text file in c - c

I have a text file full of records (output.txt) and I want to sort every record by its id. After the sorting the sorted records are written into a new file (sorted.txt).
To do that I am using bash's command "sort" via an execl() function. To check the validity of my sort command, I wrote the same command straight into the bash and the result is the expected one. But when I try to use the execl command through my C program, most of the time the answer will be that there is not a file /usr/bin/sort (I am using Mac OSX) or no error message will be thrown but nevertheless nothing happens...
What I am using is this:
execl("/usr/bin/sort", "usr/bin/sort", "-n","-k", "1", "-u", "output.txt", ">", "sorted.txt", (char*)NULL);
or this
execl("/usr/bin/sort", "usr/bin/sort", "-n","-k", "1", "-u", "-o", "sorted.txt", "output.txt", (char*)NULL);
I know that both of these 2 sort commands are correct when I m using them in the bash. What happens to C?
Thnx all in advance!

Output redirection (> somefile.txt) is a feature of the shell, not the sort program (which AFAIK is not a bash built-in).
The exec family of functions doesn't start the shell, only the program you've specified.
If you don't know the path to the program, you can use the functions with p in their names (execlp in your case, I think) and just give them "sort" as program name, they'll search for it in $PATH like bash does.

Alternatively you can try system("sort output.txt > sorted.txt"). The system function's behaviour is implementation dependent though on linux it basically spawns a new shell which executes the command passed to it. system(ARG) is equivalent to sh -c ARG. The redirection will work if the shell supports it in your system's implementation of the system function.

Related

No colour output if program run with exec

I have a C program that runs
execvp("grep", args);
Where args is an array {"grep", "test"} (test being the word I want grep to find).
The issue is that grep's output is not coloured. In a normal bash shell, grep highlights test in red, but in my program's output it just prints the line like
this is a test with no highlighting or colours of any sort.
I'm also using execvp to execute some other commands which also produce coloured output in a bash shell, and have no colours in my output.
Is there any way to fix this? Something I need to do to stdout?
You need to provide the correct option to grep in order to get it to colorize. Most likely, your shell environment includes:
alias grep='grep --color=auto'
but execvp knows nothing about aliases.
So create the args array: {"grep", "--color=auto", "test", 0} and use that in your execvp("grep", args); call.

What does execvp actually do? [duplicate]

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Writing a shell - how to execute commands
I've been tasked with writing a shell in C. So far I understand that execvp will try to run the program in arg1 with arg2 as parameters. Now it seems that doing this
execvp ("ls", args); //assume args is {"ls", ">", "awd.txt"}
is not equivalent to typing this in the console
ls > awd.txt
I realize that I need to use freopen to achieve the same results but I'm curious what execvp is doing.
The exec family of functions are ultimately a system call. System calls go straight into the kernel and typically perform a very specific service that only the kernel can do.
Redirection, on the other hand, is a shell feature.
So, when one types ls > awd.txt at a shell, the shell first does a fork(2), then it closes standard output in the child, then it opens awd.txt on file descriptor one so that it's the new standard output.
Then, and only then, the shell will make an exec-family system call.
In your case you simply passed the strings > and awd.txt to the exec system call, and from there to ls. BTW, be sure you terminate your execvp arg array with a null pointer.
Note: As you can see, the redirection operators are never seen by the executed program. Before Unix, directing output to a file had to be done by every program based on an option. More trivia: most programs never know they were redirected, but ironically, ls does check to see if its output is a tty, and if so, it does the multi-column formatted output thing.
It's executing ls with 2 arguments: > and awd.txt. It is equivalent to running:
'ls' '>' 'awd.txt'
You can pass your command directly to the shell:
char * const args[] = { "sh", "-c", "ls > awd.txt", NULL};
execvp("/bin/sh", args);
But it doesn't seems like a good idea.

Store output of C program in shell

I have a C program which gives some output. I am compiling the C program via the shell but I need the output from the run C program and store in shell.
Edit.
Save the output to a shell Variable.
I assume that you want to store the output of the program in a variable. Unix shells offer a facility that's called command substitution to do just that. Depending on your shell, you can do either :
output=$(./run)
or
output=`./run`
Bash supports both. If, however, you want to save the output to a file, you will need to redirect the standard output stream to a file. You can do this like this :
./run > output.txt
Or, if you want to see the output while the program is running and save it to an output file as well, you can use the tee utility and pipe the output of your program to it.
./run | tee output.txt
You can redirect your output into a file like this:
./run > file
If you want to store it into a variable, you have to decide which shell we're talking about. It depends whether you have a windows shell, or linux bash..

command injection in C programming

I was implementing an echo command using the system() function. The argument for the echo command comes from a command line argument. But when used ';' in the argument it is showing the directory listing.
What should i do to avoid it? Is it because of command injection in my program?
update: code added from comment
#include<string.h>
#include<stdio.h>
#include<stdlib.h>
int main(int argc, char **argv) {
char cmd[50] = "echo ";
strcat(cmd,argv[1]);
system(cmd);
}
I could compile the code but while executing if i give the command line argument as eg: './a.out hello;ls ' then directory listing is happening.
Why are you trying to use a shell access (which is exactly what System() does), and than attempt to restrict it?
If you need for some reason to use 'echo', please build your own execve() parameters, and launch /bin/echo directly.. this way you can restrict the damage only to the tasks 'echo' can do.
When attempting to run your program with the command ./a.out hello;ls, you are actually providing the shell with two separate commands that it executes in sequence. First the shell runs a.out with the command line parameter "hello" in argv[1], which prints it out using echo. Then your program exits, and the shell runs the next command, ls, and displays the directory listing.
If you want to pass that string to the program as a command line parameter, you need to escape the special shell character ;, so the shell does not parse it before giving it to your program. To escape a character, precede it with a \.
Try running the command with ./a.out hello\;ls, and then using printf instead of echo.
[can't respond to other answers yet, so reposting the question]
"Is possible to get the argument with ';', without using '\' in the command line argument. Is possible for me to include a '\' from my program after getting argv?"
No, it is not possible. The interpretation of ";" is done by the shell before getting to your program, so unless you escape at the call, your program will never be aware of the ";". i.e.
PROG1 parms ; PROG2
will cause the shell (which is interpreting what you type) to do the following:
start PROG1 and pass it parms.
once PROG1 is done, start PROG2
There are a number of special characters which the shell will take over by default and your program will never see: * for wildcards, | for pipes, & for parallel execution, etc... None of these will be seen by the program being run, they just tell the shell to do special things.
Alternatively to using the "\", you can enclose your parameter in single or double quotes (which are different, but for your example will both work). i.e.:
./a.out "hello;ls"
./a.out 'hello;ls'
Note that these will work for the printf option, if you call "system" you are in effect telling C to start a shell to run what you are passing in, so the input will once again be subject to shell interpretation.
system() is very difficult to use in a secure manner. It's much easier to just use one of the exec* functions.

Check for UNIX command line arguments, pipes and redirects from a C program

I have some problem to figure out how I can maintain the pipe and redirect functionality of a shell once I find out that there are missing command line arguments.
If I for example use a scanf call, that will work with a re-direct or a pipe from a shell, but in absence of this I get a prompt, which I don't want.
I would like to accept command line arguments through argv[], a pipe or re-direct but I can't figure out how to do it with out getting the prompt. If I for example try something like this:
if(argc < 2)
exit(0);
Then the program will terminate if I try this:
echo arg | myProgram
Or this:
myProgram < fileWithArgument
I have tried to look this up but I always get some bash scripting reference.
The common way to handle situations like this is to check if the standard input stream is connected to a terminal or not, using isatty or similar functions depending on your OS. If it is, you take parameters from the command line, if not (it's been redirected), you read standard input.
Short version: You can't do it.
Pipeline and redirect specifiers are not arguments to your program, rather they are commands to the invoking shell and are processed before the running instance of your program even exists. The shell does no pass them to the program in argv or any other variable, and you can not discover them in any reliable way.
Neil has given you the way to determine if you are connected to a terminal.
In your examples you are using pipe redirection, both echo arg | myProgram and myProgram < filesWithArguments are sending output to the STDIN of your program.
If you want to read these values, use scanf or fread on the STDIN file descriptor.
If you are trying to get the file content as an argument list for your executable, you need to use it like this:
# This will pass `lala` as a variable
myProgram `echo lala`

Resources