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

Generated on Tue Feb 19 22:26:34 2008 for rpm by  doxygen 1.5.1