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