config: enable user to specify path to configuration file

This commit is contained in:
Daniel Eklöf 2019-12-17 19:08:43 +01:00
parent d15631e3de
commit caa76bcdea
No known key found for this signature in database
GPG key ID: 5BBD4992C116573F
3 changed files with 65 additions and 35 deletions

View file

@ -463,7 +463,7 @@ get_server_socket_path(void)
} }
bool bool
config_load(struct config *conf) config_load(struct config *conf, const char *conf_path)
{ {
bool ret = false; bool ret = false;
@ -513,28 +513,35 @@ config_load(struct config *conf)
.server_socket_path = get_server_socket_path(), .server_socket_path = get_server_socket_path(),
}; };
char *path = get_config_path(); char *default_path = NULL;
if (path == NULL) { if (conf_path == NULL) {
/* Default conf */ if ((default_path = get_config_path()) == NULL) {
LOG_WARN("no configuration found, using defaults"); /* Default conf */
ret = true; LOG_WARN("no configuration found, using defaults");
goto out; ret = true;
goto out;
}
conf_path = default_path;
} }
LOG_DBG("loading configuration from %s", path); assert(conf_path != NULL);
LOG_INFO("loading configuration from %s", conf_path);
FILE *f = fopen(path, "r"); FILE *f = fopen(conf_path, "r");
if (f == NULL) { if (f == NULL) {
LOG_ERR("%s: failed to open", path); LOG_ERR("%s: failed to open", conf_path);
goto out; goto out;
} }
ret = parse_config_file(f, conf, path); ret = parse_config_file(f, conf, conf_path);
fclose(f); fclose(f);
if (ret && tll_length(conf->fonts) == 0)
tll_push_back(conf->fonts, strdup("monospace"));
out: out:
tll_push_back(conf->fonts, strdup("monospace")); free(default_path);
free(path);
return ret; return ret;
} }

View file

@ -38,5 +38,5 @@ struct config {
char *server_socket_path; char *server_socket_path;
}; };
bool config_load(struct config *conf); bool config_load(struct config *conf, const char *path);
void config_free(struct config conf); void config_free(struct config conf);

65
main.c
View file

