Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
att
GitHub Repository: att/ast
Path: blob/master/src/lib/libast/path/pathprobe.c
1810 views
1
/***********************************************************************
2
* *
3
* This software is part of the ast package *
4
* Copyright (c) 1985-2012 AT&T Intellectual Property *
5
* and is licensed under the *
6
* Eclipse Public License, Version 1.0 *
7
* by AT&T Intellectual Property *
8
* *
9
* A copy of the License is available at *
10
* http://www.eclipse.org/org/documents/epl-v10.html *
11
* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
12
* *
13
* Information and Software Systems Research *
14
* AT&T Research *
15
* Florham Park NJ *
16
* *
17
* Glenn Fowler <[email protected]> *
18
* David Korn <[email protected]> *
19
* Phong Vo <[email protected]> *
20
* *
21
***********************************************************************/
22
#pragma prototyped
23
/*
24
* Glenn Fowler
25
* AT&T Research
26
*
27
* return in path the full path name of the probe(1)
28
* information for lang and tool using proc
29
* if attr != 0 then path attribute assignments placed here
30
*
31
* if path==0 then the space is malloc'd
32
*
33
* op:
34
*
35
* -3 return non-writable path name with no generation
36
* -2 return path name with no generation
37
* -1 return no $HOME path name with no generation
38
* 0 verbose probe
39
* 1 silent probe
40
*
41
* 0 returned if the info does not exist and cannot be generated
42
*/
43
44
#define _AST_API_H 1
45
46
#include <ast.h>
47
#include <error.h>
48
#include <ls.h>
49
#include <proc.h>
50
51
char*
52
pathprobe(char* path, char* attr, const char* lang, const char* tool, const char* proc, int op)
53
{
54
return pathprobe_20100601(lang, tool, proc, op, path, PATH_MAX, attr, PATH_MAX);
55
}
56
57
#undef _AST_API_H
58
59
#include <ast_api.h>
60
61
#ifndef PROBE
62
#define PROBE "probe"
63
#endif
64
65
#if defined(ST_RDONLY) || defined(ST_NOSUID)
66
67
/*
68
* return non-0 if path is in a readonly or non-setuid fs
69
*/
70
71
static int
72
rofs(const char* path)
73
{
74
struct statvfs vfs;
75
struct stat st;
76
77
if (!statvfs(path, &vfs))
78
{
79
#if defined(ST_RDONLY)
80
if (vfs.f_flag & ST_RDONLY)
81
return 1;
82
#endif
83
#if defined(ST_NOSUID)
84
if ((vfs.f_flag & ST_NOSUID) && (stat(path, &st) || st.st_uid != getuid() && st.st_uid != geteuid()))
85
return 1;
86
#endif
87
}
88
return 0;
89
}
90
91
#else
92
93
#define rofs(p) 0
94
95
#endif
96
97
char*
98
pathprobe_20100601(const char* lang, const char* tool, const char* aproc, int op, char* path, size_t pathsize, char* attr, size_t attrsize)
99
{
100
char* proc = (char*)aproc;
101
register char* p;
102
register char* k;
103
register char* x;
104
register char** ap;
105
int n;
106
int v;
107
int force;
108
ssize_t r;
109
char* e;
110
char* np;
111
char* nx;
112
char* probe;
113
const char* dirs;
114
const char* dir;
115
Proc_t* pp;
116
Sfio_t* sp;
117
char buf[PATH_MAX];
118
char cmd[PATH_MAX];
119
char exe[PATH_MAX];
120
char lib[PATH_MAX];
121
char ver[PATH_MAX];
122
char key[16];
123
char* arg[8];
124
long ops[2];
125
unsigned long ptime;
126
struct stat st;
127
struct stat ps;
128
129
if (*proc != '/')
130
{
131
if (p = strchr(proc, ' '))
132
{
133
strncopy(buf, proc, p - proc + 1);
134
proc = buf;
135
}
136
if (!(proc = pathpath(proc, NiL, PATH_ABSOLUTE|PATH_REGULAR|PATH_EXECUTE, cmd, sizeof(cmd))))
137
proc = (char*)aproc;
138
else if (p)
139
{
140
n = strlen(proc);
141
strncopy(proc + n, p, PATH_MAX - n - 1);
142
}
143
}
144
if (!path)
145
{
146
path = buf;
147
pathsize = sizeof(buf);
148
}
149
probe = PROBE;
150
x = lib + sizeof(lib) - 1;
151
k = lib + sfsprintf(lib, x - lib, "lib/%s/", probe);
152
p = k + sfsprintf(k, x - k, "%s/%s/", lang, tool);
153
pathkey(lang, tool, proc, key, sizeof(key), attr, attrsize);
154
if (op >= -2)
155
{
156
strncopy(p, key, x - p);
157
if (pathpath(lib, "", PATH_ABSOLUTE, path, pathsize) && !stat(path, &st) && (st.st_mode & S_IWUSR))
158
return path == buf ? strdup(path) : path;
159
}
160
e = strncopy(p, probe, x - p);
161
if (!pathpath(lib, "", PATH_ABSOLUTE|PATH_EXECUTE, path, pathsize) || stat(path, &ps))
162
return 0;
163
for (;;)
164
{
165
ptime = ps.st_mtime;
166
n = strlen(path);
167
if (n < (PATH_MAX - 5))
168
{
169
strcpy(path + n, ".ini");
170
if (!stat(path, &st) && st.st_size && ptime < (unsigned long)st.st_mtime)
171
ptime = st.st_mtime;
172
path[n] = 0;
173
}
174
np = path + n - (e - k);
175
nx = path + PATH_MAX - 1;
176
strncopy(np, probe, nx - np);
177
if (!stat(path, &st))
178
break;
179
180
/*
181
* yes lib/probe/<lang>/<proc>/probe
182
* no lib/probe/probe
183
*
184
* do a manual pathaccess() to find a dir with both
185
*/
186
187
sfsprintf(exe, sizeof(exe), "lib/%s/%s", probe, probe);
188
dirs = pathbin();
189
for (;;)
190
{
191
if (!(dir = dirs))
192
return 0;
193
dirs = pathcat(dir, ':', "..", exe, path, pathsize);
194
pathcanon(path, pathsize, 0);
195
if (*path == '/' && pathexists(path, PATH_REGULAR|PATH_EXECUTE))
196
{
197
pathcat(dir, ':', "..", lib, path, pathsize);
198
pathcanon(path, pathsize, 0);
199
if (*path == '/' && pathexists(path, PATH_REGULAR|PATH_EXECUTE) && !stat(path, &ps))
200
break;
201
}
202
}
203
}
204
strncopy(p, key, x - p);
205
p = np;
206
x = nx;
207
strcpy(exe, path);
208
if (op >= -1 && (!(st.st_mode & S_ISUID) && ps.st_uid != geteuid() || rofs(path)))
209
{
210
if (!(p = getenv("HOME")))
211
return 0;
212
p = path + sfsprintf(path, PATH_MAX - 1, "%s/.%s/%s/", p, probe, HOSTTYPE);
213
}
214
strncopy(p, k, x - p);
215
force = 0;
216
if (op >= 0 && !stat(path, &st))
217
{
218
if (ptime <= (unsigned long)st.st_mtime || ptime <= (unsigned long)st.st_ctime)
219
{
220
/*
221
* verify (<sep><name><sep><option><sep><value>)* header
222
*/
223
224
if (sp = sfopen(NiL, path, "r"))
225
{
226
if (x = sfgetr(sp, '\n', 1))
227
{
228
while (*x && *x != ' ')
229
x++;
230
while (*x == ' ')
231
x++;
232
if (n = *x++)
233
for (;;)
234
{
235
for (k = x; *x && *x != n; x++);
236
if (!*x)
237
break;
238
*x++ = 0;
239
for (p = x; *x && *x != n; x++);
240
if (!*x)
241
break;
242
*x++ = 0;
243
for (e = x; *x && *x != n; x++);
244
if (!*x)
245
break;
246
*x++ = 0;
247
if (streq(k, "VERSION"))
248
{
249
ap = arg;
250
*ap++ = proc;
251
*ap++ = p;
252
*ap = 0;
253
ops[0] = PROC_FD_DUP(1, 2, 0);
254
ops[1] = 0;
255
if (pp = procopen(proc, arg, NiL, ops, PROC_READ))
256
{
257
if ((v = x - e) >= sizeof(ver))
258
v = sizeof(ver) - 1;
259
k = p = ver;
260
for (;;)
261
{
262
if (k >= p)
263
{
264
if (v <= 0)
265
break;
266
if ((r = read(pp->rfd, k, v)) < 0)
267
{
268
if (errno == EINTR)
269
continue;
270
break;
271
}
272
if (r <= 0)
273
break;
274
v -= r;
275
p = k + r;
276
}
277
if (*k == '\n' || *k == '\r')
278
break;
279
if (*k == n)
280
*k = ' ';
281
k++;
282
}
283
*k = 0;
284
if (strcmp(ver, e))
285
{
286
force = 1;
287
error(0, "probe processor %s version \"%s\" changed -- expected \"%s\"", proc, ver, e);
288
}
289
procclose(pp);
290
}
291
break;
292
}
293
}
294
}
295
sfclose(sp);
296
}
297
if (!force)
298
op = -1;
299
}
300
if (op >= 0 && (st.st_mode & S_IWUSR))
301
{
302
if (op == 0)
303
error(0, "%s probe information for %s language processor %s must be manually regenerated", tool, lang, proc);
304
op = -1;
305
force = 0;
306
}
307
}
308
if (op >= 0)
309
{
310
ap = arg;
311
*ap++ = exe;
312
if (force)
313
*ap++ = "-f";
314
if (op > 0)
315
*ap++ = "-s";
316
*ap++ = (char*)lang;
317
*ap++ = (char*)tool;
318
*ap++ = proc;
319
*ap = 0;
320
if (procrun(exe, arg, 0))
321
return 0;
322
if (eaccess(path, R_OK))
323
return 0;
324
}
325
return path == buf ? strdup(path) : path;
326
}
327
328