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

Generated at Sun Apr 8 18:43:00 2001 for rpm by doxygen1.2.3 written by Dimitri van Heesch, © 1997-2000