hirc

IRC client
Log | Files | Refs

commit 3bae42cb7ce0f670bde29fb736fa384c9e0dd6cd
parent 5b969c3978df97a00e75b157f38513408b1f551a
Author: hhvn <dev@hhvn.uk>
Date:   Thu, 23 Dec 2021 13:54:12 +0000

s/commands.c s/config.c: /source

Diffstat:
Msrc/commands.c | 14++++++++++++++
Msrc/config.c | 50++++++++++++++++++++++++++++++++++++++++++++++++--
2 files changed, 62 insertions(+), 2 deletions(-)

diff --git a/src/commands.c b/src/commands.c @@ -62,6 +62,7 @@ static void command_grep(struct Server *server, char *str); static void command_clear(struct Server *server, char *str); static void command_alias(struct Server *server, char *str); static void command_scroll(struct Server *server, char *str); +static void command_source(struct Server *server, char *str); static char *command_optarg; enum { @@ -185,6 +186,9 @@ struct Command commands[] = { "Scroll a window (main by default).", "Positive scrolls up, negative down, 0 resets and tracks", "Probably most useful with /bind", NULL}}, + {"source", command_source, 0, { + "usage: /source <file>", + "Read a config file. Can be used inside config files.", NULL}}, {NULL, NULL}, }; @@ -1164,6 +1168,16 @@ narg: command_toofew("scroll"); } +static void +command_source(struct Server *server, char *str) { + if (!str) { + command_toofew("source"); + return; + } + + config_read(str); +} + int command_getopt(char **str, struct CommandOpts *opts) { char *opt; diff --git a/src/config.c b/src/config.c @@ -21,6 +21,8 @@ #include <string.h> #include <stdlib.h> #include <errno.h> +#include <assert.h> +#include <limits.h> #include "hirc.h" int readingconf = 0; @@ -1329,19 +1331,63 @@ config_set(char *name, char *val) { void config_read(char *filename) { + static char **bt; + static int btoffset = 0; char buf[8192]; + char *path; FILE *file; + int save, i; + if (!filename) + return; + + path = realpath(filename, NULL); + + /* Check if file is already being read */ + if (bt) { + for (i = 0; i < btoffset; i++) { + if (strcmp(path, *(bt + i)) == 0) { + ui_error("recursive read of '%s' is not allowed", filename); + free(path); + return; + } + } + } + + /* Expand bt and add real path */ + if (!bt) + bt = calloc(sizeof(char *), btoffset + 1); + else + bt = reallocarray(bt, sizeof(char *), btoffset + 1); + assert(bt != NULL); + + *(bt + btoffset) = path; + btoffset++; + + /* Read and execute */ if ((file = fopen(filename, "rb")) == NULL) { ui_error("cannot open file '%s': %s", filename, strerror(errno)); - return; + goto shrink; } + save = readingconf; readingconf = 1; while (read_line(fileno(file), buf, sizeof(buf))) if (*buf == '/') command_eval(buf); - readingconf = 0; + readingconf = save; + +shrink: + /* Remove path from bt and shrink */ + free(path); + btoffset--; + if (btoffset == 0) { + free(bt); + bt = NULL; + } else { + bt = reallocarray(bt, sizeof(char *), btoffset); + assert(bt != NULL); + } } static int