Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Move resolve_tilde and get_config_path into libi3 #1600

Merged
merged 1 commit into from Mar 29, 2015
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
32 changes: 0 additions & 32 deletions i3-config-wizard/main.c
Expand Up @@ -461,38 +461,6 @@ void errorlog(char *fmt, ...) {
void debuglog(char *fmt, ...) {
}

/*
* This function resolves ~ in pathnames.
* It may resolve wildcards in the first part of the path, but if no match
* or multiple matches are found, it just returns a copy of path as given.
*
*/
static char *resolve_tilde(const char *path) {
static glob_t globbuf;
char *head, *tail, *result;

tail = strchr(path, '/');
head = strndup(path, tail ? (size_t)(tail - path) : strlen(path));

int res = glob(head, GLOB_TILDE, NULL, &globbuf);
free(head);
/* no match, or many wildcard matches are bad */
if (res == GLOB_NOMATCH || globbuf.gl_pathc != 1)
result = strdup(path);
else if (res != 0) {
err(1, "glob() failed");
} else {
head = globbuf.gl_pathv[0];
result = calloc(1, strlen(head) + (tail ? strlen(tail) : 0) + 1);
strncpy(result, head, strlen(head));
if (tail)
strncat(result, tail, strlen(tail));
}
globfree(&globbuf);

return result;
}

/*
* Handles expose events, that is, draws the window contents.
*
Expand Down
18 changes: 18 additions & 0 deletions include/libi3.h
Expand Up @@ -434,3 +434,21 @@ char *get_exe_path(const char *argv0);
*
*/
int logical_px(const int logical);

/**
* This function resolves ~ in pathnames.
* It may resolve wildcards in the first part of the path, but if no match
* or multiple matches are found, it just returns a copy of path as given.
*
*/
char *resolve_tilde(const char *path);

/**
* Get the path of the first configuration file found. If override_configpath
* is specified, that path is returned and saved for further calls. Otherwise,
* checks the home directory first, then the system directory first, always
* taking into account the XDG Base Directory Specification ($XDG_CONFIG_HOME,
* $XDG_CONFIG_DIRS)
*
*/
char *get_config_path(const char *override_configpath, bool use_system_paths);
8 changes: 0 additions & 8 deletions include/util.h
Expand Up @@ -106,14 +106,6 @@ void exec_i3_utility(char *name, char *argv[]);
void check_error(xcb_connection_t *conn, xcb_void_cookie_t cookie,
char *err_message);

/**
* This function resolves ~ in pathnames.
* It may resolve wildcards in the first part of the path, but if no match
* or multiple matches are found, it just returns a copy of path as given.
*
*/
char *resolve_tilde(const char *path);

/**
* Checks if the given path exists by calling stat().
*
Expand Down
91 changes: 91 additions & 0 deletions libi3/get_config_path.c
@@ -0,0 +1,91 @@
/*
* vim:ts=4:sw=4:expandtab
*
* i3 - an improved dynamic tiling window manager
* © 2009-2015 Michael Stapelberg and contributors (see also: LICENSE)
*
*/
#include "libi3.h"
#include <stdlib.h>
#include <string.h>
#include <sys/stat.h>

/*
* Checks if the given path exists by calling stat().
*
*/
static bool path_exists(const char *path) {
struct stat buf;
return (stat(path, &buf) == 0);
}

/*
* Get the path of the first configuration file found. If override_configpath
* is specified, that path is returned and saved for further calls. Otherwise,
* checks the home directory first, then the system directory first, always
* taking into account the XDG Base Directory Specification ($XDG_CONFIG_HOME,
* $XDG_CONFIG_DIRS)
*
*/
char *get_config_path(const char *override_configpath, bool use_system_paths) {
char *xdg_config_home, *xdg_config_dirs, *config_path;

static const char *saved_configpath = NULL;

if (override_configpath != NULL) {
saved_configpath = override_configpath;
return sstrdup(saved_configpath);
}

if (saved_configpath != NULL)
return sstrdup(saved_configpath);

/* 1: check the traditional path under the home directory */
config_path = resolve_tilde("~/.i3/config");
if (path_exists(config_path))
return config_path;
free(config_path);

/* 2: check for $XDG_CONFIG_HOME/i3/config */
if ((xdg_config_home = getenv("XDG_CONFIG_HOME")) == NULL)
xdg_config_home = "~/.config";

xdg_config_home = resolve_tilde(xdg_config_home);
sasprintf(&config_path, "%s/i3/config", xdg_config_home);
free(xdg_config_home);

if (path_exists(config_path))
return config_path;
free(config_path);

/* The below paths are considered system-level, and can be skipped if the
* caller only wants user-level configs. */
if (!use_system_paths)
return NULL;

/* 3: check the traditional path under /etc */
config_path = SYSCONFDIR "/i3/config";
if (path_exists(config_path))
return sstrdup(config_path);

/* 4: check for $XDG_CONFIG_DIRS/i3/config */
if ((xdg_config_dirs = getenv("XDG_CONFIG_DIRS")) == NULL)
xdg_config_dirs = "/etc/xdg";

char *buf = sstrdup(xdg_config_dirs);
char *tok = strtok(buf, ":");
while (tok != NULL) {
tok = resolve_tilde(tok);
sasprintf(&config_path, "%s/i3/config", tok);
free(tok);
if (path_exists(config_path)) {
free(buf);
return config_path;
}
free(config_path);
tok = strtok(NULL, ":");
}
free(buf);

return NULL;
}
45 changes: 45 additions & 0 deletions libi3/resolve_tilde.c
@@ -0,0 +1,45 @@
/*
* vim:ts=4:sw=4:expandtab
*
* i3 - an improved dynamic tiling window manager
* © 2009-2015 Michael Stapelberg and contributors (see also: LICENSE)
*
*/

#include "libi3.h"
#include <err.h>
#include <glob.h>
#include <stdlib.h>
#include <string.h>

/*
* This function resolves ~ in pathnames.
* It may resolve wildcards in the first part of the path, but if no match
* or multiple matches are found, it just returns a copy of path as given.
*
*/
char *resolve_tilde(const char *path) {
static glob_t globbuf;
char *head, *tail, *result;

tail = strchr(path, '/');
head = strndup(path, tail ? (size_t)(tail - path) : strlen(path));

int res = glob(head, GLOB_TILDE, NULL, &globbuf);
free(head);
/* no match, or many wildcard matches are bad */
if (res == GLOB_NOMATCH || globbuf.gl_pathc != 1)
result = sstrdup(path);
else if (res != 0) {
err(EXIT_FAILURE, "glob() failed");
} else {
head = globbuf.gl_pathv[0];
result = scalloc(strlen(head) + (tail ? strlen(tail) : 0) + 1);
strncpy(result, head, strlen(head));
if (tail)
strncat(result, tail, strlen(tail));
}
globfree(&globbuf);

return result;
}
74 changes: 6 additions & 68 deletions src/config.c
Expand Up @@ -39,81 +39,19 @@ void update_barconfig() {
}
}

