00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050 #ifdef HAVE_CONFIG_H
00051 #include "config.h"
00052 #endif
00053
00054 #ifdef HAVE_STDLIB_H
00055 #include <stdlib.h>
00056 #endif
00057 #ifdef HAVE_UNISTD_H
00058 #include <unistd.h>
00059 #endif
00060
00061 #include <string.h>
00062
00063 #include "ansidecl.h"
00064 #include "libiberty.h"
00065
00066 #ifndef R_OK
00067 #define R_OK 4
00068 #define W_OK 2
00069 #define X_OK 1
00070 #endif
00071
00072 #ifndef DIR_SEPARATOR
00073 # define DIR_SEPARATOR '/'
00074 #endif
00075
00076 #if defined (_WIN32) || defined (__MSDOS__) \
00077 || defined (__DJGPP__) || defined (__OS2__)
00078 # define HAVE_DOS_BASED_FILE_SYSTEM
00079 # define HAVE_HOST_EXECUTABLE_SUFFIX
00080 # define HOST_EXECUTABLE_SUFFIX ".exe"
00081 # ifndef DIR_SEPARATOR_2
00082 # define DIR_SEPARATOR_2 '\\'
00083 # endif
00084 # define PATH_SEPARATOR ';'
00085 #else
00086 # define PATH_SEPARATOR ':'
00087 #endif
00088
00089 #ifndef DIR_SEPARATOR_2
00090 # define IS_DIR_SEPARATOR(ch) ((ch) == DIR_SEPARATOR)
00091 #else
00092 # define IS_DIR_SEPARATOR(ch) \
00093 (((ch) == DIR_SEPARATOR) || ((ch) == DIR_SEPARATOR_2))
00094 #endif
00095
00096 #define DIR_UP ".."
00097
00098 static char *save_string PARAMS ((const char *, int));
00099 static char **split_directories PARAMS ((const char *, int *));
00100 static void free_split_directories PARAMS ((char **));
00101
00102 static char *
00103 save_string (s, len)
00104 const char *s;
00105 int len;
00106 {
00107 char *result = malloc (len + 1);
00108
00109 memcpy (result, s, len);
00110 result[len] = 0;
00111 return result;
00112 }
00113
00114
00115
00116 static char **
00117 split_directories (name, ptr_num_dirs)
00118 const char *name;
00119 int *ptr_num_dirs;
00120 {
00121 int num_dirs = 0;
00122 char **dirs;
00123 const char *p, *q;
00124 int ch;
00125
00126
00127
00128 p = name;
00129 #ifdef HAVE_DOS_BASED_FILE_SYSTEM
00130 if (name[1] == ':' && IS_DIR_SEPARATOR (name[2]))
00131 {
00132 p += 3;
00133 num_dirs++;
00134 }
00135 #endif
00136
00137 while ((ch = *p++) != '\0')
00138 {
00139 if (IS_DIR_SEPARATOR (ch))
00140 {
00141 num_dirs++;
00142 while (IS_DIR_SEPARATOR (*p))
00143 p++;
00144 }
00145 }
00146
00147 dirs = (char **) malloc (sizeof (char *) * (num_dirs + 2));
00148 if (dirs == NULL)
00149 return NULL;
00150
00151
00152 num_dirs = 0;
00153 p = name;
00154 #ifdef HAVE_DOS_BASED_FILE_SYSTEM
00155 if (name[1] == ':' && IS_DIR_SEPARATOR (name[2]))
00156 {
00157 dirs[num_dirs++] = save_string (p, 3);
00158 if (dirs[num_dirs - 1] == NULL)
00159 {
00160 free (dirs);
00161 return NULL;
00162 }
00163 p += 3;
00164 }
00165 #endif
00166
00167 q = p;
00168 while ((ch = *p++) != '\0')
00169 {
00170 if (IS_DIR_SEPARATOR (ch))
00171 {
00172 while (IS_DIR_SEPARATOR (*p))
00173 p++;
00174
00175 dirs[num_dirs++] = save_string (q, p - q);
00176 if (dirs[num_dirs - 1] == NULL)
00177 {
00178 dirs[num_dirs] = NULL;
00179 free_split_directories (dirs);
00180 return NULL;
00181 }
00182 q = p;
00183 }
00184 }
00185
00186 if (p - 1 - q > 0)
00187 dirs[num_dirs++] = save_string (q, p - 1 - q);
00188 dirs[num_dirs] = NULL;
00189
00190 if (dirs[num_dirs - 1] == NULL)
00191 {
00192 free_split_directories (dirs);
00193 return NULL;
00194 }
00195
00196 if (ptr_num_dirs)
00197 *ptr_num_dirs = num_dirs;
00198 return dirs;
00199 }
00200
00201
00202
00203 static void
00204 free_split_directories (dirs)
00205 char **dirs;
00206 {
00207 int i = 0;
00208
00209 while (dirs[i] != NULL)
00210 free (dirs[i++]);
00211
00212 free ((char *) dirs);
00213 }
00214
00215
00216
00217
00218
00219
00220
00221
00222
00223
00224
00225 char *
00226 make_relative_prefix (progname, bin_prefix, prefix)
00227 const char *progname;
00228 const char *bin_prefix;
00229 const char *prefix;
00230 {
00231 char **prog_dirs, **bin_dirs, **prefix_dirs;
00232 int prog_num, bin_num, prefix_num;
00233 int i, n, common;
00234 int needed_len;
00235 char *ret, *ptr, *full_progname = NULL;
00236
00237 if (progname == NULL || bin_prefix == NULL || prefix == NULL)
00238 return NULL;
00239
00240
00241
00242 if (lbasename (progname) == progname)
00243 {
00244 char *temp;
00245
00246 temp = getenv ("PATH");
00247 if (temp)
00248 {
00249 char *startp, *endp, *nstore;
00250 size_t prefixlen = strlen (temp) + 1;
00251 if (prefixlen < 2)
00252 prefixlen = 2;
00253
00254 nstore = (char *) alloca (prefixlen + strlen (progname) + 1);
00255
00256 startp = endp = temp;
00257 while (1)
00258 {
00259 if (*endp == PATH_SEPARATOR || *endp == 0)
00260 {
00261 if (endp == startp)
00262 {
00263 nstore[0] = '.';
00264 nstore[1] = DIR_SEPARATOR;
00265 nstore[2] = '\0';
00266 }
00267 else
00268 {
00269 strncpy (nstore, startp, endp - startp);
00270 if (! IS_DIR_SEPARATOR (endp[-1]))
00271 {
00272 nstore[endp - startp] = DIR_SEPARATOR;
00273 nstore[endp - startp + 1] = 0;
00274 }
00275 else
00276 nstore[endp - startp] = 0;
00277 }
00278 strcat (nstore, progname);
00279 if (! access (nstore, X_OK)
00280 #ifdef HAVE_HOST_EXECUTABLE_SUFFIX
00281 || ! access (strcat (nstore, HOST_EXECUTABLE_SUFFIX), X_OK)
00282 #endif
00283 )
00284 {
00285 progname = nstore;
00286 break;
00287 }
00288
00289 if (*endp == 0)
00290 break;
00291 endp = startp = endp + 1;
00292 }
00293 else
00294 endp++;
00295 }
00296 }
00297 }
00298
00299 full_progname = lrealpath (progname);
00300 if (full_progname == NULL)
00301 return NULL;
00302
00303 prog_dirs = split_directories (full_progname, &prog_num);
00304 bin_dirs = split_directories (bin_prefix, &bin_num);
00305 free (full_progname);
00306 if (bin_dirs == NULL || prog_dirs == NULL)
00307 return NULL;
00308
00309
00310 prog_num--;
00311
00312
00313
00314
00315
00316 if (prog_num == bin_num)
00317 {
00318 for (i = 0; i < bin_num; i++)
00319 {
00320 if (strcmp (prog_dirs[i], bin_dirs[i]) != 0)
00321 break;
00322 }
00323
00324 if (prog_num <= 0 || i == bin_num)
00325 {
00326 free_split_directories (prog_dirs);
00327 free_split_directories (bin_dirs);
00328 prog_dirs = bin_dirs = (char **) 0;
00329 return NULL;
00330 }
00331 }
00332
00333 prefix_dirs = split_directories (prefix, &prefix_num);
00334 if (prefix_dirs == NULL)
00335 {
00336 free_split_directories (prog_dirs);
00337 free_split_directories (bin_dirs);
00338 return NULL;
00339 }
00340
00341
00342 n = (prefix_num < bin_num) ? prefix_num : bin_num;
00343 for (common = 0; common < n; common++)
00344 {
00345 if (strcmp (bin_dirs[common], prefix_dirs[common]) != 0)
00346 break;
00347 }
00348
00349
00350 if (common == 0)
00351 {
00352 free_split_directories (prog_dirs);
00353 free_split_directories (bin_dirs);
00354 free_split_directories (prefix_dirs);
00355 return NULL;
00356 }
00357
00358
00359
00360 needed_len = 0;
00361 for (i = 0; i < prog_num; i++)
00362 needed_len += strlen (prog_dirs[i]);
00363 needed_len += sizeof (DIR_UP) * (bin_num - common);
00364 for (i = common; i < prefix_num; i++)
00365 needed_len += strlen (prefix_dirs[i]);
00366 needed_len += 1;
00367
00368 ret = (char *) malloc (needed_len);
00369 if (ret == NULL)
00370 return NULL;
00371
00372
00373 *ret = '\0';
00374 for (i = 0; i < prog_num; i++)
00375 strcat (ret, prog_dirs[i]);
00376
00377
00378 ptr = ret + strlen(ret);
00379 for (i = common; i < bin_num; i++)
00380 {
00381 strcpy (ptr, DIR_UP);
00382 ptr += sizeof (DIR_UP) - 1;
00383 *(ptr++) = DIR_SEPARATOR;
00384 }
00385 *ptr = '\0';
00386
00387
00388 for (i = common; i < prefix_num; i++)
00389 strcat (ret, prefix_dirs[i]);
00390
00391 free_split_directories (prog_dirs);
00392 free_split_directories (bin_dirs);
00393 free_split_directories (prefix_dirs);
00394
00395 return ret;
00396 }