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