@@ -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 )
0 commit comments