3 #if HAVE_SYS_SYSTEMCFG_H
4 #include <sys/systemcfg.h>
14 static const char *defrcfiles = LIBRPMRC_FILENAME ":/etc/rpmrc:~/.rpmrc";
17 static const char *macrofiles = MACROFILES;
20 struct MacroContext globalMacroContext;
22 struct machCacheEntry {
30 struct machCacheEntry * cache;
34 struct machEquivInfo {
39 struct machEquivTable {
41 struct machEquivInfo * list;
46 /* eventually, this arch will be replaced with a generic condition */
48 struct rpmvarValue * next;
54 int archSpecific, required, macroize, localize;
55 struct rpmOptionValue * value;
69 /* tags are 'key'canon, 'key'translate, 'key'compat
71 for giggles, 'key'_canon, 'key'_compat, and 'key'_canon will also work */
74 int hasCanon, hasTranslate;
75 struct machEquivTable equiv;
76 struct machCache cache;
77 struct defaultEntry * defaults;
78 struct canonEntry * canons;
84 static struct tableType tables[RPM_MACHTABLE_COUNT] = {
87 { "buildarch", 0, 1 },
91 /* this *must* be kept in alphabetical order */
92 /* The order of the flags is archSpecific, required, macroize, localize */
94 static struct rpmOption optionTable[] = {
95 { "builddir", RPMVAR_BUILDDIR, 0, 0, 1, 2 },
96 { "buildroot", RPMVAR_BUILDROOT, 0, 0, 1, 0 },
97 { "buildshell", RPMVAR_BUILDSHELL, 0, 0, 1, 0 },
98 { "bzip2bin", RPMVAR_BZIP2BIN, 0, 1, 1, 2 },
99 { "dbpath", RPMVAR_DBPATH, 0, 1, 1, 2 },
100 { "defaultdocdir", RPMVAR_DEFAULTDOCDIR, 0, 0, 1, 1 },
101 { "distribution", RPMVAR_DISTRIBUTION, 0, 0, 1, 0 },
102 { "excludedocs", RPMVAR_EXCLUDEDOCS, 0, 0, 1, 0 },
103 { "fixperms", RPMVAR_FIXPERMS, 0, 1, 1, 2 },
104 { "ftpport", RPMVAR_FTPPORT, 0, 0, 1, 0 },
105 { "ftpproxy", RPMVAR_FTPPROXY, 0, 0, 1, 0 },
106 { "gzipbin", RPMVAR_GZIPBIN, 0, 1, 1, 2 },
107 { "include", RPMVAR_INCLUDE, 0, 1, 1, 2 },
108 { "instchangelog", RPMVAR_INSTCHANGELOG, 0, 0, 0, 0 },
109 { "langpatt", RPMVAR_LANGPATT, 0, 0, 1, 0 },
110 { "macrofiles", RPMVAR_MACROFILES, 0, 0, 1, 1 },
111 { "messagelevel", RPMVAR_MESSAGELEVEL, 0, 0, 1, 0 },
112 { "netsharedpath", RPMVAR_NETSHAREDPATH, 0, 0, 1, 0 },
113 { "optflags", RPMVAR_OPTFLAGS, 1, 0, 1, 0 },
114 { "packager", RPMVAR_PACKAGER, 0, 0, 1, 0 },
115 { "pgp_name", RPMVAR_PGP_NAME, 0, 0, 1, 0 },
116 { "pgp_path", RPMVAR_PGP_PATH, 0, 0, 1, 0 },
117 { "provides", RPMVAR_PROVIDES, 0, 0, 1, 0 },
118 { "require_distribution", RPMVAR_REQUIREDISTRIBUTION, 0, 0, 1, 0 },
119 { "require_icon", RPMVAR_REQUIREICON, 0, 0, 1, 0 },
120 { "require_vendor", RPMVAR_REQUIREVENDOR, 0, 0, 1, 0 },
121 { "rpmdir", RPMVAR_RPMDIR, 0, 0, 1, 1 },
122 { "rpmfilename", RPMVAR_RPMFILENAME, 0, 1, 1, 2 },
123 #if defined(RPMVAR_SETENV)
124 { "setenv", RPMVAR_SETENV, 0, 1, 0. 0 },
126 { "signature", RPMVAR_SIGTYPE, 0, 0, 0, 0 },
127 { "sourcedir", RPMVAR_SOURCEDIR, 0, 0, 1, 1 },
128 { "specdir", RPMVAR_SPECDIR, 0, 0, 1, 1 },
129 { "srcrpmdir", RPMVAR_SRPMDIR, 0, 0, 1, 1 },
130 { "timecheck", RPMVAR_TIMECHECK, 0, 0, 1, 0 },
131 { "tmppath", RPMVAR_TMPPATH, 0, 1, 1, 2 },
132 { "topdir", RPMVAR_TOPDIR, 0, 0, 1, 1 },
133 { "vendor", RPMVAR_VENDOR, 0, 0, 1, 1 },
136 static int optionTableSize = sizeof(optionTable) / sizeof(*optionTable);
141 static char * current[2];
142 static int currTables[2] = { RPM_MACHTABLE_INSTOS, RPM_MACHTABLE_INSTARCH };
143 static struct rpmvarValue values[RPMVAR_NUM];
146 static void defaultMachine(char ** arch, char ** os);
147 static int doReadRC(FD_t fd, const char * filename);
148 static int optionCompare(const void * a, const void * b);
149 static int addCanon(struct canonEntry **table, int *tableLen, char *line,
150 const char *fn, int lineNum);
151 static int addDefault(struct defaultEntry **table, int *tableLen, char *line,
152 const char *fn, int lineNum);
153 static void freeRpmVar(struct rpmvarValue * orig);
154 static void rpmSetVarArch(int var, char * val, char * arch);
155 static struct canonEntry *lookupInCanonTable(char *name,
156 struct canonEntry *table,
158 static const char *lookupInDefaultTable(const char *name,
159 struct defaultEntry *table,
162 static void setVarDefault(int var, const char *macroname, const char *val, const char *body);
163 static void setPathDefault(int var, const char *macroname, const char *subdir);
164 static void setDefaults(void);
166 static void rebuildCompatTables(int type, char *name);
168 /* compatiblity tables */
169 static int machCompatCacheAdd(char * name, const char * fn, int linenum,
170 struct machCache * cache);
171 static struct machCacheEntry * machCacheFindEntry(struct machCache * cache,
173 static struct machEquivInfo * machEquivSearch(
174 struct machEquivTable * table, char * name);
175 static void machAddEquiv(struct machEquivTable * table, char * name,
177 static void machCacheEntryVisit(struct machCache * cache,
178 struct machEquivTable * table,
181 static void machFindEquivs(struct machCache * cache,
182 struct machEquivTable * table,
185 static int optionCompare(const void * a, const void * b) {
186 return strcasecmp(((struct rpmOption *) a)->name,
187 ((struct rpmOption *) b)->name);
190 static void rpmRebuildTargetVars(const char ** canontarget);
193 static struct machCacheEntry * machCacheFindEntry(struct machCache * cache,
198 for (i = 0; i < cache->size; i++)
199 if (!strcmp(cache->cache[i].name, key)) return cache->cache + i;
204 static int machCompatCacheAdd(char * name, const char * fn, int linenum,
205 struct machCache * cache)
207 char * chptr, * equivs;
210 struct machCacheEntry * entry = NULL;
212 while (*name && isspace(*name)) name++;
215 while (*chptr && *chptr != ':') chptr++;
217 rpmError(RPMERR_RPMRC, _("missing second ':' at %s:%d"), fn, linenum);
219 } else if (chptr == name) {
220 rpmError(RPMERR_RPMRC, _("missing architecture name at %s:%d"), fn,
225 while (*chptr == ':' || isspace(*chptr)) chptr--;
228 while (*equivs && isspace(*equivs)) equivs++;
234 entry = machCacheFindEntry(cache, name);
236 for (i = 0; i < entry->count; i++)
237 free(entry->equivs[i]);
238 if (entry->count) free(entry->equivs);
244 cache->cache = realloc(cache->cache,
245 (cache->size + 1) * sizeof(*cache->cache));
246 entry = cache->cache + cache->size++;
247 entry->name = strdup(name);
252 if (delEntry) return 0;
254 while ((chptr = strtok(equivs, " ")) != NULL) {
256 if (chptr[0] == '\0') /* does strtok() return "" ever?? */
259 entry->equivs = realloc(entry->equivs, sizeof(*entry->equivs)
260 * (entry->count + 1));
262 entry->equivs = malloc(sizeof(*entry->equivs));
264 entry->equivs[entry->count] = strdup(chptr);
271 static struct machEquivInfo * machEquivSearch(
272 struct machEquivTable * table, char * name)
277 * XXX The strcasecmp below is necessary so the old (rpm < 2.90) style
278 * XXX os-from-uname (e.g. "Linux") is compatible with the new
279 * XXX os-from-platform (e.g "linux" from "sparc-*-linux").
280 * XXX A copy of this string is embedded in headers and is
281 * XXX used by rpmInstallPackage->{os,arch}Okay->rpmMachineScore->.
282 * XXX to verify correct arch/os from headers.
284 for (i = 0; i < table->count; i++)
285 if (!strcasecmp(table->list[i].name, name))
286 return table->list + i;
291 static void machAddEquiv(struct machEquivTable * table, char * name,
294 struct machEquivInfo * equiv;
296 equiv = machEquivSearch(table, name);
299 table->list = realloc(table->list, (table->count + 1)
300 * sizeof(*table->list));
302 table->list = malloc(sizeof(*table->list));
304 table->list[table->count].name = strdup(name);
305 table->list[table->count++].score = distance;
309 static void machCacheEntryVisit(struct machCache * cache,
310 struct machEquivTable * table,
314 struct machCacheEntry * entry;
317 entry = machCacheFindEntry(cache, name);
318 if (!entry || entry->visited) return;
322 for (i = 0; i < entry->count; i++) {
323 machAddEquiv(table, entry->equivs[i], distance);
326 for (i = 0; i < entry->count; i++) {
327 machCacheEntryVisit(cache, table, entry->equivs[i], distance + 1);
331 static void machFindEquivs(struct machCache * cache,
332 struct machEquivTable * table,
337 for (i = 0; i < cache->size; i++)
338 cache->cache[i].visited = 0;
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. */
345 machAddEquiv(table, key, 1);
346 machCacheEntryVisit(cache, table, key, 2);
349 static int addCanon(struct canonEntry **table, int *tableLen, char *line,
350 const char *fn, int lineNum)
352 struct canonEntry *t;
357 *table = malloc(2 * sizeof(struct canonEntry));
360 *table = realloc(*table, sizeof(struct canonEntry) * (*tableLen));
362 t = & ((*table)[*tableLen - 2]);
364 t->name = strtok(line, ": \t");
365 t->short_name = strtok(NULL, " \t");
366 s = strtok(NULL, " \t");
367 if (! (t->name && t->short_name && s)) {
368 rpmError(RPMERR_RPMRC, _("Incomplete data line at %s:%d"), fn, lineNum);
371 if (strtok(NULL, " \t")) {
372 rpmError(RPMERR_RPMRC, _("Too many args in data line at %s:%d"),
377 t->num = strtoul(s, &s1, 10);
378 if ((*s1) || (s1 == s) || (t->num == ULONG_MAX)) {
379 rpmError(RPMERR_RPMRC, _("Bad arch/os number: %s (%s:%d)"), s,
381 return(RPMERR_RPMRC);
384 t->name = strdup(t->name);
385 t->short_name = strdup(t->short_name);
387 /* From A B C entry */
388 /* Add B B C entry */
389 t[1].name = strdup(t->short_name);
390 t[1].short_name = strdup(t->short_name);
396 static int addDefault(struct defaultEntry **table, int *tableLen, char *line,
397 const char *fn, int lineNum)
399 struct defaultEntry *t;
403 *table = malloc(sizeof(struct defaultEntry));
406 *table = realloc(*table, sizeof(struct defaultEntry) * (*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 rpmError(RPMERR_RPMRC, _("Incomplete default line at %s:%d"),
417 if (strtok(NULL, " \t")) {
418 rpmError(RPMERR_RPMRC, _("Too many args in default line at %s:%d"),
423 t->name = strdup(t->name);
424 t->defName = strdup(t->defName);
429 static struct canonEntry *lookupInCanonTable(char *name,
430 struct canonEntry *table,
434 if (!strcmp(name, table[tableLen].name)) {
435 return &(table[tableLen]);
442 static const char *lookupInDefaultTable(const char *name, struct defaultEntry *table,
446 if (!strcmp(name, table[tableLen].name)) {
447 return table[tableLen].defName;
454 int rpmReadConfigFiles(const char * file, const char * target)
457 rpmSetMachine(NULL, NULL);
459 if (target == NULL) {
460 rpmRebuildTargetVars(&target);
462 addMacro(&globalMacroContext, "_target", NULL, target, RMIL_RPMRC);
465 if (rpmReadRC(file)) return -1;
467 rpmRebuildTargetVars(&target);
469 { const char *cpu = getMacroBody(&globalMacroContext, "_target_cpu");
470 const char *os = getMacroBody(&globalMacroContext, "_target_os");
471 rpmSetMachine(cpu, os);
477 static void setVarDefault(int var, const char *macroname, const char *val, const char *body)
479 if (rpmGetVar(var)) return;
483 addMacro(&globalMacroContext, macroname, NULL, body, RMIL_DEFAULT);
486 static void setPathDefault(int var, const char *macroname, const char *subdir)
491 if (rpmGetVar(var)) return;
493 topdir = rpmGetVar(RPMVAR_TOPDIR);
494 if (topdir == NULL) topdir = rpmGetVar(RPMVAR_TMPPATH);
496 fn = alloca(strlen(topdir) + strlen(subdir) + 2);
498 if (fn[strlen(topdir) - 1] != '/')
504 if (macroname != NULL) {
505 #define _TOPDIRMACRO "%{_topdir}/"
506 char *body = alloca(sizeof(_TOPDIRMACRO) + strlen(subdir));
507 strcpy(body, _TOPDIRMACRO);
508 strcat(body, subdir);
509 addMacro(&globalMacroContext, macroname, NULL, body, RMIL_DEFAULT);
514 static const char *prescriptenviron = "\n\
515 RPM_SOURCE_DIR=\"%{_sourcedir}\"\n\
516 RPM_BUILD_DIR=\"%{_builddir}\"\n\
517 RPM_OPT_FLAGS=\"%{optflags}\"\n\
518 RPM_ARCH=\"%{_target_cpu}\"\n\
519 RPM_OS=\"%{_target_os}\"\n\
520 export RPM_SOURCE_DIR RPM_BUILD_DIR RPM_OPT_FLAGS RPM_ARCH RPM_OS\n\
521 RPM_DOC_DIR=\"%{_docdir}\"\n\
523 RPM_PACKAGE_NAME=\"%{name}\"\n\
524 RPM_PACKAGE_VERSION=\"%{version}\"\n\
525 RPM_PACKAGE_RELEASE=\"%{release}\"\n\
526 export RPM_PACKAGE_NAME RPM_PACKAGE_VERSION RPM_PACKAGE_RELEASE\n\
527 %{?buildroot:RPM_BUILD_ROOT=\"%{buildroot}\"\n\
528 export RPM_BUILD_ROOT\n}\
531 static void setDefaults(void) {
533 initMacros(&globalMacroContext, NULL); /* XXX initialize data structures */
534 addMacro(&globalMacroContext, "_usr", NULL, "/usr", RMIL_DEFAULT);
535 addMacro(&globalMacroContext, "_var", NULL, "/var", RMIL_DEFAULT);
537 addMacro(&globalMacroContext, "_preScriptEnvironment", NULL,
538 prescriptenviron, RMIL_DEFAULT);
540 setVarDefault(RPMVAR_MACROFILES, "_macrofiles",
541 "/usr/lib/rpm/macros", "%{_usr}/lib/rpm/macros");
542 setVarDefault(RPMVAR_TOPDIR, "_topdir",
543 "/usr/src/redhat", "%{_usr}/src/redhat");
544 setVarDefault(RPMVAR_TMPPATH, "_tmppath",
545 "/var/tmp", "%{_var}/tmp");
546 setVarDefault(RPMVAR_DBPATH, "_dbpath",
547 "/var/lib/rpm", "%{_var}/lib/rpm");
548 setVarDefault(RPMVAR_DEFAULTDOCDIR, "_defaultdocdir",
549 "/usr/doc", "%{_usr}/doc");
551 setVarDefault(RPMVAR_OPTFLAGS, "optflags", "-O2", NULL);
552 setVarDefault(RPMVAR_SIGTYPE, "sigtype", "none", NULL);
553 setVarDefault(RPMVAR_BUILDSHELL, "buildshell", "/bin/sh", NULL);
555 setPathDefault(RPMVAR_BUILDDIR, "_builddir", "BUILD");
556 setPathDefault(RPMVAR_RPMDIR, "_rpmdir", "RPMS");
557 setPathDefault(RPMVAR_SRPMDIR, "_srcrpmdir", "SRPMS");
558 setPathDefault(RPMVAR_SOURCEDIR, "_sourcedir", "SOURCES");
559 setPathDefault(RPMVAR_SPECDIR, "_specdir", "SPECS");
563 int rpmReadRC(const char * rcfiles)
565 char *myrcfiles, *r, *re;
567 static int first = 1;
575 rcfiles = defrcfiles;
577 /* Read each file in rcfiles. */
579 for (r = myrcfiles = strdup(rcfiles); *r != '\0'; r = re) {
580 char fn[FILENAME_MAX+1];
583 /* Get pointer to rest of files */
584 if ((re = strchr(r, ':')) != NULL)
589 /* Expand ~/ to $HOME/ */
591 if (r[0] == '~' && r[1] == '/') {
592 char *home = getenv("HOME");
594 rpmError(RPMERR_RPMRC, _("Cannot expand %s"), r);
603 /* Read another rcfile */
604 fd = fdOpen(fn, O_RDONLY, 0);
605 if (fdFileno(fd) < 0) {
606 /* XXX Only /usr/lib/rpm/rpmrc must exist in default rcfiles list */
607 if (rcfiles == defrcfiles && myrcfiles != r)
609 rpmError(RPMERR_RPMRC, _("Unable to open %s for reading: %s."),
610 fn, strerror(errno));
614 rc = doReadRC(fd, fn);
618 if (myrcfiles) free(myrcfiles);
622 rpmSetMachine(NULL, NULL); /* XXX WTFO? Why bother? */
624 if ((r = rpmGetVar(RPMVAR_MACROFILES)) != NULL)
625 initMacros(&globalMacroContext, r);
630 static int doReadRC(FD_t fd, const char * filename) {
632 char * start, * chptr, * next, * rest;
634 struct rpmOption searchOption, * option;
640 fstat(fdFileno(fd), &sb);
641 next = alloca(sb.st_size + 2);
642 if (fdRead(fd, next, sb.st_size) != sb.st_size) {
643 rpmError(RPMERR_RPMRC, _("Failed to read %s: %s."), filename,
647 next[sb.st_size] = '\n';
648 next[sb.st_size + 1] = '\0';
654 chptr = start = next;
655 while (*chptr != '\n') chptr++;
660 while (isspace(*start)) start++;
662 /* we used to allow comments to begin anywhere, but not anymore */
663 if (*start == '#' || !*start) continue;
666 while (!isspace(*chptr) && *chptr != ':' && *chptr) chptr++;
668 if (isspace(*chptr)) {
670 while (isspace(*chptr) && *chptr != ':' && *chptr) chptr++;
674 rpmError(RPMERR_RPMRC, _("missing ':' at %s:%d"),
681 searchOption.name = start;
682 option = bsearch(&searchOption, optionTable, optionTableSize,
683 sizeof(struct rpmOption), optionCompare);
687 while (isspace(*start) && *start) start++;
690 rpmError(RPMERR_RPMRC, _("missing argument for %s at %s:%d"),
691 option->name, filename, linenum);
695 switch (option->var) {
700 rpmRebuildTargetVars(NULL);
703 if (expandMacros(NULL, &globalMacroContext, buf, sizeof(buf))) {
704 rpmError(RPMERR_RPMRC, _("expansion failed at %s:d \"%s\""),
705 filename, linenum, start);
709 if (fdFileno(fdinc = fdOpen(buf, O_RDONLY, 0)) < 0) {
710 rpmError(RPMERR_RPMRC, _("cannot open %s at %s:%d"),
711 buf, filename, linenum);
714 rc = doReadRC(fdinc, buf);
723 if (option->archSpecific) {
724 while (!isspace(*chptr) && *chptr) chptr++;
727 rpmError(RPMERR_RPMRC,
728 _("missing architecture for %s at %s:%d"),
729 option->name, filename, linenum);
735 while (isspace(*chptr) && *chptr) chptr++;
737 rpmError(RPMERR_RPMRC,
738 _("missing argument for %s at %s:%d"),
739 option->name, filename, linenum);
742 if (option->macroize && !strcmp(start, current[ARCH])) {
744 if (option->localize)
746 strcpy(s, option->name);
747 addMacro(&globalMacroContext, buf, NULL, chptr, RMIL_RPMRC);
750 start = NULL; /* no arch */
751 /* XXX for now only non-arch values can get macroized */
752 if (option->macroize) {
754 if (option->localize)
756 strcpy(s, option->name);
757 addMacro(&globalMacroContext, buf, NULL, chptr, RMIL_RPMRC);
760 rpmSetVarArch(option->var, chptr, start);
764 for (i = 0; i < RPM_MACHTABLE_COUNT; i++) {
765 if (!strncmp(tables[i].key, start, strlen(tables[i].key)))
769 if (i < RPM_MACHTABLE_COUNT) {
770 rest = start + strlen(tables[i].key);
771 if (*rest == '_') rest++;
773 if (!strcmp(rest, "compat")) {
774 if (machCompatCacheAdd(chptr, filename, linenum,
778 } else if (tables[i].hasTranslate &&
779 !strcmp(rest, "translate")) {
780 if (addDefault(&tables[i].defaults,
781 &tables[i].defaultsLength,
782 chptr, filename, linenum))
785 } else if (tables[i].hasCanon &&
786 !strcmp(rest, "canon")) {
787 if (addCanon(&tables[i].canons, &tables[i].canonsLength,
788 chptr, filename, linenum))
795 rpmError(RPMERR_RPMRC, _("bad option '%s' at %s:%d"),
796 start, filename, linenum);
804 static void defaultMachine(char ** arch, char ** os) {
805 static struct utsname un;
806 static int gotDefaults = 0;
808 struct canonEntry * canon;
813 #if !defined(__linux__)
815 /* USUALLY un.sysname on sinix does start with the word "SINIX"
816 * let's be absolutely sure
818 sprintf(un.sysname,"SINIX");
820 if (!strcmp(un.sysname, "AIX")) {
821 strcpy(un.machine, __power_pc() ? "ppc" : "rs6000");
822 sprintf(un.sysname,"aix%s.%s",un.version,un.release);
824 else if (!strcmp(un.sysname, "SunOS")) {
825 if (!strncmp(un.release,"4", 1)) /* SunOS 4.x */ {
827 for (fd=0;(un.release[fd] != 0 && (fd < sizeof(un.release)));fd++)
828 if (!isdigit(un.release[fd]) && (un.release[fd] != '.')) {
832 sprintf(un.sysname,"sunos%s",un.release);
835 else /* Solaris 2.x: n.x.x becomes n-3.x.x */
836 sprintf(un.sysname,"solaris%1d%s",atoi(un.release)-3,un.release+1+(atoi(un.release)/10));
838 else if (!strcmp(un.sysname, "HP-UX"))
839 /*make un.sysname look like hpux9.05 for example*/
840 sprintf(un.sysname,"hpux%s",strpbrk(un.release,"123456789"));
841 else if (!strcmp(un.sysname, "OSF1"))
842 /*make un.sysname look like osf3.2 for example*/
843 sprintf(un.sysname,"osf%s",strpbrk(un.release,"123456789"));
844 else if (!strncmp(un.sysname, "IP", 2))
845 un.sysname[2] = '\0';
846 else if (!strncmp(un.sysname, "SINIX", 5)) {
847 sprintf(un.sysname, "sinix%s",un.release);
848 if (!strncmp(un.machine, "RM", 2))
849 sprintf(un.machine, "mips");
851 else if ((!strncmp(un.machine, "34", 2) || \
852 !strncmp(un.machine, "33", 2)) && \
853 !strncmp(un.release, "4.0", 3)) {
854 /* we are on ncr-sysv4 */
856 FD_t fd = fdOpen("/etc/.relid", O_RDONLY, 0700);
857 if (fdFileno(fd) > 0) {
858 chptr = (char *) calloc(256,1);
860 int irelid = read(fd, (void *)chptr, 256);
862 /* example: "112393 RELEASE 020200 Version 01 OS" */
864 if ((prelid=strstr(chptr, "RELEASE "))){
865 prelid += strlen("RELEASE ")+1;
866 sprintf(un.sysname,"ncr-sysv4.%.*s",1,prelid);
873 /* parsing /etc/.relid file failed */
874 strcpy(un.sysname,"ncr-sysv4");
875 /* wrong, just for now, find out how to look for i586 later*/
876 strcpy(un.machine,"i486");
878 #endif /* __linux__ */
880 /* get rid of the hyphens in the sysname */
881 for (chptr = un.machine; *chptr; chptr++)
882 if (*chptr == '/') *chptr = '-';
884 # if defined(__MIPSEL__) || defined(__MIPSEL) || defined(_MIPSEL)
886 strcpy(un.machine, "mipsel");
887 # elif defined(__MIPSEB__) || defined(__MIPSEB) || defined(_MIPSEB)
889 strcpy(un.machine, "mipseb");
892 # if defined(__hpux) && defined(_SC_CPU_VERSION)
894 # if !defined(CPU_PA_RISC1_2)
895 # define CPU_PA_RISC1_2 0x211 /* HP PA-RISC1.2 */
897 # if !defined(CPU_PA_RISC2_0)
898 # define CPU_PA_RISC2_0 0x214 /* HP PA-RISC2.0 */
900 int cpu_version = sysconf(_SC_CPU_VERSION);
902 # if defined(CPU_HP_MC68020)
903 if (cpu_version == CPU_HP_MC68020)
904 strcpy(un.machine, "m68k");
906 # if defined(CPU_HP_MC68030)
907 if (cpu_version == CPU_HP_MC68030)
908 strcpy(un.machine, "m68k");
910 # if defined(CPU_HP_MC68040)
911 if (cpu_version == CPU_HP_MC68040)
912 strcpy(un.machine, "m68k");
915 # if defined(CPU_PA_RISC1_0)
916 if (cpu_version == CPU_PA_RISC1_0)
917 strcpy(un.machine, "hppa1.0");
919 # if defined(CPU_PA_RISC1_1)
920 if (cpu_version == CPU_PA_RISC1_1)
921 strcpy(un.machine, "hppa1.1");
923 # if defined(CPU_PA_RISC1_2)
924 if (cpu_version == CPU_PA_RISC1_2)
925 strcpy(un.machine, "hppa1.2");
927 # if defined(CPU_PA_RISC2_0)
928 if (cpu_version == CPU_PA_RISC2_0)
929 strcpy(un.machine, "hppa2.0");
934 /* the uname() result goes through the arch_canon table */
935 canon = lookupInCanonTable(un.machine,
936 tables[RPM_MACHTABLE_INSTARCH].canons,
937 tables[RPM_MACHTABLE_INSTARCH].canonsLength);
939 strcpy(un.machine, canon->short_name);
941 canon = lookupInCanonTable(un.sysname,
942 tables[RPM_MACHTABLE_INSTOS].canons,
943 tables[RPM_MACHTABLE_INSTOS].canonsLength);
945 strcpy(un.sysname, canon->short_name);
949 if (arch) *arch = un.machine;
950 if (os) *os = un.sysname;
953 static char * rpmGetVarArch(int var, char * arch) {
954 struct rpmvarValue * next;
956 if (!arch) arch = current[ARCH];
961 if (next->arch && !strcmp(next->arch, arch)) return next->value;
967 while (next && next->arch) next = next->next;
969 return next ? next->value : NULL;
972 char *rpmGetVar(int var)
974 return rpmGetVarArch(var, NULL);
977 int rpmGetBooleanVar(int var) {
982 val = rpmGetVar(var);
985 if (val[0] == 'y' || val[0] == 'Y') return 1;
987 num = strtol(val, &chptr, 0);
988 if (chptr && *chptr == '\0') {
995 void rpmSetVar(int var, const char *val) {
996 freeRpmVar(&values[var]);
998 values[var].arch = NULL;
999 values[var].next = NULL;
1002 values[var].value = strdup(val);
1004 values[var].value = NULL;
1007 /* this doesn't free the passed pointer! */
1008 static void freeRpmVar(struct rpmvarValue * orig) {
1009 struct rpmvarValue * next, * var = orig;
1013 if (var->arch) free(var->arch);
1014 if (var->value) free(var->value);
1016 if (var != orig) free(var);
1021 static void rpmSetVarArch(int var, char * val, char * arch) {
1022 struct rpmvarValue * next = values + var;
1026 while (next->next) {
1027 if (next->arch && !strcmp(next->arch, arch)) break;
1031 while (next->next) {
1032 if (!next->arch) break;
1037 if (next->arch && arch && !strcmp(next->arch, arch)) {
1038 if (next->value) free(next->value);
1039 if (next->arch) free(next->arch);
1040 } else if (next->arch || arch) {
1041 next->next = malloc(sizeof(*next->next));
1047 next->value = strdup(val);
1049 next->arch = strdup(arch);
1054 void rpmSetTables(int archTable, int osTable) {
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, char * name) {
1071 struct machEquivInfo * info = machEquivSearch(&tables[type].equiv, name);
1072 return (info != NULL ? info->score : 0);
1075 void rpmGetMachine(char **arch, char **os)
1078 *arch = current[ARCH];
1084 void rpmSetMachine(const char * arch, const char * os) {
1085 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] = strdup(arch);
1108 rebuildCompatTables(ARCH, host_cpu);
1111 if (!current[OS] || strcmp(os, current[OS])) {
1112 if (current[OS]) free(current[OS]);
1113 current[OS] = strdup(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, char * name) {
1129 machFindEquivs(&tables[currTables[type]].cache,
1130 &tables[currTables[type]].equiv,
1134 static void getMachineInfo(int type, char ** name, int * num) {
1135 struct canonEntry * canon;
1136 int which = currTables[type];
1138 /* use the normal canon tables, even if we're looking up build stuff */
1139 if (which >= 2) which -= 2;
1141 canon = lookupInCanonTable(current[type],
1142 tables[which].canons,
1143 tables[which].canonsLength);
1146 if (num) *num = canon->num;
1147 if (name) *name = canon->short_name;
1149 if (num) *num = 255;
1150 if (name) *name = current[type];
1152 if (tables[currTables[type]].hasCanon) {
1153 rpmMessage(RPMMESS_WARNING, _("Unknown system: %s\n"), current[type]);
1154 rpmMessage(RPMMESS_WARNING, _("Please contact rpm-list@redhat.com\n"));
1159 void rpmGetArchInfo(char ** name, int * num) {
1160 getMachineInfo(ARCH, name, num);
1163 void rpmGetOsInfo(char ** name, int * num) {
1164 getMachineInfo(OS, name, num);
1167 void rpmRebuildTargetVars(const char ** canontarget)
1170 char * ca = NULL, * co = NULL;
1171 const char * target = NULL;
1175 * XXX getMacroBody() may be nuked -- I originally added it for tdyas and it's
1176 * kinda half-baked (remember, each macro is actually a stack so it's not
1177 * clear which body is intended).
1179 * You can, however, always do
1181 * strcpy(buf, "%_target")
1182 * expandMacros(NULL, &globalMacroContext, buf, sizeof(buf)))
1183 * target = strdup(buf);
1186 if ((target = getMacroBody(&globalMacroContext, "_target")) != NULL)
1187 target = strdup(target);
1189 /* Rebuild the compat table to recalculate the current target arch. */
1191 rpmSetMachine(NULL, NULL);
1192 rpmSetTables(RPM_MACHTABLE_INSTARCH, RPM_MACHTABLE_INSTOS);
1193 rpmSetTables(RPM_MACHTABLE_BUILDARCH, RPM_MACHTABLE_BUILDOS);
1195 rpmGetArchInfo(&ca,NULL);
1196 rpmGetOsInfo(&co,NULL);
1198 if (ca == NULL) defaultMachine(&ca, NULL);
1199 if (co == NULL) defaultMachine(NULL, &co);
1201 for (x = 0; ca[x]; x++)
1202 ca[x] = tolower(ca[x]);
1203 for (x = 0; co[x]; x++)
1204 co[x] = tolower(co[x]);
1206 if (target == NULL) {
1207 char *ct = malloc(strlen(co)+strlen(ca)+2);
1208 sprintf(ct, "%s-%s", ca, co);
1213 * XXX All this macro pokery/jiggery could be achieved (I think)
1214 * by doing a delayed
1215 * initMacros(&globalMacroContext, PER-PLATFORM-MACRO-FILE-NAMES);
1216 * (I haven't looked at the code :-)
1218 * In fact, if you want to get really sophisticated, you could encapsulate
1219 * within per-platform MacroContexts (but I'm not quite ready for that yet).
1221 delMacro(&globalMacroContext, "_target");
1222 addMacro(&globalMacroContext, "_target", NULL, target, RMIL_RPMRC);
1223 delMacro(&globalMacroContext, "_target_cpu");
1224 addMacro(&globalMacroContext, "_target_cpu", NULL, ca, RMIL_RPMRC);
1225 delMacro(&globalMacroContext, "_target_os");
1226 addMacro(&globalMacroContext, "_target_os", NULL, co, RMIL_RPMRC);
1229 *canontarget = target;
1232 int rpmShowRC(FILE *f)
1234 struct rpmOption *opt;
1236 struct machEquivTable * equivTable;
1238 /* the caller may set the build arch which should be printed here */
1239 fprintf(f, "ARCHITECTURE AND OS:\n");
1240 fprintf(f, "build arch : %s\n", current[ARCH]);
1242 fprintf(f, "compatible build archs:");
1243 equivTable = &tables[RPM_MACHTABLE_BUILDARCH].equiv;
1244 for (i = 0; i < equivTable->count; i++)
1245 fprintf(f," %s", equivTable->list[i].name);
1248 fprintf(f, "build os : %s\n", current[OS]);
1250 fprintf(f, "compatible build os's :");
1251 equivTable = &tables[RPM_MACHTABLE_BUILDOS].equiv;
1252 for (i = 0; i < equivTable->count; i++)
1253 fprintf(f," %s", equivTable->list[i].name);
1256 rpmSetTables(RPM_MACHTABLE_INSTARCH, RPM_MACHTABLE_INSTOS);
1257 rpmSetMachine(NULL, NULL); /* XXX WTFO? Why bother? */
1259 fprintf(f, "install arch : %s\n", current[ARCH]);
1260 fprintf(f, "install os : %s\n", current[OS]);
1262 fprintf(f, "compatible archs :");
1263 equivTable = &tables[RPM_MACHTABLE_INSTARCH].equiv;
1264 for (i = 0; i < equivTable->count; i++)
1265 fprintf(f," %s", equivTable->list[i].name);
1268 fprintf(f, "compatible os's :");
1269 equivTable = &tables[RPM_MACHTABLE_INSTOS].equiv;
1270 for (i = 0; i < equivTable->count; i++)
1271 fprintf(f," %s", equivTable->list[i].name);
1274 fprintf(f, "\nRPMRC VALUES:\n");
1275 for (i = 0, opt = optionTable; i < optionTableSize; i++, opt++) {
1276 char *s = rpmGetVar(opt->var);
1277 if (s != NULL || rpmGetVerbosity() < RPMMESS_NORMAL)
1278 fprintf(f, "%-21s : %s\n", opt->name, s ? s : "(not set)");
1281 dumpMacroTable(&globalMacroContext);