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