From 49e4b061a56eeb319e3037f89252678c779156d0 Mon Sep 17 00:00:00 2001 From: Yorhel Date: Sun, 6 Nov 2022 13:37:33 +0100 Subject: [PATCH] Backport configuration file support from 2.x --- doc/ncdu.pod | 23 +++++++++++++++ src/dir_common.c | 2 +- src/exclude.c | 3 +- src/main.c | 76 +++++++++++++++++++++++++++++++++++++++++++++--- src/util.c | 6 ++++ src/util.h | 2 ++ 6 files changed, 105 insertions(+), 7 deletions(-) diff --git a/doc/ncdu.pod b/doc/ncdu.pod index f0c28bd..5d18805 100644 --- a/doc/ncdu.pod +++ b/doc/ncdu.pod @@ -70,6 +70,10 @@ information. This enables viewing and sorting by the latest child mtime, or modified time, using 'm' and 'M', respectively. +=item B<--ignore-config> + +Do not attempt to load any configuration files. + =back =head2 Scan Options @@ -253,6 +257,25 @@ The default is I unless the C environment variable is set. =back +=head1 CONFIGURATION + +Ncdu can be configured by placing command-line options in C or +C<$HOME/.config/ncdu/config>. If both files exist, the system configuration +will be loaded before the user configuration, allowing users to override +options set in the system configuration. Options given on the command line will +override options set in the configuration files. The files will not be read at +all when C<--ignore-config> is given on the command line. + +The configuration file format is simply one command line option per line. Lines +starting with C<#> are ignored. Example configuration file: + + # Always enable extended mode + -e + + # Exclude .git directories + --exclude .git + + =head1 KEYS =over diff --git a/src/dir_common.c b/src/dir_common.c index 0a77260..2acc7ea 100644 --- a/src/dir_common.c +++ b/src/dir_common.c @@ -35,7 +35,7 @@ int (*dir_process)(void); char *dir_curpath; /* Full path of the last seen item. */ struct dir_output dir_output; char *dir_fatalerr; /* Error message on a fatal error. (NULL if there was no fatal error) */ -int dir_ui; /* User interface to use */ +int dir_ui = -1; /* User interface to use */ static int confirm_quit_while_scanning_stage_1_passed; /* Additional check before quitting */ static char *lasterr; /* Path where the last error occurred. */ static int curpathl; /* Allocated length of dir_curpath */ diff --git a/src/exclude.c b/src/exclude.c index c1c018d..b6eb437 100644 --- a/src/exclude.c +++ b/src/exclude.c @@ -46,8 +46,7 @@ void exclude_add(char *pat) { n = &((*n)->next); *n = (struct exclude *) xcalloc(1, sizeof(struct exclude)); - (*n)->pattern = (char *) xmalloc(strlen(pat)+1); - strcpy((*n)->pattern, pat); + (*n)->pattern = xstrdup(pat); } diff --git a/src/main.c b/src/main.c index 30619ec..222514d 100644 --- a/src/main.c +++ b/src/main.c @@ -294,16 +294,81 @@ static void arg_help(void) { } +static void config_read(const char *fn) { + FILE *f; + char buf[1024], *line, *tmp, **args = NULL, **argsi; + int r, len, argslen = 0, argssize = 0; + + if((f = fopen(fn, "r")) == NULL) { + if(errno == ENOENT || errno == ENOTDIR) return; + die("Error opening %s: %s.\nRun with --ignore-config to skip reading config files.\n", fn, strerror(errno)); + } + + while(fgets(buf, 1024, f) != NULL) { + line = buf; + while(*line == ' ' || *line == '\t') line++; + len = strlen(line); + while(len > 0 && (line[len-1] == ' ' || line[len-1] == '\t' || line[len-1] == '\r' || line[len-1] == '\n')) len -= 1; + line[len] = 0; + if(len == 0 || *line == '#') continue; + + /* Reserve at least 3 spots, one for the option, one for a possible argument and one for the final NULL. */ + if(argslen+3 >= argssize) { + argssize = argssize ? argssize*2 : 32; + args = xrealloc(args, sizeof(char *)*argssize); + } + for(tmp=line; *tmp && *tmp != ' ' && *tmp != '\t' && *tmp != '='; tmp++); + while(*tmp && (*tmp == ' ' || *tmp == '\t')) { + *tmp = 0; + tmp++; + } + args[argslen++] = xstrdup(line); + if(*tmp) args[argslen++] = xstrdup(tmp); + } + if(ferror(f)) + die("Error reading from %s: %s\nRun with --ignore-config to skip reading config files.\n", fn, strerror(errno)); + fclose(f); + if(!argslen) return; + + args[argslen] = NULL; + memset(&argparser_state, 0, sizeof(struct argparser)); + argparser_state.argv = args; + argparser_state.argc = argslen; + + while((r = argparser_next(&argparser_state)) > 0) + if(r == 2 || !arg_option()) + die("Unknown option in config file '%s': %s.\nRun with --ignore-config to skip reading config files.\n", fn, argparser_state.last); + + for(argsi=args; argsi && *argsi; argsi++) free(*argsi); + free(args); +} + + +static void config_load(int argc, char **argv) { + char *env, buf[1024]; + int r; + + for(r=0; r 0 && r < 1024) config_read(buf); + } else if((env = getenv("HOME")) != NULL) { + r = snprintf(buf, 1024, "%s/.config/ncdu/config", env); + if(r > 0 && r < 1024) config_read(buf); + } +} + + static void argv_parse(int argc, char **argv) { int r; char *export = NULL; char *import = NULL; char *dir = NULL; - uic_theme = getenv("NO_COLOR") ? 0 : 2; - dir_ui = -1; - si = 0; - memset(&argparser_state, 0, sizeof(struct argparser)); argparser_state.argv = argv; argparser_state.argc = argc; @@ -317,6 +382,7 @@ static void argv_parse(int argc, char **argv) { } else if(OPT("-h") || OPT("-?") || OPT("--help")) arg_help(); else if(OPT("-o")) export = ARG; else if(OPT("-f")) import = ARG; + else if(OPT("--ignore-config")) {} else if(!arg_option()) die("Unknown option '%s'.\n", argparser_state.last); } @@ -392,6 +458,8 @@ void close_nc(void) { int main(int argc, char **argv) { read_locale(); + uic_theme = getenv("NO_COLOR") ? 0 : 2; + config_load(argc, argv); argv_parse(argc, argv); if(dir_ui == 2) diff --git a/src/util.c b/src/util.c index ed20b69..16f7a39 100644 --- a/src/util.c +++ b/src/util.c @@ -449,3 +449,9 @@ void addparentstats(struct dir *d, int64_t size, int64_t asize, uint64_t mtime, void *xmalloc(size_t size) { wrap_oom(malloc(size)) } void *xcalloc(size_t n, size_t size) { wrap_oom(calloc(n, size)) } void *xrealloc(void *mem, size_t size) { wrap_oom(realloc(mem, size)) } + +char *xstrdup(const char *str) { + char *r = xmalloc(strlen(str)+1); + strcpy(r, str); + return r; +} diff --git a/src/util.h b/src/util.h index 516c5e7..4d69951 100644 --- a/src/util.h +++ b/src/util.h @@ -188,5 +188,7 @@ void *xmalloc(size_t); void *xcalloc(size_t, size_t); void *xrealloc(void *, size_t); +char *xstrdup(const char *); + #endif