I need to run source command from c++ program and pass filename and also some arguments. Is it possible? I want to use them in script like command line arguments (with argc, argv0, ...). http://www.astro.princeton.edu/~rhl/Tcl-Tk_docs/tcl/source.n.html here is not specified how to do it.
When doing this from C or C++, you should:
Initialise the Tcl library and create a Tcl interpreter.
Set the global variables argv0, argv and argc to the values expected by a normal Tcl script. This is exactly what tclsh does; the variables are entirely ordinary apart from being initialised this way.
argv0 is the name of the “main” script, which might be the script you're about to source.
argv is a Tcl list of all the other arguments; argc is the length of that list.
Use Tcl_FSEvalFileEx(interp,pathPtr,encoding) to execute the file; the source command is a very thin wrapper around that call. You probably want to pass the encoding argument as NULL, and the pathPtr argument is a Tcl_Obj reference.
If your script accepts the arguments in argv, just set this variable before you source this script.
But if this script calls exit, it will terminate the entire process, usually not what you want. You could use a slave interp to avoid this.
There are 3 predefined variables:
$argc - number items of arguments passed to a script.
$argv - list of the arguments.
$argv0 - name of the script.
So in your case, assuming the file sourced is in the same directory and its name is passed as a first argument:
source [lindex $argv 0]
Related
I have an executable, a.out which takes several command-line arguments. This executable needs to be run with root privileges, like sudo ./a.out arg1 arg2 ... .
How should I do this using the execvp system call in C++ ?
char *args[5];
args[0]="sudo";
args[1]="./a.out";
args[2]="arg1";
args[3]="arg2";
args[4]=NULL;
execvp("sudo", args);
The shell splits the given command into whitespace-delimited words. The first word gets looked up in PATH, and all the words are passed as parameters to the command.
Sinec execvp() will search the PATH for you, you can simply pass "sudo" as the command, then the arguments to the command. Note that the first argument to the command is the command's name.
The command you're executing is "sudo", so that's the first argument; then the remaining words as individual arguments, passed as an array.
This is not working: ?
execvp("/usr/bin/sudo", "./a.out arg1 erg2").
What exactly does execve() do? I've tried looking at the documentation (http://linux.die.net/man/2/execve) but given that I'm very new to linux and this sort of programming it doesn't make a lot of sense. What I want to do is be able to execute this command:
nc -l -p someport -e /bin/sh
Can I do something like the following (where someport is a number such as 4444)
char *command[2];
command[0] = "nc -l -p someport -e /bin/sh"
execve(command[0], name, NULL);
execve asks the operating system to start executing a different program in the current process.
Chances are pretty decent that you want execvp or execlp instead -- you haven't mentioned anything about wanting to provide the environment for the child, but from the looks of things you probably do want the path searched to find the executable you're using.
Correct usage is
extern char * const environ[];
char * const command[] = {"nc", "-l", "-p", "porthere", "-e", "/bin/sh", NULL};
execve("/usr/bin/nc", command, environ);
You must use a full pathname, not a short name such as "nc" (more precisely: no PATH search is done, the pathname must be an actual existing file), and you must split arguments into separate strings beforehand. You also need to propagate the environment somehow, either via the extern environ mentioned in the above snippet or as obtained from the third parameter of main(); the latter is slightly more standards-blessed but may be more painful to pass around as needed.
I need a to be able to use some of the process control facilities provided by posix_spawn() like suspend/resume/kill etc, something that system() does not give me.
So use the following call to posix_spawn() to launch a shell script from a c++ program:
int result = posix_spawn(&spawnedPid, processExecutable, 0, 0, argumentList, 0);
where processExecutable is "foo.sh" and argumentList is {"bar",0,0,0}; The process foo.sh starts up just fine, except for the argumentList part. If I do something like "echo $1" in foo.sh, I get an empty string. If I launch a binary the same way, the arguments are just fine and I can reach them via argv[]. Is there anything I should be doing differently in order to pass arguments to foo.sh ?
Shame on me, the argumentList parameter of posix_spawn() is 0-based so echo $1 actually outputs argumentList[1], which is, naturally, set to 0. Case closed.
On a Linux platform, I have C++ code that goes like this:
// ...
std::string myDir;
myDir = argv[1]; // myDir is initialized using user input from the command line.
std::string command;
command = "mkdir " + myDir;
if (system(command.c_str()) != 0) {
return 1;
}
// continue....
Is passing user input to a system() call safe at all?
Should the user input be escaped / sanitized?
How?
How could the above code be exploited for malicious purposes?
Thanks.
Just don't use system. Prefer execl.
execl ("/bin/mkdir", "mkdir", myDir, (char *)0);
That way, myDir is always passed as a single argument to mkdir, and the shell isn't involved. Note that you need to fork if you use this method.
But if this is not just an example, you should use the mkdir C function:
mkdir(myDir, someMode);
Using system() call with command line parameters without sanitizing the input can be highly insecure.
The potential security threat could be a user passing the following as directory name
somedir ; rm -rf /
To prevent this , use a mixture of the following
use getopt to ensure your input is
sanitized
sanitize the input
use execl instead of system to execute
the command
The best option would be to use all three
Further to Matthew's answer, don't spawn a shell process unless you absolutely need it. If you use a fork/execl combination, individual parameters will never be parsed so don't need to be escaped. Beware of null characters however which will still prematurely terminate the parameter (this is not a security problem in some cases).
I assume mkdir is just an example, as mkdir can trivially be called from C++ much more easily than these subprocess suggestions.
Reviving this ancient question as I ran into the same problem and the top answers, based on fork() + execl(), weren't working for me. (They create a separate process, whereas I wanted to use async to launch the command in a thread and have the system call stay in-process to share state more easily.) So I'll give an alternative solution.
It's not usually safe to pass user input as-is, especially if the utility is designed to be sudo'd; in order to sanitize it, instead of composing the string to be executed yourself, use environment variables, which the shell has built-in escape mechanisms for.
For your example:
// ...
std::string myDir;
myDir = argv[1]; // myDir is initialized using user input from the command line.
setenv("MY_DIR", myDir, 1);
if (system("mkdir \"${MY_DIR}\"") != 0) {
return 1;
}
// continue....
I am using execv() to run commands from /bin/ such as 'ls', 'pwd', 'echo' from my c++ program, and I am wondering what value I should provide in argv[0];
const char * path = getPath();
char ** argv = getArgs();
execv(path,argv);
argv[0] is supposed to be the program name. It's passed to the program's main function. Some programs differentiate their behavior depending on what string argv[0] is. For example the GNU bash shell will disable some of its features if called using sh instead of bash. Best give it the same value that you pass to path.
In linux, argv[0] is the process name displayed by the top utility (which it probably gets from reading entries in /proc/)
argv[0] should be the full path of the command that you want to run.
I know that this is not the answer you're looking for but is there a specific reason why you're doing this? The reason I ask is that most if not all of the actions people normally run with either system() or execv() are available in libraries on either Windows or Unix and are safer, faster and less likely to suffer from circumstantial errors. By that I mean, for example, when the PATH changes and suddenly your code stops working.
If you're passing in a string, either in whole or in part, and running it then you also leave yourself open to a user gaining access to the system by entering a command that could be damaging. E.g. imagine you've implemented a file search using find /home -name and your user types in:
"%" -exec rm {} \;
Ouch!