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 void defaultMachine(/*@out@*/char ** arch, /*@out@*/char ** os);
108 static int doReadRC(FD_t fd, const char * filename);
109 static int optionCompare(const void * a, const void * b);
110 static int addCanon(struct canonEntry **table, int *tableLen, char *line,
111 const char *fn, int lineNum);
112 static int addDefault(struct defaultEntry **table, int *tableLen, char *line,
113 const char *fn, int lineNum);
114 static void freeRpmVar(struct rpmvarValue * orig);
115 static void rpmSetVarArch(int var, const char * val, const char * arch);
116 static struct canonEntry *lookupInCanonTable(char *name,
117 struct canonEntry *table,
119 static const char *lookupInDefaultTable(const char *name,
120 struct defaultEntry *table,
123 static void setVarDefault(int var, const char *macroname, const char *val, const char *body);
124 static void setPathDefault(int var, const char *macroname, const char *subdir);
125 static void setDefaults(void);
127 static void rebuildCompatTables(int type, char *name);
129 /* compatiblity tables */
130 static int machCompatCacheAdd(char * name, const char * fn, int linenum,
131 struct machCache * cache);
132 static struct machCacheEntry * machCacheFindEntry(struct machCache * cache,
134 static struct machEquivInfo * machEquivSearch(
135 struct machEquivTable * table, char * name);
136 static void machAddEquiv(struct machEquivTable * table, char * name,
138 static void machCacheEntryVisit(struct machCache * cache,
139 struct machEquivTable * table,
142 static void machFindEquivs(struct machCache * cache,
143 struct machEquivTable * table,
146 static int optionCompare(const void * a, const void * b) {
147 return strcasecmp(((struct rpmOption *) a)->name,
148 ((struct rpmOption *) b)->name);
151 static void rpmRebuildTargetVars(const char **target, const char ** canontarget);
154 static struct machCacheEntry * machCacheFindEntry(struct machCache * cache,
159 for (i = 0; i < cache->size; i++)
160 if (!strcmp(cache->cache[i].name, key)) return cache->cache + i;
165 static int machCompatCacheAdd(char * name, const char * fn, int linenum,
166 struct machCache * cache)
168 char * chptr, * equivs;
171 struct machCacheEntry * entry = NULL;
173 while (*name && isspace(*name)) name++;
176 while (*chptr && *chptr != ':') chptr++;
178 rpmError(RPMERR_RPMRC, _("missing second ':' at %s:%d"), fn, linenum);
180 } else if (chptr == name) {
181 rpmError(RPMERR_RPMRC, _("missing architecture name at %s:%d"), fn,
186 while (*chptr == ':' || isspace(*chptr)) chptr--;
189 while (*equivs && isspace(*equivs)) equivs++;
195 entry = machCacheFindEntry(cache, name);
197 for (i = 0; i < entry->count; i++)
198 free(entry->equivs[i]);
199 if (entry->count) free(entry->equivs);
205 cache->cache = realloc(cache->cache,
206 (cache->size + 1) * sizeof(*cache->cache));
207 entry = cache->cache + cache->size++;
208 entry->name = strdup(name);
213 if (delEntry) return 0;
215 while ((chptr = strtok(equivs, " ")) != NULL) {
217 if (chptr[0] == '\0') /* does strtok() return "" ever?? */
220 entry->equivs = realloc(entry->equivs, sizeof(*entry->equivs)
221 * (entry->count + 1));
223 entry->equivs = malloc(sizeof(*entry->equivs));
225 entry->equivs[entry->count] = strdup(chptr);
232 static struct machEquivInfo * machEquivSearch(
233 struct machEquivTable * table, char * name)
238 * XXX The strcasecmp below is necessary so the old (rpm < 2.90) style
239 * XXX os-from-uname (e.g. "Linux") is compatible with the new
240 * XXX os-from-platform (e.g "linux" from "sparc-*-linux").
241 * XXX A copy of this string is embedded in headers and is
242 * XXX used by rpmInstallPackage->{os,arch}Okay->rpmMachineScore->.
243 * XXX to verify correct arch/os from headers.
245 for (i = 0; i < table->count; i++)
246 if (!strcasecmp(table->list[i].name, name))
247 return table->list + i;
252 static void machAddEquiv(struct machEquivTable * table, char * name,
255 struct machEquivInfo * equiv;
257 equiv = machEquivSearch(table, name);
260 table->list = realloc(table->list, (table->count + 1)
261 * sizeof(*table->list));
263 table->list = malloc(sizeof(*table->list));
265 table->list[table->count].name = strdup(name);
266 table->list[table->count++].score = distance;
270 static void machCacheEntryVisit(struct machCache * cache,
271 struct machEquivTable * table,
275 struct machCacheEntry * entry;
278 entry = machCacheFindEntry(cache, name);
279 if (!entry || entry->visited) return;
283 for (i = 0; i < entry->count; i++) {
284 machAddEquiv(table, entry->equivs[i], distance);
287 for (i = 0; i < entry->count; i++) {
288 machCacheEntryVisit(cache, table, entry->equivs[i], distance + 1);
292 static void machFindEquivs(struct machCache * cache,
293 struct machEquivTable * table,
298 for (i = 0; i < cache->size; i++)
299 cache->cache[i].visited = 0;
303 /* We have a general graph built using strings instead of pointers.
304 Yuck. We have to start at a point at traverse it, remembering how
305 far away everything is. */
306 machAddEquiv(table, key, 1);
307 machCacheEntryVisit(cache, table, key, 2);
310 static int addCanon(struct canonEntry **table, int *tableLen, char *line,
311 const char *fn, int lineNum)
313 struct canonEntry *t;
318 *table = malloc(2 * sizeof(struct canonEntry));
321 *table = realloc(*table, sizeof(struct canonEntry) * (*tableLen));
323 t = & ((*table)[*tableLen - 2]);
325 t->name = strtok(line, ": \t");
326 t->short_name = strtok(NULL, " \t");
327 s = strtok(NULL, " \t");
328 if (! (t->name && t->short_name && s)) {
329 rpmError(RPMERR_RPMRC, _("Incomplete data line at %s:%d"), fn, lineNum);
332 if (strtok(NULL, " \t")) {
333 rpmError(RPMERR_RPMRC, _("Too many args in data line at %s:%d"),
338 t->num = strtoul(s, &s1, 10);
339 if ((*s1) || (s1 == s) || (t->num == ULONG_MAX)) {
340 rpmError(RPMERR_RPMRC, _("Bad arch/os number: %s (%s:%d)"), s,
342 return(RPMERR_RPMRC);
345 t->name = strdup(t->name);
346 t->short_name = strdup(t->short_name);
348 /* From A B C entry */
349 /* Add B B C entry */
350 t[1].name = strdup(t->short_name);
351 t[1].short_name = strdup(t->short_name);
357 static int addDefault(struct defaultEntry **table, int *tableLen, char *line,
358 const char *fn, int lineNum)
360 struct defaultEntry *t;
364 *table = malloc(sizeof(struct defaultEntry));
367 *table = realloc(*table, sizeof(struct defaultEntry) * (*tableLen));
369 t = & ((*table)[*tableLen - 1]);
371 t->name = strtok(line, ": \t");
372 t->defName = strtok(NULL, " \t");
373 if (! (t->name && t->defName)) {
374 rpmError(RPMERR_RPMRC, _("Incomplete default line at %s:%d"),
378 if (strtok(NULL, " \t")) {
379 rpmError(RPMERR_RPMRC, _("Too many args in default line at %s:%d"),
384 t->name = strdup(t->name);
385 t->defName = strdup(t->defName);
390 static struct canonEntry *lookupInCanonTable(char *name,
391 struct canonEntry *table,
395 if (!strcmp(name, table[tableLen].name)) {
396 return &(table[tableLen]);
403 static const char *lookupInDefaultTable(const char *name, struct defaultEntry *table,
407 if (!strcmp(name, table[tableLen].name)) {
408 return table[tableLen].defName;
415 int rpmReadConfigFiles(const char * file, const char * target)
418 /* Preset target macros */
419 rpmRebuildTargetVars(&target, NULL);
422 if (rpmReadRC(file)) return -1;
424 /* Reset target macros */
425 rpmRebuildTargetVars(&target, NULL);
427 /* Finally set target platform */
428 { const char *cpu = rpmExpand("%{_target_cpu}", NULL);
429 const char *os = rpmExpand("%{_target_os}", NULL);
430 rpmSetMachine(cpu, os);
438 static void setVarDefault(int var, const char *macroname, const char *val, const char *body)
440 if (var >= 0) { /* XXX Dying ... */
441 if (rpmGetVar(var)) return;
446 addMacro(NULL, macroname, NULL, body, RMIL_DEFAULT);
449 static void setPathDefault(int var, const char *macroname, const char *subdir)
452 if (var >= 0) { /* XXX Dying ... */
456 if (rpmGetVar(var)) return;
458 topdir = rpmGetPath("%{_topdir}", NULL);
460 fn = alloca(strlen(topdir) + strlen(subdir) + 2);
462 if (fn[strlen(topdir) - 1] != '/')
467 if (topdir) xfree(topdir);
470 if (macroname != NULL) {
471 #define _TOPDIRMACRO "%{_topdir}/"
472 char *body = alloca(sizeof(_TOPDIRMACRO) + strlen(subdir));
473 strcpy(body, _TOPDIRMACRO);
474 strcat(body, subdir);
475 addMacro(NULL, macroname, NULL, body, RMIL_DEFAULT);
480 static const char *prescriptenviron = "\n\
481 RPM_SOURCE_DIR=\"%{_sourcedir}\"\n\
482 RPM_BUILD_DIR=\"%{_builddir}\"\n\
483 RPM_OPT_FLAGS=\"%{optflags}\"\n\
484 RPM_ARCH=\"%{_arch}\"\n\
486 export RPM_SOURCE_DIR RPM_BUILD_DIR RPM_OPT_FLAGS RPM_ARCH RPM_OS\n\
487 RPM_DOC_DIR=\"%{_docdir}\"\n\
488 export RPM_DOC_DIR\n\
489 RPM_PACKAGE_NAME=\"%{name}\"\n\
490 RPM_PACKAGE_VERSION=\"%{version}\"\n\
491 RPM_PACKAGE_RELEASE=\"%{release}\"\n\
492 export RPM_PACKAGE_NAME RPM_PACKAGE_VERSION RPM_PACKAGE_RELEASE\n\
493 %{?buildroot:RPM_BUILD_ROOT=\"%{buildroot}\"\n\
494 export RPM_BUILD_ROOT\n}\
497 static void setDefaults(void) {
499 addMacro(NULL, "_usr", NULL, "/usr", RMIL_DEFAULT);
500 addMacro(NULL, "_var", NULL, "/var", RMIL_DEFAULT);
502 addMacro(NULL, "_preScriptEnvironment",NULL, prescriptenviron,RMIL_DEFAULT);
504 setVarDefault(-1, "_topdir",
505 "/usr/src/redhat", "%{_usr}/src/redhat");
506 setVarDefault(-1, "_tmppath",
507 "/var/tmp", "%{_var}/tmp");
508 setVarDefault(-1, "_dbpath",
509 "/var/lib/rpm", "%{_var}/lib/rpm");
510 setVarDefault(-1, "_defaultdocdir",
511 "/usr/doc", "%{_usr}/doc");
513 setVarDefault(-1, "_rpmfilename",
514 "%%{ARCH}/%%{NAME}-%%{VERSION}-%%{RELEASE}.%%{ARCH}.rpm",NULL);
516 setVarDefault(RPMVAR_OPTFLAGS, "optflags",
518 setVarDefault(-1, "sigtype",
520 setVarDefault(-1, "_buildshell",
523 setPathDefault(-1, "_builddir", "BUILD");
524 setPathDefault(-1, "_rpmdir", "RPMS");
525 setPathDefault(-1, "_srcrpmdir", "SRPMS");
526 setPathDefault(-1, "_sourcedir", "SOURCES");
527 setPathDefault(-1, "_specdir", "SPECS");
531 int rpmReadRC(const char * rcfiles)
533 char *myrcfiles, *r, *re;
535 static int first = 1;
543 rcfiles = defrcfiles;
545 /* Read each file in rcfiles. */
547 for (r = myrcfiles = strdup(rcfiles); *r != '\0'; r = re) {
551 /* Get pointer to rest of files */
552 if ((re = strchr(r, ':')) != NULL)
557 /* Expand ~/ to $HOME/ */
559 if (r[0] == '~' && r[1] == '/') {
560 char *home = getenv("HOME");
562 rpmError(RPMERR_RPMRC, _("Cannot expand %s"), r);
571 /* Read another rcfile */
572 fd = fdOpen(fn, O_RDONLY, 0);
573 if (fdFileno(fd) < 0) {
574 /* XXX Only /usr/lib/rpm/rpmrc must exist in default rcfiles list */
575 if (rcfiles == defrcfiles && myrcfiles != r)
577 rpmError(RPMERR_RPMRC, _("Unable to open %s for reading: %s."),
578 fn, strerror(errno));
582 rc = doReadRC(fd, fn);
586 if (myrcfiles) free(myrcfiles);
590 rpmSetMachine(NULL, NULL); /* XXX WTFO? Why bother? */
592 if ((r = rpmGetVar(RPMVAR_MACROFILES)) != NULL)
598 static int doReadRC(FD_t fd, const char * filename)
602 struct rpmOption searchOption, * option;
606 fstat(fdFileno(fd), &sb);
607 next = alloca(sb.st_size + 2);
608 if (fdRead(fd, next, sb.st_size) != sb.st_size) {
609 rpmError(RPMERR_RPMRC, _("Failed to read %s: %s."), filename,
613 next[sb.st_size] = '\n';
614 next[sb.st_size + 1] = '\0';
621 while (*se && *se != '\n') se++;
622 if (*se) *se++ = '\0';
625 while (*s && isspace(*s)) s++;
627 /* we used to allow comments to begin anywhere, but not anymore */
628 if (*s == '#' || *s == '\0') continue;
631 while (*se && !isspace(*se) && *se != ':') se++;
635 while (*se && isspace(*se) && *se != ':') se++;
639 rpmError(RPMERR_RPMRC, _("missing ':' at %s:%d"),
644 while (*se && isspace(*se)) se++;
646 /* Find keyword in table */
647 searchOption.name = s;
648 option = bsearch(&searchOption, optionTable, optionTableSize,
649 sizeof(struct rpmOption), optionCompare);
651 if (option) { /* For configuration variables ... */
652 const char *arch, *val, *fn;
654 arch = val = fn = NULL;
656 rpmError(RPMERR_RPMRC, _("missing argument for %s at %s:%d"),
657 option->name, filename, linenum);
661 switch (option->var) {
666 while (*se && !isspace(*se)) se++;
667 if (*se) *se++ = '\0';
669 rpmRebuildTargetVars(NULL, NULL);
671 fn = rpmGetPath(s, NULL);
672 if (fn == NULL || *fn == '\0') {
673 rpmError(RPMERR_RPMRC, _("%s expansion failed at %s:%d \"%s\""),
674 option->name, filename, linenum, s);
679 fdinc = fdOpen(fn, O_RDONLY, 0);
680 if (fdFileno(fdinc) < 0) {
681 rpmError(RPMERR_RPMRC, _("cannot open %s at %s:%d"),
682 fn, filename, linenum);
685 rc = doReadRC(fdinc, fn);
690 continue; /* XXX don't save include value as var/macro */
692 case RPMVAR_MACROFILES:
693 fn = rpmGetPath(se, NULL);
694 if (fn == NULL || *fn == '\0') {
695 rpmError(RPMERR_RPMRC, _("%s expansion failed at %s:%d \"%s\""),
696 option->name, filename, linenum, fn);
702 case RPMVAR_PROVIDES:
704 s = rpmGetVar(RPMVAR_PROVIDES);
705 if (s == NULL) s = "";
706 fn = t = malloc(strlen(s) + strlen(se) + 2);
707 while (*s) *t++ = *s++;
709 while (*se) *t++ = *se++;
717 if (option->archSpecific) {
719 while (*se && !isspace(*se)) se++;
721 rpmError(RPMERR_RPMRC,
722 _("missing architecture for %s at %s:%d"),
723 option->name, filename, linenum);
727 while (*se && isspace(*se)) se++;
729 rpmError(RPMERR_RPMRC,
730 _("missing argument for %s at %s:%d"),
731 option->name, filename, linenum);
738 /* Only add macros if appropriate for this arch */
739 if (option->macroize &&
740 (arch == NULL || !strcmp(arch, current[ARCH]))) {
742 n = name = malloc(strlen(option->name)+2);
743 if (option->localize)
745 strcpy(n, option->name);
746 addMacro(NULL, name, NULL, val, RMIL_RPMRC);
749 rpmSetVarArch(option->var, val, arch);
752 } else { /* For arch/os compatibilty tables ... */
758 for (i = 0; i < RPM_MACHTABLE_COUNT; i++) {
759 if (!strncmp(tables[i].key, s, strlen(tables[i].key)))
763 if (i < RPM_MACHTABLE_COUNT) {
764 char *rest = s + strlen(tables[i].key);
765 if (*rest == '_') rest++;
767 if (!strcmp(rest, "compat")) {
768 if (machCompatCacheAdd(se, filename, linenum,
772 } else if (tables[i].hasTranslate &&
773 !strcmp(rest, "translate")) {
774 if (addDefault(&tables[i].defaults,
775 &tables[i].defaultsLength,
776 se, filename, linenum))
779 } else if (tables[i].hasCanon &&
780 !strcmp(rest, "canon")) {
781 if (addCanon(&tables[i].canons, &tables[i].canonsLength,
782 se, filename, linenum))
789 rpmError(RPMERR_RPMRC, _("bad option '%s' at %s:%d"),
790 s, filename, linenum);
798 static void defaultMachine(char ** arch, char ** os) {
799 static struct utsname un;
800 static int gotDefaults = 0;
802 struct canonEntry * canon;
807 #if !defined(__linux__)
809 /* USUALLY un.sysname on sinix does start with the word "SINIX"
810 * let's be absolutely sure
812 sprintf(un.sysname,"SINIX");
814 if (!strcmp(un.sysname, "AIX")) {
815 strcpy(un.machine, __power_pc() ? "ppc" : "rs6000");
816 sprintf(un.sysname,"aix%s.%s",un.version,un.release);
818 else if (!strcmp(un.sysname, "SunOS")) {
819 if (!strncmp(un.release,"4", 1)) /* SunOS 4.x */ {
821 for (fd=0;(un.release[fd] != 0 && (fd < sizeof(un.release)));fd++)
822 if (!isdigit(un.release[fd]) && (un.release[fd] != '.')) {
826 sprintf(un.sysname,"sunos%s",un.release);
829 else /* Solaris 2.x: n.x.x becomes n-3.x.x */
830 sprintf(un.sysname,"solaris%1d%s",atoi(un.release)-3,un.release+1+(atoi(un.release)/10));
832 else if (!strcmp(un.sysname, "HP-UX"))
833 /*make un.sysname look like hpux9.05 for example*/
834 sprintf(un.sysname,"hpux%s",strpbrk(un.release,"123456789"));
835 else if (!strcmp(un.sysname, "OSF1"))
836 /*make un.sysname look like osf3.2 for example*/
837 sprintf(un.sysname,"osf%s",strpbrk(un.release,"123456789"));
838 else if (!strncmp(un.sysname, "IP", 2))
839 un.sysname[2] = '\0';
840 else if (!strncmp(un.sysname, "SINIX", 5)) {
841 sprintf(un.sysname, "sinix%s",un.release);
842 if (!strncmp(un.machine, "RM", 2))
843 sprintf(un.machine, "mips");
845 else if ((!strncmp(un.machine, "34", 2) || \
846 !strncmp(un.machine, "33", 2)) && \
847 !strncmp(un.release, "4.0", 3)) {
848 /* we are on ncr-sysv4 */
850 FD_t fd = fdOpen("/etc/.relid", O_RDONLY, 0700);
851 if (fdFileno(fd) > 0) {
852 chptr = (char *) calloc(256,1);
854 int irelid = fdRead(fd, (void *)chptr, 256);
856 /* example: "112393 RELEASE 020200 Version 01 OS" */
858 if ((prelid=strstr(chptr, "RELEASE "))){
859 prelid += strlen("RELEASE ")+1;
860 sprintf(un.sysname,"ncr-sysv4.%.*s",1,prelid);
867 /* parsing /etc/.relid file failed */
868 strcpy(un.sysname,"ncr-sysv4");
869 /* wrong, just for now, find out how to look for i586 later*/
870 strcpy(un.machine,"i486");
872 #endif /* __linux__ */
874 /* get rid of the hyphens in the sysname */
875 for (chptr = un.machine; *chptr; chptr++)
876 if (*chptr == '/') *chptr = '-';
878 # if defined(__MIPSEL__) || defined(__MIPSEL) || defined(_MIPSEL)
880 strcpy(un.machine, "mipsel");
881 # elif defined(__MIPSEB__) || defined(__MIPSEB) || defined(_MIPSEB)
883 strcpy(un.machine, "mipseb");
886 # if defined(__hpux) && defined(_SC_CPU_VERSION)
888 # if !defined(CPU_PA_RISC1_2)
889 # define CPU_PA_RISC1_2 0x211 /* HP PA-RISC1.2 */
891 # if !defined(CPU_PA_RISC2_0)
892 # define CPU_PA_RISC2_0 0x214 /* HP PA-RISC2.0 */
894 int cpu_version = sysconf(_SC_CPU_VERSION);
896 # if defined(CPU_HP_MC68020)
897 if (cpu_version == CPU_HP_MC68020)
898 strcpy(un.machine, "m68k");
900 # if defined(CPU_HP_MC68030)
901 if (cpu_version == CPU_HP_MC68030)
902 strcpy(un.machine, "m68k");
904 # if defined(CPU_HP_MC68040)
905 if (cpu_version == CPU_HP_MC68040)
906 strcpy(un.machine, "m68k");
909 # if defined(CPU_PA_RISC1_0)
910 if (cpu_version == CPU_PA_RISC1_0)
911 strcpy(un.machine, "hppa1.0");
913 # if defined(CPU_PA_RISC1_1)
914 if (cpu_version == CPU_PA_RISC1_1)
915 strcpy(un.machine, "hppa1.1");
917 # if defined(CPU_PA_RISC1_2)
918 if (cpu_version == CPU_PA_RISC1_2)
919 strcpy(un.machine, "hppa1.2");
921 # if defined(CPU_PA_RISC2_0)
922 if (cpu_version == CPU_PA_RISC2_0)
923 strcpy(un.machine, "hppa2.0");
928 # if defined(__linux__) && defined(__sparc__)
929 if (!strcmp(un.machine, "sparc")) {
930 #define PERS_LINUX 0x00000000
931 #define PERS_LINUX_32BIT 0x00800000
932 #define PERS_LINUX32 0x00000008
934 extern int personality(unsigned long);
937 oldpers = personality(PERS_LINUX_32BIT);
939 if (personality(PERS_LINUX) != -1) {
941 if (! strcmp(un.machine, "sparc64")) {
942 strcpy(un.machine, "sparcv9");
943 oldpers = PERS_LINUX32;
946 personality(oldpers);
949 # endif /* sparc*-linux */
951 /* the uname() result goes through the arch_canon table */
952 canon = lookupInCanonTable(un.machine,
953 tables[RPM_MACHTABLE_INSTARCH].canons,
954 tables[RPM_MACHTABLE_INSTARCH].canonsLength);
956 strcpy(un.machine, canon->short_name);
958 canon = lookupInCanonTable(un.sysname,
959 tables[RPM_MACHTABLE_INSTOS].canons,
960 tables[RPM_MACHTABLE_INSTOS].canonsLength);
962 strcpy(un.sysname, canon->short_name);
966 if (arch) *arch = un.machine;
967 if (os) *os = un.sysname;
970 static char * rpmGetVarArch(int var, char * arch) {
971 struct rpmvarValue * next;
973 if (!arch) arch = current[ARCH];
978 if (next->arch && !strcmp(next->arch, arch)) return next->value;
984 while (next && next->arch) next = next->next;
986 return next ? next->value : NULL;
989 char *rpmGetVar(int var)
991 return rpmGetVarArch(var, NULL);
994 /* this doesn't free the passed pointer! */
995 static void freeRpmVar(struct rpmvarValue * orig) {
996 struct rpmvarValue * next, * var = orig;
1009 if (var != orig) free(var);
1014 void rpmSetVar(int var, const char *val) {
1015 freeRpmVar(&values[var]);
1016 values[var].value = (val ? strdup(val) : NULL);
1019 static void rpmSetVarArch(int var, const char * val, const char * arch) {
1020 struct rpmvarValue * next = values + var;
1024 while (next->next) {
1025 if (next->arch && !strcmp(next->arch, arch)) break;
1029 while (next->next) {
1030 if (!next->arch) break;
1035 if (next->arch && arch && !strcmp(next->arch, arch)) {
1036 if (next->value) free(next->value);
1037 if (next->arch) free(next->arch);
1038 } else if (next->arch || arch) {
1039 next->next = malloc(sizeof(*next->next));
1045 next->value = strdup(val);
1046 next->arch = (arch ? strdup(arch) : NULL);
1049 void rpmSetTables(int archTable, int osTable) {
1052 defaultMachine(&arch, &os);
1054 if (currTables[ARCH] != archTable) {
1055 currTables[ARCH] = archTable;
1056 rebuildCompatTables(ARCH, arch);
1059 if (currTables[OS] != osTable) {
1060 currTables[OS] = osTable;
1061 rebuildCompatTables(OS, os);
1065 int rpmMachineScore(int type, char * name) {
1066 struct machEquivInfo * info = machEquivSearch(&tables[type].equiv, name);
1067 return (info != NULL ? info->score : 0);
1070 void rpmGetMachine(char **arch, char **os)
1073 *arch = current[ARCH];
1079 void rpmSetMachine(const char * arch, const char * os) {
1080 char * host_cpu, * host_os;
1082 defaultMachine(&host_cpu, &host_os);
1086 if (tables[currTables[ARCH]].hasTranslate)
1087 arch = lookupInDefaultTable(arch,
1088 tables[currTables[ARCH]].defaults,
1089 tables[currTables[ARCH]].defaultsLength);
1094 if (tables[currTables[OS]].hasTranslate)
1095 os = lookupInDefaultTable(os,
1096 tables[currTables[OS]].defaults,
1097 tables[currTables[OS]].defaultsLength);
1100 if (!current[ARCH] || strcmp(arch, current[ARCH])) {
1101 if (current[ARCH]) free(current[ARCH]);
1102 current[ARCH] = strdup(arch);
1103 rebuildCompatTables(ARCH, host_cpu);
1106 if (!current[OS] || strcmp(os, current[OS])) {
1107 if (current[OS]) free(current[OS]);
1108 current[OS] = strdup(os);
1110 * XXX Capitalizing the 'L' is needed to insure that old
1111 * XXX os-from-uname (e.g. "Linux") is compatible with the new
1112 * XXX os-from-platform (e.g "linux" from "sparc-*-linux").
1113 * XXX A copy of this string is embedded in headers and is
1114 * XXX used by rpmInstallPackage->{os,arch}Okay->rpmMachineScore->
1115 * XXX to verify correct arch/os from headers.
1117 if (!strcmp(current[OS], "linux"))
1119 rebuildCompatTables(OS, host_os);
1123 static void rebuildCompatTables(int type, char * name) {
1124 machFindEquivs(&tables[currTables[type]].cache,
1125 &tables[currTables[type]].equiv,
1129 static void getMachineInfo(int type, /*@out@*/char ** name, /*@out@*/int * num) {
1130 struct canonEntry * canon;
1131 int which = currTables[type];
1133 /* use the normal canon tables, even if we're looking up build stuff */
1134 if (which >= 2) which -= 2;
1136 canon = lookupInCanonTable(current[type],
1137 tables[which].canons,
1138 tables[which].canonsLength);
1141 if (num) *num = canon->num;
1142 if (name) *name = canon->short_name;
1144 if (num) *num = 255;
1145 if (name) *name = current[type];
1147 if (tables[currTables[type]].hasCanon) {
1148 rpmMessage(RPMMESS_WARNING, _("Unknown system: %s\n"), current[type]);
1149 rpmMessage(RPMMESS_WARNING, _("Please contact rpm-list@redhat.com\n"));
1154 void rpmGetArchInfo(char ** name, int * num) {
1155 getMachineInfo(ARCH, name, num);
1158 void rpmGetOsInfo(char ** name, int * num) {
1159 getMachineInfo(OS, name, num);
1162 void rpmRebuildTargetVars(const char **buildtarget, const char ** canontarget)
1165 char *ca = NULL, *co = NULL, *ct = NULL;
1168 /* Rebuild the compat table to recalculate the current target arch. */
1170 rpmSetMachine(NULL, NULL);
1171 rpmSetTables(RPM_MACHTABLE_INSTARCH, RPM_MACHTABLE_INSTOS);
1172 rpmSetTables(RPM_MACHTABLE_BUILDARCH, RPM_MACHTABLE_BUILDOS);
1174 if (buildtarget && *buildtarget) {
1176 /* Set arch and os from specified build target */
1177 ca = strdup(*buildtarget);
1178 if ((c = strchr(ca, '-')) != NULL) {
1181 if ((co = strrchr(c, '-')) == NULL) {
1184 if (!strcasecmp(co, "-gnu"))
1186 if ((co = strrchr(c, '-')) == NULL)
1191 if (co != NULL) co = strdup(co);
1194 /* Set build target from rpm arch and os */
1195 rpmGetArchInfo(&ca,NULL);
1196 if (ca) ca = strdup(ca);
1197 rpmGetOsInfo(&co,NULL);
1198 if (co) co = strdup(co);
1201 /* If still not set, Set target arch/os from default uname(2) values */
1203 defaultMachine(&ca, NULL);
1206 for (x = 0; ca[x]; x++)
1207 ca[x] = tolower(ca[x]);
1210 defaultMachine(NULL, &co);
1213 for (x = 0; co[x]; x++)
1214 co[x] = tolower(co[x]);
1216 /* XXX For now, set canonical target to arch-os */
1218 ct = malloc(strlen(ca) + sizeof("-") + strlen(co));
1219 sprintf(ct, "%s-%s", ca, co);
1223 * XXX All this macro pokery/jiggery could be achieved by doing a delayed
1224 * initMacros(NULL, PER-PLATFORM-MACRO-FILE-NAMES);
1226 delMacro(NULL, "_target");
1227 addMacro(NULL, "_target", NULL, ct, RMIL_RPMRC);
1228 delMacro(NULL, "_target_cpu");
1229 addMacro(NULL, "_target_cpu", NULL, ca, RMIL_RPMRC);
1230 delMacro(NULL, "_target_os");
1231 addMacro(NULL, "_target_os", NULL, co, RMIL_RPMRC);
1233 * XXX Make sure that per-arch optflags is initialized correctly.
1235 { char *optflags = rpmGetVarArch(RPMVAR_OPTFLAGS, ca);
1236 if (optflags != NULL) {
1237 delMacro(NULL, "optflags");
1238 addMacro(NULL, "optflags", NULL, optflags, RMIL_RPMRC);
1250 int rpmShowRC(FILE *f)
1252 struct rpmOption *opt;
1254 struct machEquivTable * equivTable;
1256 /* the caller may set the build arch which should be printed here */
1257 fprintf(f, "ARCHITECTURE AND OS:\n");
1258 fprintf(f, "build arch : %s\n", current[ARCH]);
1260 fprintf(f, "compatible build archs:");
1261 equivTable = &tables[RPM_MACHTABLE_BUILDARCH].equiv;
1262 for (i = 0; i < equivTable->count; i++)
1263 fprintf(f," %s", equivTable->list[i].name);
1266 fprintf(f, "build os : %s\n", current[OS]);
1268 fprintf(f, "compatible build os's :");
1269 equivTable = &tables[RPM_MACHTABLE_BUILDOS].equiv;
1270 for (i = 0; i < equivTable->count; i++)
1271 fprintf(f," %s", equivTable->list[i].name);
1274 rpmSetTables(RPM_MACHTABLE_INSTARCH, RPM_MACHTABLE_INSTOS);
1275 rpmSetMachine(NULL, NULL); /* XXX WTFO? Why bother? */
1277 fprintf(f, "install arch : %s\n", current[ARCH]);
1278 fprintf(f, "install os : %s\n", current[OS]);
1280 fprintf(f, "compatible archs :");
1281 equivTable = &tables[RPM_MACHTABLE_INSTARCH].equiv;
1282 for (i = 0; i < equivTable->count; i++)
1283 fprintf(f," %s", equivTable->list[i].name);
1286 fprintf(f, "compatible os's :");
1287 equivTable = &tables[RPM_MACHTABLE_INSTOS].equiv;
1288 for (i = 0; i < equivTable->count; i++)
1289 fprintf(f," %s", equivTable->list[i].name);
1292 fprintf(f, "\nRPMRC VALUES:\n");
1293 for (i = 0, opt = optionTable; i < optionTableSize; i++, opt++) {
1294 char *s = rpmGetVar(opt->var);
1295 if (s != NULL || rpmGetVerbosity() < RPMMESS_NORMAL)
1296 fprintf(f, "%-21s : %s\n", opt->name, s ? s : "(not set)");
1299 dumpMacroTable(NULL, f);