I am writing a program in C as below
char *msg = "Do you want to overwrite existing data in config file? (Y/n) [n] : ";
// if (!fexists(CONFFILE)) { // Doesnt work if uncommented
// msg = "Do you want to save data to config file? (Y/n) [n] : "; // Doesnt work if uncommented
// } // Doesnt work if uncommented
struct arguments arguments;
arguments.a = "vala";
arguments.b = "valb";
arguments.c = "valc";
argp_parse (&argp, argc, argv, 0, 0, &arguments);
printf("%s", msg);
char ans = getchar();
if ((ans == 'y') || (ans == 'Y')) {
CONFIG cfg = {a, b, c};
create_config(cfg); //The function that stops working
if (!fexists(CONFFILE)) {
printf("Saved credentials to config file.\n");
} else {
printf("Err: Unable to save " CONFFILE)
}
} else {
printf("Not saving credentials to config file.\n");
}
fexists(), create_config() are confirmed to be working as intended.
bool fexists(char *fname) {
struct stat buffer;
return (stat (fname, &buffer) == 0);
}
int create_config(struct config cfg) {
struct json_object *jsonobj = json_object_new_object();
json_object_object_add(jsonobj, "api", json_object_new_string(cfg.api));
json_object_object_add(jsonobj, "key", json_object_new_string(cfg.key));
json_object_object_add(jsonobj, "domain", json_object_new_string(cfg.domain));
return json_object_to_file_ext(CONFFILE, jsonobj, JSON_C_TO_STRING_SPACED | JSON_C_TO_STRING_PRETTY);
}
create_config() [and the program] works as intended if the above if
statement is commented but stops working if uncommented.
Is there any mistake in my code? What is the solution for this?
EDIT: minimal program to reproduce the issue
// Compile with gcc -ljson-c
// libjson-c-dev is required
#include <stdio.h>
#include <string.h>
#include <stdbool.h>
#include <sys/stat.h>
#include <json-c/json.h>
#include <json-c/json_object.h>
#include <json-c/json_util.h>
struct config {
char *a;
char *b;
char *c;
};
#ifdef _WIN32
#define CONFFILE strcat(getenv("LOCALAPPDATA"), "/.conf.json")
#else
#define CONFFILE strcat(getenv("HOME"), "/.conf.json")
#endif
int create_config(struct config cfg) {
struct json_object *jsonobj = json_object_new_object();
json_object_object_add(jsonobj, "a", json_object_new_string(cfg.a));
json_object_object_add(jsonobj, "b", json_object_new_string(cfg.b));
json_object_object_add(jsonobj, "c", json_object_new_string(cfg.c));
int retval = json_object_to_file_ext(CONFFILE, jsonobj, JSON_C_TO_STRING_SPACED | JSON_C_TO_STRING_PRETTY);
printf("Err: %s\n", json_util_get_last_err());
return retval;
}
bool fexists(char *fname) {
struct stat buffer;
return (stat (fname, &buffer) == 0);
}
int main(){
char *msg = "Do you want to create conffile? (y/n) ";
// if (!fexists(CONFFILE)) { // Comment these to fix
// msg = "Do you want to overwrite conffile? (y/n) "; // Comment these to fix
// } // Comment these to fix
printf("%s", msg);
if (((a=getchar()) == 'y') || (a == 'Y')){
char *a = "vala";
char *b = "valb";
char *c = "valc";
struct config cfg = {a, b, c};
printf("%d", create_config(cfg));
}
}
libjson-c-dev is required to compile the program
EDIT2: error message is now printed.
Err: json_object_to_file: error opening file /home/user/.conf.json/.conf.json: No such file or directory
CodePudding user response:
Caught the issue...
It wasn't related to if loop. Instead it was the incorrect usage of getenv("XXX")
#ifdef _WIN32
#define CONFFILE strcat(getenv("LOCALAPPDATA"), "/.conf.json")
#else
#define CONFFILE strcat(getenv("HOME"), "/.conf.json")
#endif
is wrong as the value returned by getenv("XXX") gets modified and further calls to getenv will return incorrect value.
#ifdef _WIN32
char* confdir = getenv("LOCALAPPDATA");
#else
char* confdir = getenv("HOME");
#endif
char* conffile = malloc(sizeof(confdir) sizeof("/.conf.json") 1);
strcpy(conffile, confdir);
strcat(conffile, "/.conf.json");
// And use conffile variable instead of CONFFILE macro.
So the example code will change to
// Compile with gcc -ljson-c
// libjson-c-dev is required
#include <stdio.h>
#include <string.h>
#include <stdbool.h>
#include <sys/stat.h>
#include <json-c/json.h>
#include <json-c/json_object.h>
#include <json-c/json_util.h>
struct config {
char *a;
char *b;
char *c;
};
int create_config(struct config cfg, char* conffile) {
struct json_object *jsonobj = json_object_new_object();
json_object_object_add(jsonobj, "a", json_object_new_string(cfg.a));
json_object_object_add(jsonobj, "b", json_object_new_string(cfg.b));
json_object_object_add(jsonobj, "c", json_object_new_string(cfg.c));
int retval = json_object_to_file_ext(conffile, jsonobj, JSON_C_TO_STRING_SPACED | JSON_C_TO_STRING_PRETTY);
printf("Err: %s\n", json_util_get_last_err());
return retval;
}
bool fexists(char *fname) {
struct stat buffer;
return (stat (fname, &buffer) == 0);
}
int main(){
ifdef _WIN32
char* confdir = getenv("LOCALAPPDATA");
#else
char* confdir = getenv("HOME");
#endif
char* conffile = malloc(sizeof(confdir) sizeof("/.conf.json") 1);
strcpy(conffile, confdir);
strcat(conffile, "/.conf.json");
char *msg = "Do you want to create conffile? (y/n) ";
if (!fexists(conffile)) { // Now this works
msg = "Do you want to overwrite conffile? (y/n) "; // Now this works
} // Now this works
printf("%s", msg);
if (((a=getchar()) == 'y') || (a == 'Y')){
char *a = "vala";
char *b = "valb";
char *c = "valc";
struct config cfg = {a, b, c};
printf("%d", create_config(cfg, conffile));
}
}