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