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 */
28 static const char * defrcfiles = NULL;
29 const char * macrofiles = NULL;
31 static const char * const platform = SYSCONFDIR "/rpm/platform";
32 static char ** platpat = NULL;
33 static int nplatpat = 0;
35 typedef char * cptr_t;
37 typedef struct machCacheEntry_s {
44 typedef struct machCache_s {
49 typedef struct machEquivInfo_s {
54 typedef struct machEquivTable_s {
61 /* eventually, this arch will be replaced with a generic condition */
63 struct rpmvarValue * next;
73 struct rpmOptionValue * value;
76 typedef struct defaultEntry_s {
81 typedef struct canonEntry_s {
87 /* tags are 'key'canon, 'key'translate, 'key'compat
89 * for giggles, 'key'_canon, 'key'_compat, and 'key'_canon will also work
91 typedef struct tableType_s {
94 const int hasTranslate;
95 struct machEquivTable_s equiv;
96 struct machCache_s cache;
97 defaultEntry defaults;
103 static struct tableType_s tables[RPM_MACHTABLE_COUNT] = {
106 { "buildarch", 0, 1 },
110 /* XXX get rid of this stuff... */
111 /* Stuff for maintaining "variables" like SOURCEDIR, BUILDDIR, etc */
112 #define RPMVAR_OPTFLAGS 3
113 #define RPMVAR_INCLUDE 43
114 #define RPMVAR_MACROFILES 49
116 #define RPMVAR_NUM 55 /* number of RPMVAR entries */
118 /* this *must* be kept in alphabetical order */
119 /* The order of the flags is archSpecific, required, macroize, localize */
121 static const struct rpmOption const optionTable[] = {
122 { "include", RPMVAR_INCLUDE, 0, 1, 0, 2 },
123 { "macrofiles", RPMVAR_MACROFILES, 0, 0, 0, 1 },
124 { "optflags", RPMVAR_OPTFLAGS, 1, 0, 1, 0 },
127 static const size_t optionTableSize = sizeof(optionTable) / sizeof(*optionTable);
132 static cptr_t current[2];
134 static int currTables[2] = { RPM_MACHTABLE_INSTOS, RPM_MACHTABLE_INSTARCH };
136 static struct rpmvarValue values[RPMVAR_NUM];
138 static int defaultsInitialized = 0;
141 static rpmRC doReadRC(const char * urlfn);
143 static void rpmSetVarArch(int var, const char * val,
146 static void rebuildCompatTables(int type, const char * name);
148 static void rpmRebuildTargetVars(const char **target, const char ** canontarget);
150 static int optionCompare(const void * a, const void * b)
152 return rstrcasecmp(((const struct rpmOption *) a)->name,
153 ((const struct rpmOption *) b)->name);
156 static machCacheEntry
157 machCacheFindEntry(const machCache cache, const char * key)
161 for (i = 0; i < cache->size; i++)
162 if (!strcmp(cache->cache[i].name, key)) return cache->cache + i;
167 static int machCompatCacheAdd(char * name, const char * fn, int linenum,
170 machCacheEntry entry = NULL;
176 while (*name && risspace(*name)) name++;
179 while (*chptr && *chptr != ':') chptr++;
181 rpmlog(RPMLOG_ERR, _("missing second ':' at %s:%d\n"), fn, linenum);
183 } else if (chptr == name) {
184 rpmlog(RPMLOG_ERR, _("missing architecture name at %s:%d\n"), fn,
189 while (*chptr == ':' || risspace(*chptr)) chptr--;
192 while (*equivs && risspace(*equivs)) equivs++;
198 entry = machCacheFindEntry(cache, name);
200 for (i = 0; i < entry->count; i++)
201 entry->equivs[i] = _free(entry->equivs[i]);
202 entry->equivs = _free(entry->equivs);
208 cache->cache = xrealloc(cache->cache,
209 (cache->size + 1) * sizeof(*cache->cache));
210 entry = cache->cache + cache->size++;
211 entry->name = xstrdup(name);
216 if (delEntry) return 0;
218 while ((chptr = strtok(equivs, " ")) != NULL) {
220 if (chptr[0] == '\0') /* does strtok() return "" ever?? */
223 entry->equivs = xrealloc(entry->equivs, sizeof(*entry->equivs)
224 * (entry->count + 1));
226 entry->equivs = xmalloc(sizeof(*entry->equivs));
228 entry->equivs[entry->count] = xstrdup(chptr);
236 machEquivSearch(const machEquivTable table, const char * name)
240 for (i = 0; i < table->count; i++)
241 if (!rstrcasecmp(table->list[i].name, name))
242 return table->list + i;
247 static void machAddEquiv(machEquivTable table, const char * name,
252 equiv = machEquivSearch(table, name);
255 table->list = xrealloc(table->list, (table->count + 1)
256 * sizeof(*table->list));
258 table->list = xmalloc(sizeof(*table->list));
260 table->list[table->count].name = xstrdup(name);
261 table->list[table->count++].score = distance;
265 static void machCacheEntryVisit(machCache cache,
266 machEquivTable table, const char * name, int distance)
268 machCacheEntry entry;
271 entry = machCacheFindEntry(cache, name);
272 if (!entry || entry->visited) return;
276 for (i = 0; i < entry->count; i++) {
277 machAddEquiv(table, entry->equivs[i], distance);
280 for (i = 0; i < entry->count; i++) {
281 machCacheEntryVisit(cache, table, entry->equivs[i], distance + 1);
285 static void machFindEquivs(machCache cache, machEquivTable table,
290 for (i = 0; i < cache->size; i++)
291 cache->cache[i].visited = 0;
293 while (table->count > 0) {
295 table->list[table->count].name = _free(table->list[table->count].name);
298 table->list = _free(table->list);
301 * We have a general graph built using strings instead of pointers.
302 * Yuck. We have to start at a point at traverse it, remembering how
303 * far away everything is.
305 /* FIX: table->list may be NULL. */
306 machAddEquiv(table, key, 1);
307 machCacheEntryVisit(cache, table, key, 2);
311 static rpmRC addCanon(canonEntry * table, int * tableLen, char * line,
312 const char * fn, int lineNum)
317 const char * tshort_name;
321 *table = xrealloc(*table, sizeof(**table) * (*tableLen));
323 t = & ((*table)[*tableLen - 2]);
325 tname = strtok(line, ": \t");
326 tshort_name = strtok(NULL, " \t");
327 s = strtok(NULL, " \t");
328 if (! (tname && tshort_name && s)) {
329 rpmlog(RPMLOG_ERR, _("Incomplete data line at %s:%d\n"),
333 if (strtok(NULL, " \t")) {
334 rpmlog(RPMLOG_ERR, _("Too many args in data line at %s:%d\n"),
339 /* LCL: s != NULL here. */
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 (strcmp(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 && !strcmp(name, table[tableLen].name))
409 return table[tableLen].defName;
415 static void addMacroDefault(const char * macroname, const char * val,
420 addMacro(NULL, macroname, NULL, body, RMIL_DEFAULT);
423 static void setPathDefault(const char * macroname, const char * subdir)
426 if (macroname != NULL) {
427 char *body = rpmGetPath("%{_topdir}/", subdir, NULL);
428 addMacro(NULL, macroname, NULL, body, RMIL_DEFAULT);
433 static const char * const prescriptenviron = "\n\
434 RPM_SOURCE_DIR=\"%{_sourcedir}\"\n\
435 RPM_BUILD_DIR=\"%{_builddir}\"\n\
436 RPM_OPT_FLAGS=\"%{optflags}\"\n\
437 RPM_ARCH=\"%{_arch}\"\n\
439 export RPM_SOURCE_DIR RPM_BUILD_DIR RPM_OPT_FLAGS RPM_ARCH RPM_OS\n\
440 RPM_DOC_DIR=\"%{_docdir}\"\n\
441 export RPM_DOC_DIR\n\
442 RPM_PACKAGE_NAME=\"%{name}\"\n\
443 RPM_PACKAGE_VERSION=\"%{version}\"\n\
444 RPM_PACKAGE_RELEASE=\"%{release}\"\n\
445 export RPM_PACKAGE_NAME RPM_PACKAGE_VERSION RPM_PACKAGE_RELEASE\n\
446 %{?buildroot:RPM_BUILD_ROOT=\"%{buildroot}\"\n\
447 export RPM_BUILD_ROOT\n}\
450 static void setDefaults(void)
452 const char *confdir = rpmConfigDir();
453 defrcfiles = rstrscat(NULL, confdir, "/rpmrc", ":",
454 confdir, "/" RPMCANONVENDOR "/rpmrc", ":",
455 SYSCONFDIR "/rpmrc", ":",
459 macrofiles = rstrscat(NULL, confdir, "/macros", ":",
460 confdir, "/platform/%{_target}/macros", ":",
461 confdir, "/" RPMCANONVENDOR "/macros", ":",
462 SYSCONFDIR "/rpm/macros.*", ":",
463 SYSCONFDIR "/rpm/macros", ":",
464 SYSCONFDIR "/rpm/%{_target}/macros", ":",
465 "~/.rpmmacros", NULL);
467 macrofiles = MACROFILES;
470 addMacro(NULL, "_usr", NULL, "/usr", RMIL_DEFAULT);
471 addMacro(NULL, "_var", NULL, LOCALSTATEDIR, RMIL_DEFAULT);
473 addMacro(NULL, "_preScriptEnvironment",NULL, prescriptenviron,RMIL_DEFAULT);
475 addMacroDefault("_topdir",
476 "/usr/src/packages", "%(echo $HOME)/rpmbuild");
477 addMacroDefault("_tmppath",
478 LOCALSTATEDIR "/tmp", "%{_var}/tmp");
479 addMacroDefault("_dbpath",
480 LOCALSTATEDIR "/lib/rpm", "%{_var}/lib/rpm");
481 addMacroDefault("_defaultdocdir",
482 "/usr/doc", "%{_usr}/doc");
484 addMacroDefault("_rpmfilename",
485 "%%{ARCH}/%%{NAME}-%%{VERSION}-%%{RELEASE}.%%{ARCH}.rpm",NULL);
487 addMacroDefault("optflags",
489 addMacroDefault("sigtype",
491 addMacroDefault("_buildshell",
494 setPathDefault("_builddir", "BUILD");
495 setPathDefault("_buildrootdir", "BUILDROOT");
496 setPathDefault("_rpmdir", "RPMS");
497 setPathDefault("_srcrpmdir", "SRPMS");
498 setPathDefault("_sourcedir", "SOURCES");
499 setPathDefault("_specdir", "SPECS");
503 /* FIX: se usage inconsistent, W2DO? */
504 static rpmRC doReadRC(const char * urlfn)
507 char *se, *next, *buf = NULL, *fn;
509 struct rpmOption searchOption, * option;
510 rpmRC rc = RPMRC_FAIL;
512 fn = rpmGetPath(urlfn, NULL);
513 if (rpmioSlurp(fn, (uint8_t **) &buf, NULL) || buf == NULL) {
518 while (*next != '\0') {
523 /* Find end-of-line. */
524 while (*se && *se != '\n') se++;
525 if (*se != '\0') *se++ = '\0';
528 /* Trim leading spaces */
529 while (*s && risspace(*s)) s++;
531 /* We used to allow comments to begin anywhere, but not anymore. */
532 if (*s == '#' || *s == '\0') continue;
534 /* Find end-of-keyword. */
536 while (*se && !risspace(*se) && *se != ':') se++;
540 while (*se && risspace(*se) && *se != ':') se++;
544 rpmlog(RPMLOG_ERR, _("missing ':' (found 0x%02x) at %s:%d\n"),
545 (unsigned)(0xff & *se), fn, linenum);
548 *se++ = '\0'; /* terminate keyword or option, point to value */
549 while (*se && risspace(*se)) se++;
551 /* Find keyword in table */
552 searchOption.name = s;
553 option = bsearch(&searchOption, optionTable, optionTableSize,
554 sizeof(optionTable[0]), optionCompare);
556 if (option) { /* For configuration variables ... */
557 const char *arch, *val;
561 rpmlog(RPMLOG_ERR, _("missing argument for %s at %s:%d\n"),
562 option->name, fn, linenum);
566 switch (option->var) {
569 while (*se && !risspace(*se)) se++;
570 if (*se != '\0') *se++ = '\0';
572 #if 0 /* XXX doesn't seem to do anything useful, only break things... */
573 rpmRebuildTargetVars(NULL, NULL);
577 rpmlog(RPMLOG_ERR, _("cannot open %s at %s:%d: %m\n"),
581 continue; /* XXX don't save include value as var/macro */
588 if (option->archSpecific) {
590 while (*se && !risspace(*se)) se++;
593 _("missing architecture for %s at %s:%d\n"),
594 option->name, fn, linenum);
598 while (*se && risspace(*se)) se++;
601 _("missing argument for %s at %s:%d\n"),
602 option->name, fn, linenum);
609 /* Only add macros if appropriate for this arch */
610 if (option->macroize &&
611 (arch == NULL || !strcmp(arch, current[ARCH]))) {
613 n = name = xmalloc(strlen(option->name)+2);
614 if (option->localize)
616 strcpy(n, option->name);
617 addMacro(NULL, name, NULL, val, RMIL_RPMRC);
620 rpmSetVarArch(option->var, val, arch);
623 } else { /* For arch/os compatibilty tables ... */
629 for (i = 0; i < RPM_MACHTABLE_COUNT; i++) {
630 if (!strncmp(tables[i].key, s, strlen(tables[i].key)))
634 if (i < RPM_MACHTABLE_COUNT) {
635 const char *rest = s + strlen(tables[i].key);
636 if (*rest == '_') rest++;
638 if (!strcmp(rest, "compat")) {
639 if (machCompatCacheAdd(se, fn, linenum,
643 } else if (tables[i].hasTranslate &&
644 !strcmp(rest, "translate")) {
645 if (addDefault(&tables[i].defaults,
646 &tables[i].defaultsLength,
650 } else if (tables[i].hasCanon &&
651 !strcmp(rest, "canon")) {
652 if (addCanon(&tables[i].canons, &tables[i].canonsLength,
660 rpmlog(RPMLOG_ERR, _("bad option '%s' at %s:%d\n"),
678 static rpmRC rpmPlatform(const char * platform)
680 const char *cpu = NULL, *vendor = NULL, *os = NULL, *gnu = NULL;
683 int init_platform = 0;
687 rc = rpmioSlurp(platform, &b, &blen);
689 if (rc || b == NULL || blen <= 0) {
695 for (pe = p; p && *p; p = pe) {
696 pe = strchr(p, '\n');
700 while (*p && isspace(*p))
702 if (*p == '\0' || *p == '#')
706 char * t = p + strlen(p);
708 while (--t > p && isspace(*t))
711 platpat = xrealloc(platpat, (nplatpat + 2) * sizeof(*platpat));
712 platpat[nplatpat] = xstrdup(p);
714 platpat[nplatpat] = NULL;
723 while (*p && !(*p == '-' || isspace(*p)))
725 if (*p != '\0') *p++ = '\0';
728 while (*p && !(*p == '-' || isspace(*p)))
731 if (*p != '\0') *p++ = '\0';
735 if (*p != '\0') *p++ = '\0';
738 while (*p && !(*p == '-' || isspace(*p)))
744 while (*p && !(*p == '-' || isspace(*p)))
747 if (*p != '\0') *p++ = '\0';
750 addMacro(NULL, "_host_cpu", NULL, cpu, -1);
751 addMacro(NULL, "_host_vendor", NULL, vendor, -1);
752 addMacro(NULL, "_host_os", NULL, os, -1);
754 platpat = xrealloc(platpat, (nplatpat + 2) * sizeof(*platpat));
755 platpat[nplatpat] = rpmExpand("%{_host_cpu}-%{_host_vendor}-%{_host_os}", (gnu && *gnu ? "-" : NULL), gnu, NULL);
757 platpat[nplatpat] = NULL;
761 rc = (init_platform ? RPMRC_OK : RPMRC_FAIL);
769 # if defined(__linux__) && defined(__i386__)
774 * Generic CPUID function
776 static inline void cpuid(unsigned int op, unsigned int *eax, unsigned int *ebx, unsigned int *ecx, unsigned int *edx)
781 "movl %%ebx, %%esi \n"
783 : "=a" (*eax), "=S" (*ebx), "=c" (*ecx), "=d" (*edx)
788 * CPUID functions returning a single datum
790 static inline unsigned int cpuid_eax(unsigned int op)
792 unsigned int tmp, val;
793 cpuid(op, &val, &tmp, &tmp, &tmp);
797 static inline unsigned int cpuid_ebx(unsigned int op)
799 unsigned int tmp, val;
800 cpuid(op, &tmp, &val, &tmp, &tmp);
804 static inline unsigned int cpuid_ecx(unsigned int op)
806 unsigned int tmp, val;
807 cpuid(op, &tmp, &tmp, &val, &tmp);
811 static inline unsigned int cpuid_edx(unsigned int op)
813 unsigned int tmp, val;
814 cpuid(op, &tmp, &tmp, &tmp, &val);
818 static sigjmp_buf jenv;
820 static inline void model3(int _unused)
825 static inline int RPMClass(void)
828 unsigned int tfms, junk, cap, capamd;
829 struct sigaction oldsa;
831 sigaction(SIGILL, NULL, &oldsa);
832 signal(SIGILL, model3);
834 if (sigsetjmp(jenv, 1)) {
835 sigaction(SIGILL, &oldsa, NULL);
839 if (cpuid_eax(0x000000000)==0) {
840 sigaction(SIGILL, &oldsa, NULL);
844 cpuid(0x00000001, &tfms, &junk, &junk, &cap);
845 cpuid(0x80000001, &junk, &junk, &junk, &capamd);
849 sigaction(SIGILL, &oldsa, NULL);
855 /* CMOV supported? */
856 if (capamd & (1<<30))
857 return 7; /* 3DNOWEXT supported */
864 /* should only be called for model 6 CPU's */
865 static int is_athlon(void)
867 unsigned int eax, ebx, ecx, edx;
871 cpuid (0, &eax, &ebx, &ecx, &edx);
873 /* If you care about space, you can just check ebx, ecx and edx directly
874 instead of forming a string first and then doing a strcmp */
875 memset(vendor, 0, sizeof(vendor));
878 vendor[i] = (unsigned char) (ebx >>(8*i));
880 vendor[4+i] = (unsigned char) (edx >>(8*i));
882 vendor[8+i] = (unsigned char) (ecx >>(8*i));
884 if (strncmp(vendor, "AuthenticAMD", 12) != 0)
890 static int is_pentium3()
892 unsigned int eax, ebx, ecx, edx, family, model;
894 cpuid(0, &eax, &ebx, &ecx, &edx);
895 memset(vendor, 0, sizeof(vendor));
896 *((unsigned int *)&vendor[0]) = ebx;
897 *((unsigned int *)&vendor[4]) = edx;
898 *((unsigned int *)&vendor[8]) = ecx;
899 if (strncmp(vendor, "GenuineIntel", 12) != 0)
901 cpuid(1, &eax, &ebx, &ecx, &edx);
902 family = (eax >> 8) & 0x0f;
903 model = (eax >> 4) & 0x0f;
907 case 7: // Pentium III, Pentium III Xeon (model 7)
908 case 8: // Pentium III, Pentium III Xeon, Celeron (model 8)
911 Intel recently announced its new technology for mobile platforms,
912 named Centrino, and presents it as a big advance in mobile PCs.
913 One of the main part of Centrino consists in a brand new CPU,
914 the Pentium M, codenamed Banias, that we'll study in this review.
915 A particularity of this CPU is that it was designed for mobile platform
916 exclusively, unlike previous mobile CPU (Pentium III-M, Pentium 4-M)
917 that share the same micro-architecture as their desktop counterparts.
918 The Pentium M introduces a new micro-architecture, adapted for mobility
919 constraints, and that is halfway between the Pentium III and the Pentium 4.
920 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
922 case 10: // Pentium III Xeon (model A)
923 case 11: // Pentium III (model B)
929 static int is_pentium4()
931 unsigned int eax, ebx, ecx, edx, family, model;
933 cpuid(0, &eax, &ebx, &ecx, &edx);
934 memset(vendor, 0, sizeof(vendor));
935 *((unsigned int *)&vendor[0]) = ebx;
936 *((unsigned int *)&vendor[4]) = edx;
937 *((unsigned int *)&vendor[8]) = ecx;
938 if (strncmp(vendor, "GenuineIntel", 12) != 0)
940 cpuid(1, &eax, &ebx, &ecx, &edx);
941 family = (eax >> 8) & 0x0f;
942 model = (eax >> 4) & 0x0f;
946 case 0: // Pentium 4, Pentium 4 Xeon (0.18um)
947 case 1: // Pentium 4, Pentium 4 Xeon MP, Celeron (0.18um)
948 case 2: // Pentium 4, Mobile Pentium 4-M,
949 // Pentium 4 Xeon, Pentium 4 Xeon MP,
950 // Celeron, Mobile Celron (0.13um)
951 case 3: // Pentium 4, Celeron (0.09um)
957 static int is_geode()
959 unsigned int eax, ebx, ecx, edx, family, model;
961 /* If you care about space, you can just check ebx, ecx and edx directly
962 instead of forming a string first and then doing a strcmp */
963 memset(vendor, 0, sizeof(vendor));
965 cpuid(0, &eax, &ebx, &ecx, &edx);
966 memset(vendor, 0, sizeof(vendor));
967 *((unsigned int *)&vendor[0]) = ebx;
968 *((unsigned int *)&vendor[4]) = edx;
969 *((unsigned int *)&vendor[8]) = ecx;
970 if (strncmp(vendor, "AuthenticAMD", 12) != 0)
972 cpuid(1, &eax, &ebx, &ecx, &edx);
973 family = (eax >> 8) & 0x0f;
974 model = (eax >> 4) & 0x0f;
985 #if defined(__linux__) && defined(__powerpc__)
986 static jmp_buf mfspr_jmpbuf;
988 static void mfspr_ill(int notused)
990 longjmp(mfspr_jmpbuf, -1);
996 static void defaultMachine(const char ** arch,
999 static struct utsname un;
1000 static int gotDefaults = 0;
1005 while (!gotDefaults) {
1006 if (!rpmPlatform(platform)) {
1008 s = rpmExpand("%{_host_cpu}", NULL);
1010 rstrlcpy(un.machine, s, sizeof(un.machine));
1013 s = rpmExpand("%{_host_os}", NULL);
1015 rstrlcpy(un.sysname, s, sizeof(un.sysname));
1024 #if !defined(__linux__)
1026 /* USUALLY un.sysname on sinix does start with the word "SINIX"
1027 * let's be absolutely sure
1029 strncpy(un.sysname, "SINIX", sizeof(un.sysname));
1031 if (!strcmp(un.sysname, "AIX")) {
1032 strcpy(un.machine, __power_pc() ? "ppc" : "rs6000");
1033 sprintf(un.sysname,"aix%s.%s", un.version, un.release);
1035 else if(!strcmp(un.sysname, "Darwin")) {
1037 strcpy(un.machine, "ppc");
1038 #else ifdef __i386__
1039 strcpy(un.machine, "i386");
1042 else if (!strcmp(un.sysname, "SunOS")) {
1043 if (!strncmp(un.release,"4", 1)) /* SunOS 4.x */ {
1046 (un.release[fd] != 0 && (fd < sizeof(un.release)));
1048 if (!risdigit(un.release[fd]) && (un.release[fd] != '.')) {
1053 sprintf(un.sysname,"sunos%s",un.release);
1056 else /* Solaris 2.x: n.x.x becomes n-3.x.x */
1057 sprintf(un.sysname, "solaris%1d%s", atoi(un.release)-3,
1058 un.release+1+(atoi(un.release)/10));
1060 /* Solaris on Intel hardware reports i86pc instead of i386
1061 * (at least on 2.6 and 2.8)
1063 if (!strcmp(un.machine, "i86pc"))
1064 sprintf(un.machine, "i386");
1066 else if (!strcmp(un.sysname, "HP-UX"))
1067 /*make un.sysname look like hpux9.05 for example*/
1068 sprintf(un.sysname, "hpux%s", strpbrk(un.release, "123456789"));
1069 else if (!strcmp(un.sysname, "OSF1"))
1070 /*make un.sysname look like osf3.2 for example*/
1071 sprintf(un.sysname, "osf%s", strpbrk(un.release, "123456789"));
1072 else if (!strncmp(un.sysname, "IP", 2))
1073 un.sysname[2] = '\0';
1074 else if (!strncmp(un.sysname, "SINIX", 5)) {
1075 sprintf(un.sysname, "sinix%s",un.release);
1076 if (!strncmp(un.machine, "RM", 2))
1077 sprintf(un.machine, "mips");
1079 else if ((!strncmp(un.machine, "34", 2) ||
1080 !strncmp(un.machine, "33", 2)) && \
1081 !strncmp(un.release, "4.0", 3))
1083 /* we are on ncr-sysv4 */
1084 char * prelid = NULL;
1085 FD_t fd = Fopen("/etc/.relid", "r.fdio");
1087 if (fd != NULL && !Ferror(fd)) {
1088 chptr = xcalloc(1, 256);
1089 { int irelid = Fread(chptr, sizeof(*chptr), 256, fd);
1091 /* example: "112393 RELEASE 020200 Version 01 OS" */
1093 if ((prelid = strstr(chptr, "RELEASE "))){
1094 prelid += strlen("RELEASE ")+1;
1095 sprintf(un.sysname,"ncr-sysv4.%.*s",1,prelid);
1100 chptr = _free (chptr);
1102 if (!gotit) /* parsing /etc/.relid file failed? */
1103 strcpy(un.sysname,"ncr-sysv4");
1104 /* wrong, just for now, find out how to look for i586 later*/
1105 strcpy(un.machine,"i486");
1107 #endif /* __linux__ */
1109 /* get rid of the hyphens in the sysname */
1110 for (chptr = un.machine; *chptr != '\0'; chptr++)
1111 if (*chptr == '/') *chptr = '-';
1113 # if defined(__MIPSEL__) || defined(__MIPSEL) || defined(_MIPSEL)
1115 strcpy(un.machine, "mipsel");
1116 # elif defined(__MIPSEB__) || defined(__MIPSEB) || defined(_MIPSEB)
1118 strcpy(un.machine, "mips");
1121 # if defined(__hpux) && defined(_SC_CPU_VERSION)
1123 # if !defined(CPU_PA_RISC1_2)
1124 # define CPU_PA_RISC1_2 0x211 /* HP PA-RISC1.2 */
1126 # if !defined(CPU_PA_RISC2_0)
1127 # define CPU_PA_RISC2_0 0x214 /* HP PA-RISC2.0 */
1129 int cpu_version = sysconf(_SC_CPU_VERSION);
1131 # if defined(CPU_HP_MC68020)
1132 if (cpu_version == CPU_HP_MC68020)
1133 strcpy(un.machine, "m68k");
1135 # if defined(CPU_HP_MC68030)
1136 if (cpu_version == CPU_HP_MC68030)
1137 strcpy(un.machine, "m68k");
1139 # if defined(CPU_HP_MC68040)
1140 if (cpu_version == CPU_HP_MC68040)
1141 strcpy(un.machine, "m68k");
1144 # if defined(CPU_PA_RISC1_0)
1145 if (cpu_version == CPU_PA_RISC1_0)
1146 strcpy(un.machine, "hppa1.0");
1148 # if defined(CPU_PA_RISC1_1)
1149 if (cpu_version == CPU_PA_RISC1_1)
1150 strcpy(un.machine, "hppa1.1");
1152 # if defined(CPU_PA_RISC1_2)
1153 if (cpu_version == CPU_PA_RISC1_2)
1154 strcpy(un.machine, "hppa1.2");
1156 # if defined(CPU_PA_RISC2_0)
1157 if (cpu_version == CPU_PA_RISC2_0)
1158 strcpy(un.machine, "hppa2.0");
1163 # if defined(__linux__) && defined(__sparc__)
1164 if (!strcmp(un.machine, "sparc")) {
1165 #define PERS_LINUX 0x00000000
1166 #define PERS_LINUX_32BIT 0x00800000
1167 #define PERS_LINUX32 0x00000008
1169 extern int personality(unsigned long);
1172 oldpers = personality(PERS_LINUX_32BIT);
1173 if (oldpers != -1) {
1174 if (personality(PERS_LINUX) != -1) {
1176 if (! strcmp(un.machine, "sparc64")) {
1177 strcpy(un.machine, "sparcv9");
1178 oldpers = PERS_LINUX32;
1181 personality(oldpers);
1184 # endif /* sparc*-linux */
1186 # if defined(__GNUC__) && defined(__alpha__)
1188 unsigned long amask, implver;
1189 register long v0 __asm__("$0") = -1;
1190 __asm__ (".long 0x47e00c20" : "=r"(v0) : "0"(v0));
1192 __asm__ (".long 0x47e03d80" : "=r"(v0));
1197 case 0: strcpy(un.machine, "alphaev5"); break;
1198 case 1: strcpy(un.machine, "alphaev56"); break;
1199 case 0x101: strcpy(un.machine, "alphapca56"); break;
1204 case 0x303: strcpy(un.machine, "alphaev6"); break;
1205 case 0x307: strcpy(un.machine, "alphaev67"); break;
1212 # if defined(__linux__) && defined(__i386__)
1214 char class = (char) (RPMClass() | '0');
1216 if ((class == '6' && is_athlon()) || class == '7')
1217 strcpy(un.machine, "athlon");
1218 else if (is_pentium4())
1219 strcpy(un.machine, "pentium4");
1220 else if (is_pentium3())
1221 strcpy(un.machine, "pentium3");
1222 else if (is_geode())
1223 strcpy(un.machine, "geode");
1224 else if (strchr("3456", un.machine[1]) && un.machine[1] != class)
1225 un.machine[1] = class;
1229 /* the uname() result goes through the arch_canon table */
1230 canon = lookupInCanonTable(un.machine,
1231 tables[RPM_MACHTABLE_INSTARCH].canons,
1232 tables[RPM_MACHTABLE_INSTARCH].canonsLength);
1234 rstrlcpy(un.machine, canon->short_name, sizeof(un.machine));
1236 canon = lookupInCanonTable(un.sysname,
1237 tables[RPM_MACHTABLE_INSTOS].canons,
1238 tables[RPM_MACHTABLE_INSTOS].canonsLength);
1240 rstrlcpy(un.sysname, canon->short_name, sizeof(un.sysname));
1245 if (arch) *arch = un.machine;
1246 if (os) *os = un.sysname;
1250 const char * rpmGetVarArch(int var, const char * arch)
1252 const struct rpmvarValue * next;
1254 if (arch == NULL) arch = current[ARCH];
1257 next = &values[var];
1259 if (next->arch && !strcmp(next->arch, arch)) return next->value;
1264 next = values + var;
1265 while (next && next->arch) next = next->next;
1267 return next ? next->value : NULL;
1270 static const char *rpmGetVar(int var)
1272 return rpmGetVarArch(var, NULL);
1275 static void rpmSetVarArch(int var, const char * val, const char * arch)
1277 struct rpmvarValue * next = values + var;
1281 while (next->next) {
1282 if (next->arch && !strcmp(next->arch, arch)) break;
1286 while (next->next) {
1287 if (!next->arch) break;
1292 if (next->arch && arch && !strcmp(next->arch, arch)) {
1293 next->value = _free(next->value);
1294 next->arch = _free(next->arch);
1295 } else if (next->arch || arch) {
1296 next->next = xmalloc(sizeof(*next->next));
1304 next->value = _free(next->value);
1305 next->value = xstrdup(val);
1306 next->arch = (arch ? xstrdup(arch) : NULL);
1309 void rpmSetTables(int archTable, int osTable)
1311 const char * arch, * os;
1313 defaultMachine(&arch, &os);
1315 if (currTables[ARCH] != archTable) {
1316 currTables[ARCH] = archTable;
1317 rebuildCompatTables(ARCH, arch);
1320 if (currTables[OS] != osTable) {
1321 currTables[OS] = osTable;
1322 rebuildCompatTables(OS, os);
1326 int rpmMachineScore(int type, const char * name)
1328 machEquivInfo info = machEquivSearch(&tables[type].equiv, name);
1329 return (info != NULL ? info->score : 0);
1332 int rpmIsKnownArch(const char *name)
1334 canonEntry canon = lookupInCanonTable(name,
1335 tables[RPM_MACHTABLE_INSTARCH].canons,
1336 tables[RPM_MACHTABLE_INSTARCH].canonsLength);
1337 return (canon != NULL || strcmp(name, "noarch") == 0);
1341 * Set current arch/os names.
1342 * NULL as argument is set to the default value (munged uname())
1343 * pushed through a translation table (if appropriate).
1344 * @deprecated Use addMacro to set _target_* macros.
1347 * @param arch arch name (or NULL)
1348 * @param os os name (or NULL)
1351 static void rpmSetMachine(const char * arch, const char * os)
1353 const char * host_cpu, * host_os;
1355 defaultMachine(&host_cpu, &host_os);
1359 if (tables[currTables[ARCH]].hasTranslate)
1360 arch = lookupInDefaultTable(arch,
1361 tables[currTables[ARCH]].defaults,
1362 tables[currTables[ARCH]].defaultsLength);
1364 if (arch == NULL) return; /* XXX can't happen */
1368 if (tables[currTables[OS]].hasTranslate)
1369 os = lookupInDefaultTable(os,
1370 tables[currTables[OS]].defaults,
1371 tables[currTables[OS]].defaultsLength);
1373 if (os == NULL) return; /* XXX can't happen */
1375 if (!current[ARCH] || strcmp(arch, current[ARCH])) {
1376 current[ARCH] = _free(current[ARCH]);
1377 current[ARCH] = xstrdup(arch);
1378 rebuildCompatTables(ARCH, host_cpu);
1381 if (!current[OS] || strcmp(os, current[OS])) {
1382 char * t = xstrdup(os);
1383 current[OS] = _free(current[OS]);
1385 * XXX Capitalizing the 'L' is needed to insure that old
1386 * XXX os-from-uname (e.g. "Linux") is compatible with the new
1387 * XXX os-from-platform (e.g "linux" from "sparc-*-linux").
1388 * XXX A copy of this string is embedded in headers and is
1389 * XXX used by rpmInstallPackage->{os,arch}Okay->rpmMachineScore->
1390 * XXX to verify correct arch/os from headers.
1392 if (!strcmp(t, "linux"))
1396 rebuildCompatTables(OS, host_os);
1400 static void rebuildCompatTables(int type, const char * name)
1402 machFindEquivs(&tables[currTables[type]].cache,
1403 &tables[currTables[type]].equiv,
1407 static void getMachineInfo(int type, const char ** name,
1411 int which = currTables[type];
1413 /* use the normal canon tables, even if we're looking up build stuff */
1414 if (which >= 2) which -= 2;
1416 canon = lookupInCanonTable(current[type],
1417 tables[which].canons,
1418 tables[which].canonsLength);
1421 if (num) *num = canon->num;
1422 if (name) *name = canon->short_name;
1424 if (num) *num = 255;
1425 if (name) *name = current[type];
1427 if (tables[currTables[type]].hasCanon) {
1428 rpmlog(RPMLOG_WARNING, _("Unknown system: %s\n"), current[type]);
1429 rpmlog(RPMLOG_WARNING, _("Please contact %s\n"), PACKAGE_BUGREPORT);
1434 void rpmGetArchInfo(const char ** name, int * num)
1436 getMachineInfo(ARCH, name, num);
1439 void rpmGetOsInfo(const char ** name, int * num)
1441 getMachineInfo(OS, name, num);
1444 static void rpmRebuildTargetVars(const char ** target, const char ** canontarget)
1447 char *ca = NULL, *co = NULL, *ct = NULL;
1450 /* Rebuild the compat table to recalculate the current target arch. */
1452 rpmSetMachine(NULL, NULL);
1453 rpmSetTables(RPM_MACHTABLE_INSTARCH, RPM_MACHTABLE_INSTOS);
1454 rpmSetTables(RPM_MACHTABLE_BUILDARCH, RPM_MACHTABLE_BUILDOS);
1456 if (target && *target) {
1458 /* Set arch and os from specified build target */
1459 ca = xstrdup(*target);
1460 if ((c = strchr(ca, '-')) != NULL) {
1463 if ((co = strrchr(c, '-')) == NULL) {
1466 if (!rstrcasecmp(co, "-gnu"))
1468 if ((co = strrchr(c, '-')) == NULL)
1473 if (co != NULL) co = xstrdup(co);
1476 const char *a = NULL;
1477 const char *o = NULL;
1478 /* Set build target from rpm arch and os */
1479 rpmGetArchInfo(&a, NULL);
1480 ca = (a) ? xstrdup(a) : NULL;
1481 rpmGetOsInfo(&o, NULL);
1482 co = (o) ? xstrdup(o) : NULL;
1485 /* If still not set, Set target arch/os from default uname(2) values */
1487 const char *a = NULL;
1488 defaultMachine(&a, NULL);
1489 ca = (a) ? xstrdup(a) : NULL;
1491 for (x = 0; ca[x] != '\0'; x++)
1492 ca[x] = rtolower(ca[x]);
1495 const char *o = NULL;
1496 defaultMachine(NULL, &o);
1497 co = (o) ? xstrdup(o) : NULL;
1499 for (x = 0; co[x] != '\0'; x++)
1500 co[x] = rtolower(co[x]);
1502 /* XXX For now, set canonical target to arch-os */
1504 ct = xmalloc(strlen(ca) + sizeof("-") + strlen(co));
1505 sprintf(ct, "%s-%s", ca, co);
1509 * XXX All this macro pokery/jiggery could be achieved by doing a delayed
1510 * rpmInitMacros(NULL, PER-PLATFORM-MACRO-FILE-NAMES);
1512 delMacro(NULL, "_target");
1513 addMacro(NULL, "_target", NULL, ct, RMIL_RPMRC);
1514 delMacro(NULL, "_target_cpu");
1515 addMacro(NULL, "_target_cpu", NULL, ca, RMIL_RPMRC);
1516 delMacro(NULL, "_target_os");
1517 addMacro(NULL, "_target_os", NULL, co, RMIL_RPMRC);
1519 * XXX Make sure that per-arch optflags is initialized correctly.
1521 { const char *optflags = rpmGetVarArch(RPMVAR_OPTFLAGS, ca);
1522 if (optflags != NULL) {
1523 delMacro(NULL, "optflags");
1524 addMacro(NULL, "optflags", NULL, optflags, RMIL_RPMRC);
1536 void rpmFreeRpmrc(void)
1541 for (i = 0; i < nplatpat; i++)
1542 platpat[i] = _free(platpat[i]);
1543 platpat = _free(platpat);
1546 for (i = 0; i < RPM_MACHTABLE_COUNT; i++) {
1549 if (t->equiv.list) {
1550 for (j = 0; j < t->equiv.count; j++)
1551 t->equiv.list[j].name = _free(t->equiv.list[j].name);
1552 t->equiv.list = _free(t->equiv.list);
1555 if (t->cache.cache) {
1556 for (j = 0; j < t->cache.size; j++) {
1558 e = t->cache.cache + j;
1561 e->name = _free(e->name);
1563 for (k = 0; k < e->count; k++)
1564 e->equivs[k] = _free(e->equivs[k]);
1565 e->equivs = _free(e->equivs);
1568 t->cache.cache = _free(t->cache.cache);
1572 for (j = 0; j < t->defaultsLength; j++) {
1573 t->defaults[j].name = _free(t->defaults[j].name);
1574 t->defaults[j].defName = _free(t->defaults[j].defName);
1576 t->defaults = _free(t->defaults);
1577 t->defaultsLength = 0;
1580 for (j = 0; j < t->canonsLength; j++) {
1581 t->canons[j].name = _free(t->canons[j].name);
1582 t->canons[j].short_name = _free(t->canons[j].short_name);
1584 t->canons = _free(t->canons);
1585 t->canonsLength = 0;
1589 for (i = 0; i < RPMVAR_NUM; i++) {
1590 struct rpmvarValue * vp;
1591 while ((vp = values[i].next) != NULL) {
1592 values[i].next = vp->next;
1593 vp->value = _free(vp->value);
1594 vp->arch = _free(vp->arch);
1597 values[i].value = _free(values[i].value);
1598 values[i].arch = _free(values[i].arch);
1600 current[OS] = _free(current[OS]);
1601 current[ARCH] = _free(current[ARCH]);
1602 defaultsInitialized = 0;
1603 /* FIX: platpat/current may be NULL */
1605 /* XXX doesn't really belong here but... */
1612 * Read rpmrc (and macro) configuration file(s).
1613 * @param rcfiles colon separated files to read (NULL uses default)
1614 * @return RPMRC_OK on success
1616 static rpmRC rpmReadRC(const char * rcfiles)
1618 ARGV_t p, globs = NULL, files = NULL;
1619 rpmRC rc = RPMRC_FAIL;
1621 if (!defaultsInitialized) {
1623 defaultsInitialized = 1;
1626 if (rcfiles == NULL)
1627 rcfiles = defrcfiles;
1629 /* Expand any globs in rcfiles. Missing files are ok here. */
1630 argvSplit(&globs, rcfiles, ":");
1631 for (p = globs; *p; p++) {
1633 if (rpmGlob(*p, NULL, &av) == 0) {
1634 argvAppend(&files, av);
1640 /* Read each file in rcfiles. */
1641 for (p = files; *p; p++) {
1642 /* XXX Only /usr/lib/rpm/rpmrc must exist in default rcfiles list */
1643 if (access(*p, R_OK) != 0) {
1644 if (rcfiles == defrcfiles && p != files)
1646 rpmlog(RPMLOG_ERR, _("Unable to open %s for reading: %m.\n"), *p);
1654 rpmSetMachine(NULL, NULL); /* XXX WTFO? Why bother? */
1661 int rpmReadConfigFiles(const char * file, const char * target)
1664 /* Reset umask to its default umask(2) value. */
1667 /* Initialize crypto engine as early as possible */
1668 if (rpmInitCrypto() < 0) {
1671 /* Force preloading of name service libraries in case we go chrooting */
1672 (void) gethostbyname("localhost");
1674 /* Preset target macros */
1675 /* FIX: target can be NULL */
1676 rpmRebuildTargetVars(&target, NULL);
1678 /* Read the files */
1679 if (rpmReadRC(file)) return -1;
1681 if (macrofiles != NULL) {
1682 char *mf = rpmGetPath(macrofiles, NULL);
1683 rpmInitMacros(NULL, mf);
1687 /* Reset target macros */
1688 rpmRebuildTargetVars(&target, NULL);
1690 /* Finally set target platform */
1691 { char *cpu = rpmExpand("%{_target_cpu}", NULL);
1692 char *os = rpmExpand("%{_target_os}", NULL);
1693 rpmSetMachine(cpu, os);
1698 /* Force Lua state initialization */
1700 (void)rpmluaGetPrintBuffer(NULL);
1706 int rpmShowRC(FILE * fp)
1708 const struct rpmOption *opt;
1711 machEquivTable equivTable;
1713 /* the caller may set the build arch which should be printed here */
1714 fprintf(fp, "ARCHITECTURE AND OS:\n");
1715 fprintf(fp, "build arch : %s\n", current[ARCH]);
1717 fprintf(fp, "compatible build archs:");
1718 equivTable = &tables[RPM_MACHTABLE_BUILDARCH].equiv;
1719 for (i = 0; i < equivTable->count; i++)
1720 fprintf(fp," %s", equivTable->list[i].name);
1723 fprintf(fp, "build os : %s\n", current[OS]);
1725 fprintf(fp, "compatible build os's :");
1726 equivTable = &tables[RPM_MACHTABLE_BUILDOS].equiv;
1727 for (i = 0; i < equivTable->count; i++)
1728 fprintf(fp," %s", equivTable->list[i].name);
1731 rpmSetTables(RPM_MACHTABLE_INSTARCH, RPM_MACHTABLE_INSTOS);
1732 rpmSetMachine(NULL, NULL); /* XXX WTFO? Why bother? */
1734 fprintf(fp, "install arch : %s\n", current[ARCH]);
1735 fprintf(fp, "install os : %s\n", current[OS]);
1737 fprintf(fp, "compatible archs :");
1738 equivTable = &tables[RPM_MACHTABLE_INSTARCH].equiv;
1739 for (i = 0; i < equivTable->count; i++)
1740 fprintf(fp," %s", equivTable->list[i].name);
1743 fprintf(fp, "compatible os's :");
1744 equivTable = &tables[RPM_MACHTABLE_INSTOS].equiv;
1745 for (i = 0; i < equivTable->count; i++)
1746 fprintf(fp," %s", equivTable->list[i].name);
1749 fprintf(fp, "\nRPMRC VALUES:\n");
1750 for (i = 0, opt = optionTable; i < optionTableSize; i++, opt++) {
1751 const char *s = rpmGetVar(opt->var);
1752 if (s != NULL || rpmIsVerbose())
1753 fprintf(fp, "%-21s : %s\n", opt->name, s ? s : "(not set)");
1757 fprintf(fp, "Features supported by rpmlib:\n");
1758 xx = rpmdsRpmlib(&ds, NULL);
1760 while (rpmdsNext(ds) >= 0) {
1761 const char * DNEVR = rpmdsDNEVR(ds);
1763 fprintf(fp, " %s\n", DNEVR+2);
1768 rpmDumpMacroTable(NULL, fp);