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:
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