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

# lib/rpmrc.c

Go to the documentation of this file.

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