简体   繁体   中英

changing command line arguments

I am writing a C program. It takes its arguments from commandLine. I want to change the commandLine arguments in the code. As they are defined as "const char *", I can not change them using "strcpy", "memcpy", ... Also, you know, I can not just change their type from "const char *" to "char *". Is there any way to change them?

Thank you so much in advance.

Best regards, Shadi.

According to C99 §5.1.2.2.1/1, the signature for main is

int main(int argc, char *argv[]) { /* ... */ }

So you are allowed to remove the const . Just don't cause a buffer overrun by strcpy ing in longer strings than the original arguments, or attempting to install more arguments than originally passed.

Everyone else is basically right that you should create a copy instead.

No, you are not allowed to modify those. However, there's no rule against copying them to a new buffer and using those instead.

This may be beside the point, but you can't change anything with neither strcpy() nor memcpy(); the suffix 'cpy' is short for copy (unsurprisingly.)

Regarding changing the argv pointer, you could of course change the pointer, but why? If you want the command line arguments to be something other than what's given, just ignore them, and use whatever values you prefer. Also note that argv is a parameter and thus local to main(); if it is needed elsewhere, you have to either pass it as a parameter, or save it as a global variable.

It doesn't matter if you change the const char * to char * of main function.

Only one thing you must care about is buffer overrunning of strcpy.

According to ELF spec(see figure 3-31 stack layout), http://refspecs.linuxbase.org/elf/abi386-4.pdf , function parameter area is followed by environment value area.

argv is array of pointers to each parameter, and environ is also array of pointers to each environment var=value string. So layout is like below.

argv[0]  --> 1st parameter
argv[1]  --> 2nd parameter
argv[2]  --> 3rd parameter
...
NULL
--------------------------------------- memory boundary between param and env
environ[0] --> 1st env_var=env_value
environ[1] --> 2nd env_var=env_value
environ[2] --> 3rd env_var=env_value
...
NULL

So if you copy very long string to argv[0], it can overrun the boundary between param and env. In this case, you must move argv and environ memory area to another heap space like below. I extracted below example code from Postgresql open source code. ps_status.c)

char ** new_environ;
char ** new_argv;
char ** org_argv;
int     i;

new_argv = (char **) malloc((argc + 1) * sizeof(char *));
for (i = 0; i < argc; i++)
    new_argv[i] = strdup(argv[i]);
new_argv[argc] = NULL;
org_argv = argv;
argv = new_argv;

new_environ = (char **) malloc((i + 1) * sizeof(char *));
for (i = 0; environ[i] != NULL; i++)
    new_environ[i] = strdup(environ[i]);
new_environ[i] = NULL;
environ = new_environ;

Then, you can use getopt, getenv, etc. They will read the values from newly allocated memory area. In addition, if you change original parameter(org_argv[0]), you can manipulate the output name of your process in ps command. (also in top, htop utility) See below.

$> ps -ef | grep my_proc
  dplee 10855 1 0 7월28 pts/2 00:00:16 my_proc i can manipulate this name

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM