tool_findfile.c (4233B)
1 /*************************************************************************** 2 * _ _ ____ _ 3 * Project ___| | | | _ \| | 4 * / __| | | | |_) | | 5 * | (__| |_| | _ <| |___ 6 * \___|\___/|_| \_\_____| 7 * 8 * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al. 9 * 10 * This software is licensed as described in the file COPYING, which 11 * you should have received as part of this distribution. The terms 12 * are also available at https://curl.se/docs/copyright.html. 13 * 14 * You may opt to use, copy, modify, merge, publish, distribute and/or sell 15 * copies of the Software, and permit persons to whom the Software is 16 * furnished to do so, under the terms of the COPYING file. 17 * 18 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY 19 * KIND, either express or implied. 20 * 21 * SPDX-License-Identifier: curl 22 * 23 ***************************************************************************/ 24 #include "tool_setup.h" 25 26 #ifdef HAVE_PWD_H 27 #undef __NO_NET_API /* required for AmigaOS to declare getpwuid() */ 28 #include <pwd.h> 29 #define __NO_NET_API 30 #endif 31 32 #ifdef HAVE_FCNTL_H 33 #include <fcntl.h> 34 #endif 35 36 #include "tool_findfile.h" 37 #include "tool_cfgable.h" 38 39 #include "memdebug.h" /* keep this as LAST include */ 40 41 struct finder { 42 const char *env; 43 const char *append; 44 bool withoutdot; 45 }; 46 47 /* The order of the variables below is important, as the index number is used 48 in the findfile() function */ 49 static const struct finder conf_list[] = { 50 { "CURL_HOME", NULL, FALSE }, 51 { "XDG_CONFIG_HOME", NULL, TRUE }, 52 { "HOME", NULL, FALSE }, 53 #ifdef _WIN32 54 { "USERPROFILE", NULL, FALSE }, 55 { "APPDATA", NULL, FALSE }, 56 { "USERPROFILE", "\\Application Data", FALSE}, 57 #endif 58 /* these are for .curlrc if XDG_CONFIG_HOME is not defined */ 59 { "CURL_HOME", "/.config", TRUE }, 60 { "HOME", "/.config", TRUE }, 61 62 { NULL, NULL, FALSE } 63 }; 64 65 static char *checkhome(const char *home, const char *fname, bool dotscore) 66 { 67 const char pref[2] = { '.', '_' }; 68 int i; 69 for(i = 0; i < (dotscore ? 2 : 1); i++) { 70 char *c; 71 if(dotscore) 72 c = aprintf("%s" DIR_CHAR "%c%s", home, pref[i], &fname[1]); 73 else 74 c = aprintf("%s" DIR_CHAR "%s", home, fname); 75 if(c) { 76 int fd = open(c, O_RDONLY); 77 if(fd >= 0) { 78 char *path = strdup(c); 79 close(fd); 80 curl_free(c); 81 return path; 82 } 83 curl_free(c); 84 } 85 } 86 return NULL; 87 } 88 89 /* 90 * findfile() - return the full path name of the file. 91 * 92 * If 'dotscore' is TRUE, then check for the file first with a leading dot 93 * and then with a leading underscore. 94 * 95 * 1. Iterate over the environment variables in order, and if set, check for 96 * the given file to be accessed there, then it is a match. 97 * 2. Non-Windows: try getpwuid 98 */ 99 char *findfile(const char *fname, int dotscore) 100 { 101 int i; 102 DEBUGASSERT(fname && fname[0]); 103 DEBUGASSERT((dotscore != 1) || (fname[0] == '.')); 104 105 if(!fname[0]) 106 return NULL; 107 108 for(i = 0; conf_list[i].env; i++) { 109 char *home = curl_getenv(conf_list[i].env); 110 if(home) { 111 char *path; 112 const char *filename = fname; 113 if(!home[0]) { 114 curl_free(home); 115 continue; 116 } 117 if(conf_list[i].append) { 118 char *c = aprintf("%s%s", home, conf_list[i].append); 119 curl_free(home); 120 if(!c) 121 return NULL; 122 home = c; 123 } 124 if(conf_list[i].withoutdot) { 125 if(!dotscore) { 126 /* this is not looking for .curlrc, or the XDG_CONFIG_HOME was 127 defined so we skip the extended check */ 128 curl_free(home); 129 continue; 130 } 131 filename++; /* move past the leading dot */ 132 dotscore = 0; /* disable it for this check */ 133 } 134 path = checkhome(home, filename, dotscore ? dotscore - 1 : 0); 135 curl_free(home); 136 if(path) 137 return path; 138 } 139 } 140 #if defined(HAVE_GETPWUID) && defined(HAVE_GETEUID) 141 { 142 struct passwd *pw = getpwuid(geteuid()); 143 if(pw) { 144 char *home = pw->pw_dir; 145 if(home && home[0]) 146 return checkhome(home, fname, FALSE); 147 } 148 } 149 #endif /* PWD-stuff */ 150 return NULL; 151 }