How to pass string argument to execve - c

How to pass a string argument as shown in the program below?
The argument after -f should be a string in quotes. I tried to escape \" but did not work. I also tried to use ' and \' instead of \" and again it did not work.
#include <stdio.h>
#include <unistd.h>
int main(void)
{
char *args[] =
{
"/usr/ws/bin/tshark", "-i", "/tmp/ts_pipe", "-w",
"/tmp/output.pcap", "-f", "\"not src host 1.1.1.1\"", "2>",
"/tmp/error.log", NULL
};
char *envp[] =
{
"PATH=$PATH:/usr/wireshark/bin",
"LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/usr/lib32",
0
};
execve(args[0], &args[0], envp);
fprintf(stderr, "Oops!\n");
return -1;
}

Just because you need quotes in the shell, for example,
tshark -f "not src host 1.1.1.1"
doesn't mean you need them in exec. In fact, those quotes are telling the shell "this is one argument", so the shell will not split on spaces and will pass the string (without quotes) as one argument to the program. So, in C, you would simply:
char *args[] = { "-f", "not src host 1.1.1.1" }
and pass that to exec.
While we're at it, redirections like
2>errfile
are intercepted by the shell and not passed on to the command, so they won't work in exec. You'll have to do the dup()s yourself, or else just pass a whole shell command to the shell (which is a security no-no).

As explained in the comments, redirection will not work with execve, but you could try doing this:
#include <stdio.h>
#include <unistd.h>
int main(void)
{
char *args[] =
{
"/bin/sh", "-c",
"/usr/ws/bin/tshark -i /tmp/ts_pipe -w "
"/tmp/output.pcap -f \"not src host 1.1.1.1\" 2> "
"/tmp/error.log", NULL
};
char *envp[] =
{
"PATH=$PATH:/usr/wireshark/bin",
"LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/usr/lib32",
0
};
execve(args[0], &args[0], envp);
fprintf(stderr, "Oops!\n");
return -1;
}
You are basically launching sh shell with -c option and passing it your whole command as an option.

Related

Execute a concatenation command with execvp

How can I execute the following command using execvp, if it's possible:
"ls | tee ~/outputfile.txt"
I've tried to run the following code but got this message: execvp() not expected: No such file or directory
I'm not sure for the cause of this issue,
I can't execute this command because this is concatenation command ?
#include <unistd.h> // execvp()
#include <stdio.h> // perror()
#include <stdlib.h> // EXIT_SUCCESS, EXIT_FAILURE
int main(void) {
char *const cmd[] = {"ls | tee ~/outputfile.txt", NULL};
execvp(cmd[0], cmd);
perror("Return from execvp() not expected");
exit(EXIT_FAILURE);
}
In the bottom line, want to write the output of the command 'ls' to a file in my code.
Thank you in advance!
You can't use execvp (or any exec* function family) like that.
First of all, the first argument must be the path to the executable file.
I doubt you have an 'ls | tee ~/outputfile.txt' executable somewhere on your computer.
You have 'ls' or 'tee' probably, but not 'ls | tee ~/outputfile.txt'.
Secondly : exec* function family can't do nativly piping (the '|' part) : you have to do it yourself.
An example is the following :
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
int main(void)
{
char *const cmd[] = {"ls", "/home", NULL};
execvp(cmd[0], cmd);
perror("Return from execvp() not expected");
exit(EXIT_FAILURE);
}
That will do a ls in "/home".
It's up to you to pipe it in another execve : this can greatly help you.
If you just want to execute your command line wthout any regard for security, you can use "system"

execve with sed fails

I'm creating a small unix shell, execve has an issue with sed. When I execute sed -e 's/Roses/Turnips/' the command fails with execve.
#include <unistd.h>
#include <stdio.h>
#include <fcntl.h>
int main(int ac, char **av, char **envp)
{
char *argv[] = { "/usr/bin/sed", "-e", "'s/Roses/Turnips/'", 0 };
execve(argv[0], &argv[0], envp);
fprintf(stderr, "Failed!\n");
return -1;
}
Error:
/usr/bin/sed: -e expression #1, char 1: unknown command: `''
Get rid of the single quotes around the s/// argument. Those are part of shell syntax, not sed syntax.
char *argv[] = { "/usr/bin/sed", "-e", "s/Roses/Turnips/", 0 };
execve executes the program directly, it doesn't use a shell. Every argument is sent literally to the program, so no escaping or quoting is needed as when running a program in the shell.
That problem arises inside of sed because it doesn't want your single quotes.
You'd use those single quotes in a shell to prevent it from interpreting the sed command, but the shell would ultimately remove those quotes, which is what you need to do also.

How do I run a python script and pass arguments to it in C

