Override config from conf.d
This commit is contained in:
@@ -10,6 +10,7 @@ Nothing at the moment
|
|||||||
- feat!: Handle input device connection/disconnection at runtime (#38)
|
- feat!: Handle input device connection/disconnection at runtime (#38)
|
||||||
- feat: Update lv_drivers to git master (2023-03-11)
|
- feat: Update lv_drivers to git master (2023-03-11)
|
||||||
- feat: Update lvgl to v8.3 (2023-03-08)
|
- feat: Update lvgl to v8.3 (2023-03-08)
|
||||||
|
- feat!: Deprecate -c CLI option and add support for reading from /etc/unl0kr.conf.d/
|
||||||
|
|
||||||
## 0.3.0 (2022-11-13)
|
## 0.3.0 (2022-11-13)
|
||||||
|
|
||||||
|
23
README.md
23
README.md
@@ -39,17 +39,20 @@ A man page is planned to be added with #6. For the time being, you can get an ov
|
|||||||
$ unl0kr --help
|
$ unl0kr --help
|
||||||
Usage: unl0kr [OPTION]
|
Usage: unl0kr [OPTION]
|
||||||
|
|
||||||
|
Unl0kr values the CRYPTTAB_TRIED variable. Upon completion, the entered
|
||||||
|
password is printed to STDOUT. All other output happens on STDERR.
|
||||||
|
|
||||||
Mandatory arguments to long options are mandatory for short options too.
|
Mandatory arguments to long options are mandatory for short options too.
|
||||||
-c, --config=PATH Locaton of the main config file. Defaults to
|
-C, --config-override Path to a config override file. Can be supplied
|
||||||
/etc/unl0kr.conf.
|
multiple times. Config files are merged in the
|
||||||
-C, --config-override Location of the config override file. Values in
|
following order:
|
||||||
this file override values for the same keys in the
|
* /etc/unl0kr.conf
|
||||||
main config file. If specified multiple times, the
|
* /etc/unl0kr.conf.d/* (alphabetically)
|
||||||
values from consecutive files will be merged in
|
* Override files (in supplied order)
|
||||||
order.
|
-g, --geometry=NxM[@X,Y] Force a display size of N horizontal times M
|
||||||
-g, --geometry=NxM Force a display size of N horizontal times M
|
vertical pixels, offset horizontally by X
|
||||||
vertical pixels
|
pixels and vertically by Y pixels
|
||||||
-d --dpi=N Overrides the DPI
|
-d --dpi=N Override the display's DPI value
|
||||||
-h, --help Print this message and exit
|
-h, --help Print this message and exit
|
||||||
-v, --verbose Enable more detailed logging output on STDERR
|
-v, --verbose Enable more detailed logging output on STDERR
|
||||||
-V, --version Print the unl0kr version and exit
|
-V, --version Print the unl0kr version and exit
|
||||||
|
@@ -50,14 +50,8 @@ static void print_usage();
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
static void init_opts(ul_cli_opts *opts) {
|
static void init_opts(ul_cli_opts *opts) {
|
||||||
opts->num_config_files = 1;
|
opts->num_config_files = 0;
|
||||||
|
opts->config_files = NULL;
|
||||||
opts->config_files = malloc(sizeof(char *));
|
|
||||||
if (!opts->config_files) {
|
|
||||||
ul_log(UL_LOG_LEVEL_ERROR, "Could not allocate memory for config file paths");
|
|
||||||
exit(EXIT_FAILURE);
|
|
||||||
}
|
|
||||||
opts->config_files[0] = "/etc/unl0kr.conf";
|
|
||||||
|
|
||||||
opts->hor_res = -1;
|
opts->hor_res = -1;
|
||||||
opts->ver_res = -1;
|
opts->ver_res = -1;
|
||||||
@@ -75,13 +69,12 @@ static void print_usage() {
|
|||||||
"password is printed to STDOUT. All other output happens on STDERR.\n"
|
"password is printed to STDOUT. All other output happens on STDERR.\n"
|
||||||
"\n"
|
"\n"
|
||||||
"Mandatory arguments to long options are mandatory for short options too.\n"
|
"Mandatory arguments to long options are mandatory for short options too.\n"
|
||||||
" -c, --config=PATH Locaton of the main config file. Defaults to\n"
|
" -C, --config-override Path to a config override file. Can be supplied\n"
|
||||||
" /etc/unl0kr.conf.\n"
|
" multiple times. Config files are merged in the\n"
|
||||||
" -C, --config-override Location of the config override file. Values in\n"
|
" following order:\n"
|
||||||
" this file override values for the same keys in\n"
|
" * /etc/unl0kr.conf\n"
|
||||||
" the main config file. If specified multiple\n"
|
" * /etc/unl0kr.conf.d/* (alphabetically)\n"
|
||||||
" times, the values from consecutive files will be\n"
|
" * Override files (in supplied order)\n"
|
||||||
" merged in order.\n"
|
|
||||||
" -g, --geometry=NxM[@X,Y] Force a display size of N horizontal times M\n"
|
" -g, --geometry=NxM[@X,Y] Force a display size of N horizontal times M\n"
|
||||||
" vertical pixels, offset horizontally by X\n"
|
" vertical pixels, offset horizontally by X\n"
|
||||||
" pixels and vertically by Y pixels\n"
|
" pixels and vertically by Y pixels\n"
|
||||||
@@ -101,7 +94,6 @@ void ul_cli_parse_opts(int argc, char *argv[], ul_cli_opts *opts) {
|
|||||||
init_opts(opts);
|
init_opts(opts);
|
||||||
|
|
||||||
struct option long_opts[] = {
|
struct option long_opts[] = {
|
||||||
{ "config", required_argument, NULL, 'c' },
|
|
||||||
{ "config-override", required_argument, NULL, 'C' },
|
{ "config-override", required_argument, NULL, 'C' },
|
||||||
{ "geometry", required_argument, NULL, 'g' },
|
{ "geometry", required_argument, NULL, 'g' },
|
||||||
{ "dpi", required_argument, NULL, 'd' },
|
{ "dpi", required_argument, NULL, 'd' },
|
||||||
@@ -115,9 +107,6 @@ void ul_cli_parse_opts(int argc, char *argv[], ul_cli_opts *opts) {
|
|||||||
|
|
||||||
while ((opt = getopt_long(argc, argv, "c:C:g:d:hvV", long_opts, &index)) != -1) {
|
while ((opt = getopt_long(argc, argv, "c:C:g:d:hvV", long_opts, &index)) != -1) {
|
||||||
switch (opt) {
|
switch (opt) {
|
||||||
case 'c':
|
|
||||||
opts->config_files[0] = optarg;
|
|
||||||
break;
|
|
||||||
case 'C':
|
case 'C':
|
||||||
opts->config_files = realloc(opts->config_files, (opts->num_config_files + 1) * sizeof(char *));
|
opts->config_files = realloc(opts->config_files, (opts->num_config_files + 1) * sizeof(char *));
|
||||||
if (!opts->config_files) {
|
if (!opts->config_files) {
|
||||||
|
151
config.c
151
config.c
@@ -24,6 +24,7 @@
|
|||||||
|
|
||||||
#include "lvgl/lvgl.h"
|
#include "lvgl/lvgl.h"
|
||||||
|
|
||||||
|
#include <dirent.h>
|
||||||
#include <ini.h>
|
#include <ini.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
|
||||||
@@ -35,19 +36,31 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Initialise a config options struct with default values.
|
* Compares two strings from opaque types.
|
||||||
*
|
*
|
||||||
* @param opts pointer to the options struct
|
* @param a first string as void pointer
|
||||||
|
* @param b second string as void pointer
|
||||||
|
* @return a positive integer if a > b, a negative integer if a < b and 0 otherwise
|
||||||
*/
|
*/
|
||||||
static void init_opts(ul_config_opts *opts);
|
static int compare_strings(const void* a, const void* b);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Parse options from a configuration file.
|
* Checks whether a string ends with a suffix
|
||||||
*
|
*
|
||||||
* @param path path to configuration file
|
* @param string string to check
|
||||||
* @param opts pointer for writing the parsed options into
|
* @param suffix suffix to compare to
|
||||||
|
* @return true if the suffix matches at the end of the string, false otherwise
|
||||||
*/
|
*/
|
||||||
static void parse_file(const char *path, ul_config_opts *opts);
|
static bool string_ends_with(const char *string, const char *suffix);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Non-recursively searches a directory for configuration files.
|
||||||
|
*
|
||||||
|
* @param path folder to search in
|
||||||
|
* @param found pointer to write found configuration file names into (to be freed by the caller)
|
||||||
|
* @param num_found pointer to write number of found files into
|
||||||
|
*/
|
||||||
|
static void find_files(const char *path, char ***found, int *num_found);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Handle parsing events from INIH.
|
* Handle parsing events from INIH.
|
||||||
@@ -74,26 +87,71 @@ static bool parse_bool(const char *value, bool *result);
|
|||||||
* Static functions
|
* Static functions
|
||||||
*/
|
*/
|
||||||
|
|
||||||
static void init_opts(ul_config_opts *opts) {
|
static int compare_strings(const void* a, const void* b) {
|
||||||
opts->general.animations = false;
|
return strcmp(*(const char**)a, *(const char**)b);
|
||||||
opts->general.backend = ul_backends_backends[0] == NULL ? UL_BACKENDS_BACKEND_NONE : 0;
|
|
||||||
opts->general.timeout = 0;
|
|
||||||
opts->keyboard.autohide = true;
|
|
||||||
opts->keyboard.layout_id = SQ2LV_LAYOUT_US;
|
|
||||||
opts->keyboard.popovers = true;
|
|
||||||
opts->textarea.obscured = true;
|
|
||||||
opts->textarea.bullet = LV_SYMBOL_BULLET;
|
|
||||||
opts->theme.default_id = UL_THEMES_THEME_BREEZY_DARK;
|
|
||||||
opts->theme.alternate_id = UL_THEMES_THEME_BREEZY_LIGHT;
|
|
||||||
opts->input.keyboard = true;
|
|
||||||
opts->input.pointer = true;
|
|
||||||
opts->input.touchscreen = true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void parse_file(const char *path, ul_config_opts *opts) {
|
static bool string_ends_with(const char *string, const char *suffix) {
|
||||||
if (ini_parse(path, parsing_handler, opts) != 0) {
|
if (!string || !suffix || strlen(suffix) > strlen(string)) {
|
||||||
ul_log(UL_LOG_LEVEL_ERROR, "Ignoring invalid config file %s", path);
|
return false;
|
||||||
}
|
}
|
||||||
|
return strncmp(string + strlen(string) - strlen(suffix), suffix, strlen(suffix)) == 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void find_files(const char *path, char ***found, int *num_found) {
|
||||||
|
/* Initialise output variables */
|
||||||
|
*found = NULL;
|
||||||
|
*num_found = 0;
|
||||||
|
|
||||||
|
/* Count length of directory path */
|
||||||
|
const int path_length = strlen(path);
|
||||||
|
|
||||||
|
/* Open directory */
|
||||||
|
DIR *d = opendir(path);
|
||||||
|
if (!d) {
|
||||||
|
ul_log(UL_LOG_LEVEL_WARNING, "Could not read contents of folder %s", path);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Loop over directory contents */
|
||||||
|
struct dirent *dir;
|
||||||
|
while ((dir = readdir(d)) != NULL) {
|
||||||
|
/* Ignore anything except for .conf files */
|
||||||
|
if (dir->d_type != DT_REG || !string_ends_with(dir->d_name, ".conf")) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Grow output array */
|
||||||
|
char **tmp = realloc(*found, (*num_found + 1) * sizeof(char *));
|
||||||
|
if (!tmp) {
|
||||||
|
ul_log(UL_LOG_LEVEL_ERROR, "Could not reallocate memory for configuration file paths");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
*found = tmp;
|
||||||
|
|
||||||
|
/* Extract file name and length */
|
||||||
|
char *name = dir->d_name;
|
||||||
|
int name_length = strlen(name);
|
||||||
|
|
||||||
|
/* Allocate memory for full path */
|
||||||
|
char *found_path = malloc(path_length + name_length + 2); /* +1 for path separator and null terminator, respectively */
|
||||||
|
if (!found_path) {
|
||||||
|
ul_log(UL_LOG_LEVEL_ERROR, "Could not allocate memory for configuration file path");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Build full path */
|
||||||
|
memcpy(found_path, path, path_length);
|
||||||
|
found_path[path_length] = '/';
|
||||||
|
memcpy(found_path + path_length + 1, dir->d_name, name_length + 1); /* +1 for path separator and null terminator, respectively */
|
||||||
|
|
||||||
|
/* Store file path */
|
||||||
|
(*found)[*num_found] = found_path;
|
||||||
|
*num_found += 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Close directory */
|
||||||
|
closedir(d);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int parsing_handler(void* user_data, const char* section, const char* key, const char* value) {
|
static int parsing_handler(void* user_data, const char* section, const char* key, const char* value) {
|
||||||
@@ -196,9 +254,48 @@ static bool parse_bool(const char *value, bool *result) {
|
|||||||
* Public functions
|
* Public functions
|
||||||
*/
|
*/
|
||||||
|
|
||||||
void ul_config_parse(const char **files, int num_files, ul_config_opts *opts) {
|
void ul_config_init_opts(ul_config_opts *opts) {
|
||||||
init_opts(opts);
|
opts->general.animations = false;
|
||||||
|
opts->general.backend = ul_backends_backends[0] == NULL ? UL_BACKENDS_BACKEND_NONE : 0;
|
||||||
|
opts->general.timeout = 0;
|
||||||
|
opts->keyboard.autohide = true;
|
||||||
|
opts->keyboard.layout_id = SQ2LV_LAYOUT_US;
|
||||||
|
opts->keyboard.popovers = true;
|
||||||
|
opts->textarea.obscured = true;
|
||||||
|
opts->textarea.bullet = LV_SYMBOL_BULLET;
|
||||||
|
opts->theme.default_id = UL_THEMES_THEME_BREEZY_DARK;
|
||||||
|
opts->theme.alternate_id = UL_THEMES_THEME_BREEZY_LIGHT;
|
||||||
|
opts->input.keyboard = true;
|
||||||
|
opts->input.pointer = true;
|
||||||
|
opts->input.touchscreen = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ul_config_parse_directory(const char *path, ul_config_opts *opts) {
|
||||||
|
/* Find files in directory */
|
||||||
|
char **found = NULL;
|
||||||
|
int num_found = 0;
|
||||||
|
find_files(path, &found, &num_found);
|
||||||
|
|
||||||
|
/* Sort and parse files */
|
||||||
|
qsort(found, num_found, sizeof(char *), compare_strings);
|
||||||
|
ul_config_parse_files((const char **)found, num_found, opts);
|
||||||
|
|
||||||
|
/* Free memory */
|
||||||
|
for (int i = 0; i < num_found; ++i) {
|
||||||
|
free(found[i]);
|
||||||
|
}
|
||||||
|
free(found);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ul_config_parse_files(const char **files, int num_files, ul_config_opts *opts) {
|
||||||
for (int i = 0; i < num_files; ++i) {
|
for (int i = 0; i < num_files; ++i) {
|
||||||
parse_file(files[i], opts);
|
ul_config_parse_file(files[i], opts);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ul_config_parse_file(const char *path, ul_config_opts *opts) {
|
||||||
|
ul_log(UL_LOG_LEVEL_VERBOSE, "Parsing config file %s", path);
|
||||||
|
if (ini_parse(path, parsing_handler, opts) != 0) {
|
||||||
|
ul_log(UL_LOG_LEVEL_ERROR, "Ignoring invalid config file %s", path);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
27
config.h
27
config.h
@@ -103,12 +103,35 @@ typedef struct {
|
|||||||
} ul_config_opts;
|
} ul_config_opts;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Parse options from one or more configuration files.
|
* Initialise a config options struct with default values.
|
||||||
|
*
|
||||||
|
* @param opts pointer to the options struct
|
||||||
|
*/
|
||||||
|
void ul_config_init_opts(ul_config_opts *opts);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Find configuration files in a directory and parse them in alphabetic order.
|
||||||
|
*
|
||||||
|
* @param path directory path
|
||||||
|
* @param opts pointer for writing the parsed options into
|
||||||
|
*/
|
||||||
|
void ul_config_parse_directory(const char *path, ul_config_opts *opts);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Parse one or more configuration files.
|
||||||
*
|
*
|
||||||
* @param files paths to configuration files
|
* @param files paths to configuration files
|
||||||
* @param num_files number of configuration files
|
* @param num_files number of configuration files
|
||||||
* @param opts pointer for writing the parsed options into
|
* @param opts pointer for writing the parsed options into
|
||||||
*/
|
*/
|
||||||
void ul_config_parse(const char **files, int num_files, ul_config_opts *opts);
|
void ul_config_parse_files(const char **files, int num_files, ul_config_opts *opts);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Parse a configuration file.
|
||||||
|
*
|
||||||
|
* @param path path to configuration file
|
||||||
|
* @param opts pointer for writing the parsed options into
|
||||||
|
*/
|
||||||
|
void ul_config_parse_file(const char *path, ul_config_opts *opts);
|
||||||
|
|
||||||
#endif /* UL_CONFIG_H */
|
#endif /* UL_CONFIG_H */
|
||||||
|
5
main.c
5
main.c
@@ -351,7 +351,10 @@ int main(int argc, char *argv[]) {
|
|||||||
ul_log(UL_LOG_LEVEL_VERBOSE, "unl0kr %s", UL_VERSION);
|
ul_log(UL_LOG_LEVEL_VERBOSE, "unl0kr %s", UL_VERSION);
|
||||||
|
|
||||||
/* Parse config files */
|
/* Parse config files */
|
||||||
ul_config_parse(cli_opts.config_files, cli_opts.num_config_files, &conf_opts);
|
ul_config_init_opts(&conf_opts);
|
||||||
|
ul_config_parse_file("/etc/unl0kr.conf", &conf_opts);
|
||||||
|
ul_config_parse_directory("/etc/unl0kr.conf.d", &conf_opts);
|
||||||
|
ul_config_parse_files(cli_opts.config_files, cli_opts.num_config_files, &conf_opts);
|
||||||
|
|
||||||
/* Prepare current TTY and clean up on termination */
|
/* Prepare current TTY and clean up on termination */
|
||||||
ul_terminal_prepare_current_terminal();
|
ul_terminal_prepare_current_terminal();
|
||||||
|
Reference in New Issue
Block a user