1/***********************************************************************
2*                                                                      *
3*               This software is part of the ast package               *
4*          Copyright (c) 1985-2011 AT&T Intellectual Property          *
5*                      and is licensed under the                       *
6*                 Eclipse Public License, Version 1.0                  *
7*                    by AT&T Intellectual Property                     *
8*                                                                      *
9*                A copy of the License is available at                 *
10*          http://www.eclipse.org/org/documents/epl-v10.html           *
11*         (with md5 checksum b35adb5213ca9657e911e9befb180842)         *
12*                                                                      *
13*              Information and Software Systems Research               *
14*                            AT&T Research                             *
15*                           Florham Park NJ                            *
16*                                                                      *
17*                 Glenn Fowler <gsf@research.att.com>                  *
18*                  David Korn <dgk@research.att.com>                   *
19*                   Phong Vo <kpv@research.att.com>                    *
20*                                                                      *
21***********************************************************************/
22#pragma prototyped
23/*
24 * Glenn Fowler
25 * AT&T Bell Laboratories
26 *
27 * generate 14 char lookup key for lang path in key
28 * based on 32-bit checksum on path
29 *
30 * if key==0 then space is malloc'd
31 * if attr != 0 then attribute var assignments placed here:
32 *	ATTRIBUTES	list of attribute names
33 */
34
35#define _AST_API_H	1
36
37#include <ast.h>
38#include <ctype.h>
39#include <fs3d.h>
40#include <preroot.h>
41#include <ls.h>
42
43char*
44pathkey(char* key, char* attr, const char* lang, const char* tool, const char* path)
45{
46	return pathkey_20100601(lang, tool, path, key, 16, attr, PATH_MAX);
47}
48
49#undef	_AST_API_H
50
51#include <ast_api.h>
52
53char*
54pathkey_20100601(const char* lang, const char* tool, const char* apath, char* key, size_t keysize, char* attr, size_t attrsize)
55{
56	register char*		path = (char*)apath;
57	register char*		s;
58	register char*		k;
59	char*			t;
60	char*			flags;
61	char**			p;
62	int			c;
63	unsigned long		n;
64	char			buf[15];
65	char*			usr[16];
66	char*			env[elementsof(usr) + 3];
67	char*			ver[2];
68	char			tmp[PATH_MAX];
69#if _UWIN
70	struct stat		st;
71#endif
72
73	static char		let[] = "ABCDEFGHIJKLMNOP";
74
75	if (!key)
76		key = buf;
77	if (tool && streq(tool, "mam"))
78	{
79		for (n = 0; *path; path++)
80			n = n * 0x63c63cd9L + *path + 0x9c39c33dL;
81		k = key;
82		for (n &= 0xffffffffL; n; n >>= 4)
83			*k++ = let[n & 0xf];
84		*k = 0;
85	}
86	else
87	{
88		for (c = 0; c < elementsof(env); c++)
89			env[c] = 0;
90		n = 0;
91
92		/*
93		 * trailing flags in path
94		 */
95
96		if (flags = strchr(path, ' '))
97		{
98			if (flags == path)
99				flags = 0;
100			else
101			{
102				strlcpy(tmp, path, sizeof(tmp));
103				*(flags = tmp + (flags - path)) = 0;
104				path = tmp;
105			}
106		}
107
108		/*
109		 * 3D
110		 */
111
112		if (!flags && fs3d(FS3D_TEST) && (c = mount(path, tmp, FS3D_GET|FS3D_ALL|FS3D_SIZE(PATH_MAX), NiL)) > 1 && c < PATH_MAX)
113			path = tmp;
114
115		/*
116		 * preroot
117		 */
118
119		if (attr)
120			attr = strcopy(attr, "PREROOT='");
121#if FS_PREROOT
122		if (k = getenv(PR_BASE))
123		{
124			if (s = strrchr(k, '/'))
125				k = s + 1;
126			n = memsum(k, strlen(k), n);
127		}
128		if (attr && (getpreroot(attr, path) || getpreroot(attr, NiL)))
129			attr += strlen(attr);
130#else
131		if ((k = getenv("VIRTUAL_ROOT")) && *k == '/')
132		{
133			n = memsum(k, strlen(k), n);
134			if (attr)
135				attr = strcopy(attr, k);
136		}
137#endif
138#if _UWIN
139		if (!stat("/", &st) && st.st_ino == 64)
140		{
141			k = "/64";
142			n = memsum(k, strlen(k), n);
143			if (attr)
144				attr = strcopy(attr, k);
145		}
146#endif
147
148		/*
149		 * universe
150		 */
151
152		if (attr)
153			attr = strcopy(attr, "' UNIVERSE='");
154		if (k = astconf("UNIVERSE", NiL, NiL))
155		{
156			n = memsum(k, strlen(k), n);
157			if (attr)
158				attr = strcopy(attr, k);
159		}
160
161		/*
162		 * environment
163		 *
164		 *	${PROBE_ATTRIBUTES} || ${VERSION_ENVIRONMENT} : list of alternate env vars
165		 *	${VERSION_ENVIRONMENT}	: list of alternate env vars
166		 *	${VERSION_<lang>}
167		 *	${VERSION_<base(path)>}
168		 *	${<toupper(base(path))>VER}
169		 *	${OBJTYPE}
170		 */
171
172		if (attr)
173			*attr++ = '\'';
174		c = 0;
175		usr[c++] = "OBJTYPE";
176		if (!(k = getenv("PROBE_ATTRIBUTES")))
177			k = getenv("VERSION_ENVIRONMENT");
178		if (k)
179			while (c < (elementsof(usr) - 1))
180			{
181				while (*k && (*k == ':' || *k == ' '))
182					k++;
183				if (!*k)
184					break;
185				usr[c++] = k;
186				while (*k && *k != ':' && *k != ' ')
187					k++;
188			}
189		usr[c] = 0;
190		ver[0] = (char*)lang;
191		ver[1] = k = (s = strrchr(path, '/')) ? s + 1 : path;
192		s = buf;
193		if (isdigit(*k))
194		{
195			if (*k == '3' && *(k + 1) == 'b')
196			{
197				/*
198				 * cuteness never pays
199				 */
200
201				k += 2;
202				*s++ = 'B';
203				*s++ = 'B';
204				*s++ = 'B';
205			}
206			else
207				*s++ = 'U';
208		}
209		for (; (c = *k) && s < &buf[sizeof(buf) - 1]; k++)
210		{
211			if (!isalnum(c))
212				c = '_';
213			else if (islower(c))
214				c = toupper(c);
215			*s++ = c;
216		}
217		*s = 0;
218		for (p = environ; *p; p++)
219		{
220			s = "VERSION_";
221			for (k = *p; *k && *k == *s; k++, s++);
222			if (*k && !*s)
223			{
224				for (c = 0; c < elementsof(ver); c++)
225					if (!env[c] && (s = ver[c]))
226					{
227						for (t = k; *t && *t != '=' && *t++ == *s; s++);
228						if (*t == '=' && (!*s || (s - ver[c]) > 1))
229						{
230							env[c] = *p;
231							goto found;
232						}
233					}
234			}
235			if (!env[2])
236			{
237				s = buf;
238				for (k = *p; *k && *s++ == *k; k++);
239				if ((s - buf) > 2 && k[0] == 'V' && k[1] == 'E' && k[2] == 'R' && k[3] == '=')
240				{
241					env[2] = *p;
242					goto found;
243				}
244			}
245			for (c = 0; c < elementsof(usr) && (s = usr[c]); c++)
246				if (!env[c + elementsof(env) - elementsof(usr)])
247				{
248					for (k = *p; *k && *k == *s; k++, s++);
249					if (*k == '=' && (!*s || *s == ':' || *s == ' '))
250					{
251						env[c + elementsof(env) - elementsof(usr)] = *p;
252						goto found;
253					}
254				}
255		found:	;
256		}
257		for (c = 0; c < elementsof(env); c++)
258			if (k = env[c])
259			{
260				if (attr)
261				{
262					*attr++ = ' ';
263					while ((*attr++ = *k++) != '=');
264					*attr++ = '\'';
265					attr = strcopy(attr, k);
266					*attr++ = '\'';
267				}
268				else
269					while (*k && *k++ != '=');
270				n = memsum(k, strlen(k), n);
271			}
272		if (attr)
273		{
274			attr = strcopy(attr, " ATTRIBUTES='PREROOT UNIVERSE");
275			for (c = 0; c < elementsof(env); c++)
276				if (k = env[c])
277				{
278					*attr++ = ' ';
279					while ((*attr = *k++) != '=')
280						attr++;
281				}
282			*attr++ = '\'';
283			*attr = 0;
284		}
285
286		/*
287		 * now the normal stuff
288		 */
289
290		if (flags)
291			*flags = ' ';
292		s = path + strlen(path);
293		sfsprintf(key, 15, "%08lX", memsum(path, s - path, n));
294		k = key + 14;
295		*k = 0;
296		if (!flags)
297			t = path;
298		else if ((t = s - 4) < flags)
299			t = flags + 1;
300		for (;;)
301		{
302			if (--s < t)
303			{
304				if (t == path)
305					break;
306				s = flags - 2;
307				t = path;
308			}
309			if (*s != '/' && *s != ' ')
310			{
311				*--k = *s;
312				if (k <= key + 8)
313					break;
314			}
315		}
316		while (k > key + 8)
317			*--k = '.';
318	}
319	return key == buf ? strdup(key) : key;
320}
321