lib/rpmrc.c

Go to the documentation of this file.
00001 /*@-bounds@*/
00002 #include "system.h"
00003 
00004 #include <stdarg.h>
00005 #if defined(__linux__) && defined(__powerpc__)
00006 #include <setjmp.h>
00007 #endif
00008 
00009 #include <ctype.h>      /* XXX for /etc/rpm/platform contents */
00010 
00011 #if HAVE_SYS_SYSTEMCFG_H
00012 #include <sys/systemcfg.h>
00013 #else
00014 #define __power_pc() 0
00015 #endif
00016 
00017 #include <rpmlib.h>
00018 #include <rpmmacro.h>
00019 #include <rpmlua.h>
00020 
00021 #include "misc.h"
00022 #include "debug.h"
00023 
00024 /*@observer@*/ /*@unchecked@*/
00025 static const char *defrcfiles = LIBRPMRC_FILENAME ":" VENDORRPMRC_FILENAME ":/etc/rpmrc:~/.rpmrc"; 
00026 
00027 /*@observer@*/ /*@checked@*/
00028 const char * macrofiles = MACROFILES;
00029 
00030 /*@observer@*/ /*@unchecked@*/
00031 static const char * platform = "/etc/rpm/platform";
00032 /*@only@*/ /*@relnull@*/ /*@unchecked@*/
00033 static const char ** platpat = NULL;
00034 /*@unchecked@*/
00035 static int nplatpat = 0;
00036 
00037 typedef /*@owned@*/ const char * cptr_t;
00038 
00039 typedef struct machCacheEntry_s {
00040     const char * name;
00041     int count;
00042     cptr_t * equivs;
00043     int visited;
00044 } * machCacheEntry;
00045 
00046 typedef struct machCache_s {
00047     machCacheEntry cache;
00048     int size;
00049 } * machCache;
00050 
00051 typedef struct machEquivInfo_s {
00052     const char * name;
00053     int score;
00054 } * machEquivInfo;
00055 
00056 typedef struct machEquivTable_s {
00057     int count;
00058     machEquivInfo list;
00059 } * machEquivTable;
00060 
00061 struct rpmvarValue {
00062     const char * value;
00063     /* eventually, this arch will be replaced with a generic condition */
00064     const char * arch;
00065 /*@only@*/ /*@null@*/ struct rpmvarValue * next;
00066 };
00067 
00068 struct rpmOption {
00069     const char * name;
00070     int var;
00071     int archSpecific;
00072 /*@unused@*/ int required;
00073     int macroize;
00074     int localize;
00075 /*@unused@*/ struct rpmOptionValue * value;
00076 };
00077 
00078 typedef struct defaultEntry_s {
00079 /*@owned@*/ /*@null@*/ const char * name;
00080 /*@owned@*/ /*@null@*/ const char * defName;
00081 } * defaultEntry;
00082 
00083 typedef struct canonEntry_s {
00084 /*@owned@*/ const char * name;
00085 /*@owned@*/ const char * short_name;
00086     short num;
00087 } * canonEntry;
00088 
00089 /* tags are 'key'canon, 'key'translate, 'key'compat
00090  *
00091  * for giggles, 'key'_canon, 'key'_compat, and 'key'_canon will also work
00092  */
00093 typedef struct tableType_s {
00094 /*@observer@*/ const char * const key;
00095     const int hasCanon;
00096     const int hasTranslate;
00097     struct machEquivTable_s equiv;
00098     struct machCache_s cache;
00099     defaultEntry defaults;
00100     canonEntry canons;
00101     int defaultsLength;
00102     int canonsLength;
00103 } * tableType;
00104 
00105 /*@-fullinitblock@*/
00106 /*@unchecked@*/
00107 static struct tableType_s tables[RPM_MACHTABLE_COUNT] = {
00108     { "arch", 1, 0 },
00109     { "os", 1, 0 },
00110     { "buildarch", 0, 1 },
00111     { "buildos", 0, 1 }
00112 };
00113 
00114 /* this *must* be kept in alphabetical order */
00115 /* The order of the flags is archSpecific, required, macroize, localize */
00116 
00117 /*@unchecked@*/
00118 static struct rpmOption optionTable[] = {
00119     { "include",                RPMVAR_INCLUDE,                 0, 1,   0, 2 },
00120     { "macrofiles",             RPMVAR_MACROFILES,              0, 0,   0, 1 },
00121     { "optflags",               RPMVAR_OPTFLAGS,                1, 0,   1, 0 },
00122     { "provides",               RPMVAR_PROVIDES,                0, 0,   0, 0 },
00123 };
00124 /*@=fullinitblock@*/
00125 
00126 /*@unchecked@*/
00127 static int optionTableSize = sizeof(optionTable) / sizeof(*optionTable);
00128 
00129 #define OS      0
00130 #define ARCH    1
00131 
00132 /*@unchecked@*/
00133 static cptr_t current[2];
00134 
00135 /*@unchecked@*/
00136 static int currTables[2] = { RPM_MACHTABLE_INSTOS, RPM_MACHTABLE_INSTARCH };
00137 
00138 /*@unchecked@*/
00139 static struct rpmvarValue values[RPMVAR_NUM];
00140 
00141 /*@unchecked@*/
00142 static int defaultsInitialized = 0;
00143 
00144 /* prototypes */
00145 static int doReadRC( /*@killref@*/ FD_t fd, const char * urlfn)
00146         /*@globals rpmGlobalMacroContext, h_errno, fileSystem, internalState @*/
00147         /*@modifies fd, rpmGlobalMacroContext, fileSystem, internalState @*/;
00148 
00149 static void rpmSetVarArch(int var, const char * val,
00150                 /*@null@*/ const char * arch)
00151         /*@globals values, internalState @*/
00152         /*@modifies values, internalState @*/;
00153 
00154 static void rebuildCompatTables(int type, const char * name)
00155         /*@globals internalState @*/
00156         /*@modifies internalState @*/;
00157 
00158 static void rpmRebuildTargetVars(/*@null@*/ const char **target, /*@null@*/ const char ** canontarget)
00159         /*@globals rpmGlobalMacroContext, h_errno, fileSystem, internalState @*/
00160         /*@modifies *canontarget, rpmGlobalMacroContext,
00161                 fileSystem, internalState @*/;
00162 
00163 static int optionCompare(const void * a, const void * b)
00164         /*@*/
00165 {
00166     return xstrcasecmp(((struct rpmOption *) a)->name,
00167                       ((struct rpmOption *) b)->name);
00168 }
00169 
00170 static /*@observer@*/ /*@null@*/ machCacheEntry
00171 machCacheFindEntry(const machCache cache, const char * key)
00172         /*@*/
00173 {
00174     int i;
00175 
00176     for (i = 0; i < cache->size; i++)
00177         if (!strcmp(cache->cache[i].name, key)) return cache->cache + i;
00178 
00179     return NULL;
00180 }
00181 
00182 static int machCompatCacheAdd(char * name, const char * fn, int linenum,
00183                                 machCache cache)
00184         /*@globals internalState @*/
00185         /*@modifies *name, cache->cache, cache->size, internalState @*/
00186 {
00187     machCacheEntry entry = NULL;
00188     char * chptr;
00189     char * equivs;
00190     int delEntry = 0;
00191     int i;
00192 
00193     while (*name && xisspace(*name)) name++;
00194 
00195     chptr = name;
00196     while (*chptr && *chptr != ':') chptr++;
00197     if (!*chptr) {
00198         rpmError(RPMERR_RPMRC, _("missing second ':' at %s:%d\n"), fn, linenum);
00199         return 1;
00200     } else if (chptr == name) {
00201         rpmError(RPMERR_RPMRC, _("missing architecture name at %s:%d\n"), fn,
00202                              linenum);
00203         return 1;
00204     }
00205 
00206     while (*chptr == ':' || xisspace(*chptr)) chptr--;
00207     *(++chptr) = '\0';
00208     equivs = chptr + 1;
00209     while (*equivs && xisspace(*equivs)) equivs++;
00210     if (!*equivs) {
00211         delEntry = 1;
00212     }
00213 
00214     if (cache->size) {
00215         entry = machCacheFindEntry(cache, name);
00216         if (entry) {
00217             for (i = 0; i < entry->count; i++)
00218                 entry->equivs[i] = _free(entry->equivs[i]);
00219             entry->equivs = _free(entry->equivs);
00220             entry->count = 0;
00221         }
00222     }
00223 
00224     if (!entry) {
00225         cache->cache = xrealloc(cache->cache,
00226                                (cache->size + 1) * sizeof(*cache->cache));
00227         entry = cache->cache + cache->size++;
00228         entry->name = xstrdup(name);
00229         entry->count = 0;
00230         entry->visited = 0;
00231     }
00232 
00233     if (delEntry) return 0;
00234 
00235     while ((chptr = strtok(equivs, " ")) != NULL) {
00236         equivs = NULL;
00237         if (chptr[0] == '\0')   /* does strtok() return "" ever?? */
00238             continue;
00239         if (entry->count)
00240             entry->equivs = xrealloc(entry->equivs, sizeof(*entry->equivs)
00241                                         * (entry->count + 1));
00242         else
00243             entry->equivs = xmalloc(sizeof(*entry->equivs));
00244 
00245         entry->equivs[entry->count] = xstrdup(chptr);
00246         entry->count++;
00247     }
00248 
00249     return 0;
00250 }
00251 
00252 static /*@observer@*/ /*@null@*/ machEquivInfo
00253 machEquivSearch(const machEquivTable table, const char * name)
00254         /*@*/
00255 {
00256     int i;
00257 
00258     for (i = 0; i < table->count; i++)
00259         if (!xstrcasecmp(table->list[i].name, name))
00260             return table->list + i;
00261 
00262     return NULL;
00263 }
00264 
00265 static void machAddEquiv(machEquivTable table, const char * name,
00266                            int distance)
00267         /*@modifies table->list, table->count @*/
00268 {
00269     machEquivInfo equiv;
00270 
00271     equiv = machEquivSearch(table, name);
00272     if (!equiv) {
00273         if (table->count)
00274             table->list = xrealloc(table->list, (table->count + 1)
00275                                     * sizeof(*table->list));
00276         else
00277             table->list = xmalloc(sizeof(*table->list));
00278 
00279         table->list[table->count].name = xstrdup(name);
00280         table->list[table->count++].score = distance;
00281     }
00282 }
00283 
00284 static void machCacheEntryVisit(machCache cache,
00285                 machEquivTable table, const char * name, int distance)
00286         /*@modifies table->list, table->count @*/
00287 {
00288     machCacheEntry entry;
00289     int i;
00290 
00291     entry = machCacheFindEntry(cache, name);
00292     if (!entry || entry->visited) return;
00293 
00294     entry->visited = 1;
00295 
00296     for (i = 0; i < entry->count; i++) {
00297         machAddEquiv(table, entry->equivs[i], distance);
00298     }
00299 
00300     for (i = 0; i < entry->count; i++) {
00301         machCacheEntryVisit(cache, table, entry->equivs[i], distance + 1);
00302     }
00303 }
00304 
00305 static void machFindEquivs(machCache cache, machEquivTable table,
00306                 const char * key)
00307         /*@modifies cache->cache, table->list, table->count @*/
00308 {
00309     int i;
00310 
00311     for (i = 0; i < cache->size; i++)
00312         cache->cache[i].visited = 0;
00313 
00314     while (table->count > 0) {
00315         --table->count;
00316         table->list[table->count].name = _free(table->list[table->count].name);
00317     }
00318     table->count = 0;
00319     table->list = _free(table->list);
00320 
00321     /*
00322      *  We have a general graph built using strings instead of pointers.
00323      *  Yuck. We have to start at a point at traverse it, remembering how
00324      *  far away everything is.
00325      */
00326     /*@-nullstate@*/    /* FIX: table->list may be NULL. */
00327     machAddEquiv(table, key, 1);
00328     machCacheEntryVisit(cache, table, key, 2);
00329     return;
00330     /*@=nullstate@*/
00331 }
00332 
00333 static int addCanon(canonEntry * table, int * tableLen, char * line,
00334                     const char * fn, int lineNum)
00335         /*@globals internalState @*/
00336         /*@modifies *table, *tableLen, *line, internalState @*/
00337 {
00338     canonEntry t;
00339     char *s, *s1;
00340     const char * tname;
00341     const char * tshort_name;
00342     int tnum;
00343 
00344     (*tableLen) += 2;
00345     /*@-unqualifiedtrans@*/
00346     *table = xrealloc(*table, sizeof(**table) * (*tableLen));
00347     /*@=unqualifiedtrans@*/
00348 
00349     t = & ((*table)[*tableLen - 2]);
00350 
00351     tname = strtok(line, ": \t");
00352     tshort_name = strtok(NULL, " \t");
00353     s = strtok(NULL, " \t");
00354     if (! (tname && tshort_name && s)) {
00355         rpmError(RPMERR_RPMRC, _("Incomplete data line at %s:%d\n"),
00356                 fn, lineNum);
00357         return RPMERR_RPMRC;
00358     }
00359     if (strtok(NULL, " \t")) {
00360         rpmError(RPMERR_RPMRC, _("Too many args in data line at %s:%d\n"),
00361               fn, lineNum);
00362         return RPMERR_RPMRC;
00363     }
00364 
00365     /*@-nullpass@*/     /* LCL: s != NULL here. */
00366     tnum = strtoul(s, &s1, 10);
00367     if ((*s1) || (s1 == s) || (tnum == ULONG_MAX)) {
00368         rpmError(RPMERR_RPMRC, _("Bad arch/os number: %s (%s:%d)\n"), s,
00369               fn, lineNum);
00370         return(RPMERR_RPMRC);
00371     }
00372     /*@=nullpass@*/
00373 
00374     t[0].name = xstrdup(tname);
00375     t[0].short_name = (tshort_name ? xstrdup(tshort_name) : xstrdup(""));
00376     t[0].num = tnum;
00377 
00378     /* From A B C entry */
00379     /* Add  B B C entry */
00380     t[1].name = (tshort_name ? xstrdup(tshort_name) : xstrdup(""));
00381     t[1].short_name = (tshort_name ? xstrdup(tshort_name) : xstrdup(""));
00382     t[1].num = tnum;
00383 
00384     return 0;
00385 }
00386 
00387 static int addDefault(defaultEntry * table, int * tableLen, char * line,
00388                         const char * fn, int lineNum)
00389         /*@globals internalState @*/
00390         /*@modifies *table, *tableLen, *line, internalState @*/
00391 {
00392     defaultEntry t;
00393 
00394     (*tableLen)++;
00395     /*@-unqualifiedtrans@*/
00396     *table = xrealloc(*table, sizeof(**table) * (*tableLen));
00397     /*@=unqualifiedtrans@*/
00398 
00399     t = & ((*table)[*tableLen - 1]);
00400 
00401     /*@-temptrans@*/
00402     t->name = strtok(line, ": \t");
00403     t->defName = strtok(NULL, " \t");
00404     if (! (t->name && t->defName)) {
00405         rpmError(RPMERR_RPMRC, _("Incomplete default line at %s:%d\n"),
00406                  fn, lineNum);
00407         return RPMERR_RPMRC;
00408     }
00409     if (strtok(NULL, " \t")) {
00410         rpmError(RPMERR_RPMRC, _("Too many args in default line at %s:%d\n"),
00411               fn, lineNum);
00412         return RPMERR_RPMRC;
00413     }
00414 
00415     t->name = xstrdup(t->name);
00416     t->defName = (t->defName ? xstrdup(t->defName) : NULL);
00417     /*@=temptrans@*/
00418 
00419     return 0;
00420 }
00421 
00422 static /*@null@*/ canonEntry lookupInCanonTable(const char * name,
00423                 const canonEntry table, int tableLen)
00424         /*@*/
00425 {
00426     while (tableLen) {
00427         tableLen--;
00428         if (strcmp(name, table[tableLen].name))
00429             continue;
00430         /*@-immediatetrans -retalias@*/
00431         return &(table[tableLen]);
00432         /*@=immediatetrans =retalias@*/
00433     }
00434 
00435     return NULL;
00436 }
00437 
00438 static /*@observer@*/ /*@null@*/
00439 const char * lookupInDefaultTable(const char * name,
00440                 const defaultEntry table, int tableLen)
00441         /*@*/
00442 {
00443     while (tableLen) {
00444         tableLen--;
00445         if (table[tableLen].name && !strcmp(name, table[tableLen].name))
00446             return table[tableLen].defName;
00447     }
00448 
00449     return name;
00450 }
00451 
00452 static void setVarDefault(int var, const char * macroname, const char * val,
00453                 /*@null@*/ const char * body)
00454         /*@globals rpmGlobalMacroContext, internalState @*/
00455         /*@modifies rpmGlobalMacroContext, internalState @*/
00456 {
00457     if (var >= 0) {     /* XXX Dying ... */
00458         if (rpmGetVar(var)) return;
00459         rpmSetVar(var, val);
00460     }
00461     if (body == NULL)
00462         body = val;
00463     addMacro(NULL, macroname, NULL, body, RMIL_DEFAULT);
00464 }
00465 
00466 static void setPathDefault(int var, const char * macroname, const char * subdir)
00467         /*@globals rpmGlobalMacroContext, h_errno, internalState @*/
00468         /*@modifies rpmGlobalMacroContext, internalState @*/
00469 {
00470 
00471     if (var >= 0) {     /* XXX Dying ... */
00472         const char * topdir;
00473         char * fn;
00474 
00475         if (rpmGetVar(var)) return;
00476 
00477         topdir = rpmGetPath("%{_topdir}", NULL);
00478 
00479         fn = alloca(strlen(topdir) + strlen(subdir) + 2);
00480         strcpy(fn, topdir);
00481         if (fn[strlen(topdir) - 1] != '/')
00482             strcat(fn, "/");
00483         strcat(fn, subdir);
00484 
00485         rpmSetVar(var, fn);
00486         topdir = _free(topdir);
00487     }
00488 
00489     if (macroname != NULL) {
00490 #define _TOPDIRMACRO    "%{_topdir}/"
00491         char *body = alloca(sizeof(_TOPDIRMACRO) + strlen(subdir));
00492         strcpy(body, _TOPDIRMACRO);
00493         strcat(body, subdir);
00494         addMacro(NULL, macroname, NULL, body, RMIL_DEFAULT);
00495 #undef _TOPDIRMACRO
00496     }
00497 }
00498 
00499 /*@observer@*/ /*@unchecked@*/
00500 static const char * prescriptenviron = "\n\
00501 RPM_SOURCE_DIR=\"%{_sourcedir}\"\n\
00502 RPM_BUILD_DIR=\"%{_builddir}\"\n\
00503 RPM_OPT_FLAGS=\"%{optflags}\"\n\
00504 RPM_ARCH=\"%{_arch}\"\n\
00505 RPM_OS=\"%{_os}\"\n\
00506 export RPM_SOURCE_DIR RPM_BUILD_DIR RPM_OPT_FLAGS RPM_ARCH RPM_OS\n\
00507 RPM_DOC_DIR=\"%{_docdir}\"\n\
00508 export RPM_DOC_DIR\n\
00509 RPM_PACKAGE_NAME=\"%{name}\"\n\
00510 RPM_PACKAGE_VERSION=\"%{version}\"\n\
00511 RPM_PACKAGE_RELEASE=\"%{release}\"\n\
00512 export RPM_PACKAGE_NAME RPM_PACKAGE_VERSION RPM_PACKAGE_RELEASE\n\
00513 %{?buildroot:RPM_BUILD_ROOT=\"%{buildroot}\"\n\
00514 export RPM_BUILD_ROOT\n}\
00515 ";
00516 
00517 static void setDefaults(void)
00518         /*@globals rpmGlobalMacroContext, h_errno, internalState @*/
00519         /*@modifies rpmGlobalMacroContext, internalState @*/
00520 {
00521 
00522     addMacro(NULL, "_usr", NULL, "/usr", RMIL_DEFAULT);
00523     addMacro(NULL, "_var", NULL, "/var", RMIL_DEFAULT);
00524 
00525     addMacro(NULL, "_preScriptEnvironment",NULL, prescriptenviron,RMIL_DEFAULT);
00526 
00527     setVarDefault(-1,                   "_topdir",
00528                 "/usr/src/redhat",      "%{_usr}/src/redhat");
00529     setVarDefault(-1,                   "_tmppath",
00530                 "/var/tmp",             "%{_var}/tmp");
00531     setVarDefault(-1,                   "_dbpath",
00532                 "/var/lib/rpm",         "%{_var}/lib/rpm");
00533     setVarDefault(-1,                   "_defaultdocdir",
00534                 "/usr/doc",             "%{_usr}/doc");
00535 
00536     setVarDefault(-1,                   "_rpmfilename",
00537         "%%{ARCH}/%%{NAME}-%%{VERSION}-%%{RELEASE}.%%{ARCH}.rpm",NULL);
00538 
00539     setVarDefault(RPMVAR_OPTFLAGS,      "optflags",
00540                 "-O2",                  NULL);
00541     setVarDefault(-1,                   "sigtype",
00542                 "none",                 NULL);
00543     setVarDefault(-1,                   "_buildshell",
00544                 "/bin/sh",              NULL);
00545 
00546     setPathDefault(-1,                  "_builddir",    "BUILD");
00547     setPathDefault(-1,                  "_rpmdir",      "RPMS");
00548     setPathDefault(-1,                  "_srcrpmdir",   "SRPMS");
00549     setPathDefault(-1,                  "_sourcedir",   "SOURCES");
00550     setPathDefault(-1,                  "_specdir",     "SPECS");
00551 
00552 }
00553 
00554 /*@-usedef@*/   /*@ FIX: se usage inconsistent, W2DO? */
00555 static int doReadRC( /*@killref@*/ FD_t fd, const char * urlfn)
00556         /*@globals rpmGlobalMacroContext, h_errno, fileSystem, internalState @*/
00557         /*@modifies fd, rpmGlobalMacroContext, fileSystem, internalState @*/
00558 {
00559     const char *s;
00560     char *se, *next;
00561     int linenum = 0;
00562     struct rpmOption searchOption, * option;
00563     int rc;
00564 
00565     /* XXX really need rc = Slurp(fd, const char * filename, char ** buf) */
00566   { off_t size = fdSize(fd);
00567     size_t nb = (size >= 0 ? size : (8*BUFSIZ - 2));
00568     if (nb == 0) {
00569         (void) Fclose(fd);
00570         return 0;
00571     }
00572     next = alloca(nb + 2);
00573     next[0] = '\0';
00574     rc = Fread(next, sizeof(*next), nb, fd);
00575     if (Ferror(fd) || (size > 0 && rc != nb)) { /* XXX Feof(fd) */
00576         rpmError(RPMERR_RPMRC, _("Failed to read %s: %s.\n"), urlfn,
00577                  Fstrerror(fd));
00578         rc = 1;
00579     } else
00580         rc = 0;
00581     (void) Fclose(fd);
00582     if (rc) return rc;
00583     next[nb] = '\n';
00584     next[nb + 1] = '\0';
00585   }
00586 
00587     /*@-branchstate@*/
00588     while (*next != '\0') {
00589         linenum++;
00590 
00591         s = se = next;
00592 
00593         /* Find end-of-line. */
00594         while (*se && *se != '\n') se++;
00595         if (*se != '\0') *se++ = '\0';
00596         next = se;
00597 
00598         /* Trim leading spaces */
00599         while (*s && xisspace(*s)) s++;
00600 
00601         /* We used to allow comments to begin anywhere, but not anymore. */
00602         if (*s == '#' || *s == '\0') continue;
00603 
00604         /* Find end-of-keyword. */
00605         se = (char *)s;
00606         while (*se && !xisspace(*se) && *se != ':') se++;
00607 
00608         if (xisspace(*se)) {
00609             *se++ = '\0';
00610             while (*se && xisspace(*se) && *se != ':') se++;
00611         }
00612 
00613         if (*se != ':') {
00614             rpmError(RPMERR_RPMRC, _("missing ':' (found 0x%02x) at %s:%d\n"),
00615                      (unsigned)(0xff & *se), urlfn, linenum);
00616             return 1;
00617         }
00618         *se++ = '\0';   /* terminate keyword or option, point to value */
00619         while (*se && xisspace(*se)) se++;
00620 
00621         /* Find keyword in table */
00622         searchOption.name = s;
00623         option = bsearch(&searchOption, optionTable, optionTableSize,
00624                          sizeof(optionTable[0]), optionCompare);
00625 
00626         if (option) {   /* For configuration variables  ... */
00627             const char *arch, *val, *fn;
00628 
00629             arch = val = fn = NULL;
00630             if (*se == '\0') {
00631                 rpmError(RPMERR_RPMRC, _("missing argument for %s at %s:%d\n"),
00632                       option->name, urlfn, linenum);
00633                 return 1;
00634             }
00635 
00636             switch (option->var) {
00637             case RPMVAR_INCLUDE:
00638               { FD_t fdinc;
00639 
00640                 s = se;
00641                 while (*se && !xisspace(*se)) se++;
00642                 if (*se != '\0') *se++ = '\0';
00643 
00644 #if 0 /* XXX doesn't seem to do anything useful, only break things... */
00645                 rpmRebuildTargetVars(NULL, NULL);
00646 #endif
00647 
00648                 fn = rpmGetPath(s, NULL);
00649                 if (fn == NULL || *fn == '\0') {
00650                     rpmError(RPMERR_RPMRC, _("%s expansion failed at %s:%d \"%s\"\n"),
00651                         option->name, urlfn, linenum, s);
00652                     fn = _free(fn);
00653                     return 1;
00654                     /*@notreached@*/
00655                 }
00656 
00657                 fdinc = Fopen(fn, "r.fpio");
00658                 if (fdinc == NULL || Ferror(fdinc)) {
00659                     rpmError(RPMERR_RPMRC, _("cannot open %s at %s:%d: %s\n"),
00660                         fn, urlfn, linenum, Fstrerror(fdinc));
00661                     rc = 1;
00662                 } else {
00663                     rc = doReadRC(fdinc, fn);
00664                 }
00665                 fn = _free(fn);
00666                 if (rc) return rc;
00667                 continue;       /* XXX don't save include value as var/macro */
00668               } /*@notreached@*/ /*@switchbreak@*/ break;
00669             case RPMVAR_MACROFILES:
00670                 fn = rpmGetPath(se, NULL);
00671                 if (fn == NULL || *fn == '\0') {
00672                     rpmError(RPMERR_RPMRC, _("%s expansion failed at %s:%d \"%s\"\n"),
00673                         option->name, urlfn, linenum, fn);
00674                     fn = _free(fn);
00675                     return 1;
00676                 }
00677                 se = (char *)fn;
00678                 /*@switchbreak@*/ break;
00679             case RPMVAR_PROVIDES:
00680               { char *t;
00681                 s = rpmGetVar(RPMVAR_PROVIDES);
00682                 if (s == NULL) s = "";
00683                 fn = t = xmalloc(strlen(s) + strlen(se) + 2);
00684                 while (*s != '\0') *t++ = *s++;
00685                 *t++ = ' ';
00686                 while (*se != '\0') *t++ = *se++;
00687                 *t++ = '\0';
00688                 se = (char *)fn;
00689               } /*@switchbreak@*/ break;
00690             default:
00691                 /*@switchbreak@*/ break;
00692             }
00693 
00694             if (option->archSpecific) {
00695                 arch = se;
00696                 while (*se && !xisspace(*se)) se++;
00697                 if (*se == '\0') {
00698                     rpmError(RPMERR_RPMRC,
00699                                 _("missing architecture for %s at %s:%d\n"),
00700                                 option->name, urlfn, linenum);
00701                     return 1;
00702                 }
00703                 *se++ = '\0';
00704                 while (*se && xisspace(*se)) se++;
00705                 if (*se == '\0') {
00706                     rpmError(RPMERR_RPMRC,
00707                                 _("missing argument for %s at %s:%d\n"),
00708                                 option->name, urlfn, linenum);
00709                     return 1;
00710                 }
00711             }
00712         
00713             val = se;
00714 
00715             /* Only add macros if appropriate for this arch */
00716             if (option->macroize &&
00717               (arch == NULL || !strcmp(arch, current[ARCH]))) {
00718                 char *n, *name;
00719                 n = name = xmalloc(strlen(option->name)+2);
00720                 if (option->localize)
00721                     *n++ = '_';
00722                 strcpy(n, option->name);
00723                 addMacro(NULL, name, NULL, val, RMIL_RPMRC);
00724                 free(name);
00725             }
00726             rpmSetVarArch(option->var, val, arch);
00727             fn = _free(fn);
00728 
00729         } else {        /* For arch/os compatibilty tables ... */
00730             int gotit;
00731             int i;
00732 
00733             gotit = 0;
00734 
00735             for (i = 0; i < RPM_MACHTABLE_COUNT; i++) {
00736                 if (!strncmp(tables[i].key, s, strlen(tables[i].key)))
00737                     /*@innerbreak@*/ break;
00738             }
00739 
00740             if (i < RPM_MACHTABLE_COUNT) {
00741                 const char *rest = s + strlen(tables[i].key);
00742                 if (*rest == '_') rest++;
00743 
00744                 if (!strcmp(rest, "compat")) {
00745                     if (machCompatCacheAdd(se, urlfn, linenum,
00746                                                 &tables[i].cache))
00747                         return 1;
00748                     gotit = 1;
00749                 } else if (tables[i].hasTranslate &&
00750                            !strcmp(rest, "translate")) {
00751                     if (addDefault(&tables[i].defaults,
00752                                    &tables[i].defaultsLength,
00753                                    se, urlfn, linenum))
00754                         return 1;
00755                     gotit = 1;
00756                 } else if (tables[i].hasCanon &&
00757                            !strcmp(rest, "canon")) {
00758                     if (addCanon(&tables[i].canons, &tables[i].canonsLength,
00759                                  se, urlfn, linenum))
00760                         return 1;
00761                     gotit = 1;
00762                 }
00763             }
00764 
00765             if (!gotit) {
00766                 rpmError(RPMERR_RPMRC, _("bad option '%s' at %s:%d\n"),
00767                             s, urlfn, linenum);
00768             }
00769         }
00770     }
00771     /*@=branchstate@*/
00772 
00773     return 0;
00774 }
00775 /*@=usedef@*/
00776 
00777 
00780 /*@-bounds@*/
00781 static int rpmPlatform(const char * platform)
00782         /*@globals nplatpat, platpat,
00783                 rpmGlobalMacroContext, h_errno, fileSystem, internalState @*/
00784         /*@modifies nplatpat, platpat,
00785                 rpmGlobalMacroContext, fileSystem, internalState @*/
00786 {
00787     char *cpu = NULL, *vendor = NULL, *os = NULL, *gnu = NULL;
00788     char * b = NULL;
00789     ssize_t blen = 0;
00790     int init_platform = 0;
00791     char * p, * pe;
00792     int rc;
00793 
00794     rc = rpmioSlurp(platform, &b, &blen);
00795 
00796     if (rc || b == NULL || blen <= 0) {
00797         rc = -1;
00798         goto exit;
00799     }
00800 
00801     p = b;
00802     for (pe = p; p && *p; p = pe) {
00803         pe = strchr(p, '\n');
00804         if (pe)
00805             *pe++ = '\0';
00806 
00807         while (*p && isspace(*p))
00808             p++;
00809         if (*p == '\0' || *p == '#')
00810             continue;
00811 
00812         if (init_platform) {
00813             char * t = p + strlen(p);
00814 
00815             while (--t > p && isspace(*t))
00816                 *t = '\0';
00817             if (t > p) {
00818                 platpat = xrealloc(platpat, (nplatpat + 2) * sizeof(*platpat));
00819 /*@-onlyunqglobaltrans@*/
00820                 platpat[nplatpat] = xstrdup(p);
00821                 nplatpat++;
00822                 platpat[nplatpat] = NULL;
00823 /*@=onlyunqglobaltrans@*/
00824             }
00825             continue;
00826         }
00827 
00828         cpu = p;
00829         vendor = "unknown";
00830         os = "unknown";
00831         gnu = NULL;
00832         while (*p && !(*p == '-' || isspace(*p)))
00833             p++;
00834         if (*p != '\0') *p++ = '\0';
00835 
00836         vendor = p;
00837         while (*p && !(*p == '-' || isspace(*p)))
00838             p++;
00839 /*@-branchstate@*/
00840         if (*p != '-') {
00841             if (*p != '\0') *p++ = '\0';
00842             os = vendor;
00843             vendor = "unknown";
00844         } else {
00845             if (*p != '\0') *p++ = '\0';
00846 
00847             os = p;
00848             while (*p && !(*p == '-' || isspace(*p)))
00849                 p++;
00850             if (*p == '-') {
00851                 *p++ = '\0';
00852 
00853                 gnu = p;
00854                 while (*p && !(*p == '-' || isspace(*p)))
00855                     p++;
00856             }
00857             if (*p != '\0') *p++ = '\0';
00858         }
00859 /*@=branchstate@*/
00860 
00861         addMacro(NULL, "_host_cpu", NULL, cpu, -1);
00862         addMacro(NULL, "_host_vendor", NULL, vendor, -1);
00863         addMacro(NULL, "_host_os", NULL, os, -1);
00864 
00865         platpat = xrealloc(platpat, (nplatpat + 2) * sizeof(*platpat));
00866 /*@-onlyunqglobaltrans@*/
00867         platpat[nplatpat] = rpmExpand("%{_host_cpu}-%{_host_vendor}-%{_host_os}", (gnu && *gnu ? "-" : NULL), gnu, NULL);
00868         nplatpat++;
00869         platpat[nplatpat] = NULL;
00870 /*@=onlyunqglobaltrans@*/
00871         
00872         init_platform++;
00873     }
00874     rc = (init_platform ? 0 : -1);
00875 
00876 exit:
00877 /*@-modobserver@*/
00878     b = _free(b);
00879 /*@=modobserver@*/
00880     return rc;
00881 }
00882 /*@=bounds@*/
00883 
00884 
00885 #       if defined(__linux__) && defined(__i386__)
00886 #include <setjmp.h>
00887 #include <signal.h>
00888 
00889 /*
00890  * Generic CPUID function
00891  */
00892 static inline void cpuid(unsigned int op, int *eax, int *ebx, int *ecx, int *edx)
00893         /*@modifies *eax, *ebx, *ecx, *edx @*/
00894 {
00895 #ifdef  __LCLINT__
00896     *eax = *ebx = *ecx = *edx = 0;
00897 #endif
00898     asm volatile (
00899         "pushl  %%ebx           \n"
00900         "cpuid                  \n"
00901         "movl   %%ebx,  %%esi   \n"
00902         "popl   %%ebx           \n"
00903     : "=a" (*eax), "=S" (*ebx), "=c" (*ecx), "=d" (*edx)
00904     : "a" (op));
00905 }
00906 
00907 /*
00908  * CPUID functions returning a single datum
00909  */
00910 static inline unsigned int cpuid_eax(unsigned int op)
00911         /*@*/
00912 {
00913         unsigned int tmp, val;
00914         cpuid(op, &val, &tmp, &tmp, &tmp);
00915         return val;
00916 }
00917 
00918 static inline unsigned int cpuid_ebx(unsigned int op)
00919         /*@*/
00920 {
00921         unsigned int tmp, val;
00922         cpuid(op, &tmp, &val, &tmp, &tmp);
00923         return val;
00924 }
00925 
00926 static inline unsigned int cpuid_ecx(unsigned int op)
00927         /*@*/
00928 {
00929         unsigned int tmp, val;
00930         cpuid(op, &tmp, &tmp, &val, &tmp);
00931         return val;
00932 }
00933 
00934 static inline unsigned int cpuid_edx(unsigned int op)
00935         /*@*/
00936 {
00937         unsigned int tmp, val;
00938         cpuid(op, &tmp, &tmp, &tmp, &val);
00939         return val;
00940 }
00941 
00942 /*@unchecked@*/
00943 static sigjmp_buf jenv;
00944 
00945 static inline void model3(int _unused)
00946         /*@globals internalState @*/
00947         /*@modifies internalState @*/
00948 {
00949         siglongjmp(jenv, 1);
00950 }
00951 
00952 static inline int RPMClass(void)
00953         /*@globals internalState @*/
00954         /*@modifies internalState @*/
00955 {
00956         int cpu;
00957         unsigned int tfms, junk, cap, capamd;
00958         struct sigaction oldsa;
00959         
00960         sigaction(SIGILL, NULL, &oldsa);
00961         signal(SIGILL, model3);
00962         
00963         if (sigsetjmp(jenv, 1)) {
00964                 sigaction(SIGILL, &oldsa, NULL);
00965                 return 3;
00966         }
00967                 
00968         if (cpuid_eax(0x000000000)==0) {
00969                 sigaction(SIGILL, &oldsa, NULL);
00970                 return 4;
00971         }
00972 
00973         cpuid(0x00000001, &tfms, &junk, &junk, &cap);
00974         cpuid(0x80000001, &junk, &junk, &junk, &capamd);
00975         
00976         cpu = (tfms>>8)&15;
00977         
00978         sigaction(SIGILL, &oldsa, NULL);
00979 
00980         if (cpu < 6)
00981                 return cpu;
00982                 
00983         if (cap & (1<<15)) {
00984                 /* CMOV supported? */
00985                 if (capamd & (1<<30))
00986                         return 7;       /* 3DNOWEXT supported */
00987                 return 6;
00988         }
00989                 
00990         return 5;
00991 }
00992 
00993 /* should only be called for model 6 CPU's */
00994 static int is_athlon(void)
00995         /*@*/
00996 {
00997         unsigned int eax, ebx, ecx, edx;
00998         char vendor[16];
00999         int i;
01000         
01001         cpuid (0, &eax, &ebx, &ecx, &edx);
01002 
01003         /* If you care about space, you can just check ebx, ecx and edx directly
01004            instead of forming a string first and then doing a strcmp */
01005         memset(vendor, 0, sizeof(vendor));
01006         
01007         for (i=0; i<4; i++)
01008                 vendor[i] = (unsigned char) (ebx >>(8*i));
01009         for (i=0; i<4; i++)
01010                 vendor[4+i] = (unsigned char) (edx >>(8*i));
01011         for (i=0; i<4; i++)
01012                 vendor[8+i] = (unsigned char) (ecx >>(8*i));
01013                 
01014         if (strncmp(vendor, "AuthenticAMD", 12) != 0)  
01015                 return 0;
01016 
01017         return 1;
01018 }
01019 
01020 static int is_pentium3()
01021 {
01022     unsigned int eax, ebx, ecx, edx, family, model;
01023     char vendor[16];
01024     cpuid(0, &eax, &ebx, &ecx, &edx);
01025     memset(vendor, 0, sizeof(vendor));
01026     *((unsigned int *)&vendor[0]) = ebx;
01027     *((unsigned int *)&vendor[4]) = edx;
01028     *((unsigned int *)&vendor[8]) = ecx;
01029     if (strncmp(vendor, "GenuineIntel", 12) != 0)
01030         return 0;
01031     cpuid(1, &eax, &ebx, &ecx, &edx);
01032     family = (eax >> 8) & 0x0f;
01033     model = (eax >> 4) & 0x0f;
01034     if (family == 6)
01035         switch (model)
01036         {
01037             case 7:     // Pentium III, Pentium III Xeon (model 7)
01038             case 8:     // Pentium III, Pentium III Xeon, Celeron (model 8)
01039             case 9:     // Pentium M
01040                         /*
01041                             Intel recently announced its new technology for mobile platforms,
01042                             named Centrino, and presents it as a big advance in mobile PCs.
01043                             One of the main part of Centrino consists in a brand new CPU,
01044                             the Pentium M, codenamed Banias, that we'll study in this review.
01045                             A particularity of this CPU is that it was designed for mobile platform
01046                             exclusively, unlike previous mobile CPU (Pentium III-M, Pentium 4-M)
01047                             that share the same micro-architecture as their desktop counterparts.
01048                             The Pentium M introduces a new micro-architecture, adapted for mobility
01049                             constraints, and that is halfway between the Pentium III and the Pentium 4.
01050                                                     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
01051                         */
01052             case 10:    // Pentium III Xeon (model A)
01053             case 11:    // Pentium III (model B)
01054                 return 1;
01055         }
01056     return 0;
01057 }
01058 
01059 static int is_pentium4()
01060 {
01061     unsigned int eax, ebx, ecx, edx, family, model;
01062     char vendor[16];
01063     cpuid(0, &eax, &ebx, &ecx, &edx);
01064     memset(vendor, 0, sizeof(vendor));
01065     *((unsigned int *)&vendor[0]) = ebx;
01066     *((unsigned int *)&vendor[4]) = edx;
01067     *((unsigned int *)&vendor[8]) = ecx;
01068     if (strncmp(vendor, "GenuineIntel", 12) != 0)
01069         return 0;
01070     cpuid(1, &eax, &ebx, &ecx, &edx);
01071     family = (eax >> 8) & 0x0f;
01072     model = (eax >> 4) & 0x0f;
01073     if (family == 15)
01074         switch (model)
01075         {
01076             case 0:     // Pentium 4, Pentium 4 Xeon                 (0.18um)
01077             case 1:     // Pentium 4, Pentium 4 Xeon MP, Celeron     (0.18um)
01078             case 2:     // Pentium 4, Mobile Pentium 4-M,
01079                         // Pentium 4 Xeon, Pentium 4 Xeon MP,
01080                         // Celeron, Mobile Celron                    (0.13um)
01081             case 3:     // Pentium 4, Celeron                        (0.09um)
01082                 return 1;
01083         }
01084     return 0;
01085 }
01086 
01087 static int is_geode()
01088 {
01089     unsigned int eax, ebx, ecx, edx, family, model;
01090     char vendor[16];
01091     /* If you care about space, you can just check ebx, ecx and edx directly
01092        instead of forming a string first and then doing a strcmp */
01093     memset(vendor, 0, sizeof(vendor));
01094     
01095     cpuid(0, &eax, &ebx, &ecx, &edx);
01096     memset(vendor, 0, sizeof(vendor));
01097     *((unsigned int *)&vendor[0]) = ebx;
01098     *((unsigned int *)&vendor[4]) = edx;
01099     *((unsigned int *)&vendor[8]) = ecx;
01100     if (strncmp(vendor, "AuthenticAMD", 12) != 0)  
01101         return 0;
01102     cpuid(1, &eax, &ebx, &ecx, &edx);
01103     family = (eax >> 8) & 0x0f;
01104     model = (eax >> 4) & 0x0f;
01105     if (family == 5)
01106         switch (model)
01107         {
01108             case 10: // Geode 
01109                 return 1;
01110         }
01111     return 0;
01112 }
01113 #endif
01114 
01115 #if defined(__linux__) && defined(__powerpc__)
01116 static jmp_buf mfspr_jmpbuf;
01117 
01118 static void mfspr_ill(int notused)
01119 {
01120     longjmp(mfspr_jmpbuf, -1);
01121 }
01122 #endif
01123 
01126 static void defaultMachine(/*@out@*/ const char ** arch,
01127                 /*@out@*/ const char ** os)
01128         /*@globals rpmGlobalMacroContext, h_errno, fileSystem, internalState @*/
01129         /*@modifies *arch, *os, rpmGlobalMacroContext, fileSystem, internalState @*/
01130 {
01131     static struct utsname un;
01132     static int gotDefaults = 0;
01133     char * chptr;
01134     canonEntry canon;
01135     int rc;
01136 
01137     while (!gotDefaults) {
01138         if (!rpmPlatform(platform)) {
01139             const char * s;
01140             s = rpmExpand("%{_host_cpu}", NULL);
01141             if (s) {
01142                 strncpy(un.machine, s, sizeof(un.machine));
01143                 un.machine[sizeof(un.machine)-1] = '\0';
01144                 s = _free(s);
01145             }
01146             s = rpmExpand("%{_host_os}", NULL);
01147             if (s) {
01148                 strncpy(un.sysname, s, sizeof(un.sysname));
01149                 un.sysname[sizeof(un.sysname)-1] = '\0';
01150                 s = _free(s);
01151             }
01152             gotDefaults = 1;
01153             break;
01154         }
01155         rc = uname(&un);
01156         if (rc < 0) return;
01157 
01158 #if !defined(__linux__)
01159 #ifdef SNI
01160         /* USUALLY un.sysname on sinix does start with the word "SINIX"
01161          * let's be absolutely sure
01162          */
01163         strncpy(un.sysname, "SINIX", sizeof(un.sysname));
01164 #endif
01165         /*@-nullpass@*/
01166         if (!strcmp(un.sysname, "AIX")) {
01167             strcpy(un.machine, __power_pc() ? "ppc" : "rs6000");
01168             sprintf(un.sysname,"aix%s.%s", un.version, un.release);
01169         }
01170         else if(!strcmp(un.sysname, "Darwin")) { 
01171 #ifdef __ppc__
01172             strcpy(un.machine, "ppc");
01173 #else ifdef __i386__
01174             strcpy(un.machine, "i386");
01175 #endif 
01176         }
01177         else if (!strcmp(un.sysname, "SunOS")) {
01178             if (!strncmp(un.release,"4", 1)) /* SunOS 4.x */ {
01179                 int fd;
01180                 for (fd = 0;
01181                     (un.release[fd] != 0 && (fd < sizeof(un.release)));
01182                     fd++) {
01183                       if (!xisdigit(un.release[fd]) && (un.release[fd] != '.')) {
01184                         un.release[fd] = 0;
01185                         /*@innerbreak@*/ break;
01186                       }
01187                     }
01188                     sprintf(un.sysname,"sunos%s",un.release);
01189             }
01190 
01191             else /* Solaris 2.x: n.x.x becomes n-3.x.x */
01192                 sprintf(un.sysname, "solaris%1d%s", atoi(un.release)-3,
01193                         un.release+1+(atoi(un.release)/10));
01194 
01195             /* Solaris on Intel hardware reports i86pc instead of i386
01196              * (at least on 2.6 and 2.8)
01197              */
01198             if (!strcmp(un.machine, "i86pc"))
01199                 sprintf(un.machine, "i386");
01200         }
01201         else if (!strcmp(un.sysname, "HP-UX"))
01202             /*make un.sysname look like hpux9.05 for example*/
01203             sprintf(un.sysname, "hpux%s", strpbrk(un.release, "123456789"));
01204         else if (!strcmp(un.sysname, "OSF1"))
01205             /*make un.sysname look like osf3.2 for example*/
01206             sprintf(un.sysname, "osf%s", strpbrk(un.release, "123456789"));
01207         else if (!strncmp(un.sysname, "IP", 2))
01208             un.sysname[2] = '\0';
01209         else if (!strncmp(un.sysname, "SINIX", 5)) {
01210             sprintf(un.sysname, "sinix%s",un.release);
01211             if (!strncmp(un.machine, "RM", 2))
01212                 sprintf(un.machine, "mips");
01213         }
01214         else if ((!strncmp(un.machine, "34", 2) ||
01215                 !strncmp(un.machine, "33", 2)) && \
01216                 !strncmp(un.release, "4.0", 3))
01217         {
01218             /* we are on ncr-sysv4 */
01219             char * prelid = NULL;
01220             FD_t fd = Fopen("/etc/.relid", "r.fdio");
01221             int gotit = 0;
01222             /*@-branchstate@*/
01223             if (fd != NULL && !Ferror(fd)) {
01224                 chptr = xcalloc(1, 256);
01225                 {   int irelid = Fread(chptr, sizeof(*chptr), 256, fd);
01226                     (void) Fclose(fd);
01227                     /* example: "112393 RELEASE 020200 Version 01 OS" */
01228                     if (irelid > 0) {
01229                         if ((prelid = strstr(chptr, "RELEASE "))){
01230                             prelid += strlen("RELEASE ")+1;
01231                             sprintf(un.sysname,"ncr-sysv4.%.*s",1,prelid);
01232                             gotit = 1;
01233                         }
01234                     }
01235                 }
01236                 chptr = _free (chptr);
01237             }
01238             /*@=branchstate@*/
01239             if (!gotit) /* parsing /etc/.relid file failed? */
01240                 strcpy(un.sysname,"ncr-sysv4");
01241             /* wrong, just for now, find out how to look for i586 later*/
01242             strcpy(un.machine,"i486");
01243         }
01244         /*@=nullpass@*/
01245 #endif  /* __linux__ */
01246 
01247         /* get rid of the hyphens in the sysname */
01248         for (chptr = un.machine; *chptr != '\0'; chptr++)
01249             if (*chptr == '/') *chptr = '-';
01250 
01251 #       if defined(__MIPSEL__) || defined(__MIPSEL) || defined(_MIPSEL)
01252             /* little endian */
01253             strcpy(un.machine, "mipsel");
01254 #       elif defined(__MIPSEB__) || defined(__MIPSEB) || defined(_MIPSEB)
01255            /* big endian */
01256                 strcpy(un.machine, "mips");
01257 #       endif
01258 
01259 #       if defined(__hpux) && defined(_SC_CPU_VERSION)
01260         {
01261 #           if !defined(CPU_PA_RISC1_2)
01262 #                define CPU_PA_RISC1_2  0x211 /* HP PA-RISC1.2 */
01263 #           endif
01264 #           if !defined(CPU_PA_RISC2_0)
01265 #               define CPU_PA_RISC2_0  0x214 /* HP PA-RISC2.0 */
01266 #           endif
01267             int cpu_version = sysconf(_SC_CPU_VERSION);
01268 
01269 #           if defined(CPU_HP_MC68020)
01270                 if (cpu_version == CPU_HP_MC68020)
01271                     strcpy(un.machine, "m68k");
01272 #           endif
01273 #           if defined(CPU_HP_MC68030)
01274                 if (cpu_version == CPU_HP_MC68030)
01275                     strcpy(un.machine, "m68k");
01276 #           endif
01277 #           if defined(CPU_HP_MC68040)
01278                 if (cpu_version == CPU_HP_MC68040)
01279                     strcpy(un.machine, "m68k");
01280 #           endif
01281 
01282 #           if defined(CPU_PA_RISC1_0)
01283                 if (cpu_version == CPU_PA_RISC1_0)
01284                     strcpy(un.machine, "hppa1.0");
01285 #           endif
01286 #           if defined(CPU_PA_RISC1_1)
01287                 if (cpu_version == CPU_PA_RISC1_1)
01288                     strcpy(un.machine, "hppa1.1");
01289 #           endif
01290 #           if defined(CPU_PA_RISC1_2)
01291                 if (cpu_version == CPU_PA_RISC1_2)
01292                     strcpy(un.machine, "hppa1.2");
01293 #           endif
01294 #           if defined(CPU_PA_RISC2_0)
01295                 if (cpu_version == CPU_PA_RISC2_0)
01296                     strcpy(un.machine, "hppa2.0");
01297 #           endif
01298         }
01299 #       endif   /* hpux */
01300 
01301 #       if defined(__linux__) && defined(__sparc__)
01302         if (!strcmp(un.machine, "sparc")) {
01303             #define PERS_LINUX          0x00000000
01304             #define PERS_LINUX_32BIT    0x00800000
01305             #define PERS_LINUX32        0x00000008
01306 
01307             extern int personality(unsigned long);
01308             int oldpers;
01309             
01310             oldpers = personality(PERS_LINUX_32BIT);
01311             if (oldpers != -1) {
01312                 if (personality(PERS_LINUX) != -1) {
01313                     uname(&un);
01314                     if (! strcmp(un.machine, "sparc64")) {
01315                         strcpy(un.machine, "sparcv9");
01316                         oldpers = PERS_LINUX32;
01317                     }
01318                 }
01319                 personality(oldpers);
01320             }
01321         }
01322 #       endif   /* sparc*-linux */
01323 
01324 #       if defined(__GNUC__) && defined(__alpha__)
01325         {
01326             unsigned long amask, implver;
01327             register long v0 __asm__("$0") = -1;
01328             __asm__ (".long 0x47e00c20" : "=r"(v0) : "0"(v0));
01329             amask = ~v0;
01330             __asm__ (".long 0x47e03d80" : "=r"(v0));
01331             implver = v0;
01332             switch (implver) {
01333             case 1:
01334                 switch (amask) {
01335                 case 0: strcpy(un.machine, "alphaev5"); break;
01336                 case 1: strcpy(un.machine, "alphaev56"); break;
01337                 case 0x101: strcpy(un.machine, "alphapca56"); break;
01338                 }
01339                 break;
01340             case 2:
01341                 switch (amask) {
01342                 case 0x303: strcpy(un.machine, "alphaev6"); break;
01343                 case 0x307: strcpy(un.machine, "alphaev67"); break;
01344                 }
01345                 break;
01346             }
01347         }
01348 #       endif
01349 
01350 #       if defined(__linux__) && defined(__i386__)
01351         {
01352             char class = (char) (RPMClass() | '0');
01353 
01354             if ((class == '6' && is_athlon()) || class == '7')
01355                 strcpy(un.machine, "athlon");
01356             else if (is_pentium4())
01357                 strcpy(un.machine, "pentium4");
01358             else if (is_pentium3())
01359                 strcpy(un.machine, "pentium3");
01360             else if (is_geode())
01361                 strcpy(un.machine, "geode");
01362             else if (strchr("3456", un.machine[1]) && un.machine[1] != class)
01363                 un.machine[1] = class;
01364         }
01365 #       endif
01366 
01367         /* the uname() result goes through the arch_canon table */
01368         canon = lookupInCanonTable(un.machine,
01369                                    tables[RPM_MACHTABLE_INSTARCH].canons,
01370                                    tables[RPM_MACHTABLE_INSTARCH].canonsLength);
01371         if (canon)
01372             strcpy(un.machine, canon->short_name);
01373 
01374         canon = lookupInCanonTable(un.sysname,
01375                                    tables[RPM_MACHTABLE_INSTOS].canons,
01376                                    tables[RPM_MACHTABLE_INSTOS].canonsLength);
01377         if (canon)
01378             strcpy(un.sysname, canon->short_name);
01379         gotDefaults = 1;
01380         break;
01381     }
01382 
01383     if (arch) *arch = un.machine;
01384     if (os) *os = un.sysname;
01385 }
01386 
01387 static /*@observer@*/ /*@null@*/
01388 const char * rpmGetVarArch(int var, /*@null@*/ const char * arch)
01389         /*@*/
01390 {
01391     const struct rpmvarValue * next;
01392 
01393     if (arch == NULL) arch = current[ARCH];
01394 
01395     if (arch) {
01396         next = &values[var];
01397         while (next) {
01398             if (next->arch && !strcmp(next->arch, arch)) return next->value;
01399             next = next->next;
01400         }
01401     }
01402 
01403     next = values + var;
01404     while (next && next->arch) next = next->next;
01405 
01406     return next ? next->value : NULL;
01407 }
01408 
01409 const char *rpmGetVar(int var)
01410 {
01411     return rpmGetVarArch(var, NULL);
01412 }
01413 
01414 /* this doesn't free the passed pointer! */
01415 static void freeRpmVar(/*@only@*/ struct rpmvarValue * orig)
01416         /*@modifies *orig @*/
01417 {
01418     struct rpmvarValue * next, * var = orig;
01419 
01420     while (var) {
01421         next = var->next;
01422         var->arch = _free(var->arch);
01423         var->value = _free(var->value);
01424 
01425         /*@-branchstate@*/
01426         if (var != orig) var = _free(var);
01427         /*@=branchstate@*/
01428         var = next;
01429     }
01430 }
01431 
01432 void rpmSetVar(int var, const char * val)
01433         /*@globals values @*/
01434         /*@modifies values @*/
01435 {
01436     /*@-immediatetrans@*/
01437     freeRpmVar(&values[var]);
01438     /*@=immediatetrans@*/
01439     values[var].value = (val ? xstrdup(val) : NULL);
01440 }
01441 
01442 static void rpmSetVarArch(int var, const char * val, const char * arch)
01443 {
01444     struct rpmvarValue * next = values + var;
01445 
01446     if (next->value) {
01447         if (arch) {
01448             while (next->next) {
01449                 if (next->arch && !strcmp(next->arch, arch)) break;
01450                 next = next->next;
01451             }
01452         } else {
01453             while (next->next) {
01454                 if (!next->arch) break;
01455                 next = next->next;
01456             }
01457         }
01458 
01459         /*@-nullpass@*/ /* LCL: arch != NULL here. */
01460         if (next->arch && arch && !strcmp(next->arch, arch)) {
01461         /*@=nullpass@*/
01462             next->value = _free(next->value);
01463             next->arch = _free(next->arch);
01464         } else if (next->arch || arch) {
01465             next->next = xmalloc(sizeof(*next->next));
01466             next = next->next;
01467             next->value = NULL;
01468             next->arch = NULL;
01469             next->next = NULL;
01470         }
01471     }
01472 
01473     next->value = _free(next->value);
01474     next->value = xstrdup(val);
01475     next->arch = (arch ? xstrdup(arch) : NULL);
01476 }
01477 
01478 void rpmSetTables(int archTable, int osTable)
01479         /*@globals currTables @*/
01480         /*@modifies currTables @*/
01481 {
01482     const char * arch, * os;
01483 
01484     defaultMachine(&arch, &os);
01485 
01486     if (currTables[ARCH] != archTable) {
01487         currTables[ARCH] = archTable;
01488         rebuildCompatTables(ARCH, arch);
01489     }
01490 
01491     if (currTables[OS] != osTable) {
01492         currTables[OS] = osTable;
01493         rebuildCompatTables(OS, os);
01494     }
01495 }
01496 
01497 int rpmMachineScore(int type, const char * name)
01498 {
01499     machEquivInfo info = machEquivSearch(&tables[type].equiv, name);
01500     return (info != NULL ? info->score : 0);
01501 }
01502 
01503 void rpmGetMachine(const char ** arch, const char ** os)
01504 {
01505     if (arch)
01506         *arch = current[ARCH];
01507 
01508     if (os)
01509         *os = current[OS];
01510 }
01511 
01512 void rpmSetMachine(const char * arch, const char * os)
01513         /*@globals current @*/
01514         /*@modifies current @*/
01515 {
01516     const char * host_cpu, * host_os;
01517 
01518     defaultMachine(&host_cpu, &host_os);
01519 
01520     if (arch == NULL) {
01521         arch = host_cpu;
01522         if (tables[currTables[ARCH]].hasTranslate)
01523             arch = lookupInDefaultTable(arch,
01524                             tables[currTables[ARCH]].defaults,
01525                             tables[currTables[ARCH]].defaultsLength);
01526     }
01527     if (arch == NULL) return;   /* XXX can't happen */
01528 
01529     if (os == NULL) {
01530         os = host_os;
01531         if (tables[currTables[OS]].hasTranslate)
01532             os = lookupInDefaultTable(os,
01533                             tables[currTables[OS]].defaults,
01534                             tables[currTables[OS]].defaultsLength);
01535     }
01536     if (os == NULL) return;     /* XXX can't happen */
01537 
01538     if (!current[ARCH] || strcmp(arch, current[ARCH])) {
01539         current[ARCH] = _free(current[ARCH]);
01540         current[ARCH] = xstrdup(arch);
01541         rebuildCompatTables(ARCH, host_cpu);
01542     }
01543 
01544     if (!current[OS] || strcmp(os, current[OS])) {
01545         char * t = xstrdup(os);
01546         current[OS] = _free(current[OS]);
01547         /*
01548          * XXX Capitalizing the 'L' is needed to insure that old
01549          * XXX os-from-uname (e.g. "Linux") is compatible with the new
01550          * XXX os-from-platform (e.g "linux" from "sparc-*-linux").
01551          * XXX A copy of this string is embedded in headers and is
01552          * XXX used by rpmInstallPackage->{os,arch}Okay->rpmMachineScore->
01553          * XXX to verify correct arch/os from headers.
01554          */
01555         if (!strcmp(t, "linux"))
01556             *t = 'L';
01557         current[OS] = t;
01558         
01559         rebuildCompatTables(OS, host_os);
01560     }
01561 }
01562 
01563 static void rebuildCompatTables(int type, const char * name)
01564         /*@*/
01565 {
01566     machFindEquivs(&tables[currTables[type]].cache,
01567                    &tables[currTables[type]].equiv,
01568                    name);
01569 }
01570 
01571 static void getMachineInfo(int type, /*@null@*/ /*@out@*/ const char ** name,
01572                         /*@null@*/ /*@out@*/int * num)
01573         /*@modifies *name, *num @*/
01574 {
01575     canonEntry canon;
01576     int which = currTables[type];
01577 
01578     /* use the normal canon tables, even if we're looking up build stuff */
01579     if (which >= 2) which -= 2;
01580 
01581     canon = lookupInCanonTable(current[type],
01582                                tables[which].canons,
01583                                tables[which].canonsLength);
01584 
01585     if (canon) {
01586         if (num) *num = canon->num;
01587         if (name) *name = canon->short_name;
01588     } else {
01589         if (num) *num = 255;
01590         if (name) *name = current[type];
01591 
01592         if (tables[currTables[type]].hasCanon) {
01593             rpmMessage(RPMMESS_WARNING, _("Unknown system: %s\n"), current[type]);
01594             rpmMessage(RPMMESS_WARNING, _("Please contact rpm-maint@lists.rpm.org\n"));
01595         }
01596     }
01597 }
01598 
01599 void rpmGetArchInfo(const char ** name, int * num)
01600 {
01601     getMachineInfo(ARCH, name, num);
01602 }
01603 
01604 void rpmGetOsInfo(const char ** name, int * num)
01605 {
01606     getMachineInfo(OS, name, num);
01607 }
01608 
01609 static void rpmRebuildTargetVars(const char ** target, const char ** canontarget)
01610 {
01611 
01612     char *ca = NULL, *co = NULL, *ct = NULL;
01613     int x;
01614 
01615     /* Rebuild the compat table to recalculate the current target arch.  */
01616 
01617     rpmSetMachine(NULL, NULL);
01618     rpmSetTables(RPM_MACHTABLE_INSTARCH, RPM_MACHTABLE_INSTOS);
01619     rpmSetTables(RPM_MACHTABLE_BUILDARCH, RPM_MACHTABLE_BUILDOS);
01620 
01621     /*@-branchstate@*/
01622     if (target && *target) {
01623         char *c;
01624         /* Set arch and os from specified build target */
01625         ca = xstrdup(*target);
01626         if ((c = strchr(ca, '-')) != NULL) {
01627             *c++ = '\0';
01628             
01629             if ((co = strrchr(c, '-')) == NULL) {
01630                 co = c;
01631             } else {
01632                 if (!xstrcasecmp(co, "-gnu"))
01633                     *co = '\0';
01634                 if ((co = strrchr(c, '-')) == NULL)
01635                     co = c;
01636                 else
01637                     co++;
01638             }
01639             if (co != NULL) co = xstrdup(co);
01640         }
01641     } else {
01642         const char *a = NULL;
01643         const char *o = NULL;
01644         /* Set build target from rpm arch and os */
01645         rpmGetArchInfo(&a, NULL);
01646         ca = (a) ? xstrdup(a) : NULL;
01647         rpmGetOsInfo(&o, NULL);
01648         co = (o) ? xstrdup(o) : NULL;
01649     }
01650     /*@=branchstate@*/
01651 
01652     /* If still not set, Set target arch/os from default uname(2) values */
01653     if (ca == NULL) {
01654         const char *a = NULL;
01655         defaultMachine(&a, NULL);
01656         ca = (a) ? xstrdup(a) : NULL;
01657     }
01658     for (x = 0; ca[x] != '\0'; x++)
01659         ca[x] = xtolower(ca[x]);
01660 
01661     if (co == NULL) {
01662         const char *o = NULL;
01663         defaultMachine(NULL, &o);
01664         co = (o) ? xstrdup(o) : NULL;
01665     }
01666     for (x = 0; co[x] != '\0'; x++)
01667         co[x] = xtolower(co[x]);
01668 
01669     /* XXX For now, set canonical target to arch-os */
01670     if (ct == NULL) {
01671         ct = xmalloc(strlen(ca) + sizeof("-") + strlen(co));
01672         sprintf(ct, "%s-%s", ca, co);
01673     }
01674 
01675 /*
01676  * XXX All this macro pokery/jiggery could be achieved by doing a delayed
01677  *      rpmInitMacros(NULL, PER-PLATFORM-MACRO-FILE-NAMES);
01678  */
01679     delMacro(NULL, "_target");
01680     addMacro(NULL, "_target", NULL, ct, RMIL_RPMRC);
01681     delMacro(NULL, "_target_cpu");
01682     addMacro(NULL, "_target_cpu", NULL, ca, RMIL_RPMRC);
01683     delMacro(NULL, "_target_os");
01684     addMacro(NULL, "_target_os", NULL, co, RMIL_RPMRC);
01685 /*
01686  * XXX Make sure that per-arch optflags is initialized correctly.
01687  */
01688   { const char *optflags = rpmGetVarArch(RPMVAR_OPTFLAGS, ca);
01689     if (optflags != NULL) {
01690         delMacro(NULL, "optflags");
01691         addMacro(NULL, "optflags", NULL, optflags, RMIL_RPMRC);
01692     }
01693   }
01694 
01695     /*@-branchstate@*/
01696     if (canontarget)
01697         *canontarget = ct;
01698     else
01699         ct = _free(ct);
01700     /*@=branchstate@*/
01701     ca = _free(ca);
01702     /*@-usereleased@*/
01703     co = _free(co);
01704     /*@=usereleased@*/
01705 }
01706 
01707 void rpmFreeRpmrc(void)
01708         /*@globals current, tables, values, defaultsInitialized,
01709                 platpat, nplatpat @*/
01710         /*@modifies current, tables, values, defaultsInitialized,
01711                 platpat, nplatpat @*/
01712 {
01713     int i, j, k;
01714 
01715 /*@-onlyunqglobaltrans -unqualifiedtrans @*/
01716     if (platpat)
01717     for (i = 0; i < nplatpat; i++)
01718         platpat[i] = _free(platpat[i]);
01719     platpat = _free(platpat);
01720 /*@-onlyunqglobaltrans =unqualifiedtrans @*/
01721     nplatpat = 0;
01722 
01723     for (i = 0; i < RPM_MACHTABLE_COUNT; i++) {
01724         tableType t;
01725         t = tables + i;
01726         if (t->equiv.list) {
01727             for (j = 0; j < t->equiv.count; j++)
01728                 t->equiv.list[j].name = _free(t->equiv.list[j].name);
01729             t->equiv.list = _free(t->equiv.list);
01730             t->equiv.count = 0;
01731         }
01732         if (t->cache.cache) {
01733             for (j = 0; j < t->cache.size; j++) {
01734                 machCacheEntry e;
01735                 e = t->cache.cache + j;
01736                 if (e == NULL)
01737                     /*@innercontinue@*/ continue;
01738                 e->name = _free(e->name);
01739                 if (e->equivs) {
01740                     for (k = 0; k < e->count; k++)
01741                         e->equivs[k] = _free(e->equivs[k]);
01742                     e->equivs = _free(e->equivs);
01743                 }
01744             }
01745             t->cache.cache = _free(t->cache.cache);
01746             t->cache.size = 0;
01747         }
01748         if (t->defaults) {
01749             for (j = 0; j < t->defaultsLength; j++) {
01750                 t->defaults[j].name = _free(t->defaults[j].name);
01751                 t->defaults[j].defName = _free(t->defaults[j].defName);
01752             }
01753             t->defaults = _free(t->defaults);
01754             t->defaultsLength = 0;
01755         }
01756         if (t->canons) {
01757             for (j = 0; j < t->canonsLength; j++) {
01758                 t->canons[j].name = _free(t->canons[j].name);
01759                 t->canons[j].short_name = _free(t->canons[j].short_name);
01760             }
01761             t->canons = _free(t->canons);
01762             t->canonsLength = 0;
01763         }
01764     }
01765 
01766     for (i = 0; i < RPMVAR_NUM; i++) {
01767         /*@only@*/ /*@null@*/ struct rpmvarValue * vp;
01768         while ((vp = values[i].next) != NULL) {
01769             values[i].next = vp->next;
01770             vp->value = _free(vp->value);
01771             vp->arch = _free(vp->arch);
01772             vp = _free(vp);
01773         }
01774         values[i].value = _free(values[i].value);
01775         values[i].arch = _free(values[i].arch);
01776     }
01777     current[OS] = _free(current[OS]);
01778     current[ARCH] = _free(current[ARCH]);
01779     defaultsInitialized = 0;
01780 /*@-globstate -nullstate@*/ /* FIX: platpat/current may be NULL */
01781     return;
01782 /*@=globstate =nullstate@*/
01783 }
01784 
01790 static int rpmReadRC(/*@null@*/ const char * rcfiles)
01791         /*@globals defaultsInitialized, rpmGlobalMacroContext,
01792                 rpmCLIMacroContext, h_errno, fileSystem, internalState @*/
01793         /*@modifies defaultsInitialized, rpmGlobalMacroContext,
01794                 fileSystem, internalState @*/
01795 {
01796     char *myrcfiles, *r, *re;
01797     int rc;
01798 
01799     if (!defaultsInitialized) {
01800         setDefaults();
01801         defaultsInitialized = 1;
01802     }
01803 
01804     if (rcfiles == NULL)
01805         rcfiles = defrcfiles;
01806 
01807     /* Read each file in rcfiles. */
01808     rc = 0;
01809     for (r = myrcfiles = xstrdup(rcfiles); r && *r != '\0'; r = re) {
01810         char fn[4096];
01811         FD_t fd;
01812 
01813         /* Get pointer to rest of files */
01814         for (re = r; (re = strchr(re, ':')) != NULL; re++) {
01815             if (!(re[1] == '/' && re[2] == '/'))
01816                 /*@innerbreak@*/ break;
01817         }
01818         if (re && *re == ':')
01819             *re++ = '\0';
01820         else
01821             re = r + strlen(r);
01822 
01823         /* Expand ~/ to $HOME/ */
01824         fn[0] = '\0';
01825         if (r[0] == '~' && r[1] == '/') {
01826             const char * home = getenv("HOME");
01827             if (home == NULL) {
01828             /* XXX Only /usr/lib/rpm/rpmrc must exist in default rcfiles list */
01829                 if (rcfiles == defrcfiles && myrcfiles != r)
01830                     continue;
01831                 rpmError(RPMERR_RPMRC, _("Cannot expand %s\n"), r);
01832                 rc = 1;
01833                 break;
01834             }
01835             if (strlen(home) > (sizeof(fn) - strlen(r))) {
01836                 rpmError(RPMERR_RPMRC, _("Cannot read %s, HOME is too large.\n"),
01837                                 r);
01838                 rc = 1;
01839                 break;
01840             }
01841             strcpy(fn, home);
01842             r++;
01843         }
01844         strncat(fn, r, sizeof(fn) - (strlen(fn) + 1));
01845         fn[sizeof(fn)-1] = '\0';
01846 
01847         /* Read another rcfile */
01848         fd = Fopen(fn, "r.fpio");
01849         if (fd == NULL || Ferror(fd)) {
01850             /* XXX Only /usr/lib/rpm/rpmrc must exist in default rcfiles list */
01851             if (rcfiles == defrcfiles && myrcfiles != r)
01852                 continue;
01853             rpmError(RPMERR_RPMRC, _("Unable to open %s for reading: %s.\n"),
01854                  fn, Fstrerror(fd));
01855             rc = 1;
01856             break;
01857         } else {
01858             rc = doReadRC(fd, fn);
01859         }
01860         if (rc) break;
01861     }
01862     myrcfiles = _free(myrcfiles);
01863     if (rc)
01864         return rc;
01865 
01866     rpmSetMachine(NULL, NULL);  /* XXX WTFO? Why bother? */
01867 
01868     {   const char *mfpath;
01869         /*@-branchstate@*/
01870         if ((mfpath = rpmGetVar(RPMVAR_MACROFILES)) != NULL) {
01871             mfpath = xstrdup(mfpath);
01872             rpmInitMacros(NULL, mfpath);
01873             mfpath = _free(mfpath);
01874         }
01875         /*@=branchstate@*/
01876     }
01877 
01878     return rc;
01879 }
01880 
01881 int rpmReadConfigFiles(const char * file, const char * target)
01882 {
01883     mode_t mode = 0022;
01884     /* Reset umask to its default umask(2) value. */
01885     mode = umask(mode);
01886 
01887     /* Initialize crypto engine as early as possible */
01888     if (rpmInitCrypto() < 0) {
01889         return -1;
01890     }   
01891     /* Preset target macros */
01892     /*@-nullstate@*/    /* FIX: target can be NULL */
01893     rpmRebuildTargetVars(&target, NULL);
01894 
01895     /* Read the files */
01896     if (rpmReadRC(file)) return -1;
01897 
01898     /* Reset target macros */
01899     rpmRebuildTargetVars(&target, NULL);
01900     /*@=nullstate@*/
01901 
01902     /* Finally set target platform */
01903     {   const char *cpu = rpmExpand("%{_target_cpu}", NULL);
01904         const char *os = rpmExpand("%{_target_os}", NULL);
01905         rpmSetMachine(cpu, os);
01906         cpu = _free(cpu);
01907         os = _free(os);
01908     }
01909 
01910     /* Force Lua state initialization */
01911 #ifdef WITH_LUA
01912     (void)rpmluaGetPrintBuffer(NULL);
01913 #endif
01914 
01915     return 0;
01916 }
01917 
01918 int rpmShowRC(FILE * fp)
01919 {
01920     struct rpmOption *opt;
01921     int i;
01922     machEquivTable equivTable;
01923 
01924     /* the caller may set the build arch which should be printed here */
01925     fprintf(fp, "ARCHITECTURE AND OS:\n");
01926     fprintf(fp, "build arch            : %s\n", current[ARCH]);
01927 
01928     fprintf(fp, "compatible build archs:");
01929     equivTable = &tables[RPM_MACHTABLE_BUILDARCH].equiv;
01930     for (i = 0; i < equivTable->count; i++)
01931         fprintf(fp," %s", equivTable->list[i].name);
01932     fprintf(fp, "\n");
01933 
01934     fprintf(fp, "build os              : %s\n", current[OS]);
01935 
01936     fprintf(fp, "compatible build os's :");
01937     equivTable = &tables[RPM_MACHTABLE_BUILDOS].equiv;
01938     for (i = 0; i < equivTable->count; i++)
01939         fprintf(fp," %s", equivTable->list[i].name);
01940     fprintf(fp, "\n");
01941 
01942     rpmSetTables(RPM_MACHTABLE_INSTARCH, RPM_MACHTABLE_INSTOS);
01943     rpmSetMachine(NULL, NULL);  /* XXX WTFO? Why bother? */
01944 
01945     fprintf(fp, "install arch          : %s\n", current[ARCH]);
01946     fprintf(fp, "install os            : %s\n", current[OS]);
01947 
01948     fprintf(fp, "compatible archs      :");
01949     equivTable = &tables[RPM_MACHTABLE_INSTARCH].equiv;
01950     for (i = 0; i < equivTable->count; i++)
01951         fprintf(fp," %s", equivTable->list[i].name);
01952     fprintf(fp, "\n");
01953 
01954     fprintf(fp, "compatible os's       :");
01955     equivTable = &tables[RPM_MACHTABLE_INSTOS].equiv;
01956     for (i = 0; i < equivTable->count; i++)
01957         fprintf(fp," %s", equivTable->list[i].name);
01958     fprintf(fp, "\n");
01959 
01960     fprintf(fp, "\nRPMRC VALUES:\n");
01961     for (i = 0, opt = optionTable; i < optionTableSize; i++, opt++) {
01962         const char *s = rpmGetVar(opt->var);
01963         if (s != NULL || rpmIsVerbose())
01964             fprintf(fp, "%-21s : %s\n", opt->name, s ? s : "(not set)");
01965     }
01966     fprintf(fp, "\n");
01967 
01968     fprintf(fp, "Features supported by rpmlib:\n");
01969     rpmShowRpmlibProvides(fp);
01970     fprintf(fp, "\n");
01971 
01972     rpmDumpMacroTable(NULL, fp);
01973 
01974     return 0;
01975 }
01976 /*@=bounds@*/

Generated on Thu Jan 13 21:13:23 2011 for rpm by  doxygen 1.4.7