diff --git a/CMakeLists.txt b/CMakeLists.txt index f30d8e9..bfcf04b 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -7,7 +7,8 @@ add_executable(${exe_name} main.c prompt.c friendlist.c - chat.c) + chat.c + configdir.c) target_link_libraries(${exe_name} curses) diff --git a/configdir.c b/configdir.c index c9f7de8..7d11d02 100644 --- a/configdir.c +++ b/configdir.c @@ -21,71 +21,126 @@ #include #include #include +#include +#include +#include -#ifdef _win32 +#ifdef WIN32 #include +#include #endif #ifdef __APPLE__ -#include #include #include #endif +#include "configdir.h" + +/* + * Retrieves a correct configuration directory, depending on the OS used, with a trailing slash + */ char *get_user_config_dir(void) { - char *user_config_dir; + char *user_config_dir; - #ifdef _win32 + #ifdef WIN32 - char appdata[MAX_PATH]; - HRESULT result = SHGetFolderPath( - NULL, - CSIDL_APPDATA, // TODO: Maybe use CSIDL_LOCAL_APPDATA instead? Not sure. - NULL, - SHGFP_TYPE_CURRENT, - appdata - ) - if (!result) return NULL; + char appdata[MAX_PATH]; + HRESULT result = SHGetFolderPath( + NULL, + CSIDL_APPDATA, + NULL, + SHGFP_TYPE_CURRENT, + appdata + ) + if (!result) return NULL; - user_config_dir = malloc(strlen(appdata) + strlen(CONFIGDIR) + 1); - if (user_config_dir) { - strcpy(user_config_dir, appdata); - strcat(user_config_dir, CONFIGDIR); - } - return user_config_dir; + user_config_dir = malloc(strlen(appdata) + 1); + if (user_config_dir) { + strcpy(user_config_dir, appdata); + } + return user_config_dir; - #elif defined __APPLE__ + #elif defined __APPLE__ - struct passwd *pass = getpwuid(getuid()); - if (!pass) return NULL; - char *home = pass->pw_dir; - user_config_dir = malloc(strlen(home) + strlen("/Library/Application Support") + strlen(CONFIGDIR) + 1); - - if(user_config_dir) { - strcpy(user_config_dir, home); - strcat(user_config_dir, "/Library/Application Support"); - strcat(user_config_dir, CONFIGDIR); - } - return user_config_dir; + struct passwd *pass = getpwuid(getuid()); + if (!pass) return NULL; + char *home = pass->pw_dir; + user_config_dir = malloc(strlen(home) + strlen("/Library/Application Support") + 1); + + if(user_config_dir) { + strcpy(user_config_dir, home); + strcat(user_config_dir, "/Library/Application Support"); + } + return user_config_dir; - #else + #else - if (getenv("XDG_CONFIG_HOME")) { - user_config_dir = malloc(strlen(getenv("XDG_CONFIG_HOME")) + strlen(CONFIGDIR) + 1); - if (user_config_dir) { - strcpy(user_config_dir, getenv("XDG_CONFIG_HOME")); - strcat(user_config_dir, CONFIGDIR); - } - } else { - user_config_dir = malloc(strlen(getenv("HOME")) + strlen("/.config") + strlen(CONFIGDIR) + 1); - if (user_config_dir) { - strcpy(user_config_dir, getenv("HOME")); - strcat(user_config_dir, "/.config"); - strcat(user_config_dir, CONFIGDIR); - } - } - return user_config_dir; + if (getenv("XDG_CONFIG_HOME")) { + user_config_dir = malloc(strlen(getenv("XDG_CONFIG_HOME")) + 1); + if (user_config_dir) { + strcpy(user_config_dir, getenv("XDG_CONFIG_HOME")); + } + } else { + user_config_dir = malloc(strlen(getenv("HOME")) + strlen("/.config") + 1); + if (user_config_dir) { + strcpy(user_config_dir, getenv("HOME")); + strcat(user_config_dir, "/.config"); + } + } + return user_config_dir; - #endif + #endif +} + +/* + * Creates the config directory. + */ +int create_user_config_dir(char *path) +{ + + int mkdir_err; + + #ifdef WIN32 + + char *fullpath = malloc(strlen(path) + strlen(CONFIGDIR) + 1); + strcpy(fullpath, path); + strcat(fullpath, CONFIGDIR); + + mkdir_err = _mkdir(fullpath); + + if (mkdir_err) { + if(errno != EEXIST) return -1; + struct _stat buf; + if(_wstat64(fullpath, &buf)) return -1; + if(!S_ISDIR(buf.st_mode)) return -1; + } + + #else + + mkdir_err = mkdir(path, 0700); + struct stat buf; + + if(mkdir_err) { + if(errno != EEXIST) return -1; + if(stat(path, &buf)) return -1; + if(!S_ISDIR(buf.st_mode)) return -1; + } + + char *fullpath = malloc(strlen(path) + strlen(CONFIGDIR) + 1); + strcpy(fullpath, path); + strcat(fullpath, CONFIGDIR); + + mkdir_err = mkdir(fullpath, 0700); + + if(mkdir_err) { + if(errno != EEXIST) return -1; + if(stat(fullpath, &buf)) return -1; + if(!S_ISDIR(buf.st_mode)) return -1; + } + + #endif + + return 0; } \ No newline at end of file diff --git a/configdir.h b/configdir.h index 441ffda..d9837d7 100644 --- a/configdir.h +++ b/configdir.h @@ -23,5 +23,11 @@ #else #define CONFIGDIR "/toxic/" #endif + +#ifndef S_ISDIR +#define S_ISDIR(mode) (((mode) & S_IFMT) == S_IFDIR) +#endif -char *get_user_config_dir(void); \ No newline at end of file +char *get_user_config_dir(void); + +int create_user_config_dir(char *path); \ No newline at end of file diff --git a/main.c b/main.c index ec439c8..cb0d9e1 100644 --- a/main.c +++ b/main.c @@ -3,11 +3,19 @@ */ #include +#include #include #include #include #include +#ifdef _win32 +#include +#else +#include +#include +#endif + #include "../../core/Messenger.h" #include "../../core/network.h" @@ -332,26 +340,19 @@ int main(int argc, char *argv[]) { int ch; int f_flag = 0; - char *configdir = get_user_config_dir(); - char *default_file = "data"; - int mkdir_err - #ifdef _win32 - mkdir_err = _mkdir(configdir); - #else - mkdir_err = mkdir(configdir, 0700); - #endif - + char *user_config_dir = get_user_config_dir(); char *filename; - if(mkdir_err == -1) { - filename = default_file; + int config_err = create_user_config_dir(user_config_dir); + if(config_err) { + filename = "data"; } else { - filename = malloc(strlen(configdir) + strlen(default_file) + 1); - strcpy(filename, configdir); - strcat(filename, default_file); + filename = malloc(strlen(user_config_dir) + strlen(CONFIGDIR) + strlen("data") + 1); + strcpy(filename, user_config_dir); + strcat(filename, CONFIGDIR); + strcat(filename, "data"); } ToxWindow* a; - int i = 0; for (i = 0; i < argc; ++i) { if (argv[i] == NULL) @@ -378,6 +379,13 @@ int main(int argc, char *argv[]) "defaulting to 'data' for a keyfile...\n"); attroff(COLOR_PAIR(3) | A_BOLD); } + + if(config_err) { + attron(COLOR_PAIR(3) | A_BOLD); + wprintw(prompt->window, "Unable to determine configuration directory!\n" + "defaulting to 'data' for a keyfile...\n"); + attroff(COLOR_PAIR(3) | A_BOLD); + } while(true) { /* Update tox */