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

Generated on Fri Aug 31 12:48:24 2007 for rpm by  doxygen 1.5.1