char *pathpath(register char *path, const char *p, const char *a, int mode) { register char *s; char *x; char buf[PATH_MAX]; static char *cmd; if (!path) path = buf; if (!p) { if (cmd) free(cmd); cmd = a ? strdup(a) : (char *) 0; return 0; } if (strlen(p) < PATH_MAX) { strcpy(path, p); if (pathexists(path, mode)) return (path == buf) ? strdup(path) : path; } if (*p == '/') a = 0; else if ((s = (char *) a)) { x = s; if (strchr(p, '/')) { a = p; p = ".."; } else a = 0; if ((!cmd || *cmd) && (strchr(s, '/') || (((s = cmd) || (opt_info_argv && (s = *opt_info_argv))) && strchr(s, '/') && !strchr(s, '\n') && !access(s, F_OK)) || (environ && (s = *environ) && *s++ == '_' && *s++ == '=' && strchr(s, '/') && !strneq(s, "/bin/", 5) && !strneq(s, "/usr/bin/", 9)) || (*x && !access(x, F_OK) && (s = getenv("PWD")) && *s == '/') ) ) { if (!cmd) cmd = strdup(s); if (strlen(s) < (sizeof(buf) - 6)) { s = strcopy(path, s); for (;;) { do if (s <= path) goto normal; while (*--s == '/'); do if (s <= path) goto normal; while (*--s != '/'); strcpy(s + 1, "bin"); if (pathexists(path, PATH_EXECUTE)) { if ((s = pathaccess(path, path, p, a, mode))) return path == buf ? strdup(s) : s; goto normal; } } normal:; } } } x = !a && strchr(p, '/') ? "" : pathbin(); if (!(s = pathaccess(path, x, p, a, mode)) && !*x && (x = getenv("FPATH"))) s = pathaccess(path, x, p, a, mode); return (s && path == buf) ? strdup(s) : s; }
char* pathpath_20100601(const char* p, const char* a, int mode, register char* path, size_t size) { register char* s; char* x; char buf[PATH_MAX]; static char* cmd; if (!path) path = buf; if (!p) { if (cmd) free(cmd); cmd = a ? strdup(a) : (char*)0; return 0; } if (strlen(p) < size) { strcpy(path, p); if (pathexists(path, mode)) { if (*p != '/' && (mode & PATH_ABSOLUTE)) { getcwd(buf, sizeof(buf)); s = buf + strlen(buf); sfsprintf(s, sizeof(buf) - (s - buf), "/%s", p); if (path != buf) strcpy(path, buf); } return (path == buf) ? strdup(path) : path; } } if (*p == '/') a = 0; else if (s = (char*)a) { x = s; if (strchr(p, '/')) { a = p; p = ".."; } else a = 0; if ((!cmd || *cmd) && (strchr(s, '/') || (s = cmd))) { if (!cmd && *s == '/') cmd = strdup(s); if (strlen(s) < (sizeof(buf) - 6)) { s = strcopy(path, s); for (;;) { do if (s <= path) goto normal; while (*--s == '/'); do if (s <= path) goto normal; while (*--s != '/'); strcpy(s + 1, "bin"); if (pathexists(path, PATH_EXECUTE)) { if (s = pathaccess(path, p, a, mode, path, size)) return path == buf ? strdup(s) : s; goto normal; } } normal: ; } } } x = !a && strchr(p, '/') ? "" : pathbin(); if (!(s = pathaccess(x, p, a, mode, path, size)) && !*x && (x = getenv("FPATH"))) s = pathaccess(x, p, a, mode, path, size); return (s && path == buf) ? strdup(s) : s; }
char* pathprobe_20100601(const char* lang, const char* tool, const char* aproc, int op, char* path, size_t pathsize, char* attr, size_t attrsize) { char* proc = (char*)aproc; register char* p; register char* k; register char* x; register char** ap; int n; int v; int force; ssize_t r; char* e; char* np; char* nx; char* probe; const char* dirs; const char* dir; Proc_t* pp; Sfio_t* sp; char buf[PATH_MAX]; char cmd[PATH_MAX]; char exe[PATH_MAX]; char lib[PATH_MAX]; char ver[PATH_MAX]; char key[16]; char* arg[8]; long ops[2]; unsigned long ptime; struct stat st; struct stat ps; if (*proc != '/') { if (p = strchr(proc, ' ')) { strncopy(buf, proc, p - proc + 1); proc = buf; } if (!(proc = pathpath(proc, NiL, PATH_ABSOLUTE|PATH_REGULAR|PATH_EXECUTE, cmd, sizeof(cmd)))) proc = (char*)aproc; else if (p) { n = strlen(proc); strncopy(proc + n, p, PATH_MAX - n - 1); } } if (!path) { path = buf; pathsize = sizeof(buf); } probe = PROBE; x = lib + sizeof(lib) - 1; k = lib + sfsprintf(lib, x - lib, "lib/%s/", probe); p = k + sfsprintf(k, x - k, "%s/%s/", lang, tool); pathkey(lang, tool, proc, key, sizeof(key), attr, attrsize); if (op >= -2) { strncopy(p, key, x - p); if (pathpath(lib, "", PATH_ABSOLUTE, path, pathsize) && !stat(path, &st) && (st.st_mode & S_IWUSR)) return path == buf ? strdup(path) : path; } e = strncopy(p, probe, x - p); if (!pathpath(lib, "", PATH_ABSOLUTE|PATH_EXECUTE, path, pathsize) || stat(path, &ps)) return 0; for (;;) { ptime = ps.st_mtime; n = strlen(path); if (n < (PATH_MAX - 5)) { strcpy(path + n, ".ini"); if (!stat(path, &st) && st.st_size && ptime < (unsigned long)st.st_mtime) ptime = st.st_mtime; path[n] = 0; } np = path + n - (e - k); nx = path + PATH_MAX - 1; strncopy(np, probe, nx - np); if (!stat(path, &st)) break; /* * yes lib/probe/<lang>/<proc>/probe * no lib/probe/probe * * do a manual pathaccess() to find a dir with both */ sfsprintf(exe, sizeof(exe), "lib/%s/%s", probe, probe); dirs = pathbin(); for (;;) { if (!(dir = dirs)) return 0; dirs = pathcat(dir, ':', "..", exe, path, pathsize); pathcanon(path, pathsize, 0); if (*path == '/' && pathexists(path, PATH_REGULAR|PATH_EXECUTE)) { pathcat(dir, ':', "..", lib, path, pathsize); pathcanon(path, pathsize, 0); if (*path == '/' && pathexists(path, PATH_REGULAR|PATH_EXECUTE) && !stat(path, &ps)) break; } } } strncopy(p, key, x - p); p = np; x = nx; strcpy(exe, path); if (op >= -1 && (!(st.st_mode & S_ISUID) && ps.st_uid != geteuid() || rofs(path))) { if (!(p = getenv("HOME"))) return 0; p = path + sfsprintf(path, PATH_MAX - 1, "%s/.%s/%s/", p, probe, HOSTTYPE); } strncopy(p, k, x - p); force = 0; if (op >= 0 && !stat(path, &st)) { if (ptime <= (unsigned long)st.st_mtime || ptime <= (unsigned long)st.st_ctime) { /* * verify (<sep><name><sep><option><sep><value>)* header */ if (sp = sfopen(NiL, path, "r")) { if (x = sfgetr(sp, '\n', 1)) { while (*x && *x != ' ') x++; while (*x == ' ') x++; if (n = *x++) for (;;) { for (k = x; *x && *x != n; x++); if (!*x) break; *x++ = 0; for (p = x; *x && *x != n; x++); if (!*x) break; *x++ = 0; for (e = x; *x && *x != n; x++); if (!*x) break; *x++ = 0; if (streq(k, "VERSION")) { ap = arg; *ap++ = proc; *ap++ = p; *ap = 0; ops[0] = PROC_FD_DUP(1, 2, 0); ops[1] = 0; if (pp = procopen(proc, arg, NiL, ops, PROC_READ)) { if ((v = x - e) >= sizeof(ver)) v = sizeof(ver) - 1; for (k = p = ver;; k++) { if (k >= p) { if (v <= 0 || (r = read(pp->rfd, k, v)) <= 0) break; v -= r; p = k + r; } if (*k == '\n' || *k == '\r') break; if (*k == n) *k = ' '; } *k = 0; if (strcmp(ver, e)) { force = 1; error(0, "probe processor %s version \"%s\" changed -- expected \"%s\"", proc, ver, e); } procclose(pp); } break; } } } sfclose(sp); } if (!force) op = -1; } if (op >= 0 && (st.st_mode & S_IWUSR)) { if (op == 0) error(0, "%s probe information for %s language processor %s must be manually regenerated", tool, lang, proc); op = -1; force = 0; } } if (op >= 0) { ap = arg; *ap++ = exe; if (force) *ap++ = "-f"; if (op > 0) *ap++ = "-s"; *ap++ = (char*)lang; *ap++ = (char*)tool; *ap++ = proc; *ap = 0; if (procrun(exe, arg, 0)) return 0; if (eaccess(path, R_OK)) return 0; } return path == buf ? strdup(path) : path; }