diff options
Diffstat (limited to 'src/lib/libast/path')
-rw-r--r-- | src/lib/libast/path/pathaccess.c | 69 | ||||
-rw-r--r-- | src/lib/libast/path/pathbin.c | 46 | ||||
-rw-r--r-- | src/lib/libast/path/pathcanon.c | 222 | ||||
-rw-r--r-- | src/lib/libast/path/pathcat.c | 98 | ||||
-rw-r--r-- | src/lib/libast/path/pathcd.c | 142 | ||||
-rw-r--r-- | src/lib/libast/path/pathcheck.c | 91 | ||||
-rw-r--r-- | src/lib/libast/path/pathexists.c | 134 | ||||
-rw-r--r-- | src/lib/libast/path/pathfind.c | 168 | ||||
-rw-r--r-- | src/lib/libast/path/pathgetlink.c | 102 | ||||
-rw-r--r-- | src/lib/libast/path/pathkey.c | 320 | ||||
-rw-r--r-- | src/lib/libast/path/pathnative.c | 126 | ||||
-rw-r--r-- | src/lib/libast/path/pathpath.c | 127 | ||||
-rw-r--r-- | src/lib/libast/path/pathposix.c | 128 | ||||
-rw-r--r-- | src/lib/libast/path/pathprobe.c | 316 | ||||
-rw-r--r-- | src/lib/libast/path/pathprog.c | 128 | ||||
-rw-r--r-- | src/lib/libast/path/pathrepl.c | 93 | ||||
-rw-r--r-- | src/lib/libast/path/pathsetlink.c | 72 | ||||
-rw-r--r-- | src/lib/libast/path/pathshell.c | 112 | ||||
-rw-r--r-- | src/lib/libast/path/pathstat.c | 45 | ||||
-rw-r--r-- | src/lib/libast/path/pathtemp.c | 337 | ||||
-rw-r--r-- | src/lib/libast/path/pathtmp.c | 41 |
21 files changed, 2917 insertions, 0 deletions
diff --git a/src/lib/libast/path/pathaccess.c b/src/lib/libast/path/pathaccess.c new file mode 100644 index 0000000..7bbec12 --- /dev/null +++ b/src/lib/libast/path/pathaccess.c @@ -0,0 +1,69 @@ +/*********************************************************************** +* * +* 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 Bell Laboratories + * + * return path to file a/b with access mode using : separated dirs + * both a and b may be 0 + * if a==".." then relative paths in dirs are ignored + * if (mode&PATH_REGULAR) then path must not be a directory + * if (mode&PATH_ABSOLUTE) then path must be rooted + * path returned in path buffer + */ + +#define _AST_API_H 1 + +#include <ast.h> + +char* +pathaccess(char* path, const char* dirs, const char* a, const char* b, int mode) +{ + return pathaccess_20100601(dirs, a, b, mode, path, PATH_MAX); +} + +#undef _AST_API_H + +#include <ast_api.h> + +char* +pathaccess_20100601(register const char* dirs, const char* a, const char* b, register int mode, register char* path, size_t size) +{ + int sib = a && a[0] == '.' && a[1] == '.' && a[2] == 0; + int sep = ':'; + char cwd[PATH_MAX]; + + do + { + dirs = pathcat(dirs, sep, a, b, path, size); + pathcanon(path, size, 0); + if ((!sib || *path == '/') && pathexists(path, mode)) + { + if (*path == '/' || !(mode & PATH_ABSOLUTE)) + return path; + dirs = getcwd(cwd, sizeof(cwd)); + sep = 0; + } + } while (dirs); + return 0; +} diff --git a/src/lib/libast/path/pathbin.c b/src/lib/libast/path/pathbin.c new file mode 100644 index 0000000..cc9cdfa --- /dev/null +++ b/src/lib/libast/path/pathbin.c @@ -0,0 +1,46 @@ +/*********************************************************************** +* * +* 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 Bell Laboratories + * + * return current PATH + */ + +#include <ast.h> + +char* +pathbin(void) +{ + register char* bin; + + static char* val; + + if ((!(bin = getenv("PATH")) || !*bin) && !(bin = val)) + { + if (!*(bin = astconf("PATH", NiL, NiL)) || !(bin = strdup(bin))) + bin = "/bin:/usr/bin:/usr/local/bin"; + val = bin; + } + return bin; +} diff --git a/src/lib/libast/path/pathcanon.c b/src/lib/libast/path/pathcanon.c new file mode 100644 index 0000000..8d3cfa6 --- /dev/null +++ b/src/lib/libast/path/pathcanon.c @@ -0,0 +1,222 @@ +/*********************************************************************** +* * +* 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 + * + * in-place path name canonicalization -- preserves the logical view + * pointer to trailing 0 in path returned + * + * remove redundant .'s and /'s + * move ..'s to the front + * /.. preserved (for pdu and newcastle hacks) + * FS_3D handles ... + * if (flags&PATH_PHYSICAL) then symlinks resolved at each component + * if (flags&PATH_DOTDOT) then each .. checked for access + * if (flags&PATH_EXISTS) then path must exist at each component + * if (flags&PATH_VERIFIED(n)) then first n chars of path exist + * + * longer pathname possible if (flags&PATH_PHYSICAL) or FS_3D ... involved + * 0 returned on error and if (flags&(PATH_DOTDOT|PATH_EXISTS)) then path + * will contain the components following the failure point + */ + +#define _AST_API_H 1 + +#include <ast.h> +#include <ls.h> +#include <fs3d.h> +#include <error.h> + +char* +pathcanon(char* path, int flags) +{ + return pathcanon_20100601(path, PATH_MAX, flags); +} + +#undef _AST_API_H + +#include <ast_api.h> + +char* +pathcanon_20100601(char* path, size_t size, int flags) +{ + register char* p; + register char* r; + register char* s; + register char* t; + register int dots; + char* phys; + char* v; + int loop; + int oerrno; +#if defined(FS_3D) + long visits = 0; +#endif + + oerrno = errno; + dots = loop = 0; + phys = path; + v = path + ((flags >> 5) & 01777); + if (!size) + size = strlen(path) + 1; + if (*path == '/') + { + if (*(path + 1) == '/' && *astconf("PATH_LEADING_SLASHES", NiL, NiL) == '1') + do path++; while (*path == '/' && *(path + 1) == '/'); + if (!*(path + 1)) + return path + 1; + } + p = r = s = t = path; + for (;;) + switch (*t++ = *s++) + { + case '.': + dots++; + break; + case 0: + s--; + /*FALLTHROUGH*/ + case '/': + while (*s == '/') s++; + switch (dots) + { + case 1: + t -= 2; + break; + case 2: + if ((flags & (PATH_DOTDOT|PATH_EXISTS)) == PATH_DOTDOT && (t - 2) >= v) + { + struct stat st; + + *(t - 2) = 0; + if (stat(phys, &st)) + { + strcpy(path, s); + return 0; + } + *(t - 2) = '.'; + } +#if PRESERVE_TRAILING_SLASH + if (t - 5 < r) r = t; +#else + if (t - 5 < r) + { + if (t - 4 == r) t = r + 1; + else r = t; + } +#endif + else for (t -= 5; t > r && *(t - 1) != '/'; t--); + break; + case 3: +#if defined(FS_3D) + { + char* x; + char* o; + int c; + + o = t; + if ((t -= 5) <= path) t = path + 1; + c = *t; + *t = 0; + if (x = pathnext(phys, s - (*s != 0), &visits)) + { + r = path; + if (t == r + 1) x = r; + v = s = t = x; + } + else + { + *t = c; + t = o; + } + } +#else + r = t; +#endif + break; + default: + if ((flags & PATH_PHYSICAL) && loop < 32 && (t - 1) > path) + { + int c; + char buf[PATH_MAX]; + + c = *(t - 1); + *(t - 1) = 0; + dots = pathgetlink(phys, buf, sizeof(buf)); + *(t - 1) = c; + if (dots > 0) + { + loop++; + strcpy(buf + dots, s - (*s != 0)); + if (*buf == '/') p = r = path; + v = s = t = p; + strcpy(p, buf); + } + else if (dots < 0 && errno == ENOENT) + { + if (flags & PATH_EXISTS) + { + strcpy(path, s); + return 0; + } + flags &= ~(PATH_PHYSICAL|PATH_DOTDOT); + } + dots = 4; + } + break; + } + if (dots >= 4 && (flags & PATH_EXISTS) && (t - 1) >= v && (t > path + 1 || t > path && *(t - 1) && *(t - 1) != '/')) + { + struct stat st; + + *(t - 1) = 0; + if (stat(phys, &st)) + { + strcpy(path, s); + return 0; + } + v = t; + if (*s) *(t - 1) = '/'; + } + if (!*s) + { + if (t > path && !*(t - 1)) t--; + if (t == path) *t++ = '.'; +#if DONT_PRESERVE_TRAILING_SLASH + else if (t > path + 1 && *(t - 1) == '/') t--; +#else + else if ((s <= path || *(s - 1) != '/') && t > path + 1 && *(t - 1) == '/') t--; +#endif + *t = 0; + errno = oerrno; + return t; + } + dots = 0; + p = t; + break; + default: + dots = 4; + break; + } +} diff --git a/src/lib/libast/path/pathcat.c b/src/lib/libast/path/pathcat.c new file mode 100644 index 0000000..2fa9cde --- /dev/null +++ b/src/lib/libast/path/pathcat.c @@ -0,0 +1,98 @@ +/*********************************************************************** +* * +* 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 Bell Laboratories + * + * single dir support for pathaccess() + */ + +#define _AST_API_H 1 + +#include <ast.h> + +/* + * building 3d flirts with the dark side + */ + +#if _BLD_3d + +#undef pathcat +#define pathcat_20100601 _3d_pathcat + +#else + +char* +pathcat(char* path, const char* dirs, int sep, const char* a, const char* b) +{ + return pathcat_20100601(dirs, sep, a, b, path, PATH_MAX); +} + +#endif + +#undef _AST_API + +#include <ast_api.h> + +char* +pathcat_20100601(register const char* dirs, int sep, const char* a, register const char* b, char* path, size_t size) +{ + register char* s; + register char* e; + + s = path; + e = path + size; + while (*dirs && *dirs != sep) + { + if (s >= e) + return 0; + *s++ = *dirs++; + } + if (s != path) + { + if (s >= e) + return 0; + *s++ = '/'; + } + if (a) + { + while (*s = *a++) + if (++s >= e) + return 0; + if (b) + { + if (s >= e) + return 0; + *s++ = '/'; + } + } + else if (!b) + b = "."; + if (b) + do + { + if (s >= e) + return 0; + } while (*s++ = *b++); + return *dirs ? (char*)++dirs : 0; +} diff --git a/src/lib/libast/path/pathcd.c b/src/lib/libast/path/pathcd.c new file mode 100644 index 0000000..340a115 --- /dev/null +++ b/src/lib/libast/path/pathcd.c @@ -0,0 +1,142 @@ +/*********************************************************************** +* * +* 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 +/* + * K. P. Vo + * G. S. Fowler + * AT&T Research + */ + +#include <ast.h> +#include <error.h> +#include <stk.h> + +#if DEBUG + +#undef PATH_MAX + +#define PATH_MAX 16 + +static int +vchdir(const char* path) +{ + int n; + + if (strlen(path) >= PATH_MAX) + { + errno = ENAMETOOLONG; + n = -1; + } + else n = chdir(path); + return n; +} + +#define chdir(p) vchdir(p) + +#endif + +/* + * set the current directory to path + * if path is long and home!=0 then pathcd(home,0) + * is called on intermediate chdir errors + */ + +int +pathcd(const char* path, const char* home) +{ + register char* p = (char*)path; + register char* s; + register int n; + int i; + int r; + + r = 0; + for (;;) + { + /* + * this should work 99% of the time + */ + + if (!chdir(p)) + return r; + + /* + * chdir failed + */ + + if ((n = strlen(p)) < PATH_MAX) + return -1; +#ifdef ENAMETOOLONG + if (errno != ENAMETOOLONG) + return -1; +#endif + + /* + * path is too long -- copy so it can be modified in place + */ + + i = stktell(stkstd); + sfputr(stkstd, p, 0); + stkseek(stkstd, i); + p = stkptr(stkstd, i); + for (;;) + { + /* + * get a short prefix component + */ + + s = p + PATH_MAX; + while (--s >= p && *s != '/'); + if (s <= p) + break; + + /* + * chdir to the prefix + */ + + *s++ = 0; + if (chdir(p)) + break; + + /* + * do the remainder + */ + + if ((n -= s - p) < PATH_MAX) + { + if (chdir(s)) + break; + return r; + } + p = s; + } + + /* + * try to recover back to home + */ + + if (!(p = (char*)home)) + return -1; + home = 0; + r = -1; + } +} diff --git a/src/lib/libast/path/pathcheck.c b/src/lib/libast/path/pathcheck.c new file mode 100644 index 0000000..4ff79f6 --- /dev/null +++ b/src/lib/libast/path/pathcheck.c @@ -0,0 +1,91 @@ +/*********************************************************************** +* * +* 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 + +/* + * check if package+tool is ok to run + * a no-op here except for PARANOID packages + * this allows PARANOID_COMPANY to post PARANOID binaries to the www + * + * warn that the user should pay up if + * + * (1) the tool matches PARANOID + * (2) $_ is more than 90 days old + * (3) running on an PARANOID_PAY machine + * (4) (1)-(3) have not been defeated + * + * hows that + */ + +#define PARANOID_TOOLS PARANOID +#define PARANOID_COMPANY "Lucent Technologies" +#define PARANOID_MAIL "stc@lucent.com" +#define PARANOID_PAY "135.*&!(135.104.*)" +#define PARANOID_FREE "(192|224).*" + +#include <ast.h> +#include <ls.h> +#include <error.h> +#include <times.h> +#include <ctype.h> + +int +pathcheck(const char* package, const char* tool, Pathcheck_t* pc) +{ +#ifdef PARANOID + register char* s; + struct stat st; + + if (strmatch(tool, PARANOID) && environ && (s = *environ) && *s++ == '_' && *s++ == '=' && !stat(s, &st)) + { + unsigned long n; + unsigned long o; + Sfio_t* sp; + + n = time(NiL); + o = st.st_ctime; + if (n > o && (n - o) > (unsigned long)(60 * 60 * 24 * 90) && (sp = sfopen(NiL, "/etc/hosts", "r"))) + { + /* + * this part is infallible + */ + + n = 0; + o = 0; + while (n++ < 64 && (s = sfgetr(sp, '\n', 0))) + if (strmatch(s, PARANOID_PAY)) + { + error(1, "licensed for external use -- %s employees should contact %s for the internal license", PARANOID_COMPANY, PARANOID_MAIL); + break; + } + else if (*s != '#' && !isspace(*s) && !strneq(s, "127.", 4) && !strmatch(s, PARANOID_FREE) && o++ > 4) + break; + sfclose(sp); + } + } +#else + NoP(tool); +#endif + NoP(package); + if (pc) memzero(pc, sizeof(*pc)); + return(0); +} diff --git a/src/lib/libast/path/pathexists.c b/src/lib/libast/path/pathexists.c new file mode 100644 index 0000000..90b4ae7 --- /dev/null +++ b/src/lib/libast/path/pathexists.c @@ -0,0 +1,134 @@ +/*********************************************************************** +* * +* 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 1 if path exisis + * maintains a cache to minimize stat(2) calls + * path is modified in-place but restored on return + * path components checked in pairs to cut stat()'s + * in half by checking ENOTDIR vs. ENOENT + * case ignorance infection unavoidable here + */ + +#include "lclib.h" + +#include <ls.h> +#include <error.h> + +typedef struct Tree_s +{ + struct Tree_s* next; + struct Tree_s* tree; + int mode; + char name[1]; +} Tree_t; + +int +pathexists(char* path, int mode) +{ + register char* s; + register char* e; + register Tree_t* p; + register Tree_t* t; + register int c; + char* ee; + int cc; + int x; + struct stat st; + int (*cmp)(const char*, const char*); + + static Tree_t tree; + + t = &tree; + e = (c = *path) == '/' ? path + 1 : path; + cmp = strchr(astconf("PATH_ATTRIBUTES", path, NiL), 'c') ? strcasecmp : strcmp; + if ((ast.locale.set & (AST_LC_debug|AST_LC_find)) == (AST_LC_debug|AST_LC_find)) + sfprintf(sfstderr, "locale test %s\n", path); + while (c) + { + p = t; + for (s = e; *e && *e != '/'; e++); + c = *e; + *e = 0; + for (t = p->tree; t && (*cmp)(s, t->name); t = t->next); + if (!t) + { + if (!(t = newof(0, Tree_t, 1, strlen(s)))) + { + *e = c; + return 0; + } + strcpy(t->name, s); + t->next = p->tree; + p->tree = t; + if (c) + { + *e = c; + for (s = ee = e + 1; *ee && *ee != '/'; ee++); + cc = *ee; + *ee = 0; + } + else + ee = 0; + if ((ast.locale.set & (AST_LC_debug|AST_LC_find)) == (AST_LC_debug|AST_LC_find)) + sfprintf(sfstderr, "locale stat %s\n", path); + x = stat(path, &st); + if (ee) + { + e = ee; + c = cc; + if (!x || errno == ENOENT) + t->mode = PATH_READ|PATH_EXECUTE; + if (!(p = newof(0, Tree_t, 1, strlen(s)))) + { + *e = c; + return 0; + } + strcpy(p->name, s); + p->next = t->tree; + t->tree = p; + t = p; + } + if (x) + { + *e = c; + return 0; + } + if (st.st_mode & (S_IRUSR|S_IRGRP|S_IROTH)) + t->mode |= PATH_READ; + if (st.st_mode & (S_IWUSR|S_IWGRP|S_IWOTH)) + t->mode |= PATH_WRITE; + if (st.st_mode & (S_IXUSR|S_IXGRP|S_IXOTH)) + t->mode |= PATH_EXECUTE; + if (!S_ISDIR(st.st_mode)) + t->mode |= PATH_REGULAR; + } + *e++ = c; + if (!t->mode || c && (t->mode & PATH_REGULAR)) + return 0; + } + mode &= (PATH_READ|PATH_WRITE|PATH_EXECUTE|PATH_REGULAR); + return (t->mode & mode) == mode; +} diff --git a/src/lib/libast/path/pathfind.c b/src/lib/libast/path/pathfind.c new file mode 100644 index 0000000..54dc140 --- /dev/null +++ b/src/lib/libast/path/pathfind.c @@ -0,0 +1,168 @@ +/*********************************************************************** +* * +* 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 + * + * include style search support + */ + +#include <ast.h> +#include <error.h> +#include <ls.h> + +#define directory(p,s) (stat((p),(s))>=0&&S_ISDIR((s)->st_mode)) +#define regular(p,s) (stat((p),(s))>=0&&(S_ISREG((s)->st_mode)||streq(p,"/dev/null"))) + +typedef struct Dir_s /* directory list element */ +{ + struct Dir_s* next; /* next in list */ + char dir[1]; /* directory path */ +} Dir_t; + +static struct /* directory list state */ +{ + Dir_t* head; /* directory list head */ + Dir_t* tail; /* directory list tail */ +} state; + +/* + * append dir to pathfind() include list + */ + +int +pathinclude(const char* dir) +{ + register Dir_t* dp; + struct stat st; + + if (dir && *dir && !streq(dir, ".") && directory(dir, &st)) + { + for (dp = state.head; dp; dp = dp->next) + if (streq(dir, dp->dir)) + return 0; + if (!(dp = oldof(0, Dir_t, 1, strlen(dir)))) + return -1; + strcpy(dp->dir, dir); + dp->next = 0; + if (state.tail) + state.tail = state.tail->next = dp; + else + state.head = state.tail = dp; + } + return 0; +} + +/* + * return path to name using pathinclude() list + * path placed in <buf,size> + * if lib!=0 then pathpath() attempted after include search + * if type!=0 and name has no '.' then file.type also attempted + * any *: prefix in lib is ignored (discipline library dictionary support) + */ + +char* +pathfind(const char* name, const char* lib, const char* type, char* buf, size_t size) +{ + register Dir_t* dp; + register char* s; + char tmp[PATH_MAX]; + struct stat st; + + if (((s = strrchr(name, '/')) || (s = (char*)name)) && strchr(s, '.')) + type = 0; + + /* + * always check the unadorned path first + * this handles . and absolute paths + */ + + if (regular(name, &st)) + { + strncopy(buf, name, size); + return buf; + } + if (type) + { + sfsprintf(buf, size, "%s.%s", name, type); + if (regular(buf, &st)) + return buf; + } + if (*name == '/') + return 0; + + /* + * check the directory of the including file + * on the assumption that error_info.file is properly stacked + */ + + if (error_info.file && (s = strrchr(error_info.file, '/'))) + { + sfsprintf(buf, size, "%-.*s%s", s - error_info.file + 1, error_info.file, name); + if (regular(buf, &st)) + return buf; + if (type) + { + sfsprintf(buf, size, "%-.*s%s%.s", s - error_info.file + 1, error_info.file, name, type); + if (regular(buf, &st)) + return buf; + } + } + + /* + * check the include dir list + */ + + for (dp = state.head; dp; dp = dp->next) + { + sfsprintf(tmp, sizeof(tmp), "%s/%s", dp->dir, name); + if (pathpath(tmp, "", PATH_REGULAR, buf, size)) + return buf; + if (type) + { + sfsprintf(tmp, sizeof(tmp), "%s/%s.%s", dp->dir, name, type); + if (pathpath(tmp, "", PATH_REGULAR, buf, size)) + return buf; + } + } + + /* + * finally a lib related search on PATH + */ + + if (lib) + { + if (s = strrchr((char*)lib, ':')) + lib = (const char*)s + 1; + sfsprintf(tmp, sizeof(tmp), "lib/%s/%s", lib, name); + if (pathpath(tmp, "", PATH_REGULAR, buf, size)) + return buf; + if (type) + { + sfsprintf(tmp, sizeof(tmp), "lib/%s/%s.%s", lib, name, type); + if (pathpath(tmp, "", PATH_REGULAR, buf, size)) + return buf; + } + } + return 0; +} diff --git a/src/lib/libast/path/pathgetlink.c b/src/lib/libast/path/pathgetlink.c new file mode 100644 index 0000000..0022594 --- /dev/null +++ b/src/lib/libast/path/pathgetlink.c @@ -0,0 +1,102 @@ +/*********************************************************************** +* * +* 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 Bell Laboratories +*/ + +#include "univlib.h" + +#ifdef UNIV_MAX + +#include <ctype.h> + +#endif + +/* + * return external representation for symbolic link text of name in buf + * the link text string length is returned + */ + +int +pathgetlink(const char* name, char* buf, int siz) +{ + int n; + + if ((n = readlink(name, buf, siz)) < 0) return(-1); + if (n >= siz) + { + errno = EINVAL; + return(-1); + } + buf[n] = 0; +#ifdef UNIV_MAX + if (isspace(*buf)) + { + register char* s; + register char* t; + register char* u; + register char* v; + int match = 0; + char tmp[PATH_MAX]; + + s = buf; + t = tmp; + while (isalnum(*++s) || *s == '_' || *s == '.'); + if (*s++) + { + for (;;) + { + if (!*s || isspace(*s)) + { + if (match) + { + *t = 0; + n = t - tmp; + strcpy(buf, tmp); + } + break; + } + if (t >= &tmp[sizeof(tmp)]) break; + *t++ = *s++; + if (!match && t < &tmp[sizeof(tmp) - univ_size + 1]) for (n = 0; n < UNIV_MAX; n++) + { + if (*(v = s - 1) == *(u = univ_name[n])) + { + while (*u && *v++ == *u) u++; + if (!*u) + { + match = 1; + strcpy(t - 1, univ_cond); + t += univ_size - 1; + s = v; + break; + } + } + } + } + } + } +#endif + return(n); +} diff --git a/src/lib/libast/path/pathkey.c b/src/lib/libast/path/pathkey.c new file mode 100644 index 0000000..2432d83 --- /dev/null +++ b/src/lib/libast/path/pathkey.c @@ -0,0 +1,320 @@ +/*********************************************************************** +* * +* 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 Bell Laboratories + * + * generate 14 char lookup key for lang path in key + * based on 32-bit checksum on path + * + * if key==0 then space is malloc'd + * if attr != 0 then attribute var assignments placed here: + * ATTRIBUTES list of attribute names + */ + +#define _AST_API_H 1 + +#include <ast.h> +#include <ctype.h> +#include <fs3d.h> +#include <preroot.h> +#include <ls.h> + +char* +pathkey(char* key, char* attr, const char* lang, const char* tool, const char* path) +{ + return pathkey_20100601(lang, tool, path, key, 16, attr, PATH_MAX); +} + +#undef _AST_API_H + +#include <ast_api.h> + +char* +pathkey_20100601(const char* lang, const char* tool, const char* apath, char* key, size_t keysize, char* attr, size_t attrsize) +{ + register char* path = (char*)apath; + register char* s; + register char* k; + char* t; + char* flags; + char** p; + int c; + unsigned long n; + char buf[15]; + char* usr[16]; + char* env[elementsof(usr) + 3]; + char* ver[2]; + char tmp[PATH_MAX]; +#if _UWIN + struct stat st; +#endif + + static char let[] = "ABCDEFGHIJKLMNOP"; + + if (!key) + key = buf; + if (tool && streq(tool, "mam")) + { + for (n = 0; *path; path++) + n = n * 0x63c63cd9L + *path + 0x9c39c33dL; + k = key; + for (n &= 0xffffffffL; n; n >>= 4) + *k++ = let[n & 0xf]; + *k = 0; + } + else + { + for (c = 0; c < elementsof(env); c++) + env[c] = 0; + n = 0; + + /* + * trailing flags in path + */ + + if (flags = strchr(path, ' ')) + { + if (flags == path) + flags = 0; + else + { + strlcpy(tmp, path, sizeof(tmp)); + *(flags = tmp + (flags - path)) = 0; + path = tmp; + } + } + + /* + * 3D + */ + + if (!flags && fs3d(FS3D_TEST) && (c = mount(path, tmp, FS3D_GET|FS3D_ALL|FS3D_SIZE(PATH_MAX), NiL)) > 1 && c < PATH_MAX) + path = tmp; + + /* + * preroot + */ + + if (attr) + attr = strcopy(attr, "PREROOT='"); +#if FS_PREROOT + if (k = getenv(PR_BASE)) + { + if (s = strrchr(k, '/')) + k = s + 1; + n = memsum(k, strlen(k), n); + } + if (attr && (getpreroot(attr, path) || getpreroot(attr, NiL))) + attr += strlen(attr); +#else + if ((k = getenv("VIRTUAL_ROOT")) && *k == '/') + { + n = memsum(k, strlen(k), n); + if (attr) + attr = strcopy(attr, k); + } +#endif +#if _UWIN + if (!stat("/", &st) && st.st_ino == 64) + { + k = "/64"; + n = memsum(k, strlen(k), n); + if (attr) + attr = strcopy(attr, k); + } +#endif + + /* + * universe + */ + + if (attr) + attr = strcopy(attr, "' UNIVERSE='"); + if (k = astconf("UNIVERSE", NiL, NiL)) + { + n = memsum(k, strlen(k), n); + if (attr) + attr = strcopy(attr, k); + } + + /* + * environment + * + * ${PROBE_ATTRIBUTES} || ${VERSION_ENVIRONMENT} : list of alternate env vars + * ${VERSION_ENVIRONMENT} : list of alternate env vars + * ${VERSION_<lang>} + * ${VERSION_<base(path)>} + * ${<toupper(base(path))>VER} + * ${OBJTYPE} + */ + + if (attr) + *attr++ = '\''; + c = 0; + usr[c++] = "OBJTYPE"; + if (!(k = getenv("PROBE_ATTRIBUTES"))) + k = getenv("VERSION_ENVIRONMENT"); + if (k) + while (c < (elementsof(usr) - 1)) + { + while (*k && (*k == ':' || *k == ' ')) + k++; + if (!*k) + break; + usr[c++] = k; + while (*k && *k != ':' && *k != ' ') + k++; + } + usr[c] = 0; + ver[0] = (char*)lang; + ver[1] = k = (s = strrchr(path, '/')) ? s + 1 : path; + s = buf; + if (isdigit(*k)) + { + if (*k == '3' && *(k + 1) == 'b') + { + /* + * cuteness never pays + */ + + k += 2; + *s++ = 'B'; + *s++ = 'B'; + *s++ = 'B'; + } + else + *s++ = 'U'; + } + for (; (c = *k) && s < &buf[sizeof(buf) - 1]; k++) + { + if (!isalnum(c)) + c = '_'; + else if (islower(c)) + c = toupper(c); + *s++ = c; + } + *s = 0; + for (p = environ; *p; p++) + { + s = "VERSION_"; + for (k = *p; *k && *k == *s; k++, s++); + if (*k && !*s) + { + for (c = 0; c < elementsof(ver); c++) + if (!env[c] && (s = ver[c])) + { + for (t = k; *t && *t != '=' && *t++ == *s; s++); + if (*t == '=' && (!*s || (s - ver[c]) > 1)) + { + env[c] = *p; + goto found; + } + } + } + if (!env[2]) + { + s = buf; + for (k = *p; *k && *s++ == *k; k++); + if ((s - buf) > 2 && k[0] == 'V' && k[1] == 'E' && k[2] == 'R' && k[3] == '=') + { + env[2] = *p; + goto found; + } + } + for (c = 0; c < elementsof(usr) && (s = usr[c]); c++) + if (!env[c + elementsof(env) - elementsof(usr)]) + { + for (k = *p; *k && *k == *s; k++, s++); + if (*k == '=' && (!*s || *s == ':' || *s == ' ')) + { + env[c + elementsof(env) - elementsof(usr)] = *p; + goto found; + } + } + found: ; + } + for (c = 0; c < elementsof(env); c++) + if (k = env[c]) + { + if (attr) + { + *attr++ = ' '; + while ((*attr++ = *k++) != '='); + *attr++ = '\''; + attr = strcopy(attr, k); + *attr++ = '\''; + } + else + while (*k && *k++ != '='); + n = memsum(k, strlen(k), n); + } + if (attr) + { + attr = strcopy(attr, " ATTRIBUTES='PREROOT UNIVERSE"); + for (c = 0; c < elementsof(env); c++) + if (k = env[c]) + { + *attr++ = ' '; + while ((*attr = *k++) != '=') + attr++; + } + *attr++ = '\''; + *attr = 0; + } + + /* + * now the normal stuff + */ + + if (flags) + *flags = ' '; + s = path + strlen(path); + sfsprintf(key, 15, "%08lX", memsum(path, s - path, n)); + k = key + 14; + *k = 0; + if (!flags) + t = path; + else if ((t = s - 4) < flags) + t = flags + 1; + for (;;) + { + if (--s < t) + { + if (t == path) + break; + s = flags - 2; + t = path; + } + if (*s != '/' && *s != ' ') + { + *--k = *s; + if (k <= key + 8) + break; + } + } + while (k > key + 8) + *--k = '.'; + } + return key == buf ? strdup(key) : key; +} diff --git a/src/lib/libast/path/pathnative.c b/src/lib/libast/path/pathnative.c new file mode 100644 index 0000000..c683d17 --- /dev/null +++ b/src/lib/libast/path/pathnative.c @@ -0,0 +1,126 @@ +/*********************************************************************** +* * +* 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 + * + * convert path to native fs representation in <buf,siz> + * length of converted path returned + * if return length >= siz then buf is indeterminate, but another call + * with siz=length+1 would work + * if buf==0 then required size is returned + */ + +#include <ast.h> + +#if _UWIN + +extern int uwin_path(const char*, char*, int); + +size_t +pathnative(const char* path, char* buf, size_t siz) +{ + return uwin_path(path, buf, siz); +} + +#else + +#if __CYGWIN__ + +extern void cygwin_conv_to_win32_path(const char*, char*); + +size_t +pathnative(const char* path, char* buf, size_t siz) +{ + size_t n; + + if (!buf || siz < PATH_MAX) + { + char tmp[PATH_MAX]; + + cygwin_conv_to_win32_path(path, tmp); + if ((n = strlen(tmp)) < siz && buf) + memcpy(buf, tmp, n + 1); + return n; + } + cygwin_conv_to_win32_path(path, buf); + return strlen(buf); +} + +#else + +#if __EMX__ + +size_t +pathnative(const char* path, char* buf, size_t siz) +{ + char* s; + size_t n; + + if (!_fullpath(buf, path, siz)) + { + for (s = buf; *s; s++) + if (*s == '/') + *s = '\\'; + } + else if ((n = strlen(path)) < siz && buf) + memcpy(buf, path, n + 1); + return n; +} + +#else + +#if __INTERIX + +#include <interix/interix.h> + +size_t +pathnative(const char* path, char* buf, size_t siz) +{ + *buf = 0; + if (path[1] == ':') + strlcpy(buf, path, siz); + else + unixpath2win(path, 0, buf, siz); + return strlen(buf); +} + +#else + +size_t +pathnative(const char* path, char* buf, size_t siz) +{ + size_t n; + + if ((n = strlen(path)) < siz && buf) + memcpy(buf, path, n + 1); + return n; +} + +#endif + +#endif + +#endif + +#endif diff --git a/src/lib/libast/path/pathpath.c b/src/lib/libast/path/pathpath.c new file mode 100644 index 0000000..4c0831d --- /dev/null +++ b/src/lib/libast/path/pathpath.c @@ -0,0 +1,127 @@ +/*********************************************************************** +* * +* This software is part of the ast package * +* Copyright (c) 1985-2012 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 full path to p with mode access using $PATH + * a!=0 enables related root search + * a!=0 && a!="" searches a dir first + * the related root must have a bin subdir + * p==0 sets the cached relative dir to a + * full path returned in path buffer + * if path==0 then the space is malloc'd + */ + +#define _AST_API_H 1 + +#include <ast.h> + +char* +pathpath(char* path, const char* p, const char* a, int mode) +{ + return pathpath_20100601(p, a, mode, path, PATH_MAX); +} + +#undef _AST_API_H + +#include <ast_api.h> + +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 (!size || size > sizeof(buf)) + size = sizeof(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; +} diff --git a/src/lib/libast/path/pathposix.c b/src/lib/libast/path/pathposix.c new file mode 100644 index 0000000..d220591 --- /dev/null +++ b/src/lib/libast/path/pathposix.c @@ -0,0 +1,128 @@ +/*********************************************************************** +* * +* 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 + * + * convert native path to posix fs representation in <buf,siz> + * length of converted path returned + * if return length >= siz then buf is indeterminate, but another call + * with siz=length+1 would work + * if buf==0 then required size is returned + */ + +#include <ast.h> + +#if _UWIN + +#include <uwin.h> + +size_t +pathposix(const char* path, char* buf, size_t siz) +{ + return uwin_unpath(path, buf, siz); +} + +#else + +#if __CYGWIN__ + +extern void cygwin_conv_to_posix_path(const char*, char*); + +size_t +pathposix(const char* path, char* buf, size_t siz) +{ + size_t n; + + if (!buf || siz < PATH_MAX) + { + char tmp[PATH_MAX]; + + cygwin_conv_to_posix_path(path, tmp); + if ((n = strlen(tmp)) < siz && buf) + memcpy(buf, tmp, n + 1); + return n; + } + cygwin_conv_to_posix_path(path, buf); + return strlen(buf); +} + +#else + +#if __EMX__ && 0 /* show me the docs */ + +size_t +pathposix(const char* path, char* buf, size_t siz) +{ + char* s; + size_t n; + + if (!_posixpath(buf, path, siz)) + { + for (s = buf; *s; s++) + if (*s == '/') + *s = '\\'; + } + else if ((n = strlen(path)) < siz && buf) + memcpy(buf, path, n + 1); + return n; +} + +#else + +#if __INTERIX + +#include <interix/interix.h> + +size_t +pathposix(const char* path, char *buf, size_t siz) +{ + static const char pfx[] = "/dev/fs"; + + *buf = 0; + if (!strncasecmp(path, pfx, sizeof(pfx) - 1)) + strlcpy(buf, path, siz); + else + winpath2unix(path, PATH_NONSTRICT, buf, siz); + return strlen(buf); +} + +#else + +size_t +pathposix(const char* path, char* buf, size_t siz) +{ + size_t n; + + if ((n = strlen(path)) < siz && buf) + memcpy(buf, path, n + 1); + return n; +} + +#endif + +#endif + +#endif + +#endif 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; +} diff --git a/src/lib/libast/path/pathprog.c b/src/lib/libast/path/pathprog.c new file mode 100644 index 0000000..ac29427 --- /dev/null +++ b/src/lib/libast/path/pathprog.c @@ -0,0 +1,128 @@ +/*********************************************************************** +* * +* 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 the full path of the current program in path + * command!=0 is used as a default + */ + +#include <ast.h> + +#if _WINIX +#include <ast_windows.h> +#include <ctype.h> +#endif + +#include "FEATURE/prog" + +#if _hdr_macho_o_dyld && _lib__NSGetExecutablePath +#include <mach-o/dyld.h> +#else +#undef _lib__NSGetExecutablePath +#endif + +static size_t +prog(const char* command, char* path, size_t size) +{ + ssize_t n; + char* s; +#if _WINIX + char* t; + char* e; + int c; + int q; +#endif +#if _lib__NSGetExecutablePath + uint32_t z; +#endif + +#ifdef _PROC_PROG + if ((n = readlink(_PROC_PROG, path, size)) > 0 && *path == '/') + { + if (n < size) + path[n] = 0; + return n; + } +#endif +#if _lib_getexecname + if ((s = (char*)getexecname()) && *s == '/') + goto found; +#endif +#if _lib__NSGetExecutablePath + z = size; + if (!_NSGetExecutablePath(path, &z) && *s == '/') + return strlen(s); +#endif +#if _WINIX + if (s = GetCommandLine()) + { + n = 0; + q = 0; + t = path; + e = path + size - 1; + while (c = *s++) + { + if (c == q) + q = 0; + else if (!q && c == '"') + q = c; + else if (!q && isspace(c)) + break; + else if (t < e) + *t++ = c == '\\' ? '/' : c; + else + n++; + } + if (t < e) + *t = 0; + return (t - path) + n; + } +#endif + if (command) + { + s = (char*)command; + goto found; + } + return 0; + found: + n = strlen(s); + if (n < size) + memcpy(path, s, n + 1); + return n; +} + +size_t +pathprog(const char* command, char* path, size_t size) +{ + char* rel; + ssize_t n; + + if ((n = prog(command, path, size)) > 0 && n < size && *path != '/' && (rel = strdup(path))) + { + n = pathpath(rel, NiL, PATH_REGULAR|PATH_EXECUTE, path, size) ? strlen(path) : 0; + free(rel); + } + return n; +} diff --git a/src/lib/libast/path/pathrepl.c b/src/lib/libast/path/pathrepl.c new file mode 100644 index 0000000..d16a390 --- /dev/null +++ b/src/lib/libast/path/pathrepl.c @@ -0,0 +1,93 @@ +/*********************************************************************** +* * +* 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 Bell Laboratories + * + * in place replace of first occurrence of /match/ with /replace/ in path + * end of path returned + */ + +#define _AST_API_H 1 + +#include <ast.h> + +char* +pathrepl(char* path, const char* match, const char* replace) +{ + return pathrepl_20100601(path, PATH_MAX, match, replace); +} + +#undef _AST_API_H + +#include <ast_api.h> + +char* +pathrepl_20100601(register char* path, size_t size, const char* match, register const char* replace) +{ + register const char* m = match; + register const char* r; + char* t; + + if (!match) + match = ""; + if (!replace) + replace = ""; + if (streq(match, replace)) + return(path + strlen(path)); + if (!size) + size = strlen(path) + 1; + for (;;) + { + while (*path && *path++ != '/'); + if (!*path) break; + if (*path == *m) + { + t = path; + while (*m && *m++ == *path) path++; + if (!*m && *path == '/') + { + register char* p; + + p = t; + r = replace; + while (p < path && *r) *p++ = *r++; + if (p < path) while (*p++ = *path++); + else if (*r && p >= path) + { + register char* u; + + t = path + strlen(path); + u = t + strlen(r); + while (t >= path) *u-- = *t--; + while (*r) *p++ = *r++; + } + else p += strlen(p) + 1; + return(p - 1); + } + path = t; + m = match; + } + } + return(path); +} diff --git a/src/lib/libast/path/pathsetlink.c b/src/lib/libast/path/pathsetlink.c new file mode 100644 index 0000000..48aa4fe --- /dev/null +++ b/src/lib/libast/path/pathsetlink.c @@ -0,0 +1,72 @@ +/*********************************************************************** +* * +* 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 Bell Laboratories +*/ + +#include "univlib.h" + +/* + * create symbolic name from external representation text in buf + * the arg order matches link(2) + */ + +int +pathsetlink(const char* buf, const char* name) +{ + register char* t = (char*)buf; +#ifdef UNIV_MAX + register char* s = (char*)buf; + register char* v; + int n; + char tmp[PATH_MAX]; + + while (*s) + { + if (*s++ == univ_cond[0] && !strncmp(s - 1, univ_cond, univ_size)) + { + s--; + t = tmp; + for (n = 0; n < UNIV_MAX; n++) + if (*univ_name[n]) + { + *t++ = ' '; +#ifdef ATT_UNIV + *t++ = '1' + n; + *t++ = ':'; +#else + for (v = univ_name[n]; *t = *v++; t++); + *t++ = '%'; +#endif + for (v = (char*)buf; v < s; *t++ = *v++); + for (v = univ_name[n]; *t = *v++; t++); + for (v = s + univ_size; *t = *v++; t++); + } + t = tmp; + break; + } + } +#endif + return(symlink(t, name)); +} diff --git a/src/lib/libast/path/pathshell.c b/src/lib/libast/path/pathshell.c new file mode 100644 index 0000000..f4b2557 --- /dev/null +++ b/src/lib/libast/path/pathshell.c @@ -0,0 +1,112 @@ +/*********************************************************************** +* * +* 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 +/* + * G. S. Fowler + * D. G. Korn + * AT&T Bell Laboratories + * + * shell library support + */ + +#include <ast.h> +#include <sys/stat.h> + +/* + * return pointer to the full path name of the shell + * + * SHELL is read from the environment and must start with / + * + * if set-uid or set-gid then the executable and its containing + * directory must not be owned by the real user/group + * + * root/administrator has its own test + * + * astconf("SH",NiL,NiL) is returned by default + * + * NOTE: csh is rejected because the bsh/csh differentiation is + * not done for `csh script arg ...' + */ + +char* +pathshell(void) +{ + register char* sh; + int ru; + int eu; + int rg; + int eg; + struct stat st; + + static char* val; + + if ((sh = getenv("SHELL")) && *sh == '/' && strmatch(sh, "*/(sh|*[!cC]sh)*([[:digit:]])?(-+([.[:alnum:]]))?(.exe)")) + { + if (!(ru = getuid()) || !eaccess("/bin", W_OK)) + { + if (stat(sh, &st)) + goto defshell; + if (ru != st.st_uid && !strmatch(sh, "?(/usr)?(/local)/?([ls])bin/?([[:lower:]])sh?(.exe)")) + goto defshell; + } + else + { + eu = geteuid(); + rg = getgid(); + eg = getegid(); + if (ru != eu || rg != eg) + { + char* s; + char dir[PATH_MAX]; + + s = sh; + for (;;) + { + if (stat(s, &st)) + goto defshell; + if (ru != eu && st.st_uid == ru) + goto defshell; + if (rg != eg && st.st_gid == rg) + goto defshell; + if (s != sh) + break; + if (strlen(s) >= sizeof(dir)) + goto defshell; + strcpy(dir, s); + if (!(s = strrchr(dir, '/'))) + break; + *s = 0; + s = dir; + } + } + } + return sh; + } + defshell: + if (!(sh = val)) + { + if (!*(sh = astconf("SH", NiL, NiL)) || *sh != '/' || eaccess(sh, X_OK) || !(sh = strdup(sh))) + sh = "/bin/sh"; + val = sh; + } + return sh; +} diff --git a/src/lib/libast/path/pathstat.c b/src/lib/libast/path/pathstat.c new file mode 100644 index 0000000..6d414ca --- /dev/null +++ b/src/lib/libast/path/pathstat.c @@ -0,0 +1,45 @@ +/*********************************************************************** +* * +* 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 + +#include <ast.h> +#include <ls.h> +#include <error.h> + +/* + * physical stat if logical fails + */ + +int +pathstat(const char* path, struct stat* st) +{ +#if _lib_lstat + int oerrno; + + oerrno = errno; + if (!stat(path, st)) return(0); + errno = oerrno; + return(lstat(path, st)); +#else + return(stat(path, st)); +#endif +} diff --git a/src/lib/libast/path/pathtemp.c b/src/lib/libast/path/pathtemp.c new file mode 100644 index 0000000..844c86a --- /dev/null +++ b/src/lib/libast/path/pathtemp.c @@ -0,0 +1,337 @@ +/*********************************************************************** +* * +* 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 +/* + * AT&T Research + * + * generate a temp file / name + * + * [<dir>/][<pfx>]<bas>.<suf> + * + * length(<pfx>)<=5 + * length(<bas>)==3 + * length(<suf>)==3 + * + * pathtmp(a,b,c,d) pathtemp(a,L_tmpnam,b,c,0) + * tmpfile() char*p=pathtemp(0,0,0,"tf",&sp); + * remove(p); + * free(p) + * tmpnam(0) static char p[L_tmpnam]; + * pathtemp(p,sizeof(p),0,"tn",0) + * tmpnam(p) pathtemp(p,L_tmpnam,0,"tn",0) + * tempnam(d,p) pathtemp(0,d,p,0) + * mktemp(p) pathtemp(0,0,p,0) + * + * if buf==0 then space is malloc'd + * buf size is size + * dir and pfx may be 0 + * if pfx contains trailing X's then it is a mktemp(3) template + * otherwise only first 5 chars of pfx are used + * if fdp!=0 then the path is opened O_EXCL and *fdp is the open fd + * malloc'd space returned by successful pathtemp() calls + * must be freed by the caller + * + * generated names are pseudo-randomized to avoid both + * collisions and predictions (same alg in sfio/sftmp.c) + * + * / as first pfx char provides tmp file generation control + * 0 returned for unknown ops + * + * /cycle dir specifies TMPPATH cycle control + * automatic (default) cycled with each tmp file + * manual cycled by application with dir=(nil) + * (nil) cycle TMPPATH + * /prefix dir specifies the default prefix (default ast) + * /private private file/dir modes + * /public public file/dir modes + * /seed dir specifies pseudo-random generator seed + * 0 or "0" to re-initialize + * /TMPPATH dir overrides the env value + * /TMPDIR dir overrides the env value + */ + +#include <ast.h> +#include <ls.h> +#include <tv.h> +#include <tm.h> + +#define ATTEMPT 10 + +#define TMP_ENV "TMPDIR" +#define TMP_PATH_ENV "TMPPATH" +#define TMP1 "/tmp" +#define TMP2 "/usr/tmp" + +#define VALID(d) (*(d)&&!eaccess(d,W_OK|X_OK)) + +static struct +{ + mode_t mode; + char** vec; + char** dir; + uint32_t key; + uint32_t rng; + pid_t pid; + int manual; + int seed; + char* pfx; + char* tmpdir; + char* tmppath; +} tmp = { S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH }; + +char* +pathtemp(char* buf, size_t len, const char* dir, const char* pfx, int* fdp) +{ + register char* d; + register char* b; + register char* s; + register char* x; + uint32_t key; + int m; + int n; + int l; + int r; + int z; + int attempt; + Tv_t tv; + char keybuf[16]; + + if (pfx && *pfx == '/') + { + pfx++; + if (streq(pfx, "cycle")) + { + if (!dir) + { + tmp.manual = 1; + if (tmp.dir && !*tmp.dir++) + tmp.dir = tmp.vec; + } + else + tmp.manual = streq(dir, "manual"); + return (char*)pfx; + } + else if (streq(pfx, "prefix")) + { + if (tmp.pfx) + free(tmp.pfx); + tmp.pfx = dir ? strdup(dir) : (char*)0; + return (char*)pfx; + } + else if (streq(pfx, "private")) + { + tmp.mode = S_IRUSR|S_IWUSR; + return (char*)pfx; + } + else if (streq(pfx, "public")) + { + tmp.mode = S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH; + return (char*)pfx; + } + else if (streq(pfx, "seed")) + { + tmp.key = (tmp.seed = (tmp.rng = dir ? (uint32_t)strtoul(dir, NiL, 0) : (uint32_t)1) != 0)? (uint32_t)0x63c63cd9L : 0; + return (char*)pfx; + } + else if (streq(pfx, TMP_ENV)) + { + if (tmp.vec) + { + free(tmp.vec); + tmp.vec = 0; + } + if (tmp.tmpdir) + free(tmp.tmpdir); + tmp.tmpdir = dir ? strdup(dir) : (char*)0; + return (char*)pfx; + } + else if (streq(pfx, TMP_PATH_ENV)) + { + if (tmp.vec) + { + free(tmp.vec); + tmp.vec = 0; + } + if (tmp.tmppath) + free(tmp.tmppath); + tmp.tmppath = dir ? strdup(dir) : (char*)0; + return (char*)pfx; + } + return 0; + } + if (tmp.seed) + tv.tv_nsec = 0; + else + tvgettime(&tv); + if (!(d = (char*)dir) || *d && eaccess(d, W_OK|X_OK)) + { + if (!tmp.vec) + { + if ((x = tmp.tmppath) || (x = getenv(TMP_PATH_ENV))) + { + n = 2; + s = x; + while (s = strchr(s, ':')) + { + s++; + n++; + } + if (!(tmp.vec = newof(0, char*, n, strlen(x) + 1))) + return 0; + tmp.dir = tmp.vec; + x = strcpy((char*)(tmp.dir + n), x); + *tmp.dir++ = x; + while (x = strchr(x, ':')) + { + *x++ = 0; + if (!VALID(*(tmp.dir - 1))) + tmp.dir--; + *tmp.dir++ = x; + } + if (!VALID(*(tmp.dir - 1))) + tmp.dir--; + *tmp.dir = 0; + } + else + { + if (((d = tmp.tmpdir) || (d = getenv(TMP_ENV))) && !VALID(d)) + d = 0; + if (!(tmp.vec = newof(0, char*, 2, d ? (strlen(d) + 1) : 0))) + return 0; + if (d) + *tmp.vec = strcpy((char*)(tmp.vec + 2), d); + } + tmp.dir = tmp.vec; + } + if (!(d = *tmp.dir++)) + { + tmp.dir = tmp.vec; + d = *tmp.dir++; + } + if (!d && (!*(d = astconf("TMP", NiL, NiL)) || eaccess(d, W_OK|X_OK)) && eaccess(d = TMP1, W_OK|X_OK) && eaccess(d = TMP2, W_OK|X_OK)) + return 0; + } + if (!len) + len = PATH_MAX; + len--; + if (!(b = buf) && !(b = newof(0, char, len, 1))) + return 0; + z = 0; + if (!pfx && !(pfx = tmp.pfx)) + pfx = "ast"; + m = strlen(pfx); + if (buf && dir && (buf == (char*)dir && (buf + strlen(buf) + 1) == (char*)pfx || buf == (char*)pfx && !*dir) && !strcmp((char*)pfx + m + 1, "XXXXX")) + { + d = (char*)dir; + len = m += strlen(d) + 8; + l = 3; + r = 3; + } + else if (*pfx && pfx[m - 1] == 'X') + { + for (l = m; l && pfx[l - 1] == 'X'; l--); + r = m - l; + m = l; + l = r / 2; + r -= l; + } + else if (strchr(pfx, '.')) + { + m = 5; + l = 3; + r = 3; + } + else + { + z = '.'; + m = 5; + l = 2; + r = 3; + } + x = b + len; + s = b; + if (d) + { + while (s < x && (n = *d++)) + *s++ = n; + if (s < x && s > b && *(s - 1) != '/') + *s++ = '/'; + } + if ((x - s) > m) + x = s + m; + while (s < x && (n = *pfx++)) + { + if (n == '/' || n == '\\' || n == z) + n = '_'; + *s++ = n; + } + *s = 0; + len -= (s - b); + for (attempt = 0; attempt < ATTEMPT; attempt++) + { + if (!tmp.rng || !tmp.seed && (attempt || tmp.pid != getpid())) + { + register int r; + + /* + * get a quasi-random coefficient + */ + + tmp.pid = getpid(); + tmp.rng = (uint32_t)tmp.pid * ((uint32_t)time(NiL) ^ (((uint32_t)integralof(&attempt)) >> 3) ^ (((uint32_t)integralof(tmp.dir)) >> 3)); + if (!tmp.key) + tmp.key = (tmp.rng >> 16) | ((tmp.rng & 0xffff) << 16); + tmp.rng ^= tmp.key; + + /* + * Knuth vol.2, page.16, Thm.A + */ + + if ((r = (tmp.rng - 1) & 03)) + tmp.rng += 4 - r; + } + + /* + * generate a pseudo-random name + */ + + key = tmp.rng * tmp.key + tv.tv_nsec; + if (!tmp.seed) + tvgettime(&tv); + tmp.key = tmp.rng * key + tv.tv_nsec; + sfsprintf(keybuf, sizeof(keybuf), "%07.7.32I*u%07.7.32I*u", sizeof(key), key, sizeof(tmp.key), tmp.key); + sfsprintf(s, len, "%-.*s%s%-.*s", l, keybuf, z ? "." : "", r, keybuf + sizeof(keybuf) / 2); + if (fdp) + { + if ((n = open(b, O_CREAT|O_RDWR|O_EXCL|O_TEMPORARY, tmp.mode)) >= 0) + { + *fdp = n; + return b; + } + } + else if (access(b, F_OK)) + return b; + } + if (!buf) + free(b); + return 0; +} diff --git a/src/lib/libast/path/pathtmp.c b/src/lib/libast/path/pathtmp.c new file mode 100644 index 0000000..aac0243 --- /dev/null +++ b/src/lib/libast/path/pathtmp.c @@ -0,0 +1,41 @@ +/*********************************************************************** +* * +* 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 +/* + * obsolete -- use pathtemp() + */ + +#include <ast.h> +#include <stdio.h> + +#ifndef L_tmpnam +#define L_tmpnam 25 +#endif + +char* +pathtmp(char* buf, const char* dir, const char* pfx, int* fdp) +{ + size_t len; + + len = !buf ? 0 : !dir ? L_tmpnam : (strlen(dir) + 14); + return pathtemp(buf, len, dir, pfx, fdp); +} |