1 /***********************************************************************
2 * *
3 * This software is part of the ast package *
4 * Copyright (c) 1985-2010 AT&T Intellectual Property *
5 * and is licensed under the *
6 * Common Public License, Version 1.0 *
7 * by AT&T Intellectual Property *
8 * *
9 * A copy of the License is available at *
10 * http://www.opensource.org/licenses/cpl1.0.txt *
11 * (with md5 checksum 059e8cd6165cb4c31e351f2b69388fd9) *
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 #include <ast.h>
36 #include <ctype.h>
37 #include <fs3d.h>
38 #include <preroot.h>
39
40 char*
pathkey(char * key,char * attr,const char * lang,const char * tool,const char * apath)41 pathkey(char* key, char* attr, const char* lang, const char* tool, const char* apath)
42 {
43 register char* path = (char*)apath;
44 register char* s;
45 register char* k;
46 char* t;
47 char* flags;
48 char** p;
49 int c;
50 unsigned long n;
51 char buf[15];
52 char* usr[16];
53 char* env[elementsof(usr) + 3];
54 char* ver[2];
55 char tmp[PATH_MAX];
56
57 static char let[] = "ABCDEFGHIJKLMNOP";
58
59 if (!key)
60 key = buf;
61 if (tool && streq(tool, "mam"))
62 {
63 for (n = 0; *path; path++)
64 n = n * 0x63c63cd9L + *path + 0x9c39c33dL;
65 k = key;
66 for (n &= 0xffffffffL; n; n >>= 4)
67 *k++ = let[n & 0xf];
68 *k = 0;
69 }
70 else
71 {
72 for (c = 0; c < elementsof(env); c++)
73 env[c] = 0;
74 n = 0;
75
76 /*
77 * trailing flags in path
78 */
79
80 if (flags = strchr(path, ' '))
81 {
82 if (flags == path)
83 flags = 0;
84 else
85 {
86 strcpy(tmp, path);
87 *(flags = tmp + (flags - path)) = 0;
88 path = tmp;
89 }
90 }
91
92 /*
93 * 3D
94 */
95
96 if (fs3d(FS3D_TEST) && (c = mount(path, tmp, FS3D_GET|FS3D_ALL|FS3D_SIZE(PATH_MAX), NiL)) > 1 && c < PATH_MAX)
97 path = tmp;
98
99 /*
100 * preroot
101 */
102
103 if (attr)
104 attr = strcopy(attr, "PREROOT='");
105 #if FS_PREROOT
106 if (k = getenv(PR_BASE))
107 {
108 if (s = strrchr(k, '/'))
109 k = s + 1;
110 n = memsum(k, strlen(k), n);
111 }
112 if (attr && (getpreroot(attr, path) || getpreroot(attr, NiL)))
113 attr += strlen(attr);
114 #else
115 if ((k = getenv("VIRTUAL_ROOT")) && *k == '/')
116 {
117 n = memsum(k, strlen(k), n);
118 if (attr)
119 attr = strcopy(attr, k);
120 }
121 #endif
122
123 /*
124 * universe
125 */
126
127 if (attr)
128 attr = strcopy(attr, "' UNIVERSE='");
129 if (k = astconf("UNIVERSE", NiL, NiL))
130 {
131 n = memsum(k, strlen(k), n);
132 if (attr)
133 attr = strcopy(attr, k);
134 }
135
136 /*
137 * environment
138 *
139 * ${PROBE_ATTRIBUTES} || ${VERSION_ENVIRONMENT} : list of alternate env vars
140 * ${VERSION_ENVIRONMENT} : list of alternate env vars
141 * ${VERSION_<lang>}
142 * ${VERSION_<base(path)>}
143 * ${<toupper(base(path))>VER}
144 * ${OBJTYPE}
145 */
146
147 if (attr)
148 *attr++ = '\'';
149 c = 0;
150 usr[c++] = "OBJTYPE";
151 if (!(k = getenv("PROBE_ATTRIBUTES")))
152 k = getenv("VERSION_ENVIRONMENT");
153 if (k)
154 while (c < (elementsof(usr) - 1))
155 {
156 while (*k && (*k == ':' || *k == ' '))
157 k++;
158 if (!*k)
159 break;
160 usr[c++] = k;
161 while (*k && *k != ':' && *k != ' ')
162 k++;
163 }
164 usr[c] = 0;
165 ver[0] = (char*)lang;
166 ver[1] = k = (s = strrchr(path, '/')) ? s + 1 : path;
167 s = buf;
168 if (isdigit(*k))
169 {
170 if (*k == '3' && *(k + 1) == 'b')
171 {
172 /*
173 * cuteness never pays
174 */
175
176 k += 2;
177 *s++ = 'B';
178 *s++ = 'B';
179 *s++ = 'B';
180 }
181 else
182 *s++ = 'U';
183 }
184 for (; (c = *k) && s < &buf[sizeof(buf) - 1]; k++)
185 {
186 if (!isalnum(c))
187 c = '_';
188 else if (islower(c))
189 c = toupper(c);
190 *s++ = c;
191 }
192 *s = 0;
193 for (p = environ; *p; p++)
194 {
195 s = "VERSION_";
196 for (k = *p; *k && *k == *s; k++, s++);
197 if (*k && !*s)
198 {
199 for (c = 0; c < elementsof(ver); c++)
200 if (!env[c] && (s = ver[c]))
201 {
202 for (t = k; *t && *t != '=' && *t++ == *s; s++);
203 if (*t == '=' && (!*s || (s - ver[c]) > 1))
204 {
205 env[c] = *p;
206 goto found;
207 }
208 }
209 }
210 if (!env[2])
211 {
212 s = buf;
213 for (k = *p; *k && *s++ == *k; k++);
214 if ((s - buf) > 2 && k[0] == 'V' && k[1] == 'E' && k[2] == 'R' && k[3] == '=')
215 {
216 env[2] = *p;
217 goto found;
218 }
219 }
220 for (c = 0; c < elementsof(usr) && (s = usr[c]); c++)
221 if (!env[c + elementsof(env) - elementsof(usr)])
222 {
223 for (k = *p; *k && *k == *s; k++, s++);
224 if (*k == '=' && (!*s || *s == ':' || *s == ' '))
225 {
226 env[c + elementsof(env) - elementsof(usr)] = *p;
227 goto found;
228 }
229 }
230 found: ;
231 }
232 for (c = 0; c < elementsof(env); c++)
233 if (k = env[c])
234 {
235 if (attr)
236 {
237 *attr++ = ' ';
238 while ((*attr++ = *k++) != '=');
239 *attr++ = '\'';
240 attr = strcopy(attr, k);
241 *attr++ = '\'';
242 }
243 else
244 while (*k && *k++ != '=');
245 n = memsum(k, strlen(k), n);
246 }
247 if (attr)
248 {
249 attr = strcopy(attr, " ATTRIBUTES='PREROOT UNIVERSE");
250 for (c = 0; c < elementsof(env); c++)
251 if (k = env[c])
252 {
253 *attr++ = ' ';
254 while ((*attr = *k++) != '=')
255 attr++;
256 }
257 *attr++ = '\'';
258 *attr = 0;
259 }
260
261 /*
262 * now the normal stuff
263 */
264
265 if (flags)
266 *flags = ' ';
267 s = path + strlen(path);
268 sfsprintf(key, 15, "%08lX", memsum(path, s - path, n));
269 k = key + 14;
270 *k = 0;
271 if (!flags)
272 t = path;
273 else if ((t = s - 4) < flags)
274 t = flags + 1;
275 for (;;)
276 {
277 if (--s < t)
278 {
279 if (t == path)
280 break;
281 s = flags - 2;
282 t = path;
283 }
284 if (*s != '/' && *s != ' ')
285 {
286 *--k = *s;
287 if (k <= key + 8)
288 break;
289 }
290 }
291 while (k > key + 8)
292 *--k = '.';
293 }
294 return key == buf ? strdup(key) : key;
295 }
296