1 /*******************************************************************
2 * File: omFindExec.c
3 * Purpose: routine which determines absolute pathname of executable
4 * Author: obachman (Olaf Bachmann)
5 * Created: 11/99
6 *******************************************************************/
7
8
9 #include "singular_resourcesconfig.h"
10
11
12 #if defined(HAVE_UNISTD_H) && defined(STDC_HEADERS)
13
14 #ifdef HAVE_UNISTD_H
15 #include <unistd.h> /* always defiend */
16 #endif
17
18 #include <stdlib.h>
19 #include <string.h>
20
21 #include "omFindExec.h"
22
23 #ifndef MAXPATHLEN
24 #define MAXPATHLEN 1024
25 #endif
26
27 /* ABSOLUTE_FILENAME_P (fname): True if fname is an absolute filename */
28 #define ABSOLUTE_FILENAME_P(fname) (fname[0] == '/')
29
30 /* Return the absolute name of the program named NAME. This function
31 searches the directories in the PATH environment variable if PROG
32 has no directory components. */
33 #ifndef HAVE_READLINK
omFindExec(const char * name,char * executable)34 char * omFindExec (const char *name, char* executable)
35 #else
36 static char * omFindExec_link (const char *name, char* executable)
37 #endif
38 {
39 char *search;
40 char *p;
41 char tbuf[MAXPATHLEN];
42
43 if (ABSOLUTE_FILENAME_P(name))
44 {
45 /* If the named file exists then return it. */
46 if (! access (name, F_OK)) //think of libSingular.so as main binary
47 // r or x is required
48 {
49 strcpy(executable, name);
50 return executable;
51 }
52 }
53 else
54 {
55 if (((name[0] == '.') && (name[1] == '/')) ||
56 ((name[0] == '.') && (name[1] == '.') && (name[2] == '/')) ||
57 strchr(name, '/') != NULL)
58 {
59
60 #ifdef HAVE_GETCWD
61 getcwd (tbuf, MAXPATHLEN);
62 #else
63 # ifdef HAVE_GETWD
64 getwd (tbuf);
65 # endif
66 #endif
67 strcat (tbuf, "/");
68 strcat (tbuf, name);
69 if (! access(tbuf, F_OK))
70 {
71 strcpy(executable, tbuf);
72 return executable;
73 }
74 }
75
76
77 search = getenv("PATH");
78 /* for winnt under msdos, cwd is implictly in the path */
79 p = search;
80
81 if (p != NULL)
82 {
83 while (1)
84 {
85 char *next;
86 next = tbuf;
87
88 /* Copy directory name into [tbuf]. */
89 /* This is somewhat tricky: empty names mean cwd, w.r.t. some
90 shell spec */
91 while (*p && *p != ':')
92 *next ++ = *p ++;
93 *next = '\0';
94
95 if ((tbuf[0] == '.' && tbuf[1] == '\0') || tbuf[0] == '\0') {
96 #ifdef HAVE_GETCWD
97 getcwd (tbuf, MAXPATHLEN);
98 #else
99 # ifdef HAVE_GETWD
100 getwd (tbuf);
101 # endif
102 #endif
103 }
104
105 if (tbuf[strlen(tbuf)-1] != '/') strcat(tbuf, "/");
106 strcat (tbuf, name);
107
108 /* If the named file exists, then return it. */
109 if (! access (tbuf, F_OK))
110 {
111 strcpy(executable, tbuf);
112 return executable;
113 }
114
115 if (*p != '\0')
116 {
117 p ++;
118 }
119 else
120 {
121 break;
122 }
123 }
124 }
125 }
126 return NULL;
127 }
128
129 #ifdef HAVE_READLINK
130 /* similar to readlink, but dont' mess up absolute pathnames */
my_readlink(const char * name,char * buf,size_t bufsize)131 static int my_readlink(const char* name, char* buf, size_t bufsize)
132 {
133 char buf2[MAXPATHLEN];
134 int ret;
135
136 if ((ret = readlink(name, buf2, bufsize)) > 0)
137 {
138 buf2[ret] = 0;
139 if (*name == '/' && *buf2 != '/')
140 {
141 char* last = strrchr(name, '/');
142 int i = 0;
143 while (&(name[i]) != last)
144 {
145 buf[i] = name[i];
146 i++;
147 }
148 buf[i] = '/';
149 i++;
150 strcpy(&(buf[i]), buf2);
151 return i + ret;
152 }
153 else
154 {
155 strcpy(buf, buf2);
156 }
157 }
158 return ret;
159 }
160
161 #define MAX_LINK_LEVEL 10
162 /* similar to readlink (cf. man readlink), except that symbolic links are
163 followed up to MAX_LINK_LEVEL
164 */
full_readlink(const char * name,char * buf,size_t bufsize)165 static int full_readlink(const char* name, char* buf, size_t bufsize)
166 {
167 int ret;
168
169 if ((ret=my_readlink(name, buf, bufsize)) > 0)
170 {
171 char buf2[MAXPATHLEN];
172 int ret2, i = 0;
173
174 do
175 {
176 buf[ret] = '\0';
177 if ((ret2 = my_readlink(buf, buf2, MAXPATHLEN)) > 0)
178 {
179 i++;
180 buf2[ret2] = '\0';
181 strcpy(buf, buf2);
182 ret = ret2;
183 }
184 else
185 {
186 return ret;
187 }
188 }
189 while (i<MAX_LINK_LEVEL);
190 }
191 return -1;
192 }
193
194 #ifdef __CYGWIN__
195 /* for windows, serch first for .exe */
196 char * _omFindExec (const char *name, char* exec);
omFindExec(const char * name,char * exec)197 char* omFindExec(const char *name, char* exec)
198 {
199
200 if (strstr(name, ".exe") == NULL)
201 {
202 char buf[MAXPATHLEN];
203 char* ret;
204 strcpy(buf, name);
205 strcat(buf, ".exe");
206 ret = _omFindExec(buf, exec);
207 if (ret != NULL) return ret;
208 }
209 return _omFindExec(name, exec);
210 }
211 #else
212 #define _omFindExec omFindExec
213 #endif
214
_omFindExec(const char * name,char * exec)215 char * _omFindExec (const char *name, char* exec)
216 {
217 char * link = omFindExec_link(name, exec);
218 char buf[MAXPATHLEN];
219 int ret;
220
221 if (link == NULL && (ret=full_readlink(name, buf, MAXPATHLEN)) > 0)
222 {
223 buf[ret] ='\0';
224 link = omFindExec_link(buf, exec);
225 }
226 if (link != NULL && (ret=full_readlink(link, buf, MAXPATHLEN)) > 0)
227 {
228 char *p = strrchr(link, '/');
229
230
231 if(p!=NULL) *(p+1)='\0';
232 buf[ret]='\0';
233
234 if (buf[0] != '/')
235 {
236 strcpy(exec, link);
237 strcat(exec, buf);
238 }
239 else
240 {
241 strcpy(exec, buf);
242 }
243
244 return exec;
245 }
246 return link;
247 }
248 #endif /* HAVE_READLINK */
249
250 #else
251
omFindExec(const char * name,char * exec)252 char* omFindExec (const char *name, char* exec)
253 {
254 return name;
255 }
256
257 #endif /* defined(HAVE_UNISTD_H) && defined(STDC_HEADERS) */
258