I am trying to copy and rename a file using a system call to cp
. The problem is that the command gets changed during the call and I cannot figure out how to fix it.
char *cp=(char*) malloc(100);
snprintf(cp,100,"%s%s%s","cp ~/.nanorc ~/.nanocfgmgr/",arg,"\0" );
printf("%s\n",cp);
system(cp);
free(cp);
Executing the string, which should look like cp ~/.nanorc ~/.nanocfgmgr/newfile
, directly in the terminal works as expected, but running the program yields cp: cannot create regular file '/home/user/.nanocfgmgr/.nanocfgmgr/newfile
. I can't figure out why the directory gets duplicated. Thank for any help.
EDIT: example
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <argp.h>
struct parser_args{
int argc;
char **argv;
int *nargs;
char *path;
};
//where 'cp' is called
int parser(int key,char *arg, struct argp_state *state){
switch(key){
case 's': ;
char *cp=(char*) malloc(100);
snprintf(cp,100,"%s%s%s","cp ~/.nanorc ~/.nanocfgmgr/",arg,"\0" );
printf("arg = [[%s]]\n", arg); printf("cp = [[%s]]\n", cp);
system(cp);
free(cp);
}
return 0;
}
int main(int argc, char **argv){
char path[50]={};
strcpy(path,strcat(getenv("HOME"),"/.nanocfgmgr"));
char cfg_path[50]={};
strcpy(cfg_path, path);
strcat(cfg_path, "/configs.json");
char *mkdir=(char*) malloc(50);
strcpy(mkdir,"mkdir ");
strcat(mkdir,path);
strcat(mkdir," > /dev/null 2>&1");
system(mkdir);
free(mkdir);
struct argp_option options[]={
{"save",'s',"NAME",0,"Backs up the configuration file Usage: nanocfgmr NAME [DESCRIPTION]"},
{0}
};
struct argp argp={options,parser};
struct parser_args *input= (struct parser_args*) malloc(sizeof(struct parser_args));
return argp_parse(&argp,argc,argv,0,0,input);
}
CodePudding user response:
The problem is due to
strcat(getenv("HOME"),"/.nanocfgmgr")
getenv()
doesn't allocate a new string, it returns a pointer to the string in the environment array. When you concatenate to this, you're modifying the environment (you're probably also overwriting the environment variables that follow HOME
).
When the shell processes a filename that begins with ~
, replaces that with the HOME
environment variable variable. Since you've added .nanocfgmgr
to this, your pathnames are expanded relative to that subdirectory.
POSIX specifies that you shouldn't do this concatenation; it says:
The application shall ensure that it does not modify the string pointed to by the
getenv()
function.
It ideally should be declared to return const char *
, then the code won't compile, but there's probably historical reasons why it's not.
You can use snprintf()
instead of strcat()
, then you won't modify the environment.
snprintf(path, sizeof path, "%s/.nanocfgmgr", getenv("HOME"));