rpm  5.2.1
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 }