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

lib/rpmrc.c

Go to the documentation of this file.
00001 #include "system.h"
00002 
00003 #include <stdarg.h>
00004 
00005 #if HAVE_SYS_SYSTEMCFG_H
00006 #include <sys/systemcfg.h>
00007 #else
00008 #define __power_pc() 0
00009 #endif
00010 
00011 /*@ access FD_t @*/             /* compared with NULL */
00012 
00013 #include <rpmlib.h>
00014 #include <rpmmacro.h>
00015 
00016 #include "misc.h"
00017 #include "debug.h"
00018 
00019 static const char *defrcfiles = LIBRPMRC_FILENAME ":/etc/rpmrc:~/.rpmrc";
00020 
00021 const char * macrofiles = MACROFILES;
00022 
00023 typedef /*@owned@*/ const char * cptr_t;
00024 
00025 struct machCacheEntry {
00026     const char * name;
00027     int count;
00028     cptr_t * equivs;
00029     int visited;
00030 };
00031 
00032 struct machCache {
00033     struct machCacheEntry * cache;
00034     int size;
00035 };
00036 
00037 struct machEquivInfo {
00038     const char * name;
00039     int score;
00040 };
00041 
00042 struct machEquivTable {
00043     int count;
00044     struct machEquivInfo * list;
00045 };
00046 
00047 struct rpmvarValue {
00048     const char * value;
00049     /* eventually, this arch will be replaced with a generic condition */
00050     const char * arch;
00051     struct rpmvarValue * next;
00052 };
00053 
00054 struct rpmOption {
00055     const char * name;
00056     int var;
00057     int archSpecific, required, macroize, localize;
00058     struct rpmOptionValue * value;
00059 };
00060 
00061 struct defaultEntry {
00062 /*@owned@*/ const char * name;
00063 /*@owned@*/ const char * defName;
00064 };
00065 
00066 struct canonEntry {
00067 /*@owned@*/ const char * name;
00068 /*@owned@*/ const char * short_name;
00069     short num;
00070 };
00071 
00072 /* tags are 'key'canon, 'key'translate, 'key'compat
00073  *
00074  * for giggles, 'key'_canon, 'key'_compat, and 'key'_canon will also work
00075  */
00076 struct tableType {
00077     const char * const key;
00078     const int hasCanon;
00079     const int hasTranslate;
00080     struct machEquivTable equiv;
00081     struct machCache cache;
00082     struct defaultEntry * defaults;
00083     struct canonEntry * canons;
00084     int defaultsLength;
00085     int canonsLength;
00086 };
00087 
00088 /*@-fullinitblock@*/
00089 static struct tableType tables[RPM_MACHTABLE_COUNT] = {
00090     { "arch", 1, 0 },
00091     { "os", 1, 0 },
00092     { "buildarch", 0, 1 },
00093     { "buildos", 0, 1 }
00094 };
00095 
00096 /* this *must* be kept in alphabetical order */
00097 /* The order of the flags is archSpecific, required, macroize, localize */
00098 
00099 static struct rpmOption optionTable[] = {
00100     { "include",                RPMVAR_INCLUDE,                 0, 1,   0, 2 },
00101     { "macrofiles",             RPMVAR_MACROFILES,              0, 0,   0, 1 },
00102     { "optflags",               RPMVAR_OPTFLAGS,                1, 0,   1, 0 },
00103     { "provides",               RPMVAR_PROVIDES,                0, 0,   0, 0 },
00104 };
00105 /*@=fullinitblock@*/
00106 static int optionTableSize = sizeof(optionTable) / sizeof(*optionTable);
00107 
00108 #define OS      0
00109 #define ARCH    1
00110 
00111 static cptr_t current[2];
00112 static int currTables[2] = { RPM_MACHTABLE_INSTOS, RPM_MACHTABLE_INSTARCH };
00113 static struct rpmvarValue values[RPMVAR_NUM];
00114 static int defaultsInitialized = 0;
00115 
00116 /* prototypes */
00117 static int doReadRC( /*@killref@*/ FD_t fd, const char * urlfn);
00118 static void rpmSetVarArch(int var, const char * val, const char * arch);
00119 static void rebuildCompatTables(int type, const char *name);
00120 
00121 static int optionCompare(const void * a, const void * b) {
00122     return xstrcasecmp(((struct rpmOption *) a)->name,
00123                       ((struct rpmOption *) b)->name);
00124 }
00125 
00126 static void rpmRebuildTargetVars(const char **target, const char ** canontarget);
00127 
00128 static /*@observer@*/ struct machCacheEntry *
00129 machCacheFindEntry(struct machCache * cache, const char * key)
00130 {
00131     int i;
00132 
00133     for (i = 0; i < cache->size; i++)
00134         if (!strcmp(cache->cache[i].name, key)) return cache->cache + i;
00135 
00136     return NULL;
00137 }
00138 
00139 static int machCompatCacheAdd(char * name, const char * fn, int linenum,
00140                                 struct machCache * cache)
00141 {
00142     char * chptr, * equivs;
00143     int delEntry = 0;
00144     int i;
00145     struct machCacheEntry * entry = NULL;
00146 
00147     while (*name && isspace(*name)) name++;
00148 
00149     chptr = name;
00150     while (*chptr && *chptr != ':') chptr++;
00151     if (!*chptr) {
00152         rpmError(RPMERR_RPMRC, _("missing second ':' at %s:%d\n"), fn, linenum);
00153         return 1;
00154     } else if (chptr == name) {
00155         rpmError(RPMERR_RPMRC, _("missing architecture name at %s:%d\n"), fn,
00156                              linenum);
00157         return 1;
00158     }
00159 
00160     while (*chptr == ':' || isspace(*chptr)) chptr--;
00161     *(++chptr) = '\0';
00162     equivs = chptr + 1;
00163     while (*equivs && isspace(*equivs)) equivs++;
00164     if (!*equivs) {
00165         delEntry = 1;
00166     }
00167 
00168     if (cache->size) {
00169         entry = machCacheFindEntry(cache, name);
00170         if (entry) {
00171             for (i = 0; i < entry->count; i++)
00172                 free((void *)entry->equivs[i]);
00173             free((void *)entry->equivs);
00174             entry->equivs = NULL;
00175             entry->count = 0;
00176         }
00177     }
00178 
00179     if (!entry) {
00180         cache->cache = xrealloc(cache->cache,
00181                                (cache->size + 1) * sizeof(*cache->cache));
00182         entry = cache->cache + cache->size++;
00183         entry->name = xstrdup(name);
00184         entry->count = 0;
00185         entry->visited = 0;
00186     }
00187 
00188     if (delEntry) return 0;
00189 
00190     while ((chptr = strtok(equivs, " ")) != NULL) {
00191         equivs = NULL;
00192         if (chptr[0] == '\0')   /* does strtok() return "" ever?? */
00193             continue;
00194         if (entry->count)
00195             entry->equivs = xrealloc(entry->equivs, sizeof(*entry->equivs)
00196                                         * (entry->count + 1));
00197         else
00198             entry->equivs = xmalloc(sizeof(*entry->equivs));
00199 
00200         entry->equivs[entry->count] = xstrdup(chptr);
00201         entry->count++;
00202     }
00203 
00204     return 0;
00205 }
00206 
00207 static /*@observer@*/ struct machEquivInfo *
00208         machEquivSearch(const struct machEquivTable * table, const char * name)
00209 {
00210     int i;
00211 
00212     for (i = 0; i < table->count; i++)
00213         if (!xstrcasecmp(table->list[i].name, name))
00214             return table->list + i;
00215 
00216     return NULL;
00217 }
00218 
00219 static void machAddEquiv(struct machEquivTable * table, const char * name,
00220                            int distance)
00221 {
00222     struct machEquivInfo * equiv;
00223 
00224     equiv = machEquivSearch(table, name);
00225     if (!equiv) {
00226         if (table->count)
00227             table->list = xrealloc(table->list, (table->count + 1)
00228                                     * sizeof(*table->list));
00229         else
00230             table->list = xmalloc(sizeof(*table->list));
00231 
00232         table->list[table->count].name = xstrdup(name);
00233         table->list[table->count++].score = distance;
00234     }
00235 }
00236 
00237 static void machCacheEntryVisit(struct machCache * cache,
00238                                   struct machEquivTable * table,
00239                                   const char * name,
00240                                   int distance)
00241 {
00242     struct machCacheEntry * entry;
00243     int i;
00244 
00245     entry = machCacheFindEntry(cache, name);
00246     if (!entry || entry->visited) return;
00247 
00248     entry->visited = 1;
00249 
00250     for (i = 0; i < entry->count; i++) {
00251         machAddEquiv(table, entry->equivs[i], distance);
00252     }
00253 
00254     for (i = 0; i < entry->count; i++) {
00255         machCacheEntryVisit(cache, table, entry->equivs[i], distance + 1);
00256     }
00257 }
00258 
00259 static void machFindEquivs(struct machCache * cache,
00260                              struct machEquivTable * table,
00261                              const char * key)
00262 {
00263     int i;
00264 
00265     for (i = 0; i < cache->size; i++)
00266         cache->cache[i].visited = 0;
00267 
00268     while (table->count > 0) {
00269         free((void *)table->list[--table->count].name);
00270         table->list[table->count].name = NULL;
00271     }
00272     table->count = 0;
00273     if (table->list) free((void *)table->list);
00274     table->list = NULL;
00275 
00276     /*
00277      *  We have a general graph built using strings instead of pointers.
00278      *  Yuck. We have to start at a point at traverse it, remembering how
00279      *  far away everything is.
00280      */
00281     machAddEquiv(table, key, 1);
00282     machCacheEntryVisit(cache, table, key, 2);
00283 }
00284 
00285 static int addCanon(struct canonEntry ** table, int * tableLen, char * line,
00286                     const char * fn, int lineNum)
00287 {
00288     struct canonEntry *t;
00289     char *s, *s1;
00290     const char * tname;
00291     const char * tshort_name;
00292     int tnum;
00293 
00294     if (! *tableLen) {
00295         *tableLen = 2;
00296         *table = xmalloc(2 * sizeof(struct canonEntry));
00297     } else {
00298         (*tableLen) += 2;
00299         *table = xrealloc(*table, sizeof(struct canonEntry) * (*tableLen));
00300     }
00301     t = & ((*table)[*tableLen - 2]);
00302 
00303     tname = strtok(line, ": \t");
00304     tshort_name = strtok(NULL, " \t");
00305     s = strtok(NULL, " \t");
00306     if (! (tname && tshort_name && s)) {
00307         rpmError(RPMERR_RPMRC, _("Incomplete data line at %s:%d\n"),
00308                 fn, lineNum);
00309         return RPMERR_RPMRC;
00310     }
00311     if (strtok(NULL, " \t")) {
00312         rpmError(RPMERR_RPMRC, _("Too many args in data line at %s:%d\n"),
00313               fn, lineNum);
00314         return RPMERR_RPMRC;
00315     }
00316 
00317     tnum = strtoul(s, &s1, 10);
00318     if ((*s1) || (s1 == s) || (tnum == ULONG_MAX)) {
00319         rpmError(RPMERR_RPMRC, _("Bad arch/os number: %s (%s:%d)\n"), s,
00320               fn, lineNum);
00321         return(RPMERR_RPMRC);
00322     }
00323 
00324     t[0].name = xstrdup(tname);
00325     t[0].short_name = xstrdup(tshort_name);
00326     t[0].num = tnum;
00327 
00328     /* From A B C entry */
00329     /* Add  B B C entry */
00330     t[1].name = xstrdup(tshort_name);
00331     t[1].short_name = xstrdup(tshort_name);
00332     t[1].num = tnum;
00333 
00334     return 0;
00335 }
00336 
00337 static int addDefault(struct defaultEntry **table, int *tableLen, char *line,
00338                         const char *fn, int lineNum)
00339 {
00340     struct defaultEntry *t;
00341 
00342     if (! *tableLen) {
00343         *tableLen = 1;
00344         *table = xmalloc(sizeof(struct defaultEntry));
00345     } else {
00346         (*tableLen)++;
00347         *table = xrealloc(*table, sizeof(struct defaultEntry) * (*tableLen));
00348     }
00349     t = & ((*table)[*tableLen - 1]);
00350 
00351     t->name = strtok(line, ": \t");
00352     t->defName = strtok(NULL, " \t");
00353     if (! (t->name && t->defName)) {
00354         rpmError(RPMERR_RPMRC, _("Incomplete default line at %s:%d\n"),
00355                  fn, lineNum);
00356         return RPMERR_RPMRC;
00357     }
00358     if (strtok(NULL, " \t")) {
00359         rpmError(RPMERR_RPMRC, _("Too many args in default line at %s:%d\n"),
00360               fn, lineNum);
00361         return RPMERR_RPMRC;
00362     }
00363 
00364     t->name = xstrdup(t->name);
00365     t->defName = xstrdup(t->defName);
00366 
00367     return 0;
00368 }
00369 
00370 static /*@null@*/ const struct canonEntry *lookupInCanonTable(const char *name,
00371         const struct canonEntry *table, int tableLen)
00372 {
00373     while (tableLen) {
00374         tableLen--;
00375         if (!strcmp(name, table[tableLen].name)) {
00376             return &(table[tableLen]);
00377         }
00378     }
00379 
00380     return NULL;
00381 }
00382 
00383 static /*@observer@*/ const char * lookupInDefaultTable(const char *name,
00384                 const struct defaultEntry *table, int tableLen)
00385 {
00386     while (tableLen) {
00387         tableLen--;
00388         if (!strcmp(name, table[tableLen].name)) {
00389             return table[tableLen].defName;
00390         }
00391     }
00392 
00393     return name;
00394 }
00395 
00396 int rpmReadConfigFiles(const char * file, const char * target)
00397 {
00398 
00399     /* Preset target macros */
00400     rpmRebuildTargetVars(&target, NULL);
00401 
00402     /* Read the files */
00403     if (rpmReadRC(file)) return -1;
00404 
00405     /* Reset target macros */
00406     rpmRebuildTargetVars(&target, NULL);
00407 
00408     /* Finally set target platform */
00409     {   const char *cpu = rpmExpand("%{_target_cpu}", NULL);
00410         const char *os = rpmExpand("%{_target_os}", NULL);
00411         rpmSetMachine(cpu, os);
00412         free((void *)cpu);
00413         free((void *)os);
00414     }
00415 
00416     return 0;
00417 }
00418 
00419 static void setVarDefault(int var, const char *macroname, const char *val, const char *body)
00420 {
00421     if (var >= 0) {     /* XXX Dying ... */
00422         if (rpmGetVar(var)) return;
00423         rpmSetVar(var, val);
00424     }
00425     if (body == NULL)
00426         body = val;
00427     addMacro(NULL, macroname, NULL, body, RMIL_DEFAULT);
00428 }
00429 
00430 static void setPathDefault(int var, const char *macroname, const char *subdir)
00431 {
00432 
00433     if (var >= 0) {     /* XXX Dying ... */
00434         const char * topdir;
00435         char * fn;
00436 
00437         if (rpmGetVar(var)) return;
00438 
00439         topdir = rpmGetPath("%{_topdir}", NULL);
00440 
00441         fn = alloca(strlen(topdir) + strlen(subdir) + 2);
00442         strcpy(fn, topdir);
00443         if (fn[strlen(topdir) - 1] != '/')
00444             strcat(fn, "/");
00445         strcat(fn, subdir);
00446 
00447         rpmSetVar(var, fn);
00448         if (topdir)     free((void *)topdir);
00449     }
00450 
00451     if (macroname != NULL) {
00452 #define _TOPDIRMACRO    "%{_topdir}/"
00453         char *body = alloca(sizeof(_TOPDIRMACRO) + strlen(subdir));
00454         strcpy(body, _TOPDIRMACRO);
00455         strcat(body, subdir);
00456         addMacro(NULL, macroname, NULL, body, RMIL_DEFAULT);
00457 #undef _TOPDIRMACRO
00458     }
00459 }
00460 
00461 static const char *prescriptenviron = "\n\
00462 RPM_SOURCE_DIR=\"%{_sourcedir}\"\n\
00463 RPM_BUILD_DIR=\"%{_builddir}\"\n\
00464 RPM_OPT_FLAGS=\"%{optflags}\"\n\
00465 RPM_ARCH=\"%{_arch}\"\n\
00466 RPM_OS=\"%{_os}\"\n\
00467 export RPM_SOURCE_DIR RPM_BUILD_DIR RPM_OPT_FLAGS RPM_ARCH RPM_OS\n\
00468 RPM_DOC_DIR=\"%{_docdir}\"\n\
00469 export RPM_DOC_DIR\n\
00470 RPM_PACKAGE_NAME=\"%{name}\"\n\
00471 RPM_PACKAGE_VERSION=\"%{version}\"\n\
00472 RPM_PACKAGE_RELEASE=\"%{release}\"\n\
00473 export RPM_PACKAGE_NAME RPM_PACKAGE_VERSION RPM_PACKAGE_RELEASE\n\
00474 %{?buildroot:RPM_BUILD_ROOT=\"%{buildroot}\"\n\
00475 export RPM_BUILD_ROOT\n}\
00476 ";
00477 
00478 static void setDefaults(void) {
00479 
00480     addMacro(NULL, "_usr", NULL, "/usr", RMIL_DEFAULT);
00481     addMacro(NULL, "_var", NULL, "/var", RMIL_DEFAULT);
00482 
00483     addMacro(NULL, "_preScriptEnvironment",NULL, prescriptenviron,RMIL_DEFAULT);
00484 
00485     setVarDefault(-1,                   "_topdir",
00486                 "/usr/src/redhat",      "%{_usr}/src/redhat");
00487     setVarDefault(-1,                   "_tmppath",
00488                 "/var/tmp",             "%{_var}/tmp");
00489     setVarDefault(-1,                   "_dbpath",
00490                 "/var/lib/rpm",         "%{_var}/lib/rpm");
00491     setVarDefault(-1,                   "_defaultdocdir",
00492                 "/usr/doc",             "%{_usr}/doc");
00493 
00494     setVarDefault(-1,                   "_rpmfilename",
00495         "%%{ARCH}/%%{NAME}-%%{VERSION}-%%{RELEASE}.%%{ARCH}.rpm",NULL);
00496 
00497     setVarDefault(RPMVAR_OPTFLAGS,      "optflags",
00498                 "-O2",                  NULL);
00499     setVarDefault(-1,                   "sigtype",
00500                 "none",                 NULL);
00501     setVarDefault(-1,                   "_buildshell",
00502                 "/bin/sh",              NULL);
00503 
00504     setPathDefault(-1,                  "_builddir",    "BUILD");
00505     setPathDefault(-1,                  "_rpmdir",      "RPMS");
00506     setPathDefault(-1,                  "_srcrpmdir",   "SRPMS");
00507     setPathDefault(-1,                  "_sourcedir",   "SOURCES");
00508     setPathDefault(-1,                  "_specdir",     "SPECS");
00509 
00510 }
00511 
00512 int rpmReadRC(const char * rcfiles)
00513 {
00514     char *myrcfiles, *r, *re;
00515     int rc;
00516 
00517     if (!defaultsInitialized) {
00518         setDefaults();
00519         defaultsInitialized = 1;
00520     }
00521 
00522     if (rcfiles == NULL)
00523         rcfiles = defrcfiles;
00524 
00525     /* Read each file in rcfiles. */
00526     rc = 0;
00527     for (r = myrcfiles = xstrdup(rcfiles); *r != '\0'; r = re) {
00528         char fn[4096];
00529         FD_t fd;
00530 
00531         /* Get pointer to rest of files */
00532         for (re = r; (re = strchr(re, ':')) != NULL; re++) {
00533             if (!(re[1] == '/' && re[2] == '/'))
00534                 break;
00535         }
00536         if (re && *re == ':')
00537             *re++ = '\0';
00538         else
00539             re = r + strlen(r);
00540 
00541         /* Expand ~/ to $HOME/ */
00542         fn[0] = '\0';
00543         if (r[0] == '~' && r[1] == '/') {
00544             const char * home = getenv("HOME");
00545             if (home == NULL) {
00546             /* XXX Only /usr/lib/rpm/rpmrc must exist in default rcfiles list */
00547                 if (rcfiles == defrcfiles && myrcfiles != r)
00548                     continue;
00549                 rpmError(RPMERR_RPMRC, _("Cannot expand %s\n"), r);
00550                 rc = 1;
00551                 break;
00552             }
00553             if (strlen(home) > (sizeof(fn) - strlen(r))) {
00554                 rpmError(RPMERR_RPMRC, _("Cannot read %s, HOME is too large.\n"),
00555                                 r);
00556                 rc = 1;
00557                 break;
00558             }
00559             strcpy(fn, home);
00560             r++;
00561         }
00562         strncat(fn, r, sizeof(fn) - (strlen(fn) + 1));
00563         fn[sizeof(fn)-1] = '\0';
00564 
00565         /* Read another rcfile */
00566         fd = Fopen(fn, "r.fpio");
00567         if (fd == NULL || Ferror(fd)) {
00568             /* XXX Only /usr/lib/rpm/rpmrc must exist in default rcfiles list */
00569             if (rcfiles == defrcfiles && myrcfiles != r)
00570                 continue;
00571             rpmError(RPMERR_RPMRC, _("Unable to open %s for reading: %s.\n"),
00572                  fn, Fstrerror(fd));
00573             rc = 1;
00574             break;
00575         } else {
00576             rc = doReadRC(fd, fn);
00577         }
00578         if (rc) break;
00579     }
00580     if (myrcfiles)      free(myrcfiles);
00581     if (rc)
00582         return rc;
00583 
00584     rpmSetMachine(NULL, NULL);  /* XXX WTFO? Why bother? */
00585 
00586     {   const char *macrofiles;
00587         if ((macrofiles = rpmGetVar(RPMVAR_MACROFILES)) != NULL) {
00588             macrofiles = strdup(macrofiles);
00589             rpmInitMacros(NULL, macrofiles);
00590             free((void *)macrofiles);
00591         }
00592     }
00593 
00594     return rc;
00595 }
00596 
00597 static int doReadRC( /*@killref@*/ FD_t fd, const char * urlfn)
00598 {
00599     const char *s;
00600     char *se, *next;
00601     int linenum = 0;
00602     struct rpmOption searchOption, * option;
00603     int rc;
00604 
00605     /* XXX really need rc = Slurp(fd, const char * filename, char ** buf) */
00606   { off_t size = fdSize(fd);
00607     size_t nb = (size >= 0 ? size : (8*BUFSIZ - 2));
00608     if (nb == 0) {
00609         Fclose(fd);
00610         return 0;
00611     }
00612     next = alloca(nb + 2);
00613     next[0] = '\0';
00614     rc = Fread(next, sizeof(*next), nb, fd);
00615     if (Ferror(fd) || (size > 0 && rc != nb)) { /* XXX Feof(fd) */
00616         rpmError(RPMERR_RPMRC, _("Failed to read %s: %s.\n"), urlfn,
00617                  Fstrerror(fd));
00618         rc = 1;
00619     } else
00620         rc = 0;
00621     Fclose(fd);
00622     if (rc) return rc;
00623     next[nb] = '\n';
00624     next[nb + 1] = '\0';
00625   }
00626 
00627     while (*next) {
00628         linenum++;
00629 
00630         s = se = next;
00631 
00632         /* Find end-of-line. */
00633         while (*se && *se != '\n') se++;
00634         if (*se) *se++ = '\0';
00635         next = se;
00636 
00637         /* Trim leading spaces */
00638         while (*s && isspace(*s)) s++;
00639 
00640         /* We used to allow comments to begin anywhere, but not anymore. */
00641         if (*s == '#' || *s == '\0') continue;
00642 
00643         /* Find end-of-keyword. */
00644         se = (char *)s;
00645         while (*se && !isspace(*se) && *se != ':') se++;
00646 
00647         if (isspace(*se)) {
00648             *se++ = '\0';
00649             while (*se && isspace(*se) && *se != ':') se++;
00650         }
00651 
00652         if (*se != ':') {
00653             rpmError(RPMERR_RPMRC, _("missing ':' (found 0x%02x) at %s:%d\n"),
00654                      (0xff & *se), urlfn, linenum);
00655             return 1;
00656         }
00657         *se++ = '\0';   /* terminate keyword or option, point to value */
00658         while (*se && isspace(*se)) se++;
00659 
00660         /* Find keyword in table */
00661         searchOption.name = s;
00662         option = bsearch(&searchOption, optionTable, optionTableSize,
00663                          sizeof(struct rpmOption), optionCompare);
00664 
00665         if (option) {   /* For configuration variables  ... */
00666             const char *arch, *val, *fn;
00667 
00668             arch = val = fn = NULL;
00669             if (*se == '\0') {
00670                 rpmError(RPMERR_RPMRC, _("missing argument for %s at %s:%d\n"),
00671                       option->name, urlfn, linenum);
00672                 return 1;
00673             }
00674 
00675             switch (option->var) {
00676             case RPMVAR_INCLUDE:
00677               { FD_t fdinc;
00678 
00679                 s = se;
00680                 while (*se && !isspace(*se)) se++;
00681                 if (*se) *se++ = '\0';
00682 
00683                 rpmRebuildTargetVars(NULL, NULL);
00684 
00685                 fn = rpmGetPath(s, NULL);
00686                 if (fn == NULL || *fn == '\0') {
00687                     rpmError(RPMERR_RPMRC, _("%s expansion failed at %s:%d \"%s\"\n"),
00688                         option->name, urlfn, linenum, s);
00689                     if (fn) free((void *)fn);
00690                     return 1;
00691                     /*@notreached@*/
00692                 }
00693 
00694                 fdinc = Fopen(fn, "r.fpio");
00695                 if (fdinc == NULL || Ferror(fdinc)) {
00696                     rpmError(RPMERR_RPMRC, _("cannot open %s at %s:%d: %s\n"),
00697                         fn, urlfn, linenum, Fstrerror(fdinc));
00698                     rc = 1;
00699                 } else {
00700                     rc = doReadRC(fdinc, fn);
00701                 }
00702                 if (fn) free((void *)fn);
00703                 if (rc) return rc;
00704                 continue;       /* XXX don't save include value as var/macro */
00705               } /*@notreached@*/ break;
00706             case RPMVAR_MACROFILES:
00707                 fn = rpmGetPath(se, NULL);
00708                 if (fn == NULL || *fn == '\0') {
00709                     rpmError(RPMERR_RPMRC, _("%s expansion failed at %s:%d \"%s\"\n"),
00710                         option->name, urlfn, linenum, fn);
00711                     if (fn) free((void *)fn);
00712                     return 1;
00713                 }
00714                 se = (char *)fn;
00715                 break;
00716             case RPMVAR_PROVIDES:
00717               { char *t;
00718                 s = rpmGetVar(RPMVAR_PROVIDES);
00719                 if (s == NULL) s = "";
00720                 fn = t = xmalloc(strlen(s) + strlen(se) + 2);
00721                 while (*s) *t++ = *s++;
00722                 *t++ = ' ';
00723                 while (*se) *t++ = *se++;
00724                 *t++ = '\0';
00725                 se = (char *)fn;
00726               } break;
00727             default:
00728                 break;
00729             }
00730 
00731             if (option->archSpecific) {
00732                 arch = se;
00733                 while (*se && !isspace(*se)) se++;
00734                 if (*se == '\0') {
00735                     rpmError(RPMERR_RPMRC,
00736                                 _("missing architecture for %s at %s:%d\n"),
00737                                 option->name, urlfn, linenum);
00738                     return 1;
00739                 }
00740                 *se++ = '\0';
00741                 while (*se && isspace(*se)) se++;
00742                 if (*se == '\0') {
00743                     rpmError(RPMERR_RPMRC,
00744                                 _("missing argument for %s at %s:%d\n"),
00745                                 option->name, urlfn, linenum);
00746                     return 1;
00747                 }
00748             }
00749         
00750             val = se;
00751 
00752             /* Only add macros if appropriate for this arch */
00753             if (option->macroize &&
00754               (arch == NULL || !strcmp(arch, current[ARCH]))) {
00755                 char *n, *name;
00756                 n = name = xmalloc(strlen(option->name)+2);
00757                 if (option->localize)
00758                     *n++ = '_';
00759                 strcpy(n, option->name);
00760                 addMacro(NULL, name, NULL, val, RMIL_RPMRC);
00761                 free(name);
00762             }
00763             rpmSetVarArch(option->var, val, arch);
00764             if (fn) free((void *)fn);
00765 
00766         } else {        /* For arch/os compatibilty tables ... */
00767             int gotit;
00768             int i;
00769 
00770             gotit = 0;
00771 
00772             for (i = 0; i < RPM_MACHTABLE_COUNT; i++) {
00773                 if (!strncmp(tables[i].key, s, strlen(tables[i].key)))
00774                     break;
00775             }
00776 
00777             if (i < RPM_MACHTABLE_COUNT) {
00778                 const char *rest = s + strlen(tables[i].key);
00779                 if (*rest == '_') rest++;
00780 
00781                 if (!strcmp(rest, "compat")) {
00782                     if (machCompatCacheAdd(se, urlfn, linenum,
00783                                                 &tables[i].cache))
00784                         return 1;
00785                     gotit = 1;
00786                 } else if (tables[i].hasTranslate &&
00787                            !strcmp(rest, "translate")) {
00788                     if (addDefault(&tables[i].defaults,
00789                                    &tables[i].defaultsLength,
00790                                    se, urlfn, linenum))
00791                         return 1;
00792                     gotit = 1;
00793                 } else if (tables[i].hasCanon &&
00794                            !strcmp(rest, "canon")) {
00795                     if (addCanon(&tables[i].canons, &tables[i].canonsLength,
00796                                  se, urlfn, linenum))
00797                         return 1;
00798                     gotit = 1;
00799                 }
00800             }
00801 
00802             if (!gotit) {
00803                 rpmError(RPMERR_RPMRC, _("bad option '%s' at %s:%d\n"),
00804                             s, urlfn, linenum);
00805             }
00806         }
00807     }
00808 
00809     return 0;
00810 }
00811 
00812 #       if defined(__linux__) && defined(__i386__)
00813 #include <setjmp.h>
00814 #include <signal.h>
00815 
00816 /*
00817  * Generic CPUID function
00818  */
00819 static inline void cpuid(int op, int *eax, int *ebx, int *ecx, int *edx)
00820 {
00821 #ifdef PIC
00822         __asm__("pushl %%ebx; cpuid; movl %%ebx,%1; popl %%ebx"
00823                 : "=a"(*eax), "=g"(*ebx), "=&c"(*ecx), "=&d"(*edx)
00824                 : "a" (op));
00825 #else
00826         __asm__("cpuid"
00827                 : "=a" (*eax), "=b" (*ebx), "=c" (*ecx), "=d" (*edx)
00828                 : "a" (op));
00829 #endif
00830 
00831 }
00832 
00833 /*
00834  * CPUID functions returning a single datum
00835  */
00836 static inline unsigned int cpuid_eax(unsigned int op)
00837 {
00838         unsigned int val;
00839 
00840 #ifdef PIC
00841         __asm__("pushl %%ebx; cpuid; popl %%ebx"
00842                 : "=a" (val) : "a" (op) : "ecx", "edx");
00843 #else
00844         __asm__("cpuid"
00845                 : "=a" (val) : "a" (op) : "ebx", "ecx", "edx");
00846 #endif
00847         return val;
00848 }
00849 
00850 static inline unsigned int cpuid_ebx(unsigned int op)
00851 {
00852         unsigned int tmp, val;
00853 
00854 #ifdef PIC
00855         __asm__("pushl %%ebx; cpuid; movl %%ebx,%1; popl %%ebx"
00856                 : "=a" (tmp), "=g" (val) : "a" (op) : "ecx", "edx");
00857 #else
00858         __asm__("cpuid"
00859                 : "=a" (tmp), "=b" (val) : "a" (op) : "ecx", "edx");
00860 #endif
00861         return val;
00862 }
00863 
00864 static inline unsigned int cpuid_ecx(unsigned int op)
00865 {
00866         unsigned int tmp, val;
00867 #ifdef PIC
00868         __asm__("pushl %%ebx; cpuid; popl %%ebx"
00869                 : "=a" (tmp), "=c" (val) : "a" (op) : "edx");
00870 #else
00871         __asm__("cpuid"
00872                 : "=a" (tmp), "=c" (val) : "a" (op) : "ebx", "edx");
00873 #endif
00874         return val;
00875 
00876 }
00877 
00878 static inline unsigned int cpuid_edx(unsigned int op)
00879 {
00880         unsigned int tmp, val;
00881 #ifdef PIC
00882         __asm__("pushl %%ebx; cpuid; popl %%ebx"
00883                 : "=a" (tmp), "=d" (val) : "a" (op) : "ecx");
00884 #else
00885         __asm__("cpuid"
00886                 : "=a" (tmp), "=d" (val) : "a" (op) : "ebx", "ecx");
00887 #endif
00888         return val;
00889 
00890 }
00891 
00892 static sigjmp_buf jenv;
00893 
00894 static inline void model3(int _unused)
00895 {
00896         siglongjmp(jenv, 1);
00897 }
00898 
00899 static inline int RPMClass(void)
00900 {
00901         int cpu;
00902         unsigned int tfms, junk, cap;
00903         
00904         signal(SIGILL, model3);
00905         
00906         if(sigsetjmp(jenv, 1))
00907                 return 3;
00908                 
00909         if(cpuid_eax(0x000000000)==0)
00910                 return 4;
00911         cpuid(0x000000001, &tfms, &junk, &junk, &cap);
00912         
00913         cpu = (tfms>>8)&15;
00914         
00915         if(cpu < 6)
00916                 return cpu;
00917                 
00918         if(cap & (1<<15))
00919                 return 6;
00920                 
00921         return 5;
00922 }
00923 
00924 /* should only be called for model 6 CPU's */
00925 static int is_athlon(void) {
00926         unsigned int eax, ebx, ecx, edx;
00927         char vendor[16];
00928         int i;
00929         
00930         cpuid (0, &eax, &ebx, &ecx, &edx);
00931 
00932         /* If you care about space, you can just check ebx, ecx and edx directly
00933            instead of forming a string first and then doing a strcmp */
00934         memset(vendor, 0, sizeof(vendor));
00935         
00936         for (i=0; i<4; i++)
00937                 vendor[i] = (unsigned char) (ebx >>(8*i));
00938         for (i=0; i<4; i++)
00939                 vendor[4+i] = (unsigned char) (edx >>(8*i));
00940         for (i=0; i<4; i++)
00941                 vendor[8+i] = (unsigned char) (ecx >>(8*i));
00942                 
00943         if (strcmp(vendor, "AuthenticAMD") != 0)  
00944                 return 0;
00945 
00946         return 1;
00947 }
00948 
00949 #endif
00950 
00951 static void defaultMachine(/*@out@*/ const char ** arch, /*@out@*/ const char ** os)
00952 {
00953     static struct utsname un;
00954     static int gotDefaults = 0;
00955     char * chptr;
00956     const struct canonEntry * canon;
00957 
00958     if (!gotDefaults) {
00959         uname(&un);
00960 
00961 #if !defined(__linux__)
00962 #ifdef SNI
00963         /* USUALLY un.sysname on sinix does start with the word "SINIX"
00964          * let's be absolutely sure
00965          */
00966         sprintf(un.sysname,"SINIX");
00967 #endif
00968         if (!strcmp(un.sysname, "AIX")) {
00969             strcpy(un.machine, __power_pc() ? "ppc" : "rs6000");
00970             sprintf(un.sysname,"aix%s.%s",un.version,un.release);
00971         }
00972         else if (!strcmp(un.sysname, "SunOS")) {
00973             if (!strncmp(un.release,"4", 1)) /* SunOS 4.x */ {
00974                 int fd;
00975                 for (fd = 0;
00976                     (un.release[fd] != 0 && (fd < sizeof(un.release)));
00977                     fd++) {
00978                       if (!isdigit(un.release[fd]) && (un.release[fd] != '.')) {
00979                         un.release[fd] = 0;
00980                         break;
00981                       }
00982                     }
00983                     sprintf(un.sysname,"sunos%s",un.release);
00984             }
00985 
00986             else /* Solaris 2.x: n.x.x becomes n-3.x.x */
00987                 sprintf(un.sysname, "solaris%1d%s", atoi(un.release)-3,
00988                         un.release+1+(atoi(un.release)/10));
00989         }
00990         else if (!strcmp(un.sysname, "HP-UX"))
00991             /*make un.sysname look like hpux9.05 for example*/
00992             sprintf(un.sysname, "hpux%s", strpbrk(un.release,"123456789"));
00993         else if (!strcmp(un.sysname, "OSF1"))
00994             /*make un.sysname look like osf3.2 for example*/
00995             sprintf(un.sysname,"osf%s",strpbrk(un.release,"123456789"));
00996         else if (!strncmp(un.sysname, "IP", 2))
00997             un.sysname[2] = '\0';
00998         else if (!strncmp(un.sysname, "SINIX", 5)) {
00999             sprintf(un.sysname, "sinix%s",un.release);
01000             if (!strncmp(un.machine, "RM", 2))
01001                 sprintf(un.machine, "mips");
01002         }
01003         else if ((!strncmp(un.machine, "34", 2) ||
01004                 !strncmp(un.machine, "33", 2)) && \
01005                 !strncmp(un.release, "4.0", 3))
01006         {
01007             /* we are on ncr-sysv4 */
01008             char *prelid = NULL;
01009             FD_t fd;
01010             fd = Fopen("/etc/.relid", "r.fdio");
01011             if (!Ferror(fd)) {
01012                 chptr = (char *) xcalloc(1, 256);
01013                 if (chptr != NULL) {
01014                     int irelid = Fread(chptr, sizeof(*chptr), 256, fd);
01015                     Fclose(fd);
01016                     /* example: "112393 RELEASE 020200 Version 01 OS" */
01017                     if (irelid > 0) {
01018                         if ((prelid=strstr(chptr, "RELEASE "))){
01019                             prelid += strlen("RELEASE ")+1;
01020                             sprintf(un.sysname,"ncr-sysv4.%.*s",1,prelid);
01021                         }
01022                     }
01023                     free (chptr);
01024                 }
01025             }
01026             if (prelid == NULL) /* parsing /etc/.relid file failed? */
01027                 strcpy(un.sysname,"ncr-sysv4");
01028             /* wrong, just for now, find out how to look for i586 later*/
01029             strcpy(un.machine,"i486");
01030         }
01031 #endif  /* __linux__ */
01032 
01033         /* get rid of the hyphens in the sysname */
01034         for (chptr = un.machine; *chptr; chptr++)
01035             if (*chptr == '/') *chptr = '-';
01036 
01037 #       if defined(__MIPSEL__) || defined(__MIPSEL) || defined(_MIPSEL)
01038             /* little endian */
01039             strcpy(un.machine, "mipsel");
01040 #       elif defined(__MIPSEB__) || defined(__MIPSEB) || defined(_MIPSEB)
01041            /* big endian */
01042                 strcpy(un.machine, "mipseb");
01043 #       endif
01044 
01045 #       if defined(__hpux) && defined(_SC_CPU_VERSION)
01046         {
01047 #           if !defined(CPU_PA_RISC1_2)
01048 #                define CPU_PA_RISC1_2  0x211 /* HP PA-RISC1.2 */
01049 #           endif
01050 #           if !defined(CPU_PA_RISC2_0)
01051 #               define CPU_PA_RISC2_0  0x214 /* HP PA-RISC2.0 */
01052 #           endif
01053             int cpu_version = sysconf(_SC_CPU_VERSION);
01054 
01055 #           if defined(CPU_HP_MC68020)
01056                 if (cpu_version == CPU_HP_MC68020)
01057                     strcpy(un.machine, "m68k");
01058 #           endif
01059 #           if defined(CPU_HP_MC68030)
01060                 if (cpu_version == CPU_HP_MC68030)
01061                     strcpy(un.machine, "m68k");
01062 #           endif
01063 #           if defined(CPU_HP_MC68040)
01064                 if (cpu_version == CPU_HP_MC68040)
01065                     strcpy(un.machine, "m68k");
01066 #           endif
01067 
01068 #           if defined(CPU_PA_RISC1_0)
01069                 if (cpu_version == CPU_PA_RISC1_0)
01070                     strcpy(un.machine, "hppa1.0");
01071 #           endif
01072 #           if defined(CPU_PA_RISC1_1)
01073                 if (cpu_version == CPU_PA_RISC1_1)
01074                     strcpy(un.machine, "hppa1.1");
01075 #           endif
01076 #           if defined(CPU_PA_RISC1_2)
01077                 if (cpu_version == CPU_PA_RISC1_2)
01078                     strcpy(un.machine, "hppa1.2");
01079 #           endif
01080 #           if defined(CPU_PA_RISC2_0)
01081                 if (cpu_version == CPU_PA_RISC2_0)
01082                     strcpy(un.machine, "hppa2.0");
01083 #           endif
01084         }
01085 #       endif   /* hpux */
01086 
01087 #       if HAVE_PERSONALITY && defined(__linux__) && defined(__sparc__)
01088         if (!strcmp(un.machine, "sparc")) {
01089             #define PERS_LINUX          0x00000000
01090             #define PERS_LINUX_32BIT    0x00800000
01091             #define PERS_LINUX32        0x00000008
01092 
01093             extern int personality(unsigned long);
01094             int oldpers;
01095             
01096             oldpers = personality(PERS_LINUX_32BIT);
01097             if (oldpers != -1) {
01098                 if (personality(PERS_LINUX) != -1) {
01099                     uname(&un);
01100                     if (! strcmp(un.machine, "sparc64")) {
01101                         strcpy(un.machine, "sparcv9");
01102                         oldpers = PERS_LINUX32;
01103                     }
01104                 }
01105                 personality(oldpers);
01106             }
01107         }
01108 #       endif   /* sparc*-linux */
01109 
01110 #       if defined(__GNUC__) && defined(__alpha__)
01111         {
01112             unsigned long amask, implver;
01113             register long v0 __asm__("$0") = -1;
01114             __asm__ (".long 0x47e00c20" : "=r"(v0) : "0"(v0));
01115             amask = ~v0;
01116             __asm__ (".long 0x47e03d80" : "=r"(v0));
01117             implver = v0;
01118             switch (implver) {
01119             case 1:
01120                 switch (amask) {
01121                 case 0: strcpy(un.machine, "alphaev5"); break;
01122                 case 1: strcpy(un.machine, "alphaev56"); break;
01123                 case 0x101: strcpy(un.machine, "alphapca56"); break;
01124                 }
01125                 break;
01126             case 2:
01127                 switch (amask) {
01128                 case 0x303: strcpy(un.machine, "alphaev6"); break;
01129                 case 0x307: strcpy(un.machine, "alphaev67"); break;
01130                 }
01131                 break;
01132             }
01133         }
01134 #       endif
01135 
01136 #       if defined(__linux__) && defined(__i386__)
01137         {
01138             char class = (char) (RPMClass() | '0');
01139 
01140             if (class == '6' && is_athlon())
01141                 strcpy(un.machine, "athlon");
01142             else if (strchr("3456", un.machine[1]) && un.machine[1] != class)
01143                 un.machine[1] = class;
01144         }
01145 #       endif
01146 
01147         /* the uname() result goes through the arch_canon table */
01148         canon = lookupInCanonTable(un.machine,
01149                                    tables[RPM_MACHTABLE_INSTARCH].canons,
01150                                    tables[RPM_MACHTABLE_INSTARCH].canonsLength);
01151         if (canon)
01152             strcpy(un.machine, canon->short_name);
01153 
01154         canon = lookupInCanonTable(un.sysname,
01155                                    tables[RPM_MACHTABLE_INSTOS].canons,
01156                                    tables[RPM_MACHTABLE_INSTOS].canonsLength);
01157         if (canon)
01158             strcpy(un.sysname, canon->short_name);
01159         gotDefaults = 1;
01160     }
01161 
01162     if (arch) *arch = un.machine;
01163     if (os) *os = un.sysname;
01164 }
01165 
01166 static const char * rpmGetVarArch(int var, const char * arch) {
01167     struct rpmvarValue * next;
01168 
01169     if (!arch) arch = current[ARCH];
01170 
01171     if (arch) {
01172         next = &values[var];
01173         while (next) {
01174             if (next->arch && !strcmp(next->arch, arch)) return next->value;
01175             next = next->next;
01176         }
01177     }
01178 
01179     next = values + var;
01180     while (next && next->arch) next = next->next;
01181 
01182     return next ? next->value : NULL;
01183 }
01184 
01185 const char *rpmGetVar(int var)
01186 {
01187     return rpmGetVarArch(var, NULL);
01188 }
01189 
01190 /* this doesn't free the passed pointer! */
01191 static void freeRpmVar(struct rpmvarValue * orig) {
01192     struct rpmvarValue * next, * var = orig;
01193 
01194     while (var) {
01195         next = var->next;
01196         if (var->arch) {
01197             free((void *)var->arch);
01198             var->arch = NULL;
01199         }
01200         if (var->value) {
01201             free((void *)var->value);
01202             var->value = NULL;
01203         }
01204 
01205         if (var != orig) free(var);
01206         var = next;
01207     }
01208 }
01209 
01210 void rpmSetVar(int var, const char *val) {
01211     freeRpmVar(&values[var]);
01212     values[var].value = (val ? xstrdup(val) : NULL);
01213 }
01214 
01215 static void rpmSetVarArch(int var, const char * val, const char * arch) {
01216     struct rpmvarValue * next = values + var;
01217 
01218     if (next->value) {
01219         if (arch) {
01220             while (next->next) {
01221                 if (next->arch && !strcmp(next->arch, arch)) break;
01222                 next = next->next;
01223             }
01224         } else {
01225             while (next->next) {
01226                 if (!next->arch) break;
01227                 next = next->next;
01228             }
01229         }
01230 
01231         if (next->arch && arch && !strcmp(next->arch, arch)) {
01232             if (next->value) free((void *)next->value);
01233             if (next->arch) free((void *)next->arch);
01234         } else if (next->arch || arch) {
01235             next->next = xmalloc(sizeof(*next->next));
01236             next = next->next;
01237             next->value = NULL;
01238             next->arch = NULL;
01239             next->next = NULL;
01240         }
01241     }
01242 
01243     next->value = xstrdup(val);         /* XXX memory leak, hard to plug */
01244     next->arch = (arch ? xstrdup(arch) : NULL);
01245 }
01246 
01247 void rpmSetTables(int archTable, int osTable) {
01248     const char * arch, * os;
01249 
01250     defaultMachine(&arch, &os);
01251 
01252     if (currTables[ARCH] != archTable) {
01253         currTables[ARCH] = archTable;
01254         rebuildCompatTables(ARCH, arch);
01255     }
01256 
01257     if (currTables[OS] != osTable) {
01258         currTables[OS] = osTable;
01259         rebuildCompatTables(OS, os);
01260     }
01261 }
01262 
01263 int rpmMachineScore(int type, const char * name) {
01264     struct machEquivInfo * info = machEquivSearch(&tables[type].equiv, name);
01265     return (info != NULL ? info->score : 0);
01266 }
01267 
01268 void rpmGetMachine(const char **arch, const char **os)
01269 {
01270     if (arch)
01271         *arch = current[ARCH];
01272 
01273     if (os)
01274         *os = current[OS];
01275 }
01276 
01277 void rpmSetMachine(const char * arch, const char * os) {
01278     const char * host_cpu, * host_os;
01279 
01280     defaultMachine(&host_cpu, &host_os);
01281 
01282     if (arch == NULL) {
01283         arch = host_cpu;
01284         if (tables[currTables[ARCH]].hasTranslate)
01285             arch = lookupInDefaultTable(arch,
01286                             tables[currTables[ARCH]].defaults,
01287                             tables[currTables[ARCH]].defaultsLength);
01288     }
01289 
01290     if (os == NULL) {
01291         os = host_os;
01292         if (tables[currTables[OS]].hasTranslate)
01293             os = lookupInDefaultTable(os,
01294                             tables[currTables[OS]].defaults,
01295                             tables[currTables[OS]].defaultsLength);
01296     }
01297 
01298     if (!current[ARCH] || strcmp(arch, current[ARCH])) {
01299         if (current[ARCH]) free((void *)current[ARCH]);
01300         current[ARCH] = xstrdup(arch);
01301         rebuildCompatTables(ARCH, host_cpu);
01302     }
01303 
01304     if (!current[OS] || strcmp(os, current[OS])) {
01305         char * t = xstrdup(os);
01306         if (current[OS]) free((void *)current[OS]);
01307         /*
01308          * XXX Capitalizing the 'L' is needed to insure that old
01309          * XXX os-from-uname (e.g. "Linux") is compatible with the new
01310          * XXX os-from-platform (e.g "linux" from "sparc-*-linux").
01311          * XXX A copy of this string is embedded in headers and is
01312          * XXX used by rpmInstallPackage->{os,arch}Okay->rpmMachineScore->
01313          * XXX to verify correct arch/os from headers.
01314          */
01315         if (!strcmp(t, "linux"))
01316             *t = 'L';
01317         current[OS] = t;
01318         
01319         rebuildCompatTables(OS, host_os);
01320     }
01321 }
01322 
01323 static void rebuildCompatTables(int type, const char * name) {
01324     machFindEquivs(&tables[currTables[type]].cache,
01325                    &tables[currTables[type]].equiv,
01326                    name);
01327 }
01328 
01329 static void getMachineInfo(int type, /*@out@*/ const char ** name,
01330                         /*@out@*/int * num)
01331 {
01332     const struct canonEntry * canon;
01333     int which = currTables[type];
01334 
01335     /* use the normal canon tables, even if we're looking up build stuff */
01336     if (which >= 2) which -= 2;
01337 
01338     canon = lookupInCanonTable(current[type],
01339                                tables[which].canons,
01340                                tables[which].canonsLength);
01341 
01342     if (canon) {
01343         if (num) *num = canon->num;
01344         if (name) *name = canon->short_name;
01345     } else {
01346         if (num) *num = 255;
01347         if (name) *name = current[type];
01348 
01349         if (tables[currTables[type]].hasCanon) {
01350             rpmMessage(RPMMESS_WARNING, _("Unknown system: %s\n"), current[type]);
01351             rpmMessage(RPMMESS_WARNING, _("Please contact rpm-list@redhat.com\n"));
01352         }
01353     }
01354 }
01355 
01356 void rpmGetArchInfo(const char ** name, int * num) {
01357     getMachineInfo(ARCH, name, num);
01358 }
01359 
01360 void rpmGetOsInfo(const char ** name, int * num) {
01361     getMachineInfo(OS, name, num);
01362 }
01363 
01364 void rpmRebuildTargetVars(const char **buildtarget, const char ** canontarget)
01365 {
01366 
01367     char *ca = NULL, *co = NULL, *ct = NULL;
01368     int x;
01369 
01370     /* Rebuild the compat table to recalculate the current target arch.  */
01371 
01372     rpmSetMachine(NULL, NULL);
01373     rpmSetTables(RPM_MACHTABLE_INSTARCH, RPM_MACHTABLE_INSTOS);
01374     rpmSetTables(RPM_MACHTABLE_BUILDARCH, RPM_MACHTABLE_BUILDOS);
01375 
01376     if (buildtarget && *buildtarget) {
01377         char *c;
01378         /* Set arch and os from specified build target */
01379         ca = xstrdup(*buildtarget);
01380         if ((c = strchr(ca, '-')) != NULL) {
01381             *c++ = '\0';
01382             
01383             if ((co = strrchr(c, '-')) == NULL) {
01384                 co = c;
01385             } else {
01386                 if (!xstrcasecmp(co, "-gnu"))
01387                     *co = '\0';
01388                 if ((co = strrchr(c, '-')) == NULL)
01389                     co = c;
01390                 else
01391                     co++;
01392             }
01393             if (co != NULL) co = xstrdup(co);
01394         }
01395     } else {
01396         const char *a = NULL;
01397         const char *o = NULL;
01398         /* Set build target from rpm arch and os */
01399         rpmGetArchInfo(&a, NULL);
01400         ca = (a) ? xstrdup(a) : NULL;
01401         rpmGetOsInfo(&o, NULL);
01402         co = (o) ? xstrdup(o) : NULL;
01403     }
01404 
01405     /* If still not set, Set target arch/os from default uname(2) values */
01406     if (ca == NULL) {
01407         const char *a = NULL;
01408         defaultMachine(&a, NULL);
01409         ca = (a) ? xstrdup(a) : NULL;
01410     }
01411     for (x = 0; ca[x]; x++)
01412         ca[x] = tolower(ca[x]);
01413 
01414     if (co == NULL) {
01415         const char *o = NULL;
01416         defaultMachine(NULL, &o);
01417         co = (o) ? xstrdup(o) : NULL;
01418     }
01419     for (x = 0; co[x]; x++)
01420         co[x] = tolower(co[x]);
01421 
01422     /* XXX For now, set canonical target to arch-os */
01423     if (ct == NULL) {
01424         ct = xmalloc(strlen(ca) + sizeof("-") + strlen(co));
01425         sprintf(ct, "%s-%s", ca, co);
01426     }
01427 
01428 /*
01429  * XXX All this macro pokery/jiggery could be achieved by doing a delayed
01430  *      rpmInitMacros(NULL, PER-PLATFORM-MACRO-FILE-NAMES);
01431  */
01432     delMacro(NULL, "_target");
01433     addMacro(NULL, "_target", NULL, ct, RMIL_RPMRC);
01434     delMacro(NULL, "_target_cpu");
01435     addMacro(NULL, "_target_cpu", NULL, ca, RMIL_RPMRC);
01436     delMacro(NULL, "_target_os");
01437     addMacro(NULL, "_target_os", NULL, co, RMIL_RPMRC);
01438 /*
01439  * XXX Make sure that per-arch optflags is initialized correctly.
01440  */
01441   { const char *optflags = rpmGetVarArch(RPMVAR_OPTFLAGS, ca);
01442     if (optflags != NULL) {
01443         delMacro(NULL, "optflags");
01444         addMacro(NULL, "optflags", NULL, optflags, RMIL_RPMRC);
01445     }
01446   }
01447 
01448     if (canontarget)
01449         *canontarget = ct;
01450     else
01451         free(ct);
01452     free(ca);
01453     free(co);
01454 }
01455 
01456 void rpmFreeRpmrc(void)
01457 {
01458     int i, j, k;
01459 
01460     for (i = 0; i < RPM_MACHTABLE_COUNT; i++) {
01461         struct tableType *t;
01462         t = tables + i;
01463         if (t->equiv.list) {
01464             for (j = 0; j < t->equiv.count; j++) {
01465                 if (t->equiv.list[j].name) free((void *)t->equiv.list[j].name);
01466             }
01467             free((void *)t->equiv.list);
01468             t->equiv.list = NULL;
01469             t->equiv.count = 0;
01470         }
01471         if (t->cache.cache) {
01472             for (j = 0; j < t->cache.size; j++) {
01473                 struct machCacheEntry *e;
01474                 e = t->cache.cache + j;
01475                 if (e == NULL)  continue;
01476                 if (e->name)            free((void *)e->name);
01477                 if (e->equivs) {
01478                     for (k = 0; k < e->count; k++) {
01479                         if (e->equivs[k])       free((void *)e->equivs[k]);
01480                     }
01481                     free((void *)e->equivs);
01482                 }
01483             }
01484             free((void *)t->cache.cache);
01485             t->cache.cache = NULL;
01486             t->cache.size = 0;
01487         }
01488         if (t->defaults) {
01489             for (j = 0; j < t->defaultsLength; j++) {
01490                 if (t->defaults[j].name) free((void *)t->defaults[j].name);
01491                 if (t->defaults[j].defName) free((void *)t->defaults[j].defName);
01492             }
01493             free((void *)t->defaults);
01494             t->defaults = NULL;
01495             t->defaultsLength = 0;
01496         }
01497         if (t->canons) {
01498             for (j = 0; j < t->canonsLength; j++) {
01499                 if (t->canons[j].name)  free((void *)t->canons[j].name);
01500                 if (t->canons[j].short_name)    free((void *)t->canons[j].short_name);
01501             }
01502             free((void *)t->canons);
01503             t->canons = NULL;
01504             t->canonsLength = 0;
01505         }
01506     }
01507 
01508     for (i = 0; i < RPMVAR_NUM; i++) {
01509         struct rpmvarValue *this;
01510         while ((this = values[i].next) != NULL) {
01511             values[i].next = this->next;
01512             if (this->value)    free((void *)this->value);
01513             if (this->arch)     free((void *)this->arch);
01514             free((void *)this);
01515         }
01516         if (values[i].value)
01517             free((void *)values[i].value);
01518         values[i].value = NULL;
01519         if (values[i].arch)
01520             free((void *)values[i].arch);
01521         values[i].arch = NULL;
01522     }
01523     if (current[OS])
01524         free((void *)current[OS]);
01525     current[OS] = NULL;
01526     if (current[ARCH])
01527         free((void *)current[ARCH]);
01528     current[ARCH] = NULL;
01529     defaultsInitialized = 0;
01530     return;
01531 }
01532 
01533 int rpmShowRC(FILE *fp)
01534 {
01535     struct rpmOption *opt;
01536     int i;
01537     struct machEquivTable * equivTable;
01538 
01539     /* the caller may set the build arch which should be printed here */
01540     fprintf(fp, "ARCHITECTURE AND OS:\n");
01541     fprintf(fp, "build arch            : %s\n", current[ARCH]);
01542 
01543     fprintf(fp, "compatible build archs:");
01544     equivTable = &tables[RPM_MACHTABLE_BUILDARCH].equiv;
01545     for (i = 0; i < equivTable->count; i++)
01546         fprintf(fp," %s", equivTable->list[i].name);
01547     fprintf(fp, "\n");
01548 
01549     fprintf(fp, "build os              : %s\n", current[OS]);
01550 
01551     fprintf(fp, "compatible build os's :");
01552     equivTable = &tables[RPM_MACHTABLE_BUILDOS].equiv;
01553     for (i = 0; i < equivTable->count; i++)
01554         fprintf(fp," %s", equivTable->list[i].name);
01555     fprintf(fp, "\n");
01556 
01557     rpmSetTables(RPM_MACHTABLE_INSTARCH, RPM_MACHTABLE_INSTOS);
01558     rpmSetMachine(NULL, NULL);  /* XXX WTFO? Why bother? */
01559 
01560     fprintf(fp, "install arch          : %s\n", current[ARCH]);
01561     fprintf(fp, "install os            : %s\n", current[OS]);
01562 
01563     fprintf(fp, "compatible archs      :");
01564     equivTable = &tables[RPM_MACHTABLE_INSTARCH].equiv;
01565     for (i = 0; i < equivTable->count; i++)
01566         fprintf(fp," %s", equivTable->list[i].name);
01567     fprintf(fp, "\n");
01568 
01569     fprintf(fp, "compatible os's       :");
01570     equivTable = &tables[RPM_MACHTABLE_INSTOS].equiv;
01571     for (i = 0; i < equivTable->count; i++)
01572         fprintf(fp," %s", equivTable->list[i].name);
01573     fprintf(fp, "\n");
01574 
01575     fprintf(fp, "\nRPMRC VALUES:\n");
01576     for (i = 0, opt = optionTable; i < optionTableSize; i++, opt++) {
01577         const char *s = rpmGetVar(opt->var);
01578         if (s != NULL || rpmIsVerbose())
01579             fprintf(fp, "%-21s : %s\n", opt->name, s ? s : "(not set)");
01580     }
01581     fprintf(fp, "\n");
01582 
01583     fprintf(fp, "Features supported by rpmlib:\n");
01584     rpmShowRpmlibProvides(fp);
01585     fprintf(fp, "\n");
01586 
01587     rpmDumpMacroTable(NULL, fp);
01588 
01589     return 0;
01590 }

Generated at Thu Apr 19 15:29:44 2001 for rpm by doxygen1.2.6-20010408 written by Dimitri van Heesch, © 1997-2001