From 34fa2faba5629eb75309fcc34db646d6ab50192d Mon Sep 17 00:00:00 2001 From: steelman Date: Sun, 23 Oct 2022 22:52:54 +0200 Subject: [PATCH] Look for ~/.config/avrdude/avrduce.rc configuration file (#1131) * Look for ~/.config/avrdude/config configuration file Traditionally per-user configuration files have been placed in user's home directory with their names beginnig with a dot to hide them from some tools like ls(1). However, the number of programs following this convention have grown over time to the point where the number of hidden files becomes inconvenient to some users. For this reason the XDG Base Directory Specification[1] specifies an alternate place to store configuration files under ~/.config directory. This patch enables avrdude to look for ~/.config/avrdude/config configuration file, if ~/.avrduderc doesn't exist. [1] https://specifications.freedesktop.org/basedir-spec/basedir-spec-0.8.html * Safely concatenate directories and configurations files and minor changes in docs * Make stats variable available for WIN32 again in main.c * Utilise full usr_config[] array space * Check for xdg-style avrdude.rc file first before fallback ~/.avrduderc Co-authored-by: Stefan Rueger --- src/avrdude.1 | 18 +++++++++++++----- src/avrdude.conf.in | 2 +- src/avrdude.h | 1 + src/doc/avrdude.texi | 25 ++++++++++++++----------- src/main.c | 42 ++++++++++++++++++++++++++++++------------ 5 files changed, 59 insertions(+), 29 deletions(-) diff --git a/src/avrdude.1 b/src/avrdude.1 index ba5292ee..0049924f 100644 --- a/src/avrdude.1 +++ b/src/avrdude.1 @@ -1320,10 +1320,10 @@ the CS line being managed outside the application. .Sh FILES .Bl -tag -offset indent -width /dev/ppi0XXX .It Pa /dev/ppi0 -default device to be used for communication with the programming +Default device to be used for communication with the programming hardware .It Pa avrdude.conf -programmer and parts configuration file +Programmer and parts configuration file .Pp On Windows systems, this file is looked up in the same directory as the executable file. @@ -1332,14 +1332,22 @@ On all other systems, the file is first looked up in relative to the path of the executable, then in the same directory as the executable itself, and finally in the system default location .Pa ${PREFIX}/etc/avrdude.conf . +.It Pa ${XDG_CONFIG_HOME}/avrdude/avrdude.rc +Local programmer and parts configuration file (per-user overrides); it follows the same syntax as +.Pa avrdude.conf ; +if the +.Pa ${XDG_CONFIG_HOME} +environment variable is not set or empty, the directory +.Pa ${HOME}/.config/ +is used instead. .It Pa ${HOME}/.avrduderc -programmer and parts configuration file (per-user overrides) +Alternative location of the per-user configuration file if above file does not exist .It Pa ~/.inputrc Initialization file for the .Xr readline 3 library -.It Pa ${PREFIX}/share/doc/avrdude/avrdude.pdf -Schematic of programming hardware +.It Pa /doc/avrdude/avrdude.pdf +User manual .El .\" .Sh EXAMPLES .Sh DIAGNOSTICS diff --git a/src/avrdude.conf.in b/src/avrdude.conf.in index 706b915a..67bad16f 100644 --- a/src/avrdude.conf.in +++ b/src/avrdude.conf.in @@ -389,7 +389,7 @@ # ATmega169 0x78 # -# Overall avrdude defaults; suitable for ~/.avrduderc +# Overall avrdude defaults; suitable for ~/.config/avrdude/config # default_parallel = "@DEFAULT_PAR_PORT@"; default_serial = "@DEFAULT_SER_PORT@"; diff --git a/src/avrdude.h b/src/avrdude.h index d765e9a5..a4079974 100644 --- a/src/avrdude.h +++ b/src/avrdude.h @@ -26,6 +26,7 @@ #define USER_CONF_FILE "avrdude.rc" #else #define USER_CONF_FILE ".avrduderc" +#define XDG_USER_CONF_FILE "avrdude/avrdude.rc" #endif extern char *progname; // name of program, for messages diff --git a/src/doc/avrdude.texi b/src/doc/avrdude.texi index 1e139234..6e659593 100644 --- a/src/doc/avrdude.texi +++ b/src/doc/avrdude.texi @@ -1714,21 +1714,24 @@ AVRDUDE reads a configuration file upon startup which describes all of the parts and programmers that it knows about. The advantage of this is that if you have a chip that is not currently supported by AVRDUDE, you can add it to the configuration file without waiting for a new release -of AVRDUDE. Likewise, if you have a parallel port programmer that is -not supported by AVRDUDE, chances are good that you can copy and -existing programmer definition, and with only a few changes, make your -programmer work with AVRDUDE. +of AVRDUDE. Likewise, if you have a parallel port programmer that is +not supported, chances are that you can copy an +existing programmer definition and, with only a few changes, make your +programmer work. AVRDUDE first looks for a system wide configuration file in a platform dependent location. On Unix, this is usually -@code{/usr/local/etc/avrdude.conf}, while on Windows it is usually in the -same location as the executable file. The name of this file can be -changed using the @option{-C} command line option. After the system wide -configuration file is parsed, AVRDUDE looks for a per-user configuration +@code{/usr/local/etc/avrdude.conf}, whilst on Windows it is usually in the +same location as the executable file. The full name of this file can be +specified using the @option{-C} command line option. After parsing the system wide +configuration file, AVRDUDE looks for a per-user configuration file to augment or override the system wide defaults. On Unix, the -per-user file is @code{.avrduderc} within the user's home directory. On -Windows, this file is the @code{avrdude.rc} file located in the same -directory as the executable. +per-user file is @code{$@{XDG_CONFIG_HOME@}/avrdude/avrdude.rc}, whereas +if @code{$@{XDG_CONFIG_HOME@}} is either not set or empty, +@code{$@{HOME@}/.config/} is used instead. If that does not exists +@code{.avrduderc} within the user's home directory is used. On Windows, +this file is the @code{avrdude.rc} file located in the same directory as +the executable. @menu * AVRDUDE Defaults:: diff --git a/src/main.c b/src/main.c index 73b0a25c..035a15f3 100644 --- a/src/main.c +++ b/src/main.c @@ -425,6 +425,32 @@ static void exit_part_not_found(const char *partdesc) { } +#if !defined(WIN32) +// Safely concatenate dir/file into dst that has size n +static char *concatpath(char *dst, char *dir, char *file, size_t n) { + // Dir or file empty? + if(!dir || !*dir || !file || !*file) + return NULL; + + size_t len = strlen(dir); + + // Insufficient space? + if(len + (dir[len-1] != '/') + strlen(file) > n-1) + return NULL; + + if(dst != dir) + strcpy(dst, dir); + + if(dst[len-1] != '/') + strcat(dst, "/"); + + strcat(dst, file); + + return dst; +} +#endif + + /* * main routine */ @@ -465,10 +491,6 @@ int main(int argc, char * argv []) char * logfile; /* Use logfile rather than stderr for diagnostics */ enum updateflags uflags = UF_AUTO_ERASE | UF_VERIFY; /* Flags for do_op() */ -#if !defined(WIN32) - char * homedir; -#endif - #ifdef _MSC_VER _set_printf_count_output(1); #endif @@ -856,14 +878,10 @@ int main(int argc, char * argv []) win_usr_config_set(usr_config); #else usr_config[0] = 0; - homedir = getenv("HOME"); - if (homedir != NULL) { - strcpy(usr_config, homedir); - i = strlen(usr_config); - if (i && (usr_config[i - 1] != '/')) - strcat(usr_config, "/"); - strcat(usr_config, USER_CONF_FILE); - } + if(!concatpath(usr_config, getenv("XDG_CONFIG_HOME"), XDG_USER_CONF_FILE, sizeof usr_config)) + concatpath(usr_config, getenv("HOME"), ".config/" XDG_USER_CONF_FILE, sizeof usr_config); + if(stat(usr_config, &sb) < 0 || (sb.st_mode & S_IFREG) == 0) + concatpath(usr_config, getenv("HOME"), USER_CONF_FILE, sizeof usr_config); #endif if (quell_progress == 0)