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