rpm 5.2.1

- Main Page
- Related Pages
- Modules
- Data Structures
- Files

- File List
- Globals

lib/rpmrc.c
Go to the documentation of this file.

    00001 #include "system.h"
    00002
    00003 #include <stdarg.h>
    00004
    00005 #if defined(HAVE_SYS_SYSTEMCFG_H)
    00006 #include <sys/systemcfg.h>
    00007 #else
    00008 #define __power_pc() 0
    00009 #endif
    00010
    00011 #define _RPMIOB_INTERNAL        /* XXX for rpmiobSlurp */
    00012 #include <rpmio.h>
    00013 #include <rpmcb.h>
    00014 #define _MIRE_INTERNAL
    00015 #include <mire.h>
    00016 #include <argv.h>
    00017 #include <rpmlua.h>
    00018 #include <rpmluaext.h>
    00019 #include <rpmmacro.h>
    00020
    00021 #include <rpmtypes.h>
    00022 #include <rpmtag.h>
    00023 #define _RPMEVR_INTERNAL
    00024 #include <rpmevr.h>
    00025
    00026 #define _RPMDS_INTERNAL
    00027 #include <rpmds.h>
    00028
    00029 #include <rpmcli.h>
    00030
    00031 #include <rpmsyck.h>
    00032
    00033 #include "debug.h"
    00034
    00035 /*@access miRE@*/
    00036
    00037 /*@unchecked@*/ /*@null@*/
    00038 static const char * configTarget = NULL;
    00039
    00040 /*@observer@*/ /*@unchecked@*/
    00041 static const char * platform = SYSCONFIGDIR "/platform";
    00042
    00043 /*@only@*/ /*@relnull@*/ /*@unchecked@*/
    00044 void * platpat = NULL;
    00045 /*@unchecked@*/
    00046 int nplatpat = 0;
    00047
    00048 extern rpmds cpuinfoP;
    00049
    00050
    00051
    00057 enum rpm_machtable_e {
    00058     RPM_MACHTABLE_INSTARCH      = 0,
    00059     RPM_MACHTABLE_INSTOS        = 1,
    00060     RPM_MACHTABLE_BUILDARCH     = 2,
    00061     RPM_MACHTABLE_BUILDOS       = 3
    00062 };
    00063 #define RPM_MACHTABLE_COUNT     4
    00065 typedef /*@owned@*/ const char * cptr_t;
    00066
    00067 typedef struct machCacheEntry_s {
    00068     const char * name;
    00069     int count;
    00070     cptr_t * equivs;
    00071     int visited;
    00072 } * machCacheEntry;
    00073
    00074 typedef struct machCache_s {
    00075     machCacheEntry cache;
    00076     int size;
    00077 } * machCache;
    00078
    00079 typedef struct machEquivInfo_s {
    00080     const char * name;
    00081     int score;
    00082 } * machEquivInfo;
    00083
    00084 typedef struct machEquivTable_s {
    00085     int count;
    00086     machEquivInfo list;
    00087 } * machEquivTable;
    00088
    00089 typedef struct defaultEntry_s {
    00090 /*@owned@*/ /*@null@*/ const char * name;
    00091 /*@owned@*/ /*@null@*/ const char * defName;
    00092 } * defaultEntry;
    00093
    00094 typedef struct canonEntry_s {
    00095 /*@owned@*/ const char * name;
    00096 /*@owned@*/ const char * short_name;
    00097     short num;
    00098 } * canonEntry;
    00099
    00100 /* tags are 'key'canon, 'key'translate, 'key'compat
    00101  *
    00102  * for giggles, 'key'_canon, 'key'_compat, and 'key'_canon will also work
    00103  */
    00104 typedef struct tableType_s {
    00105 /*@observer@*/ const char * const key;
    00106     const int hasCanon;
    00107     const int hasTranslate;
    00108     struct machEquivTable_s equiv;
    00109     struct machCache_s cache;
    00110     defaultEntry defaults;
    00111     canonEntry canons;
    00112     int defaultsLength;
    00113     int canonsLength;
    00114 } * tableType;
    00115
    00116 /*@-fullinitblock@*/
    00117 /*@unchecked@*/
    00118 static struct tableType_s tables[RPM_MACHTABLE_COUNT] = {
    00119     { "arch", 1, 0  },
    00120     { "os", 1, 0 },
    00121     { "buildarch", 0, 1 },
    00122     { "buildos", 0, 1 }
    00123 };
    00124 /*@=fullinitblock@*/
    00125
    00126 #define OS      0
    00127 #define ARCH    1
    00128
    00129 /*@unchecked@*/
    00130 static cptr_t current[2];
    00131
    00132 /*@unchecked@*/
    00133 static int currTables[2] = { RPM_MACHTABLE_INSTOS, RPM_MACHTABLE_INSTARCH };
    00134
    00135 /*@unchecked@*/
    00136 static int defaultsInitialized = 0;
    00137
    00138 /* prototypes */
    00139 static void rpmRebuildTargetVars(/*@null@*/ const char **target, /*@null@*/ const char ** canontarget)
    00140         /*@globals rpmGlobalMacroContext, h_errno, fileSystem, internalState @*/
    00141         /*@modifies *canontarget, rpmGlobalMacroContext,
    00142                 fileSystem, internalState @*/;
    00143
    00144 static /*@observer@*/ /*@null@*/ machCacheEntry
    00145 machCacheFindEntry(const machCache cache, const char * key)
    00146         /*@*/
    00147 {
    00148     int i;
    00149
    00150     for (i = 0; i < cache->size; i++)
    00151         if (!strcmp(cache->cache[i].name, key)) return cache->cache + i;
    00152
    00153     return NULL;
    00154 }
    00155
    00156 static void machAddEquiv(machEquivTable table, const char * name,
    00157                            int distance)
    00158         /*@modifies table->list, table->count @*/
    00159 {
    00160     machEquivInfo equiv;
    00161
    00162     {   int i;
    00163         equiv = NULL;
    00164         for (i = 0; i < table->count; i++) {
    00165             if (xstrcasecmp(table->list[i].name, name))
    00166                 continue;
    00167             equiv = table->list + i;
    00168             break;
    00169         }
    00170     }
    00171
    00172     if (!equiv) {
    00173         if (table->count)
    00174             table->list = xrealloc(table->list, (table->count + 1)
    00175                                     * sizeof(*table->list));
    00176         else
    00177             table->list = xmalloc(sizeof(*table->list));
    00178
    00179         table->list[table->count].name = xstrdup(name);
    00180         table->list[table->count++].score = distance;
    00181     }
    00182 }
    00183
    00184 static void machCacheEntryVisit(machCache cache,
    00185                 machEquivTable table, const char * name, int distance)
    00186         /*@modifies table->list, table->count @*/
    00187 {
    00188     machCacheEntry entry;
    00189     int i;
    00190
    00191     entry = machCacheFindEntry(cache, name);
    00192     if (!entry || entry->visited) return;
    00193
    00194     entry->visited = 1;
    00195
    00196     for (i = 0; i < entry->count; i++) {
    00197         machAddEquiv(table, entry->equivs[i], distance);
    00198     }
    00199
    00200     for (i = 0; i < entry->count; i++) {
    00201         machCacheEntryVisit(cache, table, entry->equivs[i], distance + 1);
    00202     }
    00203 }
    00204
    00205 static void rebuildCompatTables(int type, const char * name)
    00206         /*@globals tables, internalState @*/
    00207         /*@modifies tables, internalState @*/
    00208 {
    00209     machCache cache = &tables[currTables[type]].cache;
    00210     machEquivTable table = &tables[currTables[type]].equiv;
    00211     const char * key = name;
    00212     int i;
    00213
    00214     for (i = 0; i < cache->size; i++)
    00215         cache->cache[i].visited = 0;
    00216
    00217     while (table->count > 0) {
    00218         --table->count;
    00219         table->list[table->count].name = _free(table->list[table->count].name);
    00220     }
    00221     table->count = 0;
    00222     table->list = _free(table->list);
    00223
    00224     /*
    00225      *  We have a general graph built using strings instead of pointers.
    00226      *  Yuck. We have to start at a point at traverse it, remembering how
    00227      *  far away everything is.
    00228      */
    00229     /*@-nullstate@*/    /* FIX: table->list may be NULL. */
    00230     machAddEquiv(table, key, 1);
    00231     machCacheEntryVisit(cache, table, key, 2);
    00232     return;
    00233     /*@=nullstate@*/
    00234 }
    00235
    00236 static /*@null@*/ canonEntry lookupInCanonTable(const char * name,
    00237                 const canonEntry table, int tableLen)
    00238         /*@*/
    00239 {
    00240     while (tableLen) {
    00241         tableLen--;
    00242         if (strcmp(name, table[tableLen].name))
    00243             continue;
    00244         /*@-immediatetrans -retalias@*/
    00245         return &(table[tableLen]);
    00246         /*@=immediatetrans =retalias@*/
    00247     }
    00248
    00249     return NULL;
    00250 }
    00251
    00252 static /*@observer@*/ /*@null@*/
    00253 const char * lookupInDefaultTable(const char * name,
    00254                 const defaultEntry table, int tableLen)
    00255         /*@*/
    00256 {
    00257     while (tableLen) {
    00258         tableLen--;
    00259         if (table[tableLen].name && !strcmp(name, table[tableLen].name))
    00260             return table[tableLen].defName;
    00261     }
    00262
    00263     return name;
    00264 }
    00265
    00266 static void addMacroDefault(const char * macroname,
    00267                 const char * val, /*@null@*/ const char * body)
    00268         /*@globals rpmGlobalMacroContext, internalState @*/
    00269         /*@modifies rpmGlobalMacroContext, internalState @*/
    00270 {
    00271     if (body == NULL)
    00272         body = val;
    00273     addMacro(NULL, macroname, NULL, body, RMIL_DEFAULT);
    00274 }
    00275
    00276 static void setPathDefault(const char * macroname, const char * subdir)
    00277         /*@globals rpmGlobalMacroContext, internalState @*/
    00278         /*@modifies rpmGlobalMacroContext, internalState @*/
    00279 {
    00280     if (macroname != NULL) {
    00281 #define _TOPDIRMACRO    "%{_topdir}/"
    00282         char *body = alloca(sizeof(_TOPDIRMACRO) + strlen(subdir));
    00283         strcpy(body, _TOPDIRMACRO);
    00284         strcat(body, subdir);
    00285         addMacro(NULL, macroname, NULL, body, RMIL_DEFAULT);
    00286 #undef _TOPDIRMACRO
    00287     }
    00288 }
    00289
    00290 /*@observer@*/ /*@unchecked@*/
    00291 static const char * ___build_pre = "\n\
    00292 RPM_SOURCE_DIR=\"%{_sourcedir}\"\n\
    00293 RPM_BUILD_DIR=\"%{_builddir}\"\n\
    00294 RPM_OPT_FLAGS=\"%{optflags}\"\n\
    00295 RPM_ARCH=\"%{_arch}\"\n\
    00296 RPM_OS=\"%{_os}\"\n\
    00297 export RPM_SOURCE_DIR RPM_BUILD_DIR RPM_OPT_FLAGS RPM_ARCH RPM_OS\n\
    00298 RPM_DOC_DIR=\"%{_docdir}\"\n\
    00299 export RPM_DOC_DIR\n\
    00300 RPM_PACKAGE_NAME=\"%{name}\"\n\
    00301 RPM_PACKAGE_VERSION=\"%{version}\"\n\
    00302 RPM_PACKAGE_RELEASE=\"%{release}\"\n\
    00303 export RPM_PACKAGE_NAME RPM_PACKAGE_VERSION RPM_PACKAGE_RELEASE\n\
    00304 %{?buildroot:RPM_BUILD_ROOT=\"%{buildroot}\"\n\
    00305 export RPM_BUILD_ROOT\n}\
    00306 ";
    00307
    00308 #if defined(RPM_VENDOR_WINDRIVER)
    00309 /*@unchecked@*/
    00310 extern const char * __usrlibrpm;
    00311 /*@unchecked@*/
    00312 extern const char * __etcrpm;
    00313 #endif
    00314
    00315 static void setDefaults(void)
    00316         /*@globals rpmGlobalMacroContext, internalState @*/
    00317         /*@modifies rpmGlobalMacroContext, internalState @*/
    00318 {
    00319
    00320 #if defined(RPM_VENDOR_WINDRIVER)
    00321     addMacro(NULL, "_usrlibrpm", NULL, __usrlibrpm, RMIL_DEFAULT);
    00322     addMacro(NULL, "_etcrpm", NULL, __etcrpm, RMIL_DEFAULT);
    00323     addMacro(NULL, "_vendor", NULL, "%{?_host_vendor}%{!?_host_vendor:wrs}", RMIL_DEFAULT);
    00324 #endif
    00325
    00326     addMacro(NULL, "_usr", NULL, USRPREFIX, RMIL_DEFAULT);
    00327     addMacro(NULL, "_var", NULL, VARPREFIX, RMIL_DEFAULT);
    00328     addMacro(NULL, "_prefix", NULL, "%{_usr}", RMIL_DEFAULT);
    00329
    00330     addMacro(NULL, "___build_pre", NULL, ___build_pre, RMIL_DEFAULT);
    00331
    00332     addMacroDefault("_topdir",
    00333                 "%{_usr}/src/rpm",      NULL);
    00334     addMacroDefault("_tmppath",
    00335                 "%{_var}/tmp",          NULL);
    00336     addMacroDefault("_dbpath",
    00337                 "%{_var}/lib/rpm",      NULL);
    00338     addMacroDefault("_defaultdocdir",
    00339                 "%{_usr}/share/doc",    NULL);
    00340
    00341     addMacroDefault("_rpmfilename",
    00342         "%%{ARCH}/%%{NAME}-%%{VERSION}-%%{RELEASE}.%%{ARCH}.rpm",NULL);
    00343
    00344     addMacroDefault("optflags",
    00345                 "-O2 -g",                       NULL);
    00346     addMacroDefault("sigtype",
    00347                 "none",                 NULL);
    00348     addMacroDefault("_buildshell",
    00349                 "/bin/sh",              NULL);
    00350
    00351     setPathDefault("_builddir", "BUILD");
    00352     setPathDefault("_rpmdir",   "RPMS");
    00353     setPathDefault("_srcrpmdir",        "SRPMS");
    00354     setPathDefault("_sourcedir",        "SOURCES");
    00355     setPathDefault("_specdir",  "SPECS");
    00356
    00357 }
    00358
    00359 typedef struct cpu_vendor_os_gnu {
    00360 /*@owned@*/
    00361     const char * str;
    00362 /*@observer@*/
    00363     const char * cpu;
    00364 /*@observer@*/
    00365     const char * vendor;
    00366 /*@observer@*/
    00367     const char * os;
    00368 /*@observer@*/
    00369     const char * gnu;
    00370 } * CVOG_t;
    00371
    00374 static int parseCVOG(const char * str, CVOG_t *cvogp)
    00375         /*@modifies *cvogp @*/
    00376 {
    00377     CVOG_t cvog = xcalloc(1, sizeof(*cvog));
    00378     char * p, * pe;
    00379
    00380     cvog->str = p = xstrdup(str);
    00381     pe = p + strlen(p);
    00382     while (pe-- > p && isspace(*pe))
    00383         *pe = '\0';
    00384
    00385     cvog->cpu = p;
    00386     cvog->vendor = "unknown";
    00387     cvog->os = "unknown";
    00388     cvog->gnu = "";
    00389     while (*p && !(*p == '-' || isspace(*p)))
    00390             p++;
    00391     if (*p != '\0') *p++ = '\0';
    00392
    00393     cvog->vendor = p;
    00394     while (*p && !(*p == '-' || isspace(*p)))
    00395         p++;
    00396     if (*p != '-') {
    00397         if (*p != '\0') *p++ = '\0';
    00398         cvog->os = cvog->vendor;
    00399         cvog->vendor = "unknown";
    00400     } else {
    00401         if (*p != '\0') *p++ = '\0';
    00402
    00403         cvog->os = p;
    00404         while (*p && !(*p == '-' || isspace(*p)))
    00405             p++;
    00406         if (*p == '-') {
    00407             *p++ = '\0';
    00408
    00409             cvog->gnu = p;
    00410             while (*p && !(*p == '-' || isspace(*p)))
    00411                 p++;
    00412         }
    00413         if (*p != '\0') *p++ = '\0';
    00414     }
    00415
    00416     if (cvogp)
    00417         *cvogp = cvog;
    00418     else {
    00419         cvog->str = _free(cvog->str);
    00420         cvog = _free(cvog);
    00421     }
    00422     return 0;
    00423 }
    00424
    00430 /*@-onlytrans@*/        /* XXX miRE array, not refcounted. */
    00431 static rpmRC rpmPlatform(const char * platform)
    00432         /*@globals nplatpat, platpat,
    00433                 rpmGlobalMacroContext, h_errno, fileSystem, internalState @*/
    00434         /*@modifies nplatpat, platpat,
    00435                 rpmGlobalMacroContext, fileSystem, internalState @*/
    00436 {
    00437     CVOG_t cvog = NULL;
    00438     rpmiob iob = NULL;
    00439     int init_platform = 0;
    00440     miRE mi_re = NULL;
    00441     int mi_nre = 0;
    00442     char * p, * pe;
    00443     rpmRC rc;
    00444     int xx;
    00445
    00446     rc = rpmiobSlurp(platform, &iob);
    00447
    00448     if (rc || iob == NULL) {
    00449         rc = RPMRC_FAIL;
    00450         goto exit;
    00451     }
    00452
    00453     p = (char *)iob->b;
    00454     for (pe = p; p && *p; p = pe) {
    00455         pe = strchr(p, '\n');
    00456         if (pe)
    00457             *pe++ = '\0';
    00458
    00459         while (*p && xisspace(*p))
    00460             p++;
    00461         if (*p == '\0' || *p == '#')
    00462             continue;
    00463
    00464         if (init_platform) {
    00465             char * t = p + strlen(p);
    00466             while (--t > p && xisspace(*t))
    00467                 *t = '\0';
    00468             if (t > p) {
    00469                 xx = mireAppend(RPMMIRE_REGEX, 0, p, NULL, &mi_re, &mi_nre);
    00470             }
    00471             continue;
    00472         }
    00473
    00474         if (!parseCVOG(p, &cvog) && cvog != NULL) {
    00475             addMacro(NULL, "_host_cpu", NULL, cvog->cpu, -1);
    00476             addMacro(NULL, "_host_vendor", NULL, cvog->vendor, -1);
    00477             addMacro(NULL, "_host_os", NULL, cvog->os, -1);
    00478         }
    00479
    00480 #if defined(RPM_VENDOR_OPENPKG) /* explicit-platform */
    00481         /* do not use vendor and GNU attribution */
    00482         p = rpmExpand("%{_host_cpu}-%{_host_os}", NULL);
    00483 #else
    00484         p = rpmExpand("%{_host_cpu}-%{_host_vendor}-%{_host_os}",
    00485                 (cvog && *cvog->gnu ? "-" : NULL),
    00486                 (cvog ? cvog->gnu : NULL), NULL);
    00487 #endif
    00488         xx = mireAppend(RPMMIRE_STRCMP, 0, p, NULL, &mi_re, &mi_nre);
    00489         p = _free(p);
    00490
    00491         init_platform++;
    00492     }
    00493     rc = (init_platform ? RPMRC_OK : RPMRC_FAIL);
    00494
    00495 exit:
    00496     if (cvog) {
    00497         cvog->str = _free(cvog->str);
    00498         cvog = _free(cvog);
    00499     }
    00500     iob = rpmiobFree(iob);
    00501     if (rc == RPMRC_OK) {
    00502         platpat = mireFreeAll(platpat, nplatpat);
    00503         platpat = mi_re;
    00504         nplatpat = mi_nre;
    00505     }
    00506     return rc;
    00507 }
    00508 /*@=onlytrans@*/
    00509
    00510 #if defined(WITH_CPUINFO) && defined(WITH_SYCK)
    00511 static inline int rpmCpuinfoMatch(const char * feature, const char * EVR, rpmds cpuinfo)
    00512 {
    00513     rpmds cpufeature = rpmdsSingle(RPMTAG_REQUIRENAME, feature, EVR, RPMSENSE_PROBE);
    00514     int ret = rpmdsMatch(cpufeature, cpuinfo);
    00515
    00516     (void)rpmdsFree(cpufeature);
    00517     cpufeature = NULL;
    00518     return ret;
    00519 }
    00520
    00521 static rpmRC rpmCpuinfo(void)
    00522 {
    00523     rpmRC rc = RPMRC_FAIL;
    00524     const char *cpu, *_cpuinfo_path;
    00525     miRE mi_re = NULL;
    00526     int mi_nre = 0, xx, i;
    00527     CVOG_t cvog = NULL;
    00528     struct stat st;
    00529     char *yaml;
    00530     rpmsyck_node *tmp, node;
    00531     rpmSyck cpuinfoYaml;
    00532     FD_t fd;
    00533
    00534     _cpuinfo_path = rpmGetPath("%{?_rpmhome}%{!?_rpmhome:" USRLIBRPM "}/cpuinfo.yaml", NULL);
    00535     if(Stat(_cpuinfo_path, &st))
    00536         return rc;
    00537
    00538     fd = Fopen(_cpuinfo_path, "r");
    00539     _cpuinfo_path = _free(_cpuinfo_path);
    00540     yaml = xcalloc(st.st_size+1, 1);
    00541     Fread(yaml, 1, st.st_size, fd);
    00542     Fclose(fd);
    00543
    00544     xx = rpmdsCpuinfo(&cpuinfoP, NULL);
    00545     cpuinfoYaml = rpmSyckLoad(yaml);
    00546     yaml = _free(yaml);
    00547     htGetEntry(cpuinfoYaml->firstNode->value.map, "cpuinfo", &tmp, NULL, NULL);
    00548     node = tmp[0]->value.seq;
    00549
    00550     /* TODO: cleanup.. */
    00551     for(i = 0; node[i].type != T_END; i++) {
    00552         if(node[i].type == T_MAP) {
    00553             rpmsyck_node *tmp;
    00554             if(htHasEntry(node[i].value.map, "Family")) {
    00555                 htGetEntry(node[i].value.map, "Family", &tmp, NULL, NULL);
    00556                 const char *family = tmp[0]->value.key;
    00557                 int j;
    00558                 hashTable cpus = NULL;
    00559                 if(rpmCpuinfoMatch(family, "", cpuinfoP)) {
    00560                     if(htHasEntry(node[i].value.map, "Arch")) {
    00561                         htGetEntry(node[i].value.map, "Arch", &tmp, NULL, NULL);
    00562                         rpmsyck_node arch = tmp[0]->value.seq;
    00563                         for(j = 0; arch[j].type != T_END; j++);
    00564                         cpus = htCreate(j*2, 0, 0, NULL, NULL);
    00565                         for(j = 0; arch[j].type != T_END; j++) {
    00566                             if(htHasEntry(arch[j].value.map, "Extends")) {
    00567                                 if(htGetEntry(arch[j].value.map, "Extends", &tmp, NULL, NULL) &&
    00568                                         tmp[0]->type == T_STR && !htHasEntry(cpus, tmp[0]->value.key))
    00569                                     continue;
    00570                             }
    00571                             if(htHasEntry(arch[j].value.map, "Features")) {
    00572                                 htGetEntry(arch[j].value.map, "Features", &tmp, NULL, NULL);
    00573                                 rpmsyck_node features = tmp[0]->value.seq;
    00574                                 int k, match = 0;
    00575                                 for(k = 0; features[k].type != T_END; k++)
    00576                                     if(features[k].type == T_STR && !(match = rpmCpuinfoMatch(features[k].value.key, "", cpuinfoP))) break;
    00577                                 if(!match) continue;
    00578                             }
    00579                             if(htHasEntry(arch[j].value.map, "Name")) {
    00580                                 htGetEntry(arch[j].value.map, "Name", &tmp, NULL, NULL);
    00581                                 if(tmp[0]->type != T_STR) continue;
    00582                                 const char *name = tmp[0]->value.key;
    00583                                 rpmsyck_node alias = NULL;
    00584                                 if(htHasEntry(arch[j].value.map, "Alias")) {
    00585                                     htGetEntry(arch[j].value.map, "Alias", &tmp, NULL, NULL);
    00586                                     alias = tmp[0]->value.seq;
    00587                                 }
    00588                                 htAddEntry(cpus, name, alias);
    00589                             }
    00590                         }
    00591                     }
    00592                     if(htHasEntry(node[i].value.map, "Priority")) {
    00593                         htGetEntry(node[i].value.map, "Priority", &tmp, NULL, NULL);
    00594                         rpmsyck_node priority = tmp[0]->value.seq;
    00595                         int j;
    00596                         for(j = 0; priority[j].type != T_END; j++)
    00597                             if(htHasEntry(cpus, priority[j].value.key)) {
    00598                                 xx = mireAppend(RPMMIRE_REGEX, 0, priority[j].value.key, NULL, &mi_re, &mi_nre);
    00599                                 htGetEntry(cpus, priority[j].value.key, &tmp, NULL, NULL);
    00600                                 if(tmp[0]) {
    00601                                     rpmsyck_node alias = tmp[0];
    00602                                     int k;
    00603                                     for(k = 0; alias[k].type != T_END; k++)
    00604                                         xx = mireAppend(RPMMIRE_REGEX, 0, alias[k].value.key, NULL, &mi_re, &mi_nre);
    00605                                 }
    00606                             }
    00607                     }
    00608                 }
    00609                 if(cpus) cpus = htFree(cpus);
    00610             }
    00611         }
    00612     }
    00613
    00614     cpuinfoYaml = rpmSyckFree(cpuinfoYaml);
    00615
    00616     xx = mireAppend(RPMMIRE_REGEX, 0, "noarch", NULL, &mi_re, &mi_nre);
    00617
    00618     cpu = mi_re[0].pattern;
    00619     if(cpu != NULL)
    00620     {
    00621         if (!parseCVOG(cpu, &cvog) && cvog != NULL) {
    00622             addMacro(NULL, "_host_cpu", NULL, cvog->cpu, -1);
    00623             addMacro(NULL, "_host_vendor", NULL, cvog->vendor, -1);
    00624             addMacro(NULL, "_host_os", NULL, cvog->os, -1);
    00625         }
    00626         if (cvog) {
    00627             cvog->str = _free(cvog->str);
    00628             cvog = _free(cvog);
    00629         }
    00630
    00631         rc = RPMRC_OK;
    00632         if (rc == RPMRC_OK) {
    00633             platpat = mireFreeAll(platpat, nplatpat);
    00634             platpat = mi_re;
    00635             nplatpat = mi_nre;
    00636         }
    00637
    00638     }
    00639     return rc;
    00640 }
    00641 #endif
    00642
    00643 /*@-onlytrans@*/        /* XXX miRE array, not refcounted. */
    00644 int rpmPlatformScore(const char * platform, void * mi_re, int mi_nre)
    00645 {
    00646     miRE mire;
    00647     int i;
    00648
    00649     if (mi_re == NULL) {
    00650         mi_re = platpat;
    00651         mi_nre = nplatpat;
    00652     }
    00653
    00654     if ((mire = mi_re) != NULL)
    00655     for (i = 0; i < mi_nre; i++) {
    00656         if (mireRegexec(mire + i, platform, 0) >= 0)
    00657             return (i + 1);
    00658     }
    00659     return 0;
    00660 }
    00661 /*@=onlytrans@*/
    00662
    00665 static void defaultMachine(/*@out@*/ const char ** arch,
    00666                 /*@out@*/ const char ** os)
    00667         /*@globals rpmGlobalMacroContext, h_errno, fileSystem, internalState @*/
    00668         /*@modifies *arch, *os, rpmGlobalMacroContext, fileSystem, internalState @*/
    00669 {
    00670 #if defined(RPM_VENDOR_OPENPKG) /* larger-utsname */
    00671     /* utsname fields on some platforms (like HP-UX) are very small
    00672        (just about 8 characters). This is too small for OpenPKG, so cheat! */
    00673     static struct utsname un_real;
    00674     static struct {
    00675         char sysname[32];
    00676         char nodename[32];
    00677         char release[32];
    00678         char version[32];
    00679         char machine[32];
    00680     } un;
    00681 #else
    00682     static struct utsname un;
    00683 #endif
    00684     static int gotDefaults = 0;
    00685     int rc;
    00686
    00687     while (!gotDefaults) {
    00688 #if defined(RPM_VENDOR_WINDRIVER)
    00689         const char * _platform = rpmGetPath(__etcrpm, "/platform", NULL);
    00690 #else
    00691         const char * _platform = platform;
    00692 #endif
    00693         CVOG_t cvog = NULL;
    00694 #if defined(RPM_VENDOR_OPENPKG) /* larger-utsname */
    00695         const char *cp;
    00696 #endif
    00697 #if defined(RPM_VENDOR_OPENPKG) /* larger-utsname */
    00698         /* utsname fields on some platforms (like HP-UX) are very small
    00699            (just about 8 characters). This is too small for OpenPKG, so cheat! */
    00700         rc = uname(&un_real);
    00701         strncpy(un.sysname,  un_real.sysname,  sizeof(un.sysname));  un.sysname [sizeof(un.sysname) -1] = '\0';
    00702         strncpy(un.nodename, un_real.nodename, sizeof(un.nodename)); un.nodename[sizeof(un.nodename)-1] = '\0';
    00703         strncpy(un.release,  un_real.release,  sizeof(un.release));  un.release [sizeof(un.release) -1] = '\0';
    00704         strncpy(un.version,  un_real.version,  sizeof(un.version));  un.version [sizeof(un.version) -1] = '\0';
    00705         strncpy(un.machine,  un_real.machine,  sizeof(un.machine));  un.machine [sizeof(un.machine) -1] = '\0';
    00706 #else
    00707         rc = uname(&un);
    00708 #endif
    00709         if (rc < 0) return;
    00710
    00711 #if defined(RPM_VENDOR_OPENPKG) /* platform-major-minor-only */
    00712     /* Reduce the platform version to major and minor version numbers */
    00713     {
    00714         char *cp;
    00715         char *cpR;
    00716         int n;
    00717         cpR = un.release;
    00718         if ((n = strcspn(cpR, "0123456789")) > 0)
    00719             cpR += n;
    00720         if ((n = strspn(cpR, "0123456789.")) > 0) {
    00721             /* terminate after "N.N.N...." prefix */
    00722             cpR[n] = '\0';
    00723             /* shorten to "N.N" if longer */
    00724             if ((cp = strchr(cpR, '.')) != NULL) {
    00725                 if ((cp = strchr(cp+1, '.')) != NULL)
    00726                     *cp = '\0';
    00727             }
    00728             strcat(un.sysname, cpR);
    00729         }
    00730         /* fix up machine hardware name containing white-space as it
    00731            happens to be on Power Macs running MacOS X */
    00732         if (!strncmp(un.machine, "Power Macintosh", 15))
    00733             sprintf(un.machine, "powerpc");
    00734     }
    00735 #endif
    00736
    00737         if (!strncmp(un.machine, "Power Macintosh", 15)) {
    00738             sprintf(un.machine, "ppc");
    00739         }
    00740
    00741 #if defined(RPM_VENDOR_OPENPKG) /* explicit-platform */
    00742         /* allow the path to the "platforms" file be overridden under run-time */
    00743         cp = rpmExpand("%{?__platform}", NULL);
    00744         if (cp == NULL || cp[0] == '\0')
    00745             cp = _platform;
    00746         if (rpmPlatform(cp) == RPMRC_OK) {
    00747 #elif defined(WITH_CPUINFO) && defined(WITH_SYCK)
    00748         if (rpmPlatform(_platform) == RPMRC_OK || rpmCpuinfo() == RPMRC_OK) {
    00749 #else
    00750         if (rpmPlatform(_platform) == RPMRC_OK) {
    00751 #endif
    00752             const char * s;
    00753             gotDefaults = 1;
    00754             s = rpmExpand("%{?_host_cpu}", NULL);
    00755             if (s && *s != '\0') {
    00756                 strncpy(un.machine, s, sizeof(un.machine));
    00757                 un.machine[sizeof(un.machine)-1] = '\0';
    00758             }
    00759             s = _free(s);
    00760             s = rpmExpand("%{?_host_os}", NULL);
    00761             if (s && *s != '\0') {
    00762                 strncpy(un.sysname, s, sizeof(un.sysname));
    00763                 un.sysname[sizeof(un.sysname)-1] = '\0';
    00764             }
    00765             s = _free(s);
    00766         }
    00767
    00768 #if defined(RPM_VENDOR_OPENPKG) /* explicit-platform */
    00769         /* cleanup after above processing */
    00770         if (cp != NULL && cp != _platform)
    00771             cp = _free(cp);
    00772 #endif
    00773 #if defined(RPM_VENDOR_WINDRIVER)
    00774         _platform = _free(_platform);
    00775 #endif
    00776
    00777         if (configTarget && !parseCVOG(configTarget, &cvog) && cvog != NULL) {
    00778             gotDefaults = 1;
    00779             if (cvog->cpu && cvog->cpu[0] != '\0') {
    00780                 strncpy(un.machine, cvog->cpu, sizeof(un.machine));
    00781                 un.machine[sizeof(un.machine)-1] = '\0';
    00782             }
    00783             if (cvog->os && cvog->os[0] != '\0') {
    00784                 strncpy(un.sysname, cvog->os, sizeof(un.sysname));
    00785                 un.sysname[sizeof(un.sysname)-1] = '\0';
    00786             }
    00787             cvog->str = _free(cvog->str);
    00788             cvog = _free(cvog);
    00789         }
    00790         if (gotDefaults)
    00791             break;
    00792         gotDefaults = 1;
    00793         break;
    00794     }
    00795
    00796     if (arch) *arch = un.machine;
    00797     if (os) *os = un.sysname;
    00798 }
    00799
    00807 static void rpmSetTables(int archTable, int osTable)
    00808         /*@globals currTables, rpmGlobalMacroContext, h_errno,
    00809                 fileSystem, internalState @*/
    00810         /*@modifies currTables, rpmGlobalMacroContext,
    00811                 fileSystem, internalState @*/
    00812 {
    00813     const char * arch, * os;
    00814
    00815     defaultMachine(&arch, &os);
    00816
    00817     if (currTables[ARCH] != archTable) {
    00818         currTables[ARCH] = archTable;
    00819         rebuildCompatTables(ARCH, arch);
    00820     }
    00821
    00822     if (currTables[OS] != osTable) {
    00823         currTables[OS] = osTable;
    00824         rebuildCompatTables(OS, os);
    00825     }
    00826 }
    00827
    00828 static void rpmSetMachine(const char * arch, const char * os)
    00829         /*@globals current, rpmGlobalMacroContext, h_errno,
    00830                 fileSystem, internalState @*/
    00831         /*@modifies current, rpmGlobalMacroContext,
    00832                 fileSystem, internalState @*/
    00833 {
    00834     if (arch == NULL) {
    00835 /*@i@*/ defaultMachine(&arch, NULL);
    00836         if (tables[currTables[ARCH]].hasTranslate)
    00837             arch = lookupInDefaultTable(arch,
    00838                             tables[currTables[ARCH]].defaults,
    00839                             tables[currTables[ARCH]].defaultsLength);
    00840     }
    00841 assert(arch != NULL);
    00842
    00843     if (os == NULL) {
    00844 /*@i@*/ defaultMachine(NULL, &os);
    00845         if (tables[currTables[OS]].hasTranslate)
    00846             os = lookupInDefaultTable(os,
    00847                             tables[currTables[OS]].defaults,
    00848                             tables[currTables[OS]].defaultsLength);
    00849     }
    00850 assert(os != NULL);
    00851
    00852
    00853     if (!current[ARCH] || strcmp(arch, current[ARCH])) {
    00854         current[ARCH] = _free(current[ARCH]);
    00855         current[ARCH] = xstrdup(arch);
    00856         rebuildCompatTables(ARCH, arch);
    00857     }
    00858
    00859     if (!current[OS] || strcmp(os, current[OS])) {
    00860         char * t = xstrdup(os);
    00861         current[OS] = _free(current[OS]);
    00862         if (!strcmp(t, "linux"))
    00863             *t = 'L';
    00864         current[OS] = t;
    00865         rebuildCompatTables(OS, os);
    00866     }
    00867 }
    00868
    00869 static void getMachineInfo(int type, /*@null@*/ /*@out@*/ const char ** name,
    00870                         /*@null@*/ /*@out@*/int * num)
    00871         /*@modifies *name, *num @*/
    00872 {
    00873     canonEntry canon;
    00874     int which = currTables[type];
    00875
    00876     /* use the normal canon tables, even if we're looking up build stuff */
    00877     if (which >= 2) which -= 2;
    00878
    00879     canon = lookupInCanonTable(current[type],
    00880                                tables[which].canons,
    00881                                tables[which].canonsLength);
    00882
    00883     if (canon) {
    00884         if (num) *num = canon->num;
    00885         if (name) *name = canon->short_name;
    00886     } else {
    00887         if (num) *num = 255;
    00888 #if defined(WITH_CPUINFO)
    00889         if (name)
    00890         {
    00891             if(type == ARCH)
    00892             {
    00893                 int i, j, n;
    00894                 ARGV_t archs = NULL;
    00895                 char *pref = rpmExpand("%{?_prefer_target_cpu}", NULL);
    00896
    00897                 (void) argvSplit(&archs, pref, " ");
    00898                 for(i = 0, n = argvCount(archs); (i < n && !*name); i++)
    00899                     if((j = rpmPlatformScore(archs[i], platpat, nplatpat)) > 0)
    00900                         *name = ((miRE)platpat)[j-1].pattern;
    00901
    00902                 archs = argvFree(archs);
    00903                 pref = _free(pref);
    00904             }
    00905             if(!*name) *name = current[type];
    00906         }
    00907 #else
    00908         if (name) *name = current[type];
    00909 #endif
    00910     }
    00911 }
    00912
    00913 static void rpmRebuildTargetVars(const char ** target, const char ** canontarget)
    00914 {
    00915
    00916     char *ca = NULL, *co = NULL, *ct = NULL;
    00917     int x;
    00918
    00919     /* Rebuild the compat table to recalculate the current target arch.  */
    00920
    00921     rpmSetMachine(NULL, NULL);
    00922     rpmSetTables(RPM_MACHTABLE_INSTARCH, RPM_MACHTABLE_INSTOS);
    00923     rpmSetTables(RPM_MACHTABLE_BUILDARCH, RPM_MACHTABLE_BUILDOS);
    00924
    00925     if (target && *target) {
    00926         char *c;
    00927         /* Set arch and os from specified build target */
    00928         ca = xstrdup(*target);
    00929         if ((c = strchr(ca, '-')) != NULL) {
    00930             *c++ = '\0';
    00931
    00932             if ((co = strrchr(c, '-')) == NULL) {
    00933                 co = c;
    00934             } else {
    00935                 if (!xstrcasecmp(co, "-gnu"))
    00936                     *co = '\0';
    00937                 if ((co = strrchr(c, '-')) == NULL)
    00938                     co = c;
    00939                 else
    00940                     co++;
    00941             }
    00942             if (co != NULL) co = xstrdup(co);
    00943         }
    00944     } else {
    00945         const char *a = NULL;
    00946         const char *o = NULL;
    00947         /* Set build target from rpm arch and os */
    00948         getMachineInfo(ARCH, &a, NULL);
    00949         ca = (a) ? xstrdup(a) : NULL;
    00950         getMachineInfo(OS, &o, NULL);
    00951         co = (o) ? xstrdup(o) : NULL;
    00952     }
    00953
    00954     /* If still not set, Set target arch/os from default uname(2) values */
    00955     if (ca == NULL) {
    00956         const char *a = NULL;
    00957         defaultMachine(&a, NULL);
    00958         ca = (a) ? xstrdup(a) : NULL;
    00959     }
    00960     if (ca != NULL)
    00961     for (x = 0; ca[x] != '\0'; x++)
    00962         ca[x] = (char)xtolower(ca[x]);
    00963
    00964     if (co == NULL) {
    00965         const char *o = NULL;
    00966         defaultMachine(NULL, &o);
    00967         co = (o) ? xstrdup(o) : NULL;
    00968     }
    00969     if (co != NULL)
    00970     for (x = 0; co[x] != '\0'; x++)
    00971         co[x] = (char)xtolower(co[x]);
    00972
    00973     /* XXX For now, set canonical target to arch-os */
    00974     if (ct == NULL) {
    00975         ct = xmalloc(strlen(ca) + sizeof("-") + strlen(co));
    00976         sprintf(ct, "%s-%s", ca, co);
    00977     }
    00978
    00979 /*
    00980  * XXX All this macro pokery/jiggery could be achieved by doing a delayed
    00981  *      rpmInitMacros(NULL, PER-PLATFORM-MACRO-FILE-NAMES);
    00982  */
    00983     delMacro(NULL, "_target");
    00984     addMacro(NULL, "_target", NULL, ct, RMIL_RPMRC);
    00985     delMacro(NULL, "_target_cpu");
    00986     addMacro(NULL, "_target_cpu", NULL, ca, RMIL_RPMRC);
    00987     delMacro(NULL, "_target_os");
    00988     addMacro(NULL, "_target_os", NULL, co, RMIL_RPMRC);
    00989
    00990     if (canontarget)
    00991         *canontarget = ct;
    00992     else
    00993         ct = _free(ct);
    00994     ca = _free(ca);
    00995     /*@-usereleased@*/
    00996     co = _free(co);
    00997     /*@=usereleased@*/
    00998 }
    00999
    01000 void rpmFreeRpmrc(void)
    01001         /*@globals current, tables, defaultsInitialized @*/
    01002         /*@modifies current, tables, defaultsInitialized @*/
    01003 {
    01004     int i, j, k;
    01005
    01006     (void)mireFreeAll(platpat, nplatpat);
    01007     platpat = NULL;
    01008     nplatpat = 0;
    01009
    01010     for (i = 0; i < RPM_MACHTABLE_COUNT; i++) {
    01011         tableType t;
    01012         t = tables + i;
    01013         if (t->equiv.list) {
    01014             for (j = 0; j < t->equiv.count; j++)
    01015                 t->equiv.list[j].name = _free(t->equiv.list[j].name);
    01016             t->equiv.list = _free(t->equiv.list);
    01017             t->equiv.count = 0;
    01018         }
    01019         if (t->cache.cache) {
    01020             for (j = 0; j < t->cache.size; j++) {
    01021                 machCacheEntry e;
    01022                 e = t->cache.cache + j;
    01023                 if (e == NULL)
    01024                     /*@innercontinue@*/ continue;
    01025                 e->name = _free(e->name);
    01026                 if (e->equivs) {
    01027                     for (k = 0; k < e->count; k++)
    01028                         e->equivs[k] = _free(e->equivs[k]);
    01029                     e->equivs = _free(e->equivs);
    01030                 }
    01031             }
    01032             t->cache.cache = _free(t->cache.cache);
    01033             t->cache.size = 0;
    01034         }
    01035         if (t->defaults) {
    01036             for (j = 0; j < t->defaultsLength; j++) {
    01037                 t->defaults[j].name = _free(t->defaults[j].name);
    01038                 t->defaults[j].defName = _free(t->defaults[j].defName);
    01039             }
    01040             t->defaults = _free(t->defaults);
    01041             t->defaultsLength = 0;
    01042         }
    01043         if (t->canons) {
    01044             for (j = 0; j < t->canonsLength; j++) {
    01045                 t->canons[j].name = _free(t->canons[j].name);
    01046                 t->canons[j].short_name = _free(t->canons[j].short_name);
    01047             }
    01048             t->canons = _free(t->canons);
    01049             t->canonsLength = 0;
    01050         }
    01051     }
    01052
    01053     current[OS] = _free(current[OS]);
    01054     current[ARCH] = _free(current[ARCH]);
    01055     defaultsInitialized = 0;
    01056 /*@-globstate -nullstate@*/ /* FIX: platpat/current may be NULL */
    01057     return;
    01058 /*@=globstate =nullstate@*/
    01059 }
    01060
    01065 static int rpmReadRC(const char *macrofiles)
    01066         /*@globals defaultsInitialized,
    01067                 rpmGlobalMacroContext, rpmCLIMacroContext, h_errno,
    01068                 fileSystem, internalState @*/
    01069         /*@modifies defaultsInitialized, rpmGlobalMacroContext,
    01070                 fileSystem, internalState @*/
    01071 {
    01072     int rc = 0;
    01073
    01074     if (!defaultsInitialized) {
    01075         setDefaults();
    01076         defaultsInitialized = 1;
    01077     }
    01078
    01079     /* Read macro files. */
    01080     {   const char *mfpath = rpmExpand(macrofiles, NULL);
    01081
    01082         if (mfpath != NULL) {
    01083             rpmInitMacros(NULL, mfpath);
    01084             mfpath = _free(mfpath);
    01085         }
    01086     }
    01087
    01088     return rc;
    01089 }
    01090
    01091 int rpmReadConfigFiles(/*@unused@*/ const char * file,
    01092                 const char * target)
    01093         /*@globals configTarget, rpmMacrofiles @*/
    01094         /*@modifies configTarget @*/
    01095 {
    01096     mode_t mode = 0022;
    01097
    01098 #ifdef PREMACROFILES
    01099     if (rpmReadRC(PREMACROFILES)) return -1;
    01100 #endif
    01101
    01102     /* Reset umask to its default umask(2) value. */
    01103     mode = umask(mode);
    01104
    01105     configTarget = target;
    01106
    01107     /* Preset target macros */
    01108     /*@-nullstate@*/    /* FIX: target can be NULL */
    01109     rpmRebuildTargetVars(&target, NULL);
    01110
    01111     /* Read the files */
    01112 /*@-globs@*/
    01113     if (rpmReadRC(rpmMacrofiles)) return -1;
    01114 /*@=globs@*/
    01115
    01116     /* Reset target macros */
    01117     rpmRebuildTargetVars(&target, NULL);
    01118     /*@=nullstate@*/
    01119
    01120     /* Finally set target platform */
    01121     {   const char *cpu = rpmExpand("%{_target_cpu}", NULL);
    01122         const char *os = rpmExpand("%{_target_os}", NULL);
    01123         rpmSetMachine(cpu, os);
    01124
    01125         cpu = _free(cpu);
    01126         os = _free(os);
    01127     }
    01128     configTarget = NULL;
    01129
    01130     /* Force Lua state initialization */
    01131 #ifdef WITH_LUA
    01132     (void)rpmluaGetPrintBuffer(NULL);
    01133 #if defined(RPM_VENDOR_OPENPKG) /* rpm-lua-extensions-based-on-rpm-lib-functionality */
    01134     (void)rpmluaextActivate(rpmluaGetGlobalState());
    01135 #endif /* RPM_VENDOR_OPENPKG */
    01136 #endif
    01137
    01138     return 0;
    01139 }
    01140
    01141 int rpmShowRC(FILE * fp)
    01142 {
    01143     rpmds ds = NULL;
    01144     int i;
    01145     machEquivTable equivTable;
    01146     int xx;
    01147     miRE mire;
    01148
    01149     /* the caller may set the build arch which should be printed here */
    01150     fprintf(fp, "ARCHITECTURE AND OS:\n");
    01151     fprintf(fp, "build arch            : %s\n", current[ARCH]);
    01152
    01153     fprintf(fp, "compatible build archs:");
    01154     equivTable = &tables[RPM_MACHTABLE_BUILDARCH].equiv;
    01155     for (i = 0; i < equivTable->count; i++)
    01156         fprintf(fp," %s", equivTable->list[i].name);
    01157     fprintf(fp, "\n");
    01158
    01159     fprintf(fp, "build os              : %s\n", current[OS]);
    01160
    01161     fprintf(fp, "compatible build os's :");
    01162     equivTable = &tables[RPM_MACHTABLE_BUILDOS].equiv;
    01163     for (i = 0; i < equivTable->count; i++)
    01164         fprintf(fp," %s", equivTable->list[i].name);
    01165     fprintf(fp, "\n");
    01166
    01167     fprintf(fp, "install arch          : %s\n", current[ARCH]);
    01168     fprintf(fp, "install os            : %s\n", current[OS]);
    01169
    01170     fprintf(fp, "compatible archs      :");
    01171     for (mire = platpat, i = 0; i < nplatpat; i++)
    01172         fprintf(fp, " %s", mire[i].pattern);
    01173     fprintf(fp, "\n");
    01174
    01175     fprintf(fp, "compatible os's       :");
    01176     equivTable = &tables[RPM_MACHTABLE_INSTOS].equiv;
    01177     for (i = 0; i < equivTable->count; i++)
    01178         fprintf(fp," %s", equivTable->list[i].name);
    01179     fprintf(fp, "\n");
    01180
    01181     {   const char * s = rpmExpand("%{?optflags}", NULL);
    01182         fprintf(fp, "%-21s : %s\n", "optflags", ((s && *s) ? s : "(not set)"));
    01183         s = _free(s);
    01184
    01185 #ifdef  WITH_LUA
    01186         fprintf(fp, "\nLUA MODULES:\n");
    01187 /*@-globs@*/
    01188         s = rpmExpand(rpmluaFiles, NULL);
    01189 /*@=globs@*/
    01190         fprintf(fp, "%-21s : %s\n", "luafiles", ((s && *s) ? s : "(not set)"));
    01191         s = _free(s);
    01192 /*@-globs@*/
    01193         s = rpmExpand(rpmluaPath, NULL);
    01194 /*@=globs@*/
    01195         fprintf(fp, "%-21s : %s\n", "luapath", ((s && *s) ? s : "(not set)"));
    01196         s = _free(s);
    01197 #endif
    01198
    01199         fprintf(fp, "\nMACRO DEFINITIONS:\n");
    01200 /*@-globs@*/
    01201         s = rpmExpand(rpmMacrofiles, NULL);
    01202 /*@=globs@*/
    01203         fprintf(fp, "%-21s : %s\n", "macrofiles", ((s && *s) ? s : "(not set)"));
    01204         s = _free(s);
    01205     }
    01206
    01207     if (rpmIsVerbose()) {
    01208         rpmPRCO PRCO = rpmdsNewPRCO(NULL);
    01209         xx = rpmdsSysinfo(PRCO, NULL);
    01210         ds = rpmdsFromPRCO(PRCO, RPMTAG_PROVIDENAME);
    01211         if (ds != NULL) {
    01212             const char * fn = (_sysinfo_path ? _sysinfo_path : "/etc/rpm/sysinfo");
    01213             fprintf(fp, _("Configured system provides (from %s):\n"), fn);
    01214             ds = rpmdsInit(ds);
    01215             while (rpmdsNext(ds) >= 0) {
    01216                 const char * DNEVR = rpmdsDNEVR(ds);
    01217                 if (DNEVR != NULL)
    01218                     fprintf(fp, "    %s\n", DNEVR+2);
    01219             }
    01220             (void)rpmdsFree(ds);
    01221             ds = NULL;
    01222             fprintf(fp, "\n");
    01223         }
    01224         PRCO = rpmdsFreePRCO(PRCO);
    01225     }
    01226
    01227     if (rpmIsVerbose()) {
    01228         fprintf(fp, _("Features provided by rpmlib installer:\n"));
    01229         xx = rpmdsRpmlib(&ds, NULL);
    01230         ds = rpmdsInit(ds);
    01231         while (rpmdsNext(ds) >= 0) {
    01232             const char * DNEVR = rpmdsDNEVR(ds);
    01233             if (DNEVR != NULL)
    01234                 fprintf(fp, "    %s\n", DNEVR+2);
    01235         }
    01236         (void)rpmdsFree(ds);
    01237         ds = NULL;
    01238         fprintf(fp, "\n");
    01239
    01240         if(cpuinfoP == NULL)
    01241             xx = rpmdsCpuinfo(&cpuinfoP, NULL);
    01242         if (cpuinfoP != NULL) {
    01243 #if defined(WITH_CPUINFO)
    01244             const char * fn = "libcpuinfo";
    01245 #else
    01246             const char * fn = (_cpuinfo_path ? _cpuinfo_path : "/proc/cpuinfo");
    01247 #endif
    01248             fprintf(fp,
    01249                 _("Features provided by current cpuinfo (from %s):\n"), fn);
    01250             cpuinfoP = rpmdsInit(cpuinfoP);
    01251             while (rpmdsNext(cpuinfoP) >= 0) {
    01252                 const char * DNEVR = rpmdsDNEVR(cpuinfoP);
    01253                 if (DNEVR != NULL)
    01254                     fprintf(fp, "    %s\n", DNEVR+2);
    01255             }
    01256             (void)rpmdsFree(cpuinfoP);
    01257             cpuinfoP = NULL;
    01258
    01259             fprintf(fp, "\n");
    01260         }
    01261     }
    01262
    01263     if (rpmIsDebug()) {
    01264         xx = rpmdsGetconf(&ds, NULL);
    01265         if (ds != NULL) {
    01266             fprintf(fp,
    01267                 _("Features provided by current getconf:\n"));
    01268             ds = rpmdsInit(ds);
    01269             while (rpmdsNext(ds) >= 0) {
    01270                 const char * DNEVR = rpmdsDNEVR(ds);
    01271                 if (DNEVR != NULL)
    01272                     fprintf(fp, "    %s\n", DNEVR+2);
    01273             }
    01274             (void)rpmdsFree(ds);
    01275             ds = NULL;
    01276             fprintf(fp, "\n");
    01277         }
    01278
    01279         xx = rpmdsUname(&ds, NULL);
    01280         if (ds != NULL) {
    01281             fprintf(fp,
    01282                 _("Features provided by current uname:\n"));
    01283             ds = rpmdsInit(ds);
    01284             while (rpmdsNext(ds) >= 0) {
    01285                 const char * DNEVR = rpmdsDNEVR(ds);
    01286                 if (DNEVR != NULL)
    01287                     fprintf(fp, "    %s\n", DNEVR+2);
    01288             }
    01289             (void)rpmdsFree(ds);
    01290             ds = NULL;
    01291             fprintf(fp, "\n");
    01292         }
    01293     }
    01294
    01295     rpmDumpMacroTable(NULL, fp);
    01296
    01297     return 0;
    01298 }