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