12 #if HAVE_SYS_UTSNAME_H
13 #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 #ifdef HAVE_SYS_AUXV_H
27 #include <rpm/rpmlib.h> /* RPM_MACTABLE*, Rc-prototypes */
28 #include <rpm/rpmmacro.h>
29 #include <rpm/rpmfileutil.h>
30 #include <rpm/rpmstring.h>
31 #include <rpm/rpmlog.h>
34 #include "rpmio/rpmlua.h"
35 #include "rpmio/rpmio_internal.h" /* XXX for rpmioSlurp */
37 #include "lib/rpmliblua.h"
38 #include "lib/rpmug.h"
42 static const char * defrcfiles = NULL;
43 const char * macrofiles = NULL;
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 /* XXX get rid of this stuff... */
115 /* Stuff for maintaining "variables" like SOURCEDIR, BUILDDIR, etc */
116 #define RPMVAR_OPTFLAGS 3
117 #define RPMVAR_ARCHCOLOR 42
118 #define RPMVAR_INCLUDE 43
119 #define RPMVAR_MACROFILES 49
121 #define RPMVAR_NUM 55 /* number of RPMVAR entries */
123 /* this *must* be kept in alphabetical order */
124 /* The order of the flags is archSpecific, macroize, localize */
126 static const struct rpmOption optionTable[] = {
127 { "archcolor", RPMVAR_ARCHCOLOR, 1, 0, 0 },
128 { "include", RPMVAR_INCLUDE, 0, 0, 2 },
129 { "macrofiles", RPMVAR_MACROFILES, 0, 0, 1 },
130 { "optflags", RPMVAR_OPTFLAGS, 1, 1, 0 },
133 static const size_t optionTableSize = sizeof(optionTable) / sizeof(*optionTable);
138 typedef struct rpmrcCtx_s * rpmrcCtx;
143 struct rpmvarValue values[RPMVAR_NUM];
144 struct tableType_s tables[RPM_MACHTABLE_COUNT];
147 pthread_rwlock_t lock;
151 static rpmRC doReadRC(rpmrcCtx ctx, const char * urlfn);
153 static void rpmSetVarArch(rpmrcCtx ctx,
154 int var, const char * val, const char * arch);
156 static void rebuildCompatTables(rpmrcCtx ctx, int type, const char * name);
158 static void rpmRebuildTargetVars(rpmrcCtx ctx, const char **target, const char ** canontarget);
160 /* Force context (lock) acquisition through a function */
161 static rpmrcCtx rpmrcCtxAcquire(int write)
163 static struct rpmrcCtx_s _globalCtx = {
164 .lock = PTHREAD_RWLOCK_INITIALIZER,
165 .currTables = { RPM_MACHTABLE_INSTOS, RPM_MACHTABLE_INSTARCH },
169 { "buildarch", 0, 1 },
173 rpmrcCtx ctx = &_globalCtx;
175 /* XXX: errors should be handled */
177 pthread_rwlock_wrlock(&ctx->lock);
179 pthread_rwlock_rdlock(&ctx->lock);
184 /* Release context (lock) */
185 static rpmrcCtx rpmrcCtxRelease(rpmrcCtx ctx)
187 pthread_rwlock_unlock(&ctx->lock);
191 static int optionCompare(const void * a, const void * b)
193 return rstrcasecmp(((const struct rpmOption *) a)->name,
194 ((const struct rpmOption *) b)->name);
197 static machCacheEntry
198 machCacheFindEntry(const machCache cache, const char * key)
202 for (i = 0; i < cache->size; i++)
203 if (rstreq(cache->cache[i].name, key)) return cache->cache + i;
208 static int machCompatCacheAdd(char * name, const char * fn, int linenum,
211 machCacheEntry entry = NULL;
217 while (*name && risspace(*name)) name++;
220 while (*chptr && *chptr != ':') chptr++;
222 rpmlog(RPMLOG_ERR, _("missing second ':' at %s:%d\n"), fn, linenum);
224 } else if (chptr == name) {
225 rpmlog(RPMLOG_ERR, _("missing architecture name at %s:%d\n"), fn,
230 while (*chptr == ':' || risspace(*chptr)) chptr--;
233 while (*equivs && risspace(*equivs)) equivs++;
239 entry = machCacheFindEntry(cache, name);
241 for (i = 0; i < entry->count; i++)
242 entry->equivs[i] = _free(entry->equivs[i]);
243 entry->equivs = _free(entry->equivs);
249 cache->cache = xrealloc(cache->cache,
250 (cache->size + 1) * sizeof(*cache->cache));
251 entry = cache->cache + cache->size++;
252 entry->name = xstrdup(name);
257 if (delEntry) return 0;
259 while ((chptr = strtok(equivs, " ")) != NULL) {
261 if (chptr[0] == '\0') /* does strtok() return "" ever?? */
264 entry->equivs = xrealloc(entry->equivs, sizeof(*entry->equivs)
265 * (entry->count + 1));
267 entry->equivs = xmalloc(sizeof(*entry->equivs));
269 entry->equivs[entry->count] = xstrdup(chptr);
277 machEquivSearch(const machEquivTable table, const char * name)
281 for (i = 0; i < table->count; i++)
282 if (!rstrcasecmp(table->list[i].name, name))
283 return table->list + i;
288 static void machAddEquiv(machEquivTable table, const char * name,
293 equiv = machEquivSearch(table, name);
296 table->list = xrealloc(table->list, (table->count + 1)
297 * sizeof(*table->list));
299 table->list = xmalloc(sizeof(*table->list));
301 table->list[table->count].name = xstrdup(name);
302 table->list[table->count++].score = distance;
306 static void machCacheEntryVisit(machCache cache,
307 machEquivTable table, const char * name, int distance)
309 machCacheEntry entry;
312 entry = machCacheFindEntry(cache, name);
313 if (!entry || entry->visited) return;
317 for (i = 0; i < entry->count; i++) {
318 machAddEquiv(table, entry->equivs[i], distance);
321 for (i = 0; i < entry->count; i++) {
322 machCacheEntryVisit(cache, table, entry->equivs[i], distance + 1);
326 static void machFindEquivs(machCache cache, machEquivTable table,
331 for (i = 0; i < cache->size; i++)
332 cache->cache[i].visited = 0;
334 while (table->count > 0) {
336 table->list[table->count].name = _free(table->list[table->count].name);
339 table->list = _free(table->list);
342 * We have a general graph built using strings instead of pointers.
343 * Yuck. We have to start at a point at traverse it, remembering how
344 * far away everything is.
346 /* FIX: table->list may be NULL. */
347 machAddEquiv(table, key, 1);
348 machCacheEntryVisit(cache, table, key, 2);
352 static rpmRC addCanon(canonEntry * table, int * tableLen, char * line,
353 const char * fn, int lineNum)
358 const char * tshort_name;
362 *table = xrealloc(*table, sizeof(**table) * (*tableLen));
364 t = & ((*table)[*tableLen - 2]);
366 tname = strtok(line, ": \t");
367 tshort_name = strtok(NULL, " \t");
368 s = strtok(NULL, " \t");
369 if (! (tname && tshort_name && s)) {
370 rpmlog(RPMLOG_ERR, _("Incomplete data line at %s:%d\n"),
374 if (strtok(NULL, " \t")) {
375 rpmlog(RPMLOG_ERR, _("Too many args in data line at %s:%d\n"),
380 tnum = strtoul(s, &s1, 10);
381 if ((*s1) || (s1 == s) || (tnum == ULONG_MAX)) {
382 rpmlog(RPMLOG_ERR, _("Bad arch/os number: %s (%s:%d)\n"), s,
387 t[0].name = xstrdup(tname);
388 t[0].short_name = (tshort_name ? xstrdup(tshort_name) : xstrdup(""));
391 /* From A B C entry */
392 /* Add B B C entry */
393 t[1].name = (tshort_name ? xstrdup(tshort_name) : xstrdup(""));
394 t[1].short_name = (tshort_name ? xstrdup(tshort_name) : xstrdup(""));
400 static rpmRC addDefault(defaultEntry * table, int * tableLen, char * line,
401 const char * fn, int lineNum)
406 *table = xrealloc(*table, sizeof(**table) * (*tableLen));
408 t = & ((*table)[*tableLen - 1]);
410 t->name = strtok(line, ": \t");
411 t->defName = strtok(NULL, " \t");
412 if (! (t->name && t->defName)) {
413 rpmlog(RPMLOG_ERR, _("Incomplete default line at %s:%d\n"),
417 if (strtok(NULL, " \t")) {
418 rpmlog(RPMLOG_ERR, _("Too many args in default line at %s:%d\n"),
423 t->name = xstrdup(t->name);
424 t->defName = (t->defName ? xstrdup(t->defName) : NULL);
429 static canonEntry lookupInCanonTable(const char * name,
430 const canonEntry table, int tableLen)
434 if (!rstreq(name, table[tableLen].name))
436 return &(table[tableLen]);
443 const char * lookupInDefaultTable(const char * name,
444 const defaultEntry table, int tableLen)
448 if (table[tableLen].name && rstreq(name, table[tableLen].name))
449 return table[tableLen].defName;
455 static void setDefaults(void)
457 const char *confdir = rpmConfigDir();
459 defrcfiles = rstrscat(NULL, confdir, "/rpmrc", ":",
460 confdir, "/" RPMCANONVENDOR "/rpmrc", ":",
461 SYSCONFDIR "/rpmrc", ":",
467 macrofiles = rstrscat(NULL, confdir, "/macros", ":",
468 confdir, "/macros.d/macros.*", ":",
469 confdir, "/platform/%{_target}/macros", ":",
470 confdir, "/fileattrs/*.attr", ":",
471 confdir, "/" RPMCANONVENDOR "/macros", ":",
472 SYSCONFDIR "/rpm/macros.*", ":",
473 SYSCONFDIR "/rpm/macros", ":",
474 SYSCONFDIR "/rpm/%{_target}/macros", ":",
475 "~/.rpmmacros", NULL);
478 macrofiles = MACROFILES;
482 /* FIX: se usage inconsistent, W2DO? */
483 static rpmRC doReadRC(rpmrcCtx ctx, const char * urlfn)
486 char *se, *next, *buf = NULL, *fn;
488 struct rpmOption searchOption, * option;
489 rpmRC rc = RPMRC_FAIL;
491 fn = rpmGetPath(urlfn, NULL);
492 if (rpmioSlurp(fn, (uint8_t **) &buf, NULL) || buf == NULL) {
497 while (*next != '\0') {
502 /* Find end-of-line. */
503 while (*se && *se != '\n') se++;
504 if (*se != '\0') *se++ = '\0';
507 /* Trim leading spaces */
508 while (*s && risspace(*s)) s++;
510 /* We used to allow comments to begin anywhere, but not anymore. */
511 if (*s == '#' || *s == '\0') continue;
513 /* Find end-of-keyword. */
515 while (*se && !risspace(*se) && *se != ':') se++;
519 while (*se && risspace(*se) && *se != ':') se++;
523 rpmlog(RPMLOG_ERR, _("missing ':' (found 0x%02x) at %s:%d\n"),
524 (unsigned)(0xff & *se), fn, linenum);
527 *se++ = '\0'; /* terminate keyword or option, point to value */
528 while (*se && risspace(*se)) se++;
530 /* Find keyword in table */
531 searchOption.name = s;
532 option = bsearch(&searchOption, optionTable, optionTableSize,
533 sizeof(optionTable[0]), optionCompare);
535 if (option) { /* For configuration variables ... */
536 const char *arch, *val;
540 rpmlog(RPMLOG_ERR, _("missing argument for %s at %s:%d\n"),
541 option->name, fn, linenum);
545 if (option->var == RPMVAR_INCLUDE) {
547 while (*se && !risspace(*se)) se++;
548 if (*se != '\0') *se = '\0';
550 if (doReadRC(ctx, s)) {
551 rpmlog(RPMLOG_ERR, _("cannot open %s at %s:%d: %m\n"),
555 /* XXX don't save include value as var/macro */
559 if (option->archSpecific) {
561 while (*se && !risspace(*se)) se++;
564 _("missing architecture for %s at %s:%d\n"),
565 option->name, fn, linenum);
569 while (*se && risspace(*se)) se++;
572 _("missing argument for %s at %s:%d\n"),
573 option->name, fn, linenum);
580 /* Only add macros if appropriate for this arch */
581 if (option->macroize &&
582 (arch == NULL || rstreq(arch, ctx->current[ARCH]))) {
584 n = name = xmalloc(strlen(option->name)+2);
585 if (option->localize)
587 strcpy(n, option->name);
588 rpmPushMacro(NULL, name, NULL, val, RMIL_RPMRC);
591 rpmSetVarArch(ctx, option->var, val, arch);
594 } else { /* For arch/os compatibility tables ... */
600 for (i = 0; i < RPM_MACHTABLE_COUNT; i++) {
601 if (rstreqn(ctx->tables[i].key, s, strlen(ctx->tables[i].key)))
605 if (i < RPM_MACHTABLE_COUNT) {
606 const char *rest = s + strlen(ctx->tables[i].key);
607 if (*rest == '_') rest++;
609 if (rstreq(rest, "compat")) {
610 if (machCompatCacheAdd(se, fn, linenum,
611 &ctx->tables[i].cache))
614 } else if (ctx->tables[i].hasTranslate &&
615 rstreq(rest, "translate")) {
616 if (addDefault(&ctx->tables[i].defaults,
617 &ctx->tables[i].defaultsLength,
621 } else if (ctx->tables[i].hasCanon &&
622 rstreq(rest, "canon")) {
623 if (addCanon(&ctx->tables[i].canons,
624 &ctx->tables[i].canonsLength,
632 rpmlog(RPMLOG_ERR, _("bad option '%s' at %s:%d\n"),
650 static rpmRC rpmPlatform(rpmrcCtx ctx, const char * platform)
652 const char *cpu = NULL, *vendor = NULL, *os = NULL, *gnu = NULL;
655 int init_platform = 0;
659 rc = (rpmioSlurp(platform, &b, &blen) == 0) ? RPMRC_OK : RPMRC_FAIL;
661 if (rc || b == NULL || blen <= 0) {
667 for (pe = p; p && *p; p = pe) {
668 pe = strchr(p, '\n');
672 while (*p && isspace(*p))
674 if (*p == '\0' || *p == '#')
678 char * t = p + strlen(p);
680 while (--t > p && isspace(*t))
683 argvAdd(&ctx->platpat, p);
692 while (*p && !(*p == '-' || isspace(*p)))
694 if (*p != '\0') *p++ = '\0';
697 while (*p && !(*p == '-' || isspace(*p)))
700 if (*p != '\0') *p = '\0';
704 if (*p != '\0') *p++ = '\0';
707 while (*p && !(*p == '-' || isspace(*p)))
713 while (*p && !(*p == '-' || isspace(*p)))
716 if (*p != '\0') *p = '\0';
719 rpmPushMacro(NULL, "_host_cpu", NULL, cpu, -1);
720 rpmPushMacro(NULL, "_host_vendor", NULL, vendor, -1);
721 rpmPushMacro(NULL, "_host_os", NULL, os, -1);
723 char *plat = rpmExpand("%{_host_cpu}-%{_host_vendor}-%{_host_os}",
724 (gnu && *gnu ? "-" : NULL), gnu, NULL);
725 argvAdd(&ctx->platpat, plat);
730 rc = (init_platform ? RPMRC_OK : RPMRC_FAIL);
738 # if defined(__linux__) && defined(__i386__)
743 * Generic CPUID function
745 static inline void cpuid(unsigned int op, unsigned int *eax, unsigned int *ebx, unsigned int *ecx, unsigned int *edx)
750 "movl %%ebx, %%esi \n"
752 : "=a" (*eax), "=S" (*ebx), "=c" (*ecx), "=d" (*edx)
757 * CPUID functions returning a single datum
759 static inline unsigned int cpuid_eax(unsigned int op)
761 unsigned int tmp, val;
762 cpuid(op, &val, &tmp, &tmp, &tmp);
766 static inline unsigned int cpuid_ebx(unsigned int op)
768 unsigned int tmp, val;
769 cpuid(op, &tmp, &val, &tmp, &tmp);
773 static inline unsigned int cpuid_ecx(unsigned int op)
775 unsigned int tmp, val;
776 cpuid(op, &tmp, &tmp, &val, &tmp);
780 static inline unsigned int cpuid_edx(unsigned int op)
782 unsigned int tmp, val;
783 cpuid(op, &tmp, &tmp, &tmp, &val);
787 static sigjmp_buf jenv;
789 static inline void model3(int _unused)
794 static inline int RPMClass(void)
797 unsigned int tfms, junk, cap, capamd;
798 struct sigaction oldsa;
800 sigaction(SIGILL, NULL, &oldsa);
801 signal(SIGILL, model3);
803 if (sigsetjmp(jenv, 1)) {
804 sigaction(SIGILL, &oldsa, NULL);
808 if (cpuid_eax(0x000000000)==0) {
809 sigaction(SIGILL, &oldsa, NULL);
813 cpuid(0x00000001, &tfms, &junk, &junk, &cap);
814 cpuid(0x80000001, &junk, &junk, &junk, &capamd);
819 && cpuid_ecx(0) == '68xM'
820 && cpuid_edx(0) == 'Teni'
821 && (cpuid_edx(1) & ((1<<8)|(1<<15))) == ((1<<8)|(1<<15))) {
822 sigaction(SIGILL, &oldsa, NULL);
823 return 6; /* has CX8 and CMOV */
826 sigaction(SIGILL, &oldsa, NULL);
828 #define USER686 ((1<<4) | (1<<8) | (1<<15))
829 /* Transmeta Crusoe CPUs say that their CPU family is "5" but they have enough features for i686. */
830 if (cpu == 5 && (cap & USER686) == USER686)
837 /* CMOV supported? */
838 if (capamd & (1<<30))
839 return 7; /* 3DNOWEXT supported */
846 /* should only be called for model 6 CPU's */
847 static int is_athlon(void)
849 unsigned int eax, ebx, ecx, edx;
853 cpuid (0, &eax, &ebx, &ecx, &edx);
855 memset(vendor, 0, sizeof(vendor));
858 vendor[i] = (unsigned char) (ebx >>(8*i));
860 vendor[4+i] = (unsigned char) (edx >>(8*i));
862 vendor[8+i] = (unsigned char) (ecx >>(8*i));
864 if (!rstreqn(vendor, "AuthenticAMD", 12))
870 static int is_pentium3(void)
872 unsigned int eax, ebx, ecx, edx, family, model;
874 cpuid(0, &eax, &ebx, &ecx, &edx);
875 memset(vendor, 0, sizeof(vendor));
876 *((unsigned int *)&vendor[0]) = ebx;
877 *((unsigned int *)&vendor[4]) = edx;
878 *((unsigned int *)&vendor[8]) = ecx;
879 if (!rstreqn(vendor, "GenuineIntel", 12))
881 cpuid(1, &eax, &ebx, &ecx, &edx);
882 family = (eax >> 8) & 0x0f;
883 model = (eax >> 4) & 0x0f;
887 case 7: // Pentium III, Pentium III Xeon (model 7)
888 case 8: // Pentium III, Pentium III Xeon, Celeron (model 8)
890 case 10: // Pentium III Xeon (model A)
891 case 11: // Pentium III (model B)
897 static int is_pentium4(void)
899 unsigned int eax, ebx, ecx, edx, family, model;
901 cpuid(0, &eax, &ebx, &ecx, &edx);
902 memset(vendor, 0, sizeof(vendor));
903 *((unsigned int *)&vendor[0]) = ebx;
904 *((unsigned int *)&vendor[4]) = edx;
905 *((unsigned int *)&vendor[8]) = ecx;
906 if (!rstreqn(vendor, "GenuineIntel", 12))
908 cpuid(1, &eax, &ebx, &ecx, &edx);
909 family = (eax >> 8) & 0x0f;
910 model = (eax >> 4) & 0x0f;
914 case 0: // Pentium 4, Pentium 4 Xeon (0.18um)
915 case 1: // Pentium 4, Pentium 4 Xeon MP, Celeron (0.18um)
916 case 2: // Pentium 4, Mobile Pentium 4-M,
917 // Pentium 4 Xeon, Pentium 4 Xeon MP,
918 // Celeron, Mobile Celron (0.13um)
919 case 3: // Pentium 4, Celeron (0.09um)
925 static int is_geode(void)
927 unsigned int eax, ebx, ecx, edx, family, model;
929 memset(vendor, 0, sizeof(vendor));
931 cpuid(0, &eax, &ebx, &ecx, &edx);
932 memset(vendor, 0, sizeof(vendor));
933 *((unsigned int *)&vendor[0]) = ebx;
934 *((unsigned int *)&vendor[4]) = edx;
935 *((unsigned int *)&vendor[8]) = ecx;
936 if (!rstreqn(vendor, "AuthenticAMD", 12))
938 cpuid(1, &eax, &ebx, &ecx, &edx);
939 family = (eax >> 8) & 0x0f;
940 model = (eax >> 4) & 0x0f;
952 #if defined(__linux__)
954 * Populate rpmat structure with auxv values
956 static void read_auxv(void)
958 static int oneshot = 1;
961 #ifdef HAVE_GETAUXVAL
962 rpmat.platform = (char *) getauxval(AT_PLATFORM);
965 rpmat.hwcap = getauxval(AT_HWCAP);
968 int fd = open("/proc/self/auxv", O_RDONLY);
971 rpmlog(RPMLOG_WARNING,
972 _("Failed to read auxiliary vector, /proc not mounted?\n"));
976 while (read(fd, &auxv, sizeof(auxv)) == sizeof(auxv)) {
982 rpmat.platform = strdup((char *) auxv.a_un.a_val);
985 rpmat.hwcap = auxv.a_un.a_val;
992 oneshot = 0; /* only try once even if it fails */
1000 static void defaultMachine(rpmrcCtx ctx, const char ** arch, const char ** os)
1002 const char * const platform_path = SYSCONFDIR "/rpm/platform";
1003 static struct utsname un;
1008 #if defined(__linux__)
1009 /* Populate rpmat struct with hw info */
1013 while (!ctx->machDefaults) {
1014 if (!rpmPlatform(ctx, platform_path)) {
1015 char * s = rpmExpand("%{_host_cpu}", NULL);
1017 rstrlcpy(un.machine, s, sizeof(un.machine));
1020 s = rpmExpand("%{_host_os}", NULL);
1022 rstrlcpy(un.sysname, s, sizeof(un.sysname));
1025 ctx->machDefaults = 1;
1031 #if !defined(__linux__)
1032 if (rstreq(un.sysname, "AIX")) {
1033 strcpy(un.machine, __power_pc() ? "ppc" : "rs6000");
1034 sprintf(un.sysname,"aix%s.%s", un.version, un.release);
1036 else if (rstreq(un.sysname, "Darwin")) {
1037 #if defined(__ppc__)
1038 strcpy(un.machine, "ppc");
1039 #elif defined(__i386__)
1040 strcpy(un.machine, "i386");
1041 #elif defined(__x86_64__)
1042 strcpy(un.machine, "x86_64");
1044 #warning "No architecture defined! Automatic detection may not work!"
1047 else if (rstreq(un.sysname, "SunOS")) {
1048 /* Solaris 2.x: n.x.x becomes n-3.x.x */
1049 sprintf(un.sysname, "solaris%1d%s", atoi(un.release)-3,
1050 un.release+1+(atoi(un.release)/10));
1052 /* Solaris on Intel hardware reports i86pc instead of i386
1053 * (at least on 2.6 and 2.8)
1055 if (rstreq(un.machine, "i86pc"))
1056 sprintf(un.machine, "i386");
1058 else if (rstreq(un.sysname, "HP-UX"))
1059 /*make un.sysname look like hpux9.05 for example*/
1060 sprintf(un.sysname, "hpux%s", strpbrk(un.release, "123456789"));
1061 else if (rstreq(un.sysname, "OSF1"))
1062 /*make un.sysname look like osf3.2 for example*/
1063 sprintf(un.sysname, "osf%s", strpbrk(un.release, "123456789"));
1064 #endif /* __linux__ */
1066 /* get rid of the hyphens in the sysname */
1067 for (chptr = un.machine; *chptr != '\0'; chptr++)
1068 if (*chptr == '/') *chptr = '-';
1070 # if defined(__MIPSEL__) || defined(__MIPSEL) || defined(_MIPSEL)
1072 # if defined(__mips64)
1074 # if !defined(__mips_isa_rev) || __mips_isa_rev < 6
1076 strcpy(un.machine, "mips64el");
1079 strcpy(un.machine, "mips64r6el");
1083 # if !defined(__mips_isa_rev) || __mips_isa_rev < 6
1085 strcpy(un.machine, "mipsel");
1088 strcpy(un.machine, "mipsr6el");
1091 # elif defined(__MIPSEB__) || defined(__MIPSEB) || defined(_MIPSEB)
1093 # if defined(__mips64)
1095 # if !defined(__mips_isa_rev) || __mips_isa_rev < 6
1097 strcpy(un.machine, "mips64");
1100 strcpy(un.machine, "mips64r6");
1104 # if !defined(__mips_isa_rev) || __mips_isa_rev < 6
1106 strcpy(un.machine, "mips");
1109 strcpy(un.machine, "mipsr6");
1114 #if defined(__linux__)
1115 /* in linux, lets rename parisc to hppa */
1116 if (rstreq(un.machine, "parisc"))
1117 strcpy(un.machine, "hppa");
1120 # if defined(__hpux) && defined(_SC_CPU_VERSION)
1122 # if !defined(CPU_PA_RISC1_2)
1123 # define CPU_PA_RISC1_2 0x211 /* HP PA-RISC1.2 */
1125 # if !defined(CPU_PA_RISC2_0)
1126 # define CPU_PA_RISC2_0 0x214 /* HP PA-RISC2.0 */
1128 int cpu_version = sysconf(_SC_CPU_VERSION);
1130 # if defined(CPU_HP_MC68020)
1131 if (cpu_version == CPU_HP_MC68020)
1132 strcpy(un.machine, "m68k");
1134 # if defined(CPU_HP_MC68030)
1135 if (cpu_version == CPU_HP_MC68030)
1136 strcpy(un.machine, "m68k");
1138 # if defined(CPU_HP_MC68040)
1139 if (cpu_version == CPU_HP_MC68040)
1140 strcpy(un.machine, "m68k");
1143 # if defined(CPU_PA_RISC1_0)
1144 if (cpu_version == CPU_PA_RISC1_0)
1145 strcpy(un.machine, "hppa1.0");
1147 # if defined(CPU_PA_RISC1_1)
1148 if (cpu_version == CPU_PA_RISC1_1)
1149 strcpy(un.machine, "hppa1.1");
1151 # if defined(CPU_PA_RISC1_2)
1152 if (cpu_version == CPU_PA_RISC1_2)
1153 strcpy(un.machine, "hppa1.2");
1155 # if defined(CPU_PA_RISC2_0)
1156 if (cpu_version == CPU_PA_RISC2_0)
1157 strcpy(un.machine, "hppa2.0");
1162 # if defined(__linux__) && defined(__sparc__)
1163 # if !defined(HWCAP_SPARC_BLKINIT)
1164 # define HWCAP_SPARC_BLKINIT 0x00000040
1166 if (rstreq(un.machine, "sparc")) {
1167 #define PERS_LINUX 0x00000000
1168 #define PERS_LINUX_32BIT 0x00800000
1169 #define PERS_LINUX32 0x00000008
1171 extern int personality(unsigned long);
1174 oldpers = personality(PERS_LINUX_32BIT);
1175 if (oldpers != -1) {
1176 if (personality(PERS_LINUX) != -1) {
1178 if (rstreq(un.machine, "sparc64")) {
1179 strcpy(un.machine, "sparcv9");
1180 oldpers = PERS_LINUX32;
1183 personality(oldpers);
1186 /* This is how glibc detects Niagara so... */
1187 if (rpmat.hwcap & HWCAP_SPARC_BLKINIT) {
1188 if (rstreq(un.machine, "sparcv9") || rstreq(un.machine, "sparc")) {
1189 strcpy(un.machine, "sparcv9v");
1190 } else if (rstreq(un.machine, "sparc64")) {
1191 strcpy(un.machine, "sparc64v");
1195 # endif /* sparc*-linux */
1197 # if defined(__linux__) && defined(__powerpc__)
1198 # if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
1201 if (!rstreq(un.machine, "ppc") &&
1202 sscanf(rpmat.platform, "power%d", &powerlvl) == 1 &&
1204 strcpy(un.machine, "ppc64p7");
1207 # endif /* __ORDER_BIG_ENDIAN__ */
1208 # endif /* ppc64*-linux */
1210 # if defined(__linux__) && defined(__arm__) && defined(__ARM_PCS_VFP)
1211 # if !defined(HWCAP_ARM_VFP)
1212 # define HWCAP_ARM_VFP (1 << 6)
1214 # if !defined(HWCAP_ARM_NEON)
1215 # define HWCAP_ARM_NEON (1 << 12)
1217 # if !defined(HWCAP_ARM_VFPv3)
1218 # define HWCAP_ARM_VFPv3 (1 << 13)
1220 if (rstreq(un.machine, "armv7l")) {
1221 if (rpmat.hwcap & HWCAP_ARM_VFPv3) {
1222 if (rpmat.hwcap & HWCAP_ARM_NEON)
1223 strcpy(un.machine, "armv7hnl");
1225 strcpy(un.machine, "armv7hl");
1227 } else if (rstreq(un.machine, "armv6l")) {
1228 if (rpmat.hwcap & HWCAP_ARM_VFP)
1229 strcpy(un.machine, "armv6hl");
1231 # endif /* arm*-linux */
1233 # if defined(__linux__) && defined(__riscv__)
1234 if (rstreq(un.machine, "riscv")) {
1235 if (sizeof(long) == 4)
1236 strcpy(un.machine, "riscv32");
1237 else if (sizeof(long) == 8)
1238 strcpy(un.machine, "riscv64");
1239 else if (sizeof(long) == 16)
1240 strcpy(un.machine, "riscv128");
1244 # if defined(__GNUC__) && defined(__alpha__)
1246 unsigned long amask, implver;
1247 register long v0 __asm__("$0") = -1;
1248 __asm__ (".long 0x47e00c20" : "=r"(v0) : "0"(v0));
1250 __asm__ (".long 0x47e03d80" : "=r"(v0));
1255 case 0: strcpy(un.machine, "alphaev5"); break;
1256 case 1: strcpy(un.machine, "alphaev56"); break;
1257 case 0x101: strcpy(un.machine, "alphapca56"); break;
1262 case 0x303: strcpy(un.machine, "alphaev6"); break;
1263 case 0x307: strcpy(un.machine, "alphaev67"); break;
1270 # if defined(__linux__) && defined(__i386__)
1272 char mclass = (char) (RPMClass() | '0');
1274 if ((mclass == '6' && is_athlon()) || mclass == '7')
1275 strcpy(un.machine, "athlon");
1276 else if (is_pentium4())
1277 strcpy(un.machine, "pentium4");
1278 else if (is_pentium3())
1279 strcpy(un.machine, "pentium3");
1280 else if (is_geode())
1281 strcpy(un.machine, "geode");
1282 else if (strchr("3456", un.machine[1]) && un.machine[1] != mclass)
1283 un.machine[1] = mclass;
1287 /* the uname() result goes through the arch_canon table */
1288 canon = lookupInCanonTable(un.machine,
1289 ctx->tables[RPM_MACHTABLE_INSTARCH].canons,
1290 ctx->tables[RPM_MACHTABLE_INSTARCH].canonsLength);
1292 rstrlcpy(un.machine, canon->short_name, sizeof(un.machine));
1294 canon = lookupInCanonTable(un.sysname,
1295 ctx->tables[RPM_MACHTABLE_INSTOS].canons,
1296 ctx->tables[RPM_MACHTABLE_INSTOS].canonsLength);
1298 rstrlcpy(un.sysname, canon->short_name, sizeof(un.sysname));
1299 ctx->machDefaults = 1;
1303 if (arch) *arch = un.machine;
1304 if (os) *os = un.sysname;
1308 const char * rpmGetVarArch(rpmrcCtx ctx, int var, const char * arch)
1310 const struct rpmvarValue * next;
1312 if (arch == NULL) arch = ctx->current[ARCH];
1315 next = &ctx->values[var];
1317 if (next->arch && rstreq(next->arch, arch)) return next->value;
1322 next = ctx->values + var;
1323 while (next && next->arch) next = next->next;
1325 return next ? next->value : NULL;
1328 static void rpmSetVarArch(rpmrcCtx ctx,
1329 int var, const char * val, const char * arch)
1331 struct rpmvarValue * next = ctx->values + var;
1335 while (next->next) {
1336 if (next->arch && rstreq(next->arch, arch)) break;
1340 while (next->next) {
1341 if (!next->arch) break;
1346 if (next->arch && arch && rstreq(next->arch, arch)) {
1347 next->value = _free(next->value);
1348 next->arch = _free(next->arch);
1349 } else if (next->arch || arch) {
1350 next->next = xmalloc(sizeof(*next->next));
1358 next->value = _free(next->value);
1359 next->value = xstrdup(val);
1360 next->arch = (arch ? xstrdup(arch) : NULL);
1363 static void rpmSetTables(rpmrcCtx ctx, int archTable, int osTable)
1365 const char * arch, * os;
1367 defaultMachine(ctx, &arch, &os);
1369 if (ctx->currTables[ARCH] != archTable) {
1370 ctx->currTables[ARCH] = archTable;
1371 rebuildCompatTables(ctx, ARCH, arch);
1374 if (ctx->currTables[OS] != osTable) {
1375 ctx->currTables[OS] = osTable;
1376 rebuildCompatTables(ctx, OS, os);
1381 * Set current arch/os names.
1382 * NULL as argument is set to the default value (munged uname())
1383 * pushed through a translation table (if appropriate).
1384 * @deprecated Use addMacro to set _target_* macros.
1387 * @param ctx rpmrc context
1388 * @param arch arch name (or NULL)
1389 * @param os os name (or NULL)
1392 static void rpmSetMachine(rpmrcCtx ctx, const char * arch, const char * os)
1394 const char * host_cpu, * host_os;
1396 defaultMachine(ctx, &host_cpu, &host_os);
1400 if (ctx->tables[ctx->currTables[ARCH]].hasTranslate)
1401 arch = lookupInDefaultTable(arch,
1402 ctx->tables[ctx->currTables[ARCH]].defaults,
1403 ctx->tables[ctx->currTables[ARCH]].defaultsLength);
1405 if (arch == NULL) return; /* XXX can't happen */
1409 if (ctx->tables[ctx->currTables[OS]].hasTranslate)
1410 os = lookupInDefaultTable(os,
1411 ctx->tables[ctx->currTables[OS]].defaults,
1412 ctx->tables[ctx->currTables[OS]].defaultsLength);
1414 if (os == NULL) return; /* XXX can't happen */
1416 if (!ctx->current[ARCH] || !rstreq(arch, ctx->current[ARCH])) {
1417 ctx->current[ARCH] = _free(ctx->current[ARCH]);
1418 ctx->current[ARCH] = xstrdup(arch);
1419 rebuildCompatTables(ctx, ARCH, host_cpu);
1422 if (!ctx->current[OS] || !rstreq(os, ctx->current[OS])) {
1423 char * t = xstrdup(os);
1424 ctx->current[OS] = _free(ctx->current[OS]);
1426 * XXX Capitalizing the 'L' is needed to insure that old
1427 * XXX os-from-uname (e.g. "Linux") is compatible with the new
1428 * XXX os-from-platform (e.g "linux" from "sparc-*-linux").
1429 * XXX A copy of this string is embedded in headers and is
1430 * XXX used by rpmInstallPackage->{os,arch}Okay->rpmMachineScore->
1431 * XXX to verify correct arch/os from headers.
1433 if (rstreq(t, "linux"))
1435 ctx->current[OS] = t;
1437 rebuildCompatTables(ctx, OS, host_os);
1441 static void rebuildCompatTables(rpmrcCtx ctx, int type, const char * name)
1443 machFindEquivs(&ctx->tables[ctx->currTables[type]].cache,
1444 &ctx->tables[ctx->currTables[type]].equiv,
1448 static void getMachineInfo(rpmrcCtx ctx,
1449 int type, const char ** name, int * num)
1452 int which = ctx->currTables[type];
1454 /* use the normal canon tables, even if we're looking up build stuff */
1455 if (which >= 2) which -= 2;
1457 canon = lookupInCanonTable(ctx->current[type],
1458 ctx->tables[which].canons,
1459 ctx->tables[which].canonsLength);
1462 if (num) *num = canon->num;
1463 if (name) *name = canon->short_name;
1465 if (num) *num = 255;
1466 if (name) *name = ctx->current[type];
1468 if (ctx->tables[ctx->currTables[type]].hasCanon) {
1469 rpmlog(RPMLOG_WARNING, _("Unknown system: %s\n"),
1470 ctx->current[type]);
1471 rpmlog(RPMLOG_WARNING, _("Please contact %s\n"), PACKAGE_BUGREPORT);
1476 static void rpmRebuildTargetVars(rpmrcCtx ctx,
1477 const char ** target, const char ** canontarget)
1480 char *ca = NULL, *co = NULL, *ct = NULL;
1483 /* Rebuild the compat table to recalculate the current target arch. */
1485 rpmSetMachine(ctx, NULL, NULL);
1486 rpmSetTables(ctx, RPM_MACHTABLE_INSTARCH, RPM_MACHTABLE_INSTOS);
1487 rpmSetTables(ctx, RPM_MACHTABLE_BUILDARCH, RPM_MACHTABLE_BUILDOS);
1489 if (target && *target) {
1491 /* Set arch and os from specified build target */
1492 ca = xstrdup(*target);
1493 if ((c = strchr(ca, '-')) != NULL) {
1496 if ((co = strrchr(c, '-')) == NULL) {
1499 if (!rstrcasecmp(co, "-gnu"))
1501 if ((co = strrchr(c, '-')) == NULL)
1506 if (co != NULL) co = xstrdup(co);
1509 const char *a = NULL;
1510 const char *o = NULL;
1511 /* Set build target from rpm arch and os */
1512 getMachineInfo(ctx, ARCH, &a, NULL);
1513 ca = (a) ? xstrdup(a) : NULL;
1514 getMachineInfo(ctx, OS, &o, NULL);
1515 co = (o) ? xstrdup(o) : NULL;
1518 /* If still not set, Set target arch/os from default uname(2) values */
1520 const char *a = NULL;
1521 defaultMachine(ctx, &a, NULL);
1522 ca = xstrdup(a ? a : "(arch)");
1524 for (x = 0; ca[x] != '\0'; x++)
1525 ca[x] = rtolower(ca[x]);
1528 const char *o = NULL;
1529 defaultMachine(ctx, NULL, &o);
1530 co = xstrdup(o ? o : "(os)");
1532 for (x = 0; co[x] != '\0'; x++)
1533 co[x] = rtolower(co[x]);
1535 /* XXX For now, set canonical target to arch-os */
1537 rasprintf(&ct, "%s-%s", ca, co);
1541 * XXX All this macro pokery/jiggery could be achieved by doing a delayed
1542 * rpmInitMacros(NULL, PER-PLATFORM-MACRO-FILE-NAMES);
1544 rpmPopMacro(NULL, "_target");
1545 rpmPushMacro(NULL, "_target", NULL, ct, RMIL_RPMRC);
1546 rpmPopMacro(NULL, "_target_cpu");
1547 rpmPushMacro(NULL, "_target_cpu", NULL, ca, RMIL_RPMRC);
1548 rpmPopMacro(NULL, "_target_os");
1549 rpmPushMacro(NULL, "_target_os", NULL, co, RMIL_RPMRC);
1551 * XXX Make sure that per-arch optflags is initialized correctly.
1553 { const char *optflags = rpmGetVarArch(ctx, RPMVAR_OPTFLAGS, ca);
1554 if (optflags != NULL) {
1555 rpmPopMacro(NULL, "optflags");
1556 rpmPushMacro(NULL, "optflags", NULL, optflags, RMIL_RPMRC);
1569 * Read rpmrc (and macro) configuration file(s).
1570 * @param ctx rpmrc context
1571 * @param rcfiles colon separated files to read (NULL uses default)
1572 * @return RPMRC_OK on success
1574 static rpmRC rpmReadRC(rpmrcCtx ctx, const char * rcfiles)
1576 ARGV_t p, globs = NULL, files = NULL;
1577 rpmRC rc = RPMRC_FAIL;
1579 if (!ctx->pathDefaults) {
1581 ctx->pathDefaults = 1;
1584 if (rcfiles == NULL)
1585 rcfiles = defrcfiles;
1587 /* Expand any globs in rcfiles. Missing files are ok here. */
1588 argvSplit(&globs, rcfiles, ":");
1589 for (p = globs; *p; p++) {
1591 if (rpmGlob(*p, NULL, &av) == 0) {
1592 argvAppend(&files, av);
1598 /* Read each file in rcfiles. */
1599 for (p = files; p && *p; p++) {
1600 /* XXX Only /usr/lib/rpm/rpmrc must exist in default rcfiles list */
1601 if (access(*p, R_OK) != 0) {
1602 if (rcfiles == defrcfiles && p != files)
1604 rpmlog(RPMLOG_ERR, _("Unable to open %s for reading: %m.\n"), *p);
1608 rc = doReadRC(ctx, *p);
1612 rpmSetMachine(ctx, NULL, NULL); /* XXX WTFO? Why bother? */
1619 static void register_atexit(void)
1621 if (atexit(rpmAtExit) != 0)
1622 rpmlog(RPMLOG_WARNING, _("failed to register exit handler"));
1625 /* External interfaces */
1627 int rpmReadConfigFiles(const char * file, const char * target)
1629 static pthread_once_t atexit_registered = PTHREAD_ONCE_INIT;
1630 int rc = -1; /* assume failure */
1631 rpmrcCtx ctx = rpmrcCtxAcquire(1);
1633 pthread_once(&atexit_registered, register_atexit);
1635 /* Force preloading of dlopen()'ed libraries in case we go chrooting */
1639 if (rpmInitCrypto())
1642 /* Preset target macros */
1643 /* FIX: target can be NULL */
1644 rpmRebuildTargetVars(ctx, &target, NULL);
1646 /* Read the files */
1647 if (rpmReadRC(ctx, file))
1650 if (macrofiles != NULL) {
1651 char *mf = rpmGetPath(macrofiles, NULL);
1652 rpmInitMacros(NULL, mf);
1656 /* Reset target macros */
1657 rpmRebuildTargetVars(ctx, &target, NULL);
1659 /* Finally set target platform */
1660 { char *cpu = rpmExpand("%{_target_cpu}", NULL);
1661 char *os = rpmExpand("%{_target_os}", NULL);
1662 rpmSetMachine(ctx, cpu, os);
1668 /* Force Lua state initialization */
1674 rpmrcCtxRelease(ctx);
1678 void rpmFreeRpmrc(void)
1680 rpmrcCtx ctx = rpmrcCtxAcquire(1);
1683 ctx->platpat = argvFree(ctx->platpat);
1685 for (i = 0; i < RPM_MACHTABLE_COUNT; i++) {
1687 t = ctx->tables + i;
1688 if (t->equiv.list) {
1689 for (j = 0; j < t->equiv.count; j++)
1690 t->equiv.list[j].name = _free(t->equiv.list[j].name);
1691 t->equiv.list = _free(t->equiv.list);
1694 if (t->cache.cache) {
1695 for (j = 0; j < t->cache.size; j++) {
1697 e = t->cache.cache + j;
1700 e->name = _free(e->name);
1702 for (k = 0; k < e->count; k++)
1703 e->equivs[k] = _free(e->equivs[k]);
1704 e->equivs = _free(e->equivs);
1707 t->cache.cache = _free(t->cache.cache);
1711 for (j = 0; j < t->defaultsLength; j++) {
1712 t->defaults[j].name = _free(t->defaults[j].name);
1713 t->defaults[j].defName = _free(t->defaults[j].defName);
1715 t->defaults = _free(t->defaults);
1716 t->defaultsLength = 0;
1719 for (j = 0; j < t->canonsLength; j++) {
1720 t->canons[j].name = _free(t->canons[j].name);
1721 t->canons[j].short_name = _free(t->canons[j].short_name);
1723 t->canons = _free(t->canons);
1724 t->canonsLength = 0;
1728 for (i = 0; i < RPMVAR_NUM; i++) {
1729 struct rpmvarValue * vp;
1730 while ((vp = ctx->values[i].next) != NULL) {
1731 ctx->values[i].next = vp->next;
1732 vp->value = _free(vp->value);
1733 vp->arch = _free(vp->arch);
1736 ctx->values[i].value = _free(ctx->values[i].value);
1737 ctx->values[i].arch = _free(ctx->values[i].arch);
1739 ctx->current[OS] = _free(ctx->current[OS]);
1740 ctx->current[ARCH] = _free(ctx->current[ARCH]);
1741 ctx->machDefaults = 0;
1742 ctx->pathDefaults = 0;
1744 /* XXX doesn't really belong here but... */
1750 rpmrcCtxRelease(ctx);
1754 int rpmShowRC(FILE * fp)
1756 /* Write-context necessary as this calls rpmSetTables(), ugh */
1757 rpmrcCtx ctx = rpmrcCtxAcquire(1);
1758 const struct rpmOption *opt;
1761 machEquivTable equivTable;
1763 /* the caller may set the build arch which should be printed here */
1764 fprintf(fp, "ARCHITECTURE AND OS:\n");
1765 fprintf(fp, "build arch : %s\n", ctx->current[ARCH]);
1767 fprintf(fp, "compatible build archs:");
1768 equivTable = &ctx->tables[RPM_MACHTABLE_BUILDARCH].equiv;
1769 for (i = 0; i < equivTable->count; i++)
1770 fprintf(fp," %s", equivTable->list[i].name);
1773 fprintf(fp, "build os : %s\n", ctx->current[OS]);
1775 fprintf(fp, "compatible build os's :");
1776 equivTable = &ctx->tables[RPM_MACHTABLE_BUILDOS].equiv;
1777 for (i = 0; i < equivTable->count; i++)
1778 fprintf(fp," %s", equivTable->list[i].name);
1781 rpmSetTables(ctx, RPM_MACHTABLE_INSTARCH, RPM_MACHTABLE_INSTOS);
1782 rpmSetMachine(ctx, NULL, NULL); /* XXX WTFO? Why bother? */
1784 fprintf(fp, "install arch : %s\n", ctx->current[ARCH]);
1785 fprintf(fp, "install os : %s\n", ctx->current[OS]);
1787 fprintf(fp, "compatible archs :");
1788 equivTable = &ctx->tables[RPM_MACHTABLE_INSTARCH].equiv;
1789 for (i = 0; i < equivTable->count; i++)
1790 fprintf(fp," %s", equivTable->list[i].name);
1793 fprintf(fp, "compatible os's :");
1794 equivTable = &ctx->tables[RPM_MACHTABLE_INSTOS].equiv;
1795 for (i = 0; i < equivTable->count; i++)
1796 fprintf(fp," %s", equivTable->list[i].name);
1799 fprintf(fp, "\nRPMRC VALUES:\n");
1800 for (i = 0, opt = optionTable; i < optionTableSize; i++, opt++) {
1801 const char *s = rpmGetVarArch(ctx, opt->var, NULL);
1802 if (s != NULL || rpmIsVerbose())
1803 fprintf(fp, "%-21s : %s\n", opt->name, s ? s : "(not set)");
1807 fprintf(fp, "Features supported by rpmlib:\n");
1808 rpmdsRpmlib(&ds, NULL);
1810 while (rpmdsNext(ds) >= 0) {
1811 const char * DNEVR = rpmdsDNEVR(ds);
1813 fprintf(fp, " %s\n", DNEVR+2);
1818 fprintf(fp, "Macro path: %s\n", macrofiles);
1821 rpmDumpMacroTable(NULL, fp);
1823 /* XXX: Move this earlier eventually... */
1824 rpmrcCtxRelease(ctx);
1829 int rpmMachineScore(int type, const char * name)
1833 rpmrcCtx ctx = rpmrcCtxAcquire(0);
1834 machEquivInfo info = machEquivSearch(&ctx->tables[type].equiv, name);
1836 score = info->score;
1837 rpmrcCtxRelease(ctx);
1842 int rpmIsKnownArch(const char *name)
1844 rpmrcCtx ctx = rpmrcCtxAcquire(0);
1845 canonEntry canon = lookupInCanonTable(name,
1846 ctx->tables[RPM_MACHTABLE_INSTARCH].canons,
1847 ctx->tables[RPM_MACHTABLE_INSTARCH].canonsLength);
1848 int known = (canon != NULL || rstreq(name, "noarch"));
1849 rpmrcCtxRelease(ctx);
1853 void rpmGetArchInfo(const char ** name, int * num)
1855 rpmrcCtx ctx = rpmrcCtxAcquire(0);
1856 getMachineInfo(ctx, ARCH, name, num);
1857 rpmrcCtxRelease(ctx);
1860 int rpmGetArchColor(const char *arch)
1862 rpmrcCtx ctx = rpmrcCtxAcquire(0);
1865 int color_i = -1; /* assume failure */
1867 arch = lookupInDefaultTable(arch,
1868 ctx->tables[ctx->currTables[ARCH]].defaults,
1869 ctx->tables[ctx->currTables[ARCH]].defaultsLength);
1870 color = rpmGetVarArch(ctx, RPMVAR_ARCHCOLOR, arch);
1872 color_i = strtol(color, &e, 10);
1873 if (!(e && *e == '\0')) {
1877 rpmrcCtxRelease(ctx);
1882 void rpmGetOsInfo(const char ** name, int * num)
1884 rpmrcCtx ctx = rpmrcCtxAcquire(0);
1885 getMachineInfo(ctx, OS, name, num);
1886 rpmrcCtxRelease(ctx);