X-Git-Url: https://git.dogcows.com/gitweb?a=blobdiff_plain;f=obt%2Fpaths.c;h=25cb6b0eb58c7a4c415f3c24dd7dd2d9d8da8498;hb=f6fb70a4b95d0289aa642bc4c2dd0fba31511e94;hp=68615433e1d9426dc58cdf462050cbe89937cf6c;hpb=acafa38c8ea210b12ed92fc16281b915ab61542c;p=chaz%2Fopenbox diff --git a/obt/paths.c b/obt/paths.c index 68615433..25cb6b0e 100644 --- a/obt/paths.c +++ b/obt/paths.c @@ -16,9 +16,13 @@ See the COPYING file for a copy of the GNU General Public License. */ +#include "obt/bsearch.h" #include "obt/paths.h" #include "obt/util.h" +#ifdef HAVE_STDLIB_H +# include +#endif #ifdef HAVE_SYS_STAT_H # include #endif @@ -28,6 +32,15 @@ #ifdef HAVE_STRING_H # include #endif +#ifdef HAVE_UNISTD_H +# include +#endif +#ifdef HAVE_GRP_H +# include +#endif +#ifdef HAVE_PWD_H +# include +#endif struct _ObtPaths { @@ -37,6 +50,12 @@ struct _ObtPaths gchar *cache_home; GSList *config_dirs; GSList *data_dirs; + GSList *autostart_dirs; + GSList *exec_dirs; + + uid_t uid; + gid_t *gid; + guint n_gid; }; static gint slist_path_cmp(const gchar *a, const gchar *b) @@ -69,20 +88,60 @@ static GSList* split_paths(const gchar *paths) if (!paths) return NULL; spl = g_strsplit(paths, ":", -1); - for (it = spl; *it; ++it) - list = slist_path_add(list, *it, (GSListFunc) g_slist_append); + for (it = spl; *it; ++it) { + if ((*it)[0]) /* skip empty strings */ + list = slist_path_add(list, *it, (GSListFunc) g_slist_append); + } g_free(spl); return list; } +int gid_cmp(const void *va, const void *vb) +{ + const gid_t a = *(const gid_t*)va, b = *(const gid_t*)vb; + return a>b ? 1 : (a == b ? 0 : -1); +} + +static void find_uid_gid(uid_t *u, gid_t **g, guint *n) +{ + struct passwd *pw; + const gchar *name; + struct group *gr; + + *u = getuid(); + pw = getpwuid(*u); + name = pw->pw_name; + + *g = g_new(gid_t, *n=1); + (*g)[0] = getgid(); + + while ((gr = getgrent())) { + if (gr->gr_gid != (*g)[0]) { /* skip the main group */ + gchar **c; + for (c = gr->gr_mem; *c; ++c) + if (strcmp(*c, name) == 0) { + *g = g_renew(gid_t, *g, ++(*n)); /* save the group */ + (*g)[*n-1] = gr->gr_gid; + break; + } + } + } + endgrent(); + + qsort(*g, *n, sizeof(gid_t), gid_cmp); +} + ObtPaths* obt_paths_new(void) { ObtPaths *p; const gchar *path; + GSList *it; - p = g_new0(ObtPaths, 1); + p = g_slice_new0(ObtPaths); p->ref = 1; + find_uid_gid(&p->uid, &p->gid, &p->n_gid); + path = g_getenv("XDG_CONFIG_HOME"); if (path && path[0] != '\0') /* not unset or empty */ p->config_home = g_build_filename(path, NULL); @@ -119,6 +178,11 @@ ObtPaths* obt_paths_new(void) g_strdup(p->config_home), (GSListFunc) g_slist_prepend); + for (it = p->config_dirs; it; it = g_slist_next(it)) { + gchar *const s = g_strdup_printf("%s/autostart", (gchar*)it->data); + p->autostart_dirs = g_slist_append(p->autostart_dirs, s); + } + path = g_getenv("XDG_DATA_DIRS"); if (path && path[0] != '\0') /* not unset or empty */ p->data_dirs = split_paths(path); @@ -140,6 +204,13 @@ ObtPaths* obt_paths_new(void) p->data_dirs = slist_path_add(p->data_dirs, g_strdup(p->data_home), (GSListFunc) g_slist_prepend); + + path = g_getenv("PATH"); + if (path && path[0] != '\0') /* not unset or empty */ + p->exec_dirs = split_paths(path); + else + p->exec_dirs = NULL; + return p; } @@ -159,11 +230,18 @@ void obt_paths_unref(ObtPaths *p) for (it = p->data_dirs; it; it = g_slist_next(it)) g_free(it->data); g_slist_free(p->data_dirs); + for (it = p->autostart_dirs; it; it = g_slist_next(it)) + g_free(it->data); + g_slist_free(p->autostart_dirs); + for (it = p->exec_dirs; it; it = g_slist_next(it)) + g_free(it->data); + g_slist_free(p->exec_dirs); g_free(p->config_home); g_free(p->data_home); g_free(p->cache_home); + g_free(p->gid); - obt_free0(p, ObtPaths, 1); + g_slice_free(ObtPaths, p); } } @@ -247,3 +325,46 @@ GSList* obt_paths_data_dirs(ObtPaths *p) { return p->data_dirs; } + +GSList* obt_paths_autostart_dirs(ObtPaths *p) +{ + return p->autostart_dirs; +} + +static inline gboolean try_exec(const ObtPaths *const p, + const gchar *const path) +{ + struct stat st; + BSEARCH_SETUP(); + + if (stat(path, &st) != 0) + return FALSE; + + if (!S_ISREG(st.st_mode)) + return FALSE; + if (st.st_uid == p->uid) + return st.st_mode & S_IXUSR; + BSEARCH(guint, p->gid, 0, p->n_gid, st.st_gid); + if (BSEARCH_FOUND()) + return st.st_mode & S_IXGRP; + return st.st_mode & S_IXOTH; +} + +gboolean obt_paths_try_exec(ObtPaths *p, const gchar *path) +{ + if (path[0] == '/') { + return try_exec(p, path); + } + else { + GSList *it; + + for (it = p->exec_dirs; it; it = g_slist_next(it)) { + gchar *f = g_build_filename(it->data, path, NULL); + gboolean e = try_exec(p, f); + g_free(f); + if (e) return TRUE; + } + } + + return FALSE; +}