/*
* Get the path of the first configuration file found. If override_configpath
* is specified, that path is returned and saved for further calls. Otherwise,
* checks the home directory first, then the system directory first, always
* taking into account the XDG Base Directory Specification ($XDG_CONFIG_HOME,
* $XDG_CONFIG_DIRS)
*
*/
static char *get_config_path(const char *override_configpath) {
char *xdg_config_home, *xdg_config_dirs, *config_path;

static const char *saved_configpath = NULL;

if (override_configpath != NULL) {
saved_configpath = override_configpath;
return sstrdup(saved_configpath);
}

if (saved_configpath != NULL)
return sstrdup(saved_configpath);

/* 1: check the traditional path under the home directory */
config_path = resolve_tilde("~/.i3/config");
if (path_exists(config_path))
return config_path;
free(config_path);

/* 2: check for $XDG_CONFIG_HOME/i3/config */
if ((xdg_config_home = getenv("XDG_CONFIG_HOME")) == NULL)
xdg_config_home = "~/.config";

xdg_config_home = resolve_tilde(xdg_config_home);
sasprintf(&config_path, "%s/i3/config", xdg_config_home);
free(xdg_config_home);

if (path_exists(config_path))
return config_path;
free(config_path);

/* 3: check the traditional path under /etc */
config_path = SYSCONFDIR "/i3/config";
if (path_exists(config_path))
return sstrdup(config_path);

/* 4: check for $XDG_CONFIG_DIRS/i3/config */
if ((xdg_config_dirs = getenv("XDG_CONFIG_DIRS")) == NULL)
xdg_config_dirs = "/etc/xdg";

char *buf = sstrdup(xdg_config_dirs);
char *tok = strtok(buf, ":");
while (tok != NULL) {
tok = resolve_tilde(tok);
sasprintf(&config_path, "%s/i3/config", tok);
free(tok);
if (path_exists(config_path)) {
free(buf);
return config_path;
}
free(config_path);
tok = strtok(NULL, ":");
}
free(buf);

die("Unable to find the configuration file (looked at "
"~/.i3/config, $XDG_CONFIG_HOME/i3/config, " SYSCONFDIR "/i3/config and $XDG_CONFIG_DIRS/i3/config)");
}

/*
* Finds the configuration file to use (either the one specified by
* override_configpath), the user’s one or the system default) and calls
* parse_file().
*
*/
bool parse_configuration(const char *override_configpath, bool use_nagbar) {
char *path = get_config_path(override_configpath);
char *path = get_config_path(override_configpath, true);
if (path == NULL) {
die("Unable to find the configuration file (looked at "
"~/.i3/config, $XDG_CONFIG_HOME/i3/config, " SYSCONFDIR "/i3/config and $XDG_CONFIG_DIRS/i3/config)");
}

LOG("Parsing configfile %s\n", path);
FREE(current_configpath);
current_configpath = path;
Expand Down
32 changes: 0 additions & 32 deletions src/util.c
Expand Up @@ -159,38 +159,6 @@ void check_error(xcb_connection_t *conn, xcb_void_cookie_t cookie, char *err_mes
}
}

/*
* This function resolves ~ in pathnames.
* It may resolve wildcards in the first part of the path, but if no match
* or multiple matches are found, it just returns a copy of path as given.
*
*/
char *resolve_tilde(const char *path) {
static glob_t globbuf;
char *head, *tail, *result;

tail = strchr(path, '/');
head = strndup(path, tail ? (size_t)(tail - path) : strlen(path));

int res = glob(head, GLOB_TILDE, NULL, &globbuf);
free(head);
/* no match, or many wildcard matches are bad */
if (res == GLOB_NOMATCH || globbuf.gl_pathc != 1)
result = sstrdup(path);
else if (res != 0) {
die("glob() failed");
} else {
head = globbuf.gl_pathv[0];
result = scalloc(strlen(head) + (tail ? strlen(tail) : 0) + 1);
strncpy(result, head, strlen(head));
if (tail)
strncat(result, tail, strlen(tail));
}
globfree(&globbuf);

return result;
}

/*
* Checks if the given path exists by calling stat().
*
Expand Down