00001
00002 #include "system.h"
00003
00004 #include <stdarg.h>
00005
00006 #if defined(__linux__) && defined(__powerpc__)
00007 #include <setjmp.h>
00008 #endif
00009
00010 #if HAVE_SYS_SYSTEMCFG_H
00011 #include <sys/systemcfg.h>
00012 #else
00013 #define __power_pc() 0
00014 #endif
00015
00016 #include <rpmlib.h>
00017 #include <rpmmacro.h>
00018
00019 #include "misc.h"
00020 #include "debug.h"
00021
00022
00023
00024
00025 static const char *defrcfiles = LIBRPMRC_FILENAME ":/etc/rpmrc:~/.rpmrc";
00026
00027
00028 const char * macrofiles = MACROFILES;
00029
00030 typedef const char * cptr_t;
00031
00032 typedef struct machCacheEntry_s {
00033 const char * name;
00034 int count;
00035 cptr_t * equivs;
00036 int visited;
00037 } * machCacheEntry;
00038
00039 typedef struct machCache_s {
00040 machCacheEntry cache;
00041 int size;
00042 } * machCache;
00043
00044 typedef struct machEquivInfo_s {
00045 const char * name;
00046 int score;
00047 } * machEquivInfo;
00048
00049 typedef struct machEquivTable_s {
00050 int count;
00051 machEquivInfo list;
00052 } * machEquivTable;
00053
00054 struct rpmvarValue {
00055 const char * value;
00056
00057 const char * arch;
00058 struct rpmvarValue * next;
00059 };
00060
00061 struct rpmOption {
00062 const char * name;
00063 int var;
00064 int archSpecific;
00065 int required;
00066 int macroize;
00067 int localize;
00068 struct rpmOptionValue * value;
00069 };
00070
00071 typedef struct defaultEntry_s {
00072 const char * name;
00073 const char * defName;
00074 } * defaultEntry;
00075
00076 typedef struct canonEntry_s {
00077 const char * name;
00078 const char * short_name;
00079 short num;
00080 } * canonEntry;
00081
00082
00083
00084
00085
00086 typedef struct tableType_s {
00087 const char * const key;
00088 const int hasCanon;
00089 const int hasTranslate;
00090 struct machEquivTable_s equiv;
00091 struct machCache_s cache;
00092 defaultEntry defaults;
00093 canonEntry canons;
00094 int defaultsLength;
00095 int canonsLength;
00096 } * tableType;
00097
00098
00099
00100 static struct tableType_s tables[RPM_MACHTABLE_COUNT] = {
00101 { "arch", 1, 0 },
00102 { "os", 1, 0 },
00103 { "buildarch", 0, 1 },
00104 { "buildos", 0, 1 }
00105 };
00106
00107
00108
00109
00110
00111 static struct rpmOption optionTable[] = {
00112 { "include", RPMVAR_INCLUDE, 0, 1, 0, 2 },
00113 { "macrofiles", RPMVAR_MACROFILES, 0, 0, 0, 1 },
00114 { "optflags", RPMVAR_OPTFLAGS, 1, 0, 1, 0 },
00115 { "provides", RPMVAR_PROVIDES, 0, 0, 0, 0 },
00116 };
00117
00118
00119
00120 static int optionTableSize = sizeof(optionTable) / sizeof(*optionTable);
00121
00122 #define OS 0
00123 #define ARCH 1
00124
00125
00126 static cptr_t current[2];
00127
00128
00129 static int currTables[2] = { RPM_MACHTABLE_INSTOS, RPM_MACHTABLE_INSTARCH };
00130
00131
00132 static struct rpmvarValue values[RPMVAR_NUM];
00133
00134
00135 static int defaultsInitialized = 0;
00136
00137
00138 static int doReadRC( FD_t fd, const char * urlfn)
00139
00140
00141 ;
00142
00143 static void rpmSetVarArch(int var, const char * val,
00144 const char * arch)
00145
00146 ;
00147
00148 static void rebuildCompatTables(int type, const char * name)
00149
00150 ;
00151
00152 static void rpmRebuildTargetVars( const char **target, const char ** canontarget)
00153
00154
00155 ;
00156
00157 static int optionCompare(const void * a, const void * b)
00158
00159 {
00160 return xstrcasecmp(((struct rpmOption *) a)->name,
00161 ((struct rpmOption *) b)->name);
00162 }
00163
00164 static machCacheEntry
00165 machCacheFindEntry(const machCache cache, const char * key)
00166
00167 {
00168 int i;
00169
00170 for (i = 0; i < cache->size; i++)
00171 if (!strcmp(cache->cache[i].name, key)) return cache->cache + i;
00172
00173 return NULL;
00174 }
00175
00176 static int machCompatCacheAdd(char * name, const char * fn, int linenum,
00177 machCache cache)
00178
00179
00180 {
00181 machCacheEntry entry = NULL;
00182 char * chptr;
00183 char * equivs;
00184 int delEntry = 0;
00185 int i;
00186
00187 while (*name && xisspace(*name)) name++;
00188
00189 chptr = name;
00190 while (*chptr && *chptr != ':') chptr++;
00191 if (!*chptr) {
00192 rpmError(RPMERR_RPMRC, _("missing second ':' at %s:%d\n"), fn, linenum);
00193 return 1;
00194 } else if (chptr == name) {
00195 rpmError(RPMERR_RPMRC, _("missing architecture name at %s:%d\n"), fn,
00196 linenum);
00197 return 1;
00198 }
00199
00200 while (*chptr == ':' || xisspace(*chptr)) chptr--;
00201 *(++chptr) = '\0';
00202 equivs = chptr + 1;
00203 while (*equivs && xisspace(*equivs)) equivs++;
00204 if (!*equivs) {
00205 delEntry = 1;
00206 }
00207
00208 if (cache->size) {
00209 entry = machCacheFindEntry(cache, name);
00210 if (entry) {
00211 for (i = 0; i < entry->count; i++)
00212 entry->equivs[i] = _free(entry->equivs[i]);
00213 entry->equivs = _free(entry->equivs);
00214 entry->count = 0;
00215 }
00216 }
00217
00218 if (!entry) {
00219 cache->cache = xrealloc(cache->cache,
00220 (cache->size + 1) * sizeof(*cache->cache));
00221 entry = cache->cache + cache->size++;
00222 entry->name = xstrdup(name);
00223 entry->count = 0;
00224 entry->visited = 0;
00225 }
00226
00227 if (delEntry) return 0;
00228
00229 while ((chptr = strtok(equivs, " ")) != NULL) {
00230 equivs = NULL;
00231 if (chptr[0] == '\0')
00232 continue;
00233 if (entry->count)
00234 entry->equivs = xrealloc(entry->equivs, sizeof(*entry->equivs)
00235 * (entry->count + 1));
00236 else
00237 entry->equivs = xmalloc(sizeof(*entry->equivs));
00238
00239 entry->equivs[entry->count] = xstrdup(chptr);
00240 entry->count++;
00241 }
00242
00243 return 0;
00244 }
00245
00246 static machEquivInfo
00247 machEquivSearch(const machEquivTable table, const char * name)
00248
00249 {
00250 int i;
00251
00252 for (i = 0; i < table->count; i++)
00253 if (!xstrcasecmp(table->list[i].name, name))
00254 return table->list + i;
00255
00256 return NULL;
00257 }
00258
00259 static void machAddEquiv(machEquivTable table, const char * name,
00260 int distance)
00261
00262 {
00263 machEquivInfo equiv;
00264
00265 equiv = machEquivSearch(table, name);
00266 if (!equiv) {
00267 if (table->count)
00268 table->list = xrealloc(table->list, (table->count + 1)
00269 * sizeof(*table->list));
00270 else
00271 table->list = xmalloc(sizeof(*table->list));
00272
00273 table->list[table->count].name = xstrdup(name);
00274 table->list[table->count++].score = distance;
00275 }
00276 }
00277
00278 static void machCacheEntryVisit(machCache cache,
00279 machEquivTable table, const char * name, int distance)
00280
00281 {
00282 machCacheEntry entry;
00283 int i;
00284
00285 entry = machCacheFindEntry(cache, name);
00286 if (!entry || entry->visited) return;
00287
00288 entry->visited = 1;
00289
00290 for (i = 0; i < entry->count; i++) {
00291 machAddEquiv(table, entry->equivs[i], distance);
00292 }
00293
00294 for (i = 0; i < entry->count; i++) {
00295 machCacheEntryVisit(cache, table, entry->equivs[i], distance + 1);
00296 }
00297 }
00298
00299 static void machFindEquivs(machCache cache, machEquivTable table,
00300 const char * key)
00301
00302 {
00303 int i;
00304
00305 for (i = 0; i < cache->size; i++)
00306 cache->cache[i].visited = 0;
00307
00308 while (table->count > 0) {
00309 --table->count;
00310 table->list[table->count].name = _free(table->list[table->count].name);
00311 }
00312 table->count = 0;
00313 table->list = _free(table->list);
00314
00315
00316
00317
00318
00319
00320
00321 machAddEquiv(table, key, 1);
00322 machCacheEntryVisit(cache, table, key, 2);
00323 return;
00324
00325 }
00326
00327 static int addCanon(canonEntry * table, int * tableLen, char * line,
00328 const char * fn, int lineNum)
00329
00330
00331 {
00332 canonEntry t;
00333 char *s, *s1;
00334 const char * tname;
00335 const char * tshort_name;
00336 int tnum;
00337
00338 (*tableLen) += 2;
00339
00340 *table = xrealloc(*table, sizeof(**table) * (*tableLen));
00341
00342
00343 t = & ((*table)[*tableLen - 2]);
00344
00345 tname = strtok(line, ": \t");
00346 tshort_name = strtok(NULL, " \t");
00347 s = strtok(NULL, " \t");
00348 if (! (tname && tshort_name && s)) {
00349 rpmError(RPMERR_RPMRC, _("Incomplete data line at %s:%d\n"),
00350 fn, lineNum);
00351 return RPMERR_RPMRC;
00352 }
00353 if (strtok(NULL, " \t")) {
00354 rpmError(RPMERR_RPMRC, _("Too many args in data line at %s:%d\n"),
00355 fn, lineNum);
00356 return RPMERR_RPMRC;
00357 }
00358
00359
00360 tnum = strtoul(s, &s1, 10);
00361 if ((*s1) || (s1 == s) || (tnum == ULONG_MAX)) {
00362 rpmError(RPMERR_RPMRC, _("Bad arch/os number: %s (%s:%d)\n"), s,
00363 fn, lineNum);
00364 return(RPMERR_RPMRC);
00365 }
00366
00367
00368 t[0].name = xstrdup(tname);
00369 t[0].short_name = (tshort_name ? xstrdup(tshort_name) : xstrdup(""));
00370 t[0].num = tnum;
00371
00372
00373
00374 t[1].name = (tshort_name ? xstrdup(tshort_name) : xstrdup(""));
00375 t[1].short_name = (tshort_name ? xstrdup(tshort_name) : xstrdup(""));
00376 t[1].num = tnum;
00377
00378 return 0;
00379 }
00380
00381 static int addDefault(defaultEntry * table, int * tableLen, char * line,
00382 const char * fn, int lineNum)
00383
00384
00385 {
00386 defaultEntry t;
00387
00388 (*tableLen)++;
00389
00390 *table = xrealloc(*table, sizeof(**table) * (*tableLen));
00391
00392
00393 t = & ((*table)[*tableLen - 1]);
00394
00395
00396 t->name = strtok(line, ": \t");
00397 t->defName = strtok(NULL, " \t");
00398 if (! (t->name && t->defName)) {
00399 rpmError(RPMERR_RPMRC, _("Incomplete default line at %s:%d\n"),
00400 fn, lineNum);
00401 return RPMERR_RPMRC;
00402 }
00403 if (strtok(NULL, " \t")) {
00404 rpmError(RPMERR_RPMRC, _("Too many args in default line at %s:%d\n"),
00405 fn, lineNum);
00406 return RPMERR_RPMRC;
00407 }
00408
00409 t->name = xstrdup(t->name);
00410 t->defName = (t->defName ? xstrdup(t->defName) : NULL);
00411
00412
00413 return 0;
00414 }
00415
00416 static const canonEntry lookupInCanonTable(const char * name,
00417 const canonEntry table, int tableLen)
00418
00419 {
00420 while (tableLen) {
00421 tableLen--;
00422 if (strcmp(name, table[tableLen].name))
00423 continue;
00424
00425 return &(table[tableLen]);
00426
00427 }
00428
00429 return NULL;
00430 }
00431
00432 static
00433 const char * lookupInDefaultTable(const char * name,
00434 const defaultEntry table, int tableLen)
00435
00436 {
00437 while (tableLen) {
00438 tableLen--;
00439 if (table[tableLen].name && !strcmp(name, table[tableLen].name))
00440 return table[tableLen].defName;
00441 }
00442
00443 return name;
00444 }
00445
00446 static void setVarDefault(int var, const char * macroname, const char * val,
00447 const char * body)
00448
00449
00450
00451 {
00452 if (var >= 0) {
00453 if (rpmGetVar(var)) return;
00454 rpmSetVar(var, val);
00455 }
00456 if (body == NULL)
00457 body = val;
00458 addMacro(NULL, macroname, NULL, body, RMIL_DEFAULT);
00459 }
00460
00461 static void setPathDefault(int var, const char * macroname, const char * subdir)
00462
00463
00464
00465 {
00466
00467 if (var >= 0) {
00468 const char * topdir;
00469 char * fn;
00470
00471 if (rpmGetVar(var)) return;
00472
00473 topdir = rpmGetPath("%{_topdir}", NULL);
00474
00475 fn = alloca(strlen(topdir) + strlen(subdir) + 2);
00476 strcpy(fn, topdir);
00477 if (fn[strlen(topdir) - 1] != '/')
00478 strcat(fn, "/");
00479 strcat(fn, subdir);
00480
00481 rpmSetVar(var, fn);
00482 topdir = _free(topdir);
00483 }
00484
00485 if (macroname != NULL) {
00486 #define _TOPDIRMACRO "%{_topdir}/"
00487 char *body = alloca(sizeof(_TOPDIRMACRO) + strlen(subdir));
00488 strcpy(body, _TOPDIRMACRO);
00489 strcat(body, subdir);
00490 addMacro(NULL, macroname, NULL, body, RMIL_DEFAULT);
00491 #undef _TOPDIRMACRO
00492 }
00493 }
00494
00495
00496 static const char * prescriptenviron = "\n\
00497 RPM_SOURCE_DIR=\"%{_sourcedir}\"\n\
00498 RPM_BUILD_DIR=\"%{_builddir}\"\n\
00499 RPM_OPT_FLAGS=\"%{optflags}\"\n\
00500 RPM_ARCH=\"%{_arch}\"\n\
00501 RPM_OS=\"%{_os}\"\n\
00502 export RPM_SOURCE_DIR RPM_BUILD_DIR RPM_OPT_FLAGS RPM_ARCH RPM_OS\n\
00503 RPM_DOC_DIR=\"%{_docdir}\"\n\
00504 export RPM_DOC_DIR\n\
00505 RPM_PACKAGE_NAME=\"%{name}\"\n\
00506 RPM_PACKAGE_VERSION=\"%{version}\"\n\
00507 RPM_PACKAGE_RELEASE=\"%{release}\"\n\
00508 export RPM_PACKAGE_NAME RPM_PACKAGE_VERSION RPM_PACKAGE_RELEASE\n\
00509 %{?buildroot:RPM_BUILD_ROOT=\"%{buildroot}\"\n\
00510 export RPM_BUILD_ROOT\n}\
00511 ";
00512
00513 static void setDefaults(void)
00514
00515
00516
00517 {
00518
00519 addMacro(NULL, "_usr", NULL, "/usr", RMIL_DEFAULT);
00520 addMacro(NULL, "_var", NULL, "/var", RMIL_DEFAULT);
00521
00522 addMacro(NULL, "_preScriptEnvironment",NULL, prescriptenviron,RMIL_DEFAULT);
00523
00524 setVarDefault(-1, "_topdir",
00525 "/usr/src/redhat", "%{_usr}/src/redhat");
00526 setVarDefault(-1, "_tmppath",
00527 "/var/tmp", "%{_var}/tmp");
00528 setVarDefault(-1, "_dbpath",
00529 "/var/lib/rpm", "%{_var}/lib/rpm");
00530 setVarDefault(-1, "_defaultdocdir",
00531 "/usr/doc", "%{_usr}/doc");
00532
00533 setVarDefault(-1, "_rpmfilename",
00534 "%%{ARCH}/%%{NAME}-%%{VERSION}-%%{RELEASE}.%%{ARCH}.rpm",NULL);
00535
00536 setVarDefault(RPMVAR_OPTFLAGS, "optflags",
00537 "-O2", NULL);
00538 setVarDefault(-1, "sigtype",
00539 "none", NULL);
00540 setVarDefault(-1, "_buildshell",
00541 "/bin/sh", NULL);
00542
00543 setPathDefault(-1, "_builddir", "BUILD");
00544 setPathDefault(-1, "_rpmdir", "RPMS");
00545 setPathDefault(-1, "_srcrpmdir", "SRPMS");
00546 setPathDefault(-1, "_sourcedir", "SOURCES");
00547 setPathDefault(-1, "_specdir", "SPECS");
00548
00549 }
00550
00551
00552 static int doReadRC( FD_t fd, const char * urlfn)
00553
00554
00555
00556 {
00557 const char *s;
00558 char *se, *next;
00559 int linenum = 0;
00560 struct rpmOption searchOption, * option;
00561 int rc;
00562
00563
00564 { off_t size = fdSize(fd);
00565 size_t nb = (size >= 0 ? size : (8*BUFSIZ - 2));
00566 if (nb == 0) {
00567 (void) Fclose(fd);
00568 return 0;
00569 }
00570 next = alloca(nb + 2);
00571 next[0] = '\0';
00572 rc = Fread(next, sizeof(*next), nb, fd);
00573 if (Ferror(fd) || (size > 0 && rc != nb)) {
00574 rpmError(RPMERR_RPMRC, _("Failed to read %s: %s.\n"), urlfn,
00575 Fstrerror(fd));
00576 rc = 1;
00577 } else
00578 rc = 0;
00579 (void) Fclose(fd);
00580 if (rc) return rc;
00581 next[nb] = '\n';
00582 next[nb + 1] = '\0';
00583 }
00584
00585
00586 while (*next != '\0') {
00587 linenum++;
00588
00589 s = se = next;
00590
00591
00592 while (*se && *se != '\n') se++;
00593 if (*se != '\0') *se++ = '\0';
00594 next = se;
00595
00596
00597 while (*s && xisspace(*s)) s++;
00598
00599
00600 if (*s == '#' || *s == '\0') continue;
00601
00602
00603 se = (char *)s;
00604 while (*se && !xisspace(*se) && *se != ':') se++;
00605
00606 if (xisspace(*se)) {
00607 *se++ = '\0';
00608 while (*se && xisspace(*se) && *se != ':') se++;
00609 }
00610
00611 if (*se != ':') {
00612 rpmError(RPMERR_RPMRC, _("missing ':' (found 0x%02x) at %s:%d\n"),
00613 (unsigned)(0xff & *se), urlfn, linenum);
00614 return 1;
00615 }
00616 *se++ = '\0';
00617 while (*se && xisspace(*se)) se++;
00618
00619
00620 searchOption.name = s;
00621 option = bsearch(&searchOption, optionTable, optionTableSize,
00622 sizeof(optionTable[0]), optionCompare);
00623
00624 if (option) {
00625 const char *arch, *val, *fn;
00626
00627 arch = val = fn = NULL;
00628 if (*se == '\0') {
00629 rpmError(RPMERR_RPMRC, _("missing argument for %s at %s:%d\n"),
00630 option->name, urlfn, linenum);
00631 return 1;
00632 }
00633
00634 switch (option->var) {
00635 case RPMVAR_INCLUDE:
00636 { FD_t fdinc;
00637
00638 s = se;
00639 while (*se && !xisspace(*se)) se++;
00640 if (*se != '\0') *se++ = '\0';
00641
00642 rpmRebuildTargetVars(NULL, NULL);
00643
00644 fn = rpmGetPath(s, NULL);
00645 if (fn == NULL || *fn == '\0') {
00646 rpmError(RPMERR_RPMRC, _("%s expansion failed at %s:%d \"%s\"\n"),
00647 option->name, urlfn, linenum, s);
00648 fn = _free(fn);
00649 return 1;
00650
00651 }
00652
00653 fdinc = Fopen(fn, "r.fpio");
00654 if (fdinc == NULL || Ferror(fdinc)) {
00655 rpmError(RPMERR_RPMRC, _("cannot open %s at %s:%d: %s\n"),
00656 fn, urlfn, linenum, Fstrerror(fdinc));
00657 rc = 1;
00658 } else {
00659 rc = doReadRC(fdinc, fn);
00660 }
00661 fn = _free(fn);
00662 if (rc) return rc;
00663 continue;
00664 } break;
00665 case RPMVAR_MACROFILES:
00666 fn = rpmGetPath(se, NULL);
00667 if (fn == NULL || *fn == '\0') {
00668 rpmError(RPMERR_RPMRC, _("%s expansion failed at %s:%d \"%s\"\n"),
00669 option->name, urlfn, linenum, fn);
00670 fn = _free(fn);
00671 return 1;
00672 }
00673 se = (char *)fn;
00674 break;
00675 case RPMVAR_PROVIDES:
00676 { char *t;
00677 s = rpmGetVar(RPMVAR_PROVIDES);
00678 if (s == NULL) s = "";
00679 fn = t = xmalloc(strlen(s) + strlen(se) + 2);
00680 while (*s != '\0') *t++ = *s++;
00681 *t++ = ' ';
00682 while (*se != '\0') *t++ = *se++;
00683 *t++ = '\0';
00684 se = (char *)fn;
00685 } break;
00686 default:
00687 break;
00688 }
00689
00690 if (option->archSpecific) {
00691 arch = se;
00692 while (*se && !xisspace(*se)) se++;
00693 if (*se == '\0') {
00694 rpmError(RPMERR_RPMRC,
00695 _("missing architecture for %s at %s:%d\n"),
00696 option->name, urlfn, linenum);
00697 return 1;
00698 }
00699 *se++ = '\0';
00700 while (*se && xisspace(*se)) se++;
00701 if (*se == '\0') {
00702 rpmError(RPMERR_RPMRC,
00703 _("missing argument for %s at %s:%d\n"),
00704 option->name, urlfn, linenum);
00705 return 1;
00706 }
00707 }
00708
00709 val = se;
00710
00711
00712 if (option->macroize &&
00713 (arch == NULL || !strcmp(arch, current[ARCH]))) {
00714 char *n, *name;
00715 n = name = xmalloc(strlen(option->name)+2);
00716 if (option->localize)
00717 *n++ = '_';
00718 strcpy(n, option->name);
00719 addMacro(NULL, name, NULL, val, RMIL_RPMRC);
00720 free(name);
00721 }
00722 rpmSetVarArch(option->var, val, arch);
00723 fn = _free(fn);
00724
00725 } else {
00726 int gotit;
00727 int i;
00728
00729 gotit = 0;
00730
00731 for (i = 0; i < RPM_MACHTABLE_COUNT; i++) {
00732 if (!strncmp(tables[i].key, s, strlen(tables[i].key)))
00733 break;
00734 }
00735
00736 if (i < RPM_MACHTABLE_COUNT) {
00737 const char *rest = s + strlen(tables[i].key);
00738 if (*rest == '_') rest++;
00739
00740 if (!strcmp(rest, "compat")) {
00741 if (machCompatCacheAdd(se, urlfn, linenum,
00742 &tables[i].cache))
00743 return 1;
00744 gotit = 1;
00745 } else if (tables[i].hasTranslate &&
00746 !strcmp(rest, "translate")) {
00747 if (addDefault(&tables[i].defaults,
00748 &tables[i].defaultsLength,
00749 se, urlfn, linenum))
00750 return 1;
00751 gotit = 1;
00752 } else if (tables[i].hasCanon &&
00753 !strcmp(rest, "canon")) {
00754 if (addCanon(&tables[i].canons, &tables[i].canonsLength,
00755 se, urlfn, linenum))
00756 return 1;
00757 gotit = 1;
00758 }
00759 }
00760
00761 if (!gotit) {
00762 rpmError(RPMERR_RPMRC, _("bad option '%s' at %s:%d\n"),
00763 s, urlfn, linenum);
00764 }
00765 }
00766 }
00767
00768
00769 return 0;
00770 }
00771
00772
00773 # if defined(__linux__) && defined(__i386__)
00774 #include <setjmp.h>
00775 #include <signal.h>
00776
00777
00778
00779
00780 static inline void cpuid(int op, int *eax, int *ebx, int *ecx, int *edx)
00781
00782 {
00783 #ifdef __LCLINT__
00784 *eax = *ebx = *ecx = *edx = 0;
00785 #endif
00786 #ifdef PIC
00787 __asm__("pushl %%ebx; cpuid; movl %%ebx,%1; popl %%ebx"
00788 : "=a"(*eax), "=g"(*ebx), "=&c"(*ecx), "=&d"(*edx)
00789 : "a" (op));
00790 #else
00791 __asm__("cpuid"
00792 : "=a" (*eax), "=b" (*ebx), "=c" (*ecx), "=d" (*edx)
00793 : "a" (op));
00794 #endif
00795
00796 }
00797
00798
00799
00800
00801 static inline unsigned int cpuid_eax(unsigned int op)
00802
00803 {
00804 unsigned int val;
00805
00806 #ifdef PIC
00807 __asm__("pushl %%ebx; cpuid; popl %%ebx"
00808 : "=a" (val) : "a" (op) : "ecx", "edx");
00809 #else
00810 __asm__("cpuid"
00811 : "=a" (val) : "a" (op) : "ebx", "ecx", "edx");
00812 #endif
00813 return val;
00814 }
00815
00816 static inline unsigned int cpuid_ebx(unsigned int op)
00817
00818 {
00819 unsigned int tmp, val;
00820
00821 #ifdef PIC
00822 __asm__("pushl %%ebx; cpuid; movl %%ebx,%1; popl %%ebx"
00823 : "=a" (tmp), "=g" (val) : "a" (op) : "ecx", "edx");
00824 #else
00825 __asm__("cpuid"
00826 : "=a" (tmp), "=b" (val) : "a" (op) : "ecx", "edx");
00827 #endif
00828 return val;
00829 }
00830
00831 static inline unsigned int cpuid_ecx(unsigned int op)
00832
00833 {
00834 unsigned int tmp, val;
00835 #ifdef PIC
00836 __asm__("pushl %%ebx; cpuid; popl %%ebx"
00837 : "=a" (tmp), "=c" (val) : "a" (op) : "edx");
00838 #else
00839 __asm__("cpuid"
00840 : "=a" (tmp), "=c" (val) : "a" (op) : "ebx", "edx");
00841 #endif
00842 return val;
00843
00844 }
00845
00846 static inline unsigned int cpuid_edx(unsigned int op)
00847
00848 {
00849 unsigned int tmp, val;
00850 #ifdef PIC
00851 __asm__("pushl %%ebx; cpuid; popl %%ebx"
00852 : "=a" (tmp), "=d" (val) : "a" (op) : "ecx");
00853 #else
00854 __asm__("cpuid"
00855 : "=a" (tmp), "=d" (val) : "a" (op) : "ebx", "ecx");
00856 #endif
00857 return val;
00858
00859 }
00860
00861
00862 static sigjmp_buf jenv;
00863
00864 static inline void model3(int _unused)
00865
00866
00867 {
00868 siglongjmp(jenv, 1);
00869 }
00870
00871 static inline int RPMClass(void)
00872
00873
00874 {
00875 int cpu;
00876 unsigned int tfms, junk, cap;
00877
00878 signal(SIGILL, model3);
00879
00880 if(sigsetjmp(jenv, 1))
00881 return 3;
00882
00883 if(cpuid_eax(0x000000000)==0)
00884 return 4;
00885 cpuid(0x000000001, &tfms, &junk, &junk, &cap);
00886
00887 cpu = (tfms>>8)&15;
00888
00889 if(cpu < 6)
00890 return cpu;
00891
00892 if(cap & (1<<15))
00893 return 6;
00894
00895 return 5;
00896 }
00897
00898
00899 static int is_athlon(void)
00900
00901 {
00902 unsigned int eax, ebx, ecx, edx;
00903 char vendor[16];
00904 int i;
00905
00906 cpuid (0, &eax, &ebx, &ecx, &edx);
00907
00908
00909
00910 memset(vendor, 0, sizeof(vendor));
00911
00912 for (i=0; i<4; i++)
00913 vendor[i] = (unsigned char) (ebx >>(8*i));
00914 for (i=0; i<4; i++)
00915 vendor[4+i] = (unsigned char) (edx >>(8*i));
00916 for (i=0; i<4; i++)
00917 vendor[8+i] = (unsigned char) (ecx >>(8*i));
00918
00919 if (strcmp(vendor, "AuthenticAMD") != 0)
00920 return 0;
00921
00922 return 1;
00923 }
00924
00925 #endif
00926
00927 #if defined(__linux__) && defined(__powerpc__)
00928 static jmp_buf mfspr_jmpbuf;
00929
00930 static void mfspr_ill(int notused)
00931 {
00932 longjmp(mfspr_jmpbuf, -1);
00933 }
00934 #endif
00935
00936 static void defaultMachine( const char ** arch,
00937 const char ** os)
00938
00939
00940 {
00941 static struct utsname un;
00942 static int gotDefaults = 0;
00943 char * chptr;
00944 canonEntry canon;
00945 int rc;
00946
00947 if (!gotDefaults) {
00948 rc = uname(&un);
00949 if (rc < 0) return;
00950
00951 #if !defined(__linux__)
00952 #ifdef SNI
00953
00954
00955
00956 strncpy(un.sysname, "SINIX", sizeof(un.sysname));
00957 #endif
00958
00959 if (!strcmp(un.sysname, "AIX")) {
00960 strcpy(un.machine, __power_pc() ? "ppc" : "rs6000");
00961 sprintf(un.sysname,"aix%s.%s", un.version, un.release);
00962 }
00963 else if (!strcmp(un.sysname, "SunOS")) {
00964 if (!strncmp(un.release,"4", 1)) {
00965 int fd;
00966 for (fd = 0;
00967 (un.release[fd] != 0 && (fd < sizeof(un.release)));
00968 fd++) {
00969 if (!xisdigit(un.release[fd]) && (un.release[fd] != '.')) {
00970 un.release[fd] = 0;
00971 break;
00972 }
00973 }
00974 sprintf(un.sysname,"sunos%s",un.release);
00975 }
00976
00977 else
00978 sprintf(un.sysname, "solaris%1d%s", atoi(un.release)-3,
00979 un.release+1+(atoi(un.release)/10));
00980
00981
00982
00983
00984 if (!strcmp(un.machine, "i86pc"))
00985 sprintf(un.machine, "i386");
00986 }
00987 else if (!strcmp(un.sysname, "HP-UX"))
00988
00989 sprintf(un.sysname, "hpux%s", strpbrk(un.release, "123456789"));
00990 else if (!strcmp(un.sysname, "OSF1"))
00991
00992 sprintf(un.sysname, "osf%s", strpbrk(un.release, "123456789"));
00993 else if (!strncmp(un.sysname, "IP", 2))
00994 un.sysname[2] = '\0';
00995 else if (!strncmp(un.sysname, "SINIX", 5)) {
00996 sprintf(un.sysname, "sinix%s",un.release);
00997 if (!strncmp(un.machine, "RM", 2))
00998 sprintf(un.machine, "mips");
00999 }
01000 else if ((!strncmp(un.machine, "34", 2) ||
01001 !strncmp(un.machine, "33", 2)) && \
01002 !strncmp(un.release, "4.0", 3))
01003 {
01004
01005 char * prelid = NULL;
01006 FD_t fd = Fopen("/etc/.relid", "r.fdio");
01007 int gotit = 0;
01008
01009 if (fd != NULL && !Ferror(fd)) {
01010 chptr = xcalloc(1, 256);
01011 { int irelid = Fread(chptr, sizeof(*chptr), 256, fd);
01012 (void) Fclose(fd);
01013
01014 if (irelid > 0) {
01015 if ((prelid = strstr(chptr, "RELEASE "))){
01016 prelid += strlen("RELEASE ")+1;
01017 sprintf(un.sysname,"ncr-sysv4.%.*s",1,prelid);
01018 gotit = 1;
01019 }
01020 }
01021 }
01022 chptr = _free (chptr);
01023 }
01024
01025 if (!gotit)
01026 strcpy(un.sysname,"ncr-sysv4");
01027
01028 strcpy(un.machine,"i486");
01029 }
01030
01031 #endif
01032
01033
01034 for (chptr = un.machine; *chptr != '\0'; chptr++)
01035 if (*chptr == '/') *chptr = '-';
01036
01037 # if defined(__MIPSEL__) || defined(__MIPSEL) || defined(_MIPSEL)
01038
01039 strcpy(un.machine, "mipsel");
01040 # elif defined(__MIPSEB__) || defined(__MIPSEB) || defined(_MIPSEB)
01041
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
01049 # endif
01050 # if !defined(CPU_PA_RISC2_0)
01051 # define CPU_PA_RISC2_0 0x214
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
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
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 # if defined(__linux__) && defined(__powerpc__)
01148 {
01149 unsigned pvr = 0;
01150 __sighandler_t oldh = signal(SIGILL, mfspr_ill);
01151 if (setjmp(mfspr_jmpbuf) == 0) {
01152 __asm__ __volatile__ ("mfspr %0, 287" : "=r" (pvr));
01153 }
01154 signal(SIGILL, oldh);
01155
01156 if ( pvr ) {
01157 pvr >>= 16;
01158 if ( pvr >= 0x40)
01159 strcpy(un.machine, "ppcpseries");
01160 else if ( (pvr == 0x36) || (pvr == 0x37) )
01161 strcpy(un.machine, "ppciseries");
01162 else
01163 strcpy(un.machine, "ppc");
01164 }
01165 }
01166 # endif
01167
01168
01169 canon = lookupInCanonTable(un.machine,
01170 tables[RPM_MACHTABLE_INSTARCH].canons,
01171 tables[RPM_MACHTABLE_INSTARCH].canonsLength);
01172 if (canon)
01173 strcpy(un.machine, canon->short_name);
01174
01175 canon = lookupInCanonTable(un.sysname,
01176 tables[RPM_MACHTABLE_INSTOS].canons,
01177 tables[RPM_MACHTABLE_INSTOS].canonsLength);
01178 if (canon)
01179 strcpy(un.sysname, canon->short_name);
01180 gotDefaults = 1;
01181 }
01182
01183 if (arch) *arch = un.machine;
01184 if (os) *os = un.sysname;
01185 }
01186
01187 static
01188 const char * rpmGetVarArch(int var, const char * arch)
01189
01190 {
01191 const struct rpmvarValue * next;
01192
01193 if (arch == NULL) arch = current[ARCH];
01194
01195 if (arch) {
01196 next = &values[var];
01197 while (next) {
01198 if (next->arch && !strcmp(next->arch, arch)) return next->value;
01199 next = next->next;
01200 }
01201 }
01202
01203 next = values + var;
01204 while (next && next->arch) next = next->next;
01205
01206 return next ? next->value : NULL;
01207 }
01208
01209 const char *rpmGetVar(int var)
01210 {
01211 return rpmGetVarArch(var, NULL);
01212 }
01213
01214
01215 static void freeRpmVar( struct rpmvarValue * orig)
01216
01217 {
01218 struct rpmvarValue * next, * var = orig;
01219
01220 while (var) {
01221 next = var->next;
01222 var->arch = _free(var->arch);
01223 var->value = _free(var->value);
01224
01225
01226 if (var != orig) var = _free(var);
01227
01228 var = next;
01229 }
01230 }
01231
01232 void rpmSetVar(int var, const char * val)
01233 {
01234
01235 freeRpmVar(&values[var]);
01236
01237 values[var].value = (val ? xstrdup(val) : NULL);
01238 }
01239
01240 static void rpmSetVarArch(int var, const char * val, const char * arch)
01241
01242 {
01243 struct rpmvarValue * next = values + var;
01244
01245 if (next->value) {
01246 if (arch) {
01247 while (next->next) {
01248 if (next->arch && !strcmp(next->arch, arch)) break;
01249 next = next->next;
01250 }
01251 } else {
01252 while (next->next) {
01253 if (!next->arch) break;
01254 next = next->next;
01255 }
01256 }
01257
01258
01259 if (next->arch && arch && !strcmp(next->arch, arch)) {
01260
01261 next->value = _free(next->value);
01262 next->arch = _free(next->arch);
01263 } else if (next->arch || arch) {
01264 next->next = xmalloc(sizeof(*next->next));
01265 next = next->next;
01266 next->value = NULL;
01267 next->arch = NULL;
01268 next->next = NULL;
01269 }
01270 }
01271
01272 next->value = xstrdup(val);
01273 next->arch = (arch ? xstrdup(arch) : NULL);
01274 }
01275
01276 void rpmSetTables(int archTable, int osTable)
01277 {
01278 const char * arch, * os;
01279
01280 defaultMachine(&arch, &os);
01281
01282 if (currTables[ARCH] != archTable) {
01283 currTables[ARCH] = archTable;
01284 rebuildCompatTables(ARCH, arch);
01285 }
01286
01287 if (currTables[OS] != osTable) {
01288 currTables[OS] = osTable;
01289 rebuildCompatTables(OS, os);
01290 }
01291 }
01292
01293 int rpmMachineScore(int type, const char * name)
01294 {
01295 machEquivInfo info = machEquivSearch(&tables[type].equiv, name);
01296 return (info != NULL ? info->score : 0);
01297 }
01298
01299 void rpmGetMachine(const char ** arch, const char ** os)
01300 {
01301 if (arch)
01302 *arch = current[ARCH];
01303
01304 if (os)
01305 *os = current[OS];
01306 }
01307
01308 void rpmSetMachine(const char * arch, const char * os)
01309 {
01310 const char * host_cpu, * host_os;
01311
01312 defaultMachine(&host_cpu, &host_os);
01313
01314 if (arch == NULL) {
01315 arch = host_cpu;
01316 if (tables[currTables[ARCH]].hasTranslate)
01317 arch = lookupInDefaultTable(arch,
01318 tables[currTables[ARCH]].defaults,
01319 tables[currTables[ARCH]].defaultsLength);
01320 }
01321 if (arch == NULL) return;
01322
01323 if (os == NULL) {
01324 os = host_os;
01325 if (tables[currTables[OS]].hasTranslate)
01326 os = lookupInDefaultTable(os,
01327 tables[currTables[OS]].defaults,
01328 tables[currTables[OS]].defaultsLength);
01329 }
01330 if (os == NULL) return;
01331
01332 if (!current[ARCH] || strcmp(arch, current[ARCH])) {
01333 current[ARCH] = _free(current[ARCH]);
01334 current[ARCH] = xstrdup(arch);
01335 rebuildCompatTables(ARCH, host_cpu);
01336 }
01337
01338 if (!current[OS] || strcmp(os, current[OS])) {
01339 char * t = xstrdup(os);
01340 current[OS] = _free(current[OS]);
01341
01342
01343
01344
01345
01346
01347
01348
01349 if (!strcmp(t, "linux"))
01350 *t = 'L';
01351 current[OS] = t;
01352
01353 rebuildCompatTables(OS, host_os);
01354 }
01355 }
01356
01357 static void rebuildCompatTables(int type, const char * name)
01358
01359 {
01360 machFindEquivs(&tables[currTables[type]].cache,
01361 &tables[currTables[type]].equiv,
01362 name);
01363 }
01364
01365 static void getMachineInfo(int type, const char ** name,
01366 int * num)
01367
01368 {
01369 canonEntry canon;
01370 int which = currTables[type];
01371
01372
01373 if (which >= 2) which -= 2;
01374
01375 canon = lookupInCanonTable(current[type],
01376 tables[which].canons,
01377 tables[which].canonsLength);
01378
01379 if (canon) {
01380 if (num) *num = canon->num;
01381 if (name) *name = canon->short_name;
01382 } else {
01383 if (num) *num = 255;
01384 if (name) *name = current[type];
01385
01386 if (tables[currTables[type]].hasCanon) {
01387 rpmMessage(RPMMESS_WARNING, _("Unknown system: %s\n"), current[type]);
01388 rpmMessage(RPMMESS_WARNING, _("Please contact rpm-list@redhat.com\n"));
01389 }
01390 }
01391 }
01392
01393 void rpmGetArchInfo(const char ** name, int * num)
01394 {
01395 getMachineInfo(ARCH, name, num);
01396 }
01397
01398 void rpmGetOsInfo(const char ** name, int * num)
01399 {
01400 getMachineInfo(OS, name, num);
01401 }
01402
01403 void rpmRebuildTargetVars(const char ** target, const char ** canontarget)
01404 {
01405
01406 char *ca = NULL, *co = NULL, *ct = NULL;
01407 int x;
01408
01409
01410
01411 rpmSetMachine(NULL, NULL);
01412 rpmSetTables(RPM_MACHTABLE_INSTARCH, RPM_MACHTABLE_INSTOS);
01413 rpmSetTables(RPM_MACHTABLE_BUILDARCH, RPM_MACHTABLE_BUILDOS);
01414
01415
01416 if (target && *target) {
01417 char *c;
01418
01419 ca = xstrdup(*target);
01420 if ((c = strchr(ca, '-')) != NULL) {
01421 *c++ = '\0';
01422
01423 if ((co = strrchr(c, '-')) == NULL) {
01424 co = c;
01425 } else {
01426 if (!xstrcasecmp(co, "-gnu"))
01427 *co = '\0';
01428 if ((co = strrchr(c, '-')) == NULL)
01429 co = c;
01430 else
01431 co++;
01432 }
01433 if (co != NULL) co = xstrdup(co);
01434 }
01435 } else {
01436 const char *a = NULL;
01437 const char *o = NULL;
01438
01439 rpmGetArchInfo(&a, NULL);
01440 ca = (a) ? xstrdup(a) : NULL;
01441 rpmGetOsInfo(&o, NULL);
01442 co = (o) ? xstrdup(o) : NULL;
01443 }
01444
01445
01446
01447 if (ca == NULL) {
01448 const char *a = NULL;
01449 defaultMachine(&a, NULL);
01450 ca = (a) ? xstrdup(a) : NULL;
01451 }
01452 for (x = 0; ca[x] != '\0'; x++)
01453 ca[x] = xtolower(ca[x]);
01454
01455 if (co == NULL) {
01456 const char *o = NULL;
01457 defaultMachine(NULL, &o);
01458 co = (o) ? xstrdup(o) : NULL;
01459 }
01460 for (x = 0; co[x] != '\0'; x++)
01461 co[x] = xtolower(co[x]);
01462
01463
01464 if (ct == NULL) {
01465 ct = xmalloc(strlen(ca) + sizeof("-") + strlen(co));
01466 sprintf(ct, "%s-%s", ca, co);
01467 }
01468
01469
01470
01471
01472
01473 delMacro(NULL, "_target");
01474 addMacro(NULL, "_target", NULL, ct, RMIL_RPMRC);
01475 delMacro(NULL, "_target_cpu");
01476 addMacro(NULL, "_target_cpu", NULL, ca, RMIL_RPMRC);
01477 delMacro(NULL, "_target_os");
01478 addMacro(NULL, "_target_os", NULL, co, RMIL_RPMRC);
01479
01480
01481
01482 { const char *optflags = rpmGetVarArch(RPMVAR_OPTFLAGS, ca);
01483 if (optflags != NULL) {
01484 delMacro(NULL, "optflags");
01485 addMacro(NULL, "optflags", NULL, optflags, RMIL_RPMRC);
01486 }
01487 }
01488
01489
01490 if (canontarget)
01491 *canontarget = ct;
01492 else
01493 ct = _free(ct);
01494
01495 ca = _free(ca);
01496
01497 co = _free(co);
01498
01499 }
01500
01501 void rpmFreeRpmrc(void)
01502 {
01503 int i, j, k;
01504
01505 for (i = 0; i < RPM_MACHTABLE_COUNT; i++) {
01506 tableType t;
01507 t = tables + i;
01508 if (t->equiv.list) {
01509 for (j = 0; j < t->equiv.count; j++)
01510 t->equiv.list[j].name = _free(t->equiv.list[j].name);
01511 t->equiv.list = _free(t->equiv.list);
01512 t->equiv.count = 0;
01513 }
01514 if (t->cache.cache) {
01515 for (j = 0; j < t->cache.size; j++) {
01516 machCacheEntry e;
01517 e = t->cache.cache + j;
01518 if (e == NULL)
01519 continue;
01520 e->name = _free(e->name);
01521 if (e->equivs) {
01522 for (k = 0; k < e->count; k++)
01523 e->equivs[k] = _free(e->equivs[k]);
01524 e->equivs = _free(e->equivs);
01525 }
01526 }
01527 t->cache.cache = _free(t->cache.cache);
01528 t->cache.size = 0;
01529 }
01530 if (t->defaults) {
01531 for (j = 0; j < t->defaultsLength; j++) {
01532 t->defaults[j].name = _free(t->defaults[j].name);
01533 t->defaults[j].defName = _free(t->defaults[j].defName);
01534 }
01535 t->defaults = _free(t->defaults);
01536 t->defaultsLength = 0;
01537 }
01538 if (t->canons) {
01539 for (j = 0; j < t->canonsLength; j++) {
01540 t->canons[j].name = _free(t->canons[j].name);
01541 t->canons[j].short_name = _free(t->canons[j].short_name);
01542 }
01543 t->canons = _free(t->canons);
01544 t->canonsLength = 0;
01545 }
01546 }
01547
01548 for (i = 0; i < RPMVAR_NUM; i++) {
01549 struct rpmvarValue * vp;
01550 while ((vp = values[i].next) != NULL) {
01551 values[i].next = vp->next;
01552 vp->value = _free(vp->value);
01553 vp->arch = _free(vp->arch);
01554 vp = _free(vp);
01555 }
01556 values[i].value = _free(values[i].value);
01557 values[i].arch = _free(values[i].arch);
01558 }
01559 current[OS] = _free(current[OS]);
01560 current[ARCH] = _free(current[ARCH]);
01561 defaultsInitialized = 0;
01562
01563 return;
01564
01565 }
01566
01572 static int rpmReadRC( const char * rcfiles)
01573
01574
01575
01576
01577 {
01578 char *myrcfiles, *r, *re;
01579 int rc;
01580
01581 if (!defaultsInitialized) {
01582 setDefaults();
01583 defaultsInitialized = 1;
01584 }
01585
01586 if (rcfiles == NULL)
01587 rcfiles = defrcfiles;
01588
01589
01590 rc = 0;
01591 for (r = myrcfiles = xstrdup(rcfiles); r && *r != '\0'; r = re) {
01592 char fn[4096];
01593 FD_t fd;
01594
01595
01596 for (re = r; (re = strchr(re, ':')) != NULL; re++) {
01597 if (!(re[1] == '/' && re[2] == '/'))
01598 break;
01599 }
01600 if (re && *re == ':')
01601 *re++ = '\0';
01602 else
01603 re = r + strlen(r);
01604
01605
01606 fn[0] = '\0';
01607 if (r[0] == '~' && r[1] == '/') {
01608 const char * home = getenv("HOME");
01609 if (home == NULL) {
01610
01611 if (rcfiles == defrcfiles && myrcfiles != r)
01612 continue;
01613 rpmError(RPMERR_RPMRC, _("Cannot expand %s\n"), r);
01614 rc = 1;
01615 break;
01616 }
01617 if (strlen(home) > (sizeof(fn) - strlen(r))) {
01618 rpmError(RPMERR_RPMRC, _("Cannot read %s, HOME is too large.\n"),
01619 r);
01620 rc = 1;
01621 break;
01622 }
01623 strcpy(fn, home);
01624 r++;
01625 }
01626 strncat(fn, r, sizeof(fn) - (strlen(fn) + 1));
01627 fn[sizeof(fn)-1] = '\0';
01628
01629
01630 fd = Fopen(fn, "r.fpio");
01631 if (fd == NULL || Ferror(fd)) {
01632
01633 if (rcfiles == defrcfiles && myrcfiles != r)
01634 continue;
01635 rpmError(RPMERR_RPMRC, _("Unable to open %s for reading: %s.\n"),
01636 fn, Fstrerror(fd));
01637 rc = 1;
01638 break;
01639 } else {
01640 rc = doReadRC(fd, fn);
01641 }
01642 if (rc) break;
01643 }
01644 myrcfiles = _free(myrcfiles);
01645 if (rc)
01646 return rc;
01647
01648 rpmSetMachine(NULL, NULL);
01649
01650 { const char *mfpath;
01651
01652 if ((mfpath = rpmGetVar(RPMVAR_MACROFILES)) != NULL) {
01653 mfpath = xstrdup(mfpath);
01654 rpmInitMacros(NULL, mfpath);
01655 mfpath = _free(mfpath);
01656 }
01657
01658 }
01659
01660 return rc;
01661 }
01662
01663 int rpmReadConfigFiles(const char * file, const char * target)
01664 {
01665
01666
01667
01668 rpmRebuildTargetVars(&target, NULL);
01669
01670
01671 if (rpmReadRC(file)) return -1;
01672
01673
01674 rpmRebuildTargetVars(&target, NULL);
01675
01676
01677
01678 { const char *cpu = rpmExpand("%{_target_cpu}", NULL);
01679 const char *os = rpmExpand("%{_target_os}", NULL);
01680 rpmSetMachine(cpu, os);
01681 cpu = _free(cpu);
01682 os = _free(os);
01683 }
01684
01685 return 0;
01686 }
01687
01688 int rpmShowRC(FILE * fp)
01689 {
01690 struct rpmOption *opt;
01691 int i;
01692 machEquivTable equivTable;
01693
01694
01695 fprintf(fp, "ARCHITECTURE AND OS:\n");
01696 fprintf(fp, "build arch : %s\n", current[ARCH]);
01697
01698 fprintf(fp, "compatible build archs:");
01699 equivTable = &tables[RPM_MACHTABLE_BUILDARCH].equiv;
01700 for (i = 0; i < equivTable->count; i++)
01701 fprintf(fp," %s", equivTable->list[i].name);
01702 fprintf(fp, "\n");
01703
01704 fprintf(fp, "build os : %s\n", current[OS]);
01705
01706 fprintf(fp, "compatible build os's :");
01707 equivTable = &tables[RPM_MACHTABLE_BUILDOS].equiv;
01708 for (i = 0; i < equivTable->count; i++)
01709 fprintf(fp," %s", equivTable->list[i].name);
01710 fprintf(fp, "\n");
01711
01712 rpmSetTables(RPM_MACHTABLE_INSTARCH, RPM_MACHTABLE_INSTOS);
01713 rpmSetMachine(NULL, NULL);
01714
01715 fprintf(fp, "install arch : %s\n", current[ARCH]);
01716 fprintf(fp, "install os : %s\n", current[OS]);
01717
01718 fprintf(fp, "compatible archs :");
01719 equivTable = &tables[RPM_MACHTABLE_INSTARCH].equiv;
01720 for (i = 0; i < equivTable->count; i++)
01721 fprintf(fp," %s", equivTable->list[i].name);
01722 fprintf(fp, "\n");
01723
01724 fprintf(fp, "compatible os's :");
01725 equivTable = &tables[RPM_MACHTABLE_INSTOS].equiv;
01726 for (i = 0; i < equivTable->count; i++)
01727 fprintf(fp," %s", equivTable->list[i].name);
01728 fprintf(fp, "\n");
01729
01730 fprintf(fp, "\nRPMRC VALUES:\n");
01731 for (i = 0, opt = optionTable; i < optionTableSize; i++, opt++) {
01732 const char *s = rpmGetVar(opt->var);
01733 if (s != NULL || rpmIsVerbose())
01734 fprintf(fp, "%-21s : %s\n", opt->name, s ? s : "(not set)");
01735 }
01736 fprintf(fp, "\n");
01737
01738 fprintf(fp, "Features supported by rpmlib:\n");
01739 rpmShowRpmlibProvides(fp);
01740 fprintf(fp, "\n");
01741
01742 rpmDumpMacroTable(NULL, fp);
01743
01744 return 0;
01745 }
01746