5 #if HAVE_SYS_SYSTEMCFG_H
6 #include <sys/systemcfg.h>
16 static const char *defrcfiles = LIBRPMRC_FILENAME ":/etc/rpmrc:~/.rpmrc";
19 static const char *macrofiles = MACROFILES;
22 struct MacroContext globalMacroContext;
24 struct machCacheEntry {
32 struct machCacheEntry * cache;
36 struct machEquivInfo {
41 struct machEquivTable {
43 struct machEquivInfo * list;
48 /* eventually, this arch will be replaced with a generic condition */
50 struct rpmvarValue * next;
56 int archSpecific, required, macroize, localize;
57 struct rpmOptionValue * value;
71 /* tags are 'key'canon, 'key'translate, 'key'compat
73 for giggles, 'key'_canon, 'key'_compat, and 'key'_canon will also work */
76 int hasCanon, hasTranslate;
77 struct machEquivTable equiv;
78 struct machCache cache;
79 struct defaultEntry * defaults;
80 struct canonEntry * canons;
86 static struct tableType tables[RPM_MACHTABLE_COUNT] = {
89 { "buildarch", 0, 1 },
93 /* this *must* be kept in alphabetical order */
94 /* The order of the flags is archSpecific, required, macroize, localize */
96 static struct rpmOption optionTable[] = {
97 { "include", RPMVAR_INCLUDE, 0, 1, 1, 2 },
98 { "macrofiles", RPMVAR_MACROFILES, 0, 0, 1, 1 },
99 { "optflags", RPMVAR_OPTFLAGS, 1, 0, 1, 0 },
100 { "provides", RPMVAR_PROVIDES, 0, 0, 1, 0 },
103 static int optionTableSize = sizeof(optionTable) / sizeof(*optionTable);
108 static char * current[2];
109 static int currTables[2] = { RPM_MACHTABLE_INSTOS, RPM_MACHTABLE_INSTARCH };
110 static struct rpmvarValue values[RPMVAR_NUM];
113 static void defaultMachine(char ** arch, char ** os);
114 static int doReadRC(FD_t fd, const char * filename);
115 static int optionCompare(const void * a, const void * b);
116 static int addCanon(struct canonEntry **table, int *tableLen, char *line,
117 const char *fn, int lineNum);
118 static int addDefault(struct defaultEntry **table, int *tableLen, char *line,
119 const char *fn, int lineNum);
120 static void freeRpmVar(struct rpmvarValue * orig);
121 static void rpmSetVarArch(int var, char * val, char * arch);
122 static struct canonEntry *lookupInCanonTable(char *name,
123 struct canonEntry *table,
125 static const char *lookupInDefaultTable(const char *name,
126 struct defaultEntry *table,
129 static void setVarDefault(int var, const char *macroname, const char *val, const char *body);
130 static void setPathDefault(int var, const char *macroname, const char *subdir);
131 static void setDefaults(void);
133 static void rebuildCompatTables(int type, char *name);
135 /* compatiblity tables */
136 static int machCompatCacheAdd(char * name, const char * fn, int linenum,
137 struct machCache * cache);
138 static struct machCacheEntry * machCacheFindEntry(struct machCache * cache,
140 static struct machEquivInfo * machEquivSearch(
141 struct machEquivTable * table, char * name);
142 static void machAddEquiv(struct machEquivTable * table, char * name,
144 static void machCacheEntryVisit(struct machCache * cache,
145 struct machEquivTable * table,
148 static void machFindEquivs(struct machCache * cache,
149 struct machEquivTable * table,
152 static int optionCompare(const void * a, const void * b) {
153 return strcasecmp(((struct rpmOption *) a)->name,
154 ((struct rpmOption *) b)->name);
157 static void rpmRebuildTargetVars(const char **target, const char ** canontarget);
160 static struct machCacheEntry * machCacheFindEntry(struct machCache * cache,
165 for (i = 0; i < cache->size; i++)
166 if (!strcmp(cache->cache[i].name, key)) return cache->cache + i;
171 static int machCompatCacheAdd(char * name, const char * fn, int linenum,
172 struct machCache * cache)
174 char * chptr, * equivs;
177 struct machCacheEntry * entry = NULL;
179 while (*name && isspace(*name)) name++;
182 while (*chptr && *chptr != ':') chptr++;
184 rpmError(RPMERR_RPMRC, _("missing second ':' at %s:%d"), fn, linenum);
186 } else if (chptr == name) {
187 rpmError(RPMERR_RPMRC, _("missing architecture name at %s:%d"), fn,
192 while (*chptr == ':' || isspace(*chptr)) chptr--;
195 while (*equivs && isspace(*equivs)) equivs++;
201 entry = machCacheFindEntry(cache, name);
203 for (i = 0; i < entry->count; i++)
204 free(entry->equivs[i]);
205 if (entry->count) free(entry->equivs);
211 cache->cache = realloc(cache->cache,
212 (cache->size + 1) * sizeof(*cache->cache));
213 entry = cache->cache + cache->size++;
214 entry->name = strdup(name);
219 if (delEntry) return 0;
221 while ((chptr = strtok(equivs, " ")) != NULL) {
223 if (chptr[0] == '\0') /* does strtok() return "" ever?? */
226 entry->equivs = realloc(entry->equivs, sizeof(*entry->equivs)
227 * (entry->count + 1));
229 entry->equivs = malloc(sizeof(*entry->equivs));
231 entry->equivs[entry->count] = strdup(chptr);
238 static struct machEquivInfo * machEquivSearch(
239 struct machEquivTable * table, char * name)
244 * XXX The strcasecmp below is necessary so the old (rpm < 2.90) style
245 * XXX os-from-uname (e.g. "Linux") is compatible with the new
246 * XXX os-from-platform (e.g "linux" from "sparc-*-linux").
247 * XXX A copy of this string is embedded in headers and is
248 * XXX used by rpmInstallPackage->{os,arch}Okay->rpmMachineScore->.
249 * XXX to verify correct arch/os from headers.
251 for (i = 0; i < table->count; i++)
252 if (!strcasecmp(table->list[i].name, name))
253 return table->list + i;
258 static void machAddEquiv(struct machEquivTable * table, char * name,
261 struct machEquivInfo * equiv;
263 equiv = machEquivSearch(table, name);
266 table->list = realloc(table->list, (table->count + 1)
267 * sizeof(*table->list));
269 table->list = malloc(sizeof(*table->list));
271 table->list[table->count].name = strdup(name);
272 table->list[table->count++].score = distance;
276 static void machCacheEntryVisit(struct machCache * cache,
277 struct machEquivTable * table,
281 struct machCacheEntry * entry;
284 entry = machCacheFindEntry(cache, name);
285 if (!entry || entry->visited) return;
289 for (i = 0; i < entry->count; i++) {
290 machAddEquiv(table, entry->equivs[i], distance);
293 for (i = 0; i < entry->count; i++) {
294 machCacheEntryVisit(cache, table, entry->equivs[i], distance + 1);
298 static void machFindEquivs(struct machCache * cache,
299 struct machEquivTable * table,
304 for (i = 0; i < cache->size; i++)
305 cache->cache[i].visited = 0;
309 /* We have a general graph built using strings instead of pointers.
310 Yuck. We have to start at a point at traverse it, remembering how
311 far away everything is. */
312 machAddEquiv(table, key, 1);
313 machCacheEntryVisit(cache, table, key, 2);
316 static int addCanon(struct canonEntry **table, int *tableLen, char *line,
317 const char *fn, int lineNum)
319 struct canonEntry *t;
324 *table = malloc(2 * sizeof(struct canonEntry));
327 *table = realloc(*table, sizeof(struct canonEntry) * (*tableLen));
329 t = & ((*table)[*tableLen - 2]);
331 t->name = strtok(line, ": \t");
332 t->short_name = strtok(NULL, " \t");
333 s = strtok(NULL, " \t");
334 if (! (t->name && t->short_name && s)) {
335 rpmError(RPMERR_RPMRC, _("Incomplete data line at %s:%d"), fn, lineNum);
338 if (strtok(NULL, " \t")) {
339 rpmError(RPMERR_RPMRC, _("Too many args in data line at %s:%d"),
344 t->num = strtoul(s, &s1, 10);
345 if ((*s1) || (s1 == s) || (t->num == ULONG_MAX)) {
346 rpmError(RPMERR_RPMRC, _("Bad arch/os number: %s (%s:%d)"), s,
348 return(RPMERR_RPMRC);
351 t->name = strdup(t->name);
352 t->short_name = strdup(t->short_name);
354 /* From A B C entry */
355 /* Add B B C entry */
356 t[1].name = strdup(t->short_name);
357 t[1].short_name = strdup(t->short_name);
363 static int addDefault(struct defaultEntry **table, int *tableLen, char *line,
364 const char *fn, int lineNum)
366 struct defaultEntry *t;
370 *table = malloc(sizeof(struct defaultEntry));
373 *table = realloc(*table, sizeof(struct defaultEntry) * (*tableLen));
375 t = & ((*table)[*tableLen - 1]);
377 t->name = strtok(line, ": \t");
378 t->defName = strtok(NULL, " \t");
379 if (! (t->name && t->defName)) {
380 rpmError(RPMERR_RPMRC, _("Incomplete default line at %s:%d"),
384 if (strtok(NULL, " \t")) {
385 rpmError(RPMERR_RPMRC, _("Too many args in default line at %s:%d"),
390 t->name = strdup(t->name);
391 t->defName = strdup(t->defName);
396 static struct canonEntry *lookupInCanonTable(char *name,
397 struct canonEntry *table,
401 if (!strcmp(name, table[tableLen].name)) {
402 return &(table[tableLen]);
409 static const char *lookupInDefaultTable(const char *name, struct defaultEntry *table,
413 if (!strcmp(name, table[tableLen].name)) {
414 return table[tableLen].defName;
421 int rpmReadConfigFiles(const char * file, const char * target)
424 /* Preset target macros */
425 rpmRebuildTargetVars(&target, NULL);
428 if (rpmReadRC(file)) return -1;
430 /* Reset target macros */
431 rpmRebuildTargetVars(&target, NULL);
433 /* Finally set target platform */
434 { const char *cpu = rpmExpand("%{_target_cpu}", NULL);
435 const char *os = rpmExpand("%{_target_os}", NULL);
436 rpmSetMachine(cpu, os);
444 static void setVarDefault(int var, const char *macroname, const char *val, const char *body)
446 if (var >= 0) { /* XXX Dying ... */
447 if (rpmGetVar(var)) return;
452 addMacro(&globalMacroContext, macroname, NULL, body, RMIL_DEFAULT);
455 static void setPathDefault(int var, const char *macroname, const char *subdir)
458 if (var >= 0) { /* XXX Dying ... */
462 if (rpmGetVar(var)) return;
464 topdir = rpmGetPath("%{_topdir}", NULL);
466 fn = alloca(strlen(topdir) + strlen(subdir) + 2);
468 if (fn[strlen(topdir) - 1] != '/')
473 if (topdir) xfree(topdir);
476 if (macroname != NULL) {
477 #define _TOPDIRMACRO "%{_topdir}/"
478 char *body = alloca(sizeof(_TOPDIRMACRO) + strlen(subdir));
479 strcpy(body, _TOPDIRMACRO);
480 strcat(body, subdir);
481 addMacro(&globalMacroContext, macroname, NULL, body, RMIL_DEFAULT);
486 static const char *prescriptenviron = "\n\
487 RPM_SOURCE_DIR=\"%{_sourcedir}\"\n\
488 RPM_BUILD_DIR=\"%{_builddir}\"\n\
489 RPM_OPT_FLAGS=\"%{optflags}\"\n\
490 RPM_ARCH=\"%{_target_cpu}\"\n\
491 RPM_OS=\"%{_target_os}\"\n\
492 export RPM_SOURCE_DIR RPM_BUILD_DIR RPM_OPT_FLAGS RPM_ARCH RPM_OS\n\
493 RPM_DOC_DIR=\"%{_docdir}\"\n\
495 RPM_PACKAGE_NAME=\"%{name}\"\n\
496 RPM_PACKAGE_VERSION=\"%{version}\"\n\
497 RPM_PACKAGE_RELEASE=\"%{release}\"\n\
498 export RPM_PACKAGE_NAME RPM_PACKAGE_VERSION RPM_PACKAGE_RELEASE\n\
499 %{?buildroot:RPM_BUILD_ROOT=\"%{buildroot}\"\n\
500 export RPM_BUILD_ROOT\n}\
503 static void setDefaults(void) {
505 initMacros(&globalMacroContext, NULL); /* XXX initialize data structures */
506 addMacro(&globalMacroContext, "_usr", NULL, "/usr", RMIL_DEFAULT);
507 addMacro(&globalMacroContext, "_var", NULL, "/var", RMIL_DEFAULT);
509 addMacro(&globalMacroContext, "_preScriptEnvironment", NULL,
510 prescriptenviron, RMIL_DEFAULT);
512 setVarDefault(RPMVAR_MACROFILES, "_macrofiles",
513 "/usr/lib/rpm/macros", "%{_usr}/lib/rpm/macros");
514 setVarDefault(-1, "_topdir",
515 "/usr/src/redhat", "%{_usr}/src/redhat");
516 setVarDefault(-1, "_tmppath",
517 "/var/tmp", "%{_var}/tmp");
518 setVarDefault(-1, "_dbpath",
519 "/var/lib/rpm", "%{_var}/lib/rpm");
520 setVarDefault(-1, "_defaultdocdir",
521 "/usr/doc", "%{_usr}/doc");
523 setVarDefault(RPMVAR_OPTFLAGS, "optflags", "-O2", NULL);
524 setVarDefault(-1, "sigtype",
526 setVarDefault(-1, "_buildshell",
529 setPathDefault(-1, "_builddir", "BUILD");
530 setPathDefault(-1, "_rpmdir", "RPMS");
531 setPathDefault(-1, "_srcrpmdir", "SRPMS");
532 setPathDefault(-1, "_sourcedir", "SOURCES");
533 setPathDefault(-1, "_specdir", "SPECS");
537 int rpmReadRC(const char * rcfiles)
539 char *myrcfiles, *r, *re;
541 static int first = 1;
549 rcfiles = defrcfiles;
551 /* Read each file in rcfiles. */
553 for (r = myrcfiles = strdup(rcfiles); *r != '\0'; r = re) {
554 char fn[FILENAME_MAX+1];
557 /* Get pointer to rest of files */
558 if ((re = strchr(r, ':')) != NULL)
563 /* Expand ~/ to $HOME/ */
565 if (r[0] == '~' && r[1] == '/') {
566 char *home = getenv("HOME");
568 rpmError(RPMERR_RPMRC, _("Cannot expand %s"), r);
577 /* Read another rcfile */
578 fd = fdOpen(fn, O_RDONLY, 0);
579 if (fdFileno(fd) < 0) {
580 /* XXX Only /usr/lib/rpm/rpmrc must exist in default rcfiles list */
581 if (rcfiles == defrcfiles && myrcfiles != r)
583 rpmError(RPMERR_RPMRC, _("Unable to open %s for reading: %s."),
584 fn, strerror(errno));
588 rc = doReadRC(fd, fn);
592 if (myrcfiles) free(myrcfiles);
596 rpmSetMachine(NULL, NULL); /* XXX WTFO? Why bother? */
598 if ((r = rpmGetVar(RPMVAR_MACROFILES)) != NULL)
599 initMacros(&globalMacroContext, r);
604 static int doReadRC(FD_t fd, const char * filename) {
606 char * start, * chptr, * next, * rest;
608 struct rpmOption searchOption, * option;
614 fstat(fdFileno(fd), &sb);
615 next = alloca(sb.st_size + 2);
616 if (fdRead(fd, next, sb.st_size) != sb.st_size) {
617 rpmError(RPMERR_RPMRC, _("Failed to read %s: %s."), filename,
621 next[sb.st_size] = '\n';
622 next[sb.st_size + 1] = '\0';
628 chptr = start = next;
629 while (*chptr != '\n') chptr++;
634 while (isspace(*start)) start++;
636 /* we used to allow comments to begin anywhere, but not anymore */
637 if (*start == '#' || !*start) continue;
640 while (!isspace(*chptr) && *chptr != ':' && *chptr) chptr++;
642 if (isspace(*chptr)) {
644 while (isspace(*chptr) && *chptr != ':' && *chptr) chptr++;
648 rpmError(RPMERR_RPMRC, _("missing ':' at %s:%d"),
655 searchOption.name = start;
656 option = bsearch(&searchOption, optionTable, optionTableSize,
657 sizeof(struct rpmOption), optionCompare);
661 while (isspace(*start) && *start) start++;
664 rpmError(RPMERR_RPMRC, _("missing argument for %s at %s:%d"),
665 option->name, filename, linenum);
669 switch (option->var) {
674 rpmRebuildTargetVars(NULL, NULL);
677 if (expandMacros(NULL, &globalMacroContext, buf, sizeof(buf))) {
678 rpmError(RPMERR_RPMRC, _("expansion failed at %s:%d \"%s\""),
679 filename, linenum, start);
683 if (fdFileno(fdinc = fdOpen(buf, O_RDONLY, 0)) < 0) {
684 rpmError(RPMERR_RPMRC, _("cannot open %s at %s:%d"),
685 buf, filename, linenum);
688 rc = doReadRC(fdinc, buf);
697 if (option->archSpecific) {
698 while (!isspace(*chptr) && *chptr) chptr++;
701 rpmError(RPMERR_RPMRC,
702 _("missing architecture for %s at %s:%d"),
703 option->name, filename, linenum);
709 while (isspace(*chptr) && *chptr) chptr++;
711 rpmError(RPMERR_RPMRC,
712 _("missing argument for %s at %s:%d"),
713 option->name, filename, linenum);
716 if (option->macroize && !strcmp(start, current[ARCH])) {
718 if (option->localize)
720 strcpy(s, option->name);
721 addMacro(&globalMacroContext, buf, NULL, chptr, RMIL_RPMRC);
724 start = NULL; /* no arch */
725 /* XXX for now only non-arch values can get macroized */
726 if (option->macroize) {
728 if (option->localize)
730 strcpy(s, option->name);
731 addMacro(&globalMacroContext, buf, NULL, chptr, RMIL_RPMRC);
734 rpmSetVarArch(option->var, chptr, start);
738 for (i = 0; i < RPM_MACHTABLE_COUNT; i++) {
739 if (!strncmp(tables[i].key, start, strlen(tables[i].key)))
743 if (i < RPM_MACHTABLE_COUNT) {
744 rest = start + strlen(tables[i].key);
745 if (*rest == '_') rest++;
747 if (!strcmp(rest, "compat")) {
748 if (machCompatCacheAdd(chptr, filename, linenum,
752 } else if (tables[i].hasTranslate &&
753 !strcmp(rest, "translate")) {
754 if (addDefault(&tables[i].defaults,
755 &tables[i].defaultsLength,
756 chptr, filename, linenum))
759 } else if (tables[i].hasCanon &&
760 !strcmp(rest, "canon")) {
761 if (addCanon(&tables[i].canons, &tables[i].canonsLength,
762 chptr, filename, linenum))
769 rpmError(RPMERR_RPMRC, _("bad option '%s' at %s:%d"),
770 start, filename, linenum);
778 static void defaultMachine(char ** arch, char ** os) {
779 static struct utsname un;
780 static int gotDefaults = 0;
782 struct canonEntry * canon;
787 #if !defined(__linux__)
789 /* USUALLY un.sysname on sinix does start with the word "SINIX"
790 * let's be absolutely sure
792 sprintf(un.sysname,"SINIX");
794 if (!strcmp(un.sysname, "AIX")) {
795 strcpy(un.machine, __power_pc() ? "ppc" : "rs6000");
796 sprintf(un.sysname,"aix%s.%s",un.version,un.release);
798 else if (!strcmp(un.sysname, "SunOS")) {
799 if (!strncmp(un.release,"4", 1)) /* SunOS 4.x */ {
801 for (fd=0;(un.release[fd] != 0 && (fd < sizeof(un.release)));fd++)
802 if (!isdigit(un.release[fd]) && (un.release[fd] != '.')) {
806 sprintf(un.sysname,"sunos%s",un.release);
809 else /* Solaris 2.x: n.x.x becomes n-3.x.x */
810 sprintf(un.sysname,"solaris%1d%s",atoi(un.release)-3,un.release+1+(atoi(un.release)/10));
812 else if (!strcmp(un.sysname, "HP-UX"))
813 /*make un.sysname look like hpux9.05 for example*/
814 sprintf(un.sysname,"hpux%s",strpbrk(un.release,"123456789"));
815 else if (!strcmp(un.sysname, "OSF1"))
816 /*make un.sysname look like osf3.2 for example*/
817 sprintf(un.sysname,"osf%s",strpbrk(un.release,"123456789"));
818 else if (!strncmp(un.sysname, "IP", 2))
819 un.sysname[2] = '\0';
820 else if (!strncmp(un.sysname, "SINIX", 5)) {
821 sprintf(un.sysname, "sinix%s",un.release);
822 if (!strncmp(un.machine, "RM", 2))
823 sprintf(un.machine, "mips");
825 else if ((!strncmp(un.machine, "34", 2) || \
826 !strncmp(un.machine, "33", 2)) && \
827 !strncmp(un.release, "4.0", 3)) {
828 /* we are on ncr-sysv4 */
830 FD_t fd = fdOpen("/etc/.relid", O_RDONLY, 0700);
831 if (fdFileno(fd) > 0) {
832 chptr = (char *) calloc(256,1);
834 int irelid = read(fd, (void *)chptr, 256);
836 /* example: "112393 RELEASE 020200 Version 01 OS" */
838 if ((prelid=strstr(chptr, "RELEASE "))){
839 prelid += strlen("RELEASE ")+1;
840 sprintf(un.sysname,"ncr-sysv4.%.*s",1,prelid);
847 /* parsing /etc/.relid file failed */
848 strcpy(un.sysname,"ncr-sysv4");
849 /* wrong, just for now, find out how to look for i586 later*/
850 strcpy(un.machine,"i486");
852 #endif /* __linux__ */
854 /* get rid of the hyphens in the sysname */
855 for (chptr = un.machine; *chptr; chptr++)
856 if (*chptr == '/') *chptr = '-';
858 # if defined(__MIPSEL__) || defined(__MIPSEL) || defined(_MIPSEL)
860 strcpy(un.machine, "mipsel");
861 # elif defined(__MIPSEB__) || defined(__MIPSEB) || defined(_MIPSEB)
863 strcpy(un.machine, "mipseb");
866 # if defined(__hpux) && defined(_SC_CPU_VERSION)
868 # if !defined(CPU_PA_RISC1_2)
869 # define CPU_PA_RISC1_2 0x211 /* HP PA-RISC1.2 */
871 # if !defined(CPU_PA_RISC2_0)
872 # define CPU_PA_RISC2_0 0x214 /* HP PA-RISC2.0 */
874 int cpu_version = sysconf(_SC_CPU_VERSION);
876 # if defined(CPU_HP_MC68020)
877 if (cpu_version == CPU_HP_MC68020)
878 strcpy(un.machine, "m68k");
880 # if defined(CPU_HP_MC68030)
881 if (cpu_version == CPU_HP_MC68030)
882 strcpy(un.machine, "m68k");
884 # if defined(CPU_HP_MC68040)
885 if (cpu_version == CPU_HP_MC68040)
886 strcpy(un.machine, "m68k");
889 # if defined(CPU_PA_RISC1_0)
890 if (cpu_version == CPU_PA_RISC1_0)
891 strcpy(un.machine, "hppa1.0");
893 # if defined(CPU_PA_RISC1_1)
894 if (cpu_version == CPU_PA_RISC1_1)
895 strcpy(un.machine, "hppa1.1");
897 # if defined(CPU_PA_RISC1_2)
898 if (cpu_version == CPU_PA_RISC1_2)
899 strcpy(un.machine, "hppa1.2");
901 # if defined(CPU_PA_RISC2_0)
902 if (cpu_version == CPU_PA_RISC2_0)
903 strcpy(un.machine, "hppa2.0");
908 /* the uname() result goes through the arch_canon table */
909 canon = lookupInCanonTable(un.machine,
910 tables[RPM_MACHTABLE_INSTARCH].canons,
911 tables[RPM_MACHTABLE_INSTARCH].canonsLength);
913 strcpy(un.machine, canon->short_name);
915 canon = lookupInCanonTable(un.sysname,
916 tables[RPM_MACHTABLE_INSTOS].canons,
917 tables[RPM_MACHTABLE_INSTOS].canonsLength);
919 strcpy(un.sysname, canon->short_name);
923 if (arch) *arch = un.machine;
924 if (os) *os = un.sysname;
927 static char * rpmGetVarArch(int var, char * arch) {
928 struct rpmvarValue * next;
930 if (!arch) arch = current[ARCH];
935 if (next->arch && !strcmp(next->arch, arch)) return next->value;
941 while (next && next->arch) next = next->next;
943 return next ? next->value : NULL;
946 char *rpmGetVar(int var)
948 return rpmGetVarArch(var, NULL);
951 /* this doesn't free the passed pointer! */
952 static void freeRpmVar(struct rpmvarValue * orig) {
953 struct rpmvarValue * next, * var = orig;
966 if (var != orig) free(var);
971 void rpmSetVar(int var, const char *val) {
972 freeRpmVar(&values[var]);
973 values[var].value = (val ? strdup(val) : NULL);
976 static void rpmSetVarArch(int var, char * val, char * arch) {
977 struct rpmvarValue * next = values + var;
982 if (next->arch && !strcmp(next->arch, arch)) break;
987 if (!next->arch) break;
992 if (next->arch && arch && !strcmp(next->arch, arch)) {
993 if (next->value) free(next->value);
994 if (next->arch) free(next->arch);
995 } else if (next->arch || arch) {
996 next->next = malloc(sizeof(*next->next));
1002 next->value = strdup(val);
1003 next->arch = (arch ? strdup(arch) : NULL);
1006 void rpmSetTables(int archTable, int osTable) {
1009 defaultMachine(&arch, &os);
1011 if (currTables[ARCH] != archTable) {
1012 currTables[ARCH] = archTable;
1013 rebuildCompatTables(ARCH, arch);
1016 if (currTables[OS] != osTable) {
1017 currTables[OS] = osTable;
1018 rebuildCompatTables(OS, os);
1022 int rpmMachineScore(int type, char * name) {
1023 struct machEquivInfo * info = machEquivSearch(&tables[type].equiv, name);
1024 return (info != NULL ? info->score : 0);
1027 void rpmGetMachine(char **arch, char **os)
1030 *arch = current[ARCH];
1036 void rpmSetMachine(const char * arch, const char * os) {
1037 char * host_cpu, * host_os;
1039 defaultMachine(&host_cpu, &host_os);
1043 if (tables[currTables[ARCH]].hasTranslate)
1044 arch = lookupInDefaultTable(arch,
1045 tables[currTables[ARCH]].defaults,
1046 tables[currTables[ARCH]].defaultsLength);
1051 if (tables[currTables[OS]].hasTranslate)
1052 os = lookupInDefaultTable(os,
1053 tables[currTables[OS]].defaults,
1054 tables[currTables[OS]].defaultsLength);
1057 if (!current[ARCH] || strcmp(arch, current[ARCH])) {
1058 if (current[ARCH]) free(current[ARCH]);
1059 current[ARCH] = strdup(arch);
1060 rebuildCompatTables(ARCH, host_cpu);
1063 if (!current[OS] || strcmp(os, current[OS])) {
1064 if (current[OS]) free(current[OS]);
1065 current[OS] = strdup(os);
1067 * XXX Capitalizing the 'L' is needed to insure that old
1068 * XXX os-from-uname (e.g. "Linux") is compatible with the new
1069 * XXX os-from-platform (e.g "linux" from "sparc-*-linux").
1070 * XXX A copy of this string is embedded in headers and is
1071 * XXX used by rpmInstallPackage->{os,arch}Okay->rpmMachineScore->
1072 * XXX to verify correct arch/os from headers.
1074 if (!strcmp(current[OS], "linux"))
1076 rebuildCompatTables(OS, host_os);
1080 static void rebuildCompatTables(int type, char * name) {
1081 machFindEquivs(&tables[currTables[type]].cache,
1082 &tables[currTables[type]].equiv,
1086 static void getMachineInfo(int type, char ** name, int * num) {
1087 struct canonEntry * canon;
1088 int which = currTables[type];
1090 /* use the normal canon tables, even if we're looking up build stuff */
1091 if (which >= 2) which -= 2;
1093 canon = lookupInCanonTable(current[type],
1094 tables[which].canons,
1095 tables[which].canonsLength);
1098 if (num) *num = canon->num;
1099 if (name) *name = canon->short_name;
1101 if (num) *num = 255;
1102 if (name) *name = current[type];
1104 if (tables[currTables[type]].hasCanon) {
1105 rpmMessage(RPMMESS_WARNING, _("Unknown system: %s\n"), current[type]);
1106 rpmMessage(RPMMESS_WARNING, _("Please contact rpm-list@redhat.com\n"));
1111 void rpmGetArchInfo(char ** name, int * num) {
1112 getMachineInfo(ARCH, name, num);
1115 void rpmGetOsInfo(char ** name, int * num) {
1116 getMachineInfo(OS, name, num);
1119 void rpmRebuildTargetVars(const char **buildtarget, const char ** canontarget)
1122 char *ca = NULL, *co = NULL, *ct;
1123 const char * target = NULL;
1126 /* Rebuild the compat table to recalculate the current target arch. */
1128 rpmSetMachine(NULL, NULL);
1129 rpmSetTables(RPM_MACHTABLE_INSTARCH, RPM_MACHTABLE_INSTOS);
1130 rpmSetTables(RPM_MACHTABLE_BUILDARCH, RPM_MACHTABLE_BUILDOS);
1132 if (buildtarget && *buildtarget) {
1133 /* Set arch and os from specified build target */
1134 ca = ct = strdup(*buildtarget);
1135 if ((co = strrchr(ct, '-')) != NULL) {
1137 if (!strcmp(co, "gnu") && (co = strrchr(ct, '-')) != NULL)
1143 /* Set build target from default arch and os */
1144 rpmGetArchInfo(&ca,NULL);
1145 rpmGetOsInfo(&co,NULL);
1147 if (ca == NULL) defaultMachine(&ca, NULL);
1148 if (co == NULL) defaultMachine(NULL, &co);
1150 for (x = 0; ca[x]; x++)
1151 ca[x] = tolower(ca[x]);
1152 for (x = 0; co[x]; x++)
1153 co[x] = tolower(co[x]);
1155 ct = malloc(strlen(co)+strlen(ca)+2);
1156 sprintf(ct, "%s-%s", ca, co);
1161 * XXX All this macro pokery/jiggery could be achieved by doing a delayed
1162 * initMacros(&globalMacroContext, PER-PLATFORM-MACRO-FILE-NAMES);
1164 delMacro(&globalMacroContext, "_target");
1165 addMacro(&globalMacroContext, "_target", NULL, target, RMIL_RPMRC);
1166 delMacro(&globalMacroContext, "_target_cpu");
1167 addMacro(&globalMacroContext, "_target_cpu", NULL, ca, RMIL_RPMRC);
1168 delMacro(&globalMacroContext, "_target_os");
1169 addMacro(&globalMacroContext, "_target_os", NULL, co, RMIL_RPMRC);
1172 *canontarget = target;
1173 if (ct != NULL && ct != target)
1177 int rpmShowRC(FILE *f)
1179 struct rpmOption *opt;
1181 struct machEquivTable * equivTable;
1183 /* the caller may set the build arch which should be printed here */
1184 fprintf(f, "ARCHITECTURE AND OS:\n");
1185 fprintf(f, "build arch : %s\n", current[ARCH]);
1187 fprintf(f, "compatible build archs:");
1188 equivTable = &tables[RPM_MACHTABLE_BUILDARCH].equiv;
1189 for (i = 0; i < equivTable->count; i++)
1190 fprintf(f," %s", equivTable->list[i].name);
1193 fprintf(f, "build os : %s\n", current[OS]);
1195 fprintf(f, "compatible build os's :");
1196 equivTable = &tables[RPM_MACHTABLE_BUILDOS].equiv;
1197 for (i = 0; i < equivTable->count; i++)
1198 fprintf(f," %s", equivTable->list[i].name);
1201 rpmSetTables(RPM_MACHTABLE_INSTARCH, RPM_MACHTABLE_INSTOS);
1202 rpmSetMachine(NULL, NULL); /* XXX WTFO? Why bother? */
1204 fprintf(f, "install arch : %s\n", current[ARCH]);
1205 fprintf(f, "install os : %s\n", current[OS]);
1207 fprintf(f, "compatible archs :");
1208 equivTable = &tables[RPM_MACHTABLE_INSTARCH].equiv;
1209 for (i = 0; i < equivTable->count; i++)
1210 fprintf(f," %s", equivTable->list[i].name);
1213 fprintf(f, "compatible os's :");
1214 equivTable = &tables[RPM_MACHTABLE_INSTOS].equiv;
1215 for (i = 0; i < equivTable->count; i++)
1216 fprintf(f," %s", equivTable->list[i].name);
1219 fprintf(f, "\nRPMRC VALUES:\n");
1220 for (i = 0, opt = optionTable; i < optionTableSize; i++, opt++) {
1221 char *s = rpmGetVar(opt->var);
1222 if (s != NULL || rpmGetVerbosity() < RPMMESS_NORMAL)
1223 fprintf(f, "%-21s : %s\n", opt->name, s ? s : "(not set)");
1226 dumpMacroTable(&globalMacroContext, f);