Main Page | Modules | Data Structures | File List | Data Fields | Globals | Related Pages

lib/rpmrc.c

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

Generated on Tue Dec 27 22:41:25 2016 for rpm by  doxygen 1.4.4