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