4 #if defined(__linux__) && defined(__powerpc__)
8 #include <ctype.h> /* XXX for /etc/rpm/platform contents */
10 #if HAVE_SYS_SYSTEMCFG_H
11 #include <sys/systemcfg.h>
13 #define __power_pc() 0
16 #include <rpm/rpmlib.h> /* RPM_MACTABLE*, Rc-prototypes */
17 #include <rpm/rpmmacro.h>
18 #include <rpm/rpmfileutil.h>
19 #include <rpm/rpmstring.h>
20 #include <rpm/rpmlog.h>
22 #include "rpmio/rpmlua.h"
23 #include "rpmio/rpmio_internal.h" /* XXX for rpmioSlurp */
25 #include "lib/rpmliblua.h"
29 static const char * defrcfiles = NULL;
30 const char * macrofiles = NULL;
32 static const char * const platform = SYSCONFDIR "/rpm/platform";
33 static char ** platpat = NULL;
34 static int nplatpat = 0;
36 typedef char * cptr_t;
38 typedef struct machCacheEntry_s {
45 typedef struct machCache_s {
50 typedef struct machEquivInfo_s {
55 typedef struct machEquivTable_s {
62 /* eventually, this arch will be replaced with a generic condition */
64 struct rpmvarValue * next;
74 struct rpmOptionValue * value;
77 typedef struct defaultEntry_s {
82 typedef struct canonEntry_s {
88 /* tags are 'key'canon, 'key'translate, 'key'compat
90 * for giggles, 'key'_canon, 'key'_compat, and 'key'_canon will also work
92 typedef struct tableType_s {
95 const int hasTranslate;
96 struct machEquivTable_s equiv;
97 struct machCache_s cache;
98 defaultEntry defaults;
104 static struct tableType_s tables[RPM_MACHTABLE_COUNT] = {
107 { "buildarch", 0, 1 },
111 /* XXX get rid of this stuff... */
112 /* Stuff for maintaining "variables" like SOURCEDIR, BUILDDIR, etc */
113 #define RPMVAR_OPTFLAGS 3
114 #define RPMVAR_INCLUDE 43
115 #define RPMVAR_MACROFILES 49
117 #define RPMVAR_NUM 55 /* number of RPMVAR entries */
119 /* this *must* be kept in alphabetical order */
120 /* The order of the flags is archSpecific, required, macroize, localize */
122 static const struct rpmOption const optionTable[] = {
123 { "include", RPMVAR_INCLUDE, 0, 1, 0, 2 },
124 { "macrofiles", RPMVAR_MACROFILES, 0, 0, 0, 1 },
125 { "optflags", RPMVAR_OPTFLAGS, 1, 0, 1, 0 },
128 static const size_t optionTableSize = sizeof(optionTable) / sizeof(*optionTable);
133 static cptr_t current[2];
135 static int currTables[2] = { RPM_MACHTABLE_INSTOS, RPM_MACHTABLE_INSTARCH };
137 static struct rpmvarValue values[RPMVAR_NUM];
139 static int defaultsInitialized = 0;
142 static rpmRC doReadRC(const char * urlfn);
144 static void rpmSetVarArch(int var, const char * val,
147 static void rebuildCompatTables(int type, const char * name);
149 static void rpmRebuildTargetVars(const char **target, const char ** canontarget);
151 static int optionCompare(const void * a, const void * b)
153 return rstrcasecmp(((const struct rpmOption *) a)->name,
154 ((const struct rpmOption *) b)->name);
157 static machCacheEntry
158 machCacheFindEntry(const machCache cache, const char * key)
162 for (i = 0; i < cache->size; i++)
163 if (rstreq(cache->cache[i].name, key)) return cache->cache + i;
168 static int machCompatCacheAdd(char * name, const char * fn, int linenum,
171 machCacheEntry entry = NULL;
177 while (*name && risspace(*name)) name++;
180 while (*chptr && *chptr != ':') chptr++;
182 rpmlog(RPMLOG_ERR, _("missing second ':' at %s:%d\n"), fn, linenum);
184 } else if (chptr == name) {
185 rpmlog(RPMLOG_ERR, _("missing architecture name at %s:%d\n"), fn,
190 while (*chptr == ':' || risspace(*chptr)) chptr--;
193 while (*equivs && risspace(*equivs)) equivs++;
199 entry = machCacheFindEntry(cache, name);
201 for (i = 0; i < entry->count; i++)
202 entry->equivs[i] = _free(entry->equivs[i]);
203 entry->equivs = _free(entry->equivs);
209 cache->cache = xrealloc(cache->cache,
210 (cache->size + 1) * sizeof(*cache->cache));
211 entry = cache->cache + cache->size++;
212 entry->name = xstrdup(name);
217 if (delEntry) return 0;
219 while ((chptr = strtok(equivs, " ")) != NULL) {
221 if (chptr[0] == '\0') /* does strtok() return "" ever?? */
224 entry->equivs = xrealloc(entry->equivs, sizeof(*entry->equivs)
225 * (entry->count + 1));
227 entry->equivs = xmalloc(sizeof(*entry->equivs));
229 entry->equivs[entry->count] = xstrdup(chptr);
237 machEquivSearch(const machEquivTable table, const char * name)
241 for (i = 0; i < table->count; i++)
242 if (!rstrcasecmp(table->list[i].name, name))
243 return table->list + i;
248 static void machAddEquiv(machEquivTable table, const char * name,
253 equiv = machEquivSearch(table, name);
256 table->list = xrealloc(table->list, (table->count + 1)
257 * sizeof(*table->list));
259 table->list = xmalloc(sizeof(*table->list));
261 table->list[table->count].name = xstrdup(name);
262 table->list[table->count++].score = distance;
266 static void machCacheEntryVisit(machCache cache,
267 machEquivTable table, const char * name, int distance)
269 machCacheEntry entry;
272 entry = machCacheFindEntry(cache, name);
273 if (!entry || entry->visited) return;
277 for (i = 0; i < entry->count; i++) {
278 machAddEquiv(table, entry->equivs[i], distance);
281 for (i = 0; i < entry->count; i++) {
282 machCacheEntryVisit(cache, table, entry->equivs[i], distance + 1);
286 static void machFindEquivs(machCache cache, machEquivTable table,
291 for (i = 0; i < cache->size; i++)
292 cache->cache[i].visited = 0;
294 while (table->count > 0) {
296 table->list[table->count].name = _free(table->list[table->count].name);
299 table->list = _free(table->list);
302 * We have a general graph built using strings instead of pointers.
303 * Yuck. We have to start at a point at traverse it, remembering how
304 * far away everything is.
306 /* FIX: table->list may be NULL. */
307 machAddEquiv(table, key, 1);
308 machCacheEntryVisit(cache, table, key, 2);
312 static rpmRC addCanon(canonEntry * table, int * tableLen, char * line,
313 const char * fn, int lineNum)
318 const char * tshort_name;
322 *table = xrealloc(*table, sizeof(**table) * (*tableLen));
324 t = & ((*table)[*tableLen - 2]);
326 tname = strtok(line, ": \t");
327 tshort_name = strtok(NULL, " \t");
328 s = strtok(NULL, " \t");
329 if (! (tname && tshort_name && s)) {
330 rpmlog(RPMLOG_ERR, _("Incomplete data line at %s:%d\n"),
334 if (strtok(NULL, " \t")) {
335 rpmlog(RPMLOG_ERR, _("Too many args in data line at %s:%d\n"),
340 tnum = strtoul(s, &s1, 10);
341 if ((*s1) || (s1 == s) || (tnum == ULONG_MAX)) {
342 rpmlog(RPMLOG_ERR, _("Bad arch/os number: %s (%s:%d)\n"), s,
347 t[0].name = xstrdup(tname);
348 t[0].short_name = (tshort_name ? xstrdup(tshort_name) : xstrdup(""));
351 /* From A B C entry */
352 /* Add B B C entry */
353 t[1].name = (tshort_name ? xstrdup(tshort_name) : xstrdup(""));
354 t[1].short_name = (tshort_name ? xstrdup(tshort_name) : xstrdup(""));
360 static rpmRC addDefault(defaultEntry * table, int * tableLen, char * line,
361 const char * fn, int lineNum)
366 *table = xrealloc(*table, sizeof(**table) * (*tableLen));
368 t = & ((*table)[*tableLen - 1]);
370 t->name = strtok(line, ": \t");
371 t->defName = strtok(NULL, " \t");
372 if (! (t->name && t->defName)) {
373 rpmlog(RPMLOG_ERR, _("Incomplete default line at %s:%d\n"),
377 if (strtok(NULL, " \t")) {
378 rpmlog(RPMLOG_ERR, _("Too many args in default line at %s:%d\n"),
383 t->name = xstrdup(t->name);
384 t->defName = (t->defName ? xstrdup(t->defName) : NULL);
389 static canonEntry lookupInCanonTable(const char * name,
390 const canonEntry table, int tableLen)
394 if (!rstreq(name, table[tableLen].name))
396 return &(table[tableLen]);
403 const char * lookupInDefaultTable(const char * name,
404 const defaultEntry table, int tableLen)
408 if (table[tableLen].name && rstreq(name, table[tableLen].name))
409 return table[tableLen].defName;
415 static void setDefaults(void)
417 const char *confdir = rpmConfigDir();
419 defrcfiles = rstrscat(NULL, confdir, "/rpmrc", ":",
420 confdir, "/" RPMCANONVENDOR "/rpmrc", ":",
421 SYSCONFDIR "/rpmrc", ":",
427 macrofiles = rstrscat(NULL, confdir, "/macros", ":",
428 confdir, "/platform/%{_target}/macros", ":",
429 confdir, "/" RPMCANONVENDOR "/macros", ":",
430 SYSCONFDIR "/rpm/macros.*", ":",
431 SYSCONFDIR "/rpm/macros", ":",
432 SYSCONFDIR "/rpm/%{_target}/macros", ":",
433 "~/.rpmmacros", NULL);
436 macrofiles = MACROFILES;
440 /* FIX: se usage inconsistent, W2DO? */
441 static rpmRC doReadRC(const char * urlfn)
444 char *se, *next, *buf = NULL, *fn;
446 struct rpmOption searchOption, * option;
447 rpmRC rc = RPMRC_FAIL;
449 fn = rpmGetPath(urlfn, NULL);
450 if (rpmioSlurp(fn, (uint8_t **) &buf, NULL) || buf == NULL) {
455 while (*next != '\0') {
460 /* Find end-of-line. */
461 while (*se && *se != '\n') se++;
462 if (*se != '\0') *se++ = '\0';
465 /* Trim leading spaces */
466 while (*s && risspace(*s)) s++;
468 /* We used to allow comments to begin anywhere, but not anymore. */
469 if (*s == '#' || *s == '\0') continue;
471 /* Find end-of-keyword. */
473 while (*se && !risspace(*se) && *se != ':') se++;
477 while (*se && risspace(*se) && *se != ':') se++;
481 rpmlog(RPMLOG_ERR, _("missing ':' (found 0x%02x) at %s:%d\n"),
482 (unsigned)(0xff & *se), fn, linenum);
485 *se++ = '\0'; /* terminate keyword or option, point to value */
486 while (*se && risspace(*se)) se++;
488 /* Find keyword in table */
489 searchOption.name = s;
490 option = bsearch(&searchOption, optionTable, optionTableSize,
491 sizeof(optionTable[0]), optionCompare);
493 if (option) { /* For configuration variables ... */
494 const char *arch, *val;
498 rpmlog(RPMLOG_ERR, _("missing argument for %s at %s:%d\n"),
499 option->name, fn, linenum);
503 switch (option->var) {
506 while (*se && !risspace(*se)) se++;
507 if (*se != '\0') *se++ = '\0';
509 #if 0 /* XXX doesn't seem to do anything useful, only break things... */
510 rpmRebuildTargetVars(NULL, NULL);
514 rpmlog(RPMLOG_ERR, _("cannot open %s at %s:%d: %m\n"),
518 continue; /* XXX don't save include value as var/macro */
525 if (option->archSpecific) {
527 while (*se && !risspace(*se)) se++;
530 _("missing architecture for %s at %s:%d\n"),
531 option->name, fn, linenum);
535 while (*se && risspace(*se)) se++;
538 _("missing argument for %s at %s:%d\n"),
539 option->name, fn, linenum);
546 /* Only add macros if appropriate for this arch */
547 if (option->macroize &&
548 (arch == NULL || rstreq(arch, current[ARCH]))) {
550 n = name = xmalloc(strlen(option->name)+2);
551 if (option->localize)
553 strcpy(n, option->name);
554 addMacro(NULL, name, NULL, val, RMIL_RPMRC);
557 rpmSetVarArch(option->var, val, arch);
560 } else { /* For arch/os compatibilty tables ... */
566 for (i = 0; i < RPM_MACHTABLE_COUNT; i++) {
567 if (rstreqn(tables[i].key, s, strlen(tables[i].key)))
571 if (i < RPM_MACHTABLE_COUNT) {
572 const char *rest = s + strlen(tables[i].key);
573 if (*rest == '_') rest++;
575 if (rstreq(rest, "compat")) {
576 if (machCompatCacheAdd(se, fn, linenum,
580 } else if (tables[i].hasTranslate &&
581 rstreq(rest, "translate")) {
582 if (addDefault(&tables[i].defaults,
583 &tables[i].defaultsLength,
587 } else if (tables[i].hasCanon &&
588 rstreq(rest, "canon")) {
589 if (addCanon(&tables[i].canons, &tables[i].canonsLength,
597 rpmlog(RPMLOG_ERR, _("bad option '%s' at %s:%d\n"),
615 static rpmRC rpmPlatform(const char * platform)
617 const char *cpu = NULL, *vendor = NULL, *os = NULL, *gnu = NULL;
620 int init_platform = 0;
624 rc = rpmioSlurp(platform, &b, &blen);
626 if (rc || b == NULL || blen <= 0) {
632 for (pe = p; p && *p; p = pe) {
633 pe = strchr(p, '\n');
637 while (*p && isspace(*p))
639 if (*p == '\0' || *p == '#')
643 char * t = p + strlen(p);
645 while (--t > p && isspace(*t))
648 platpat = xrealloc(platpat, (nplatpat + 2) * sizeof(*platpat));
649 platpat[nplatpat] = xstrdup(p);
651 platpat[nplatpat] = NULL;
660 while (*p && !(*p == '-' || isspace(*p)))
662 if (*p != '\0') *p++ = '\0';
665 while (*p && !(*p == '-' || isspace(*p)))
668 if (*p != '\0') *p++ = '\0';
672 if (*p != '\0') *p++ = '\0';
675 while (*p && !(*p == '-' || isspace(*p)))
681 while (*p && !(*p == '-' || isspace(*p)))
684 if (*p != '\0') *p++ = '\0';
687 addMacro(NULL, "_host_cpu", NULL, cpu, -1);
688 addMacro(NULL, "_host_vendor", NULL, vendor, -1);
689 addMacro(NULL, "_host_os", NULL, os, -1);
691 platpat = xrealloc(platpat, (nplatpat + 2) * sizeof(*platpat));
692 platpat[nplatpat] = rpmExpand("%{_host_cpu}-%{_host_vendor}-%{_host_os}", (gnu && *gnu ? "-" : NULL), gnu, NULL);
694 platpat[nplatpat] = NULL;
698 rc = (init_platform ? RPMRC_OK : RPMRC_FAIL);
706 # if defined(__linux__) && defined(__i386__)
711 * Generic CPUID function
713 static inline void cpuid(unsigned int op, unsigned int *eax, unsigned int *ebx, unsigned int *ecx, unsigned int *edx)
718 "movl %%ebx, %%esi \n"
720 : "=a" (*eax), "=S" (*ebx), "=c" (*ecx), "=d" (*edx)
725 * CPUID functions returning a single datum
727 static inline unsigned int cpuid_eax(unsigned int op)
729 unsigned int tmp, val;
730 cpuid(op, &val, &tmp, &tmp, &tmp);
734 static inline unsigned int cpuid_ebx(unsigned int op)
736 unsigned int tmp, val;
737 cpuid(op, &tmp, &val, &tmp, &tmp);
741 static inline unsigned int cpuid_ecx(unsigned int op)
743 unsigned int tmp, val;
744 cpuid(op, &tmp, &tmp, &val, &tmp);
748 static inline unsigned int cpuid_edx(unsigned int op)
750 unsigned int tmp, val;
751 cpuid(op, &tmp, &tmp, &tmp, &val);
755 static sigjmp_buf jenv;
757 static inline void model3(int _unused)
762 static inline int RPMClass(void)
765 unsigned int tfms, junk, cap, capamd;
766 struct sigaction oldsa;
768 sigaction(SIGILL, NULL, &oldsa);
769 signal(SIGILL, model3);
771 if (sigsetjmp(jenv, 1)) {
772 sigaction(SIGILL, &oldsa, NULL);
776 if (cpuid_eax(0x000000000)==0) {
777 sigaction(SIGILL, &oldsa, NULL);
781 cpuid(0x00000001, &tfms, &junk, &junk, &cap);
782 cpuid(0x80000001, &junk, &junk, &junk, &capamd);
786 sigaction(SIGILL, &oldsa, NULL);
792 /* CMOV supported? */
793 if (capamd & (1<<30))
794 return 7; /* 3DNOWEXT supported */
801 /* should only be called for model 6 CPU's */
802 static int is_athlon(void)
804 unsigned int eax, ebx, ecx, edx;
808 cpuid (0, &eax, &ebx, &ecx, &edx);
810 /* If you care about space, you can just check ebx, ecx and edx directly
811 instead of forming a string first and then doing a strcmp */
812 memset(vendor, 0, sizeof(vendor));
815 vendor[i] = (unsigned char) (ebx >>(8*i));
817 vendor[4+i] = (unsigned char) (edx >>(8*i));
819 vendor[8+i] = (unsigned char) (ecx >>(8*i));
821 if (!rstreqn(vendor, "AuthenticAMD", 12))
827 static int is_pentium3()
829 unsigned int eax, ebx, ecx, edx, family, model;
831 cpuid(0, &eax, &ebx, &ecx, &edx);
832 memset(vendor, 0, sizeof(vendor));
833 *((unsigned int *)&vendor[0]) = ebx;
834 *((unsigned int *)&vendor[4]) = edx;
835 *((unsigned int *)&vendor[8]) = ecx;
836 if (!rstreqn(vendor, "GenuineIntel", 12))
838 cpuid(1, &eax, &ebx, &ecx, &edx);
839 family = (eax >> 8) & 0x0f;
840 model = (eax >> 4) & 0x0f;
844 case 7: // Pentium III, Pentium III Xeon (model 7)
845 case 8: // Pentium III, Pentium III Xeon, Celeron (model 8)
848 Intel recently announced its new technology for mobile platforms,
849 named Centrino, and presents it as a big advance in mobile PCs.
850 One of the main part of Centrino consists in a brand new CPU,
851 the Pentium M, codenamed Banias, that we'll study in this review.
852 A particularity of this CPU is that it was designed for mobile platform
853 exclusively, unlike previous mobile CPU (Pentium III-M, Pentium 4-M)
854 that share the same micro-architecture as their desktop counterparts.
855 The Pentium M introduces a new micro-architecture, adapted for mobility
856 constraints, and that is halfway between the Pentium III and the Pentium 4.
857 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
859 case 10: // Pentium III Xeon (model A)
860 case 11: // Pentium III (model B)
866 static int is_pentium4()
868 unsigned int eax, ebx, ecx, edx, family, model;
870 cpuid(0, &eax, &ebx, &ecx, &edx);
871 memset(vendor, 0, sizeof(vendor));
872 *((unsigned int *)&vendor[0]) = ebx;
873 *((unsigned int *)&vendor[4]) = edx;
874 *((unsigned int *)&vendor[8]) = ecx;
875 if (!rstreqn(vendor, "GenuineIntel", 12))
877 cpuid(1, &eax, &ebx, &ecx, &edx);
878 family = (eax >> 8) & 0x0f;
879 model = (eax >> 4) & 0x0f;
883 case 0: // Pentium 4, Pentium 4 Xeon (0.18um)
884 case 1: // Pentium 4, Pentium 4 Xeon MP, Celeron (0.18um)
885 case 2: // Pentium 4, Mobile Pentium 4-M,
886 // Pentium 4 Xeon, Pentium 4 Xeon MP,
887 // Celeron, Mobile Celron (0.13um)
888 case 3: // Pentium 4, Celeron (0.09um)
894 static int is_geode()
896 unsigned int eax, ebx, ecx, edx, family, model;
898 /* If you care about space, you can just check ebx, ecx and edx directly
899 instead of forming a string first and then doing a strcmp */
900 memset(vendor, 0, sizeof(vendor));
902 cpuid(0, &eax, &ebx, &ecx, &edx);
903 memset(vendor, 0, sizeof(vendor));
904 *((unsigned int *)&vendor[0]) = ebx;
905 *((unsigned int *)&vendor[4]) = edx;
906 *((unsigned int *)&vendor[8]) = ecx;
907 if (!rstreqn(vendor, "AuthenticAMD", 12))
909 cpuid(1, &eax, &ebx, &ecx, &edx);
910 family = (eax >> 8) & 0x0f;
911 model = (eax >> 4) & 0x0f;
922 #if defined(__linux__) && defined(__powerpc__)
923 static jmp_buf mfspr_jmpbuf;
925 static void mfspr_ill(int notused)
927 longjmp(mfspr_jmpbuf, -1);
933 static void defaultMachine(const char ** arch,
936 static struct utsname un;
937 static int gotDefaults = 0;
942 while (!gotDefaults) {
943 if (!rpmPlatform(platform)) {
945 s = rpmExpand("%{_host_cpu}", NULL);
947 rstrlcpy(un.machine, s, sizeof(un.machine));
950 s = rpmExpand("%{_host_os}", NULL);
952 rstrlcpy(un.sysname, s, sizeof(un.sysname));
961 #if !defined(__linux__)
963 /* USUALLY un.sysname on sinix does start with the word "SINIX"
964 * let's be absolutely sure
966 strncpy(un.sysname, "SINIX", sizeof(un.sysname));
968 if (rstreq(un.sysname, "AIX")) {
969 strcpy(un.machine, __power_pc() ? "ppc" : "rs6000");
970 sprintf(un.sysname,"aix%s.%s", un.version, un.release);
972 else if(rstreq(un.sysname, "Darwin")) {
974 strcpy(un.machine, "ppc");
976 strcpy(un.machine, "i386");
979 else if (rstreq(un.sysname, "SunOS")) {
980 if (rstreqn(un.release,"4", 1)) /* SunOS 4.x */ {
983 (un.release[fd] != 0 && (fd < sizeof(un.release)));
985 if (!risdigit(un.release[fd]) && (un.release[fd] != '.')) {
990 sprintf(un.sysname,"sunos%s",un.release);
993 else /* Solaris 2.x: n.x.x becomes n-3.x.x */
994 sprintf(un.sysname, "solaris%1d%s", atoi(un.release)-3,
995 un.release+1+(atoi(un.release)/10));
997 /* Solaris on Intel hardware reports i86pc instead of i386
998 * (at least on 2.6 and 2.8)
1000 if (rstreq(un.machine, "i86pc"))
1001 sprintf(un.machine, "i386");
1003 else if (rstreq(un.sysname, "HP-UX"))
1004 /*make un.sysname look like hpux9.05 for example*/
1005 sprintf(un.sysname, "hpux%s", strpbrk(un.release, "123456789"));
1006 else if (rstreq(un.sysname, "OSF1"))
1007 /*make un.sysname look like osf3.2 for example*/
1008 sprintf(un.sysname, "osf%s", strpbrk(un.release, "123456789"));
1009 else if (rstreqn(un.sysname, "IP", 2))
1010 un.sysname[2] = '\0';
1011 else if (rstreqn(un.sysname, "SINIX", 5)) {
1012 sprintf(un.sysname, "sinix%s",un.release);
1013 if (rstreqn(un.machine, "RM", 2))
1014 sprintf(un.machine, "mips");
1016 else if ((rstreqn(un.machine, "34", 2) ||
1017 rstreqn(un.machine, "33", 2)) && \
1018 rstreqn(un.release, "4.0", 3))
1020 /* we are on ncr-sysv4 */
1021 char * prelid = NULL;
1022 FD_t fd = Fopen("/etc/.relid", "r.fdio");
1024 if (fd != NULL && !Ferror(fd)) {
1025 chptr = xcalloc(1, 256);
1026 { int irelid = Fread(chptr, sizeof(*chptr), 256, fd);
1028 /* example: "112393 RELEASE 020200 Version 01 OS" */
1030 if ((prelid = strstr(chptr, "RELEASE "))){
1031 prelid += strlen("RELEASE ")+1;
1032 sprintf(un.sysname,"ncr-sysv4.%.*s",1,prelid);
1037 chptr = _free (chptr);
1039 if (!gotit) /* parsing /etc/.relid file failed? */
1040 strcpy(un.sysname,"ncr-sysv4");
1041 /* wrong, just for now, find out how to look for i586 later*/
1042 strcpy(un.machine,"i486");
1044 #endif /* __linux__ */
1046 /* get rid of the hyphens in the sysname */
1047 for (chptr = un.machine; *chptr != '\0'; chptr++)
1048 if (*chptr == '/') *chptr = '-';
1050 # if defined(__MIPSEL__) || defined(__MIPSEL) || defined(_MIPSEL)
1052 strcpy(un.machine, "mipsel");
1053 # elif defined(__MIPSEB__) || defined(__MIPSEB) || defined(_MIPSEB)
1055 strcpy(un.machine, "mips");
1058 # if defined(__hpux) && defined(_SC_CPU_VERSION)
1060 # if !defined(CPU_PA_RISC1_2)
1061 # define CPU_PA_RISC1_2 0x211 /* HP PA-RISC1.2 */
1063 # if !defined(CPU_PA_RISC2_0)
1064 # define CPU_PA_RISC2_0 0x214 /* HP PA-RISC2.0 */
1066 int cpu_version = sysconf(_SC_CPU_VERSION);
1068 # if defined(CPU_HP_MC68020)
1069 if (cpu_version == CPU_HP_MC68020)
1070 strcpy(un.machine, "m68k");
1072 # if defined(CPU_HP_MC68030)
1073 if (cpu_version == CPU_HP_MC68030)
1074 strcpy(un.machine, "m68k");
1076 # if defined(CPU_HP_MC68040)
1077 if (cpu_version == CPU_HP_MC68040)
1078 strcpy(un.machine, "m68k");
1081 # if defined(CPU_PA_RISC1_0)
1082 if (cpu_version == CPU_PA_RISC1_0)
1083 strcpy(un.machine, "hppa1.0");
1085 # if defined(CPU_PA_RISC1_1)
1086 if (cpu_version == CPU_PA_RISC1_1)
1087 strcpy(un.machine, "hppa1.1");
1089 # if defined(CPU_PA_RISC1_2)
1090 if (cpu_version == CPU_PA_RISC1_2)
1091 strcpy(un.machine, "hppa1.2");
1093 # if defined(CPU_PA_RISC2_0)
1094 if (cpu_version == CPU_PA_RISC2_0)
1095 strcpy(un.machine, "hppa2.0");
1100 # if defined(__linux__) && defined(__sparc__)
1101 if (rstreq(un.machine, "sparc")) {
1102 #define PERS_LINUX 0x00000000
1103 #define PERS_LINUX_32BIT 0x00800000
1104 #define PERS_LINUX32 0x00000008
1106 extern int personality(unsigned long);
1109 oldpers = personality(PERS_LINUX_32BIT);
1110 if (oldpers != -1) {
1111 if (personality(PERS_LINUX) != -1) {
1113 if (rstreq(un.machine, "sparc64")) {
1114 strcpy(un.machine, "sparcv9");
1115 oldpers = PERS_LINUX32;
1118 personality(oldpers);
1121 # endif /* sparc*-linux */
1123 # if defined(__GNUC__) && defined(__alpha__)
1125 unsigned long amask, implver;
1126 register long v0 __asm__("$0") = -1;
1127 __asm__ (".long 0x47e00c20" : "=r"(v0) : "0"(v0));
1129 __asm__ (".long 0x47e03d80" : "=r"(v0));
1134 case 0: strcpy(un.machine, "alphaev5"); break;
1135 case 1: strcpy(un.machine, "alphaev56"); break;
1136 case 0x101: strcpy(un.machine, "alphapca56"); break;
1141 case 0x303: strcpy(un.machine, "alphaev6"); break;
1142 case 0x307: strcpy(un.machine, "alphaev67"); break;
1149 # if defined(__linux__) && defined(__i386__)
1151 char class = (char) (RPMClass() | '0');
1153 if ((class == '6' && is_athlon()) || class == '7')
1154 strcpy(un.machine, "athlon");
1155 else if (is_pentium4())
1156 strcpy(un.machine, "pentium4");
1157 else if (is_pentium3())
1158 strcpy(un.machine, "pentium3");
1159 else if (is_geode())
1160 strcpy(un.machine, "geode");
1161 else if (strchr("3456", un.machine[1]) && un.machine[1] != class)
1162 un.machine[1] = class;
1166 /* the uname() result goes through the arch_canon table */
1167 canon = lookupInCanonTable(un.machine,
1168 tables[RPM_MACHTABLE_INSTARCH].canons,
1169 tables[RPM_MACHTABLE_INSTARCH].canonsLength);
1171 rstrlcpy(un.machine, canon->short_name, sizeof(un.machine));
1173 canon = lookupInCanonTable(un.sysname,
1174 tables[RPM_MACHTABLE_INSTOS].canons,
1175 tables[RPM_MACHTABLE_INSTOS].canonsLength);
1177 rstrlcpy(un.sysname, canon->short_name, sizeof(un.sysname));
1182 if (arch) *arch = un.machine;
1183 if (os) *os = un.sysname;
1187 const char * rpmGetVarArch(int var, const char * arch)
1189 const struct rpmvarValue * next;
1191 if (arch == NULL) arch = current[ARCH];
1194 next = &values[var];
1196 if (next->arch && rstreq(next->arch, arch)) return next->value;
1201 next = values + var;
1202 while (next && next->arch) next = next->next;
1204 return next ? next->value : NULL;
1207 static const char *rpmGetVar(int var)
1209 return rpmGetVarArch(var, NULL);
1212 static void rpmSetVarArch(int var, const char * val, const char * arch)
1214 struct rpmvarValue * next = values + var;
1218 while (next->next) {
1219 if (next->arch && rstreq(next->arch, arch)) break;
1223 while (next->next) {
1224 if (!next->arch) break;
1229 if (next->arch && arch && rstreq(next->arch, arch)) {
1230 next->value = _free(next->value);
1231 next->arch = _free(next->arch);
1232 } else if (next->arch || arch) {
1233 next->next = xmalloc(sizeof(*next->next));
1241 next->value = _free(next->value);
1242 next->value = xstrdup(val);
1243 next->arch = (arch ? xstrdup(arch) : NULL);
1246 void rpmSetTables(int archTable, int osTable)
1248 const char * arch, * os;
1250 defaultMachine(&arch, &os);
1252 if (currTables[ARCH] != archTable) {
1253 currTables[ARCH] = archTable;
1254 rebuildCompatTables(ARCH, arch);
1257 if (currTables[OS] != osTable) {
1258 currTables[OS] = osTable;
1259 rebuildCompatTables(OS, os);
1263 int rpmMachineScore(int type, const char * name)
1265 machEquivInfo info = machEquivSearch(&tables[type].equiv, name);
1266 return (info != NULL ? info->score : 0);
1269 int rpmIsKnownArch(const char *name)
1271 canonEntry canon = lookupInCanonTable(name,
1272 tables[RPM_MACHTABLE_INSTARCH].canons,
1273 tables[RPM_MACHTABLE_INSTARCH].canonsLength);
1274 return (canon != NULL || rstreq(name, "noarch"));
1278 * Set current arch/os names.
1279 * NULL as argument is set to the default value (munged uname())
1280 * pushed through a translation table (if appropriate).
1281 * @deprecated Use addMacro to set _target_* macros.
1284 * @param arch arch name (or NULL)
1285 * @param os os name (or NULL)
1288 static void rpmSetMachine(const char * arch, const char * os)
1290 const char * host_cpu, * host_os;
1292 defaultMachine(&host_cpu, &host_os);
1296 if (tables[currTables[ARCH]].hasTranslate)
1297 arch = lookupInDefaultTable(arch,
1298 tables[currTables[ARCH]].defaults,
1299 tables[currTables[ARCH]].defaultsLength);
1301 if (arch == NULL) return; /* XXX can't happen */
1305 if (tables[currTables[OS]].hasTranslate)
1306 os = lookupInDefaultTable(os,
1307 tables[currTables[OS]].defaults,
1308 tables[currTables[OS]].defaultsLength);
1310 if (os == NULL) return; /* XXX can't happen */
1312 if (!current[ARCH] || !rstreq(arch, current[ARCH])) {
1313 current[ARCH] = _free(current[ARCH]);
1314 current[ARCH] = xstrdup(arch);
1315 rebuildCompatTables(ARCH, host_cpu);
1318 if (!current[OS] || !rstreq(os, current[OS])) {
1319 char * t = xstrdup(os);
1320 current[OS] = _free(current[OS]);
1322 * XXX Capitalizing the 'L' is needed to insure that old
1323 * XXX os-from-uname (e.g. "Linux") is compatible with the new
1324 * XXX os-from-platform (e.g "linux" from "sparc-*-linux").
1325 * XXX A copy of this string is embedded in headers and is
1326 * XXX used by rpmInstallPackage->{os,arch}Okay->rpmMachineScore->
1327 * XXX to verify correct arch/os from headers.
1329 if (rstreq(t, "linux"))
1333 rebuildCompatTables(OS, host_os);
1337 static void rebuildCompatTables(int type, const char * name)
1339 machFindEquivs(&tables[currTables[type]].cache,
1340 &tables[currTables[type]].equiv,
1344 static void getMachineInfo(int type, const char ** name,
1348 int which = currTables[type];
1350 /* use the normal canon tables, even if we're looking up build stuff */
1351 if (which >= 2) which -= 2;
1353 canon = lookupInCanonTable(current[type],
1354 tables[which].canons,
1355 tables[which].canonsLength);
1358 if (num) *num = canon->num;
1359 if (name) *name = canon->short_name;
1361 if (num) *num = 255;
1362 if (name) *name = current[type];
1364 if (tables[currTables[type]].hasCanon) {
1365 rpmlog(RPMLOG_WARNING, _("Unknown system: %s\n"), current[type]);
1366 rpmlog(RPMLOG_WARNING, _("Please contact %s\n"), PACKAGE_BUGREPORT);
1371 void rpmGetArchInfo(const char ** name, int * num)
1373 getMachineInfo(ARCH, name, num);
1376 void rpmGetOsInfo(const char ** name, int * num)
1378 getMachineInfo(OS, name, num);
1381 static void rpmRebuildTargetVars(const char ** target, const char ** canontarget)
1384 char *ca = NULL, *co = NULL, *ct = NULL;
1387 /* Rebuild the compat table to recalculate the current target arch. */
1389 rpmSetMachine(NULL, NULL);
1390 rpmSetTables(RPM_MACHTABLE_INSTARCH, RPM_MACHTABLE_INSTOS);
1391 rpmSetTables(RPM_MACHTABLE_BUILDARCH, RPM_MACHTABLE_BUILDOS);
1393 if (target && *target) {
1395 /* Set arch and os from specified build target */
1396 ca = xstrdup(*target);
1397 if ((c = strchr(ca, '-')) != NULL) {
1400 if ((co = strrchr(c, '-')) == NULL) {
1403 if (!rstrcasecmp(co, "-gnu"))
1405 if ((co = strrchr(c, '-')) == NULL)
1410 if (co != NULL) co = xstrdup(co);
1413 const char *a = NULL;
1414 const char *o = NULL;
1415 /* Set build target from rpm arch and os */
1416 rpmGetArchInfo(&a, NULL);
1417 ca = (a) ? xstrdup(a) : NULL;
1418 rpmGetOsInfo(&o, NULL);
1419 co = (o) ? xstrdup(o) : NULL;
1422 /* If still not set, Set target arch/os from default uname(2) values */
1424 const char *a = NULL;
1425 defaultMachine(&a, NULL);
1426 ca = xstrdup(a ? a : "(arch)");
1428 for (x = 0; ca[x] != '\0'; x++)
1429 ca[x] = rtolower(ca[x]);
1432 const char *o = NULL;
1433 defaultMachine(NULL, &o);
1434 co = xstrdup(o ? o : "(os)");
1436 for (x = 0; co[x] != '\0'; x++)
1437 co[x] = rtolower(co[x]);
1439 /* XXX For now, set canonical target to arch-os */
1441 ct = xmalloc(strlen(ca) + sizeof("-") + strlen(co));
1442 sprintf(ct, "%s-%s", ca, co);
1446 * XXX All this macro pokery/jiggery could be achieved by doing a delayed
1447 * rpmInitMacros(NULL, PER-PLATFORM-MACRO-FILE-NAMES);
1449 delMacro(NULL, "_target");
1450 addMacro(NULL, "_target", NULL, ct, RMIL_RPMRC);
1451 delMacro(NULL, "_target_cpu");
1452 addMacro(NULL, "_target_cpu", NULL, ca, RMIL_RPMRC);
1453 delMacro(NULL, "_target_os");
1454 addMacro(NULL, "_target_os", NULL, co, RMIL_RPMRC);
1456 * XXX Make sure that per-arch optflags is initialized correctly.
1458 { const char *optflags = rpmGetVarArch(RPMVAR_OPTFLAGS, ca);
1459 if (optflags != NULL) {
1460 delMacro(NULL, "optflags");
1461 addMacro(NULL, "optflags", NULL, optflags, RMIL_RPMRC);
1473 void rpmFreeRpmrc(void)
1478 for (i = 0; i < nplatpat; i++)
1479 platpat[i] = _free(platpat[i]);
1480 platpat = _free(platpat);
1483 for (i = 0; i < RPM_MACHTABLE_COUNT; i++) {
1486 if (t->equiv.list) {
1487 for (j = 0; j < t->equiv.count; j++)
1488 t->equiv.list[j].name = _free(t->equiv.list[j].name);
1489 t->equiv.list = _free(t->equiv.list);
1492 if (t->cache.cache) {
1493 for (j = 0; j < t->cache.size; j++) {
1495 e = t->cache.cache + j;
1498 e->name = _free(e->name);
1500 for (k = 0; k < e->count; k++)
1501 e->equivs[k] = _free(e->equivs[k]);
1502 e->equivs = _free(e->equivs);
1505 t->cache.cache = _free(t->cache.cache);
1509 for (j = 0; j < t->defaultsLength; j++) {
1510 t->defaults[j].name = _free(t->defaults[j].name);
1511 t->defaults[j].defName = _free(t->defaults[j].defName);
1513 t->defaults = _free(t->defaults);
1514 t->defaultsLength = 0;
1517 for (j = 0; j < t->canonsLength; j++) {
1518 t->canons[j].name = _free(t->canons[j].name);
1519 t->canons[j].short_name = _free(t->canons[j].short_name);
1521 t->canons = _free(t->canons);
1522 t->canonsLength = 0;
1526 for (i = 0; i < RPMVAR_NUM; i++) {
1527 struct rpmvarValue * vp;
1528 while ((vp = values[i].next) != NULL) {
1529 values[i].next = vp->next;
1530 vp->value = _free(vp->value);
1531 vp->arch = _free(vp->arch);
1534 values[i].value = _free(values[i].value);
1535 values[i].arch = _free(values[i].arch);
1537 current[OS] = _free(current[OS]);
1538 current[ARCH] = _free(current[ARCH]);
1539 defaultsInitialized = 0;
1540 /* FIX: platpat/current may be NULL */
1542 /* XXX doesn't really belong here but... */
1552 * Read rpmrc (and macro) configuration file(s).
1553 * @param rcfiles colon separated files to read (NULL uses default)
1554 * @return RPMRC_OK on success
1556 static rpmRC rpmReadRC(const char * rcfiles)
1558 ARGV_t p, globs = NULL, files = NULL;
1559 rpmRC rc = RPMRC_FAIL;
1561 if (!defaultsInitialized) {
1563 defaultsInitialized = 1;
1566 if (rcfiles == NULL)
1567 rcfiles = defrcfiles;
1569 /* Expand any globs in rcfiles. Missing files are ok here. */
1570 argvSplit(&globs, rcfiles, ":");
1571 for (p = globs; *p; p++) {
1573 if (rpmGlob(*p, NULL, &av) == 0) {
1574 argvAppend(&files, av);
1580 /* Read each file in rcfiles. */
1581 for (p = files; p && *p; p++) {
1582 /* XXX Only /usr/lib/rpm/rpmrc must exist in default rcfiles list */
1583 if (access(*p, R_OK) != 0) {
1584 if (rcfiles == defrcfiles && p != files)
1586 rpmlog(RPMLOG_ERR, _("Unable to open %s for reading: %m.\n"), *p);
1594 rpmSetMachine(NULL, NULL); /* XXX WTFO? Why bother? */
1601 int rpmReadConfigFiles(const char * file, const char * target)
1604 /* Reset umask to its default umask(2) value. */
1607 /* Force preloading of dlopen()'ed libraries in case we go chrooting */
1608 (void) gethostbyname("localhost");
1609 (void) rpmInitCrypto();
1611 /* Preset target macros */
1612 /* FIX: target can be NULL */
1613 rpmRebuildTargetVars(&target, NULL);
1615 /* Read the files */
1616 if (rpmReadRC(file)) return -1;
1618 if (macrofiles != NULL) {
1619 char *mf = rpmGetPath(macrofiles, NULL);
1620 rpmInitMacros(NULL, mf);
1624 /* Reset target macros */
1625 rpmRebuildTargetVars(&target, NULL);
1627 /* Finally set target platform */
1628 { char *cpu = rpmExpand("%{_target_cpu}", NULL);
1629 char *os = rpmExpand("%{_target_os}", NULL);
1630 rpmSetMachine(cpu, os);
1636 /* Force Lua state initialization */
1643 int rpmShowRC(FILE * fp)
1645 const struct rpmOption *opt;
1648 machEquivTable equivTable;
1650 /* the caller may set the build arch which should be printed here */
1651 fprintf(fp, "ARCHITECTURE AND OS:\n");
1652 fprintf(fp, "build arch : %s\n", current[ARCH]);
1654 fprintf(fp, "compatible build archs:");
1655 equivTable = &tables[RPM_MACHTABLE_BUILDARCH].equiv;
1656 for (i = 0; i < equivTable->count; i++)
1657 fprintf(fp," %s", equivTable->list[i].name);
1660 fprintf(fp, "build os : %s\n", current[OS]);
1662 fprintf(fp, "compatible build os's :");
1663 equivTable = &tables[RPM_MACHTABLE_BUILDOS].equiv;
1664 for (i = 0; i < equivTable->count; i++)
1665 fprintf(fp," %s", equivTable->list[i].name);
1668 rpmSetTables(RPM_MACHTABLE_INSTARCH, RPM_MACHTABLE_INSTOS);
1669 rpmSetMachine(NULL, NULL); /* XXX WTFO? Why bother? */
1671 fprintf(fp, "install arch : %s\n", current[ARCH]);
1672 fprintf(fp, "install os : %s\n", current[OS]);
1674 fprintf(fp, "compatible archs :");
1675 equivTable = &tables[RPM_MACHTABLE_INSTARCH].equiv;
1676 for (i = 0; i < equivTable->count; i++)
1677 fprintf(fp," %s", equivTable->list[i].name);
1680 fprintf(fp, "compatible os's :");
1681 equivTable = &tables[RPM_MACHTABLE_INSTOS].equiv;
1682 for (i = 0; i < equivTable->count; i++)
1683 fprintf(fp," %s", equivTable->list[i].name);
1686 fprintf(fp, "\nRPMRC VALUES:\n");
1687 for (i = 0, opt = optionTable; i < optionTableSize; i++, opt++) {
1688 const char *s = rpmGetVar(opt->var);
1689 if (s != NULL || rpmIsVerbose())
1690 fprintf(fp, "%-21s : %s\n", opt->name, s ? s : "(not set)");
1694 fprintf(fp, "Features supported by rpmlib:\n");
1695 xx = rpmdsRpmlib(&ds, NULL);
1697 while (rpmdsNext(ds) >= 0) {
1698 const char * DNEVR = rpmdsDNEVR(ds);
1700 fprintf(fp, " %s\n", DNEVR+2);
1705 rpmDumpMacroTable(NULL, fp);