Skip to content

Commit

Permalink
feat: config files are now tied to tox data files by default
Browse files Browse the repository at this point in the history
Instead of using the same default config file for every profile
we now use the same name and path as the custom tox profile
(with a .conf file extension), and create an empty config file
if it doesn't already exist. In addition, if the user passes a
non-existent file as a run option, we now create an empty file
instead of returning an error.

Behaviour should not be changed for default profiles.
  • Loading branch information
JFreegman committed Feb 1, 2024
1 parent 2a5bcfb commit 78c5b7d
Show file tree
Hide file tree
Showing 8 changed files with 147 additions and 69 deletions.
1 change: 1 addition & 0 deletions src/bootstrap.c
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@
#include "line_info.h"
#include "misc_tools.h"
#include "prompt.h"
#include "run_options.h"
#include "settings.h"
#include "windows.h"

Expand Down
4 changes: 2 additions & 2 deletions src/misc_tools.c
Original file line number Diff line number Diff line change
Expand Up @@ -559,7 +559,7 @@ size_t copy_tox_str(char *msg, size_t size, const char *data, size_t length)
returns length of s if char not found or 0 if s is NULL. */
int char_find(int idx, const char *s, char ch)
{
if (!s) {
if (s == NULL) {
return 0;
}

Expand All @@ -578,7 +578,7 @@ int char_find(int idx, const char *s, char ch)
returns 0 if char not found or s is NULL (skips 0th index). */
int char_rfind(const char *s, char ch, int len)
{
if (!s) {
if (s == NULL) {
return 0;
}

Expand Down
1 change: 1 addition & 0 deletions src/name_lookup.c
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
#include "global_commands.h"
#include "line_info.h"
#include "misc_tools.h"
#include "run_options.h"
#include "toxic.h"
#include "windows.h"

Expand Down
57 changes: 57 additions & 0 deletions src/run_options.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
/* run_options.h
*
*
* Copyright (C) 2024 Toxic All Rights Reserved.
*
* This file is part of Toxic.
*
* Toxic is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Toxic is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Toxic. If not, see <http://www.gnu.org/licenses/>.
*
*/

#ifndef RUN_OPTIONS_H

#include <stdbool.h>
#include <stdio.h> // needed for FILE
#include <stdint.h>

#include "toxic_constants.h"

typedef struct Run_Options {
bool use_ipv4;
bool force_tcp;
bool disable_local_discovery;
bool debug;
bool default_locale;
bool use_custom_data;
bool use_custom_config_file;
bool no_connect;
bool encrypt_data;
bool unencrypt_data;

char nameserver_path[MAX_STR_SIZE];
char config_path[MAX_STR_SIZE];
char nodes_path[MAX_STR_SIZE];

bool logging;
FILE *log_fp;

char proxy_address[256];
uint8_t proxy_type;
uint16_t proxy_port;

uint16_t tcp_port;
} Run_Options;

#endif /* RUN_OPTIONS_H */
73 changes: 45 additions & 28 deletions src/settings.c
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
#include "groupchats.h"
#include "misc_tools.h"
#include "notify.h"
#include "run_options.h"
#include "toxic.h"
#include "windows.h"

Expand Down Expand Up @@ -340,29 +341,50 @@ static void set_key_binding(int *key, const char **bind)
}
}

static bool get_settings_path(char *path, unsigned int path_size, const char *patharg)
#define TOXIC_CONF_FILE_EXT ".conf"

bool settings_load_config_file(Run_Options *run_opts, const char *data_path)
{
if (patharg != NULL) {
snprintf(path, path_size, "%s", patharg);
return true;
}
char tmp_path[MAX_STR_SIZE] = {0};

if (run_opts->use_custom_config_file) {
snprintf(tmp_path, sizeof(tmp_path), "%s", run_opts->config_path);
} else if (run_opts->use_custom_data) {
char tmp_data[MAX_STR_SIZE - strlen(TOXIC_CONF_FILE_EXT)];

if (strlen(data_path) >= sizeof(tmp_data)) {
return false;
}

char *user_config_dir = get_user_config_dir();
snprintf(path, path_size, "%s%stoxic.conf", user_config_dir, CONFIGDIR);
free(user_config_dir);
snprintf(tmp_data, sizeof(tmp_data), "%s", data_path);

const int dot_idx = char_rfind(tmp_data, '.', strlen(tmp_data));

if (dot_idx > 0) {
tmp_data[dot_idx] = '\0'; // remove .tox file extension (or any others) if it exists
}

snprintf(tmp_path, sizeof(tmp_path), "%s%s", tmp_data, TOXIC_CONF_FILE_EXT);
} else {
char *user_config_dir = get_user_config_dir();
snprintf(tmp_path, sizeof(tmp_path), "%s%stoxic%s", user_config_dir, CONFIGDIR, TOXIC_CONF_FILE_EXT);
free(user_config_dir);
}

/* make sure path exists or is created on first time running */
if (!file_exists(path)) {
FILE *fp = fopen(path, "w");
if (!file_exists(tmp_path)) {
FILE *fp = fopen(tmp_path, "w");

if (fp == NULL) {
fprintf(stderr, "failed to open config path: %s\n", path);
fprintf(stderr, "failed to create config path `%s`\n", tmp_path);
return false;
}

fclose(fp);
}

snprintf(run_opts->config_path, sizeof(run_opts->config_path), "%s", tmp_path);

return true;
}

Expand Down Expand Up @@ -404,22 +426,17 @@ static const char *extract_setting_public_key(const config_setting_t *keys)
/*
* Initializes `cfg` with the contents from the toxic config file.
*
* `patharg` points to a user specified config path. If `patharg` is NULL
* the default config path will be used.
*
* Return 0 on success.
* Return -1 if we failed to fetch or create the config path.
* Return -1 if the config file was not set by the client.
* Return -2 if the config file cannot be read or is invalid.
*/
static int settings_init_config(config_t *cfg, const char *patharg)
static int settings_init_config(config_t *cfg, const Run_Options *run_opts)
{
char path[MAX_STR_SIZE] = {0};

if (!get_settings_path(path, sizeof(path), patharg)) {
if (string_is_empty(run_opts->config_path)) {
return -1;
}

if (!config_read_file(cfg, path)) {
if (!config_read_file(cfg, run_opts->config_path)) {
fprintf(stderr, "config_read_file() error: %s:%d - %s\n", config_error_file(cfg),
config_error_line(cfg), config_error_text(cfg));
return -2;
Expand All @@ -428,12 +445,12 @@ static int settings_init_config(config_t *cfg, const char *patharg)
return 0;
}

int settings_load_conferences(const char *patharg)
int settings_load_conferences(const Run_Options *run_opts)
{
config_t cfg[1];
config_init(cfg);

const int c_ret = settings_init_config(cfg, patharg);
const int c_ret = settings_init_config(cfg, run_opts);

if (c_ret < 0) {
config_destroy(cfg);
Expand Down Expand Up @@ -480,12 +497,12 @@ int settings_load_conferences(const char *patharg)
return 0;
}

int settings_load_groups(const char *patharg)
int settings_load_groups(const Run_Options *run_opts)
{
config_t cfg[1];
config_init(cfg);

const int c_ret = settings_init_config(cfg, patharg);
const int c_ret = settings_init_config(cfg, run_opts);

if (c_ret < 0) {
config_destroy(cfg);
Expand Down Expand Up @@ -532,12 +549,12 @@ int settings_load_groups(const char *patharg)
return 0;
}

int settings_load_friends(const char *patharg)
int settings_load_friends(const Run_Options *run_opts)
{
config_t cfg[1];
config_init(cfg);

const int c_ret = settings_init_config(cfg, patharg);
const int c_ret = settings_init_config(cfg, run_opts);

if (c_ret < 0) {
config_destroy(cfg);
Expand Down Expand Up @@ -600,7 +617,7 @@ int settings_load_friends(const char *patharg)
return 0;
}

int settings_load_main(Client_Config *s, const char *patharg)
int settings_load_main(Client_Config *s, const Run_Options *run_opts)
{
config_t cfg[1];
config_init(cfg);
Expand All @@ -616,7 +633,7 @@ int settings_load_main(Client_Config *s, const char *patharg)
audio_defaults(s);
#endif

const int c_ret = settings_init_config(cfg, patharg);
const int c_ret = settings_init_config(cfg, run_opts);

if (c_ret < 0) {
config_destroy(cfg);
Expand Down
29 changes: 25 additions & 4 deletions src/settings.h
Original file line number Diff line number Diff line change
Expand Up @@ -141,14 +141,35 @@ enum settings_values {
#define LOG_TIMESTAMP_DEFAULT "%Y/%m/%d [%H:%M:%S]"
#define MPLEX_AWAY_NOTE "Away from keyboard, be back soon!"

typedef struct Run_Options Run_Options;

/*
* Loads the config file into `run_opts` and creates an empty file if it does not
* already exist. This function must be called before any other `settings_load` function.
*
* If the client has set a custom config file via the run option it will be
* prioritized.
*
* If the client is using the default tox data file and has not specified a custom
* config file, the default config file in the user config directory is used
*
* If the client is using a custom tox data file, the config path and filename will be
* identical to those of the data file, but with a `.conf` file extension.
*
* `data_path` is the name of the tox profile being used.
*
* Returns true if config file is successfully loaded.
*/
bool settings_load_config_file(Run_Options *run_opts, const char *data_path);

/*
* Loads general toxic settings from the toxic config file pointed to by `patharg'.
*
* Return 0 on success.
* Return -1 if we fail to open the file path.
* Return -2 if libconfig fails to read the config file.
*/
int settings_load_main(Client_Config *s, const char *patharg);
int settings_load_main(Client_Config *s, const Run_Options *run_opts);

/*
* Loads friend config settings from the toxic config file pointed to by `patharg`.
Expand All @@ -160,7 +181,7 @@ int settings_load_main(Client_Config *s, const char *patharg);
*
* This function will have no effect on friends that are added in the future.
*/
int settings_load_friends(const char *patharg);
int settings_load_friends(const Run_Options *run_opts);

/*
* Loads groupchat config settings from the toxic config file pointed to by `patharg`.
Expand All @@ -172,7 +193,7 @@ int settings_load_friends(const char *patharg);
*
* This function will have no effect on groupchat instances that are created in the future.
*/
int settings_load_groups(const char *patharg);
int settings_load_groups(const Run_Options *run_opts);

/*
* Loads conference config settings from the toxic config file pointed to by `patharg`.
Expand All @@ -184,6 +205,6 @@ int settings_load_groups(const char *patharg);
*
* This function will have no effect on conference instances that are created in the future.
*/
int settings_load_conferences(const char *patharg);
int settings_load_conferences(const Run_Options *run_opts);

#endif /* SETTINGS_H */
25 changes: 15 additions & 10 deletions src/toxic.c
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@
#include "name_lookup.h"
#include "notify.h"
#include "prompt.h"
#include "run_options.h"
#include "settings.h"
#include "term_mplex.h"
#include "toxic.h"
Expand Down Expand Up @@ -1397,11 +1398,9 @@ static void parse_args(Toxic *toxic, int argc, char *argv[])
}

snprintf(run_opts->config_path, sizeof(run_opts->config_path), "%s", optarg);
run_opts->use_custom_config_file = true;

if (!file_exists(run_opts->config_path)) {
queue_init_message("Config file not found");
}

queue_init_message("Using '%s' custom config file", run_opts->config_path);
break;
}

Expand Down Expand Up @@ -1453,7 +1452,7 @@ static void parse_args(Toxic *toxic, int argc, char *argv[])
strcpy(client_data->block_path, optarg);
strcat(client_data->block_path, "-blocklist");

queue_init_message("Using '%s' data file", client_data->data_path);
queue_init_message("Using '%s' tox profile", client_data->data_path);

break;
}
Expand Down Expand Up @@ -1708,14 +1707,20 @@ int main(int argc, char **argv)
first_time_encrypt(&toxic->client_data, "Encrypt existing data file? Y/n (q to quit)");
}

const char *config_path = !string_is_empty(run_opts->config_path) ? run_opts->config_path : NULL;
if (!settings_load_config_file(run_opts, toxic->client_data.data_path)) {
queue_init_message("Failed to load config file");
}

const int ms_ret = settings_load_main(toxic->c_config, config_path);
const int ms_ret = settings_load_main(toxic->c_config, run_opts);

if (ms_ret < 0) {
queue_init_message("Failed to load user settings: error %d", ms_ret);
}

if (!run_opts->use_custom_config_file && run_opts->use_custom_data) {
queue_init_message("Using '%s' config file", run_opts->config_path);
}

const int curl_init = curl_global_init(CURL_GLOBAL_ALL);
const int nameserver_ret = name_lookup_init(run_opts->nameserver_path, curl_init);

Expand Down Expand Up @@ -1753,19 +1758,19 @@ int main(int argc, char **argv)
load_groups(toxic);
load_conferences(toxic);

const int fs_ret = settings_load_friends(config_path);
const int fs_ret = settings_load_friends(run_opts);

if (fs_ret != 0) {
queue_init_message("Failed to load friend config settings: error %d", fs_ret);
}

const int gs_ret = settings_load_groups(config_path);
const int gs_ret = settings_load_groups(run_opts);

if (gs_ret != 0) {
queue_init_message("Failed to load groupchat config settings: error %d", gs_ret);
}

const int cs_ret = settings_load_conferences(config_path);
const int cs_ret = settings_load_conferences(run_opts);

if (cs_ret != 0) {
queue_init_message("Failed to load conference config settings: error %d", cs_ret);
Expand Down
Loading

0 comments on commit 78c5b7d

Please sign in to comment.