Find argc and argv from a library
This response in your second link contains working source code which worked fine for me (Gnu/Linux elf-based system), including during LD_PRELOAD
.
The code is very short; it consists of a function:
int foo(int argc, char **argv, char **env) {
// Do something with argc, argv (and env, if desired)
}
and a pointer to that function in the .init_array
section:
__attribute__((section(".init_array"))) static void *foo_constructor = &foo;
Putting that into a shared library and then LD_PRELOADing the shared library certainly triggered the call to foo
when I tried it, and it was clearly called with the argc
and argv
which would later be passed to main
(and also the value of environ
).
Argc and argv for external program calling C shared library
The cmd_args
module only parses verbose
, quiet
, output
and max-memory
arguments. Assuming only output
is relevant for you, you could set the values with PySys_SetArgv
just after Py_Initialize()
.
char **argv = {"", "-o", "path/to/output/file"};
PySys_SetArgv(3, argv);
Parse string into argv/argc
If glib solution is overkill for your case you may consider coding one yourself.
Then you can:
- scan the string and count how many arguments there are (and you get your argc)
- allocate an array of char * (for your argv)
- rescan the string, assign the pointers in the allocated array and replace spaces with '\0' (if you can't modify the string containing the arguments, you should duplicate it).
- don't forget to free what you have allocated!
The diagram below should clarify (hopefully):
aa bbb ccc "dd d" ee <- original string
aa0bbb0ccc00dd d00ee0 <- transformed string
| | | | |
argv[0] __/ / / / /
argv[1] ____/ / / /
argv[2] _______/ / /
argv[3] ___________/ /
argv[4] ________________/
A possible API could be:
char **parseargs(char *arguments, int *argc);
void freeparsedargs(char **argv);
You will need additional considerations to implement freeparsedargs() safely.
If your string is very long and you don't want to scan twice you may consider alteranatives like allocating more elements for the argv arrays (and reallocating if needed).
EDIT: Proposed solution (desn't handle quoted argument).
#include <stdio.h>
static int setargs(char *args, char **argv)
{
int count = 0;
while (isspace(*args)) ++args;
while (*args) {
if (argv) argv[count] = args;
while (*args && !isspace(*args)) ++args;
if (argv && *args) *args++ = '\0';
while (isspace(*args)) ++args;
count++;
}
return count;
}
char **parsedargs(char *args, int *argc)
{
char **argv = NULL;
int argn = 0;
if (args && *args
&& (args = strdup(args))
&& (argn = setargs(args,NULL))
&& (argv = malloc((argn+1) * sizeof(char *)))) {
*argv++ = args;
argn = setargs(args,argv);
}
if (args && !argv) free(args);
*argc = argn;
return argv;
}
void freeparsedargs(char **argv)
{
if (argv) {
free(argv[-1]);
free(argv-1);
}
}
int main(int argc, char *argv[])
{
int i;
char **av;
int ac;
char *as = NULL;
if (argc > 1) as = argv[1];
av = parsedargs(as,&ac);
printf("== %d\n",ac);
for (i = 0; i < ac; i++)
printf("[%s]\n",av[i]);
freeparsedargs(av);
exit(0);
}
Parsing Command Line Arguments in C++?
Boost.Program_options should do the trick
Related Topics
How to Read Linux File Permission Programmatically in C/C++
Iterate Through Struct and Class Members
In Which Order Should Floats Be Added to Get the Most Precise Result
Difference Between Char* and Char[]
Why Istream Object Can Be Used as a Bool Expression
"Undefined Reference To" Using 'G++' to Compile a C++ Program
How to Write Custom Input Stream in C++
How to Decode the Boost Library Naming
Colour Output of Program Run Under Bash
How to Get Memory Information on Linux System
When Are Static and Global Variables Initialized
Std::Fstream Doesn't Create File
When to Use the Brace-Enclosed Initializer