11 #if HAVE_SYS_UTSNAME_H
12 #include <sys/utsname.h>
15 #include <ctype.h> /* XXX for /etc/rpm/platform contents */
17 #if HAVE_SYS_SYSTEMCFG_H
18 #include <sys/systemcfg.h>
20 #define __power_pc() 0
23 #include <rpm/rpmlib.h> /* RPM_MACTABLE*, Rc-prototypes */
24 #include <rpm/rpmmacro.h>
25 #include <rpm/rpmfileutil.h>
26 #include <rpm/rpmstring.h>
27 #include <rpm/rpmlog.h>
29 #include "rpmio/rpmlua.h"
30 #include "rpmio/rpmio_internal.h" /* XXX for rpmioSlurp */
32 #include "lib/rpmliblua.h"
36 static const char * defrcfiles = NULL;
37 const char * macrofiles = NULL;
39 static const char * const platform = SYSCONFDIR "/rpm/platform";
40 static char ** platpat = NULL;
41 static int nplatpat = 0;
43 typedef char * cptr_t;
45 typedef struct machCacheEntry_s {
52 typedef struct machCache_s {
57 typedef struct machEquivInfo_s {
62 typedef struct machEquivTable_s {
69 /* eventually, this arch will be replaced with a generic condition */
71 struct rpmvarValue * next;
82 static struct rpmat_s {
87 typedef struct defaultEntry_s {
92 typedef struct canonEntry_s {
98 /* tags are 'key'canon, 'key'translate, 'key'compat
100 * for giggles, 'key'_canon, 'key'_compat, and 'key'_canon will also work
102 typedef struct tableType_s {
105 const int hasTranslate;
106 struct machEquivTable_s equiv;
107 struct machCache_s cache;
108 defaultEntry defaults;
114 static struct tableType_s tables[RPM_MACHTABLE_COUNT] = {
117 { "buildarch", 0, 1 },
121 /* XXX get rid of this stuff... */
122 /* Stuff for maintaining "variables" like SOURCEDIR, BUILDDIR, etc */
123 #define RPMVAR_OPTFLAGS 3
124 #define RPMVAR_ARCHCOLOR 42
125 #define RPMVAR_INCLUDE 43
126 #define RPMVAR_MACROFILES 49
128 #define RPMVAR_NUM 55 /* number of RPMVAR entries */
130 /* this *must* be kept in alphabetical order */
131 /* The order of the flags is archSpecific, macroize, localize */
133 static const struct rpmOption optionTable[] = {
134 { "archcolor", RPMVAR_ARCHCOLOR, 1, 0, 0 },
135 { "include", RPMVAR_INCLUDE, 0, 0, 2 },
136 { "macrofiles", RPMVAR_MACROFILES, 0, 0, 1 },
137 { "optflags", RPMVAR_OPTFLAGS, 1, 1, 0 },
140 static const size_t optionTableSize = sizeof(optionTable) / sizeof(*optionTable);
145 static cptr_t current[2];
147 static int currTables[2] = { RPM_MACHTABLE_INSTOS, RPM_MACHTABLE_INSTARCH };
149 static struct rpmvarValue values[RPMVAR_NUM];
151 static int defaultsInitialized = 0;
154 static rpmRC doReadRC(const char * urlfn);
156 static void rpmSetVarArch(int var, const char * val,
159 static void rebuildCompatTables(int type, const char * name);
161 static void rpmRebuildTargetVars(const char **target, const char ** canontarget);
163 static int optionCompare(const void * a, const void * b)
165 return rstrcasecmp(((const struct rpmOption *) a)->name,
166 ((const struct rpmOption *) b)->name);
169 static machCacheEntry
170 machCacheFindEntry(const machCache cache, const char * key)
174 for (i = 0; i < cache->size; i++)
175 if (rstreq(cache->cache[i].name, key)) return cache->cache + i;
180 static int machCompatCacheAdd(char * name, const char * fn, int linenum,
183 machCacheEntry entry = NULL;
189 while (*name && risspace(*name)) name++;
192 while (*chptr && *chptr != ':') chptr++;
194 rpmlog(RPMLOG_ERR, _("missing second ':' at %s:%d\n"), fn, linenum);
196 } else if (chptr == name) {
197 rpmlog(RPMLOG_ERR, _("missing architecture name at %s:%d\n"), fn,
202 while (*chptr == ':' || risspace(*chptr)) chptr--;
205 while (*equivs && risspace(*equivs)) equivs++;
211 entry = machCacheFindEntry(cache, name);
213 for (i = 0; i < entry->count; i++)
214 entry->equivs[i] = _free(entry->equivs[i]);
215 entry->equivs = _free(entry->equivs);
221 cache->cache = xrealloc(cache->cache,
222 (cache->size + 1) * sizeof(*cache->cache));
223 entry = cache->cache + cache->size++;
224 entry->name = xstrdup(name);
229 if (delEntry) return 0;
231 while ((chptr = strtok(equivs, " ")) != NULL) {
233 if (chptr[0] == '\0') /* does strtok() return "" ever?? */
236 entry->equivs = xrealloc(entry->equivs, sizeof(*entry->equivs)
237 * (entry->count + 1));
239 entry->equivs = xmalloc(sizeof(*entry->equivs));
241 entry->equivs[entry->count] = xstrdup(chptr);
249 machEquivSearch(const machEquivTable table, const char * name)
253 for (i = 0; i < table->count; i++)
254 if (!rstrcasecmp(table->list[i].name, name))
255 return table->list + i;
260 static void machAddEquiv(machEquivTable table, const char * name,
265 equiv = machEquivSearch(table, name);
268 table->list = xrealloc(table->list, (table->count + 1)
269 * sizeof(*table->list));
271 table->list = xmalloc(sizeof(*table->list));
273 table->list[table->count].name = xstrdup(name);
274 table->list[table->count++].score = distance;
278 static void machCacheEntryVisit(machCache cache,
279 machEquivTable table, const char * name, int distance)
281 machCacheEntry entry;
284 entry = machCacheFindEntry(cache, name);
285 if (!entry || entry->visited) return;
289 for (i = 0; i < entry->count; i++) {
290 machAddEquiv(table, entry->equivs[i], distance);
293 for (i = 0; i < entry->count; i++) {
294 machCacheEntryVisit(cache, table, entry->equivs[i], distance + 1);
298 static void machFindEquivs(machCache cache, machEquivTable table,
303 for (i = 0; i < cache->size; i++)
304 cache->cache[i].visited = 0;
306 while (table->count > 0) {
308 table->list[table->count].name = _free(table->list[table->count].name);
311 table->list = _free(table->list);
314 * We have a general graph built using strings instead of pointers.
315 * Yuck. We have to start at a point at traverse it, remembering how
316 * far away everything is.
318 /* FIX: table->list may be NULL. */
319 machAddEquiv(table, key, 1);
320 machCacheEntryVisit(cache, table, key, 2);
324 static rpmRC addCanon(canonEntry * table, int * tableLen, char * line,
325 const char * fn, int lineNum)
330 const char * tshort_name;
334 *table = xrealloc(*table, sizeof(**table) * (*tableLen));
336 t = & ((*table)[*tableLen - 2]);
338 tname = strtok(line, ": \t");
339 tshort_name = strtok(NULL, " \t");
340 s = strtok(NULL, " \t");
341 if (! (tname && tshort_name && s)) {
342 rpmlog(RPMLOG_ERR, _("Incomplete data line at %s:%d\n"),
346 if (strtok(NULL, " \t")) {
347 rpmlog(RPMLOG_ERR, _("Too many args in data line at %s:%d\n"),
352 tnum = strtoul(s, &s1, 10);
353 if ((*s1) || (s1 == s) || (tnum == ULONG_MAX)) {
354 rpmlog(RPMLOG_ERR, _("Bad arch/os number: %s (%s:%d)\n"), s,
359 t[0].name = xstrdup(tname);
360 t[0].short_name = (tshort_name ? xstrdup(tshort_name) : xstrdup(""));
363 /* From A B C entry */
364 /* Add B B C entry */
365 t[1].name = (tshort_name ? xstrdup(tshort_name) : xstrdup(""));
366 t[1].short_name = (tshort_name ? xstrdup(tshort_name) : xstrdup(""));
372 static rpmRC addDefault(defaultEntry * table, int * tableLen, char * line,
373 const char * fn, int lineNum)
378 *table = xrealloc(*table, sizeof(**table) * (*tableLen));
380 t = & ((*table)[*tableLen - 1]);
382 t->name = strtok(line, ": \t");
383 t->defName = strtok(NULL, " \t");
384 if (! (t->name && t->defName)) {
385 rpmlog(RPMLOG_ERR, _("Incomplete default line at %s:%d\n"),
389 if (strtok(NULL, " \t")) {
390 rpmlog(RPMLOG_ERR, _("Too many args in default line at %s:%d\n"),
395 t->name = xstrdup(t->name);
396 t->defName = (t->defName ? xstrdup(t->defName) : NULL);
401 static canonEntry lookupInCanonTable(const char * name,
402 const canonEntry table, int tableLen)
406 if (!rstreq(name, table[tableLen].name))
408 return &(table[tableLen]);
415 const char * lookupInDefaultTable(const char * name,
416 const defaultEntry table, int tableLen)
420 if (table[tableLen].name && rstreq(name, table[tableLen].name))
421 return table[tableLen].defName;
427 static void setDefaults(void)
429 const char *confdir = rpmConfigDir();
431 defrcfiles = rstrscat(NULL, confdir, "/rpmrc", ":",
432 confdir, "/" RPMCANONVENDOR "/rpmrc", ":",
433 SYSCONFDIR "/rpmrc", ":",
439 macrofiles = rstrscat(NULL, confdir, "/macros", ":",
440 confdir, "/macros.d/macros.*", ":",
441 confdir, "/platform/%{_target}/macros", ":",
442 confdir, "/fileattrs/*.attr", ":",
443 confdir, "/" RPMCANONVENDOR "/macros", ":",
444 SYSCONFDIR "/rpm/macros.*", ":",
445 SYSCONFDIR "/rpm/macros", ":",
446 SYSCONFDIR "/rpm/%{_target}/macros", ":",
447 "~/.rpmmacros", NULL);
450 macrofiles = MACROFILES;
454 /* FIX: se usage inconsistent, W2DO? */
455 static rpmRC doReadRC(const char * urlfn)
458 char *se, *next, *buf = NULL, *fn;
460 struct rpmOption searchOption, * option;
461 rpmRC rc = RPMRC_FAIL;
463 fn = rpmGetPath(urlfn, NULL);
464 if (rpmioSlurp(fn, (uint8_t **) &buf, NULL) || buf == NULL) {
469 while (*next != '\0') {
474 /* Find end-of-line. */
475 while (*se && *se != '\n') se++;
476 if (*se != '\0') *se++ = '\0';
479 /* Trim leading spaces */
480 while (*s && risspace(*s)) s++;
482 /* We used to allow comments to begin anywhere, but not anymore. */
483 if (*s == '#' || *s == '\0') continue;
485 /* Find end-of-keyword. */
487 while (*se && !risspace(*se) && *se != ':') se++;
491 while (*se && risspace(*se) && *se != ':') se++;
495 rpmlog(RPMLOG_ERR, _("missing ':' (found 0x%02x) at %s:%d\n"),
496 (unsigned)(0xff & *se), fn, linenum);
499 *se++ = '\0'; /* terminate keyword or option, point to value */
500 while (*se && risspace(*se)) se++;
502 /* Find keyword in table */
503 searchOption.name = s;
504 option = bsearch(&searchOption, optionTable, optionTableSize,
505 sizeof(optionTable[0]), optionCompare);
507 if (option) { /* For configuration variables ... */
508 const char *arch, *val;
512 rpmlog(RPMLOG_ERR, _("missing argument for %s at %s:%d\n"),
513 option->name, fn, linenum);
517 if (option->var == RPMVAR_INCLUDE) {
519 while (*se && !risspace(*se)) se++;
520 if (*se != '\0') *se = '\0';
523 rpmlog(RPMLOG_ERR, _("cannot open %s at %s:%d: %m\n"),
527 /* XXX don't save include value as var/macro */
531 if (option->archSpecific) {
533 while (*se && !risspace(*se)) se++;
536 _("missing architecture for %s at %s:%d\n"),
537 option->name, fn, linenum);
541 while (*se && risspace(*se)) se++;
544 _("missing argument for %s at %s:%d\n"),
545 option->name, fn, linenum);
552 /* Only add macros if appropriate for this arch */
553 if (option->macroize &&
554 (arch == NULL || rstreq(arch, current[ARCH]))) {
556 n = name = xmalloc(strlen(option->name)+2);
557 if (option->localize)
559 strcpy(n, option->name);
560 addMacro(NULL, name, NULL, val, RMIL_RPMRC);
563 rpmSetVarArch(option->var, val, arch);
566 } else { /* For arch/os compatibilty tables ... */
572 for (i = 0; i < RPM_MACHTABLE_COUNT; i++) {
573 if (rstreqn(tables[i].key, s, strlen(tables[i].key)))
577 if (i < RPM_MACHTABLE_COUNT) {
578 const char *rest = s + strlen(tables[i].key);
579 if (*rest == '_') rest++;
581 if (rstreq(rest, "compat")) {
582 if (machCompatCacheAdd(se, fn, linenum,
586 } else if (tables[i].hasTranslate &&
587 rstreq(rest, "translate")) {
588 if (addDefault(&tables[i].defaults,
589 &tables[i].defaultsLength,
593 } else if (tables[i].hasCanon &&
594 rstreq(rest, "canon")) {
595 if (addCanon(&tables[i].canons, &tables[i].canonsLength,
603 rpmlog(RPMLOG_ERR, _("bad option '%s' at %s:%d\n"),
621 static rpmRC rpmPlatform(const char * platform)
623 const char *cpu = NULL, *vendor = NULL, *os = NULL, *gnu = NULL;
626 int init_platform = 0;
630 rc = (rpmioSlurp(platform, &b, &blen) == 0) ? RPMRC_OK : RPMRC_FAIL;
632 if (rc || b == NULL || blen <= 0) {
638 for (pe = p; p && *p; p = pe) {
639 pe = strchr(p, '\n');
643 while (*p && isspace(*p))
645 if (*p == '\0' || *p == '#')
649 char * t = p + strlen(p);
651 while (--t > p && isspace(*t))
654 platpat = xrealloc(platpat, (nplatpat + 2) * sizeof(*platpat));
655 platpat[nplatpat] = xstrdup(p);
657 platpat[nplatpat] = NULL;
666 while (*p && !(*p == '-' || isspace(*p)))
668 if (*p != '\0') *p++ = '\0';
671 while (*p && !(*p == '-' || isspace(*p)))
674 if (*p != '\0') *p = '\0';
678 if (*p != '\0') *p++ = '\0';
681 while (*p && !(*p == '-' || isspace(*p)))
687 while (*p && !(*p == '-' || isspace(*p)))
690 if (*p != '\0') *p = '\0';
693 addMacro(NULL, "_host_cpu", NULL, cpu, -1);
694 addMacro(NULL, "_host_vendor", NULL, vendor, -1);
695 addMacro(NULL, "_host_os", NULL, os, -1);
697 platpat = xrealloc(platpat, (nplatpat + 2) * sizeof(*platpat));
698 platpat[nplatpat] = rpmExpand("%{_host_cpu}-%{_host_vendor}-%{_host_os}", (gnu && *gnu ? "-" : NULL), gnu, NULL);
700 platpat[nplatpat] = NULL;
704 rc = (init_platform ? RPMRC_OK : RPMRC_FAIL);
712 # if defined(__linux__) && defined(__i386__)
717 * Generic CPUID function
719 static inline void cpuid(unsigned int op, unsigned int *eax, unsigned int *ebx, unsigned int *ecx, unsigned int *edx)
724 "movl %%ebx, %%esi \n"
726 : "=a" (*eax), "=S" (*ebx), "=c" (*ecx), "=d" (*edx)
731 * CPUID functions returning a single datum
733 static inline unsigned int cpuid_eax(unsigned int op)
735 unsigned int tmp, val;
736 cpuid(op, &val, &tmp, &tmp, &tmp);
740 static inline unsigned int cpuid_ebx(unsigned int op)
742 unsigned int tmp, val;
743 cpuid(op, &tmp, &val, &tmp, &tmp);
747 static inline unsigned int cpuid_ecx(unsigned int op)
749 unsigned int tmp, val;
750 cpuid(op, &tmp, &tmp, &val, &tmp);
754 static inline unsigned int cpuid_edx(unsigned int op)
756 unsigned int tmp, val;
757 cpuid(op, &tmp, &tmp, &tmp, &val);
761 static sigjmp_buf jenv;
763 static inline void model3(int _unused)
768 static inline int RPMClass(void)
771 unsigned int tfms, junk, cap, capamd;
772 struct sigaction oldsa;
774 sigaction(SIGILL, NULL, &oldsa);
775 signal(SIGILL, model3);
777 if (sigsetjmp(jenv, 1)) {
778 sigaction(SIGILL, &oldsa, NULL);
782 if (cpuid_eax(0x000000000)==0) {
783 sigaction(SIGILL, &oldsa, NULL);
787 cpuid(0x00000001, &tfms, &junk, &junk, &cap);
788 cpuid(0x80000001, &junk, &junk, &junk, &capamd);
792 sigaction(SIGILL, &oldsa, NULL);
798 /* CMOV supported? */
799 if (capamd & (1<<30))
800 return 7; /* 3DNOWEXT supported */
807 /* should only be called for model 6 CPU's */
808 static int is_athlon(void)
810 unsigned int eax, ebx, ecx, edx;
814 cpuid (0, &eax, &ebx, &ecx, &edx);
816 memset(vendor, 0, sizeof(vendor));
819 vendor[i] = (unsigned char) (ebx >>(8*i));
821 vendor[4+i] = (unsigned char) (edx >>(8*i));
823 vendor[8+i] = (unsigned char) (ecx >>(8*i));
825 if (!rstreqn(vendor, "AuthenticAMD", 12))
831 static int is_pentium3(void)
833 unsigned int eax, ebx, ecx, edx, family, model;
835 cpuid(0, &eax, &ebx, &ecx, &edx);
836 memset(vendor, 0, sizeof(vendor));
837 *((unsigned int *)&vendor[0]) = ebx;
838 *((unsigned int *)&vendor[4]) = edx;
839 *((unsigned int *)&vendor[8]) = ecx;
840 if (!rstreqn(vendor, "GenuineIntel", 12))
842 cpuid(1, &eax, &ebx, &ecx, &edx);
843 family = (eax >> 8) & 0x0f;
844 model = (eax >> 4) & 0x0f;
848 case 7: // Pentium III, Pentium III Xeon (model 7)
849 case 8: // Pentium III, Pentium III Xeon, Celeron (model 8)
851 case 10: // Pentium III Xeon (model A)
852 case 11: // Pentium III (model B)
858 static int is_pentium4(void)
860 unsigned int eax, ebx, ecx, edx, family, model;
862 cpuid(0, &eax, &ebx, &ecx, &edx);
863 memset(vendor, 0, sizeof(vendor));
864 *((unsigned int *)&vendor[0]) = ebx;
865 *((unsigned int *)&vendor[4]) = edx;
866 *((unsigned int *)&vendor[8]) = ecx;
867 if (!rstreqn(vendor, "GenuineIntel", 12))
869 cpuid(1, &eax, &ebx, &ecx, &edx);
870 family = (eax >> 8) & 0x0f;
871 model = (eax >> 4) & 0x0f;
875 case 0: // Pentium 4, Pentium 4 Xeon (0.18um)
876 case 1: // Pentium 4, Pentium 4 Xeon MP, Celeron (0.18um)
877 case 2: // Pentium 4, Mobile Pentium 4-M,
878 // Pentium 4 Xeon, Pentium 4 Xeon MP,
879 // Celeron, Mobile Celron (0.13um)
880 case 3: // Pentium 4, Celeron (0.09um)
886 static int is_geode(void)
888 unsigned int eax, ebx, ecx, edx, family, model;
890 memset(vendor, 0, sizeof(vendor));
892 cpuid(0, &eax, &ebx, &ecx, &edx);
893 memset(vendor, 0, sizeof(vendor));
894 *((unsigned int *)&vendor[0]) = ebx;
895 *((unsigned int *)&vendor[4]) = edx;
896 *((unsigned int *)&vendor[8]) = ecx;
897 if (!rstreqn(vendor, "AuthenticAMD", 12))
899 cpuid(1, &eax, &ebx, &ecx, &edx);
900 family = (eax >> 8) & 0x0f;
901 model = (eax >> 4) & 0x0f;
913 #if defined(__linux__)
915 * Populate rpmat structure with parsed info from /proc/self/auxv
917 static void parse_auxv(void)
919 static int oneshot = 1;
923 int fd = open("/proc/self/auxv", O_RDONLY);
926 rpmlog(RPMLOG_WARNING,
927 _("Failed to read auxiliary vector, /proc not mounted?\n"));
931 while (read(fd, &auxv, sizeof(auxv)) == sizeof(auxv)) {
937 rpmat.platform = strdup((char *) auxv.a_un.a_val);
940 rpmat.hwcap = auxv.a_un.a_val;
946 oneshot = 0; /* only try once even if it fails */
954 static void defaultMachine(const char ** arch,
957 static struct utsname un;
958 static int gotDefaults = 0;
963 #if defined(__linux__)
964 /* Populate rpmat struct with hw info */
968 while (!gotDefaults) {
969 if (!rpmPlatform(platform)) {
970 char * s = rpmExpand("%{_host_cpu}", NULL);
972 rstrlcpy(un.machine, s, sizeof(un.machine));
975 s = rpmExpand("%{_host_os}", NULL);
977 rstrlcpy(un.sysname, s, sizeof(un.sysname));
986 #if !defined(__linux__)
987 if (rstreq(un.sysname, "AIX")) {
988 strcpy(un.machine, __power_pc() ? "ppc" : "rs6000");
989 sprintf(un.sysname,"aix%s.%s", un.version, un.release);
991 else if(rstreq(un.sysname, "Darwin")) {
993 strcpy(un.machine, "ppc");
995 strcpy(un.machine, "i386");
998 else if (rstreq(un.sysname, "SunOS")) {
999 /* Solaris 2.x: n.x.x becomes n-3.x.x */
1000 sprintf(un.sysname, "solaris%1d%s", atoi(un.release)-3,
1001 un.release+1+(atoi(un.release)/10));
1003 /* Solaris on Intel hardware reports i86pc instead of i386
1004 * (at least on 2.6 and 2.8)
1006 if (rstreq(un.machine, "i86pc"))
1007 sprintf(un.machine, "i386");
1009 else if (rstreq(un.sysname, "HP-UX"))
1010 /*make un.sysname look like hpux9.05 for example*/
1011 sprintf(un.sysname, "hpux%s", strpbrk(un.release, "123456789"));
1012 else if (rstreq(un.sysname, "OSF1"))
1013 /*make un.sysname look like osf3.2 for example*/
1014 sprintf(un.sysname, "osf%s", strpbrk(un.release, "123456789"));
1015 #endif /* __linux__ */
1017 /* get rid of the hyphens in the sysname */
1018 for (chptr = un.machine; *chptr != '\0'; chptr++)
1019 if (*chptr == '/') *chptr = '-';
1021 # if defined(__MIPSEL__) || defined(__MIPSEL) || defined(_MIPSEL)
1023 strcpy(un.machine, "mipsel");
1024 # elif defined(__MIPSEB__) || defined(__MIPSEB) || defined(_MIPSEB)
1026 strcpy(un.machine, "mips");
1029 # if defined(__hpux) && defined(_SC_CPU_VERSION)
1031 # if !defined(CPU_PA_RISC1_2)
1032 # define CPU_PA_RISC1_2 0x211 /* HP PA-RISC1.2 */
1034 # if !defined(CPU_PA_RISC2_0)
1035 # define CPU_PA_RISC2_0 0x214 /* HP PA-RISC2.0 */
1037 int cpu_version = sysconf(_SC_CPU_VERSION);
1039 # if defined(CPU_HP_MC68020)
1040 if (cpu_version == CPU_HP_MC68020)
1041 strcpy(un.machine, "m68k");
1043 # if defined(CPU_HP_MC68030)
1044 if (cpu_version == CPU_HP_MC68030)
1045 strcpy(un.machine, "m68k");
1047 # if defined(CPU_HP_MC68040)
1048 if (cpu_version == CPU_HP_MC68040)
1049 strcpy(un.machine, "m68k");
1052 # if defined(CPU_PA_RISC1_0)
1053 if (cpu_version == CPU_PA_RISC1_0)
1054 strcpy(un.machine, "hppa1.0");
1056 # if defined(CPU_PA_RISC1_1)
1057 if (cpu_version == CPU_PA_RISC1_1)
1058 strcpy(un.machine, "hppa1.1");
1060 # if defined(CPU_PA_RISC1_2)
1061 if (cpu_version == CPU_PA_RISC1_2)
1062 strcpy(un.machine, "hppa1.2");
1064 # if defined(CPU_PA_RISC2_0)
1065 if (cpu_version == CPU_PA_RISC2_0)
1066 strcpy(un.machine, "hppa2.0");
1071 # if defined(__linux__) && defined(__sparc__)
1072 if (rstreq(un.machine, "sparc")) {
1073 #define PERS_LINUX 0x00000000
1074 #define PERS_LINUX_32BIT 0x00800000
1075 #define PERS_LINUX32 0x00000008
1077 extern int personality(unsigned long);
1080 oldpers = personality(PERS_LINUX_32BIT);
1081 if (oldpers != -1) {
1082 if (personality(PERS_LINUX) != -1) {
1084 if (rstreq(un.machine, "sparc64")) {
1085 strcpy(un.machine, "sparcv9");
1086 oldpers = PERS_LINUX32;
1089 personality(oldpers);
1092 # endif /* sparc*-linux */
1094 # if defined(__linux__) && defined(__powerpc__)
1097 if (!rstreq(un.machine, "ppc") &&
1098 sscanf(rpmat.platform, "power%d", &powerlvl) == 1 &&
1100 strcpy(un.machine, "ppc64p7");
1103 # endif /* ppc64*-linux */
1105 # if defined(__GNUC__) && defined(__alpha__)
1107 unsigned long amask, implver;
1108 register long v0 __asm__("$0") = -1;
1109 __asm__ (".long 0x47e00c20" : "=r"(v0) : "0"(v0));
1111 __asm__ (".long 0x47e03d80" : "=r"(v0));
1116 case 0: strcpy(un.machine, "alphaev5"); break;
1117 case 1: strcpy(un.machine, "alphaev56"); break;
1118 case 0x101: strcpy(un.machine, "alphapca56"); break;
1123 case 0x303: strcpy(un.machine, "alphaev6"); break;
1124 case 0x307: strcpy(un.machine, "alphaev67"); break;
1131 # if defined(__linux__) && defined(__i386__)
1133 char mclass = (char) (RPMClass() | '0');
1135 if ((mclass == '6' && is_athlon()) || mclass == '7')
1136 strcpy(un.machine, "athlon");
1137 else if (is_pentium4())
1138 strcpy(un.machine, "pentium4");
1139 else if (is_pentium3())
1140 strcpy(un.machine, "pentium3");
1141 else if (is_geode())
1142 strcpy(un.machine, "geode");
1143 else if (strchr("3456", un.machine[1]) && un.machine[1] != mclass)
1144 un.machine[1] = mclass;
1148 /* the uname() result goes through the arch_canon table */
1149 canon = lookupInCanonTable(un.machine,
1150 tables[RPM_MACHTABLE_INSTARCH].canons,
1151 tables[RPM_MACHTABLE_INSTARCH].canonsLength);
1153 rstrlcpy(un.machine, canon->short_name, sizeof(un.machine));
1155 canon = lookupInCanonTable(un.sysname,
1156 tables[RPM_MACHTABLE_INSTOS].canons,
1157 tables[RPM_MACHTABLE_INSTOS].canonsLength);
1159 rstrlcpy(un.sysname, canon->short_name, sizeof(un.sysname));
1164 if (arch) *arch = un.machine;
1165 if (os) *os = un.sysname;
1169 const char * rpmGetVarArch(int var, const char * arch)
1171 const struct rpmvarValue * next;
1173 if (arch == NULL) arch = current[ARCH];
1176 next = &values[var];
1178 if (next->arch && rstreq(next->arch, arch)) return next->value;
1183 next = values + var;
1184 while (next && next->arch) next = next->next;
1186 return next ? next->value : NULL;
1189 static const char *rpmGetVar(int var)
1191 return rpmGetVarArch(var, NULL);
1194 static void rpmSetVarArch(int var, const char * val, const char * arch)
1196 struct rpmvarValue * next = values + var;
1200 while (next->next) {
1201 if (next->arch && rstreq(next->arch, arch)) break;
1205 while (next->next) {
1206 if (!next->arch) break;
1211 if (next->arch && arch && rstreq(next->arch, arch)) {
1212 next->value = _free(next->value);
1213 next->arch = _free(next->arch);
1214 } else if (next->arch || arch) {
1215 next->next = xmalloc(sizeof(*next->next));
1223 next->value = _free(next->value);
1224 next->value = xstrdup(val);
1225 next->arch = (arch ? xstrdup(arch) : NULL);
1228 static void rpmSetTables(int archTable, int osTable)
1230 const char * arch, * os;
1232 defaultMachine(&arch, &os);
1234 if (currTables[ARCH] != archTable) {
1235 currTables[ARCH] = archTable;
1236 rebuildCompatTables(ARCH, arch);
1239 if (currTables[OS] != osTable) {
1240 currTables[OS] = osTable;
1241 rebuildCompatTables(OS, os);
1245 int rpmMachineScore(int type, const char * name)
1247 machEquivInfo info = NULL;
1249 info = machEquivSearch(&tables[type].equiv, name);
1250 return info ? info->score : 0;
1253 int rpmIsKnownArch(const char *name)
1255 canonEntry canon = lookupInCanonTable(name,
1256 tables[RPM_MACHTABLE_INSTARCH].canons,
1257 tables[RPM_MACHTABLE_INSTARCH].canonsLength);
1258 return (canon != NULL || rstreq(name, "noarch"));
1262 * Set current arch/os names.
1263 * NULL as argument is set to the default value (munged uname())
1264 * pushed through a translation table (if appropriate).
1265 * @deprecated Use addMacro to set _target_* macros.
1268 * @param arch arch name (or NULL)
1269 * @param os os name (or NULL)
1272 static void rpmSetMachine(const char * arch, const char * os)
1274 const char * host_cpu, * host_os;
1276 defaultMachine(&host_cpu, &host_os);
1280 if (tables[currTables[ARCH]].hasTranslate)
1281 arch = lookupInDefaultTable(arch,
1282 tables[currTables[ARCH]].defaults,
1283 tables[currTables[ARCH]].defaultsLength);
1285 if (arch == NULL) return; /* XXX can't happen */
1289 if (tables[currTables[OS]].hasTranslate)
1290 os = lookupInDefaultTable(os,
1291 tables[currTables[OS]].defaults,
1292 tables[currTables[OS]].defaultsLength);
1294 if (os == NULL) return; /* XXX can't happen */
1296 if (!current[ARCH] || !rstreq(arch, current[ARCH])) {
1297 current[ARCH] = _free(current[ARCH]);
1298 current[ARCH] = xstrdup(arch);
1299 rebuildCompatTables(ARCH, host_cpu);
1302 if (!current[OS] || !rstreq(os, current[OS])) {
1303 char * t = xstrdup(os);
1304 current[OS] = _free(current[OS]);
1306 * XXX Capitalizing the 'L' is needed to insure that old
1307 * XXX os-from-uname (e.g. "Linux") is compatible with the new
1308 * XXX os-from-platform (e.g "linux" from "sparc-*-linux").
1309 * XXX A copy of this string is embedded in headers and is
1310 * XXX used by rpmInstallPackage->{os,arch}Okay->rpmMachineScore->
1311 * XXX to verify correct arch/os from headers.
1313 if (rstreq(t, "linux"))
1317 rebuildCompatTables(OS, host_os);
1321 static void rebuildCompatTables(int type, const char * name)
1323 machFindEquivs(&tables[currTables[type]].cache,
1324 &tables[currTables[type]].equiv,
1328 static void getMachineInfo(int type, const char ** name,
1332 int which = currTables[type];
1334 /* use the normal canon tables, even if we're looking up build stuff */
1335 if (which >= 2) which -= 2;
1337 canon = lookupInCanonTable(current[type],
1338 tables[which].canons,
1339 tables[which].canonsLength);
1342 if (num) *num = canon->num;
1343 if (name) *name = canon->short_name;
1345 if (num) *num = 255;
1346 if (name) *name = current[type];
1348 if (tables[currTables[type]].hasCanon) {
1349 rpmlog(RPMLOG_WARNING, _("Unknown system: %s\n"), current[type]);
1350 rpmlog(RPMLOG_WARNING, _("Please contact %s\n"), PACKAGE_BUGREPORT);
1355 void rpmGetArchInfo(const char ** name, int * num)
1357 getMachineInfo(ARCH, name, num);
1360 int rpmGetArchColor(const char *arch)
1366 arch = lookupInDefaultTable(arch,
1367 tables[currTables[ARCH]].defaults,
1368 tables[currTables[ARCH]].defaultsLength);
1369 color = rpmGetVarArch(RPMVAR_ARCHCOLOR, arch);
1370 if (color == NULL) {
1374 color_i = strtol(color, &e, 10);
1375 if (!(e && *e == '\0')) {
1382 void rpmGetOsInfo(const char ** name, int * num)
1384 getMachineInfo(OS, name, num);
1387 static void rpmRebuildTargetVars(const char ** target, const char ** canontarget)
1390 char *ca = NULL, *co = NULL, *ct = NULL;
1393 /* Rebuild the compat table to recalculate the current target arch. */
1395 rpmSetMachine(NULL, NULL);
1396 rpmSetTables(RPM_MACHTABLE_INSTARCH, RPM_MACHTABLE_INSTOS);
1397 rpmSetTables(RPM_MACHTABLE_BUILDARCH, RPM_MACHTABLE_BUILDOS);
1399 if (target && *target) {
1401 /* Set arch and os from specified build target */
1402 ca = xstrdup(*target);
1403 if ((c = strchr(ca, '-')) != NULL) {
1406 if ((co = strrchr(c, '-')) == NULL) {
1409 if (!rstrcasecmp(co, "-gnu"))
1411 if ((co = strrchr(c, '-')) == NULL)
1416 if (co != NULL) co = xstrdup(co);
1419 const char *a = NULL;
1420 const char *o = NULL;
1421 /* Set build target from rpm arch and os */
1422 rpmGetArchInfo(&a, NULL);
1423 ca = (a) ? xstrdup(a) : NULL;
1424 rpmGetOsInfo(&o, NULL);
1425 co = (o) ? xstrdup(o) : NULL;
1428 /* If still not set, Set target arch/os from default uname(2) values */
1430 const char *a = NULL;
1431 defaultMachine(&a, NULL);
1432 ca = xstrdup(a ? a : "(arch)");
1434 for (x = 0; ca[x] != '\0'; x++)
1435 ca[x] = rtolower(ca[x]);
1438 const char *o = NULL;
1439 defaultMachine(NULL, &o);
1440 co = xstrdup(o ? o : "(os)");
1442 for (x = 0; co[x] != '\0'; x++)
1443 co[x] = rtolower(co[x]);
1445 /* XXX For now, set canonical target to arch-os */
1447 rasprintf(&ct, "%s-%s", ca, co);
1451 * XXX All this macro pokery/jiggery could be achieved by doing a delayed
1452 * rpmInitMacros(NULL, PER-PLATFORM-MACRO-FILE-NAMES);
1454 delMacro(NULL, "_target");
1455 addMacro(NULL, "_target", NULL, ct, RMIL_RPMRC);
1456 delMacro(NULL, "_target_cpu");
1457 addMacro(NULL, "_target_cpu", NULL, ca, RMIL_RPMRC);
1458 delMacro(NULL, "_target_os");
1459 addMacro(NULL, "_target_os", NULL, co, RMIL_RPMRC);
1461 * XXX Make sure that per-arch optflags is initialized correctly.
1463 { const char *optflags = rpmGetVarArch(RPMVAR_OPTFLAGS, ca);
1464 if (optflags != NULL) {
1465 delMacro(NULL, "optflags");
1466 addMacro(NULL, "optflags", NULL, optflags, RMIL_RPMRC);
1478 void rpmFreeRpmrc(void)
1483 for (i = 0; i < nplatpat; i++)
1484 platpat[i] = _free(platpat[i]);
1485 platpat = _free(platpat);
1488 for (i = 0; i < RPM_MACHTABLE_COUNT; i++) {
1491 if (t->equiv.list) {
1492 for (j = 0; j < t->equiv.count; j++)
1493 t->equiv.list[j].name = _free(t->equiv.list[j].name);
1494 t->equiv.list = _free(t->equiv.list);
1497 if (t->cache.cache) {
1498 for (j = 0; j < t->cache.size; j++) {
1500 e = t->cache.cache + j;
1503 e->name = _free(e->name);
1505 for (k = 0; k < e->count; k++)
1506 e->equivs[k] = _free(e->equivs[k]);
1507 e->equivs = _free(e->equivs);
1510 t->cache.cache = _free(t->cache.cache);
1514 for (j = 0; j < t->defaultsLength; j++) {
1515 t->defaults[j].name = _free(t->defaults[j].name);
1516 t->defaults[j].defName = _free(t->defaults[j].defName);
1518 t->defaults = _free(t->defaults);
1519 t->defaultsLength = 0;
1522 for (j = 0; j < t->canonsLength; j++) {
1523 t->canons[j].name = _free(t->canons[j].name);
1524 t->canons[j].short_name = _free(t->canons[j].short_name);
1526 t->canons = _free(t->canons);
1527 t->canonsLength = 0;
1531 for (i = 0; i < RPMVAR_NUM; i++) {
1532 struct rpmvarValue * vp;
1533 while ((vp = values[i].next) != NULL) {
1534 values[i].next = vp->next;
1535 vp->value = _free(vp->value);
1536 vp->arch = _free(vp->arch);
1539 values[i].value = _free(values[i].value);
1540 values[i].arch = _free(values[i].arch);
1542 current[OS] = _free(current[OS]);
1543 current[ARCH] = _free(current[ARCH]);
1544 defaultsInitialized = 0;
1545 /* FIX: platpat/current may be NULL */
1547 /* XXX doesn't really belong here but... */
1557 * Read rpmrc (and macro) configuration file(s).
1558 * @param rcfiles colon separated files to read (NULL uses default)
1559 * @return RPMRC_OK on success
1561 static rpmRC rpmReadRC(const char * rcfiles)
1563 ARGV_t p, globs = NULL, files = NULL;
1564 rpmRC rc = RPMRC_FAIL;
1566 if (!defaultsInitialized) {
1568 defaultsInitialized = 1;
1571 if (rcfiles == NULL)
1572 rcfiles = defrcfiles;
1574 /* Expand any globs in rcfiles. Missing files are ok here. */
1575 argvSplit(&globs, rcfiles, ":");
1576 for (p = globs; *p; p++) {
1578 if (rpmGlob(*p, NULL, &av) == 0) {
1579 argvAppend(&files, av);
1585 /* Read each file in rcfiles. */
1586 for (p = files; p && *p; p++) {
1587 /* XXX Only /usr/lib/rpm/rpmrc must exist in default rcfiles list */
1588 if (access(*p, R_OK) != 0) {
1589 if (rcfiles == defrcfiles && p != files)
1591 rpmlog(RPMLOG_ERR, _("Unable to open %s for reading: %m.\n"), *p);
1599 rpmSetMachine(NULL, NULL); /* XXX WTFO? Why bother? */
1606 int rpmReadConfigFiles(const char * file, const char * target)
1608 /* Force preloading of dlopen()'ed libraries in case we go chrooting */
1609 (void) gethostbyname("localhost");
1610 (void) rpmInitCrypto();
1612 /* Preset target macros */
1613 /* FIX: target can be NULL */
1614 rpmRebuildTargetVars(&target, NULL);
1616 /* Read the files */
1617 if (rpmReadRC(file)) return -1;
1619 if (macrofiles != NULL) {
1620 char *mf = rpmGetPath(macrofiles, NULL);
1621 rpmInitMacros(NULL, mf);
1625 /* Reset target macros */
1626 rpmRebuildTargetVars(&target, NULL);
1628 /* Finally set target platform */
1629 { char *cpu = rpmExpand("%{_target_cpu}", NULL);
1630 char *os = rpmExpand("%{_target_os}", NULL);
1631 rpmSetMachine(cpu, os);
1637 /* Force Lua state initialization */
1644 int rpmShowRC(FILE * fp)
1646 const struct rpmOption *opt;
1649 machEquivTable equivTable;
1651 /* the caller may set the build arch which should be printed here */
1652 fprintf(fp, "ARCHITECTURE AND OS:\n");
1653 fprintf(fp, "build arch : %s\n", current[ARCH]);
1655 fprintf(fp, "compatible build archs:");
1656 equivTable = &tables[RPM_MACHTABLE_BUILDARCH].equiv;
1657 for (i = 0; i < equivTable->count; i++)
1658 fprintf(fp," %s", equivTable->list[i].name);
1661 fprintf(fp, "build os : %s\n", current[OS]);
1663 fprintf(fp, "compatible build os's :");
1664 equivTable = &tables[RPM_MACHTABLE_BUILDOS].equiv;
1665 for (i = 0; i < equivTable->count; i++)
1666 fprintf(fp," %s", equivTable->list[i].name);
1669 rpmSetTables(RPM_MACHTABLE_INSTARCH, RPM_MACHTABLE_INSTOS);
1670 rpmSetMachine(NULL, NULL); /* XXX WTFO? Why bother? */
1672 fprintf(fp, "install arch : %s\n", current[ARCH]);
1673 fprintf(fp, "install os : %s\n", current[OS]);
1675 fprintf(fp, "compatible archs :");
1676 equivTable = &tables[RPM_MACHTABLE_INSTARCH].equiv;
1677 for (i = 0; i < equivTable->count; i++)
1678 fprintf(fp," %s", equivTable->list[i].name);
1681 fprintf(fp, "compatible os's :");
1682 equivTable = &tables[RPM_MACHTABLE_INSTOS].equiv;
1683 for (i = 0; i < equivTable->count; i++)
1684 fprintf(fp," %s", equivTable->list[i].name);
1687 fprintf(fp, "\nRPMRC VALUES:\n");
1688 for (i = 0, opt = optionTable; i < optionTableSize; i++, opt++) {
1689 const char *s = rpmGetVar(opt->var);
1690 if (s != NULL || rpmIsVerbose())
1691 fprintf(fp, "%-21s : %s\n", opt->name, s ? s : "(not set)");
1695 fprintf(fp, "Features supported by rpmlib:\n");
1696 rpmdsRpmlib(&ds, NULL);
1698 while (rpmdsNext(ds) >= 0) {
1699 const char * DNEVR = rpmdsDNEVR(ds);
1701 fprintf(fp, " %s\n", DNEVR+2);
1706 rpmDumpMacroTable(NULL, fp);