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