1414989183b268337a4f7e329237f3c1fd726d823Petr Machata/*
2414989183b268337a4f7e329237f3c1fd726d823Petr Machata * This file is part of ltrace.
333f0ca5350ccc9ded3a2bfa82a988e9bd640233fPetr Machata * Copyright (C) 2012, 2013 Petr Machata
4414989183b268337a4f7e329237f3c1fd726d823Petr Machata *
5414989183b268337a4f7e329237f3c1fd726d823Petr Machata * This program is free software; you can redistribute it and/or
6414989183b268337a4f7e329237f3c1fd726d823Petr Machata * modify it under the terms of the GNU General Public License as
7414989183b268337a4f7e329237f3c1fd726d823Petr Machata * published by the Free Software Foundation; either version 2 of the
8414989183b268337a4f7e329237f3c1fd726d823Petr Machata * License, or (at your option) any later version.
9414989183b268337a4f7e329237f3c1fd726d823Petr Machata *
10414989183b268337a4f7e329237f3c1fd726d823Petr Machata * This program is distributed in the hope that it will be useful, but
11414989183b268337a4f7e329237f3c1fd726d823Petr Machata * WITHOUT ANY WARRANTY; without even the implied warranty of
12414989183b268337a4f7e329237f3c1fd726d823Petr Machata * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13414989183b268337a4f7e329237f3c1fd726d823Petr Machata * General Public License for more details.
14414989183b268337a4f7e329237f3c1fd726d823Petr Machata *
15414989183b268337a4f7e329237f3c1fd726d823Petr Machata * You should have received a copy of the GNU General Public License
16414989183b268337a4f7e329237f3c1fd726d823Petr Machata * along with this program; if not, write to the Free Software
17414989183b268337a4f7e329237f3c1fd726d823Petr Machata * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
18414989183b268337a4f7e329237f3c1fd726d823Petr Machata * 02110-1301 USA
19414989183b268337a4f7e329237f3c1fd726d823Petr Machata */
20414989183b268337a4f7e329237f3c1fd726d823Petr Machata
21414989183b268337a4f7e329237f3c1fd726d823Petr Machata#define _POSIX_C_SOURCE 200809L
22414989183b268337a4f7e329237f3c1fd726d823Petr Machata#include <sys/types.h>
23414989183b268337a4f7e329237f3c1fd726d823Petr Machata#include <alloca.h>
24414989183b268337a4f7e329237f3c1fd726d823Petr Machata#include <errno.h>
25414989183b268337a4f7e329237f3c1fd726d823Petr Machata#include <pwd.h>
26414989183b268337a4f7e329237f3c1fd726d823Petr Machata#include <stdio.h>
27414989183b268337a4f7e329237f3c1fd726d823Petr Machata#include <stdlib.h>
28414989183b268337a4f7e329237f3c1fd726d823Petr Machata#include <string.h>
29414989183b268337a4f7e329237f3c1fd726d823Petr Machata#include <unistd.h>
30414989183b268337a4f7e329237f3c1fd726d823Petr Machata
31b3d6180e6d1cfc188a44b60dda6a7ac4faf0fdcePetr Machata#include "backend.h"
32414989183b268337a4f7e329237f3c1fd726d823Petr Machata#include "dict.h"
33414989183b268337a4f7e329237f3c1fd726d823Petr Machata#include "options.h"
34b3d6180e6d1cfc188a44b60dda6a7ac4faf0fdcePetr Machata#include "sysdep.h"
35b3d6180e6d1cfc188a44b60dda6a7ac4faf0fdcePetr Machata#include "vect.h"
36414989183b268337a4f7e329237f3c1fd726d823Petr Machata
37414989183b268337a4f7e329237f3c1fd726d823Petr Machatastatic char *
38414989183b268337a4f7e329237f3c1fd726d823Petr Machataappend(const char *str1, const char *str2)
39414989183b268337a4f7e329237f3c1fd726d823Petr Machata{
40414989183b268337a4f7e329237f3c1fd726d823Petr Machata	char *ret = malloc(strlen(str1) + strlen(str2) + 2);
41414989183b268337a4f7e329237f3c1fd726d823Petr Machata	if (ret == NULL)
42414989183b268337a4f7e329237f3c1fd726d823Petr Machata		return ret;
436bc89fea4e132d3937dd5aafbabca0d12e3af22fChristopher Ferris	strcpy(stpcpy(ret, str1), str2);
44414989183b268337a4f7e329237f3c1fd726d823Petr Machata	return ret;
45414989183b268337a4f7e329237f3c1fd726d823Petr Machata}
46414989183b268337a4f7e329237f3c1fd726d823Petr Machata
47414989183b268337a4f7e329237f3c1fd726d823Petr Machatastatic void
48414989183b268337a4f7e329237f3c1fd726d823Petr Machataadd_dir(struct vect *dirs, const char *str1, const char *str2)
49414989183b268337a4f7e329237f3c1fd726d823Petr Machata{
50414989183b268337a4f7e329237f3c1fd726d823Petr Machata	char *dir = append(str1, str2);
51414989183b268337a4f7e329237f3c1fd726d823Petr Machata	if (dir != NULL
52414989183b268337a4f7e329237f3c1fd726d823Petr Machata	    && VECT_PUSHBACK(dirs, &dir) < 0)
53414989183b268337a4f7e329237f3c1fd726d823Petr Machata		fprintf(stderr,
54414989183b268337a4f7e329237f3c1fd726d823Petr Machata			"Couldn't store candidate config directory %s%s: %s.\n",
55414989183b268337a4f7e329237f3c1fd726d823Petr Machata			str1, str2, strerror(errno));
56414989183b268337a4f7e329237f3c1fd726d823Petr Machata}
57414989183b268337a4f7e329237f3c1fd726d823Petr Machata
58414989183b268337a4f7e329237f3c1fd726d823Petr Machatastatic enum callback_status
59414989183b268337a4f7e329237f3c1fd726d823Petr Machataadd_dir_component_cb(struct opt_F_t *entry, void *data)
60414989183b268337a4f7e329237f3c1fd726d823Petr Machata{
61414989183b268337a4f7e329237f3c1fd726d823Petr Machata	struct vect *dirs = data;
62414989183b268337a4f7e329237f3c1fd726d823Petr Machata	if (opt_F_get_kind(entry) == OPT_F_DIR)
63414989183b268337a4f7e329237f3c1fd726d823Petr Machata		add_dir(dirs, entry->pathname, "/ltrace");
64414989183b268337a4f7e329237f3c1fd726d823Petr Machata	return CBS_CONT;
65414989183b268337a4f7e329237f3c1fd726d823Petr Machata}
66414989183b268337a4f7e329237f3c1fd726d823Petr Machata
67414989183b268337a4f7e329237f3c1fd726d823Petr Machatastatic void
68414989183b268337a4f7e329237f3c1fd726d823Petr Machatadestroy_opt_F_cb(struct opt_F_t *entry, void *data)
69414989183b268337a4f7e329237f3c1fd726d823Petr Machata{
70414989183b268337a4f7e329237f3c1fd726d823Petr Machata	opt_F_destroy(entry);
71414989183b268337a4f7e329237f3c1fd726d823Petr Machata}
72414989183b268337a4f7e329237f3c1fd726d823Petr Machata
73364753a1cfe46998946a42badd9099591a00325aPetr Machatastatic char *g_home_dir = NULL;
74364753a1cfe46998946a42badd9099591a00325aPetr Machata
75414989183b268337a4f7e329237f3c1fd726d823Petr Machataint
76414989183b268337a4f7e329237f3c1fd726d823Petr Machataos_get_config_dirs(int private, const char ***retp)
77414989183b268337a4f7e329237f3c1fd726d823Petr Machata{
78414989183b268337a4f7e329237f3c1fd726d823Petr Machata	/* Vector of char *.  Contains first pointers to local paths,
79414989183b268337a4f7e329237f3c1fd726d823Petr Machata	 * then NULL, then pointers to system paths, then another
80414989183b268337a4f7e329237f3c1fd726d823Petr Machata	 * NULL.  SYS_START points to the beginning of the second
81414989183b268337a4f7e329237f3c1fd726d823Petr Machata	 * part.  */
82414989183b268337a4f7e329237f3c1fd726d823Petr Machata	static struct vect dirs;
83414989183b268337a4f7e329237f3c1fd726d823Petr Machata	static ssize_t sys_start = 0;
84414989183b268337a4f7e329237f3c1fd726d823Petr Machata
85414989183b268337a4f7e329237f3c1fd726d823Petr Machataagain:
86414989183b268337a4f7e329237f3c1fd726d823Petr Machata	if (sys_start != 0) {
87414989183b268337a4f7e329237f3c1fd726d823Petr Machata		if (sys_start == -1)
88414989183b268337a4f7e329237f3c1fd726d823Petr Machata			return -1;
89414989183b268337a4f7e329237f3c1fd726d823Petr Machata
90364753a1cfe46998946a42badd9099591a00325aPetr Machata		if (retp != NULL) {
91364753a1cfe46998946a42badd9099591a00325aPetr Machata			if (private)
92364753a1cfe46998946a42badd9099591a00325aPetr Machata				*retp = VECT_ELEMENT(&dirs, const char *, 0);
93364753a1cfe46998946a42badd9099591a00325aPetr Machata			else
94364753a1cfe46998946a42badd9099591a00325aPetr Machata				*retp = VECT_ELEMENT(&dirs, const char *,
95364753a1cfe46998946a42badd9099591a00325aPetr Machata						     (size_t)sys_start);
96364753a1cfe46998946a42badd9099591a00325aPetr Machata		}
97364753a1cfe46998946a42badd9099591a00325aPetr Machata
98414989183b268337a4f7e329237f3c1fd726d823Petr Machata		return 0;
99414989183b268337a4f7e329237f3c1fd726d823Petr Machata	}
100414989183b268337a4f7e329237f3c1fd726d823Petr Machata
101414989183b268337a4f7e329237f3c1fd726d823Petr Machata	VECT_INIT(&dirs, char *);
102414989183b268337a4f7e329237f3c1fd726d823Petr Machata
103414989183b268337a4f7e329237f3c1fd726d823Petr Machata	char *home = getenv("HOME");
104414989183b268337a4f7e329237f3c1fd726d823Petr Machata	if (home == NULL) {
105414989183b268337a4f7e329237f3c1fd726d823Petr Machata		struct passwd *pwd = getpwuid(getuid());
106414989183b268337a4f7e329237f3c1fd726d823Petr Machata		if (pwd != NULL)
107414989183b268337a4f7e329237f3c1fd726d823Petr Machata			home = pwd->pw_dir;
108414989183b268337a4f7e329237f3c1fd726d823Petr Machata	}
109364753a1cfe46998946a42badd9099591a00325aPetr Machata
11033f0ca5350ccc9ded3a2bfa82a988e9bd640233fPetr Machata	size_t home_len = home != NULL ? strlen(home) : 0;
11133f0ca5350ccc9ded3a2bfa82a988e9bd640233fPetr Machata
112414989183b268337a4f7e329237f3c1fd726d823Petr Machata	/* The values coming from getenv and getpwuid may not be
113414989183b268337a4f7e329237f3c1fd726d823Petr Machata	 * persistent.  */
114364753a1cfe46998946a42badd9099591a00325aPetr Machata	if (home != NULL) {
11589396203c9de0d60374e1b298529afcf0bfbf5edPetr Machata		free(g_home_dir);
116364753a1cfe46998946a42badd9099591a00325aPetr Machata		g_home_dir = strdup(home);
117364753a1cfe46998946a42badd9099591a00325aPetr Machata		if (g_home_dir != NULL) {
118364753a1cfe46998946a42badd9099591a00325aPetr Machata			home = g_home_dir;
119364753a1cfe46998946a42badd9099591a00325aPetr Machata		} else {
12033f0ca5350ccc9ded3a2bfa82a988e9bd640233fPetr Machata			char *tmp = alloca(home_len + 1);
121364753a1cfe46998946a42badd9099591a00325aPetr Machata			strcpy(tmp, home);
122364753a1cfe46998946a42badd9099591a00325aPetr Machata			home = tmp;
123364753a1cfe46998946a42badd9099591a00325aPetr Machata		}
124414989183b268337a4f7e329237f3c1fd726d823Petr Machata	}
125414989183b268337a4f7e329237f3c1fd726d823Petr Machata
126414989183b268337a4f7e329237f3c1fd726d823Petr Machata	char *xdg_home = getenv("XDG_CONFIG_HOME");
127414989183b268337a4f7e329237f3c1fd726d823Petr Machata	if (xdg_home == NULL && home != NULL) {
12833f0ca5350ccc9ded3a2bfa82a988e9bd640233fPetr Machata		xdg_home = alloca(home_len + sizeof "/.config");
12933f0ca5350ccc9ded3a2bfa82a988e9bd640233fPetr Machata		sprintf(xdg_home, "%s/.config", home);
130414989183b268337a4f7e329237f3c1fd726d823Petr Machata	}
131414989183b268337a4f7e329237f3c1fd726d823Petr Machata	if (xdg_home != NULL)
132414989183b268337a4f7e329237f3c1fd726d823Petr Machata		add_dir(&dirs, xdg_home, "/ltrace");
133414989183b268337a4f7e329237f3c1fd726d823Petr Machata	if (home != NULL)
134414989183b268337a4f7e329237f3c1fd726d823Petr Machata		add_dir(&dirs, home, "/.ltrace");
135414989183b268337a4f7e329237f3c1fd726d823Petr Machata
136414989183b268337a4f7e329237f3c1fd726d823Petr Machata	char *delim = NULL;
137414989183b268337a4f7e329237f3c1fd726d823Petr Machata	if (VECT_PUSHBACK(&dirs, &delim) < 0) {
138414989183b268337a4f7e329237f3c1fd726d823Petr Machata	fail:
139414989183b268337a4f7e329237f3c1fd726d823Petr Machata		/* This can't work :(  */
140414989183b268337a4f7e329237f3c1fd726d823Petr Machata		fprintf(stderr,
141414989183b268337a4f7e329237f3c1fd726d823Petr Machata			"Couldn't initialize list of config directories: %s.\n",
142414989183b268337a4f7e329237f3c1fd726d823Petr Machata			strerror(errno));
143414989183b268337a4f7e329237f3c1fd726d823Petr Machata		VECT_DESTROY(&dirs, const char *, dict_dtor_string, NULL);
144414989183b268337a4f7e329237f3c1fd726d823Petr Machata		sys_start = -1;
145414989183b268337a4f7e329237f3c1fd726d823Petr Machata		return -1;
146414989183b268337a4f7e329237f3c1fd726d823Petr Machata	}
147414989183b268337a4f7e329237f3c1fd726d823Petr Machata	sys_start = vect_size(&dirs);
148414989183b268337a4f7e329237f3c1fd726d823Petr Machata
149414989183b268337a4f7e329237f3c1fd726d823Petr Machata	/* """preference-ordered set of base directories to search for
150414989183b268337a4f7e329237f3c1fd726d823Petr Machata	 * configuration files in addition to the $XDG_CONFIG_HOME
151414989183b268337a4f7e329237f3c1fd726d823Petr Machata	 * base directory. The directories in $XDG_CONFIG_DIRS should
152414989183b268337a4f7e329237f3c1fd726d823Petr Machata	 * be seperated with a colon ':'."""  */
153414989183b268337a4f7e329237f3c1fd726d823Petr Machata	char *xdg_sys = getenv("XDG_CONFIG_DIRS");
154414989183b268337a4f7e329237f3c1fd726d823Petr Machata	if (xdg_sys != NULL) {
155414989183b268337a4f7e329237f3c1fd726d823Petr Machata		struct vect v;
156414989183b268337a4f7e329237f3c1fd726d823Petr Machata		VECT_INIT(&v, struct opt_F_t);
157414989183b268337a4f7e329237f3c1fd726d823Petr Machata		if (parse_colon_separated_list(xdg_sys, &v) < 0
158414989183b268337a4f7e329237f3c1fd726d823Petr Machata		    || VECT_EACH(&v, struct opt_F_t, NULL,
159414989183b268337a4f7e329237f3c1fd726d823Petr Machata				 add_dir_component_cb, &dirs) != NULL)
160414989183b268337a4f7e329237f3c1fd726d823Petr Machata			fprintf(stderr,
161414989183b268337a4f7e329237f3c1fd726d823Petr Machata				"Error processing $XDG_CONFIG_DIRS '%s': %s\n",
162414989183b268337a4f7e329237f3c1fd726d823Petr Machata				xdg_sys, strerror(errno));
163414989183b268337a4f7e329237f3c1fd726d823Petr Machata		VECT_DESTROY(&v, struct opt_F_t, destroy_opt_F_cb, NULL);
164414989183b268337a4f7e329237f3c1fd726d823Petr Machata	}
165414989183b268337a4f7e329237f3c1fd726d823Petr Machata
166aa3db6b1234da0e542ba7782849cf200d0d91c1cPetr Machata	/* PKGDATADIR is passed via -D when compiling.  */
167aa3db6b1234da0e542ba7782849cf200d0d91c1cPetr Machata	const char *pkgdatadir = PKGDATADIR;
168aa3db6b1234da0e542ba7782849cf200d0d91c1cPetr Machata	if (pkgdatadir != NULL)
169aa3db6b1234da0e542ba7782849cf200d0d91c1cPetr Machata		add_dir(&dirs, pkgdatadir, "");
170414989183b268337a4f7e329237f3c1fd726d823Petr Machata
171414989183b268337a4f7e329237f3c1fd726d823Petr Machata	if (VECT_PUSHBACK(&dirs, &delim) < 0)
172414989183b268337a4f7e329237f3c1fd726d823Petr Machata		goto fail;
173414989183b268337a4f7e329237f3c1fd726d823Petr Machata
174414989183b268337a4f7e329237f3c1fd726d823Petr Machata	goto again;
175414989183b268337a4f7e329237f3c1fd726d823Petr Machata}
176364753a1cfe46998946a42badd9099591a00325aPetr Machata
177364753a1cfe46998946a42badd9099591a00325aPetr Machataint
178aa3db6b1234da0e542ba7782849cf200d0d91c1cPetr Machataos_get_ltrace_conf_filenames(struct vect *retp)
179364753a1cfe46998946a42badd9099591a00325aPetr Machata{
180aa3db6b1234da0e542ba7782849cf200d0d91c1cPetr Machata	char *homepath = NULL;
181aa3db6b1234da0e542ba7782849cf200d0d91c1cPetr Machata	char *syspath = NULL;
182aa3db6b1234da0e542ba7782849cf200d0d91c1cPetr Machata
183aa3db6b1234da0e542ba7782849cf200d0d91c1cPetr Machata#define FN ".ltrace.conf"
184364753a1cfe46998946a42badd9099591a00325aPetr Machata	if (g_home_dir == NULL)
185364753a1cfe46998946a42badd9099591a00325aPetr Machata		os_get_config_dirs(0, NULL);
186aa3db6b1234da0e542ba7782849cf200d0d91c1cPetr Machata
187aa3db6b1234da0e542ba7782849cf200d0d91c1cPetr Machata	if (g_home_dir != NULL) {
188aa3db6b1234da0e542ba7782849cf200d0d91c1cPetr Machata		homepath = malloc(strlen(g_home_dir) + 1 + sizeof FN);
189aa3db6b1234da0e542ba7782849cf200d0d91c1cPetr Machata		if (homepath == NULL
190aa3db6b1234da0e542ba7782849cf200d0d91c1cPetr Machata		    || sprintf(homepath, "%s/%s", g_home_dir, FN) < 0) {
191aa3db6b1234da0e542ba7782849cf200d0d91c1cPetr Machata		fail:
192aa3db6b1234da0e542ba7782849cf200d0d91c1cPetr Machata			free(syspath);
193aa3db6b1234da0e542ba7782849cf200d0d91c1cPetr Machata			free(homepath);
194aa3db6b1234da0e542ba7782849cf200d0d91c1cPetr Machata			return -1;
195aa3db6b1234da0e542ba7782849cf200d0d91c1cPetr Machata		}
196aa3db6b1234da0e542ba7782849cf200d0d91c1cPetr Machata	}
197aa3db6b1234da0e542ba7782849cf200d0d91c1cPetr Machata
198aa3db6b1234da0e542ba7782849cf200d0d91c1cPetr Machata	/* SYSCONFDIR is passed via -D when compiling.  */
199aa3db6b1234da0e542ba7782849cf200d0d91c1cPetr Machata	const char *sysconfdir = SYSCONFDIR;
200aa3db6b1234da0e542ba7782849cf200d0d91c1cPetr Machata	if (sysconfdir != NULL && *sysconfdir != '\0') {
201aa3db6b1234da0e542ba7782849cf200d0d91c1cPetr Machata		/* No +1, we skip the initial period.  */
202aa3db6b1234da0e542ba7782849cf200d0d91c1cPetr Machata		syspath = malloc(strlen(sysconfdir) + sizeof FN);
203aa3db6b1234da0e542ba7782849cf200d0d91c1cPetr Machata		if (syspath == NULL
204aa3db6b1234da0e542ba7782849cf200d0d91c1cPetr Machata		    || sprintf(syspath, "%s/%s", sysconfdir, FN + 1) < 0)
205aa3db6b1234da0e542ba7782849cf200d0d91c1cPetr Machata			goto fail;
206aa3db6b1234da0e542ba7782849cf200d0d91c1cPetr Machata	}
207aa3db6b1234da0e542ba7782849cf200d0d91c1cPetr Machata
208aa3db6b1234da0e542ba7782849cf200d0d91c1cPetr Machata	if (VECT_PUSHBACK(retp, &homepath) < 0
209aa3db6b1234da0e542ba7782849cf200d0d91c1cPetr Machata	    || VECT_PUSHBACK(retp, &syspath) < 0)
210aa3db6b1234da0e542ba7782849cf200d0d91c1cPetr Machata		goto fail;
211aa3db6b1234da0e542ba7782849cf200d0d91c1cPetr Machata
212aa3db6b1234da0e542ba7782849cf200d0d91c1cPetr Machata	return 0;
213364753a1cfe46998946a42badd9099591a00325aPetr Machata}
214