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