Duplicating an array of strings (or copying them to another array)?

I need arguments that were passed to my process when it was started. This means that argv[] I need everything except the first (this is my process name).

I'm having trouble copying because it is of type char * argv[] . Can someone give me an idea of ​​how to do this correctly, or perhaps a small piece of code. I would rather have banged my head on the wall.

EDIT:

Clarification of my problem:

The key point is that I need everything except the first argv argument. Therefore, I can’t just send it to other processes, as I actually use it as an argument to execv.

+4
source share
8 answers

You wrote in the comment "My first program would have a list of arguments" pname otherpname -arg1 -arg2 -arg3 ", and I want to use execv to call otherpname with -arg1 -arg2 -arg3." In this case, the argument list you want to pass to execv is [otherpname -arg1 -arg2 -arg3] ... the argument list passed to execv is exactly what mainpute mainpeat will see as argv, and it should include argv [ 0], which is usually the name of the program. Conveniently, this list is exactly what argv + 1 indicates that ... nothing needs to be copied.

[edit] However, you have a problem with passing execv as the first argument - the name of the program file for exec. Any other name must be a fully qualified path, or you must use execvp, which looks for PATH for the program.

+3
source

It makes no sense to copy lines - they will be preserved throughout the life of the program, and you are not allowed to change them. Just pass argc and argv to everyone who needs them, or copy them into global variables.

 #include <stdio.h> int myargc; char **myargv; void print_args() { int i; for (i = 1; i < myargc; ++i) { puts(myargv[i]); } } int main(int argc, char **argv) { myargc = argc; myargv = argv; print_args(); return 0; } 
+5
source

Note that argv is char ** , if necessary, you can just save the argv pointer to a global variable of this type.

Otherwise, to copy it, you need to select the array and copy the pointers. If you also don't need to copy the lines themselves, something like this should work:

 char **copy_of_argv = malloc(sizeof(char *) * (argc-1)); memcpy(copy_of_argv, argv + 1, sizeof(char *) * (argc - 1)); 

(although you may or may not want to allocate an extra slot in copy_of_argv to designate a NULL pointer as a sentinel).

If you need to copy lines for an unknown reason, this is a little more complicated:

 int i; char **copy_of_argv = malloc(sizeof(char *) * (argc-1)); for (i = 0; i < argc - 1; i++) { copy_of_argv[i] = strdup(argv[i + 1]); } 

(again, you can allocate an additional slot for the sentinel device).

+3
source

If you need a modifiable copy of the arguments, follow these steps:

  #include <stdio.h> void main(int argc, char** argv) { int myargc = argc; char** myargv = malloc( (argc-1)*sizeof(void*)); int i; for(i=1; i<argc; i++) { int len = strlen(argv[i]); myargv[i-1] = malloc(len+1); memcpy(myargv[i-1], argv[i], len+1); // +1 so \0 copied too. } getch(); } 
+2
source

Interestingly, you should say:

The key point is that I need everything except the first argv argument. So I can’t just send it to other processes, as I actually use it as an execv argument

This is very similar to what I do when I want to set LD_LIBRARY_PATH and then run the binary using my own copy of ld.so, so that the common shared libraries by default will not be used. The argument for execve is my copy of ld.so, but after running the real binaries, I want argv to look normal (and the environment). Here's how I did it on Linux:

 include <stdlib.h> #include <stdio.h> #define PYBINARY "/data1/packages/python272/bin/python" #define LDSO "/data1/packages/python272/lib/ld-linux-x86-64.so.2" #define MYLIBS "/data1/packages/python272/lib" extern char **environ; main(int argc, char **argv, char **envp) { int retcode; char **e; char **myargv; setenv("LD_LIBRARY_PATH",MYLIBS,1); setenv("_",PYBINARY,1); /* copy argv */ int i = 0; myargv = (char **)malloc(sizeof(char *) * 100); for(;argv[i] != NULL; i++) { myargv[i+1] = (char *)malloc(sizeof(char) * (strlen(argv[i]) + 1)); memcpy(myargv[i+1], argv[i], strlen(argv[i])); } myargv[i+1] = NULL; myargv[0] = LDSO; myargv[1] = PYBINARY; e = myargv; while (*e != NULL){ printf("arg: %s\n",*e++); } retcode = execve(LDSO, myargv, environ); perror("exec2: execve() failed"); exit(1); } 

If you put this in test.py:

 import sys print sys.argv import os print os.environ["_"] 

and run it with python -i test.py , you will get the same results as ./mypy -i test.py , so nothing that depends on argv or envp will be broken.

+1
source

If you want to access one of the argv lines, follow these steps:

printf ("% s", argv [0]);

0
source

What exactly do you need to do with the arguments?

arg 1 , arg [2], arg [3] ... etc. are simple strings of C (char *).

If you need to copy them to another array, you can use strcpy (for example, strcpy(destination,arg[1]) , but since the parameter values ​​will not change, you most likely will not have to copy it.

0
source

For execv, something like this, then

 #include <stdlib.h> #include <unistd.h> int main(int argc, char **argv) { int i; char** myargs; if (argc <= 0) { return EXIT_FAILURE; } myargs = malloc(sizeof *myargs * (argc + 1)); myargs[0] = "your_program_name_here"; for (i = 1; i < argc; ++i) { myargs[i] = argv[i]; } myargs[argc] = 0; execv("/your/program/here", myargs); return EXIT_FAILURE; } 
0
source

Source: https://habr.com/ru/post/1342452/


All Articles