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