Skip to content

Commit 8d4881b

Browse files
committed
look for config at $HOME/.config/rhash/ and honor $XDG_CONFIG_DIRS
1 parent a479d7a commit 8d4881b

File tree

8 files changed

+125
-84
lines changed

8 files changed

+125
-84
lines changed

ChangeLog

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,6 @@
1+
Wed 06 Jan 2021 Aleksey
2+
* look for config file at $HOME/.config/rhash/rhashrc
3+
14
Mon 04 Jan 2021 Aleksey
25
* supported --blake2s, --blake2b options for the BLAKE2 hash functions
36

dist/rhash.1

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -304,7 +304,8 @@ placing a hardlink/symlink to it with a filename containing strings `crc32',
304304

305305
.SH CONFIG FILE
306306
RHash looks for a config file
307-
at $XDG_CONFIG_HOME/rhash/rhashrc, $HOME/.rhashrc and /etc/rhashrc.
307+
at $XDG_CONFIG_HOME/rhash/rhashrc, $HOME/.config/rhash/rhashrc,
308+
$XDG_CONFIG_DIRS/rhash/rhashrc, $HOME/.rhashrc and /etc/rhashrc.
308309

309310
The config file consists of lines formatted as
310311
.RS

file.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -110,7 +110,7 @@ char* make_path(const char* dir_path, const char* sub_path, int user_path_separa
110110
* @param sub_path the filepath to append to the directory
111111
* @return concatinated file path
112112
*/
113-
tpath_t make_wpath(ctpath_t dir_path, size_t dir_len, wchar_t* sub_path)
113+
tpath_t make_wpath(ctpath_t dir_path, size_t dir_len, ctpath_t sub_path)
114114
{
115115
wchar_t* result;
116116
size_t len;

file.h

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -28,10 +28,10 @@ typedef const file_tchar* ctpath_t;
2828
/* Generic path functions */
2929
char* make_path(const char* dir, const char* filename, int user_path_separator);
3030
#ifdef _WIN32
31-
tpath_t make_wpath(ctpath_t dir_path, size_t dir_len, wchar_t* filename);
32-
# define make_tpath(dir_path, filename) make_wpath(dir_path, (size_t)-1, filename)
31+
tpath_t make_wpath(ctpath_t dir_path, size_t dir_len, ctpath_t sub_path);
32+
# define make_tpath(dir_path, sub_path) make_wpath(dir_path, (size_t)-1, sub_path)
3333
#else
34-
# define make_tpath(dir_path, filename) make_path(dir_path, filename, 0)
34+
# define make_tpath(dir_path, sub_path) make_path(dir_path, sub_path, 0)
3535
#endif /* _WIN32 */
3636

3737
int is_regular_file(const char* path); /* shall be deprecated */

parse_cmdline.c

Lines changed: 114 additions & 78 deletions
Original file line numberDiff line numberDiff line change
@@ -553,89 +553,125 @@ static void apply_option(options_t* opts, parsed_option_t* option)
553553
}
554554
}
555555

556+
#ifdef _WIN32
557+
# define rsh_tgetenv(name) _wgetenv(name)
558+
#else
559+
# define rsh_tgetenv(name) getenv(name)
560+
#endif
561+
#define COUNTOF(array) (sizeof(array) / sizeof(*array))
562+
enum ConfigLookupFlags
563+
{
564+
ConfFlagNeedSplit = 8,
565+
ConfFlagNoVars = 16
566+
};
567+
556568
/**
557-
* Search for config file.
569+
* Check if a config file, specified by path subparts, is a regular file.
570+
* On success the resulting path is stored as rhash_data.config_file.
558571
*
559-
* @return the relative path to config file
572+
* @param path_parts subparts of the path
573+
* @param flags check flags
574+
* @return 1 if the file is regular, 0 otherwise
560575
*/
561-
static const char* find_conf_file(void)
576+
static int try_config(ctpath_t path_parts[], unsigned flags)
562577
{
563-
#ifndef SYSCONFDIR
564-
# define SYSCONFDIR "/etc"
578+
const size_t parts_count = flags & 3;
579+
tpath_t allocated = NULL;
580+
ctpath_t path = NULL;
581+
size_t i;
582+
for (i = 0; i < parts_count; i++) {
583+
ctpath_t sub_path = path_parts[i];
584+
if (sub_path[0] == RSH_T('$') && !(flags & ConfFlagNoVars)) {
585+
sub_path = rsh_tgetenv(sub_path + 1);
586+
if (!sub_path || !sub_path[0]) {
587+
free(allocated);
588+
return 0;
589+
}
590+
#ifndef _WIN32
591+
/* check if the variable should be splitted */
592+
if (flags == (2 | ConfFlagNeedSplit) && i == 0) {
593+
tpath_t next;
594+
ctpath_t parts[2];
595+
parts[1] = path_parts[1];
596+
sub_path = allocated = strdup(sub_path);
597+
do {
598+
next = strchr(sub_path, ':');
599+
if (next)
600+
*(next++) = '\0';
601+
if (sub_path[0]) {
602+
parts[0] = sub_path;
603+
if (try_config(parts, COUNTOF(parts) | ConfFlagNoVars)) {
604+
free(allocated);
605+
return 1;
606+
}
607+
}
608+
sub_path = next;
609+
} while(sub_path);
610+
free(allocated);
611+
return 0;
612+
}
565613
#endif
566-
#define CONFIG_FILENAME "rhashrc"
567-
568-
char* dir1;
569-
char* path;
570-
571-
#ifndef _WIN32 /* Linux/Unix part */
572-
/* first check for $XDG_CONFIG_HOME/rhash/rhashrc file */
573-
if ( (dir1 = getenv("XDG_CONFIG_HOME")) ) {
574-
dir1 = make_path(dir1, "rhash", 0);
575-
path = make_path(dir1, CONFIG_FILENAME, 0);
576-
free(dir1);
577-
if (is_regular_file(path)) {
578-
rsh_vector_add_ptr(opt.mem, path);
579-
return (conf_opt.config_file = path);
580614
}
581-
free(path);
582-
}
583-
/* then check for $HOME/.rhashrc file */
584-
if ( (dir1 = getenv("HOME")) ) {
585-
path = make_path(dir1, ".rhashrc", 0);
586-
if (is_regular_file(path)) {
587-
rsh_vector_add_ptr(opt.mem, path);
588-
return (conf_opt.config_file = path);
615+
if (path) {
616+
tpath_t old_allocated = allocated;
617+
path = allocated = make_tpath(path, sub_path);
618+
free(old_allocated);
619+
} else {
620+
path = sub_path;
589621
}
590-
free(path);
591622
}
592-
/* then check for global config */
593-
path = SYSCONFDIR "/" CONFIG_FILENAME;
594-
if (is_regular_file(path)) {
595-
return (conf_opt.config_file = path);
623+
assert(!rhash_data.config_file.real_path);
624+
{
625+
unsigned init_flags = FileInitRunFstat | (!allocated ? FileInitReusePath : 0);
626+
int res = file_init(&rhash_data.config_file, path, init_flags);
627+
free(allocated);
628+
if (res == 0 && FILE_ISREG(&rhash_data.config_file))
629+
return 1;
630+
file_cleanup(&rhash_data.config_file);
631+
return 0;
596632
}
633+
}
634+
635+
/**
636+
* Search for config file.
637+
*
638+
* @return 1 if config file is found, 0 otherwise
639+
*/
640+
static int find_conf_file(void)
641+
{
642+
#ifndef SYSCONFDIR
643+
# define SYSCONFDIR "/etc"
644+
#endif
645+
646+
#ifndef _WIN32
647+
/* Linux/Unix part */
648+
static ctpath_t xdg_conf_home[2] = { "$XDG_CONFIG_HOME", "rhash/rhashrc" };
649+
static ctpath_t xdg_conf_default[2] = { "$HOME", ".config/rhash/rhashrc" };
650+
static ctpath_t xdg_conf_dirs[2] = { "$XDG_CONFIG_DIRS", "rhash/rhashrc" };
651+
static ctpath_t home_conf[2] = { "$HOME", ".rhashrc" };
652+
static ctpath_t sysconf_dir[1] = { SYSCONFDIR "/rhashrc" };
653+
654+
return (try_config(xdg_conf_home, COUNTOF(xdg_conf_home)) ||
655+
try_config(xdg_conf_default, COUNTOF(xdg_conf_default)) ||
656+
try_config(xdg_conf_dirs, COUNTOF(xdg_conf_dirs) | ConfFlagNeedSplit) ||
657+
try_config(home_conf, COUNTOF(home_conf)) ||
658+
try_config(sysconf_dir, COUNTOF(sysconf_dir)));
597659

598660
#else /* _WIN32 */
599-
wchar_t* program_dir = get_program_dir();
600-
601-
/* first check for the %APPDATA%\RHash\rhashrc config */
602-
if ( (dir1 = getenv("APPDATA")) ) {
603-
dir1 = make_path(dir1, "RHash", 0);
604-
path = make_path(dir1, CONFIG_FILENAME, 0);
605-
free(dir1);
606-
if (is_regular_file(path)) {
607-
rsh_vector_add_ptr(opt.mem, path);
608-
return (conf_opt.config_file = path);
609-
}
610-
free(path);
611-
}
612661

613-
/* then check for %HOMEDRIVE%%HOMEPATH%\rhashrc */
614-
/* note that %USERPROFILE% is generally not a user home dir */
615-
if ( (dir1 = getenv("HOMEDRIVE")) && (path = getenv("HOMEPATH"))) {
616-
dir1 = make_path(dir1, path, 0);
617-
path = make_path(dir1, CONFIG_FILENAME, 0);
618-
free(dir1);
619-
if (is_regular_file(path)) {
620-
rsh_vector_add_ptr(opt.mem, path);
621-
return (conf_opt.config_file = path);
622-
}
623-
free(path);
624-
}
662+
static ctpath_t app_data[2] = { L"$APPDATA", L"RHash\\rhashrc" };
663+
static ctpath_t home_conf[3] = { L"$HOMEDRIVE", L"$HOMEPATH", L"rhashrc" };
625664

626-
/* check for ${PROGRAM_DIR}\rhashrc */
627-
if (program_dir && program_dir[0] && (dir1 = convert_wcs_to_str(program_dir, ConvertToPrimaryEncoding))) {
628-
path = make_path(dir1, CONFIG_FILENAME, 0);
629-
free(dir1);
630-
if (is_regular_file(path)) {
631-
rsh_vector_add_ptr(opt.mem, path);
632-
return (conf_opt.config_file = path);
633-
}
634-
free(path);
665+
if (try_config(app_data, COUNTOF(app_data)) || try_config(home_conf, COUNTOF(home_conf))) {
666+
return 1;
667+
} else {
668+
tpath_t prog_dir[2];
669+
prog_dir[0] = get_program_dir();
670+
prog_dir[1] = L"rhashrc";
671+
return try_config((ctpath_t*)prog_dir, COUNTOF(prog_dir));
635672
}
636-
#endif /* _WIN32 */
637673

638-
return (conf_opt.config_file = NULL); /* config file not found */
674+
#endif /* _WIN32 */
639675
}
640676

641677
/**
@@ -647,20 +683,19 @@ static int read_config(void)
647683
{
648684
#define LINE_BUF_SIZE 2048
649685
char buf[LINE_BUF_SIZE];
650-
file_t file;
651686
FILE* fd;
652687
parsed_option_t option;
653688
int res;
654689

655-
/* initialize conf_opt and opt structures */
690+
/* initialize conf_opt */
656691
memset(&conf_opt, 0, sizeof(opt));
657692
conf_opt.find_max_depth = -1;
658693

659694
if (!find_conf_file()) return 0;
695+
assert(!!rhash_data.config_file.real_path);
696+
assert(FILE_ISREG(&rhash_data.config_file));
660697

661-
file_init_by_print_path(&file, 0, conf_opt.config_file, 0);
662-
fd = file_fopen(&file, FOpenRead);
663-
file_cleanup(&file);
698+
fd = file_fopen(&rhash_data.config_file, FOpenRead);
664699
if (!fd) return -1;
665700

666701
while (fgets(buf, LINE_BUF_SIZE, fd)) {
@@ -675,7 +710,7 @@ static int read_config(void)
675710
/* search for '=' */
676711
index = strcspn(line, "=");
677712
if (line[index] == 0) {
678-
log_warning(_("%s: can't parse line \"%s\"\n"), conf_opt.config_file, line);
713+
log_warning(_("%s: can't parse line \"%s\"\n"), file_get_print_path(&rhash_data.config_file, FPathUtf8 | FPathNotNull), line);
679714
continue;
680715
}
681716
line[index] = 0;
@@ -688,7 +723,7 @@ static int read_config(void)
688723
}
689724

690725
if (!t->type) {
691-
log_warning(_("%s: unknown option \"%s\"\n"), conf_opt.config_file, line);
726+
log_warning(_("%s: unknown option \"%s\"\n"), file_get_print_path(&rhash_data.config_file, FPathUtf8 | FPathNotNull), line);
692727
continue;
693728
}
694729

@@ -713,7 +748,8 @@ static int read_config(void)
713748
res = fclose(fd);
714749

715750
#ifdef _WIN32
716-
if ( (opt.flags & OPT_ENCODING) == 0 ) opt.flags |= (conf_opt.flags & OPT_ENCODING);
751+
if ( (opt.flags & OPT_ENCODING) == 0 )
752+
opt.flags |= (conf_opt.flags & OPT_ENCODING);
717753
#endif
718754
return (res == 0 ? 0 : -1);
719755
}
@@ -1078,9 +1114,9 @@ static void make_final_options_checks(void)
10781114
{
10791115
unsigned ext_format_bits = (opt.printf_str ? 0x100 : 0) | (opt.template_file ? 0x200 : 0);
10801116

1081-
if ((opt.flags & OPT_VERBOSE) && conf_opt.config_file) {
1117+
if ((opt.flags & OPT_VERBOSE) && !!rhash_data.config_file.real_path) {
10821118
/* note that the first log_msg call shall be made after setup_output() */
1083-
log_msg(_("Config file: %s\n"), conf_opt.config_file);
1119+
log_msg_file_t(_("Config file: %s\n"), &rhash_data.config_file);
10841120
}
10851121

10861122
if (opt.bt_batch_file)

parse_cmdline.h

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,6 @@ struct options_t
7777
unsigned fmt; /* flags to specify output format to use */
7878
unsigned mode; /* flags to specify program mode */
7979
unsigned openssl_mask; /* bit-mask for enabled OpenSSL hash functions */
80-
const char* config_file; /* config file path */
8180
char* printf_str; /* printf-like format */
8281
opt_tchar* template_file; /* printf-like template file path */
8382
opt_tchar* output; /* file to output calculation or checking results to */

rhash_main.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -204,6 +204,7 @@ void rhash_destroy(struct rhash_t* ptr)
204204
file_cleanup(&ptr->out_file);
205205
file_cleanup(&ptr->log_file);
206206
file_cleanup(&ptr->upd_file);
207+
file_cleanup(&ptr->config_file);
207208
}
208209

209210
static void free_allocated_data(void)

rhash_main.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ struct rhash_t
2323
file_t out_file;
2424
file_t log_file;
2525
file_t upd_file;
26+
file_t config_file;
2627

2728
char* printf_str;
2829
struct print_item* print_list;

0 commit comments

Comments
 (0)