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