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 <gsf@research.att.com> * 18 * David Korn <dgk@research.att.com> * 19 * Phong Vo <kpv@research.att.com> * 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