@ -38,7 +38,8 @@ print_usage(const char *prog_name)
printf("Usage: %s [OPTIONS]... -- command\n", prog_name); printf("Usage: %s [OPTIONS]... -- command\n", prog_name);
printf("\n"); printf("\n");
printf("Options:\n"); printf("Options:\n");
printf(" -f,--font=FONT comma separated list of fonts in fontconfig format (monospace)\n" printf(" -c,--config=PATH load configuration from PATH (XDG_CONFIG_HOME/footrc)\n"
" -f,--font=FONT comma separated list of fonts in fontconfig format (monospace)\n"
" -t,--term=TERM value to set the environment variable TERM to (foot)\n" " -t,--term=TERM value to set the environment variable TERM to (foot)\n"
" -g,--geometry=WIDTHxHEIGHT set initial width and height\n" " -g,--geometry=WIDTHxHEIGHT set initial width and height\n"
" -s,--server[=PATH] run as a server (use 'footclient' to start terminals).\n" " -s,--server[=PATH] run as a server (use 'footclient' to start terminals).\n"
@ -68,13 +69,10 @@ main(int argc, char *const *argv)
* don't pass this on to programs launched by us */ * don't pass this on to programs launched by us */
unsetenv("DESKTOP_STARTUP_ID"); unsetenv("DESKTOP_STARTUP_ID");
struct config conf = {NULL};
if (!config_load(&conf))
return ret;
const char *const prog_name = argv[0]; const char *const prog_name = argv[0];
static const struct option longopts[] = { static const struct option longopts[] = {
{"config", required_argument, 0, 'c'},
{"term", required_argument, 0, 't'}, {"term", required_argument, 0, 't'},
{"font", required_argument, 0, 'f'}, {"font", required_argument, 0, 'f'},
{"geometry", required_argument, 0, 'g'}, {"geometry", required_argument, 0, 'g'},
@ -84,21 +82,30 @@ main(int argc, char *const *argv)
{NULL, no_argument, 0, 0}, {NULL, no_argument, 0, 0},
}; };
const char *conf_path = NULL;
const char *conf_term = NULL;
tll(char *) conf_fonts = tll_init();
int conf_width = -1;
int conf_height = -1;
bool as_server = false; bool as_server = false;
const char *conf_server_socket_path = NULL;
while (true) { while (true) {
int c = getopt_long(argc, argv, ":t:f:g:s::vh", longopts, NULL); int c = getopt_long(argc, argv, ":c:tf:g:s::vh", longopts, NULL);
if (c == -1) if (c == -1)
break; break;
switch (c) { switch (c) {
case 'c':
conf_path = optarg;
break;
case 't': case 't':
free(conf.term); conf_term = optarg;
conf.term = strdup(optarg);
break; break;
case 'f': case 'f':
tll_free_and_free(conf.fonts, free); tll_free_and_free(conf_fonts, free);
for (char *font = strtok(optarg, ","); font != NULL; font = strtok(NULL, ",")) { for (char *font = strtok(optarg, ","); font != NULL; font = strtok(NULL, ",")) {
/* Strip leading spaces */ /* Strip leading spaces */
@ -115,7 +122,7 @@ main(int argc, char *const *argv)
if (strlen(font) == 0) if (strlen(font) == 0)
continue; continue;
tll_push_back(conf.fonts, strdup(font)); tll_push_back(conf_fonts, strdup(font));
} }
break; break;
@ -123,41 +130,34 @@ main(int argc, char *const *argv)
unsigned width, height; unsigned width, height;
if (sscanf(optarg, "%ux%u", &width, &height) != 2 || width == 0 || height == 0) { if (sscanf(optarg, "%ux%u", &width, &height) != 2 || width == 0 || height == 0) {
fprintf(stderr, "error: invalid geometry: %s\n", optarg); fprintf(stderr, "error: invalid geometry: %s\n", optarg);
config_free(conf);
return EXIT_FAILURE; return EXIT_FAILURE;
} }
conf.width = width; conf_width = width;
conf.height = height; conf_height = height;
break; break;
} }
case 's': case 's':
as_server = true; as_server = true;
if (optarg != NULL) { if (optarg != NULL)
free(conf.server_socket_path); conf_server_socket_path = optarg;
conf.server_socket_path = strdup(optarg);
}
break; break;
case 'v': case 'v':
printf("foot version %s\n", FOOT_VERSION); printf("foot version %s\n", FOOT_VERSION);
config_free(conf);
return EXIT_SUCCESS; return EXIT_SUCCESS;
case 'h': case 'h':
print_usage(prog_name); print_usage(prog_name);
config_free(conf);
return EXIT_SUCCESS; return EXIT_SUCCESS;
case ':': case ':':
fprintf(stderr, "error: -%c: missing required argument\n", optopt); fprintf(stderr, "error: -%c: missing required argument\n", optopt);
config_free(conf);
return EXIT_FAILURE; return EXIT_FAILURE;
case '?': case '?':
fprintf(stderr, "error: -%c: invalid option\n", optopt); fprintf(stderr, "error: -%c: invalid option\n", optopt);
config_free(conf);
return EXIT_FAILURE; return EXIT_FAILURE;
} }
} }
@ -169,6 +169,29 @@ main(int argc, char *const *argv)
setlocale(LC_ALL, ""); setlocale(LC_ALL, "");
struct config conf = {NULL};
if (!config_load(&conf, conf_path))
return ret;
if (conf_term != NULL) {
free(conf.term);
conf.term = strdup(conf_term);
}
if (tll_length(conf_fonts) > 0) {
tll_free_and_free(conf.fonts, free);
tll_foreach(conf_fonts, it)
tll_push_back(conf.fonts, it->item);
tll_free(conf_fonts);
}
if (conf_width > 0)
conf.width = conf_width;
if (conf_height > 0)
conf.height = conf_height;
if (conf_server_socket_path != NULL) {
free(conf.server_socket_path);
conf.server_socket_path = strdup(conf_server_socket_path);
}
struct fdm *fdm = NULL; struct fdm *fdm = NULL;
struct wayland *wayl = NULL; struct wayland *wayl = NULL;
struct terminal *term = NULL; struct terminal *term = NULL;