summaryrefslogtreecommitdiff
path: root/src/lib/libast/path
diff options
context:
space:
mode:
Diffstat (limited to 'src/lib/libast/path')
-rw-r--r--src/lib/libast/path/pathaccess.c69
-rw-r--r--src/lib/libast/path/pathbin.c46
-rw-r--r--src/lib/libast/path/pathcanon.c222
-rw-r--r--src/lib/libast/path/pathcat.c98
-rw-r--r--src/lib/libast/path/pathcd.c142
-rw-r--r--src/lib/libast/path/pathcheck.c91
-rw-r--r--src/lib/libast/path/pathexists.c134
-rw-r--r--src/lib/libast/path/pathfind.c168
-rw-r--r--src/lib/libast/path/pathgetlink.c102
-rw-r--r--src/lib/libast/path/pathkey.c320
-rw-r--r--src/lib/libast/path/pathnative.c126
-rw-r--r--src/lib/libast/path/pathpath.c127
-rw-r--r--src/lib/libast/path/pathposix.c128
-rw-r--r--src/lib/libast/path/pathprobe.c316
-rw-r--r--src/lib/libast/path/pathprog.c128
-rw-r--r--src/lib/libast/path/pathrepl.c93
-rw-r--r--src/lib/libast/path/pathsetlink.c72
-rw-r--r--src/lib/libast/path/pathshell.c112
-rw-r--r--src/lib/libast/path/pathstat.c45
-rw-r--r--src/lib/libast/path/pathtemp.c337
-rw-r--r--src/lib/libast/path/pathtmp.c41
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);
+}