#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] ...
Related
I have spent the last 2 days trying to understand the execlp() system call, but yet here I am. Let me get straight to the issue.
The man page of execlp declares the system call as int execlp(const char *file, const char *arg, ...); with the description: The const char arg and subsequent ellipses in the execl(), execlp(), and execle() functions can be thought of as arg0, arg1, ..., argn.
Yet I see the system call being called like this in our text book: execlp(“/bin/sh”, ..., “ls -l /bin/??”, ...); (the "..." are for us to figure out as students). However this system call doesn´t even resemble anything like the declaration on the man page of the system call.
I am super confused. Any help is appreciated.
this prototype:
int execlp(const char *file, const char *arg, ...);
Says that execlp ìs a variable argument function. It takes 2 const char *. The rest of the arguments, if any, are the additional arguments to hand over to program we want to run - also char * - all these are C strings (and the last argument must be a NULL pointer)
So, the file argument is the path name of an executable file to be executed. arg is the string we want to appear as argv[0] in the executable. By convention, argv[0] is just the file name of the executable, normally it's set to the same as file.
The ... are now the additional arguments to give to the executable.
Say you run this from a commandline/shell:
$ ls
That'd be execlp("ls", "ls", (char *)NULL);
Or if you run
$ ls -l /
That'd be execlp("ls", "ls", "-l", "/", (char *)NULL);
So on to execlp("/bin/sh", ..., "ls -l /bin/??", ...);
Here you are going to the shell, /bin/sh , and you're giving the shell a command to execute. That command is "ls -l /bin/??". You can run that manually from a commandline/shell:
$ ls -l /bin/??
Now, how do you run a shell and tell it to execute a command ? You open up the documentation/man page for your shell and read it.
What you want to run is:
$ /bin/sh -c "ls -l /bin/??"
This becomes
execlp("/bin/sh","/bin/sh", "-c", "ls -l /bin/??", (char *)NULL);
Side note:
The /bin/?? is doing pattern matching, this pattern matching is done by the shell, and it expands to all files under /bin/ with 2 characters. If you simply did
execlp("ls","ls", "-l", "/bin/??", (char *)NULL);
Probably nothing would happen (unless there's a file actually named /bin/??) as there's no shell that interprets and expands /bin/??
The limitation of execl is that when executing a shell command or any other script that is not in the current working directory, then we have to pass the full path of the command or the script.
Example:
execl("/bin/ls", "ls", "-la", NULL);
The workaround to passing the full path of the executable is to use the function execlp, that searches for the file (1st argument of execlp) in those directories pointed by PATH:
execlp("ls", "ls", "-la", NULL);
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"
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 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.
I have spent the last 2 days trying to understand the execlp() system call, but yet here I am. Let me get straight to the issue.
The man page of execlp declares the system call as int execlp(const char *file, const char *arg, ...); with the description: The const char arg and subsequent ellipses in the execl(), execlp(), and execle() functions can be thought of as arg0, arg1, ..., argn.
Yet I see the system call being called like this in our text book: execlp(“/bin/sh”, ..., “ls -l /bin/??”, ...); (the "..." are for us to figure out as students). However this system call doesn´t even resemble anything like the declaration on the man page of the system call.
I am super confused. Any help is appreciated.
this prototype:
int execlp(const char *file, const char *arg, ...);
Says that execlp ìs a variable argument function. It takes 2 const char *. The rest of the arguments, if any, are the additional arguments to hand over to program we want to run - also char * - all these are C strings (and the last argument must be a NULL pointer)
So, the file argument is the path name of an executable file to be executed. arg is the string we want to appear as argv[0] in the executable. By convention, argv[0] is just the file name of the executable, normally it's set to the same as file.
The ... are now the additional arguments to give to the executable.
Say you run this from a commandline/shell:
$ ls
That'd be execlp("ls", "ls", (char *)NULL);
Or if you run
$ ls -l /
That'd be execlp("ls", "ls", "-l", "/", (char *)NULL);
So on to execlp("/bin/sh", ..., "ls -l /bin/??", ...);
Here you are going to the shell, /bin/sh , and you're giving the shell a command to execute. That command is "ls -l /bin/??". You can run that manually from a commandline/shell:
$ ls -l /bin/??
Now, how do you run a shell and tell it to execute a command ? You open up the documentation/man page for your shell and read it.
What you want to run is:
$ /bin/sh -c "ls -l /bin/??"
This becomes
execlp("/bin/sh","/bin/sh", "-c", "ls -l /bin/??", (char *)NULL);
Side note:
The /bin/?? is doing pattern matching, this pattern matching is done by the shell, and it expands to all files under /bin/ with 2 characters. If you simply did
execlp("ls","ls", "-l", "/bin/??", (char *)NULL);
Probably nothing would happen (unless there's a file actually named /bin/??) as there's no shell that interprets and expands /bin/??
The limitation of execl is that when executing a shell command or any other script that is not in the current working directory, then we have to pass the full path of the command or the script.
Example:
execl("/bin/ls", "ls", "-la", NULL);
The workaround to passing the full path of the executable is to use the function execlp, that searches for the file (1st argument of execlp) in those directories pointed by PATH:
execlp("ls", "ls", "-la", NULL);