4294
|
1 /* Locating a program in PATH. |
|
2 Copyright (C) 2001-2003 Free Software Foundation, Inc. |
|
3 Written by Bruno Haible <haible@clisp.cons.org>, 2001. |
|
4 |
|
5 This program is free software; you can redistribute it and/or modify |
|
6 it under the terms of the GNU General Public License as published by |
|
7 the Free Software Foundation; either version 2, or (at your option) |
|
8 any later version. |
|
9 |
|
10 This program is distributed in the hope that it will be useful, |
|
11 but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
13 GNU General Public License for more details. |
|
14 |
|
15 You should have received a copy of the GNU General Public License |
|
16 along with this program; if not, write to the Free Software Foundation, |
|
17 Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ |
|
18 |
|
19 |
|
20 #ifdef HAVE_CONFIG_H |
|
21 # include "config.h" |
|
22 #endif |
|
23 |
|
24 /* Specification. */ |
|
25 #include "findprog.h" |
|
26 |
|
27 #include <stdbool.h> |
|
28 #include <stdlib.h> |
|
29 #include <string.h> |
|
30 |
|
31 #ifdef HAVE_UNISTD_H |
|
32 # include <unistd.h> |
|
33 #endif |
|
34 |
|
35 #include "xalloc.h" |
|
36 #include "pathname.h" |
|
37 |
|
38 |
|
39 const char * |
|
40 find_in_path (const char *progname) |
|
41 { |
|
42 #if defined _WIN32 || defined __WIN32__ || defined __EMX__ || defined __DJGPP__ |
|
43 /* Win32, OS/2, DOS */ |
|
44 /* The searching rules with .COM, .EXE, .BAT, .CMD etc. suffixes are |
|
45 too complicated. Leave it to the OS. */ |
|
46 return progname; |
|
47 #else |
|
48 /* Unix */ |
|
49 char *path; |
|
50 char *dir; |
|
51 char *cp; |
|
52 |
|
53 if (strchr (progname, '/') != NULL) |
|
54 /* If progname contains a slash, it is either absolute or relative to |
|
55 the current directory. PATH is not used. */ |
|
56 return progname; |
|
57 |
|
58 path = getenv ("PATH"); |
|
59 if (path == NULL || *path == '\0') |
|
60 /* If PATH is not set, the default search path is implementation |
|
61 dependent. */ |
|
62 return progname; |
|
63 |
|
64 /* Make a copy, to prepare for destructive modifications. */ |
|
65 path = xstrdup (path); |
|
66 for (dir = path; ; dir = cp + 1) |
|
67 { |
|
68 bool last; |
|
69 char *progpathname; |
|
70 |
|
71 /* Extract next directory in PATH. */ |
|
72 for (cp = dir; *cp != '\0' && *cp != ':'; cp++) |
|
73 ; |
|
74 last = (*cp == '\0'); |
|
75 *cp = '\0'; |
|
76 |
|
77 /* Empty PATH components designate the current directory. */ |
|
78 if (dir == cp) |
|
79 dir = "."; |
|
80 |
|
81 /* Concatenate dir and progname. */ |
|
82 progpathname = concatenated_pathname (dir, progname, NULL); |
|
83 |
|
84 /* On systems which have the eaccess() system call, let's use it. |
|
85 On other systems, let's hope that this program is not installed |
|
86 setuid or setgid, so that it is ok to call access() despite its |
|
87 design flaw. */ |
|
88 if (eaccess (progpathname, X_OK) == 0) |
|
89 { |
|
90 /* Found! */ |
|
91 if (strcmp (progpathname, progname) == 0) |
|
92 { |
|
93 free (progpathname); |
|
94 |
|
95 /* Add the "./" prefix for real, that concatenated_pathname() |
|
96 optimized away. This avoids a second PATH search when the |
|
97 caller uses execlp/execvp. */ |
|
98 progpathname = xmalloc (2 + strlen (progname) + 1); |
|
99 progpathname[0] = '.'; |
|
100 progpathname[1] = '/'; |
|
101 memcpy (progpathname + 2, progname, strlen (progname) + 1); |
|
102 } |
|
103 |
|
104 free (path); |
|
105 return progpathname; |
|
106 } |
|
107 |
|
108 free (progpathname); |
|
109 |
|
110 if (last) |
|
111 break; |
|
112 } |
|
113 |
|
114 /* Not found in PATH. An error will be signalled at the first call. */ |
|
115 free (path); |
|
116 return progname; |
|
117 #endif |
|
118 } |