15796c8dcSSimon Schubert /* Relative (relocatable) prefix support.
25796c8dcSSimon Schubert Copyright (C) 1987, 1989, 1992, 1993, 1994, 1995, 1996, 1997, 1998,
3*ef5ccd6cSJohn Marino 1999, 2000, 2001, 2002, 2006, 2012 Free Software Foundation, Inc.
45796c8dcSSimon Schubert
55796c8dcSSimon Schubert This file is part of libiberty.
65796c8dcSSimon Schubert
75796c8dcSSimon Schubert GCC is free software; you can redistribute it and/or modify it under
85796c8dcSSimon Schubert the terms of the GNU General Public License as published by the Free
95796c8dcSSimon Schubert Software Foundation; either version 2, or (at your option) any later
105796c8dcSSimon Schubert version.
115796c8dcSSimon Schubert
125796c8dcSSimon Schubert GCC is distributed in the hope that it will be useful, but WITHOUT ANY
135796c8dcSSimon Schubert WARRANTY; without even the implied warranty of MERCHANTABILITY or
145796c8dcSSimon Schubert FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
155796c8dcSSimon Schubert for more details.
165796c8dcSSimon Schubert
175796c8dcSSimon Schubert You should have received a copy of the GNU General Public License
185796c8dcSSimon Schubert along with GCC; see the file COPYING. If not, write to the Free
195796c8dcSSimon Schubert Software Foundation, 51 Franklin Street - Fifth Floor, Boston, MA
205796c8dcSSimon Schubert 02110-1301, USA. */
215796c8dcSSimon Schubert
225796c8dcSSimon Schubert /*
235796c8dcSSimon Schubert
24c50c785cSJohn Marino @deftypefn Extension {const char*} make_relative_prefix (const char *@var{progname}, @
25c50c785cSJohn Marino const char *@var{bin_prefix}, const char *@var{prefix})
265796c8dcSSimon Schubert
275796c8dcSSimon Schubert Given three paths @var{progname}, @var{bin_prefix}, @var{prefix},
285796c8dcSSimon Schubert return the path that is in the same position relative to
295796c8dcSSimon Schubert @var{progname}'s directory as @var{prefix} is relative to
305796c8dcSSimon Schubert @var{bin_prefix}. That is, a string starting with the directory
315796c8dcSSimon Schubert portion of @var{progname}, followed by a relative pathname of the
325796c8dcSSimon Schubert difference between @var{bin_prefix} and @var{prefix}.
335796c8dcSSimon Schubert
345796c8dcSSimon Schubert If @var{progname} does not contain any directory separators,
355796c8dcSSimon Schubert @code{make_relative_prefix} will search @env{PATH} to find a program
365796c8dcSSimon Schubert named @var{progname}. Also, if @var{progname} is a symbolic link,
375796c8dcSSimon Schubert the symbolic link will be resolved.
385796c8dcSSimon Schubert
395796c8dcSSimon Schubert For example, if @var{bin_prefix} is @code{/alpha/beta/gamma/gcc/delta},
405796c8dcSSimon Schubert @var{prefix} is @code{/alpha/beta/gamma/omega/}, and @var{progname} is
415796c8dcSSimon Schubert @code{/red/green/blue/gcc}, then this function will return
425796c8dcSSimon Schubert @code{/red/green/blue/../../omega/}.
435796c8dcSSimon Schubert
445796c8dcSSimon Schubert The return value is normally allocated via @code{malloc}. If no
455796c8dcSSimon Schubert relative prefix can be found, return @code{NULL}.
465796c8dcSSimon Schubert
475796c8dcSSimon Schubert @end deftypefn
485796c8dcSSimon Schubert
495796c8dcSSimon Schubert */
505796c8dcSSimon Schubert
515796c8dcSSimon Schubert #ifdef HAVE_CONFIG_H
525796c8dcSSimon Schubert #include "config.h"
535796c8dcSSimon Schubert #endif
545796c8dcSSimon Schubert
555796c8dcSSimon Schubert #ifdef HAVE_STDLIB_H
565796c8dcSSimon Schubert #include <stdlib.h>
575796c8dcSSimon Schubert #endif
585796c8dcSSimon Schubert #ifdef HAVE_UNISTD_H
595796c8dcSSimon Schubert #include <unistd.h>
605796c8dcSSimon Schubert #endif
61*ef5ccd6cSJohn Marino #ifdef HAVE_SYS_STAT_H
62*ef5ccd6cSJohn Marino #include <sys/stat.h>
63*ef5ccd6cSJohn Marino #endif
645796c8dcSSimon Schubert
655796c8dcSSimon Schubert #include <string.h>
665796c8dcSSimon Schubert
675796c8dcSSimon Schubert #include "ansidecl.h"
685796c8dcSSimon Schubert #include "libiberty.h"
695796c8dcSSimon Schubert
705796c8dcSSimon Schubert #ifndef R_OK
715796c8dcSSimon Schubert #define R_OK 4
725796c8dcSSimon Schubert #define W_OK 2
735796c8dcSSimon Schubert #define X_OK 1
745796c8dcSSimon Schubert #endif
755796c8dcSSimon Schubert
765796c8dcSSimon Schubert #ifndef DIR_SEPARATOR
775796c8dcSSimon Schubert # define DIR_SEPARATOR '/'
785796c8dcSSimon Schubert #endif
795796c8dcSSimon Schubert
805796c8dcSSimon Schubert #if defined (_WIN32) || defined (__MSDOS__) \
815796c8dcSSimon Schubert || defined (__DJGPP__) || defined (__OS2__)
825796c8dcSSimon Schubert # define HAVE_DOS_BASED_FILE_SYSTEM
835796c8dcSSimon Schubert # define HAVE_HOST_EXECUTABLE_SUFFIX
845796c8dcSSimon Schubert # define HOST_EXECUTABLE_SUFFIX ".exe"
855796c8dcSSimon Schubert # ifndef DIR_SEPARATOR_2
865796c8dcSSimon Schubert # define DIR_SEPARATOR_2 '\\'
875796c8dcSSimon Schubert # endif
885796c8dcSSimon Schubert # define PATH_SEPARATOR ';'
895796c8dcSSimon Schubert #else
905796c8dcSSimon Schubert # define PATH_SEPARATOR ':'
915796c8dcSSimon Schubert #endif
925796c8dcSSimon Schubert
935796c8dcSSimon Schubert #ifndef DIR_SEPARATOR_2
945796c8dcSSimon Schubert # define IS_DIR_SEPARATOR(ch) ((ch) == DIR_SEPARATOR)
955796c8dcSSimon Schubert #else
965796c8dcSSimon Schubert # define IS_DIR_SEPARATOR(ch) \
975796c8dcSSimon Schubert (((ch) == DIR_SEPARATOR) || ((ch) == DIR_SEPARATOR_2))
985796c8dcSSimon Schubert #endif
995796c8dcSSimon Schubert
1005796c8dcSSimon Schubert #define DIR_UP ".."
1015796c8dcSSimon Schubert
1025796c8dcSSimon Schubert static char *save_string (const char *, int);
1035796c8dcSSimon Schubert static char **split_directories (const char *, int *);
1045796c8dcSSimon Schubert static void free_split_directories (char **);
1055796c8dcSSimon Schubert
1065796c8dcSSimon Schubert static char *
save_string(const char * s,int len)1075796c8dcSSimon Schubert save_string (const char *s, int len)
1085796c8dcSSimon Schubert {
1095796c8dcSSimon Schubert char *result = (char *) malloc (len + 1);
1105796c8dcSSimon Schubert
1115796c8dcSSimon Schubert memcpy (result, s, len);
1125796c8dcSSimon Schubert result[len] = 0;
1135796c8dcSSimon Schubert return result;
1145796c8dcSSimon Schubert }
1155796c8dcSSimon Schubert
1165796c8dcSSimon Schubert /* Split a filename into component directories. */
1175796c8dcSSimon Schubert
1185796c8dcSSimon Schubert static char **
split_directories(const char * name,int * ptr_num_dirs)1195796c8dcSSimon Schubert split_directories (const char *name, int *ptr_num_dirs)
1205796c8dcSSimon Schubert {
1215796c8dcSSimon Schubert int num_dirs = 0;
1225796c8dcSSimon Schubert char **dirs;
1235796c8dcSSimon Schubert const char *p, *q;
1245796c8dcSSimon Schubert int ch;
1255796c8dcSSimon Schubert
1265796c8dcSSimon Schubert /* Count the number of directories. Special case MSDOS disk names as part
1275796c8dcSSimon Schubert of the initial directory. */
1285796c8dcSSimon Schubert p = name;
1295796c8dcSSimon Schubert #ifdef HAVE_DOS_BASED_FILE_SYSTEM
1305796c8dcSSimon Schubert if (name[1] == ':' && IS_DIR_SEPARATOR (name[2]))
1315796c8dcSSimon Schubert {
1325796c8dcSSimon Schubert p += 3;
1335796c8dcSSimon Schubert num_dirs++;
1345796c8dcSSimon Schubert }
1355796c8dcSSimon Schubert #endif /* HAVE_DOS_BASED_FILE_SYSTEM */
1365796c8dcSSimon Schubert
1375796c8dcSSimon Schubert while ((ch = *p++) != '\0')
1385796c8dcSSimon Schubert {
1395796c8dcSSimon Schubert if (IS_DIR_SEPARATOR (ch))
1405796c8dcSSimon Schubert {
1415796c8dcSSimon Schubert num_dirs++;
1425796c8dcSSimon Schubert while (IS_DIR_SEPARATOR (*p))
1435796c8dcSSimon Schubert p++;
1445796c8dcSSimon Schubert }
1455796c8dcSSimon Schubert }
1465796c8dcSSimon Schubert
1475796c8dcSSimon Schubert dirs = (char **) malloc (sizeof (char *) * (num_dirs + 2));
1485796c8dcSSimon Schubert if (dirs == NULL)
1495796c8dcSSimon Schubert return NULL;
1505796c8dcSSimon Schubert
1515796c8dcSSimon Schubert /* Now copy the directory parts. */
1525796c8dcSSimon Schubert num_dirs = 0;
1535796c8dcSSimon Schubert p = name;
1545796c8dcSSimon Schubert #ifdef HAVE_DOS_BASED_FILE_SYSTEM
1555796c8dcSSimon Schubert if (name[1] == ':' && IS_DIR_SEPARATOR (name[2]))
1565796c8dcSSimon Schubert {
1575796c8dcSSimon Schubert dirs[num_dirs++] = save_string (p, 3);
1585796c8dcSSimon Schubert if (dirs[num_dirs - 1] == NULL)
1595796c8dcSSimon Schubert {
1605796c8dcSSimon Schubert free (dirs);
1615796c8dcSSimon Schubert return NULL;
1625796c8dcSSimon Schubert }
1635796c8dcSSimon Schubert p += 3;
1645796c8dcSSimon Schubert }
1655796c8dcSSimon Schubert #endif /* HAVE_DOS_BASED_FILE_SYSTEM */
1665796c8dcSSimon Schubert
1675796c8dcSSimon Schubert q = p;
1685796c8dcSSimon Schubert while ((ch = *p++) != '\0')
1695796c8dcSSimon Schubert {
1705796c8dcSSimon Schubert if (IS_DIR_SEPARATOR (ch))
1715796c8dcSSimon Schubert {
1725796c8dcSSimon Schubert while (IS_DIR_SEPARATOR (*p))
1735796c8dcSSimon Schubert p++;
1745796c8dcSSimon Schubert
1755796c8dcSSimon Schubert dirs[num_dirs++] = save_string (q, p - q);
1765796c8dcSSimon Schubert if (dirs[num_dirs - 1] == NULL)
1775796c8dcSSimon Schubert {
1785796c8dcSSimon Schubert dirs[num_dirs] = NULL;
1795796c8dcSSimon Schubert free_split_directories (dirs);
1805796c8dcSSimon Schubert return NULL;
1815796c8dcSSimon Schubert }
1825796c8dcSSimon Schubert q = p;
1835796c8dcSSimon Schubert }
1845796c8dcSSimon Schubert }
1855796c8dcSSimon Schubert
1865796c8dcSSimon Schubert if (p - 1 - q > 0)
1875796c8dcSSimon Schubert dirs[num_dirs++] = save_string (q, p - 1 - q);
1885796c8dcSSimon Schubert dirs[num_dirs] = NULL;
1895796c8dcSSimon Schubert
1905796c8dcSSimon Schubert if (dirs[num_dirs - 1] == NULL)
1915796c8dcSSimon Schubert {
1925796c8dcSSimon Schubert free_split_directories (dirs);
1935796c8dcSSimon Schubert return NULL;
1945796c8dcSSimon Schubert }
1955796c8dcSSimon Schubert
1965796c8dcSSimon Schubert if (ptr_num_dirs)
1975796c8dcSSimon Schubert *ptr_num_dirs = num_dirs;
1985796c8dcSSimon Schubert return dirs;
1995796c8dcSSimon Schubert }
2005796c8dcSSimon Schubert
2015796c8dcSSimon Schubert /* Release storage held by split directories. */
2025796c8dcSSimon Schubert
2035796c8dcSSimon Schubert static void
free_split_directories(char ** dirs)2045796c8dcSSimon Schubert free_split_directories (char **dirs)
2055796c8dcSSimon Schubert {
2065796c8dcSSimon Schubert int i = 0;
2075796c8dcSSimon Schubert
2085796c8dcSSimon Schubert if (dirs != NULL)
2095796c8dcSSimon Schubert {
2105796c8dcSSimon Schubert while (dirs[i] != NULL)
2115796c8dcSSimon Schubert free (dirs[i++]);
2125796c8dcSSimon Schubert
2135796c8dcSSimon Schubert free ((char *) dirs);
2145796c8dcSSimon Schubert }
2155796c8dcSSimon Schubert }
2165796c8dcSSimon Schubert
2175796c8dcSSimon Schubert /* Given three strings PROGNAME, BIN_PREFIX, PREFIX, return a string that gets
2185796c8dcSSimon Schubert to PREFIX starting with the directory portion of PROGNAME and a relative
2195796c8dcSSimon Schubert pathname of the difference between BIN_PREFIX and PREFIX.
2205796c8dcSSimon Schubert
2215796c8dcSSimon Schubert For example, if BIN_PREFIX is /alpha/beta/gamma/gcc/delta, PREFIX is
2225796c8dcSSimon Schubert /alpha/beta/gamma/omega/, and PROGNAME is /red/green/blue/gcc, then this
2235796c8dcSSimon Schubert function will return /red/green/blue/../../omega/.
2245796c8dcSSimon Schubert
2255796c8dcSSimon Schubert If no relative prefix can be found, return NULL. */
2265796c8dcSSimon Schubert
2275796c8dcSSimon Schubert static char *
make_relative_prefix_1(const char * progname,const char * bin_prefix,const char * prefix,const int resolve_links)2285796c8dcSSimon Schubert make_relative_prefix_1 (const char *progname, const char *bin_prefix,
2295796c8dcSSimon Schubert const char *prefix, const int resolve_links)
2305796c8dcSSimon Schubert {
2315796c8dcSSimon Schubert char **prog_dirs = NULL, **bin_dirs = NULL, **prefix_dirs = NULL;
2325796c8dcSSimon Schubert int prog_num, bin_num, prefix_num;
2335796c8dcSSimon Schubert int i, n, common;
2345796c8dcSSimon Schubert int needed_len;
2355796c8dcSSimon Schubert char *ret = NULL, *ptr, *full_progname;
2365796c8dcSSimon Schubert
2375796c8dcSSimon Schubert if (progname == NULL || bin_prefix == NULL || prefix == NULL)
2385796c8dcSSimon Schubert return NULL;
2395796c8dcSSimon Schubert
2405796c8dcSSimon Schubert /* If there is no full pathname, try to find the program by checking in each
2415796c8dcSSimon Schubert of the directories specified in the PATH environment variable. */
2425796c8dcSSimon Schubert if (lbasename (progname) == progname)
2435796c8dcSSimon Schubert {
2445796c8dcSSimon Schubert char *temp;
2455796c8dcSSimon Schubert
2465796c8dcSSimon Schubert temp = getenv ("PATH");
2475796c8dcSSimon Schubert if (temp)
2485796c8dcSSimon Schubert {
2495796c8dcSSimon Schubert char *startp, *endp, *nstore;
2505796c8dcSSimon Schubert size_t prefixlen = strlen (temp) + 1;
251*ef5ccd6cSJohn Marino size_t len;
2525796c8dcSSimon Schubert if (prefixlen < 2)
2535796c8dcSSimon Schubert prefixlen = 2;
2545796c8dcSSimon Schubert
255*ef5ccd6cSJohn Marino len = prefixlen + strlen (progname) + 1;
256*ef5ccd6cSJohn Marino #ifdef HAVE_HOST_EXECUTABLE_SUFFIX
257*ef5ccd6cSJohn Marino len += strlen (HOST_EXECUTABLE_SUFFIX);
258*ef5ccd6cSJohn Marino #endif
259*ef5ccd6cSJohn Marino nstore = (char *) alloca (len);
2605796c8dcSSimon Schubert
2615796c8dcSSimon Schubert startp = endp = temp;
2625796c8dcSSimon Schubert while (1)
2635796c8dcSSimon Schubert {
2645796c8dcSSimon Schubert if (*endp == PATH_SEPARATOR || *endp == 0)
2655796c8dcSSimon Schubert {
2665796c8dcSSimon Schubert if (endp == startp)
2675796c8dcSSimon Schubert {
2685796c8dcSSimon Schubert nstore[0] = '.';
2695796c8dcSSimon Schubert nstore[1] = DIR_SEPARATOR;
2705796c8dcSSimon Schubert nstore[2] = '\0';
2715796c8dcSSimon Schubert }
2725796c8dcSSimon Schubert else
2735796c8dcSSimon Schubert {
274*ef5ccd6cSJohn Marino memcpy (nstore, startp, endp - startp);
2755796c8dcSSimon Schubert if (! IS_DIR_SEPARATOR (endp[-1]))
2765796c8dcSSimon Schubert {
2775796c8dcSSimon Schubert nstore[endp - startp] = DIR_SEPARATOR;
2785796c8dcSSimon Schubert nstore[endp - startp + 1] = 0;
2795796c8dcSSimon Schubert }
2805796c8dcSSimon Schubert else
2815796c8dcSSimon Schubert nstore[endp - startp] = 0;
2825796c8dcSSimon Schubert }
2835796c8dcSSimon Schubert strcat (nstore, progname);
2845796c8dcSSimon Schubert if (! access (nstore, X_OK)
2855796c8dcSSimon Schubert #ifdef HAVE_HOST_EXECUTABLE_SUFFIX
2865796c8dcSSimon Schubert || ! access (strcat (nstore, HOST_EXECUTABLE_SUFFIX), X_OK)
2875796c8dcSSimon Schubert #endif
2885796c8dcSSimon Schubert )
2895796c8dcSSimon Schubert {
290*ef5ccd6cSJohn Marino #if defined (HAVE_SYS_STAT_H) && defined (S_ISREG)
291*ef5ccd6cSJohn Marino struct stat st;
292*ef5ccd6cSJohn Marino if (stat (nstore, &st) >= 0 && S_ISREG (st.st_mode))
293*ef5ccd6cSJohn Marino #endif
294*ef5ccd6cSJohn Marino {
2955796c8dcSSimon Schubert progname = nstore;
2965796c8dcSSimon Schubert break;
2975796c8dcSSimon Schubert }
298*ef5ccd6cSJohn Marino }
2995796c8dcSSimon Schubert
3005796c8dcSSimon Schubert if (*endp == 0)
3015796c8dcSSimon Schubert break;
3025796c8dcSSimon Schubert endp = startp = endp + 1;
3035796c8dcSSimon Schubert }
3045796c8dcSSimon Schubert else
3055796c8dcSSimon Schubert endp++;
3065796c8dcSSimon Schubert }
3075796c8dcSSimon Schubert }
3085796c8dcSSimon Schubert }
3095796c8dcSSimon Schubert
3105796c8dcSSimon Schubert if (resolve_links)
3115796c8dcSSimon Schubert full_progname = lrealpath (progname);
3125796c8dcSSimon Schubert else
3135796c8dcSSimon Schubert full_progname = strdup (progname);
3145796c8dcSSimon Schubert if (full_progname == NULL)
3155796c8dcSSimon Schubert return NULL;
3165796c8dcSSimon Schubert
3175796c8dcSSimon Schubert prog_dirs = split_directories (full_progname, &prog_num);
3185796c8dcSSimon Schubert free (full_progname);
3195796c8dcSSimon Schubert if (prog_dirs == NULL)
3205796c8dcSSimon Schubert return NULL;
3215796c8dcSSimon Schubert
3225796c8dcSSimon Schubert bin_dirs = split_directories (bin_prefix, &bin_num);
3235796c8dcSSimon Schubert if (bin_dirs == NULL)
3245796c8dcSSimon Schubert goto bailout;
3255796c8dcSSimon Schubert
3265796c8dcSSimon Schubert /* Remove the program name from comparison of directory names. */
3275796c8dcSSimon Schubert prog_num--;
3285796c8dcSSimon Schubert
3295796c8dcSSimon Schubert /* If we are still installed in the standard location, we don't need to
3305796c8dcSSimon Schubert specify relative directories. Also, if argv[0] still doesn't contain
3315796c8dcSSimon Schubert any directory specifiers after the search above, then there is not much
3325796c8dcSSimon Schubert we can do. */
3335796c8dcSSimon Schubert if (prog_num == bin_num)
3345796c8dcSSimon Schubert {
3355796c8dcSSimon Schubert for (i = 0; i < bin_num; i++)
3365796c8dcSSimon Schubert {
3375796c8dcSSimon Schubert if (strcmp (prog_dirs[i], bin_dirs[i]) != 0)
3385796c8dcSSimon Schubert break;
3395796c8dcSSimon Schubert }
3405796c8dcSSimon Schubert
3415796c8dcSSimon Schubert if (prog_num <= 0 || i == bin_num)
3425796c8dcSSimon Schubert goto bailout;
3435796c8dcSSimon Schubert }
3445796c8dcSSimon Schubert
3455796c8dcSSimon Schubert prefix_dirs = split_directories (prefix, &prefix_num);
3465796c8dcSSimon Schubert if (prefix_dirs == NULL)
3475796c8dcSSimon Schubert goto bailout;
3485796c8dcSSimon Schubert
3495796c8dcSSimon Schubert /* Find how many directories are in common between bin_prefix & prefix. */
3505796c8dcSSimon Schubert n = (prefix_num < bin_num) ? prefix_num : bin_num;
3515796c8dcSSimon Schubert for (common = 0; common < n; common++)
3525796c8dcSSimon Schubert {
3535796c8dcSSimon Schubert if (strcmp (bin_dirs[common], prefix_dirs[common]) != 0)
3545796c8dcSSimon Schubert break;
3555796c8dcSSimon Schubert }
3565796c8dcSSimon Schubert
3575796c8dcSSimon Schubert /* If there are no common directories, there can be no relative prefix. */
3585796c8dcSSimon Schubert if (common == 0)
3595796c8dcSSimon Schubert goto bailout;
3605796c8dcSSimon Schubert
3615796c8dcSSimon Schubert /* Two passes: first figure out the size of the result string, and
3625796c8dcSSimon Schubert then construct it. */
3635796c8dcSSimon Schubert needed_len = 0;
3645796c8dcSSimon Schubert for (i = 0; i < prog_num; i++)
3655796c8dcSSimon Schubert needed_len += strlen (prog_dirs[i]);
3665796c8dcSSimon Schubert needed_len += sizeof (DIR_UP) * (bin_num - common);
3675796c8dcSSimon Schubert for (i = common; i < prefix_num; i++)
3685796c8dcSSimon Schubert needed_len += strlen (prefix_dirs[i]);
3695796c8dcSSimon Schubert needed_len += 1; /* Trailing NUL. */
3705796c8dcSSimon Schubert
3715796c8dcSSimon Schubert ret = (char *) malloc (needed_len);
3725796c8dcSSimon Schubert if (ret == NULL)
3735796c8dcSSimon Schubert goto bailout;
3745796c8dcSSimon Schubert
3755796c8dcSSimon Schubert /* Build up the pathnames in argv[0]. */
3765796c8dcSSimon Schubert *ret = '\0';
3775796c8dcSSimon Schubert for (i = 0; i < prog_num; i++)
3785796c8dcSSimon Schubert strcat (ret, prog_dirs[i]);
3795796c8dcSSimon Schubert
3805796c8dcSSimon Schubert /* Now build up the ..'s. */
3815796c8dcSSimon Schubert ptr = ret + strlen(ret);
3825796c8dcSSimon Schubert for (i = common; i < bin_num; i++)
3835796c8dcSSimon Schubert {
3845796c8dcSSimon Schubert strcpy (ptr, DIR_UP);
3855796c8dcSSimon Schubert ptr += sizeof (DIR_UP) - 1;
3865796c8dcSSimon Schubert *(ptr++) = DIR_SEPARATOR;
3875796c8dcSSimon Schubert }
3885796c8dcSSimon Schubert *ptr = '\0';
3895796c8dcSSimon Schubert
3905796c8dcSSimon Schubert /* Put in directories to move over to prefix. */
3915796c8dcSSimon Schubert for (i = common; i < prefix_num; i++)
3925796c8dcSSimon Schubert strcat (ret, prefix_dirs[i]);
3935796c8dcSSimon Schubert
3945796c8dcSSimon Schubert bailout:
3955796c8dcSSimon Schubert free_split_directories (prog_dirs);
3965796c8dcSSimon Schubert free_split_directories (bin_dirs);
3975796c8dcSSimon Schubert free_split_directories (prefix_dirs);
3985796c8dcSSimon Schubert
3995796c8dcSSimon Schubert return ret;
4005796c8dcSSimon Schubert }
4015796c8dcSSimon Schubert
4025796c8dcSSimon Schubert
4035796c8dcSSimon Schubert /* Do the full job, including symlink resolution.
4045796c8dcSSimon Schubert This path will find files installed in the same place as the
4055796c8dcSSimon Schubert program even when a soft link has been made to the program
4065796c8dcSSimon Schubert from somwhere else. */
4075796c8dcSSimon Schubert
4085796c8dcSSimon Schubert char *
make_relative_prefix(const char * progname,const char * bin_prefix,const char * prefix)4095796c8dcSSimon Schubert make_relative_prefix (const char *progname, const char *bin_prefix,
4105796c8dcSSimon Schubert const char *prefix)
4115796c8dcSSimon Schubert {
4125796c8dcSSimon Schubert return make_relative_prefix_1 (progname, bin_prefix, prefix, 1);
4135796c8dcSSimon Schubert }
4145796c8dcSSimon Schubert
4155796c8dcSSimon Schubert /* Make the relative pathname without attempting to resolve any links.
4165796c8dcSSimon Schubert '..' etc may also be left in the pathname.
4175796c8dcSSimon Schubert This will find the files the user meant the program to find if the
4185796c8dcSSimon Schubert installation is patched together with soft links. */
4195796c8dcSSimon Schubert
4205796c8dcSSimon Schubert char *
make_relative_prefix_ignore_links(const char * progname,const char * bin_prefix,const char * prefix)4215796c8dcSSimon Schubert make_relative_prefix_ignore_links (const char *progname,
4225796c8dcSSimon Schubert const char *bin_prefix,
4235796c8dcSSimon Schubert const char *prefix)
4245796c8dcSSimon Schubert {
4255796c8dcSSimon Schubert return make_relative_prefix_1 (progname, bin_prefix, prefix, 0);
4265796c8dcSSimon Schubert }
4275796c8dcSSimon Schubert
428