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