]>
Dogcows Code - chaz/openbox/blob - obt/paths.c
f723ae2c247feb0a62ac94edefdd36cf24499946
1 /* -*- indent-tabs-mode: nil; tab-width: 4; c-basic-offset: 4; -*-
3 obt/paths.c for the Openbox window manager
4 Copyright (c) 2003-2007 Dana Jansens
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2 of the License, or
9 (at your option) any later version.
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 See the COPYING file for a copy of the GNU General Public License.
19 #include "obt/paths.h"
22 #ifdef HAVE_SYS_STAT_H
23 # include <sys/stat.h>
25 #ifdef HAVE_SYS_TYPES_H
26 # include <sys/types.h>
49 GSList
*autostart_dirs
;
57 static gint
slist_path_cmp(const gchar
*a
, const gchar
*b
)
62 typedef GSList
* (*GSListFunc
) (gpointer list
, gconstpointer data
);
64 static GSList
* slist_path_add(GSList
*list
, gpointer data
, GSListFunc func
)
71 if (!g_slist_find_custom(list
, data
, (GCompareFunc
) slist_path_cmp
))
72 list
= func(list
, data
);
79 static GSList
* split_paths(const gchar
*paths
)
86 spl
= g_strsplit(paths
, ":", -1);
87 for (it
= spl
; *it
; ++it
)
88 list
= slist_path_add(list
, *it
, (GSListFunc
) g_slist_append
);
93 static void find_uid_gid(uid_t
*u
, gid_t
**g
, guint
*n
)
103 *g
= g_new(gid_t
, *n
=1);
106 while ((gr
= getgrent())) {
107 if (gr
->gr_gid
!= (*g
)[0]) { /* skip the main group */
109 for (c
= gr
->gr_mem
; *c
; ++c
)
110 if (strcmp(*c
, name
) == 0) {
111 *g
= g_renew(gid_t
, *g
, ++(*n
)); /* save the group */
112 (*g
)[*n
-1] = gr
->gr_gid
;
120 ObtPaths
* obt_paths_new(void)
126 p
= g_slice_new0(ObtPaths
);
129 find_uid_gid(&p
->uid
, &p
->gid
, &p
->n_gid
);
131 path
= g_getenv("XDG_CONFIG_HOME");
132 if (path
&& path
[0] != '\0') /* not unset or empty */
133 p
->config_home
= g_build_filename(path
, NULL
);
135 p
->config_home
= g_build_filename(g_get_home_dir(), ".config", NULL
);
137 path
= g_getenv("XDG_DATA_HOME");
138 if (path
&& path
[0] != '\0') /* not unset or empty */
139 p
->data_home
= g_build_filename(path
, NULL
);
141 p
->data_home
= g_build_filename(g_get_home_dir(), ".local",
144 path
= g_getenv("XDG_CACHE_HOME");
145 if (path
&& path
[0] != '\0') /* not unset or empty */
146 p
->cache_home
= g_build_filename(path
, NULL
);
148 p
->cache_home
= g_build_filename(g_get_home_dir(), ".cache", NULL
);
150 path
= g_getenv("XDG_CONFIG_DIRS");
151 if (path
&& path
[0] != '\0') /* not unset or empty */
152 p
->config_dirs
= split_paths(path
);
154 p
->config_dirs
= slist_path_add(p
->config_dirs
,
156 (GSListFunc
) g_slist_append
);
157 p
->config_dirs
= slist_path_add(p
->config_dirs
,
161 (GSListFunc
) g_slist_append
);
163 p
->config_dirs
= slist_path_add(p
->config_dirs
,
164 g_strdup(p
->config_home
),
165 (GSListFunc
) g_slist_prepend
);
167 for (it
= p
->config_dirs
; it
; it
= g_slist_next(it
)) {
168 gchar
*const s
= g_strdup_printf("%s/autostart", (gchar
*)it
->data
);
169 p
->autostart_dirs
= g_slist_append(p
->autostart_dirs
, s
);
172 path
= g_getenv("XDG_DATA_DIRS");
173 if (path
&& path
[0] != '\0') /* not unset or empty */
174 p
->data_dirs
= split_paths(path
);
176 p
->data_dirs
= slist_path_add(p
->data_dirs
,
178 (GSListFunc
) g_slist_append
);
179 p
->data_dirs
= slist_path_add(p
->data_dirs
,
182 "usr", "local", "share", NULL
),
183 (GSListFunc
) g_slist_append
);
184 p
->data_dirs
= slist_path_add(p
->data_dirs
,
187 "usr", "share", NULL
),
188 (GSListFunc
) g_slist_append
);
190 p
->data_dirs
= slist_path_add(p
->data_dirs
,
191 g_strdup(p
->data_home
),
192 (GSListFunc
) g_slist_prepend
);
194 path
= g_getenv("PATH");
195 if (path
&& path
[0] != '\0') /* not unset or empty */
196 p
->exec_dirs
= split_paths(path
);
203 void obt_paths_ref(ObtPaths
*p
)
208 void obt_paths_unref(ObtPaths
*p
)
210 if (p
&& --p
->ref
== 0) {
213 for (it
= p
->config_dirs
; it
; it
= g_slist_next(it
))
215 g_slist_free(p
->config_dirs
);
216 for (it
= p
->data_dirs
; it
; it
= g_slist_next(it
))
218 g_slist_free(p
->data_dirs
);
219 for (it
= p
->autostart_dirs
; it
; it
= g_slist_next(it
))
221 g_slist_free(p
->autostart_dirs
);
222 g_free(p
->config_home
);
223 g_free(p
->data_home
);
224 g_free(p
->cache_home
);
226 g_slice_free(ObtPaths
, p
);
230 gchar
*obt_paths_expand_tilde(const gchar
*f
)
238 regex
= g_regex_new("(?:^|(?<=[ \\t]))~(?=[/ \\t$])", G_REGEX_MULTILINE
| G_REGEX_RAW
, 0, NULL
);
239 ret
= g_regex_replace_literal(regex
, f
, -1, 0, g_get_home_dir(), 0, NULL
);
240 g_regex_unref(regex
);
245 gboolean
obt_paths_mkdir(const gchar
*path
, gint mode
)
249 g_return_val_if_fail(path
!= NULL
, FALSE
);
250 g_return_val_if_fail(path
[0] != '\0', FALSE
);
252 if (!g_file_test(path
, G_FILE_TEST_IS_DIR
))
253 if (mkdir(path
, mode
) == -1)
259 gboolean
obt_paths_mkdir_path(const gchar
*path
, gint mode
)
263 g_return_val_if_fail(path
!= NULL
, FALSE
);
264 g_return_val_if_fail(path
[0] == '/', FALSE
);
266 if (!g_file_test(path
, G_FILE_TEST_IS_DIR
)) {
271 while ((e
= strchr(e
+ 1, '/'))) {
273 if (!(ret
= obt_paths_mkdir(c
, mode
)))
274 goto parse_mkdir_path_end
;
277 ret
= obt_paths_mkdir(c
, mode
);
279 parse_mkdir_path_end
:
286 const gchar
* obt_paths_config_home(ObtPaths
*p
)
288 return p
->config_home
;
291 const gchar
* obt_paths_data_home(ObtPaths
*p
)
296 const gchar
* obt_paths_cache_home(ObtPaths
*p
)
298 return p
->cache_home
;
301 GSList
* obt_paths_config_dirs(ObtPaths
*p
)
303 return p
->config_dirs
;
306 GSList
* obt_paths_data_dirs(ObtPaths
*p
)
311 GSList
* obt_paths_autostart_dirs(ObtPaths
*p
)
313 return p
->autostart_dirs
;
316 static inline gboolean
try_exec(const ObtPaths
*const p
,
317 const gchar
*const path
)
324 if (!S_ISREG(st
.st_mode
))
326 if (st
.st_uid
== p
->uid
)
327 return st
.st_mode
& S_IXUSR
;
328 for (i
= 0; i
< p
->n_gid
; ++i
)
329 if (st
.st_gid
== p
->gid
[i
])
330 return st
.st_mode
& S_IXGRP
;
331 return st
.st_mode
& S_IXOTH
;
334 gboolean
obt_paths_try_exec(ObtPaths
*p
, const gchar
*path
)
336 if (path
[0] == '/') {
337 return try_exec(p
, path
);
342 for (it
= p
->exec_dirs
; it
; it
= g_slist_next(it
)) {
343 gchar
*f
= g_strdup_printf(it
->data
, G_DIR_SEPARATOR_S
, path
);
344 gboolean e
= try_exec(p
, f
);
This page took 0.053949 seconds and 3 git commands to generate.