1 /*
2 * pathsearch.c: $PATH-searching functions.
3 *
4 * Copyright (C) 2004, 2007, 2008, 2009, 2011 Colin Watson.
5 *
6 * This file is part of man-db.
7 *
8 * man-db is free software; you can redistribute it and/or modify it
9 * under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
12 *
13 * man-db is distributed in the hope that it will be useful, but
14 * WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with man-db; if not, write to the Free Software Foundation,
20 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
21 */
22
23 #ifdef HAVE_CONFIG_H
24 # include "config.h"
25 #endif /* HAVE_CONFIG_H */
26
27 #include <assert.h>
28 #include <errno.h>
29 #include <stdbool.h>
30 #include <string.h>
31 #include <stdlib.h>
32
33 #include <sys/types.h>
34 #include <sys/stat.h>
35 #include <unistd.h>
36
37 #include "gettext.h"
38 #define _(String) gettext (String)
39
40 #include "xalloc.h"
41 #include "xgetcwd.h"
42 #include "xvasprintf.h"
43
44 #include "manconfig.h"
45
46 #include "fatal.h"
47 #include "pathsearch.h"
48
49 static bool pathsearch (const char *name, const mode_t bits)
50 {
51 char *cwd = NULL;
52 char *path = getenv ("PATH");
53 char *pathtok;
54 const char *element;
55 struct stat st;
56 bool ret = false;
57
58 if (!path)
59 /* Eh? Oh well. */
60 return false;
61
62 if (strchr (name, '/')) {
63 /* Qualified name; look directly. */
64 if (stat (name, &st) == -1)
65 return false;
66 if (S_ISREG (st.st_mode) && (st.st_mode & bits))
67 return true;
68 return false;
69 }
70
71 pathtok = path = xstrdup (path);
72
73 /* Unqualified name; iterate over $PATH looking for it. */
74 for (element = strsep (&pathtok, ":"); element;
75 element = strsep (&pathtok, ":")) {
76 char *filename;
77
78 if (!*element) {
79 if (!cwd)
80 cwd = xgetcwd ();
81 if (!cwd)
82 fatal (errno,
83 _("can't determine current directory"));
84 element = cwd;
85 }
86
87 filename = xasprintf ("%s/%s", element, name);
88 assert (filename);
89 if (stat (filename, &st) == -1) {
90 free (filename);
91 continue;
92 }
93
94 free (filename);
95
96 if (S_ISREG (st.st_mode) && (st.st_mode & bits)) {
97 ret = true;
98 break;
99 }
100 }
101
102 free (path);
103 free (cwd);
104 return ret;
105 }
106
107 bool pathsearch_executable (const char *name)
108 {
109 return pathsearch (name, 0111);
110 }
111
112 bool directory_on_path (const char *dir)
113 {
114 char *cwd = NULL;
115 char *path = getenv ("PATH");
116 char *pathtok;
117 const char *element;
118 bool ret = false;
119
120 if (!path)
121 /* Eh? Oh well. */
122 return false;
123
124 pathtok = path = xstrdup (path);
125
126 for (element = strsep (&pathtok, ":"); element;
127 element = strsep (&pathtok, ":")) {
128 if (!*element) {
129 if (!cwd)
130 cwd = xgetcwd ();
131 if (!cwd)
132 fatal (errno,
133 _("can't determine current directory"));
134 element = cwd;
135 }
136
137 if (STREQ (element, dir)) {
138 ret = true;
139 break;
140 }
141 }
142
143 free (path);
144 free (cwd);
145 return ret;
146 }