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