I have a python script script.py which takes command line params
I want to make a wrapper in C so I can call the script.py using ./script args
So far I have this in my script.c file
#include<stdio.h>
#include <stdlib.h>
int main(int argc, char *argv[]){
system("python3.4 script.py");
return 0;
}
How do I modify the script so I can do ./script arg1 arg2 and the C code executes system("python3.4 script.py arg1 arg2");
I don't have experience in C. Above code is from googling
Using system() is needlessly complicated in this case, as it effectively passes the given command string to (forked) sh -c <command>. This means that you'd have to handle possible quoting of arguments etc. when forming the command string:
% sh -c 'ls asdf asdf'
ls: cannot access 'asdf': No such file or directory
ls: cannot access 'asdf': No such file or directory
% sh -c 'ls "asdf asdf"'
ls: cannot access 'asdf asdf': No such file or directory
Note the difference between the unquoted and quoted versions.
I'd suggest using execve(), if executing the python command is the only purpose of your C program, as the exec family of functions do not return on success. It takes an array of const pointers to char as the new argv, which makes handling arguments easier:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#define PYTHON "/usr/bin/python3"
#define SCRIPT "script.py"
int
main(int argc, char *argv[])
{
/* Reserve enough space for "python3", "script.py", argv[1..] copies
* and a terminating NULL, 1 + 1 + (argc - 1) + 1 */
int newargvsize = argc + 2;
/* VLA could be used here as well. */
char **newargv = malloc(newargvsize * sizeof(*newargv));
char *newenv[] = { NULL };
newargv[0] = PYTHON;
newargv[1] = SCRIPT;
/* execve requires a NULL terminated argv */
newargv[newargvsize - 1] = NULL;
/* Copy over argv[1..] */
memcpy(&newargv[2], &argv[1], (argc - 1) * sizeof(*newargv));
/* execve does not return on success */
execve(PYTHON, newargv, newenv);
perror("execve");
exit(EXIT_FAILURE);
}
As pointed out by others, you should use the official APIs for this, if at all possible.
You can generate your command as a string. You just need to loop through argv[] to append each parameters given to the C program at then end of your command string. Then you can use your command string as the argument for the system() function.

Using execl to copy two files provided when calling the executable

My executable is named copy.
I want when executing
copy file1 file2
to basically do
cp -i -p file1 file2
And I want to accomplish this using the execl function.
Now I have more expertise with the execvp that automatically searches for the path of the command.
So I can do something like the following:
char *cmd[] = {"cp","-ip",0}
execvp(cmd[0],cmd);
But how can I even using execvp to specify the argv[1] which is file1 and argv[2] which is file2
Here is the prototype of the execl function:
int execl(const char *path, const char *arg, ...
/* (char *) NULL */);
So it take in parameters the path to the binary, and then the arguments.
The binary you want to use is cp, so, the path will be /bin/cp (you can use whereis cp to find the binary location).
And then you juste have to pass the arguments needed by cp.
Like this for exemple:
int main(int argc, char **argv)
{
execl("/bin/cp", "-i", "-p", argv[1], argv[2], (char *)0);
}
To have the cp interactive prompt, you have to call cp from a shell. To simulate this you can call your command with sh. You can use directly the system function, or use the functions from the execl family.
int main(int argc, char **argv)
{
char *cmd;
if (asprintf(&cmd, "cp -ip %s %s", argv[1], argv[2]) == -1)
return (1);
execlp("sh", "sh", "-c" , cmd, (char *)0);
}

How to create a file using execl command in c

#include<stdio.h>
#include<unistd.h>
#include<string.h>
#define MAXLINIE 100
main(int argc, char* argv[]) {
if (fork()==0){
execl("/bin/> temporar.txt", "/bin/> temporar.txt", ">temporar.txt", NULL);
}
}
Basically, what I am trying to do is creating a file using a process in unix, here is my code, but for some reason it does not work, I do not really understand the execl command and why the first two parameters have to be the same: execl("/bin/ls", "/bin/ls", "-l", NULL); this is working well, could someone help me ?
Thanks a lot!
first search whereis is touch:
~$ whereis touch
touch: /bin/touch /usr/bin/touch /usr/bin/X11/touch
use: int execl(const char *path, const char *arg, ...);
execl("/bin/touch", "touch", "filename", NULL);
^ ^ ^ ^
command command argument
path name
arg 0 arg 1
Consider use system() instead:
system("/bin/ls -l > temporar.txt");
Or using execl call /bin/sh to redirect stream:
execl("/bin/sh", "/bin/sh", "-c" , "/bin/ls -l >temporar.txt", NULL);
First parameter of execl is a command to execute, second is a first parameter to be passed to command (argv[0]), third and next - other arguments argv[1] ...

Resources