5 #if HAVE_SYS_SYSTEMCFG_H
6 #include <sys/systemcfg.h>
16 static const char *defrcfiles = LIBRPMRC_FILENAME ":/etc/rpmrc:~/.rpmrc";
18 struct machCacheEntry {
26 struct machCacheEntry * cache;
30 struct machEquivInfo {
35 struct machEquivTable {
37 struct machEquivInfo * list;
42 /* eventually, this arch will be replaced with a generic condition */
44 struct rpmvarValue * next;
50 int archSpecific, required, macroize, localize;
51 struct rpmOptionValue * value;
65 /* tags are 'key'canon, 'key'translate, 'key'compat
67 for giggles, 'key'_canon, 'key'_compat, and 'key'_canon will also work */
70 int hasCanon, hasTranslate;
71 struct machEquivTable equiv;
72 struct machCache cache;
73 struct defaultEntry * defaults;
74 struct canonEntry * canons;
80 static struct tableType tables[RPM_MACHTABLE_COUNT] = {
83 { "buildarch", 0, 1 },
87 /* this *must* be kept in alphabetical order */
88 /* The order of the flags is archSpecific, required, macroize, localize */
90 static struct rpmOption optionTable[] = {
91 { "include", RPMVAR_INCLUDE, 0, 1, 0, 2 },
92 { "macrofiles", RPMVAR_MACROFILES, 0, 0, 0, 1 },
93 { "optflags", RPMVAR_OPTFLAGS, 1, 0, 1, 0 },
94 { "provides", RPMVAR_PROVIDES, 0, 0, 0, 0 },
97 static int optionTableSize = sizeof(optionTable) / sizeof(*optionTable);
102 static char * current[2];
103 static int currTables[2] = { RPM_MACHTABLE_INSTOS, RPM_MACHTABLE_INSTARCH };
104 static struct rpmvarValue values[RPMVAR_NUM];
107 static int doReadRC(FD_t fd, const char * filename);
108 static void rpmSetVarArch(int var, const char * val, const char * arch);
109 static void rebuildCompatTables(int type, const char *name);
111 static int optionCompare(const void * a, const void * b) {
112 return strcasecmp(((struct rpmOption *) a)->name,
113 ((struct rpmOption *) b)->name);
116 static void rpmRebuildTargetVars(const char **target, const char ** canontarget);
118 static struct machCacheEntry * machCacheFindEntry(struct machCache * cache,
123 for (i = 0; i < cache->size; i++)
124 if (!strcmp(cache->cache[i].name, key)) return cache->cache + i;
129 static int machCompatCacheAdd(char * name, const char * fn, int linenum,
130 struct machCache * cache)
132 char * chptr, * equivs;
135 struct machCacheEntry * entry = NULL;
137 while (*name && isspace(*name)) name++;
140 while (*chptr && *chptr != ':') chptr++;
142 rpmError(RPMERR_RPMRC, _("missing second ':' at %s:%d"), fn, linenum);
144 } else if (chptr == name) {
145 rpmError(RPMERR_RPMRC, _("missing architecture name at %s:%d"), fn,
150 while (*chptr == ':' || isspace(*chptr)) chptr--;
153 while (*equivs && isspace(*equivs)) equivs++;
159 entry = machCacheFindEntry(cache, name);
161 for (i = 0; i < entry->count; i++)
162 free(entry->equivs[i]);
163 if (entry->count) free(entry->equivs);
169 cache->cache = xrealloc(cache->cache,
170 (cache->size + 1) * sizeof(*cache->cache));
171 entry = cache->cache + cache->size++;
172 entry->name = xstrdup(name);
177 if (delEntry) return 0;
179 while ((chptr = strtok(equivs, " ")) != NULL) {
181 if (chptr[0] == '\0') /* does strtok() return "" ever?? */
184 entry->equivs = xrealloc(entry->equivs, sizeof(*entry->equivs)
185 * (entry->count + 1));
187 entry->equivs = xmalloc(sizeof(*entry->equivs));
189 entry->equivs[entry->count] = xstrdup(chptr);
196 static struct machEquivInfo * machEquivSearch(
197 struct machEquivTable * table, const char * name)
202 * XXX The strcasecmp below is necessary so the old (rpm < 2.90) style
203 * XXX os-from-uname (e.g. "Linux") is compatible with the new
204 * XXX os-from-platform (e.g "linux" from "sparc-*-linux").
205 * XXX A copy of this string is embedded in headers and is
206 * XXX used by rpmInstallPackage->{os,arch}Okay->rpmMachineScore->.
207 * XXX to verify correct arch/os from headers.
209 for (i = 0; i < table->count; i++)
210 if (!strcasecmp(table->list[i].name, name))
211 return table->list + i;
216 static void machAddEquiv(struct machEquivTable * table, const char * name,
219 struct machEquivInfo * equiv;
221 equiv = machEquivSearch(table, name);
224 table->list = xrealloc(table->list, (table->count + 1)
225 * sizeof(*table->list));
227 table->list = xmalloc(sizeof(*table->list));
229 table->list[table->count].name = xstrdup(name);
230 table->list[table->count++].score = distance;
234 static void machCacheEntryVisit(struct machCache * cache,
235 struct machEquivTable * table,
239 struct machCacheEntry * entry;
242 entry = machCacheFindEntry(cache, name);
243 if (!entry || entry->visited) return;
247 for (i = 0; i < entry->count; i++) {
248 machAddEquiv(table, entry->equivs[i], distance);
251 for (i = 0; i < entry->count; i++) {
252 machCacheEntryVisit(cache, table, entry->equivs[i], distance + 1);
256 static void machFindEquivs(struct machCache * cache,
257 struct machEquivTable * table,
262 for (i = 0; i < cache->size; i++)
263 cache->cache[i].visited = 0;
265 while (table->count > 0) {
266 xfree(table->list[--table->count].name);
267 table->list[table->count].name = NULL;
270 if (table->list) xfree(table->list);
274 * We have a general graph built using strings instead of pointers.
275 * Yuck. We have to start at a point at traverse it, remembering how
276 * far away everything is.
278 machAddEquiv(table, key, 1);
279 machCacheEntryVisit(cache, table, key, 2);
282 static int addCanon(struct canonEntry **table, int *tableLen, char *line,
283 const char *fn, int lineNum)
285 struct canonEntry *t;
290 *table = xmalloc(2 * sizeof(struct canonEntry));
293 *table = xrealloc(*table, sizeof(struct canonEntry) * (*tableLen));
295 t = & ((*table)[*tableLen - 2]);
297 t->name = strtok(line, ": \t");
298 t->short_name = strtok(NULL, " \t");
299 s = strtok(NULL, " \t");
300 if (! (t->name && t->short_name && s)) {
301 rpmError(RPMERR_RPMRC, _("Incomplete data line at %s:%d"), fn, lineNum);
304 if (strtok(NULL, " \t")) {
305 rpmError(RPMERR_RPMRC, _("Too many args in data line at %s:%d"),
310 t->num = strtoul(s, &s1, 10);
311 if ((*s1) || (s1 == s) || (t->num == ULONG_MAX)) {
312 rpmError(RPMERR_RPMRC, _("Bad arch/os number: %s (%s:%d)"), s,
314 return(RPMERR_RPMRC);
317 t->name = xstrdup(t->name);
318 t->short_name = xstrdup(t->short_name);
320 /* From A B C entry */
321 /* Add B B C entry */
322 t[1].name = xstrdup(t->short_name);
323 t[1].short_name = xstrdup(t->short_name);
329 static int addDefault(struct defaultEntry **table, int *tableLen, char *line,
330 const char *fn, int lineNum)
332 struct defaultEntry *t;
336 *table = xmalloc(sizeof(struct defaultEntry));
339 *table = xrealloc(*table, sizeof(struct defaultEntry) * (*tableLen));
341 t = & ((*table)[*tableLen - 1]);
343 t->name = strtok(line, ": \t");
344 t->defName = strtok(NULL, " \t");
345 if (! (t->name && t->defName)) {
346 rpmError(RPMERR_RPMRC, _("Incomplete default line at %s:%d"),
350 if (strtok(NULL, " \t")) {
351 rpmError(RPMERR_RPMRC, _("Too many args in default line at %s:%d"),
356 t->name = xstrdup(t->name);
357 t->defName = xstrdup(t->defName);
362 static struct canonEntry *lookupInCanonTable(char *name,
363 struct canonEntry *table,
367 if (!strcmp(name, table[tableLen].name)) {
368 return &(table[tableLen]);
375 static const char *lookupInDefaultTable(const char *name, struct defaultEntry *table,
379 if (!strcmp(name, table[tableLen].name)) {
380 return table[tableLen].defName;
387 int rpmReadConfigFiles(const char * file, const char * target)
390 /* Preset target macros */
391 rpmRebuildTargetVars(&target, NULL);
394 if (rpmReadRC(file)) return -1;
396 /* Reset target macros */
397 rpmRebuildTargetVars(&target, NULL);
399 /* Finally set target platform */
400 { const char *cpu = rpmExpand("%{_target_cpu}", NULL);
401 const char *os = rpmExpand("%{_target_os}", NULL);
402 rpmSetMachine(cpu, os);
410 static void setVarDefault(int var, const char *macroname, const char *val, const char *body)
412 if (var >= 0) { /* XXX Dying ... */
413 if (rpmGetVar(var)) return;
418 addMacro(NULL, macroname, NULL, body, RMIL_DEFAULT);
421 static void setPathDefault(int var, const char *macroname, const char *subdir)
424 if (var >= 0) { /* XXX Dying ... */
428 if (rpmGetVar(var)) return;
430 topdir = rpmGetPath("%{_topdir}", NULL);
432 fn = alloca(strlen(topdir) + strlen(subdir) + 2);
434 if (fn[strlen(topdir) - 1] != '/')
439 if (topdir) xfree(topdir);
442 if (macroname != NULL) {
443 #define _TOPDIRMACRO "%{_topdir}/"
444 char *body = alloca(sizeof(_TOPDIRMACRO) + strlen(subdir));
445 strcpy(body, _TOPDIRMACRO);
446 strcat(body, subdir);
447 addMacro(NULL, macroname, NULL, body, RMIL_DEFAULT);
452 static const char *prescriptenviron = "\n\
453 RPM_SOURCE_DIR=\"%{_sourcedir}\"\n\
454 RPM_BUILD_DIR=\"%{_builddir}\"\n\
455 RPM_OPT_FLAGS=\"%{optflags}\"\n\
456 RPM_ARCH=\"%{_arch}\"\n\
458 export RPM_SOURCE_DIR RPM_BUILD_DIR RPM_OPT_FLAGS RPM_ARCH RPM_OS\n\
459 RPM_DOC_DIR=\"%{_docdir}\"\n\
460 export RPM_DOC_DIR\n\
461 RPM_PACKAGE_NAME=\"%{name}\"\n\
462 RPM_PACKAGE_VERSION=\"%{version}\"\n\
463 RPM_PACKAGE_RELEASE=\"%{release}\"\n\
464 export RPM_PACKAGE_NAME RPM_PACKAGE_VERSION RPM_PACKAGE_RELEASE\n\
465 %{?buildroot:RPM_BUILD_ROOT=\"%{buildroot}\"\n\
466 export RPM_BUILD_ROOT\n}\
469 static void setDefaults(void) {
471 addMacro(NULL, "_usr", NULL, "/usr", RMIL_DEFAULT);
472 addMacro(NULL, "_var", NULL, "/var", RMIL_DEFAULT);
474 addMacro(NULL, "_preScriptEnvironment",NULL, prescriptenviron,RMIL_DEFAULT);
476 setVarDefault(-1, "_topdir",
477 "/usr/src/redhat", "%{_usr}/src/redhat");
478 setVarDefault(-1, "_tmppath",
479 "/var/tmp", "%{_var}/tmp");
480 setVarDefault(-1, "_dbpath",
481 "/var/lib/rpm", "%{_var}/lib/rpm");
482 setVarDefault(-1, "_defaultdocdir",
483 "/usr/doc", "%{_usr}/doc");
485 setVarDefault(-1, "_rpmfilename",
486 "%%{ARCH}/%%{NAME}-%%{VERSION}-%%{RELEASE}.%%{ARCH}.rpm",NULL);
488 setVarDefault(RPMVAR_OPTFLAGS, "optflags",
490 setVarDefault(-1, "sigtype",
492 setVarDefault(-1, "_buildshell",
495 setPathDefault(-1, "_builddir", "BUILD");
496 setPathDefault(-1, "_rpmdir", "RPMS");
497 setPathDefault(-1, "_srcrpmdir", "SRPMS");
498 setPathDefault(-1, "_sourcedir", "SOURCES");
499 setPathDefault(-1, "_specdir", "SPECS");
503 int rpmReadRC(const char * rcfiles)
505 char *myrcfiles, *r, *re;
507 static int first = 1;
515 rcfiles = defrcfiles;
517 /* Read each file in rcfiles. */
519 for (r = myrcfiles = xstrdup(rcfiles); *r != '\0'; r = re) {
523 /* Get pointer to rest of files */
524 for (re = r; (re = strchr(re, ':')) != NULL; re++) {
525 if (!(re[1] == '/' && re[2] == '/'))
528 if (re && *re == ':')
533 /* Expand ~/ to $HOME/ */
535 if (r[0] == '~' && r[1] == '/') {
536 char *home = getenv("HOME");
538 /* XXX Only /usr/lib/rpm/rpmrc must exist in default rcfiles list */
539 if (rcfiles == defrcfiles && myrcfiles != r)
541 rpmError(RPMERR_RPMRC, _("Cannot expand %s"), r);
550 /* Read another rcfile */
551 fd = Fopen(fn, "r.ufdio");
552 if (fd == NULL || Ferror(fd)) {
553 /* XXX Only /usr/lib/rpm/rpmrc must exist in default rcfiles list */
554 if (rcfiles == defrcfiles && myrcfiles != r)
556 rpmError(RPMERR_RPMRC, _("Unable to open %s for reading: %s."),
561 rc = doReadRC(fd, fn);
565 if (myrcfiles) free(myrcfiles);
569 rpmSetMachine(NULL, NULL); /* XXX WTFO? Why bother? */
571 { const char *macrofiles;
572 if ((macrofiles = rpmGetVar(RPMVAR_MACROFILES)) != NULL) {
573 macrofiles = strdup(macrofiles);
574 initMacros(NULL, macrofiles);
582 static int doReadRC( /*@killref@*/ FD_t fd, const char * filename)
587 struct rpmOption searchOption, * option;
590 /* XXX fstat doesn't work on ufdio, default to 64K */
592 int fdno = Fileno(fd);
595 nb = (sb.st_size > 0 ? sb.st_size : (8*BUFSIZ - 2));
596 next = alloca(nb + 2);
598 rc = Fread(next, sizeof(*next), nb, fd);
599 if (Ferror(fd) || (sb.st_size > 0 && rc != nb)) { /* XXX Feof(fd) */
600 rpmError(RPMERR_RPMRC, _("Failed to read %s: %s."), filename,
616 /* Find end-of-line. */
617 while (*se && *se != '\n') se++;
618 if (*se) *se++ = '\0';
621 /* Trim leading spaces */
622 while (*s && isspace(*s)) s++;
624 /* We used to allow comments to begin anywhere, but not anymore. */
625 if (*s == '#' || *s == '\0') continue;
627 /* Find end-of-keyword. */
629 while (*se && !isspace(*se) && *se != ':') se++;
633 while (*se && isspace(*se) && *se != ':') se++;
637 rpmError(RPMERR_RPMRC, _("missing ':' (found 0x%02x) at %s:%d"),
638 (0xff & *se), filename, linenum);
641 *se++ = '\0'; /* terminate keyword or option, point to value */
642 while (*se && isspace(*se)) se++;
644 /* Find keyword in table */
645 searchOption.name = s;
646 option = bsearch(&searchOption, optionTable, optionTableSize,
647 sizeof(struct rpmOption), optionCompare);
649 if (option) { /* For configuration variables ... */
650 const char *arch, *val, *fn;
652 arch = val = fn = NULL;
654 rpmError(RPMERR_RPMRC, _("missing argument for %s at %s:%d"),
655 option->name, filename, linenum);
659 switch (option->var) {
664 while (*se && !isspace(*se)) se++;
665 if (*se) *se++ = '\0';
667 rpmRebuildTargetVars(NULL, NULL);
669 fn = rpmGetPath(s, NULL);
670 if (fn == NULL || *fn == '\0') {
671 rpmError(RPMERR_RPMRC, _("%s expansion failed at %s:%d \"%s\""),
672 option->name, filename, linenum, s);
678 fdinc = Fopen(fn, "r.ufdio");
679 if (fdinc == NULL || Ferror(fdinc)) {
680 rpmError(RPMERR_RPMRC, _("cannot open %s at %s:%d: %s"),
681 fn, filename, linenum, Fstrerror(fdinc));
684 rc = doReadRC(fdinc, fn);
688 continue; /* XXX don't save include value as var/macro */
689 } /*@notreached@*/ break;
690 case RPMVAR_MACROFILES:
691 fn = rpmGetPath(se, NULL);
692 if (fn == NULL || *fn == '\0') {
693 rpmError(RPMERR_RPMRC, _("%s expansion failed at %s:%d \"%s\""),
694 option->name, filename, linenum, fn);
700 case RPMVAR_PROVIDES:
702 s = rpmGetVar(RPMVAR_PROVIDES);
703 if (s == NULL) s = "";
704 fn = t = xmalloc(strlen(s) + strlen(se) + 2);
705 while (*s) *t++ = *s++;
707 while (*se) *t++ = *se++;
715 if (option->archSpecific) {
717 while (*se && !isspace(*se)) se++;
719 rpmError(RPMERR_RPMRC,
720 _("missing architecture for %s at %s:%d"),
721 option->name, filename, linenum);
725 while (*se && isspace(*se)) se++;
727 rpmError(RPMERR_RPMRC,
728 _("missing argument for %s at %s:%d"),
729 option->name, filename, linenum);
736 /* Only add macros if appropriate for this arch */
737 if (option->macroize &&
738 (arch == NULL || !strcmp(arch, current[ARCH]))) {
740 n = name = xmalloc(strlen(option->name)+2);
741 if (option->localize)
743 strcpy(n, option->name);
744 addMacro(NULL, name, NULL, val, RMIL_RPMRC);
747 rpmSetVarArch(option->var, val, arch);
750 } else { /* For arch/os compatibilty tables ... */
756 for (i = 0; i < RPM_MACHTABLE_COUNT; i++) {
757 if (!strncmp(tables[i].key, s, strlen(tables[i].key)))
761 if (i < RPM_MACHTABLE_COUNT) {
762 const char *rest = s + strlen(tables[i].key);
763 if (*rest == '_') rest++;
765 if (!strcmp(rest, "compat")) {
766 if (machCompatCacheAdd(se, filename, linenum,
770 } else if (tables[i].hasTranslate &&
771 !strcmp(rest, "translate")) {
772 if (addDefault(&tables[i].defaults,
773 &tables[i].defaultsLength,
774 se, filename, linenum))
777 } else if (tables[i].hasCanon &&
778 !strcmp(rest, "canon")) {
779 if (addCanon(&tables[i].canons, &tables[i].canonsLength,
780 se, filename, linenum))
787 rpmError(RPMERR_RPMRC, _("bad option '%s' at %s:%d"),
788 s, filename, linenum);
796 static void defaultMachine(const char ** arch, const char ** os) {
797 static struct utsname un;
798 static int gotDefaults = 0;
800 struct canonEntry * canon;
805 #if !defined(__linux__)
807 /* USUALLY un.sysname on sinix does start with the word "SINIX"
808 * let's be absolutely sure
810 sprintf(un.sysname,"SINIX");
812 if (!strcmp(un.sysname, "AIX")) {
813 strcpy(un.machine, __power_pc() ? "ppc" : "rs6000");
814 sprintf(un.sysname,"aix%s.%s",un.version,un.release);
816 else if (!strcmp(un.sysname, "SunOS")) {
817 if (!strncmp(un.release,"4", 1)) /* SunOS 4.x */ {
820 (un.release[fd] != 0 && (fd < sizeof(un.release)));
822 if (!isdigit(un.release[fd]) && (un.release[fd] != '.')) {
827 sprintf(un.sysname,"sunos%s",un.release);
830 else /* Solaris 2.x: n.x.x becomes n-3.x.x */
831 sprintf(un.sysname, "solaris%1d%s", atoi(un.release)-3,
832 un.release+1+(atoi(un.release)/10));
834 else if (!strcmp(un.sysname, "HP-UX"))
835 /*make un.sysname look like hpux9.05 for example*/
836 sprintf(un.sysname, "hpux%s", strpbrk(un.release,"123456789"));
837 else if (!strcmp(un.sysname, "OSF1"))
838 /*make un.sysname look like osf3.2 for example*/
839 sprintf(un.sysname,"osf%s",strpbrk(un.release,"123456789"));
840 else if (!strncmp(un.sysname, "IP", 2))
841 un.sysname[2] = '\0';
842 else if (!strncmp(un.sysname, "SINIX", 5)) {
843 sprintf(un.sysname, "sinix%s",un.release);
844 if (!strncmp(un.machine, "RM", 2))
845 sprintf(un.machine, "mips");
847 else if ((!strncmp(un.machine, "34", 2) ||
848 !strncmp(un.machine, "33", 2)) && \
849 !strncmp(un.release, "4.0", 3))
851 /* we are on ncr-sysv4 */
854 fd = Fopen("/etc/.relid", "r.fdio");
856 chptr = (char *) xcalloc(1, 256);
858 int irelid = Fread(chptr, sizeof(*chptr), 256, fd);
860 /* example: "112393 RELEASE 020200 Version 01 OS" */
862 if ((prelid=strstr(chptr, "RELEASE "))){
863 prelid += strlen("RELEASE ")+1;
864 sprintf(un.sysname,"ncr-sysv4.%.*s",1,prelid);
870 if (prelid == NULL) /* parsing /etc/.relid file failed? */
871 strcpy(un.sysname,"ncr-sysv4");
872 /* wrong, just for now, find out how to look for i586 later*/
873 strcpy(un.machine,"i486");
875 #endif /* __linux__ */
877 /* get rid of the hyphens in the sysname */
878 for (chptr = un.machine; *chptr; chptr++)
879 if (*chptr == '/') *chptr = '-';
881 # if defined(__MIPSEL__) || defined(__MIPSEL) || defined(_MIPSEL)
883 strcpy(un.machine, "mipsel");
884 # elif defined(__MIPSEB__) || defined(__MIPSEB) || defined(_MIPSEB)
886 strcpy(un.machine, "mipseb");
889 # if defined(__hpux) && defined(_SC_CPU_VERSION)
891 # if !defined(CPU_PA_RISC1_2)
892 # define CPU_PA_RISC1_2 0x211 /* HP PA-RISC1.2 */
894 # if !defined(CPU_PA_RISC2_0)
895 # define CPU_PA_RISC2_0 0x214 /* HP PA-RISC2.0 */
897 int cpu_version = sysconf(_SC_CPU_VERSION);
899 # if defined(CPU_HP_MC68020)
900 if (cpu_version == CPU_HP_MC68020)
901 strcpy(un.machine, "m68k");
903 # if defined(CPU_HP_MC68030)
904 if (cpu_version == CPU_HP_MC68030)
905 strcpy(un.machine, "m68k");
907 # if defined(CPU_HP_MC68040)
908 if (cpu_version == CPU_HP_MC68040)
909 strcpy(un.machine, "m68k");
912 # if defined(CPU_PA_RISC1_0)
913 if (cpu_version == CPU_PA_RISC1_0)
914 strcpy(un.machine, "hppa1.0");
916 # if defined(CPU_PA_RISC1_1)
917 if (cpu_version == CPU_PA_RISC1_1)
918 strcpy(un.machine, "hppa1.1");
920 # if defined(CPU_PA_RISC1_2)
921 if (cpu_version == CPU_PA_RISC1_2)
922 strcpy(un.machine, "hppa1.2");
924 # if defined(CPU_PA_RISC2_0)
925 if (cpu_version == CPU_PA_RISC2_0)
926 strcpy(un.machine, "hppa2.0");
931 # if defined(__linux__) && defined(__sparc__)
932 if (!strcmp(un.machine, "sparc")) {
933 #define PERS_LINUX 0x00000000
934 #define PERS_LINUX_32BIT 0x00800000
935 #define PERS_LINUX32 0x00000008
937 extern int personality(unsigned long);
940 oldpers = personality(PERS_LINUX_32BIT);
942 if (personality(PERS_LINUX) != -1) {
944 if (! strcmp(un.machine, "sparc64")) {
945 strcpy(un.machine, "sparcv9");
946 oldpers = PERS_LINUX32;
949 personality(oldpers);
952 # endif /* sparc*-linux */
954 /* the uname() result goes through the arch_canon table */
955 canon = lookupInCanonTable(un.machine,
956 tables[RPM_MACHTABLE_INSTARCH].canons,
957 tables[RPM_MACHTABLE_INSTARCH].canonsLength);
959 strcpy(un.machine, canon->short_name);
961 canon = lookupInCanonTable(un.sysname,
962 tables[RPM_MACHTABLE_INSTOS].canons,
963 tables[RPM_MACHTABLE_INSTOS].canonsLength);
965 strcpy(un.sysname, canon->short_name);
969 if (arch) *arch = un.machine;
970 if (os) *os = un.sysname;
973 static const char * rpmGetVarArch(int var, char * arch) {
974 struct rpmvarValue * next;
976 if (!arch) arch = current[ARCH];
981 if (next->arch && !strcmp(next->arch, arch)) return next->value;
987 while (next && next->arch) next = next->next;
989 return next ? next->value : NULL;
992 const char *rpmGetVar(int var)
994 return rpmGetVarArch(var, NULL);
997 /* this doesn't free the passed pointer! */
998 static void freeRpmVar(struct rpmvarValue * orig) {
999 struct rpmvarValue * next, * var = orig;
1012 if (var != orig) free(var);
1017 void rpmSetVar(int var, const char *val) {
1018 freeRpmVar(&values[var]);
1019 values[var].value = (val ? xstrdup(val) : NULL);
1022 static void rpmSetVarArch(int var, const char * val, const char * arch) {
1023 struct rpmvarValue * next = values + var;
1027 while (next->next) {
1028 if (next->arch && !strcmp(next->arch, arch)) break;
1032 while (next->next) {
1033 if (!next->arch) break;
1038 if (next->arch && arch && !strcmp(next->arch, arch)) {
1039 if (next->value) xfree(next->value);
1040 if (next->arch) xfree(next->arch);
1041 } else if (next->arch || arch) {
1042 next->next = xmalloc(sizeof(*next->next));
1050 next->value = xstrdup(val); /* XXX memory leak, hard to plug */
1051 next->arch = (arch ? xstrdup(arch) : NULL);
1054 void rpmSetTables(int archTable, int osTable) {
1055 const char * arch, * os;
1057 defaultMachine(&arch, &os);
1059 if (currTables[ARCH] != archTable) {
1060 currTables[ARCH] = archTable;
1061 rebuildCompatTables(ARCH, arch);
1064 if (currTables[OS] != osTable) {
1065 currTables[OS] = osTable;
1066 rebuildCompatTables(OS, os);
1070 int rpmMachineScore(int type, const char * name) {
1071 struct machEquivInfo * info = machEquivSearch(&tables[type].equiv, name);
1072 return (info != NULL ? info->score : 0);
1075 void rpmGetMachine(const char **arch, const char **os)
1078 *arch = current[ARCH];
1084 void rpmSetMachine(const char * arch, const char * os) {
1085 const char * host_cpu, * host_os;
1087 defaultMachine(&host_cpu, &host_os);
1091 if (tables[currTables[ARCH]].hasTranslate)
1092 arch = lookupInDefaultTable(arch,
1093 tables[currTables[ARCH]].defaults,
1094 tables[currTables[ARCH]].defaultsLength);
1099 if (tables[currTables[OS]].hasTranslate)
1100 os = lookupInDefaultTable(os,
1101 tables[currTables[OS]].defaults,
1102 tables[currTables[OS]].defaultsLength);
1105 if (!current[ARCH] || strcmp(arch, current[ARCH])) {
1106 if (current[ARCH]) free(current[ARCH]);
1107 current[ARCH] = xstrdup(arch);
1108 rebuildCompatTables(ARCH, host_cpu);
1111 if (!current[OS] || strcmp(os, current[OS])) {
1112 if (current[OS]) free(current[OS]);
1113 current[OS] = xstrdup(os);
1115 * XXX Capitalizing the 'L' is needed to insure that old
1116 * XXX os-from-uname (e.g. "Linux") is compatible with the new
1117 * XXX os-from-platform (e.g "linux" from "sparc-*-linux").
1118 * XXX A copy of this string is embedded in headers and is
1119 * XXX used by rpmInstallPackage->{os,arch}Okay->rpmMachineScore->
1120 * XXX to verify correct arch/os from headers.
1122 if (!strcmp(current[OS], "linux"))
1124 rebuildCompatTables(OS, host_os);
1128 static void rebuildCompatTables(int type, const char * name) {
1129 machFindEquivs(&tables[currTables[type]].cache,
1130 &tables[currTables[type]].equiv,
1134 static void getMachineInfo(int type, /*@only@*/ /*@out@*/ const char ** name,
1137 struct canonEntry * canon;
1138 int which = currTables[type];
1140 /* use the normal canon tables, even if we're looking up build stuff */
1141 if (which >= 2) which -= 2;
1143 canon = lookupInCanonTable(current[type],
1144 tables[which].canons,
1145 tables[which].canonsLength);
1148 if (num) *num = canon->num;
1149 if (name) *name = canon->short_name;
1151 if (num) *num = 255;
1152 if (name) *name = current[type];
1154 if (tables[currTables[type]].hasCanon) {
1155 rpmMessage(RPMMESS_WARNING, _("Unknown system: %s\n"), current[type]);
1156 rpmMessage(RPMMESS_WARNING, _("Please contact rpm-list@redhat.com\n"));
1161 void rpmGetArchInfo(const char ** name, int * num) {
1162 getMachineInfo(ARCH, name, num);
1165 void rpmGetOsInfo(const char ** name, int * num) {
1166 getMachineInfo(OS, name, num);
1169 void rpmRebuildTargetVars(const char **buildtarget, const char ** canontarget)
1172 char *ca = NULL, *co = NULL, *ct = NULL;
1175 /* Rebuild the compat table to recalculate the current target arch. */
1177 rpmSetMachine(NULL, NULL);
1178 rpmSetTables(RPM_MACHTABLE_INSTARCH, RPM_MACHTABLE_INSTOS);
1179 rpmSetTables(RPM_MACHTABLE_BUILDARCH, RPM_MACHTABLE_BUILDOS);
1181 if (buildtarget && *buildtarget) {
1183 /* Set arch and os from specified build target */
1184 ca = xstrdup(*buildtarget);
1185 if ((c = strchr(ca, '-')) != NULL) {
1188 if ((co = strrchr(c, '-')) == NULL) {
1191 if (!strcasecmp(co, "-gnu"))
1193 if ((co = strrchr(c, '-')) == NULL)
1198 if (co != NULL) co = xstrdup(co);
1202 /* Set build target from rpm arch and os */
1203 rpmGetArchInfo(&a,NULL);
1204 ca = (a) ? xstrdup(a) : NULL;
1205 rpmGetOsInfo(&o,NULL);
1206 co = (o) ? xstrdup(o) : NULL;
1209 /* If still not set, Set target arch/os from default uname(2) values */
1212 defaultMachine(&a, NULL);
1213 ca = (a) ? xstrdup(a) : NULL;
1215 for (x = 0; ca[x]; x++)
1216 ca[x] = tolower(ca[x]);
1220 defaultMachine(NULL, &o);
1221 co = (o) ? xstrdup(o) : NULL;
1223 for (x = 0; co[x]; x++)
1224 co[x] = tolower(co[x]);
1226 /* XXX For now, set canonical target to arch-os */
1228 ct = xmalloc(strlen(ca) + sizeof("-") + strlen(co));
1229 sprintf(ct, "%s-%s", ca, co);
1233 * XXX All this macro pokery/jiggery could be achieved by doing a delayed
1234 * initMacros(NULL, PER-PLATFORM-MACRO-FILE-NAMES);
1236 delMacro(NULL, "_target");
1237 addMacro(NULL, "_target", NULL, ct, RMIL_RPMRC);
1238 delMacro(NULL, "_target_cpu");
1239 addMacro(NULL, "_target_cpu", NULL, ca, RMIL_RPMRC);
1240 delMacro(NULL, "_target_os");
1241 addMacro(NULL, "_target_os", NULL, co, RMIL_RPMRC);
1243 * XXX Make sure that per-arch optflags is initialized correctly.
1245 { const char *optflags = rpmGetVarArch(RPMVAR_OPTFLAGS, ca);
1246 if (optflags != NULL) {
1247 delMacro(NULL, "optflags");
1248 addMacro(NULL, "optflags", NULL, optflags, RMIL_RPMRC);
1260 void rpmFreeRpmrc(void)
1264 for (i = 0; i < RPM_MACHTABLE_COUNT; i++) {
1265 struct tableType *t;
1267 if (t->equiv.list) {
1268 for (j = 0; j < t->equiv.count; j++) {
1269 if (t->equiv.list[j].name) xfree(t->equiv.list[j].name);
1271 xfree(t->equiv.list);
1273 if (t->cache.cache) {
1274 for (j = 0; j < t->cache.size; j++) {
1275 struct machCacheEntry *e;
1276 e = t->cache.cache + j;
1277 if (e == NULL) continue;
1278 if (e->name) xfree(e->name);
1280 for (k = 0; k < e->count; k++) {
1281 if (e->equivs[k]) xfree(e->equivs[k]);
1286 xfree(t->cache.cache);
1289 for (j = 0; j < t->defaultsLength; j++) {
1290 if (t->defaults[j].name) xfree(t->defaults[j].name);
1291 if (t->defaults[j].defName) xfree(t->defaults[j].defName);
1296 for (j = 0; j < t->canonsLength; j++) {
1297 if (t->canons[j].name) xfree(t->canons[j].name);
1298 if (t->canons[j].short_name) xfree(t->canons[j].short_name);
1304 for (i = 0; i < RPMVAR_NUM; i++) {
1305 struct rpmvarValue *this;
1306 while ((this = values[i].next) != NULL) {
1307 values[i].next = this->next;
1308 if (this->value) xfree(this->value);
1309 if (this->arch) xfree(this->arch);
1312 if (values[i].value) xfree(values[i].value);
1313 if (values[i].arch) xfree(values[i].arch);
1315 if (current[OS]) xfree(current[OS]);
1316 if (current[ARCH]) xfree(current[ARCH]);
1320 int rpmShowRC(FILE *f)
1322 struct rpmOption *opt;
1324 struct machEquivTable * equivTable;
1326 /* the caller may set the build arch which should be printed here */
1327 fprintf(f, "ARCHITECTURE AND OS:\n");
1328 fprintf(f, "build arch : %s\n", current[ARCH]);
1330 fprintf(f, "compatible build archs:");
1331 equivTable = &tables[RPM_MACHTABLE_BUILDARCH].equiv;
1332 for (i = 0; i < equivTable->count; i++)
1333 fprintf(f," %s", equivTable->list[i].name);
1336 fprintf(f, "build os : %s\n", current[OS]);
1338 fprintf(f, "compatible build os's :");
1339 equivTable = &tables[RPM_MACHTABLE_BUILDOS].equiv;
1340 for (i = 0; i < equivTable->count; i++)
1341 fprintf(f," %s", equivTable->list[i].name);
1344 rpmSetTables(RPM_MACHTABLE_INSTARCH, RPM_MACHTABLE_INSTOS);
1345 rpmSetMachine(NULL, NULL); /* XXX WTFO? Why bother? */
1347 fprintf(f, "install arch : %s\n", current[ARCH]);
1348 fprintf(f, "install os : %s\n", current[OS]);
1350 fprintf(f, "compatible archs :");
1351 equivTable = &tables[RPM_MACHTABLE_INSTARCH].equiv;
1352 for (i = 0; i < equivTable->count; i++)
1353 fprintf(f," %s", equivTable->list[i].name);
1356 fprintf(f, "compatible os's :");
1357 equivTable = &tables[RPM_MACHTABLE_INSTOS].equiv;
1358 for (i = 0; i < equivTable->count; i++)
1359 fprintf(f," %s", equivTable->list[i].name);
1362 fprintf(f, "\nRPMRC VALUES:\n");
1363 for (i = 0, opt = optionTable; i < optionTableSize; i++, opt++) {
1364 const char *s = rpmGetVar(opt->var);
1365 if (s != NULL || rpmGetVerbosity() < RPMMESS_NORMAL)
1366 fprintf(f, "%-21s : %s\n", opt->name, s ? s : "(not set)");
1369 dumpMacroTable(NULL, f);