1*e4b17023SJohn Marino /* Relative (relocatable) prefix support. 2*e4b17023SJohn Marino Copyright (C) 1987, 1989, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 3*e4b17023SJohn Marino 1999, 2000, 2001, 2002, 2006, 2012 Free Software Foundation, Inc. 4*e4b17023SJohn Marino 5*e4b17023SJohn Marino This file is part of libiberty. 6*e4b17023SJohn Marino 7*e4b17023SJohn Marino GCC is free software; you can redistribute it and/or modify it under 8*e4b17023SJohn Marino the terms of the GNU General Public License as published by the Free 9*e4b17023SJohn Marino Software Foundation; either version 2, or (at your option) any later 10*e4b17023SJohn Marino version. 11*e4b17023SJohn Marino 12*e4b17023SJohn Marino GCC is distributed in the hope that it will be useful, but WITHOUT ANY 13*e4b17023SJohn Marino WARRANTY; without even the implied warranty of MERCHANTABILITY or 14*e4b17023SJohn Marino FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 15*e4b17023SJohn Marino for more details. 16*e4b17023SJohn Marino 17*e4b17023SJohn Marino You should have received a copy of the GNU General Public License 18*e4b17023SJohn Marino along with GCC; see the file COPYING. If not, write to the Free 19*e4b17023SJohn Marino Software Foundation, 51 Franklin Street - Fifth Floor, Boston, MA 20*e4b17023SJohn Marino 02110-1301, USA. */ 21*e4b17023SJohn Marino 22*e4b17023SJohn Marino /* 23*e4b17023SJohn Marino 24*e4b17023SJohn Marino @deftypefn Extension {const char*} make_relative_prefix (const char *@var{progname}, @ 25*e4b17023SJohn Marino const char *@var{bin_prefix}, const char *@var{prefix}) 26*e4b17023SJohn Marino 27*e4b17023SJohn Marino Given three paths @var{progname}, @var{bin_prefix}, @var{prefix}, 28*e4b17023SJohn Marino return the path that is in the same position relative to 29*e4b17023SJohn Marino @var{progname}'s directory as @var{prefix} is relative to 30*e4b17023SJohn Marino @var{bin_prefix}. That is, a string starting with the directory 31*e4b17023SJohn Marino portion of @var{progname}, followed by a relative pathname of the 32*e4b17023SJohn Marino difference between @var{bin_prefix} and @var{prefix}. 33*e4b17023SJohn Marino 34*e4b17023SJohn Marino If @var{progname} does not contain any directory separators, 35*e4b17023SJohn Marino @code{make_relative_prefix} will search @env{PATH} to find a program 36*e4b17023SJohn Marino named @var{progname}. Also, if @var{progname} is a symbolic link, 37*e4b17023SJohn Marino the symbolic link will be resolved. 38*e4b17023SJohn Marino 39*e4b17023SJohn Marino For example, if @var{bin_prefix} is @code{/alpha/beta/gamma/gcc/delta}, 40*e4b17023SJohn Marino @var{prefix} is @code{/alpha/beta/gamma/omega/}, and @var{progname} is 41*e4b17023SJohn Marino @code{/red/green/blue/gcc}, then this function will return 42*e4b17023SJohn Marino @code{/red/green/blue/../../omega/}. 43*e4b17023SJohn Marino 44*e4b17023SJohn Marino The return value is normally allocated via @code{malloc}. If no 45*e4b17023SJohn Marino relative prefix can be found, return @code{NULL}. 46*e4b17023SJohn Marino 47*e4b17023SJohn Marino @end deftypefn 48*e4b17023SJohn Marino 49*e4b17023SJohn Marino */ 50*e4b17023SJohn Marino 51*e4b17023SJohn Marino #ifdef HAVE_CONFIG_H 52*e4b17023SJohn Marino #include "config.h" 53*e4b17023SJohn Marino #endif 54*e4b17023SJohn Marino 55*e4b17023SJohn Marino #ifdef HAVE_STDLIB_H 56*e4b17023SJohn Marino #include <stdlib.h> 57*e4b17023SJohn Marino #endif 58*e4b17023SJohn Marino #ifdef HAVE_UNISTD_H 59*e4b17023SJohn Marino #include <unistd.h> 60*e4b17023SJohn Marino #endif 61*e4b17023SJohn Marino #ifdef HAVE_SYS_STAT_H 62*e4b17023SJohn Marino #include <sys/stat.h> 63*e4b17023SJohn Marino #endif 64*e4b17023SJohn Marino 65*e4b17023SJohn Marino #include <string.h> 66*e4b17023SJohn Marino 67*e4b17023SJohn Marino #include "ansidecl.h" 68*e4b17023SJohn Marino #include "libiberty.h" 69*e4b17023SJohn Marino 70*e4b17023SJohn Marino #ifndef R_OK 71*e4b17023SJohn Marino #define R_OK 4 72*e4b17023SJohn Marino #define W_OK 2 73*e4b17023SJohn Marino #define X_OK 1 74*e4b17023SJohn Marino #endif 75*e4b17023SJohn Marino 76*e4b17023SJohn Marino #ifndef DIR_SEPARATOR 77*e4b17023SJohn Marino # define DIR_SEPARATOR '/' 78*e4b17023SJohn Marino #endif 79*e4b17023SJohn Marino 80*e4b17023SJohn Marino #if defined (_WIN32) || defined (__MSDOS__) \ 81*e4b17023SJohn Marino || defined (__DJGPP__) || defined (__OS2__) 82*e4b17023SJohn Marino # define HAVE_DOS_BASED_FILE_SYSTEM 83*e4b17023SJohn Marino # define HAVE_HOST_EXECUTABLE_SUFFIX 84*e4b17023SJohn Marino # define HOST_EXECUTABLE_SUFFIX ".exe" 85*e4b17023SJohn Marino # ifndef DIR_SEPARATOR_2 86*e4b17023SJohn Marino # define DIR_SEPARATOR_2 '\\' 87*e4b17023SJohn Marino # endif 88*e4b17023SJohn Marino # define PATH_SEPARATOR ';' 89*e4b17023SJohn Marino #else 90*e4b17023SJohn Marino # define PATH_SEPARATOR ':' 91*e4b17023SJohn Marino #endif 92*e4b17023SJohn Marino 93*e4b17023SJohn Marino #ifndef DIR_SEPARATOR_2 94*e4b17023SJohn Marino # define IS_DIR_SEPARATOR(ch) ((ch) == DIR_SEPARATOR) 95*e4b17023SJohn Marino #else 96*e4b17023SJohn Marino # define IS_DIR_SEPARATOR(ch) \ 97*e4b17023SJohn Marino (((ch) == DIR_SEPARATOR) || ((ch) == DIR_SEPARATOR_2)) 98*e4b17023SJohn Marino #endif 99*e4b17023SJohn Marino 100*e4b17023SJohn Marino #define DIR_UP ".." 101*e4b17023SJohn Marino 102*e4b17023SJohn Marino static char *save_string (const char *, int); 103*e4b17023SJohn Marino static char **split_directories (const char *, int *); 104*e4b17023SJohn Marino static void free_split_directories (char **); 105*e4b17023SJohn Marino 106*e4b17023SJohn Marino static char * 107*e4b17023SJohn Marino save_string (const char *s, int len) 108*e4b17023SJohn Marino { 109*e4b17023SJohn Marino char *result = (char *) malloc (len + 1); 110*e4b17023SJohn Marino 111*e4b17023SJohn Marino memcpy (result, s, len); 112*e4b17023SJohn Marino result[len] = 0; 113*e4b17023SJohn Marino return result; 114*e4b17023SJohn Marino } 115*e4b17023SJohn Marino 116*e4b17023SJohn Marino /* Split a filename into component directories. */ 117*e4b17023SJohn Marino 118*e4b17023SJohn Marino static char ** 119*e4b17023SJohn Marino split_directories (const char *name, int *ptr_num_dirs) 120*e4b17023SJohn Marino { 121*e4b17023SJohn Marino int num_dirs = 0; 122*e4b17023SJohn Marino char **dirs; 123*e4b17023SJohn Marino const char *p, *q; 124*e4b17023SJohn Marino int ch; 125*e4b17023SJohn Marino 126*e4b17023SJohn Marino /* Count the number of directories. Special case MSDOS disk names as part 127*e4b17023SJohn Marino of the initial directory. */ 128*e4b17023SJohn Marino p = name; 129*e4b17023SJohn Marino #ifdef HAVE_DOS_BASED_FILE_SYSTEM 130*e4b17023SJohn Marino if (name[1] == ':' && IS_DIR_SEPARATOR (name[2])) 131*e4b17023SJohn Marino { 132*e4b17023SJohn Marino p += 3; 133*e4b17023SJohn Marino num_dirs++; 134*e4b17023SJohn Marino } 135*e4b17023SJohn Marino #endif /* HAVE_DOS_BASED_FILE_SYSTEM */ 136*e4b17023SJohn Marino 137*e4b17023SJohn Marino while ((ch = *p++) != '\0') 138*e4b17023SJohn Marino { 139*e4b17023SJohn Marino if (IS_DIR_SEPARATOR (ch)) 140*e4b17023SJohn Marino { 141*e4b17023SJohn Marino num_dirs++; 142*e4b17023SJohn Marino while (IS_DIR_SEPARATOR (*p)) 143*e4b17023SJohn Marino p++; 144*e4b17023SJohn Marino } 145*e4b17023SJohn Marino } 146*e4b17023SJohn Marino 147*e4b17023SJohn Marino dirs = (char **) malloc (sizeof (char *) * (num_dirs + 2)); 148*e4b17023SJohn Marino if (dirs == NULL) 149*e4b17023SJohn Marino return NULL; 150*e4b17023SJohn Marino 151*e4b17023SJohn Marino /* Now copy the directory parts. */ 152*e4b17023SJohn Marino num_dirs = 0; 153*e4b17023SJohn Marino p = name; 154*e4b17023SJohn Marino #ifdef HAVE_DOS_BASED_FILE_SYSTEM 155*e4b17023SJohn Marino if (name[1] == ':' && IS_DIR_SEPARATOR (name[2])) 156*e4b17023SJohn Marino { 157*e4b17023SJohn Marino dirs[num_dirs++] = save_string (p, 3); 158*e4b17023SJohn Marino if (dirs[num_dirs - 1] == NULL) 159*e4b17023SJohn Marino { 160*e4b17023SJohn Marino free (dirs); 161*e4b17023SJohn Marino return NULL; 162*e4b17023SJohn Marino } 163*e4b17023SJohn Marino p += 3; 164*e4b17023SJohn Marino } 165*e4b17023SJohn Marino #endif /* HAVE_DOS_BASED_FILE_SYSTEM */ 166*e4b17023SJohn Marino 167*e4b17023SJohn Marino q = p; 168*e4b17023SJohn Marino while ((ch = *p++) != '\0') 169*e4b17023SJohn Marino { 170*e4b17023SJohn Marino if (IS_DIR_SEPARATOR (ch)) 171*e4b17023SJohn Marino { 172*e4b17023SJohn Marino while (IS_DIR_SEPARATOR (*p)) 173*e4b17023SJohn Marino p++; 174*e4b17023SJohn Marino 175*e4b17023SJohn Marino dirs[num_dirs++] = save_string (q, p - q); 176*e4b17023SJohn Marino if (dirs[num_dirs - 1] == NULL) 177*e4b17023SJohn Marino { 178*e4b17023SJohn Marino dirs[num_dirs] = NULL; 179*e4b17023SJohn Marino free_split_directories (dirs); 180*e4b17023SJohn Marino return NULL; 181*e4b17023SJohn Marino } 182*e4b17023SJohn Marino q = p; 183*e4b17023SJohn Marino } 184*e4b17023SJohn Marino } 185*e4b17023SJohn Marino 186*e4b17023SJohn Marino if (p - 1 - q > 0) 187*e4b17023SJohn Marino dirs[num_dirs++] = save_string (q, p - 1 - q); 188*e4b17023SJohn Marino dirs[num_dirs] = NULL; 189*e4b17023SJohn Marino 190*e4b17023SJohn Marino if (dirs[num_dirs - 1] == NULL) 191*e4b17023SJohn Marino { 192*e4b17023SJohn Marino free_split_directories (dirs); 193*e4b17023SJohn Marino return NULL; 194*e4b17023SJohn Marino } 195*e4b17023SJohn Marino 196*e4b17023SJohn Marino if (ptr_num_dirs) 197*e4b17023SJohn Marino *ptr_num_dirs = num_dirs; 198*e4b17023SJohn Marino return dirs; 199*e4b17023SJohn Marino } 200*e4b17023SJohn Marino 201*e4b17023SJohn Marino /* Release storage held by split directories. */ 202*e4b17023SJohn Marino 203*e4b17023SJohn Marino static void 204*e4b17023SJohn Marino free_split_directories (char **dirs) 205*e4b17023SJohn Marino { 206*e4b17023SJohn Marino int i = 0; 207*e4b17023SJohn Marino 208*e4b17023SJohn Marino if (dirs != NULL) 209*e4b17023SJohn Marino { 210*e4b17023SJohn Marino while (dirs[i] != NULL) 211*e4b17023SJohn Marino free (dirs[i++]); 212*e4b17023SJohn Marino 213*e4b17023SJohn Marino free ((char *) dirs); 214*e4b17023SJohn Marino } 215*e4b17023SJohn Marino } 216*e4b17023SJohn Marino 217*e4b17023SJohn Marino /* Given three strings PROGNAME, BIN_PREFIX, PREFIX, return a string that gets 218*e4b17023SJohn Marino to PREFIX starting with the directory portion of PROGNAME and a relative 219*e4b17023SJohn Marino pathname of the difference between BIN_PREFIX and PREFIX. 220*e4b17023SJohn Marino 221*e4b17023SJohn Marino For example, if BIN_PREFIX is /alpha/beta/gamma/gcc/delta, PREFIX is 222*e4b17023SJohn Marino /alpha/beta/gamma/omega/, and PROGNAME is /red/green/blue/gcc, then this 223*e4b17023SJohn Marino function will return /red/green/blue/../../omega/. 224*e4b17023SJohn Marino 225*e4b17023SJohn Marino If no relative prefix can be found, return NULL. */ 226*e4b17023SJohn Marino 227*e4b17023SJohn Marino static char * 228*e4b17023SJohn Marino make_relative_prefix_1 (const char *progname, const char *bin_prefix, 229*e4b17023SJohn Marino const char *prefix, const int resolve_links) 230*e4b17023SJohn Marino { 231*e4b17023SJohn Marino char **prog_dirs = NULL, **bin_dirs = NULL, **prefix_dirs = NULL; 232*e4b17023SJohn Marino int prog_num, bin_num, prefix_num; 233*e4b17023SJohn Marino int i, n, common; 234*e4b17023SJohn Marino int needed_len; 235*e4b17023SJohn Marino char *ret = NULL, *ptr, *full_progname; 236*e4b17023SJohn Marino 237*e4b17023SJohn Marino if (progname == NULL || bin_prefix == NULL || prefix == NULL) 238*e4b17023SJohn Marino return NULL; 239*e4b17023SJohn Marino 240*e4b17023SJohn Marino /* If there is no full pathname, try to find the program by checking in each 241*e4b17023SJohn Marino of the directories specified in the PATH environment variable. */ 242*e4b17023SJohn Marino if (lbasename (progname) == progname) 243*e4b17023SJohn Marino { 244*e4b17023SJohn Marino char *temp; 245*e4b17023SJohn Marino 246*e4b17023SJohn Marino temp = getenv ("PATH"); 247*e4b17023SJohn Marino if (temp) 248*e4b17023SJohn Marino { 249*e4b17023SJohn Marino char *startp, *endp, *nstore; 250*e4b17023SJohn Marino size_t prefixlen = strlen (temp) + 1; 251*e4b17023SJohn Marino size_t len; 252*e4b17023SJohn Marino if (prefixlen < 2) 253*e4b17023SJohn Marino prefixlen = 2; 254*e4b17023SJohn Marino 255*e4b17023SJohn Marino len = prefixlen + strlen (progname) + 1; 256*e4b17023SJohn Marino #ifdef HAVE_HOST_EXECUTABLE_SUFFIX 257*e4b17023SJohn Marino len += strlen (HOST_EXECUTABLE_SUFFIX); 258*e4b17023SJohn Marino #endif 259*e4b17023SJohn Marino nstore = (char *) alloca (len); 260*e4b17023SJohn Marino 261*e4b17023SJohn Marino startp = endp = temp; 262*e4b17023SJohn Marino while (1) 263*e4b17023SJohn Marino { 264*e4b17023SJohn Marino if (*endp == PATH_SEPARATOR || *endp == 0) 265*e4b17023SJohn Marino { 266*e4b17023SJohn Marino if (endp == startp) 267*e4b17023SJohn Marino { 268*e4b17023SJohn Marino nstore[0] = '.'; 269*e4b17023SJohn Marino nstore[1] = DIR_SEPARATOR; 270*e4b17023SJohn Marino nstore[2] = '\0'; 271*e4b17023SJohn Marino } 272*e4b17023SJohn Marino else 273*e4b17023SJohn Marino { 274*e4b17023SJohn Marino memcpy (nstore, startp, endp - startp); 275*e4b17023SJohn Marino if (! IS_DIR_SEPARATOR (endp[-1])) 276*e4b17023SJohn Marino { 277*e4b17023SJohn Marino nstore[endp - startp] = DIR_SEPARATOR; 278*e4b17023SJohn Marino nstore[endp - startp + 1] = 0; 279*e4b17023SJohn Marino } 280*e4b17023SJohn Marino else 281*e4b17023SJohn Marino nstore[endp - startp] = 0; 282*e4b17023SJohn Marino } 283*e4b17023SJohn Marino strcat (nstore, progname); 284*e4b17023SJohn Marino if (! access (nstore, X_OK) 285*e4b17023SJohn Marino #ifdef HAVE_HOST_EXECUTABLE_SUFFIX 286*e4b17023SJohn Marino || ! access (strcat (nstore, HOST_EXECUTABLE_SUFFIX), X_OK) 287*e4b17023SJohn Marino #endif 288*e4b17023SJohn Marino ) 289*e4b17023SJohn Marino { 290*e4b17023SJohn Marino #if defined (HAVE_SYS_STAT_H) && defined (S_ISREG) 291*e4b17023SJohn Marino struct stat st; 292*e4b17023SJohn Marino if (stat (nstore, &st) >= 0 && S_ISREG (st.st_mode)) 293*e4b17023SJohn Marino #endif 294*e4b17023SJohn Marino { 295*e4b17023SJohn Marino progname = nstore; 296*e4b17023SJohn Marino break; 297*e4b17023SJohn Marino } 298*e4b17023SJohn Marino } 299*e4b17023SJohn Marino 300*e4b17023SJohn Marino if (*endp == 0) 301*e4b17023SJohn Marino break; 302*e4b17023SJohn Marino endp = startp = endp + 1; 303*e4b17023SJohn Marino } 304*e4b17023SJohn Marino else 305*e4b17023SJohn Marino endp++; 306*e4b17023SJohn Marino } 307*e4b17023SJohn Marino } 308*e4b17023SJohn Marino } 309*e4b17023SJohn Marino 310*e4b17023SJohn Marino if (resolve_links) 311*e4b17023SJohn Marino full_progname = lrealpath (progname); 312*e4b17023SJohn Marino else 313*e4b17023SJohn Marino full_progname = strdup (progname); 314*e4b17023SJohn Marino if (full_progname == NULL) 315*e4b17023SJohn Marino return NULL; 316*e4b17023SJohn Marino 317*e4b17023SJohn Marino prog_dirs = split_directories (full_progname, &prog_num); 318*e4b17023SJohn Marino free (full_progname); 319*e4b17023SJohn Marino if (prog_dirs == NULL) 320*e4b17023SJohn Marino return NULL; 321*e4b17023SJohn Marino 322*e4b17023SJohn Marino bin_dirs = split_directories (bin_prefix, &bin_num); 323*e4b17023SJohn Marino if (bin_dirs == NULL) 324*e4b17023SJohn Marino goto bailout; 325*e4b17023SJohn Marino 326*e4b17023SJohn Marino /* Remove the program name from comparison of directory names. */ 327*e4b17023SJohn Marino prog_num--; 328*e4b17023SJohn Marino 329*e4b17023SJohn Marino /* If we are still installed in the standard location, we don't need to 330*e4b17023SJohn Marino specify relative directories. Also, if argv[0] still doesn't contain 331*e4b17023SJohn Marino any directory specifiers after the search above, then there is not much 332*e4b17023SJohn Marino we can do. */ 333*e4b17023SJohn Marino if (prog_num == bin_num) 334*e4b17023SJohn Marino { 335*e4b17023SJohn Marino for (i = 0; i < bin_num; i++) 336*e4b17023SJohn Marino { 337*e4b17023SJohn Marino if (strcmp (prog_dirs[i], bin_dirs[i]) != 0) 338*e4b17023SJohn Marino break; 339*e4b17023SJohn Marino } 340*e4b17023SJohn Marino 341*e4b17023SJohn Marino if (prog_num <= 0 || i == bin_num) 342*e4b17023SJohn Marino goto bailout; 343*e4b17023SJohn Marino } 344*e4b17023SJohn Marino 345*e4b17023SJohn Marino prefix_dirs = split_directories (prefix, &prefix_num); 346*e4b17023SJohn Marino if (prefix_dirs == NULL) 347*e4b17023SJohn Marino goto bailout; 348*e4b17023SJohn Marino 349*e4b17023SJohn Marino /* Find how many directories are in common between bin_prefix & prefix. */ 350*e4b17023SJohn Marino n = (prefix_num < bin_num) ? prefix_num : bin_num; 351*e4b17023SJohn Marino for (common = 0; common < n; common++) 352*e4b17023SJohn Marino { 353*e4b17023SJohn Marino if (strcmp (bin_dirs[common], prefix_dirs[common]) != 0) 354*e4b17023SJohn Marino break; 355*e4b17023SJohn Marino } 356*e4b17023SJohn Marino 357*e4b17023SJohn Marino /* If there are no common directories, there can be no relative prefix. */ 358*e4b17023SJohn Marino if (common == 0) 359*e4b17023SJohn Marino goto bailout; 360*e4b17023SJohn Marino 361*e4b17023SJohn Marino /* Two passes: first figure out the size of the result string, and 362*e4b17023SJohn Marino then construct it. */ 363*e4b17023SJohn Marino needed_len = 0; 364*e4b17023SJohn Marino for (i = 0; i < prog_num; i++) 365*e4b17023SJohn Marino needed_len += strlen (prog_dirs[i]); 366*e4b17023SJohn Marino needed_len += sizeof (DIR_UP) * (bin_num - common); 367*e4b17023SJohn Marino for (i = common; i < prefix_num; i++) 368*e4b17023SJohn Marino needed_len += strlen (prefix_dirs[i]); 369*e4b17023SJohn Marino needed_len += 1; /* Trailing NUL. */ 370*e4b17023SJohn Marino 371*e4b17023SJohn Marino ret = (char *) malloc (needed_len); 372*e4b17023SJohn Marino if (ret == NULL) 373*e4b17023SJohn Marino goto bailout; 374*e4b17023SJohn Marino 375*e4b17023SJohn Marino /* Build up the pathnames in argv[0]. */ 376*e4b17023SJohn Marino *ret = '\0'; 377*e4b17023SJohn Marino for (i = 0; i < prog_num; i++) 378*e4b17023SJohn Marino strcat (ret, prog_dirs[i]); 379*e4b17023SJohn Marino 380*e4b17023SJohn Marino /* Now build up the ..'s. */ 381*e4b17023SJohn Marino ptr = ret + strlen(ret); 382*e4b17023SJohn Marino for (i = common; i < bin_num; i++) 383*e4b17023SJohn Marino { 384*e4b17023SJohn Marino strcpy (ptr, DIR_UP); 385*e4b17023SJohn Marino ptr += sizeof (DIR_UP) - 1; 386*e4b17023SJohn Marino *(ptr++) = DIR_SEPARATOR; 387*e4b17023SJohn Marino } 388*e4b17023SJohn Marino *ptr = '\0'; 389*e4b17023SJohn Marino 390*e4b17023SJohn Marino /* Put in directories to move over to prefix. */ 391*e4b17023SJohn Marino for (i = common; i < prefix_num; i++) 392*e4b17023SJohn Marino strcat (ret, prefix_dirs[i]); 393*e4b17023SJohn Marino 394*e4b17023SJohn Marino bailout: 395*e4b17023SJohn Marino free_split_directories (prog_dirs); 396*e4b17023SJohn Marino free_split_directories (bin_dirs); 397*e4b17023SJohn Marino free_split_directories (prefix_dirs); 398*e4b17023SJohn Marino 399*e4b17023SJohn Marino return ret; 400*e4b17023SJohn Marino } 401*e4b17023SJohn Marino 402*e4b17023SJohn Marino 403*e4b17023SJohn Marino /* Do the full job, including symlink resolution. 404*e4b17023SJohn Marino This path will find files installed in the same place as the 405*e4b17023SJohn Marino program even when a soft link has been made to the program 406*e4b17023SJohn Marino from somwhere else. */ 407*e4b17023SJohn Marino 408*e4b17023SJohn Marino char * 409*e4b17023SJohn Marino make_relative_prefix (const char *progname, const char *bin_prefix, 410*e4b17023SJohn Marino const char *prefix) 411*e4b17023SJohn Marino { 412*e4b17023SJohn Marino return make_relative_prefix_1 (progname, bin_prefix, prefix, 1); 413*e4b17023SJohn Marino } 414*e4b17023SJohn Marino 415*e4b17023SJohn Marino /* Make the relative pathname without attempting to resolve any links. 416*e4b17023SJohn Marino '..' etc may also be left in the pathname. 417*e4b17023SJohn Marino This will find the files the user meant the program to find if the 418*e4b17023SJohn Marino installation is patched together with soft links. */ 419*e4b17023SJohn Marino 420*e4b17023SJohn Marino char * 421*e4b17023SJohn Marino make_relative_prefix_ignore_links (const char *progname, 422*e4b17023SJohn Marino const char *bin_prefix, 423*e4b17023SJohn Marino const char *prefix) 424*e4b17023SJohn Marino { 425*e4b17023SJohn Marino return make_relative_prefix_1 (progname, bin_prefix, prefix, 0); 426*e4b17023SJohn Marino } 427*e4b17023SJohn Marino 428