1 /*********************************************************************** 2 * * 3 * This software is part of the ast package * 4 * Copyright (c) 1985-2010 AT&T Intellectual Property * 5 * and is licensed under the * 6 * Common Public License, Version 1.0 * 7 * by AT&T Intellectual Property * 8 * * 9 * A copy of the License is available at * 10 * http://www.opensource.org/licenses/cpl1.0.txt * 11 * (with md5 checksum 059e8cd6165cb4c31e351f2b69388fd9) * 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 #include <ast.h> 45 #include <error.h> 46 #include <ls.h> 47 #include <proc.h> 48 49 #ifndef PROBE 50 #define PROBE "probe" 51 #endif 52 53 #if defined(ST_RDONLY) || defined(ST_NOSUID) 54 55 /* 56 * return non-0 if path is in a readonly or non-setuid fs 57 */ 58 59 static int 60 rofs(const char* path) 61 { 62 struct statvfs vfs; 63 struct stat st; 64 65 if (!statvfs(path, &vfs)) 66 { 67 #if defined(ST_RDONLY) 68 if (vfs.f_flag & ST_RDONLY) 69 return 1; 70 #endif 71 #if defined(ST_NOSUID) 72 if ((vfs.f_flag & ST_NOSUID) && (stat(path, &st) || st.st_uid != getuid() && st.st_uid != geteuid())) 73 return 1; 74 #endif 75 } 76 return 0; 77 } 78 79 #else 80 81 #define rofs(p) 0 82 83 #endif 84 85 char* 86 pathprobe(char* path, char* attr, const char* lang, const char* tool, const char* aproc, int op) 87 { 88 char* proc = (char*)aproc; 89 register char* p; 90 register char* k; 91 register char* x; 92 register char** ap; 93 int n; 94 int v; 95 int force; 96 ssize_t r; 97 char* e; 98 char* np; 99 char* nx; 100 char* probe; 101 const char* dirs; 102 const char* dir; 103 Proc_t* pp; 104 Sfio_t* sp; 105 char buf[PATH_MAX]; 106 char cmd[PATH_MAX]; 107 char exe[PATH_MAX]; 108 char lib[PATH_MAX]; 109 char ver[PATH_MAX]; 110 char key[16]; 111 char* arg[8]; 112 long ops[2]; 113 unsigned long ptime; 114 struct stat st; 115 struct stat ps; 116 117 if (*proc != '/') 118 { 119 if (p = strchr(proc, ' ')) 120 { 121 strncopy(buf, proc, p - proc + 1); 122 proc = buf; 123 } 124 if (!(proc = pathpath(cmd, proc, NiL, PATH_ABSOLUTE|PATH_REGULAR|PATH_EXECUTE))) 125 proc = (char*)aproc; 126 else if (p) 127 { 128 n = strlen(proc); 129 strncopy(proc + n, p, PATH_MAX - n - 1); 130 } 131 } 132 if (!path) 133 path = buf; 134 probe = PROBE; 135 x = lib + sizeof(lib) - 1; 136 k = lib + sfsprintf(lib, x - lib, "lib/%s/", probe); 137 p = k + sfsprintf(k, x - k, "%s/%s/", lang, tool); 138 pathkey(key, attr, lang, tool, proc); 139 if (op >= -2) 140 { 141 strncopy(p, key, x - p); 142 if (pathpath(path, lib, "", PATH_ABSOLUTE) && !stat(path, &st) && (st.st_mode & S_IWUSR)) 143 return path == buf ? strdup(path) : path; 144 } 145 e = strncopy(p, probe, x - p); 146 if (!pathpath(path, lib, "", PATH_ABSOLUTE|PATH_EXECUTE) || stat(path, &ps)) 147 return 0; 148 for (;;) 149 { 150 ptime = ps.st_mtime; 151 n = strlen(path); 152 if (n < (PATH_MAX - 5)) 153 { 154 strcpy(path + n, ".ini"); 155 if (!stat(path, &st) && st.st_size && ptime < (unsigned long)st.st_mtime) 156 ptime = st.st_mtime; 157 path[n] = 0; 158 } 159 np = path + n - (e - k); 160 nx = path + PATH_MAX - 1; 161 strncopy(np, probe, nx - np); 162 if (!stat(path, &st)) 163 break; 164 165 /* 166 * yes lib/probe/<lang>/<proc>/probe 167 * no lib/probe/probe 168 * 169 * do a manual pathaccess() to find a dir with both 170 */ 171 172 sfsprintf(exe, sizeof(exe), "lib/%s/%s", probe, probe); 173 dirs = pathbin(); 174 for (;;) 175 { 176 if (!(dir = dirs)) 177 return 0; 178 dirs = pathcat(path, dir, ':', "..", exe); 179 pathcanon(path, 0); 180 if (*path == '/' && pathexists(path, PATH_REGULAR|PATH_EXECUTE)) 181 { 182 pathcat(path, dir, ':', "..", lib); 183 pathcanon(path, 0); 184 if (*path == '/' && pathexists(path, PATH_REGULAR|PATH_EXECUTE) && !stat(path, &ps)) 185 break; 186 } 187 } 188 } 189 strncopy(p, key, x - p); 190 p = np; 191 x = nx; 192 strcpy(exe, path); 193 if (op >= -1 && (!(st.st_mode & S_ISUID) && ps.st_uid != geteuid() || rofs(path))) 194 { 195 if (!(p = getenv("HOME"))) 196 return 0; 197 p = path + sfsprintf(path, PATH_MAX - 1, "%s/.%s/%s/", p, probe, HOSTTYPE); 198 } 199 strncopy(p, k, x - p); 200 force = 0; 201 if (op >= 0 && !stat(path, &st)) 202 { 203 if (ptime <= (unsigned long)st.st_mtime || ptime <= (unsigned long)st.st_ctime) 204 { 205 /* 206 * verify (<sep><name><sep><option><sep><value>)* header 207 */ 208 209 if (sp = sfopen(NiL, path, "r")) 210 { 211 if (x = sfgetr(sp, '\n', 1)) 212 { 213 while (*x && *x != ' ') 214 x++; 215 while (*x == ' ') 216 x++; 217 if (n = *x++) 218 for (;;) 219 { 220 for (k = x; *x && *x != n; x++); 221 if (!*x) 222 break; 223 *x++ = 0; 224 for (p = x; *x && *x != n; x++); 225 if (!*x) 226 break; 227 *x++ = 0; 228 for (e = x; *x && *x != n; x++); 229 if (!*x) 230 break; 231 *x++ = 0; 232 if (streq(k, "VERSION")) 233 { 234 ap = arg; 235 *ap++ = proc; 236 *ap++ = p; 237 *ap = 0; 238 ops[0] = PROC_FD_DUP(1, 2, 0); 239 ops[1] = 0; 240 if (pp = procopen(proc, arg, NiL, ops, PROC_READ)) 241 { 242 if ((v = x - e) >= sizeof(ver)) 243 v = sizeof(ver) - 1; 244 for (k = p = ver;; k++) 245 { 246 if (k >= p) 247 { 248 if (v <= 0 || (r = read(pp->rfd, k, v)) <= 0) 249 break; 250 v -= r; 251 p = k + r; 252 } 253 if (*k == '\n' || *k == '\r') 254 break; 255 if (*k == n) 256 *k = ' '; 257 } 258 *k = 0; 259 if (strcmp(ver, e)) 260 { 261 force = 1; 262 error(0, "probe processor %s version \"%s\" changed -- expected \"%s\"", proc, ver, e); 263 } 264 procclose(pp); 265 } 266 break; 267 } 268 } 269 } 270 sfclose(sp); 271 } 272 if (!force) 273 op = -1; 274 } 275 if (op >= 0 && (st.st_mode & S_IWUSR)) 276 { 277 if (op == 0) 278 error(0, "%s probe information for %s language processor %s must be manually regenerated", tool, lang, proc); 279 op = -1; 280 force = 0; 281 } 282 } 283 if (op >= 0) 284 { 285 ap = arg; 286 *ap++ = exe; 287 if (force) 288 *ap++ = "-f"; 289 if (op > 0) 290 *ap++ = "-s"; 291 *ap++ = (char*)lang; 292 *ap++ = (char*)tool; 293 *ap++ = proc; 294 *ap = 0; 295 if (procrun(exe, arg, 0)) 296 return 0; 297 if (eaccess(path, R_OK)) 298 return 0; 299 } 300 return path == buf ? strdup(path) : path; 301 } 302