diff options
author | Igor Pashev <pashev.igor@gmail.com> | 2012-06-24 22:28:35 +0000 |
---|---|---|
committer | Igor Pashev <pashev.igor@gmail.com> | 2012-06-24 22:28:35 +0000 |
commit | 3950ffe2a485479f6561c27364d3d7df5a21d124 (patch) | |
tree | 468c6e14449d1b1e279222ec32f676b0311917d2 /src/lib/libast/path/pathprobe.c | |
download | ksh-upstream.tar.gz |
Imported Upstream version 93u+upstream
Diffstat (limited to 'src/lib/libast/path/pathprobe.c')
-rw-r--r-- | src/lib/libast/path/pathprobe.c | 316 |
1 files changed, 316 insertions, 0 deletions
diff --git a/src/lib/libast/path/pathprobe.c b/src/lib/libast/path/pathprobe.c new file mode 100644 index 0000000..26d1fe3 --- /dev/null +++ b/src/lib/libast/path/pathprobe.c @@ -0,0 +1,316 @@ +/*********************************************************************** +* * +* This software is part of the ast package * +* Copyright (c) 1985-2011 AT&T Intellectual Property * +* and is licensed under the * +* Eclipse Public License, Version 1.0 * +* by AT&T Intellectual Property * +* * +* A copy of the License is available at * +* http://www.eclipse.org/org/documents/epl-v10.html * +* (with md5 checksum b35adb5213ca9657e911e9befb180842) * +* * +* Information and Software Systems Research * +* AT&T Research * +* Florham Park NJ * +* * +* Glenn Fowler <gsf@research.att.com> * +* David Korn <dgk@research.att.com> * +* Phong Vo <kpv@research.att.com> * +* * +***********************************************************************/ +#pragma prototyped +/* + * Glenn Fowler + * AT&T Research + * + * return in path the full path name of the probe(1) + * information for lang and tool using proc + * if attr != 0 then path attribute assignments placed here + * + * if path==0 then the space is malloc'd + * + * op: + * + * -3 return non-writable path name with no generation + * -2 return path name with no generation + * -1 return no $HOME path name with no generation + * 0 verbose probe + * 1 silent probe + * + * 0 returned if the info does not exist and cannot be generated + */ + +#define _AST_API_H 1 + +#include <ast.h> +#include <error.h> +#include <ls.h> +#include <proc.h> + +char* +pathprobe(char* path, char* attr, const char* lang, const char* tool, const char* proc, int op) +{ + return pathprobe_20100601(lang, tool, proc, op, path, PATH_MAX, attr, PATH_MAX); +} + +#undef _AST_API_H + +#include <ast_api.h> + +#ifndef PROBE +#define PROBE "probe" +#endif + +#if defined(ST_RDONLY) || defined(ST_NOSUID) + +/* + * return non-0 if path is in a readonly or non-setuid fs + */ + +static int +rofs(const char* path) +{ + struct statvfs vfs; + struct stat st; + + if (!statvfs(path, &vfs)) + { +#if defined(ST_RDONLY) + if (vfs.f_flag & ST_RDONLY) + return 1; +#endif +#if defined(ST_NOSUID) + if ((vfs.f_flag & ST_NOSUID) && (stat(path, &st) || st.st_uid != getuid() && st.st_uid != geteuid())) + return 1; +#endif + } + return 0; +} + +#else + +#define rofs(p) 0 + +#endif + +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; +} |