rpm 5.2.1

- Main Page
- Related Pages
- Modules
- Data Structures
- Files

- File List
- Globals

rpmrc.c
Go to the documentation of this file.
1 #include "system.h"
2
3 #include <stdarg.h>
4
5 #if defined(HAVE_SYS_SYSTEMCFG_H)
6 #include <sys/systemcfg.h>
7 #else
8 #define __power_pc() 0
9 #endif
10
11 #define _RPMIOB_INTERNAL /* XXX for rpmiobSlurp */
12 #include <rpmio.h>
13 #include <rpmcb.h>
14 #define _MIRE_INTERNAL
15 #include <mire.h>
16 #include <argv.h>
17 #include <rpmlua.h>
18 #include <rpmluaext.h>
19 #include <rpmmacro.h>
20
21 #include <rpmtypes.h>
22 #include <rpmtag.h>
23 #define _RPMEVR_INTERNAL
24 #include <rpmevr.h>
25
26 #define _RPMDS_INTERNAL
27 #include <rpmds.h>
28
29 #include <rpmcli.h>
30
31 #include <rpmsyck.h>
32
33 #include "debug.h"
34
35 /*@access miRE@*/
36
37 /*@unchecked@*/ /*@null@*/
38 static const char * configTarget = NULL;
39
40 /*@observer@*/ /*@unchecked@*/
41 static const char * platform = SYSCONFIGDIR "/platform";
42
43 /*@only@*/ /*@relnull@*/ /*@unchecked@*/
44 void * platpat = NULL;
45 /*@unchecked@*/
46 int nplatpat = 0;
47
48 extern rpmds cpuinfoP;
49
50
51
57 enum rpm_machtable_e {
58 RPM_MACHTABLE_INSTARCH = 0,
59 RPM_MACHTABLE_INSTOS = 1,
60 RPM_MACHTABLE_BUILDARCH = 2,
61 RPM_MACHTABLE_BUILDOS = 3
62 };
63 #define RPM_MACHTABLE_COUNT 4
65 typedef /*@owned@*/ const char * cptr_t;
66
67 typedef struct machCacheEntry_s {
68 const char * name;
69 int count;
70 cptr_t * equivs;
71 int visited;
72 } * machCacheEntry;
73
74 typedef struct machCache_s {
75 machCacheEntry cache;
76 int size;
77 } * machCache;
78
79 typedef struct machEquivInfo_s {
80 const char * name;
81 int score;
82 } * machEquivInfo;
83
84 typedef struct machEquivTable_s {
85 int count;
86 machEquivInfo list;
87 } * machEquivTable;
88
89 typedef struct defaultEntry_s {
90 /*@owned@*/ /*@null@*/ const char * name;
91 /*@owned@*/ /*@null@*/ const char * defName;
92 } * defaultEntry;
93
94 typedef struct canonEntry_s {
95 /*@owned@*/ const char * name;
96 /*@owned@*/ const char * short_name;
97 short num;
98 } * canonEntry;
99
100 /* tags are 'key'canon, 'key'translate, 'key'compat
101 *
102 * for giggles, 'key'_canon, 'key'_compat, and 'key'_canon will also work
103 */
104 typedef struct tableType_s {
105 /*@observer@*/ const char * const key;
106 const int hasCanon;
107 const int hasTranslate;
108 struct machEquivTable_s equiv;
109 struct machCache_s cache;
110 defaultEntry defaults;
111 canonEntry canons;
112 int defaultsLength;
113 int canonsLength;
114 } * tableType;
115
116 /*@-fullinitblock@*/
117 /*@unchecked@*/
118 static struct tableType_s tables[RPM_MACHTABLE_COUNT] = {
119 { "arch", 1, 0 },
120 { "os", 1, 0 },
121 { "buildarch", 0, 1 },
122 { "buildos", 0, 1 }
123 };
124 /*@=fullinitblock@*/
125
126 #define OS 0
127 #define ARCH 1
128
129 /*@unchecked@*/
130 static cptr_t current[2];
131
132 /*@unchecked@*/
133 static int currTables[2] = { RPM_MACHTABLE_INSTOS, RPM_MACHTABLE_INSTARCH };
134
135 /*@unchecked@*/
136 static int defaultsInitialized = 0;
137
138 /* prototypes */
139 static void rpmRebuildTargetVars(/*@null@*/ const char **target, /*@null@*/ const char ** canontarget)
140 /*@globals rpmGlobalMacroContext, h_errno, fileSystem, internalState @*/
141 /*@modifies *canontarget, rpmGlobalMacroContext,
142 fileSystem, internalState @*/;
143
144 static /*@observer@*/ /*@null@*/ machCacheEntry
145 machCacheFindEntry(const machCache cache, const char * key)
146 /*@*/
147 {
148 int i;
149
150 for (i = 0; i < cache->size; i++)
151 if (!strcmp(cache->cache[i].name, key)) return cache->cache + i;
152
153 return NULL;
154 }
155
156 static void machAddEquiv(machEquivTable table, const char * name,
157 int distance)
158 /*@modifies table->list, table->count @*/
159 {
160 machEquivInfo equiv;
161
162 { int i;
163 equiv = NULL;
164 for (i = 0; i < table->count; i++) {
165 if (xstrcasecmp(table->list[i].name, name))
166 continue;
167 equiv = table->list + i;
168 break;
169 }
170 }
171
172 if (!equiv) {
173 if (table->count)
174 table->list = xrealloc(table->list, (table->count + 1)
175 * sizeof(*table->list));
176 else
177 table->list = xmalloc(sizeof(*table->list));
178
179 table->list[table->count].name = xstrdup(name);
180 table->list[table->count++].score = distance;
181 }
182 }
183
184 static void machCacheEntryVisit(machCache cache,
185 machEquivTable table, const char * name, int distance)
186 /*@modifies table->list, table->count @*/
187 {
188 machCacheEntry entry;
189 int i;
190
191 entry = machCacheFindEntry(cache, name);
192 if (!entry || entry->visited) return;
193
194 entry->visited = 1;
195
196 for (i = 0; i < entry->count; i++) {
197 machAddEquiv(table, entry->equivs[i], distance);
198 }
199
200 for (i = 0; i < entry->count; i++) {
201 machCacheEntryVisit(cache, table, entry->equivs[i], distance + 1);
202 }
203 }
204
205 static void rebuildCompatTables(int type, const char * name)
206 /*@globals tables, internalState @*/
207 /*@modifies tables, internalState @*/
208 {
209 machCache cache = &tables[currTables[type]].cache;
210 machEquivTable table = &tables[currTables[type]].equiv;
211 const char * key = name;
212 int i;
213
214 for (i = 0; i < cache->size; i++)
215 cache->cache[i].visited = 0;
216
217 while (table->count > 0) {
218 --table->count;
219 table->list[table->count].name = _free(table->list[table->count].name);
220 }
221 table->count = 0;
222 table->list = _free(table->list);
223
224 /*
225 * We have a general graph built using strings instead of pointers.
226 * Yuck. We have to start at a point at traverse it, remembering how
227 * far away everything is.
228 */
229 /*@-nullstate@*/ /* FIX: table->list may be NULL. */
230 machAddEquiv(table, key, 1);
231 machCacheEntryVisit(cache, table, key, 2);
232 return;
233 /*@=nullstate@*/
234 }
235
236 static /*@null@*/ canonEntry lookupInCanonTable(const char * name,
237 const canonEntry table, int tableLen)
238 /*@*/
239 {
240 while (tableLen) {
241 tableLen--;
242 if (strcmp(name, table[tableLen].name))
243 continue;
244 /*@-immediatetrans -retalias@*/
245 return &(table[tableLen]);
246 /*@=immediatetrans =retalias@*/
247 }
248
249 return NULL;
250 }
251
252 static /*@observer@*/ /*@null@*/
253 const char * lookupInDefaultTable(const char * name,
254 const defaultEntry table, int tableLen)
255 /*@*/
256 {
257 while (tableLen) {
258 tableLen--;
259 if (table[tableLen].name && !strcmp(name, table[tableLen].name))
260 return table[tableLen].defName;
261 }
262
263 return name;
264 }
265
266 static void addMacroDefault(const char * macroname,
267 const char * val, /*@null@*/ const char * body)
268 /*@globals rpmGlobalMacroContext, internalState @*/
269 /*@modifies rpmGlobalMacroContext, internalState @*/
270 {
271 if (body == NULL)
272 body = val;
273 addMacro(NULL, macroname, NULL, body, RMIL_DEFAULT);
274 }
275
276 static void setPathDefault(const char * macroname, const char * subdir)
277 /*@globals rpmGlobalMacroContext, internalState @*/
278 /*@modifies rpmGlobalMacroContext, internalState @*/
279 {
280 if (macroname != NULL) {
281 #define _TOPDIRMACRO "%{_topdir}/"
282 char *body = alloca(sizeof(_TOPDIRMACRO) + strlen(subdir));
283 strcpy(body, _TOPDIRMACRO);
284 strcat(body, subdir);
285 addMacro(NULL, macroname, NULL, body, RMIL_DEFAULT);
286 #undef _TOPDIRMACRO
287 }
288 }
289
290 /*@observer@*/ /*@unchecked@*/
291 static const char * ___build_pre = "\n\
292 RPM_SOURCE_DIR=\"%{_sourcedir}\"\n\
293 RPM_BUILD_DIR=\"%{_builddir}\"\n\
294 RPM_OPT_FLAGS=\"%{optflags}\"\n\
295 RPM_ARCH=\"%{_arch}\"\n\
296 RPM_OS=\"%{_os}\"\n\
297 export RPM_SOURCE_DIR RPM_BUILD_DIR RPM_OPT_FLAGS RPM_ARCH RPM_OS\n\
298 RPM_DOC_DIR=\"%{_docdir}\"\n\
299 export RPM_DOC_DIR\n\
300 RPM_PACKAGE_NAME=\"%{name}\"\n\
301 RPM_PACKAGE_VERSION=\"%{version}\"\n\
302 RPM_PACKAGE_RELEASE=\"%{release}\"\n\
303 export RPM_PACKAGE_NAME RPM_PACKAGE_VERSION RPM_PACKAGE_RELEASE\n\
304 %{?buildroot:RPM_BUILD_ROOT=\"%{buildroot}\"\n\
305 export RPM_BUILD_ROOT\n}\
306 ";
307
308 #if defined(RPM_VENDOR_WINDRIVER)
309 /*@unchecked@*/
310 extern const char * __usrlibrpm;
311 /*@unchecked@*/
312 extern const char * __etcrpm;
313 #endif
314
315 static void setDefaults(void)
316 /*@globals rpmGlobalMacroContext, internalState @*/
317 /*@modifies rpmGlobalMacroContext, internalState @*/
318 {
319
320 #if defined(RPM_VENDOR_WINDRIVER)
321 addMacro(NULL, "_usrlibrpm", NULL, __usrlibrpm, RMIL_DEFAULT);
322 addMacro(NULL, "_etcrpm", NULL, __etcrpm, RMIL_DEFAULT);
323 addMacro(NULL, "_vendor", NULL, "%{?_host_vendor}%{!?_host_vendor:wrs}", RMIL_DEFAULT);
324 #endif
325
326 addMacro(NULL, "_usr", NULL, USRPREFIX, RMIL_DEFAULT);
327 addMacro(NULL, "_var", NULL, VARPREFIX, RMIL_DEFAULT);
328 addMacro(NULL, "_prefix", NULL, "%{_usr}", RMIL_DEFAULT);
329
330 addMacro(NULL, "___build_pre", NULL, ___build_pre, RMIL_DEFAULT);
331
332 addMacroDefault("_topdir",
333 "%{_usr}/src/rpm", NULL);
334 addMacroDefault("_tmppath",
335 "%{_var}/tmp", NULL);
336 addMacroDefault("_dbpath",
337 "%{_var}/lib/rpm", NULL);
338 addMacroDefault("_defaultdocdir",
339 "%{_usr}/share/doc", NULL);
340
341 addMacroDefault("_rpmfilename",
342 "%%{ARCH}/%%{NAME}-%%{VERSION}-%%{RELEASE}.%%{ARCH}.rpm",NULL);
343
344 addMacroDefault("optflags",
345 "-O2 -g", NULL);
346 addMacroDefault("sigtype",
347 "none", NULL);
348 addMacroDefault("_buildshell",
349 "/bin/sh", NULL);
350
351 setPathDefault("_builddir", "BUILD");
352 setPathDefault("_rpmdir", "RPMS");
353 setPathDefault("_srcrpmdir", "SRPMS");
354 setPathDefault("_sourcedir", "SOURCES");
355 setPathDefault("_specdir", "SPECS");
356
357 }
358
359 typedef struct cpu_vendor_os_gnu {
360 /*@owned@*/
361 const char * str;
362 /*@observer@*/
363 const char * cpu;
364 /*@observer@*/
365 const char * vendor;
366 /*@observer@*/
367 const char * os;
368 /*@observer@*/
369 const char * gnu;
370 } * CVOG_t;
371
374 static int parseCVOG(const char * str, CVOG_t *cvogp)
375 /*@modifies *cvogp @*/
376 {
377 CVOG_t cvog = xcalloc(1, sizeof(*cvog));
378 char * p, * pe;
379
380 cvog->str = p = xstrdup(str);
381 pe = p + strlen(p);
382 while (pe-- > p && isspace(*pe))
383 *pe = '\0';
384
385 cvog->cpu = p;
386 cvog->vendor = "unknown";
387 cvog->os = "unknown";
388 cvog->gnu = "";
389 while (*p && !(*p == '-' || isspace(*p)))
390 p++;
391 if (*p != '\0') *p++ = '\0';
392
393 cvog->vendor = p;
394 while (*p && !(*p == '-' || isspace(*p)))
395 p++;
396 if (*p != '-') {
397 if (*p != '\0') *p++ = '\0';
398 cvog->os = cvog->vendor;
399 cvog->vendor = "unknown";
400 } else {
401 if (*p != '\0') *p++ = '\0';
402
403 cvog->os = p;
404 while (*p && !(*p == '-' || isspace(*p)))
405 p++;
406 if (*p == '-') {
407 *p++ = '\0';
408
409 cvog->gnu = p;
410 while (*p && !(*p == '-' || isspace(*p)))
411 p++;
412 }
413 if (*p != '\0') *p++ = '\0';
414 }
415
416 if (cvogp)
417 *cvogp = cvog;
418 else {
419 cvog->str = _free(cvog->str);
420 cvog = _free(cvog);
421 }
422 return 0;
423 }
424
430 /*@-onlytrans@*/ /* XXX miRE array, not refcounted. */
431 static rpmRC rpmPlatform(const char * platform)
432 /*@globals nplatpat, platpat,
433 rpmGlobalMacroContext, h_errno, fileSystem, internalState @*/
434 /*@modifies nplatpat, platpat,
435 rpmGlobalMacroContext, fileSystem, internalState @*/
436 {
437 CVOG_t cvog = NULL;
438 rpmiob iob = NULL;
439 int init_platform = 0;
440 miRE mi_re = NULL;
441 int mi_nre = 0;
442 char * p, * pe;
443 rpmRC rc;
444 int xx;
445
446 rc = rpmiobSlurp(platform, &iob);
447
448 if (rc || iob == NULL) {
449 rc = RPMRC_FAIL;
450 goto exit;
451 }
452
453 p = (char *)iob->b;
454 for (pe = p; p && *p; p = pe) {
455 pe = strchr(p, '\n');
456 if (pe)
457 *pe++ = '\0';
458
459 while (*p && xisspace(*p))
460 p++;
461 if (*p == '\0' || *p == '#')
462 continue;
463
464 if (init_platform) {
465 char * t = p + strlen(p);
466 while (--t > p && xisspace(*t))
467 *t = '\0';
468 if (t > p) {
469 xx = mireAppend(RPMMIRE_REGEX, 0, p, NULL, &mi_re, &mi_nre);
470 }
471 continue;
472 }
473
474 if (!parseCVOG(p, &cvog) && cvog != NULL) {
475 addMacro(NULL, "_host_cpu", NULL, cvog->cpu, -1);
476 addMacro(NULL, "_host_vendor", NULL, cvog->vendor, -1);
477 addMacro(NULL, "_host_os", NULL, cvog->os, -1);
478 }
479
480 #if defined(RPM_VENDOR_OPENPKG) /* explicit-platform */
481 /* do not use vendor and GNU attribution */
482 p = rpmExpand("%{_host_cpu}-%{_host_os}", NULL);
483 #else
484 p = rpmExpand("%{_host_cpu}-%{_host_vendor}-%{_host_os}",
485 (cvog && *cvog->gnu ? "-" : NULL),
486 (cvog ? cvog->gnu : NULL), NULL);
487 #endif
488 xx = mireAppend(RPMMIRE_STRCMP, 0, p, NULL, &mi_re, &mi_nre);
489 p = _free(p);
490
491 init_platform++;
492 }
493 rc = (init_platform ? RPMRC_OK : RPMRC_FAIL);
494
495 exit:
496 if (cvog) {
497 cvog->str = _free(cvog->str);
498 cvog = _free(cvog);
499 }
500 iob = rpmiobFree(iob);
501 if (rc == RPMRC_OK) {
502 platpat = mireFreeAll(platpat, nplatpat);
503 platpat = mi_re;
504 nplatpat = mi_nre;
505 }
506 return rc;
507 }
508 /*@=onlytrans@*/
509
510 #if defined(WITH_CPUINFO) && defined(WITH_SYCK)
511 static inline int rpmCpuinfoMatch(const char * feature, const char * EVR, rpmds cpuinfo)
512 {
513 rpmds cpufeature = rpmdsSingle(RPMTAG_REQUIRENAME, feature, EVR, RPMSENSE_PROBE);
514 int ret = rpmdsMatch(cpufeature, cpuinfo);
515
516 (void)rpmdsFree(cpufeature);
517 cpufeature = NULL;
518 return ret;
519 }
520
521 static rpmRC rpmCpuinfo(void)
522 {
523 rpmRC rc = RPMRC_FAIL;
524 const char *cpu, *_cpuinfo_path;
525 miRE mi_re = NULL;
526 int mi_nre = 0, xx, i;
527 CVOG_t cvog = NULL;
528 struct stat st;
529 char *yaml;
530 rpmsyck_node *tmp, node;
531 rpmSyck cpuinfoYaml;
532 FD_t fd;
533
534 _cpuinfo_path = rpmGetPath("%{?_rpmhome}%{!?_rpmhome:" USRLIBRPM "}/cpuinfo.yaml", NULL);
535 if(Stat(_cpuinfo_path, &st))
536 return rc;
537
538 fd = Fopen(_cpuinfo_path, "r");
539 _cpuinfo_path = _free(_cpuinfo_path);
540 yaml = xcalloc(st.st_size+1, 1);
541 Fread(yaml, 1, st.st_size, fd);
542 Fclose(fd);
543
544 xx = rpmdsCpuinfo(&cpuinfoP, NULL);
545 cpuinfoYaml = rpmSyckLoad(yaml);
546 yaml = _free(yaml);
547 htGetEntry(cpuinfoYaml->firstNode->value.map, "cpuinfo", &tmp, NULL, NULL);
548 node = tmp[0]->value.seq;
549
550 /* TODO: cleanup.. */
551 for(i = 0; node[i].type != T_END; i++) {
552 if(node[i].type == T_MAP) {
553 rpmsyck_node *tmp;
554 if(htHasEntry(node[i].value.map, "Family")) {
555 htGetEntry(node[i].value.map, "Family", &tmp, NULL, NULL);
556 const char *family = tmp[0]->value.key;
557 int j;
558 hashTable cpus = NULL;
559 if(rpmCpuinfoMatch(family, "", cpuinfoP)) {
560 if(htHasEntry(node[i].value.map, "Arch")) {
561 htGetEntry(node[i].value.map, "Arch", &tmp, NULL, NULL);
562 rpmsyck_node arch = tmp[0]->value.seq;
563 for(j = 0; arch[j].type != T_END; j++);
564 cpus = htCreate(j*2, 0, 0, NULL, NULL);
565 for(j = 0; arch[j].type != T_END; j++) {
566 if(htHasEntry(arch[j].value.map, "Extends")) {
567 if(htGetEntry(arch[j].value.map, "Extends", &tmp, NULL, NULL) &&
568 tmp[0]->type == T_STR && !htHasEntry(cpus, tmp[0]->value.key))
569 continue;
570 }
571 if(htHasEntry(arch[j].value.map, "Features")) {
572 htGetEntry(arch[j].value.map, "Features", &tmp, NULL, NULL);
573 rpmsyck_node features = tmp[0]->value.seq;
574 int k, match = 0;
575 for(k = 0; features[k].type != T_END; k++)
576 if(features[k].type == T_STR && !(match = rpmCpuinfoMatch(features[k].value.key, "", cpuinfoP))) break;
577 if(!match) continue;
578 }
579 if(htHasEntry(arch[j].value.map, "Name")) {
580 htGetEntry(arch[j].value.map, "Name", &tmp, NULL, NULL);
581 if(tmp[0]->type != T_STR) continue;
582 const char *name = tmp[0]->value.key;
583 rpmsyck_node alias = NULL;
584 if(htHasEntry(arch[j].value.map, "Alias")) {
585 htGetEntry(arch[j].value.map, "Alias", &tmp, NULL, NULL);
586 alias = tmp[0]->value.seq;
587 }
588 htAddEntry(cpus, name, alias);
589 }
590 }
591 }
592 if(htHasEntry(node[i].value.map, "Priority")) {
593 htGetEntry(node[i].value.map, "Priority", &tmp, NULL, NULL);
594 rpmsyck_node priority = tmp[0]->value.seq;
595 int j;
596 for(j = 0; priority[j].type != T_END; j++)
597 if(htHasEntry(cpus, priority[j].value.key)) {
598 xx = mireAppend(RPMMIRE_REGEX, 0, priority[j].value.key, NULL, &mi_re, &mi_nre);
599 htGetEntry(cpus, priority[j].value.key, &tmp, NULL, NULL);
600 if(tmp[0]) {
601 rpmsyck_node alias = tmp[0];
602 int k;
603 for(k = 0; alias[k].type != T_END; k++)
604 xx = mireAppend(RPMMIRE_REGEX, 0, alias[k].value.key, NULL, &mi_re, &mi_nre);
605 }
606 }
607 }
608 }
609 if(cpus) cpus = htFree(cpus);
610 }
611 }
612 }
613
614 cpuinfoYaml = rpmSyckFree(cpuinfoYaml);
615
616 xx = mireAppend(RPMMIRE_REGEX, 0, "noarch", NULL, &mi_re, &mi_nre);
617
618 cpu = mi_re[0].pattern;
619 if(cpu != NULL)
620 {
621 if (!parseCVOG(cpu, &cvog) && cvog != NULL) {
622 addMacro(NULL, "_host_cpu", NULL, cvog->cpu, -1);
623 addMacro(NULL, "_host_vendor", NULL, cvog->vendor, -1);
624 addMacro(NULL, "_host_os", NULL, cvog->os, -1);
625 }
626 if (cvog) {
627 cvog->str = _free(cvog->str);
628 cvog = _free(cvog);
629 }
630
631 rc = RPMRC_OK;
632 if (rc == RPMRC_OK) {
633 platpat = mireFreeAll(platpat, nplatpat);
634 platpat = mi_re;
635 nplatpat = mi_nre;
636 }
637
638 }
639 return rc;
640 }
641 #endif
642
643 /*@-onlytrans@*/ /* XXX miRE array, not refcounted. */
644 int rpmPlatformScore(const char * platform, void * mi_re, int mi_nre)
645 {
646 miRE mire;
647 int i;
648
649 if (mi_re == NULL) {
650 mi_re = platpat;
651 mi_nre = nplatpat;
652 }
653
654 if ((mire = mi_re) != NULL)
655 for (i = 0; i < mi_nre; i++) {
656 if (mireRegexec(mire + i, platform, 0) >= 0)
657 return (i + 1);
658 }
659 return 0;
660 }
661 /*@=onlytrans@*/
662
665 static void defaultMachine(/*@out@*/ const char ** arch,
666 /*@out@*/ const char ** os)
667 /*@globals rpmGlobalMacroContext, h_errno, fileSystem, internalState @*/
668 /*@modifies *arch, *os, rpmGlobalMacroContext, fileSystem, internalState @*/
669 {
670 #if defined(RPM_VENDOR_OPENPKG) /* larger-utsname */
671 /* utsname fields on some platforms (like HP-UX) are very small
672 (just about 8 characters). This is too small for OpenPKG, so cheat! */
673 static struct utsname un_real;
674 static struct {
675 char sysname[32];
676 char nodename[32];
677 char release[32];
678 char version[32];
679 char machine[32];
680 } un;
681 #else
682 static struct utsname un;
683 #endif
684 static int gotDefaults = 0;
685 int rc;
686
687 while (!gotDefaults) {
688 #if defined(RPM_VENDOR_WINDRIVER)
689 const char * _platform = rpmGetPath(__etcrpm, "/platform", NULL);
690 #else
691 const char * _platform = platform;
692 #endif
693 CVOG_t cvog = NULL;
694 #if defined(RPM_VENDOR_OPENPKG) /* larger-utsname */
695 const char *cp;
696 #endif
697 #if defined(RPM_VENDOR_OPENPKG) /* larger-utsname */
698 /* utsname fields on some platforms (like HP-UX) are very small
699 (just about 8 characters). This is too small for OpenPKG, so cheat! */
700 rc = uname(&un_real);
701 strncpy(un.sysname, un_real.sysname, sizeof(un.sysname)); un.sysname [sizeof(un.sysname) -1] = '\0';
702 strncpy(un.nodename, un_real.nodename, sizeof(un.nodename)); un.nodename[sizeof(un.nodename)-1] = '\0';
703 strncpy(un.release, un_real.release, sizeof(un.release)); un.release [sizeof(un.release) -1] = '\0';
704 strncpy(un.version, un_real.version, sizeof(un.version)); un.version [sizeof(un.version) -1] = '\0';
705 strncpy(un.machine, un_real.machine, sizeof(un.machine)); un.machine [sizeof(un.machine) -1] = '\0';
706 #else
707 rc = uname(&un);
708 #endif
709 if (rc < 0) return;
710
711 #if defined(RPM_VENDOR_OPENPKG) /* platform-major-minor-only */
712 /* Reduce the platform version to major and minor version numbers */
713 {
714 char *cp;
715 char *cpR;
716 int n;
717 cpR = un.release;
718 if ((n = strcspn(cpR, "0123456789")) > 0)
719 cpR += n;
720 if ((n = strspn(cpR, "0123456789.")) > 0) {
721 /* terminate after "N.N.N...." prefix */
722 cpR[n] = '\0';
723 /* shorten to "N.N" if longer */
724 if ((cp = strchr(cpR, '.')) != NULL) {
725 if ((cp = strchr(cp+1, '.')) != NULL)
726 *cp = '\0';
727 }
728 strcat(un.sysname, cpR);
729 }
730 /* fix up machine hardware name containing white-space as it
731 happens to be on Power Macs running MacOS X */
732 if (!strncmp(un.machine, "Power Macintosh", 15))
733 sprintf(un.machine, "powerpc");
734 }
735 #endif
736
737 if (!strncmp(un.machine, "Power Macintosh", 15)) {
738 sprintf(un.machine, "ppc");
739 }
740
741 #if defined(RPM_VENDOR_OPENPKG) /* explicit-platform */
742 /* allow the path to the "platforms" file be overridden under run-time */
743 cp = rpmExpand("%{?__platform}", NULL);
744 if (cp == NULL || cp[0] == '\0')
745 cp = _platform;
746 if (rpmPlatform(cp) == RPMRC_OK) {
747 #elif defined(WITH_CPUINFO) && defined(WITH_SYCK)
748 if (rpmPlatform(_platform) == RPMRC_OK || rpmCpuinfo() == RPMRC_OK) {
749 #else
750 if (rpmPlatform(_platform) == RPMRC_OK) {
751 #endif
752 const char * s;
753 gotDefaults = 1;
754 s = rpmExpand("%{?_host_cpu}", NULL);
755 if (s && *s != '\0') {
756 strncpy(un.machine, s, sizeof(un.machine));
757 un.machine[sizeof(un.machine)-1] = '\0';
758 }
759 s = _free(s);
760 s = rpmExpand("%{?_host_os}", NULL);
761 if (s && *s != '\0') {
762 strncpy(un.sysname, s, sizeof(un.sysname));
763 un.sysname[sizeof(un.sysname)-1] = '\0';
764 }
765 s = _free(s);
766 }
767
768 #if defined(RPM_VENDOR_OPENPKG) /* explicit-platform */
769 /* cleanup after above processing */
770 if (cp != NULL && cp != _platform)
771 cp = _free(cp);
772 #endif
773 #if defined(RPM_VENDOR_WINDRIVER)
774 _platform = _free(_platform);
775 #endif
776
777 if (configTarget && !parseCVOG(configTarget, &cvog) && cvog != NULL) {
778 gotDefaults = 1;
779 if (cvog->cpu && cvog->cpu[0] != '\0') {
780 strncpy(un.machine, cvog->cpu, sizeof(un.machine));
781 un.machine[sizeof(un.machine)-1] = '\0';
782 }
783 if (cvog->os && cvog->os[0] != '\0') {
784 strncpy(un.sysname, cvog->os, sizeof(un.sysname));
785 un.sysname[sizeof(un.sysname)-1] = '\0';
786 }
787 cvog->str = _free(cvog->str);
788 cvog = _free(cvog);
789 }
790 if (gotDefaults)
791 break;
792 gotDefaults = 1;
793 break;
794 }
795
796 if (arch) *arch = un.machine;
797 if (os) *os = un.sysname;
798 }
799
807 static void rpmSetTables(int archTable, int osTable)
808 /*@globals currTables, rpmGlobalMacroContext, h_errno,
809 fileSystem, internalState @*/
810 /*@modifies currTables, rpmGlobalMacroContext,
811 fileSystem, internalState @*/
812 {
813 const char * arch, * os;
814
815 defaultMachine(&arch, &os);
816
817 if (currTables[ARCH] != archTable) {
818 currTables[ARCH] = archTable;
819 rebuildCompatTables(ARCH, arch);
820 }
821
822 if (currTables[OS] != osTable) {
823 currTables[OS] = osTable;
824 rebuildCompatTables(OS, os);
825 }
826 }
827
828 static void rpmSetMachine(const char * arch, const char * os)
829 /*@globals current, rpmGlobalMacroContext, h_errno,
830 fileSystem, internalState @*/
831 /*@modifies current, rpmGlobalMacroContext,
832 fileSystem, internalState @*/
833 {
834 if (arch == NULL) {
835 /*@i@*/ defaultMachine(&arch, NULL);
836 if (tables[currTables[ARCH]].hasTranslate)
837 arch = lookupInDefaultTable(arch,
838 tables[currTables[ARCH]].defaults,
839 tables[currTables[ARCH]].defaultsLength);
840 }
841 assert(arch != NULL);
842
843 if (os == NULL) {
844 /*@i@*/ defaultMachine(NULL, &os);
845 if (tables[currTables[OS]].hasTranslate)
846 os = lookupInDefaultTable(os,
847 tables[currTables[OS]].defaults,
848 tables[currTables[OS]].defaultsLength);
849 }
850 assert(os != NULL);
851
852
853 if (!current[ARCH] || strcmp(arch, current[ARCH])) {
854 current[ARCH] = _free(current[ARCH]);
855 current[ARCH] = xstrdup(arch);
856 rebuildCompatTables(ARCH, arch);
857 }
858
859 if (!current[OS] || strcmp(os, current[OS])) {
860 char * t = xstrdup(os);
861 current[OS] = _free(current[OS]);
862 if (!strcmp(t, "linux"))
863 *t = 'L';
864 current[OS] = t;
865 rebuildCompatTables(OS, os);
866 }
867 }
868
869 static void getMachineInfo(int type, /*@null@*/ /*@out@*/ const char ** name,
870 /*@null@*/ /*@out@*/int * num)
871 /*@modifies *name, *num @*/
872 {
873 canonEntry canon;
874 int which = currTables[type];
875
876 /* use the normal canon tables, even if we're looking up build stuff */
877 if (which >= 2) which -= 2;
878
879 canon = lookupInCanonTable(current[type],
880 tables[which].canons,
881 tables[which].canonsLength);
882
883 if (canon) {
884 if (num) *num = canon->num;
885 if (name) *name = canon->short_name;
886 } else {
887 if (num) *num = 255;
888 #if defined(WITH_CPUINFO)
889 if (name)
890 {
891 if(type == ARCH)
892 {
893 int i, j, n;
894 ARGV_t archs = NULL;
895 char *pref = rpmExpand("%{?_prefer_target_cpu}", NULL);
896
897 (void) argvSplit(&archs, pref, " ");
898 for(i = 0, n = argvCount(archs); (i < n && !*name); i++)
899 if((j = rpmPlatformScore(archs[i], platpat, nplatpat)) > 0)
900 *name = ((miRE)platpat)[j-1].pattern;
901
902 archs = argvFree(archs);
903 pref = _free(pref);
904 }
905 if(!*name) *name = current[type];
906 }
907 #else
908 if (name) *name = current[type];
909 #endif
910 }
911 }
912
913 static void rpmRebuildTargetVars(const char ** target, const char ** canontarget)
914 {
915
916 char *ca = NULL, *co = NULL, *ct = NULL;
917 int x;
918
919 /* Rebuild the compat table to recalculate the current target arch. */
920
921 rpmSetMachine(NULL, NULL);
922 rpmSetTables(RPM_MACHTABLE_INSTARCH, RPM_MACHTABLE_INSTOS);
923 rpmSetTables(RPM_MACHTABLE_BUILDARCH, RPM_MACHTABLE_BUILDOS);
924
925 if (target && *target) {
926 char *c;
927 /* Set arch and os from specified build target */
928 ca = xstrdup(*target);
929 if ((c = strchr(ca, '-')) != NULL) {
930 *c++ = '\0';
931
932 if ((co = strrchr(c, '-')) == NULL) {
933 co = c;
934 } else {
935 if (!xstrcasecmp(co, "-gnu"))
936 *co = '\0';
937 if ((co = strrchr(c, '-')) == NULL)
938 co = c;
939 else
940 co++;
941 }
942 if (co != NULL) co = xstrdup(co);
943 }
944 } else {
945 const char *a = NULL;
946 const char *o = NULL;
947 /* Set build target from rpm arch and os */
948 getMachineInfo(ARCH, &a, NULL);
949 ca = (a) ? xstrdup(a) : NULL;
950 getMachineInfo(OS, &o, NULL);
951 co = (o) ? xstrdup(o) : NULL;
952 }
953
954 /* If still not set, Set target arch/os from default uname(2) values */
955 if (ca == NULL) {
956 const char *a = NULL;
957 defaultMachine(&a, NULL);
958 ca = (a) ? xstrdup(a) : NULL;
959 }
960 if (ca != NULL)
961 for (x = 0; ca[x] != '\0'; x++)
962 ca[x] = (char)xtolower(ca[x]);
963
964 if (co == NULL) {
965 const char *o = NULL;
966 defaultMachine(NULL, &o);
967 co = (o) ? xstrdup(o) : NULL;
968 }
969 if (co != NULL)
970 for (x = 0; co[x] != '\0'; x++)
971 co[x] = (char)xtolower(co[x]);
972
973 /* XXX For now, set canonical target to arch-os */
974 if (ct == NULL) {
975 ct = xmalloc(strlen(ca) + sizeof("-") + strlen(co));
976 sprintf(ct, "%s-%s", ca, co);
977 }
978
979 /*
980 * XXX All this macro pokery/jiggery could be achieved by doing a delayed
981 * rpmInitMacros(NULL, PER-PLATFORM-MACRO-FILE-NAMES);
982 */
983 delMacro(NULL, "_target");
984 addMacro(NULL, "_target", NULL, ct, RMIL_RPMRC);
985 delMacro(NULL, "_target_cpu");
986 addMacro(NULL, "_target_cpu", NULL, ca, RMIL_RPMRC);
987 delMacro(NULL, "_target_os");
988 addMacro(NULL, "_target_os", NULL, co, RMIL_RPMRC);
989
990 if (canontarget)
991 *canontarget = ct;
992 else
993 ct = _free(ct);
994 ca = _free(ca);
995 /*@-usereleased@*/
996 co = _free(co);
997 /*@=usereleased@*/
998 }
999
1000 void rpmFreeRpmrc(void)
1001 /*@globals current, tables, defaultsInitialized @*/
1002 /*@modifies current, tables, defaultsInitialized @*/
1003 {
1004 int i, j, k;
1005
1006 (void)mireFreeAll(platpat, nplatpat);
1007 platpat = NULL;
1008 nplatpat = 0;
1009
1010 for (i = 0; i < RPM_MACHTABLE_COUNT; i++) {
1011 tableType t;
1012 t = tables + i;
1013 if (t->equiv.list) {
1014 for (j = 0; j < t->equiv.count; j++)
1015 t->equiv.list[j].name = _free(t->equiv.list[j].name);
1016 t->equiv.list = _free(t->equiv.list);
1017 t->equiv.count = 0;
1018 }
1019 if (t->cache.cache) {
1020 for (j = 0; j < t->cache.size; j++) {
1021 machCacheEntry e;
1022 e = t->cache.cache + j;
1023 if (e == NULL)
1024 /*@innercontinue@*/ continue;
1025 e->name = _free(e->name);
1026 if (e->equivs) {
1027 for (k = 0; k < e->count; k++)
1028 e->equivs[k] = _free(e->equivs[k]);
1029 e->equivs = _free(e->equivs);
1030 }
1031 }
1032 t->cache.cache = _free(t->cache.cache);
1033 t->cache.size = 0;
1034 }
1035 if (t->defaults) {
1036 for (j = 0; j < t->defaultsLength; j++) {
1037 t->defaults[j].name = _free(t->defaults[j].name);
1038 t->defaults[j].defName = _free(t->defaults[j].defName);
1039 }
1040 t->defaults = _free(t->defaults);
1041 t->defaultsLength = 0;
1042 }
1043 if (t->canons) {
1044 for (j = 0; j < t->canonsLength; j++) {
1045 t->canons[j].name = _free(t->canons[j].name);
1046 t->canons[j].short_name = _free(t->canons[j].short_name);
1047 }
1048 t->canons = _free(t->canons);
1049 t->canonsLength = 0;
1050 }
1051 }
1052
1053 current[OS] = _free(current[OS]);
1054 current[ARCH] = _free(current[ARCH]);
1055 defaultsInitialized = 0;
1056 /*@-globstate -nullstate@*/ /* FIX: platpat/current may be NULL */
1057 return;
1058 /*@=globstate =nullstate@*/
1059 }
1060
1065 static int rpmReadRC(const char *macrofiles)
1066 /*@globals defaultsInitialized,
1067 rpmGlobalMacroContext, rpmCLIMacroContext, h_errno,
1068 fileSystem, internalState @*/
1069 /*@modifies defaultsInitialized, rpmGlobalMacroContext,
1070 fileSystem, internalState @*/
1071 {
1072 int rc = 0;
1073
1074 if (!defaultsInitialized) {
1075 setDefaults();
1076 defaultsInitialized = 1;
1077 }
1078
1079 /* Read macro files. */
1080 { const char *mfpath = rpmExpand(macrofiles, NULL);
1081
1082 if (mfpath != NULL) {
1083 rpmInitMacros(NULL, mfpath);
1084 mfpath = _free(mfpath);
1085 }
1086 }
1087
1088 return rc;
1089 }
1090
1091 int rpmReadConfigFiles(/*@unused@*/ const char * file,
1092 const char * target)
1093 /*@globals configTarget, rpmMacrofiles @*/
1094 /*@modifies configTarget @*/
1095 {
1096 mode_t mode = 0022;
1097
1098 #ifdef PREMACROFILES
1099 if (rpmReadRC(PREMACROFILES)) return -1;
1100 #endif
1101
1102 /* Reset umask to its default umask(2) value. */
1103 mode = umask(mode);
1104
1105 configTarget = target;
1106
1107 /* Preset target macros */
1108 /*@-nullstate@*/ /* FIX: target can be NULL */
1109 rpmRebuildTargetVars(&target, NULL);
1110
1111 /* Read the files */
1112 /*@-globs@*/
1113 if (rpmReadRC(rpmMacrofiles)) return -1;
1114 /*@=globs@*/
1115
1116 /* Reset target macros */
1117 rpmRebuildTargetVars(&target, NULL);
1118 /*@=nullstate@*/
1119
1120 /* Finally set target platform */
1121 { const char *cpu = rpmExpand("%{_target_cpu}", NULL);
1122 const char *os = rpmExpand("%{_target_os}", NULL);
1123 rpmSetMachine(cpu, os);
1124
1125 cpu = _free(cpu);
1126 os = _free(os);
1127 }
1128 configTarget = NULL;
1129
1130 /* Force Lua state initialization */
1131 #ifdef WITH_LUA
1132 (void)rpmluaGetPrintBuffer(NULL);
1133 #if defined(RPM_VENDOR_OPENPKG) /* rpm-lua-extensions-based-on-rpm-lib-functionality */
1134 (void)rpmluaextActivate(rpmluaGetGlobalState());
1135 #endif /* RPM_VENDOR_OPENPKG */
1136 #endif
1137
1138 return 0;
1139 }
1140
1141 int rpmShowRC(FILE * fp)
1142 {
1143 rpmds ds = NULL;
1144 int i;
1145 machEquivTable equivTable;
1146 int xx;
1147 miRE mire;
1148
1149 /* the caller may set the build arch which should be printed here */
1150 fprintf(fp, "ARCHITECTURE AND OS:\n");
1151 fprintf(fp, "build arch : %s\n", current[ARCH]);
1152
1153 fprintf(fp, "compatible build archs:");
1154 equivTable = &tables[RPM_MACHTABLE_BUILDARCH].equiv;
1155 for (i = 0; i < equivTable->count; i++)
1156 fprintf(fp," %s", equivTable->list[i].name);
1157 fprintf(fp, "\n");
1158
1159 fprintf(fp, "build os : %s\n", current[OS]);
1160
1161 fprintf(fp, "compatible build os's :");
1162 equivTable = &tables[RPM_MACHTABLE_BUILDOS].equiv;
1163 for (i = 0; i < equivTable->count; i++)
1164 fprintf(fp," %s", equivTable->list[i].name);
1165 fprintf(fp, "\n");
1166
1167 fprintf(fp, "install arch : %s\n", current[ARCH]);
1168 fprintf(fp, "install os : %s\n", current[OS]);
1169
1170 fprintf(fp, "compatible archs :");
1171 for (mire = platpat, i = 0; i < nplatpat; i++)
1172 fprintf(fp, " %s", mire[i].pattern);
1173 fprintf(fp, "\n");
1174
1175 fprintf(fp, "compatible os's :");
1176 equivTable = &tables[RPM_MACHTABLE_INSTOS].equiv;
1177 for (i = 0; i < equivTable->count; i++)
1178 fprintf(fp," %s", equivTable->list[i].name);
1179 fprintf(fp, "\n");
1180
1181 { const char * s = rpmExpand("%{?optflags}", NULL);
1182 fprintf(fp, "%-21s : %s\n", "optflags", ((s && *s) ? s : "(not set)"));
1183 s = _free(s);
1184
1185 #ifdef WITH_LUA
1186 fprintf(fp, "\nLUA MODULES:\n");
1187 /*@-globs@*/
1188 s = rpmExpand(rpmluaFiles, NULL);
1189 /*@=globs@*/
1190 fprintf(fp, "%-21s : %s\n", "luafiles", ((s && *s) ? s : "(not set)"));
1191 s = _free(s);
1192 /*@-globs@*/
1193 s = rpmExpand(rpmluaPath, NULL);
1194 /*@=globs@*/
1195 fprintf(fp, "%-21s : %s\n", "luapath", ((s && *s) ? s : "(not set)"));
1196 s = _free(s);
1197 #endif
1198
1199 fprintf(fp, "\nMACRO DEFINITIONS:\n");
1200 /*@-globs@*/
1201 s = rpmExpand(rpmMacrofiles, NULL);
1202 /*@=globs@*/
1203 fprintf(fp, "%-21s : %s\n", "macrofiles", ((s && *s) ? s : "(not set)"));
1204 s = _free(s);
1205 }
1206
1207 if (rpmIsVerbose()) {
1208 rpmPRCO PRCO = rpmdsNewPRCO(NULL);
1209 xx = rpmdsSysinfo(PRCO, NULL);
1210 ds = rpmdsFromPRCO(PRCO, RPMTAG_PROVIDENAME);
1211 if (ds != NULL) {
1212 const char * fn = (_sysinfo_path ? _sysinfo_path : "/etc/rpm/sysinfo");
1213 fprintf(fp, _("Configured system provides (from %s):\n"), fn);
1214 ds = rpmdsInit(ds);
1215 while (rpmdsNext(ds) >= 0) {
1216 const char * DNEVR = rpmdsDNEVR(ds);
1217 if (DNEVR != NULL)
1218 fprintf(fp, " %s\n", DNEVR+2);
1219 }
1220 (void)rpmdsFree(ds);
1221 ds = NULL;
1222 fprintf(fp, "\n");
1223 }
1224 PRCO = rpmdsFreePRCO(PRCO);
1225 }
1226
1227 if (rpmIsVerbose()) {
1228 fprintf(fp, _("Features provided by rpmlib installer:\n"));
1229 xx = rpmdsRpmlib(&ds, NULL);
1230 ds = rpmdsInit(ds);
1231 while (rpmdsNext(ds) >= 0) {
1232 const char * DNEVR = rpmdsDNEVR(ds);
1233 if (DNEVR != NULL)
1234 fprintf(fp, " %s\n", DNEVR+2);
1235 }
1236 (void)rpmdsFree(ds);
1237 ds = NULL;
1238 fprintf(fp, "\n");
1239
1240 if(cpuinfoP == NULL)
1241 xx = rpmdsCpuinfo(&cpuinfoP, NULL);
1242 if (cpuinfoP != NULL) {
1243 #if defined(WITH_CPUINFO)
1244 const char * fn = "libcpuinfo";
1245 #else
1246 const char * fn = (_cpuinfo_path ? _cpuinfo_path : "/proc/cpuinfo");
1247 #endif
1248 fprintf(fp,
1249 _("Features provided by current cpuinfo (from %s):\n"), fn);
1250 cpuinfoP = rpmdsInit(cpuinfoP);
1251 while (rpmdsNext(cpuinfoP) >= 0) {
1252 const char * DNEVR = rpmdsDNEVR(cpuinfoP);
1253 if (DNEVR != NULL)
1254 fprintf(fp, " %s\n", DNEVR+2);
1255 }
1256 (void)rpmdsFree(cpuinfoP);
1257 cpuinfoP = NULL;
1258
1259 fprintf(fp, "\n");
1260 }
1261 }
1262
1263 if (rpmIsDebug()) {
1264 xx = rpmdsGetconf(&ds, NULL);
1265 if (ds != NULL) {
1266 fprintf(fp,
1267 _("Features provided by current getconf:\n"));
1268 ds = rpmdsInit(ds);
1269 while (rpmdsNext(ds) >= 0) {
1270 const char * DNEVR = rpmdsDNEVR(ds);
1271 if (DNEVR != NULL)
1272 fprintf(fp, " %s\n", DNEVR+2);
1273 }
1274 (void)rpmdsFree(ds);
1275 ds = NULL;
1276 fprintf(fp, "\n");
1277 }
1278
1279 xx = rpmdsUname(&ds, NULL);
1280 if (ds != NULL) {
1281 fprintf(fp,
1282 _("Features provided by current uname:\n"));
1283 ds = rpmdsInit(ds);
1284 while (rpmdsNext(ds) >= 0) {
1285 const char * DNEVR = rpmdsDNEVR(ds);
1286 if (DNEVR != NULL)
1287 fprintf(fp, " %s\n", DNEVR+2);
1288 }
1289 (void)rpmdsFree(ds);
1290 ds = NULL;
1291 fprintf(fp, "\n");
1292 }
1293 }
1294
1295 rpmDumpMacroTable(NULL, fp);
1296
1297 return 0;
1298 }