HPCToolkit
executable-path.c
Go to the documentation of this file.
1 // -*-Mode: C++;-*- // technically C99
2 
3 // * BeginRiceCopyright *****************************************************
4 //
5 // $HeadURL$
6 // $Id$
7 //
8 // --------------------------------------------------------------------------
9 // Part of HPCToolkit (hpctoolkit.org)
10 //
11 // Information about sources of support for research and development of
12 // HPCToolkit is at 'hpctoolkit.org' and in 'README.Acknowledgments'.
13 // --------------------------------------------------------------------------
14 //
15 // Copyright ((c)) 2002-2019, Rice University
16 // All rights reserved.
17 //
18 // Redistribution and use in source and binary forms, with or without
19 // modification, are permitted provided that the following conditions are
20 // met:
21 //
22 // * Redistributions of source code must retain the above copyright
23 // notice, this list of conditions and the following disclaimer.
24 //
25 // * Redistributions in binary form must reproduce the above copyright
26 // notice, this list of conditions and the following disclaimer in the
27 // documentation and/or other materials provided with the distribution.
28 //
29 // * Neither the name of Rice University (RICE) nor the names of its
30 // contributors may be used to endorse or promote products derived from
31 // this software without specific prior written permission.
32 //
33 // This software is provided by RICE and contributors "as is" and any
34 // express or implied warranties, including, but not limited to, the
35 // implied warranties of merchantability and fitness for a particular
36 // purpose are disclaimed. In no event shall RICE or contributors be
37 // liable for any direct, indirect, incidental, special, exemplary, or
38 // consequential damages (including, but not limited to, procurement of
39 // substitute goods or services; loss of use, data, or profits; or
40 // business interruption) however caused and on any theory of liability,
41 // whether in contract, strict liability, or tort (including negligence
42 // or otherwise) arising in any way out of the use of this software, even
43 // if advised of the possibility of such damage.
44 //
45 // ******************************************************* EndRiceCopyright *
46 
47 #include <unistd.h>
48 #include <limits.h>
49 #include <stdlib.h>
50 #include <string.h>
51 
52 #include "executable-path.h"
53 
54 /*
55  *******************************************************************************
56  * forward declarations
57  *******************************************************************************
58  */
59 
60 static int assemble_fullpath(const char *prefix, const int terminator,
61  const char *suffix, char *result,
62  char *result_end);
63 
64 
65 
66 /*
67  *******************************************************************************
68  * interface operations
69  *******************************************************************************
70  */
71 
72 /*
73  * NOTES:
74  * 1. path_list is colon separated
75  * 2. pathresult must point to a buffer of length PATH_MAX
76  * 2. this routine can't allocate any memory, which
77  * makes the implementation a bit more complicated
78  * because it can't handle cases as uniformly
79  * using in-place modification.
80  */
81 char *
82 executable_path(const char *filename, const char *path_list,
83  char *executable_name)
84 {
85  if (!access(filename, F_OK)) return realpath(filename, executable_name);
86  else {
87  char path[PATH_MAX];
88  int failure;
89  const char *path_prefix;
90  const char *colon;
91 
92  /* check for bad absolute path (lookup already failed above) */
93  if (*filename == '/') return NULL;
94 
95  /* look for the file using each path in path_list */
96  path_prefix = path_list;
97  colon = path_list;
98  while (path_prefix) {
99  colon = strchr(path_prefix,':'); /* find the end of path_prefix */
100 
101  /*
102  * assemble a new path using the current path_prefix. the character
103  * marking the end of path_prefix is either a ':' if there is another
104  * path in path_list or it is a 0 if path_prefix points to the last
105  * prefix
106  */
107  failure = assemble_fullpath(path_prefix, (colon ? ':' : 0), filename,
108  path, &path[PATH_MAX - 1]);
109  if (failure) return NULL;
110 
111  /* if the file is present at path, return its real path in
112  * executable_name
113  */
114  if (!access(path, X_OK)) return realpath(path, executable_name);
115 
116  /* move path_prefix to the next path in path_list, if any */
117  path_prefix = (colon ? colon + 1 : NULL);
118  }
119  }
120 
121  return NULL;
122 }
123 
124 
125 
126 /*
127  *******************************************************************************
128  * private operations
129  *******************************************************************************
130  */
131 
132 /*
133  * function: strtcpy
134  *
135  * purpose:
136  * copy string from src to dest until either the terminating character t
137  * is encountered in the src string, or dest passes dest_end
138  *
139  * arguments: t is the terminating character
140  */
141 static char *
142 strtcpy(char *dest, const char *src, const int t, char *dest_end)
143 {
144  for (;;) {
145  char c = *src++;
146  if (c == t) break;
147  if (dest > dest_end) return 0;
148  *dest++ = c;
149  }
150  return dest;
151 }
152 
153 
154 static int
155 assemble_fullpath(const char *prefix, const int terminator,
156  const char *suffix, char *result, char *result_end)
157 {
158  char *end;
159 
160  /* copy prefix */
161  end = strtcpy(result, prefix, terminator, result_end);
162  if (!end) return -1; /* string too long */
163 
164  /* ensure path prefix is terminated by a slash */
165  if (*(end - 1) != '/') {
166  if (end > result_end) return -1;
167  else *end++ = '/';
168  }
169 
170  /* append suffix */
171  end = strtcpy(end, suffix, 0, result_end);
172  if (!end) return -1;
173 
174  /* null terminate */
175  if (end > result_end) return -1;
176  *end = 0;
177 
178  return 0;
179 }
char * executable_name
static int assemble_fullpath(const char *prefix, const int terminator, const char *suffix, char *result, char *result_end)
static char * prefix
Definition: common.c:164
static char * strtcpy(char *dest, const char *src, const int t, char *dest_end)
#define NULL
Definition: ElfHelper.cpp:85
char * executable_path(const char *filename, const char *path_list, char *executable_name)