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