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);
}
Related
So i trying to input multiple files in the assigned program.
My input file code is as such:
int read_File(int *hp, int *d, int *s, char t[])
{
FILE *infile;
infile = fopen("input1.txt", "r");
if (!infile)
{
return 0;
}
else
{
fscanf(infile, "%d", hp);
fscanf(infile, "%d", d);
fscanf(infile, "%d", s);
fscanf(infile, "%s", t);
fclose(infile);
return 1;
}
i did
$>gcc assignedProgram.c -o nqt
$>./nqt input1.txt
but if i want to read input2.txt, i have to change from input1.txt to input2.txt in the codes. Is there anyway to bypass that and read input2.txt without changing from input1.txt to input2.txt in the codes
like when i tried ./nqt input1.txt => it's normal
BUT ./nqt input2.txt it's segmentation fault:11
I tried:
to change "input1.txt" in the codes to "nqt" but that was a dumb idea
and BTW: what is ./nqt
Please help me!
You must write main() as one of the equivalent forms below
int main(int argc, char **argv) { /*...*/ }
int main(int argc, char *argv[]) { /*...*/ }
so that argc and argv are set up by your environment to proper values.
For example
$ ./nqt input.txt
^^^^^ ^^^^^^^^^ --> 1
\\\\\-------------> 0
Translates in your program to
argc == 2
argv[0] ==> pointer to "./nqt"
argv[1] ==> pointer to "input.txt"
argv[2] ==> NULL
When it comes to nqt, it is the name of the program you specified with -o flag when compiling: gcc assignedProgram.c -o nqt. In order to run the program, you need to use ./ prefix, thus ./nqt means "run the program called nqt".
If you want to pass the name of the file as an argument, you should tell main function to accept command line arguments: int argc and char* argv[] (you can read about it here). Then the name of the file you will pass by running ./nqt <filename> would be stored in argv[1], which you should pass to read_File function as an argument.
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 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.
#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] ...
How do I read command-line parameters in C? For example, in
./test --help
or
./test --build
how do I access "--build" or "--help"?
Your parameters are in argv:
int main(int argc, char **argv)
if you printf the content of argv (argv[0],argv[1] etc) youll get the idea.
try:
int main (int argc, char **argv)
{
for(int i = 0;i< argc;i++)
printf("%s\r\n",argv[i]);
}
You can use the argc and argv arguments to the main function and do different things based on them:
#include <string.h>
void dohelp(void) { /* whatever; */ }
void dobuild(void) { /* whatever; */ }
int main(int argc, char **argv) {
if (argc == 2) {
if (!strcmp(argv[1], "--help")) dohelp();
if (!strcmp(argv[1], "--build")) dobuild();
}
return 0;
}
argc contains the number of parameters passed by the shell to your program, including the program name. So myapp --help gets an argc of 2.
argv are the arguments themselves. The last argv (argv[argc]) is the NULL pointer.
Edit: the parameters don't need to be named argc and argv, but naming else something else is very, very bad!
int main(int foo, char **bar) /* RGAGGGGHH */
int main(int n, char **options) /* RGAGGGGHH */
The very basic is to use the arguments (int argc, char *argv[]) and you can parse those directly.
One more advanced method is to use getopt... http://www.gnu.org/s/libc/manual/html_node/Getopt.html
Command line arguments are arguments passed to your program with its name. For example, the UNIX program cp (copies two files) has the following command line arguments:
cp SOURCE DEST
You can access the command line arguments with argc and argv:
int main(int argc, char *argv[])
{
return 0;
}
argc is the number of arguments, including the program name, and argv is the array of strings containing the arguments. argv[0] is the program name, and argv[argc] is guaranteed to be a NULL pointer.
So the cp program can be implemented as such:
int main(int argc, char *argv[])
{
char *src = argv[1];
char *dest = argv[2];
cpy(dest, src);
}
They do not have to be named argc and argv; they can have any name you want, though traditionally they are called that.
There are several ways to do it [as usual].
Command line arguments are read from argv (passed to main along with argc).
You can parse those yourself and have a bit switch setting flags each time a new option is found in argv. Or you can use a library to parser command line arguments. I suggest libc getopt (google it).