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.
Related
default setting
setting changed.
How can I set this in command line?
I'm going to write a c program using system() call.
Thank you.
You can find some documentation on archlinux: https://wiki.archlinux.org/index.php/Vino
From a command line, you would have to type:
gsettings set org.gnome.Vino vnc-password $(echo -n 'mypasswd'|base64)
So, the equivalent C source should be:
#include <stdlib.h>
#include <stdio.h>
int main(int argc, char *argv[])
{
char command[256];
sprintf(command, "gsettings set org.gnome.Vino vnc-password $(echo -n '%s'|base64)", argv[1]);
system(command);
return 0;
}
Note that this code lakes at least:
test that the program is called with one parameter
use snprintf instead of sprintf (to prevent writing to much data in command)
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"
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.
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 shell scripts and I need to run that continuous work in background.
For example:
#include <stdio.h>
int main(int argc, char **argv)
{
for (; ;) {
system("./dup -r /root/duptest/");
sleep(60);
}
return 0;
}
It's working and run every minute.
First question: How can I run this background(like & --> ./dup ... &) without put &.
Second question: How can I put shell codes in C source codes?
I found this, Do I need to put \n\ for all lines? It's so hard for edit.
#include <stdio.h>
#include <stdlib.h>
#define SHELLSCRIPT "\
#/bin/bash \n\
echo \"hello\" \n\
echo \"how are you\" \n\
echo \"today\" \n\
"
int main()
{
system(SHELLSCRIPT);
return 0;
}
Third question: How can I use shell parameter in C, like this:
./dup.exe -r /blablabla...
mean
system("./dup -r /blablabla");
I need to use $1 $2 parameter with compiled C program.
Question 1: Look for "how to make a process as deamon process in UNIX" Although daemon process is a overkill for your requirement, you can perform steps until the process is running according to your requirements
Question 3: You need to have command line arguments, check about that. Your main should look like main(int arg_count, char *args_vector[]){...} and in that you can access each command line argument as an array element
Q1: use fork() and don't wait on the child's PID.
Q2: C and C++ will concatenate adjacent string literals, like so:
static const char script[] =
"echo hello\n"
"echo how are you\n"
"echo today"
;
int main(int argc, char* argv[])
{
puts(script); // so you can see what it looks like
// system(script); // <-- uncomment this line to actually run it.
return 0;
}
Q3: use the argc and argv parameters to main() to build the command line you want to execute.