Bug Summary

File:lib/rpmrc.c
Warning:line 690, column 2
Value stored to 'os' is never read

Annotated Source Code

1#include "system.h"
2
3#include <stdarg.h>
4#include <pthread.h>
5
6#if defined(__linux__1)
7#include <elf.h>
8#include <link.h>
9#endif
10
11
12#if HAVE_SYS_UTSNAME_H1
13#include <sys/utsname.h>
14#endif
15#include <ctype.h> /* XXX for /etc/rpm/platform contents */
16
17#if HAVE_SYS_SYSTEMCFG_H
18#include <sys/systemcfg.h>
19#else
20#define __power_pc()0 0
21#endif
22
23#ifdef HAVE_SYS_AUXV_H1
24#include <sys/auxv.h>
25#endif
26
27#include <rpm/rpmlib.h> /* RPM_MACTABLE*, Rc-prototypes */
28#include <rpm/rpmmacro.h>
29#include <rpm/rpmfileutil.h>
30#include <rpm/rpmstring.h>
31#include <rpm/rpmlog.h>
32#include <rpm/argv.h>
33
34#include "rpmio/rpmlua.h"
35#include "rpmio/rpmio_internal.h" /* XXX for rpmioSlurp */
36#include "lib/misc.h"
37#include "lib/rpmliblua.h"
38#include "lib/rpmug.h"
39
40#include "debug.h"
41
42static const char * defrcfiles = NULL((void*)0);
43const char * macrofiles = NULL((void*)0);
44
45typedef struct machCacheEntry_s {
46 char * name;
47 int count;
48 char ** equivs;
49 int visited;
50} * machCacheEntry;
51
52typedef struct machCache_s {
53 machCacheEntry cache;
54 int size;
55} * machCache;
56
57typedef struct machEquivInfo_s {
58 char * name;
59 int score;
60} * machEquivInfo;
61
62typedef struct machEquivTable_s {
63 int count;
64 machEquivInfo list;
65} * machEquivTable;
66
67struct rpmvarValue {
68 char * value;
69 /* eventually, this arch will be replaced with a generic condition */
70 char * arch;
71struct rpmvarValue * next;
72};
73
74struct rpmOption {
75 char * name;
76 int var;
77 int archSpecific;
78 int macroize;
79 int localize;
80};
81
82static struct rpmat_s {
83 const char *platform;
84 uint64_t hwcap;
85} rpmat;
86
87typedef struct defaultEntry_s {
88 char * name;
89 char * defName;
90} * defaultEntry;
91
92typedef struct canonEntry_s {
93 char * name;
94 char * short_name;
95 short num;
96} * canonEntry;
97
98/* tags are 'key'canon, 'key'translate, 'key'compat
99 *
100 * for giggles, 'key'_canon, 'key'_compat, and 'key'_canon will also work
101 */
102typedef struct tableType_s {
103 char * const key;
104 const int hasCanon;
105 const int hasTranslate;
106 struct machEquivTable_s equiv;
107 struct machCache_s cache;
108 defaultEntry defaults;
109 canonEntry canons;
110 int defaultsLength;
111 int canonsLength;
112} * tableType;
113
114/* XXX get rid of this stuff... */
115/* Stuff for maintaining "variables" like SOURCEDIR, BUILDDIR, etc */
116#define RPMVAR_OPTFLAGS3 3
117#define RPMVAR_ARCHCOLOR42 42
118#define RPMVAR_INCLUDE43 43
119#define RPMVAR_MACROFILES49 49
120
121#define RPMVAR_NUM55 55 /* number of RPMVAR entries */
122
123/* this *must* be kept in alphabetical order */
124/* The order of the flags is archSpecific, macroize, localize */
125
126static const struct rpmOption optionTable[] = {
127 { "archcolor", RPMVAR_ARCHCOLOR42, 1, 0, 0 },
128 { "include", RPMVAR_INCLUDE43, 0, 0, 2 },
129 { "macrofiles", RPMVAR_MACROFILES49, 0, 0, 1 },
130 { "optflags", RPMVAR_OPTFLAGS3, 1, 1, 0 },
131};
132
133static const size_t optionTableSize = sizeof(optionTable) / sizeof(*optionTable);
134
135#define OS0 0
136#define ARCH1 1
137
138typedef struct rpmrcCtx_s * rpmrcCtx;
139struct rpmrcCtx_s {
140 ARGV_t platpat;
141 char *current[2];
142 int currTables[2];
143 struct rpmvarValue values[RPMVAR_NUM55];
144 struct tableType_s tables[RPM_MACHTABLE_COUNT4];
145 int machDefaults;
146 int pathDefaults;
147 pthread_rwlock_t lock;
148};
149
150/* prototypes */
151static rpmRC doReadRC(rpmrcCtx ctx, const char * urlfn);
152
153static void rpmSetVarArch(rpmrcCtx ctx,
154 int var, const char * val, const char * arch);
155
156static void rebuildCompatTables(rpmrcCtx ctx, int type, const char * name);
157
158static void rpmRebuildTargetVars(rpmrcCtx ctx, const char **target, const char ** canontarget);
159
160/* Force context (lock) acquisition through a function */
161static rpmrcCtx rpmrcCtxAcquire(int write)
162{
163 static struct rpmrcCtx_s _globalCtx = {
164 .lock = PTHREAD_RWLOCK_INITIALIZER{ { 0, 0, 0, 0, 0, 0, 0, 0, 0, { 0, 0, 0, 0, 0, 0, 0 }, 0, 0 }
}
,
165 .currTables = { RPM_MACHTABLE_INSTOS, RPM_MACHTABLE_INSTARCH },
166 .tables = {
167 { "arch", 1, 0 },
168 { "os", 1, 0 },
169 { "buildarch", 0, 1 },
170 { "buildos", 0, 1 }
171 },
172 };
173 rpmrcCtx ctx = &_globalCtx;
174
175 /* XXX: errors should be handled */
176 if (write)
177 pthread_rwlock_wrlock(&ctx->lock);
178 else
179 pthread_rwlock_rdlock(&ctx->lock);
180
181 return ctx;
182}
183
184/* Release context (lock) */
185static rpmrcCtx rpmrcCtxRelease(rpmrcCtx ctx)
186{
187 pthread_rwlock_unlock(&ctx->lock);
188 return NULL((void*)0);
189}
190
191static int optionCompare(const void * a, const void * b)
192{
193 return rstrcasecmp(((const struct rpmOption *) a)->name,
194 ((const struct rpmOption *) b)->name);
195}
196
197static machCacheEntry
198machCacheFindEntry(const machCache cache, const char * key)
199{
200 int i;
201
202 for (i = 0; i < cache->size; i++)
203 if (rstreq(cache->cache[i].name, key)) return cache->cache + i;
204
205 return NULL((void*)0);
206}
207
208static int machCompatCacheAdd(char * name, const char * fn, int linenum,
209 machCache cache)
210{
211 machCacheEntry entry = NULL((void*)0);
212 char * chptr;
213 char * equivs;
214 int delEntry = 0;
215 int i;
216
217 while (*name && risspace(*name)) name++;
218
219 chptr = name;
220 while (*chptr && *chptr != ':') chptr++;
221 if (!*chptr) {
222 rpmlog(RPMLOG_ERR, _("missing second ':' at %s:%d\n")dcgettext ("rpm", "missing second ':' at %s:%d\n", 5), fn, linenum);
223 return 1;
224 } else if (chptr == name) {
225 rpmlog(RPMLOG_ERR, _("missing architecture name at %s:%d\n")dcgettext ("rpm", "missing architecture name at %s:%d\n", 5), fn,
226 linenum);
227 return 1;
228 }
229
230 while (*chptr == ':' || risspace(*chptr)) chptr--;
231 *(++chptr) = '\0';
232 equivs = chptr + 1;
233 while (*equivs && risspace(*equivs)) equivs++;
234 if (!*equivs) {
235 delEntry = 1;
236 }
237
238 if (cache->size) {
239 entry = machCacheFindEntry(cache, name);
240 if (entry) {
241 for (i = 0; i < entry->count; i++)
242 entry->equivs[i] = _free(entry->equivs[i])rfree((entry->equivs[i]));
243 entry->equivs = _free(entry->equivs)rfree((entry->equivs));
244 entry->count = 0;
245 }
246 }
247
248 if (!entry) {
249 cache->cache = xrealloc(cache->cache,rrealloc((cache->cache), ((cache->size + 1) * sizeof(*cache
->cache)))
250 (cache->size + 1) * sizeof(*cache->cache))rrealloc((cache->cache), ((cache->size + 1) * sizeof(*cache
->cache)))
;
251 entry = cache->cache + cache->size++;
252 entry->name = xstrdup(name)rstrdup((name));
253 entry->count = 0;
254 entry->visited = 0;
255 }
256
257 if (delEntry) return 0;
258
259 while ((chptr = strtok(equivs, " ")) != NULL((void*)0)) {
260 equivs = NULL((void*)0);
261 if (chptr[0] == '\0') /* does strtok() return "" ever?? */
262 continue;
263 if (entry->count)
264 entry->equivs = xrealloc(entry->equivs, sizeof(*entry->equivs)rrealloc((entry->equivs), (sizeof(*entry->equivs) * (entry
->count + 1)))
265 * (entry->count + 1))rrealloc((entry->equivs), (sizeof(*entry->equivs) * (entry
->count + 1)))
;
266 else
267 entry->equivs = xmalloc(sizeof(*entry->equivs))rmalloc((sizeof(*entry->equivs)));
268
269 entry->equivs[entry->count] = xstrdup(chptr)rstrdup((chptr));
270 entry->count++;
271 }
272
273 return 0;
274}
275
276static machEquivInfo
277machEquivSearch(const machEquivTable table, const char * name)
278{
279 int i;
280
281 for (i = 0; i < table->count; i++)
282 if (!rstrcasecmp(table->list[i].name, name))
283 return table->list + i;
284
285 return NULL((void*)0);
286}
287
288static void machAddEquiv(machEquivTable table, const char * name,
289 int distance)
290{
291 machEquivInfo equiv;
292
293 equiv = machEquivSearch(table, name);
294 if (!equiv) {
295 if (table->count)
296 table->list = xrealloc(table->list, (table->count + 1)rrealloc((table->list), ((table->count + 1) * sizeof(*table
->list)))
297 * sizeof(*table->list))rrealloc((table->list), ((table->count + 1) * sizeof(*table
->list)))
;
298 else
299 table->list = xmalloc(sizeof(*table->list))rmalloc((sizeof(*table->list)));
300
301 table->list[table->count].name = xstrdup(name)rstrdup((name));
302 table->list[table->count++].score = distance;
303 }
304}
305
306static void machCacheEntryVisit(machCache cache,
307 machEquivTable table, const char * name, int distance)
308{
309 machCacheEntry entry;
310 int i;
311
312 entry = machCacheFindEntry(cache, name);
313 if (!entry || entry->visited) return;
314
315 entry->visited = 1;
316
317 for (i = 0; i < entry->count; i++) {
318 machAddEquiv(table, entry->equivs[i], distance);
319 }
320
321 for (i = 0; i < entry->count; i++) {
322 machCacheEntryVisit(cache, table, entry->equivs[i], distance + 1);
323 }
324}
325
326static void machFindEquivs(machCache cache, machEquivTable table,
327 const char * key)
328{
329 int i;
330
331 for (i = 0; i < cache->size; i++)
332 cache->cache[i].visited = 0;
333
334 while (table->count > 0) {
335 --table->count;
336 table->list[table->count].name = _free(table->list[table->count].name)rfree((table->list[table->count].name));
337 }
338 table->count = 0;
339 table->list = _free(table->list)rfree((table->list));
340
341 /*
342 * We have a general graph built using strings instead of pointers.
343 * Yuck. We have to start at a point at traverse it, remembering how
344 * far away everything is.
345 */
346 /* FIX: table->list may be NULL. */
347 machAddEquiv(table, key, 1);
348 machCacheEntryVisit(cache, table, key, 2);
349 return;
350}
351
352static rpmRC addCanon(canonEntry * table, int * tableLen, char * line,
353 const char * fn, int lineNum)
354{
355 canonEntry t;
356 char *s, *s1;
357 const char * tname;
358 const char * tshort_name;
359 int tnum;
360
361 (*tableLen) += 2;
362 *table = xrealloc(*table, sizeof(**table) * (*tableLen))rrealloc((*table), (sizeof(**table) * (*tableLen)));
363
364 t = & ((*table)[*tableLen - 2]);
365
366 tname = strtok(line, ": \t");
367 tshort_name = strtok(NULL((void*)0), " \t");
368 s = strtok(NULL((void*)0), " \t");
369 if (! (tname && tshort_name && s)) {
370 rpmlog(RPMLOG_ERR, _("Incomplete data line at %s:%d\n")dcgettext ("rpm", "Incomplete data line at %s:%d\n", 5),
371 fn, lineNum);
372 return RPMRC_FAIL;
373 }
374 if (strtok(NULL((void*)0), " \t")) {
375 rpmlog(RPMLOG_ERR, _("Too many args in data line at %s:%d\n")dcgettext ("rpm", "Too many args in data line at %s:%d\n", 5),
376 fn, lineNum);
377 return RPMRC_FAIL;
378 }
379
380 tnum = strtoul(s, &s1, 10);
381 if ((*s1) || (s1 == s) || (tnum == ULONG_MAX(9223372036854775807L *2UL+1UL))) {
382 rpmlog(RPMLOG_ERR, _("Bad arch/os number: %s (%s:%d)\n")dcgettext ("rpm", "Bad arch/os number: %s (%s:%d)\n", 5), s,
383 fn, lineNum);
384 return RPMRC_FAIL;
385 }
386
387 t[0].name = xstrdup(tname)rstrdup((tname));
388 t[0].short_name = (tshort_name ? xstrdup(tshort_name)rstrdup((tshort_name)) : xstrdup("")rstrdup(("")));
389 t[0].num = tnum;
390
391 /* From A B C entry */
392 /* Add B B C entry */
393 t[1].name = (tshort_name ? xstrdup(tshort_name)rstrdup((tshort_name)) : xstrdup("")rstrdup(("")));
394 t[1].short_name = (tshort_name ? xstrdup(tshort_name)rstrdup((tshort_name)) : xstrdup("")rstrdup(("")));
395 t[1].num = tnum;
396
397 return RPMRC_OK;
398}
399
400static rpmRC addDefault(defaultEntry * table, int * tableLen, char * line,
401 const char * fn, int lineNum)
402{
403 defaultEntry t;
404
405 (*tableLen)++;
406 *table = xrealloc(*table, sizeof(**table) * (*tableLen))rrealloc((*table), (sizeof(**table) * (*tableLen)));
407
408 t = & ((*table)[*tableLen - 1]);
409
410 t->name = strtok(line, ": \t");
411 t->defName = strtok(NULL((void*)0), " \t");
412 if (! (t->name && t->defName)) {
413 rpmlog(RPMLOG_ERR, _("Incomplete default line at %s:%d\n")dcgettext ("rpm", "Incomplete default line at %s:%d\n", 5),
414 fn, lineNum);
415 return RPMRC_FAIL;
416 }
417 if (strtok(NULL((void*)0), " \t")) {
418 rpmlog(RPMLOG_ERR, _("Too many args in default line at %s:%d\n")dcgettext ("rpm", "Too many args in default line at %s:%d\n",
5)
,
419 fn, lineNum);
420 return RPMRC_FAIL;
421 }
422
423 t->name = xstrdup(t->name)rstrdup((t->name));
424 t->defName = (t->defName ? xstrdup(t->defName)rstrdup((t->defName)) : NULL((void*)0));
425
426 return RPMRC_OK;
427}
428
429static canonEntry lookupInCanonTable(const char * name,
430 const canonEntry table, int tableLen)
431{
432 while (tableLen) {
433 tableLen--;
434 if (!rstreq(name, table[tableLen].name))
435 continue;
436 return &(table[tableLen]);
437 }
438
439 return NULL((void*)0);
440}
441
442static
443const char * lookupInDefaultTable(const char * name,
444 const defaultEntry table, int tableLen)
445{
446 while (tableLen) {
447 tableLen--;
448 if (table[tableLen].name && rstreq(name, table[tableLen].name))
449 return table[tableLen].defName;
450 }
451
452 return name;
453}
454
455static void setDefaults(void)
456{
457 const char *confdir = rpmConfigDir();
458 if (!defrcfiles) {
459 defrcfiles = rstrscat(NULL((void*)0), confdir, "/rpmrc", ":",
460 confdir, "/" RPMCANONVENDOR"redhat" "/rpmrc", ":",
461 SYSCONFDIR"/etc" "/rpmrc", ":",
462 "~/.rpmrc", NULL((void*)0));
463 }
464
465#ifndef MACROFILES
466 if (!macrofiles) {
467 macrofiles = rstrscat(NULL((void*)0), confdir, "/macros", ":",
468 confdir, "/macros.d/macros.*", ":",
469 confdir, "/platform/%{_target}/macros", ":",
470 confdir, "/fileattrs/*.attr", ":",
471 confdir, "/" RPMCANONVENDOR"redhat" "/macros", ":",
472 SYSCONFDIR"/etc" "/rpm/macros.*", ":",
473 SYSCONFDIR"/etc" "/rpm/macros", ":",
474 SYSCONFDIR"/etc" "/rpm/%{_target}/macros", ":",
475 "~/.rpmmacros", NULL((void*)0));
476 }
477#else
478 macrofiles = MACROFILES;
479#endif
480}
481
482/* FIX: se usage inconsistent, W2DO? */
483static rpmRC doReadRC(rpmrcCtx ctx, const char * urlfn)
484{
485 char *s;
486 char *se, *next, *buf = NULL((void*)0), *fn;
487 int linenum = 0;
488 struct rpmOption searchOption, * option;
489 rpmRC rc = RPMRC_FAIL;
490
491 fn = rpmGetPath(urlfn, NULL((void*)0));
492 if (rpmioSlurp(fn, (uint8_t **) &buf, NULL((void*)0)) || buf == NULL((void*)0)) {
493 goto exit;
494 }
495
496 next = buf;
497 while (*next != '\0') {
498 linenum++;
499
500 s = se = next;
501
502 /* Find end-of-line. */
503 while (*se && *se != '\n') se++;
504 if (*se != '\0') *se++ = '\0';
505 next = se;
506
507 /* Trim leading spaces */
508 while (*s && risspace(*s)) s++;
509
510 /* We used to allow comments to begin anywhere, but not anymore. */
511 if (*s == '#' || *s == '\0') continue;
512
513 /* Find end-of-keyword. */
514 se = (char *)s;
515 while (*se && !risspace(*se) && *se != ':') se++;
516
517 if (risspace(*se)) {
518 *se++ = '\0';
519 while (*se && risspace(*se) && *se != ':') se++;
520 }
521
522 if (*se != ':') {
523 rpmlog(RPMLOG_ERR, _("missing ':' (found 0x%02x) at %s:%d\n")dcgettext ("rpm", "missing ':' (found 0x%02x) at %s:%d\n", 5),
524 (unsigned)(0xff & *se), fn, linenum);
525 goto exit;
526 }
527 *se++ = '\0'; /* terminate keyword or option, point to value */
528 while (*se && risspace(*se)) se++;
529
530 /* Find keyword in table */
531 searchOption.name = s;
532 option = bsearch(&searchOption, optionTable, optionTableSize,
533 sizeof(optionTable[0]), optionCompare);
534
535 if (option) { /* For configuration variables ... */
536 const char *arch, *val;
537
538 arch = val = NULL((void*)0);
539 if (*se == '\0') {
540 rpmlog(RPMLOG_ERR, _("missing argument for %s at %s:%d\n")dcgettext ("rpm", "missing argument for %s at %s:%d\n", 5),
541 option->name, fn, linenum);
542 goto exit;
543 }
544
545 if (option->var == RPMVAR_INCLUDE43) {
546 s = se;
547 while (*se && !risspace(*se)) se++;
548 if (*se != '\0') *se = '\0';
549
550 if (doReadRC(ctx, s)) {
551 rpmlog(RPMLOG_ERR, _("cannot open %s at %s:%d: %m\n")dcgettext ("rpm", "cannot open %s at %s:%d: %m\n", 5),
552 s, fn, linenum);
553 goto exit;
554 }
555 /* XXX don't save include value as var/macro */
556 continue;
557 }
558
559 if (option->archSpecific) {
560 arch = se;
561 while (*se && !risspace(*se)) se++;
562 if (*se == '\0') {
563 rpmlog(RPMLOG_ERR,
564 _("missing architecture for %s at %s:%d\n")dcgettext ("rpm", "missing architecture for %s at %s:%d\n", 5
)
,
565 option->name, fn, linenum);
566 goto exit;
567 }
568 *se++ = '\0';
569 while (*se && risspace(*se)) se++;
570 if (*se == '\0') {
571 rpmlog(RPMLOG_ERR,
572 _("missing argument for %s at %s:%d\n")dcgettext ("rpm", "missing argument for %s at %s:%d\n", 5),
573 option->name, fn, linenum);
574 goto exit;
575 }
576 }
577
578 val = se;
579
580 /* Only add macros if appropriate for this arch */
581 if (option->macroize &&
582 (arch == NULL((void*)0) || rstreq(arch, ctx->current[ARCH1]))) {
583 char *n, *name;
584 n = name = xmalloc(strlen(option->name)+2)rmalloc((strlen(option->name)+2));
585 if (option->localize)
586 *n++ = '_';
587 strcpy(n, option->name);
588 rpmPushMacro(NULL((void*)0), name, NULL((void*)0), val, RMIL_RPMRC-11);
589 free(name);
590 }
591 rpmSetVarArch(ctx, option->var, val, arch);
592 fn = _free(fn)rfree((fn));
593
594 } else { /* For arch/os compatibility tables ... */
595 int gotit;
596 int i;
597
598 gotit = 0;
599
600 for (i = 0; i < RPM_MACHTABLE_COUNT4; i++) {
601 if (rstreqn(ctx->tables[i].key, s, strlen(ctx->tables[i].key)))
602 break;
603 }
604
605 if (i < RPM_MACHTABLE_COUNT4) {
606 const char *rest = s + strlen(ctx->tables[i].key);
607 if (*rest == '_') rest++;
608
609 if (rstreq(rest, "compat")) {
610 if (machCompatCacheAdd(se, fn, linenum,
611 &ctx->tables[i].cache))
612 goto exit;
613 gotit = 1;
614 } else if (ctx->tables[i].hasTranslate &&
615 rstreq(rest, "translate")) {
616 if (addDefault(&ctx->tables[i].defaults,
617 &ctx->tables[i].defaultsLength,
618 se, fn, linenum))
619 goto exit;
620 gotit = 1;
621 } else if (ctx->tables[i].hasCanon &&
622 rstreq(rest, "canon")) {
623 if (addCanon(&ctx->tables[i].canons,
624 &ctx->tables[i].canonsLength,
625 se, fn, linenum))
626 goto exit;
627 gotit = 1;
628 }
629 }
630
631 if (!gotit) {
632 rpmlog(RPMLOG_ERR, _("bad option '%s' at %s:%d\n")dcgettext ("rpm", "bad option '%s' at %s:%d\n", 5),
633 s, fn, linenum);
634 goto exit;
635 }
636 }
637 }
638 rc = RPMRC_OK;
639
640exit:
641 free(fn);
642 free(buf);
643
644 return rc;
645}
646
647
648/**
649 */
650static rpmRC rpmPlatform(rpmrcCtx ctx, const char * platform)
651{
652 const char *cpu = NULL((void*)0), *vendor = NULL((void*)0), *os = NULL((void*)0), *gnu = NULL((void*)0);
653 uint8_t * b = NULL((void*)0);
654 ssize_t blen = 0;
655 int init_platform = 0;
656 char * p, * pe;
657 rpmRC rc;
658
659 rc = (rpmioSlurp(platform, &b, &blen) == 0) ? RPMRC_OK : RPMRC_FAIL;
660
661 if (rc || b == NULL((void*)0) || blen <= 0) {
662 rc = RPMRC_FAIL;
663 goto exit;
664 }
665
666 p = (char *)b;
667 for (pe = p; p && *p; p = pe) {
668 pe = strchr(p, '\n');
669 if (pe)
670 *pe++ = '\0';
671
672 while (*p && isspace(*p)((*__ctype_b_loc ())[(int) ((*p))] & (unsigned short int)
_ISspace)
)
673 p++;
674 if (*p == '\0' || *p == '#')
675 continue;
676
677 if (init_platform) {
678 char * t = p + strlen(p);
679
680 while (--t > p && isspace(*t)((*__ctype_b_loc ())[(int) ((*t))] & (unsigned short int)
_ISspace)
)
681 *t = '\0';
682 if (t > p) {
683 argvAdd(&ctx->platpat, p);
684 }
685 continue;
686 }
687
688 cpu = p;
689 vendor = "unknown";
690 os = "unknown";
Value stored to 'os' is never read
691 gnu = NULL((void*)0);
692 while (*p && !(*p == '-' || isspace(*p)((*__ctype_b_loc ())[(int) ((*p))] & (unsigned short int)
_ISspace)
))
693 p++;
694 if (*p != '\0') *p++ = '\0';
695
696 vendor = p;
697 while (*p && !(*p == '-' || isspace(*p)((*__ctype_b_loc ())[(int) ((*p))] & (unsigned short int)
_ISspace)
))
698 p++;
699 if (*p != '-') {
700 if (*p != '\0') *p = '\0';
701 os = vendor;
702 vendor = "unknown";
703 } else {
704 if (*p != '\0') *p++ = '\0';
705
706 os = p;
707 while (*p && !(*p == '-' || isspace(*p)((*__ctype_b_loc ())[(int) ((*p))] & (unsigned short int)
_ISspace)
))
708 p++;
709 if (*p == '-') {
710 *p++ = '\0';
711
712 gnu = p;
713 while (*p && !(*p == '-' || isspace(*p)((*__ctype_b_loc ())[(int) ((*p))] & (unsigned short int)
_ISspace)
))
714 p++;
715 }
716 if (*p != '\0') *p = '\0';
717 }
718
719 rpmPushMacro(NULL((void*)0), "_host_cpu", NULL((void*)0), cpu, -1);
720 rpmPushMacro(NULL((void*)0), "_host_vendor", NULL((void*)0), vendor, -1);
721 rpmPushMacro(NULL((void*)0), "_host_os", NULL((void*)0), os, -1);
722
723 char *plat = rpmExpand("%{_host_cpu}-%{_host_vendor}-%{_host_os}",
724 (gnu && *gnu ? "-" : NULL((void*)0)), gnu, NULL((void*)0));
725 argvAdd(&ctx->platpat, plat);
726 free(plat);
727
728 init_platform++;
729 }
730 rc = (init_platform ? RPMRC_OK : RPMRC_FAIL);
731
732exit:
733 b = _free(b)rfree((b));
734 return rc;
735}
736
737
738# if defined(__linux__1) && defined(__i386__)
739#include <setjmp.h>
740#include <signal.h>
741
742/*
743 * Generic CPUID function
744 */
745static inline void cpuid(unsigned int op, unsigned int *eax, unsigned int *ebx, unsigned int *ecx, unsigned int *edx)
746{
747 asm volatile (
748 "pushl %%ebx \n"
749 "cpuid \n"
750 "movl %%ebx, %%esi \n"
751 "popl %%ebx \n"
752 : "=a" (*eax), "=S" (*ebx), "=c" (*ecx), "=d" (*edx)
753 : "a" (op));
754}
755
756/*
757 * CPUID functions returning a single datum
758 */
759static inline unsigned int cpuid_eax(unsigned int op)
760{
761 unsigned int tmp, val;
762 cpuid(op, &val, &tmp, &tmp, &tmp);
763 return val;
764}
765
766static inline unsigned int cpuid_ebx(unsigned int op)
767{
768 unsigned int tmp, val;
769 cpuid(op, &tmp, &val, &tmp, &tmp);
770 return val;
771}
772
773static inline unsigned int cpuid_ecx(unsigned int op)
774{
775 unsigned int tmp, val;
776 cpuid(op, &tmp, &tmp, &val, &tmp);
777 return val;
778}
779
780static inline unsigned int cpuid_edx(unsigned int op)
781{
782 unsigned int tmp, val;
783 cpuid(op, &tmp, &tmp, &tmp, &val);
784 return val;
785}
786
787static sigjmp_buf jenv;
788
789static inline void model3(int _unused)
790{
791 siglongjmp(jenv, 1);
792}
793
794static inline int RPMClass(void)
795{
796 int cpu;
797 unsigned int tfms, junk, cap, capamd;
798 struct sigaction oldsa;
799
800 sigaction(SIGILL4, NULL((void*)0), &oldsa);
801 signal(SIGILL4, model3);
802
803 if (sigsetjmp(jenv, 1)) {
804 sigaction(SIGILL4, &oldsa, NULL((void*)0));
805 return 3;
806 }
807
808 if (cpuid_eax(0x000000000)==0) {
809 sigaction(SIGILL4, &oldsa, NULL((void*)0));
810 return 4;
811 }
812
813 cpuid(0x00000001, &tfms, &junk, &junk, &cap);
814 cpuid(0x80000001, &junk, &junk, &junk, &capamd);
815
816 cpu = (tfms>>8)&15;
817
818 if (cpu == 5
819 && cpuid_ecx(0) == '68xM'
820 && cpuid_edx(0) == 'Teni'
821 && (cpuid_edx(1) & ((1<<8)|(1<<15))) == ((1<<8)|(1<<15))) {
822 sigaction(SIGILL4, &oldsa, NULL((void*)0));
823 return 6; /* has CX8 and CMOV */
824 }
825
826 sigaction(SIGILL4, &oldsa, NULL((void*)0));
827
828#define USER686 ((1<<4) | (1<<8) | (1<<15))
829 /* Transmeta Crusoe CPUs say that their CPU family is "5" but they have enough features for i686. */
830 if (cpu == 5 && (cap & USER686) == USER686)
831 return 6;
832
833 if (cpu < 6)
834 return cpu;
835
836 if (cap & (1<<15)) {
837 /* CMOV supported? */
838 if (capamd & (1<<30))
839 return 7; /* 3DNOWEXT supported */
840 return 6;
841 }
842
843 return 5;
844}
845
846/* should only be called for model 6 CPU's */
847static int is_athlon(void)
848{
849 unsigned int eax, ebx, ecx, edx;
850 char vendor[16];
851 int i;
852
853 cpuid (0, &eax, &ebx, &ecx, &edx);
854
855 memset(vendor, 0, sizeof(vendor));
856
857 for (i=0; i<4; i++)
858 vendor[i] = (unsigned char) (ebx >>(8*i));
859 for (i=0; i<4; i++)
860 vendor[4+i] = (unsigned char) (edx >>(8*i));
861 for (i=0; i<4; i++)
862 vendor[8+i] = (unsigned char) (ecx >>(8*i));
863
864 if (!rstreqn(vendor, "AuthenticAMD", 12))
865 return 0;
866
867 return 1;
868}
869
870static int is_pentium3(void)
871{
872 unsigned int eax, ebx, ecx, edx, family, model;
873 char vendor[16];
874 cpuid(0, &eax, &ebx, &ecx, &edx);
875 memset(vendor, 0, sizeof(vendor));
876 *((unsigned int *)&vendor[0]) = ebx;
877 *((unsigned int *)&vendor[4]) = edx;
878 *((unsigned int *)&vendor[8]) = ecx;
879 if (!rstreqn(vendor, "GenuineIntel", 12))
880 return 0;
881 cpuid(1, &eax, &ebx, &ecx, &edx);
882 family = (eax >> 8) & 0x0f;
883 model = (eax >> 4) & 0x0f;
884 if (family == 6)
885 switch (model)
886 {
887 case 7: // Pentium III, Pentium III Xeon (model 7)
888 case 8: // Pentium III, Pentium III Xeon, Celeron (model 8)
889 case 9: // Pentium M
890 case 10: // Pentium III Xeon (model A)
891 case 11: // Pentium III (model B)
892 return 1;
893 }
894 return 0;
895}
896
897static int is_pentium4(void)
898{
899 unsigned int eax, ebx, ecx, edx, family, model;
900 char vendor[16];
901 cpuid(0, &eax, &ebx, &ecx, &edx);
902 memset(vendor, 0, sizeof(vendor));
903 *((unsigned int *)&vendor[0]) = ebx;
904 *((unsigned int *)&vendor[4]) = edx;
905 *((unsigned int *)&vendor[8]) = ecx;
906 if (!rstreqn(vendor, "GenuineIntel", 12))
907 return 0;
908 cpuid(1, &eax, &ebx, &ecx, &edx);
909 family = (eax >> 8) & 0x0f;
910 model = (eax >> 4) & 0x0f;
911 if (family == 15)
912 switch (model)
913 {
914 case 0: // Pentium 4, Pentium 4 Xeon (0.18um)
915 case 1: // Pentium 4, Pentium 4 Xeon MP, Celeron (0.18um)
916 case 2: // Pentium 4, Mobile Pentium 4-M,
917 // Pentium 4 Xeon, Pentium 4 Xeon MP,
918 // Celeron, Mobile Celron (0.13um)
919 case 3: // Pentium 4, Celeron (0.09um)
920 return 1;
921 }
922 return 0;
923}
924
925static int is_geode(void)
926{
927 unsigned int eax, ebx, ecx, edx, family, model;
928 char vendor[16];
929 memset(vendor, 0, sizeof(vendor));
930
931 cpuid(0, &eax, &ebx, &ecx, &edx);
932 memset(vendor, 0, sizeof(vendor));
933 *((unsigned int *)&vendor[0]) = ebx;
934 *((unsigned int *)&vendor[4]) = edx;
935 *((unsigned int *)&vendor[8]) = ecx;
936 if (!rstreqn(vendor, "AuthenticAMD", 12))
937 return 0;
938 cpuid(1, &eax, &ebx, &ecx, &edx);
939 family = (eax >> 8) & 0x0f;
940 model = (eax >> 4) & 0x0f;
941 if (family == 5)
942 switch (model)
943 {
944 case 10: // Geode
945 return 1;
946 }
947 return 0;
948}
949#endif
950
951
952#if defined(__linux__1)
953/**
954 * Populate rpmat structure with auxv values
955 */
956static void read_auxv(void)
957{
958 static int oneshot = 1;
959
960 if (oneshot) {
961#ifdef HAVE_GETAUXVAL1
962 rpmat.platform = (char *) getauxval(AT_PLATFORM15);
963 if (!rpmat.platform)
964 rpmat.platform = "";
965 rpmat.hwcap = getauxval(AT_HWCAP16);
966#else
967 rpmat.platform = "";
968 int fd = open("/proc/self/auxv", O_RDONLY00);
969
970 if (fd == -1) {
971 rpmlog(RPMLOG_WARNING,
972 _("Failed to read auxiliary vector, /proc not mounted?\n")dcgettext ("rpm", "Failed to read auxiliary vector, /proc not mounted?\n"
, 5)
);
973 return;
974 } else {
975 ElfW(auxv_t)Elf64_auxv_t auxv;
976 while (read(fd, &auxv, sizeof(auxv)) == sizeof(auxv)) {
977 switch (auxv.a_type)
978 {
979 case AT_NULL0:
980 break;
981 case AT_PLATFORM15:
982 rpmat.platform = strdup((char *) auxv.a_un.a_val);
983 break;
984 case AT_HWCAP16:
985 rpmat.hwcap = auxv.a_un.a_val;
986 break;
987 }
988 }
989 close(fd);
990 }
991#endif
992 oneshot = 0; /* only try once even if it fails */
993 }
994 return;
995}
996#endif
997
998/**
999 */
1000static void defaultMachine(rpmrcCtx ctx, const char ** arch, const char ** os)
1001{
1002 const char * const platform_path = SYSCONFDIR"/etc" "/rpm/platform";
1003 static struct utsname un;
1004 char * chptr;
1005 canonEntry canon;
1006 int rc;
1007
1008#if defined(__linux__1)
1009 /* Populate rpmat struct with hw info */
1010 read_auxv();
1011#endif
1012
1013 while (!ctx->machDefaults) {
1014 if (!rpmPlatform(ctx, platform_path)) {
1015 char * s = rpmExpand("%{_host_cpu}", NULL((void*)0));
1016 if (s) {
1017 rstrlcpy(un.machine, s, sizeof(un.machine));
1018 free(s);
1019 }
1020 s = rpmExpand("%{_host_os}", NULL((void*)0));
1021 if (s) {
1022 rstrlcpy(un.sysname, s, sizeof(un.sysname));
1023 free(s);
1024 }
1025 ctx->machDefaults = 1;
1026 break;
1027 }
1028 rc = uname(&un);
1029 if (rc < 0) return;
1030
1031#if !defined(__linux__1)
1032 if (rstreq(un.sysname, "AIX")) {
1033 strcpy(un.machine, __power_pc()0 ? "ppc" : "rs6000");
1034 sprintf(un.sysname,"aix%s.%s", un.version, un.release);
1035 }
1036 else if (rstreq(un.sysname, "Darwin")) {
1037#if defined(__ppc__)
1038 strcpy(un.machine, "ppc");
1039#elif defined(__i386__)
1040 strcpy(un.machine, "i386");
1041#elif defined(__x86_64__1)
1042 strcpy(un.machine, "x86_64");
1043#else
1044 #warning "No architecture defined! Automatic detection may not work!"
1045#endif
1046 }
1047 else if (rstreq(un.sysname, "SunOS")) {
1048 /* Solaris 2.x: n.x.x becomes n-3.x.x */
1049 sprintf(un.sysname, "solaris%1d%s", atoi(un.release)-3,
1050 un.release+1+(atoi(un.release)/10));
1051
1052 /* Solaris on Intel hardware reports i86pc instead of i386
1053 * (at least on 2.6 and 2.8)
1054 */
1055 if (rstreq(un.machine, "i86pc"))
1056 sprintf(un.machine, "i386");
1057 }
1058 else if (rstreq(un.sysname, "HP-UX"))
1059 /*make un.sysname look like hpux9.05 for example*/
1060 sprintf(un.sysname, "hpux%s", strpbrk(un.release, "123456789"));
1061 else if (rstreq(un.sysname, "OSF1"))
1062 /*make un.sysname look like osf3.2 for example*/
1063 sprintf(un.sysname, "osf%s", strpbrk(un.release, "123456789"));
1064#endif /* __linux__ */
1065
1066 /* get rid of the hyphens in the sysname */
1067 for (chptr = un.machine; *chptr != '\0'; chptr++)
1068 if (*chptr == '/') *chptr = '-';
1069
1070# if defined(__MIPSEL__) || defined(__MIPSEL) || defined(_MIPSEL)
1071 /* little endian */
1072# if defined(__mips64)
1073 /* 64-bit */
1074# if !defined(__mips_isa_rev) || __mips_isa_rev < 6
1075 /* r1-r5 */
1076 strcpy(un.machine, "mips64el");
1077# else
1078 /* r6 */
1079 strcpy(un.machine, "mips64r6el");
1080# endif
1081# else
1082 /* 32-bit */
1083# if !defined(__mips_isa_rev) || __mips_isa_rev < 6
1084 /* r1-r5 */
1085 strcpy(un.machine, "mipsel");
1086# else
1087 /* r6 */
1088 strcpy(un.machine, "mipsr6el");
1089# endif
1090# endif
1091# elif defined(__MIPSEB__) || defined(__MIPSEB) || defined(_MIPSEB)
1092 /* big endian */
1093# if defined(__mips64)
1094 /* 64-bit */
1095# if !defined(__mips_isa_rev) || __mips_isa_rev < 6
1096 /* r1-r5 */
1097 strcpy(un.machine, "mips64");
1098# else
1099 /* r6 */
1100 strcpy(un.machine, "mips64r6");
1101# endif
1102# else
1103 /* 32-bit */
1104# if !defined(__mips_isa_rev) || __mips_isa_rev < 6
1105 /* r1-r5 */
1106 strcpy(un.machine, "mips");
1107# else
1108 /* r6 */
1109 strcpy(un.machine, "mipsr6");
1110# endif
1111# endif
1112# endif
1113
1114#if defined(__linux__1)
1115 /* in linux, lets rename parisc to hppa */
1116 if (rstreq(un.machine, "parisc"))
1117 strcpy(un.machine, "hppa");
1118#endif
1119
1120# if defined(__hpux) && defined(_SC_CPU_VERSION)
1121 {
1122# if !defined(CPU_PA_RISC1_2)
1123# define CPU_PA_RISC1_2 0x211 /* HP PA-RISC1.2 */
1124# endif
1125# if !defined(CPU_PA_RISC2_0)
1126# define CPU_PA_RISC2_0 0x214 /* HP PA-RISC2.0 */
1127# endif
1128 int cpu_version = sysconf(_SC_CPU_VERSION);
1129
1130# if defined(CPU_HP_MC68020)
1131 if (cpu_version == CPU_HP_MC68020)
1132 strcpy(un.machine, "m68k");
1133# endif
1134# if defined(CPU_HP_MC68030)
1135 if (cpu_version == CPU_HP_MC68030)
1136 strcpy(un.machine, "m68k");
1137# endif
1138# if defined(CPU_HP_MC68040)
1139 if (cpu_version == CPU_HP_MC68040)
1140 strcpy(un.machine, "m68k");
1141# endif
1142
1143# if defined(CPU_PA_RISC1_0)
1144 if (cpu_version == CPU_PA_RISC1_0)
1145 strcpy(un.machine, "hppa1.0");
1146# endif
1147# if defined(CPU_PA_RISC1_1)
1148 if (cpu_version == CPU_PA_RISC1_1)
1149 strcpy(un.machine, "hppa1.1");
1150# endif
1151# if defined(CPU_PA_RISC1_2)
1152 if (cpu_version == CPU_PA_RISC1_2)
1153 strcpy(un.machine, "hppa1.2");
1154# endif
1155# if defined(CPU_PA_RISC2_0)
1156 if (cpu_version == CPU_PA_RISC2_0)
1157 strcpy(un.machine, "hppa2.0");
1158# endif
1159 }
1160# endif /* hpux */
1161
1162# if defined(__linux__1) && defined(__sparc__)
1163# if !defined(HWCAP_SPARC_BLKINIT)
1164# define HWCAP_SPARC_BLKINIT 0x00000040
1165# endif
1166 if (rstreq(un.machine, "sparc")) {
1167 #define PERS_LINUX 0x00000000
1168 #define PERS_LINUX_32BIT 0x00800000
1169 #define PERS_LINUX32 0x00000008
1170
1171 extern int personality(unsigned long);
1172 int oldpers;
1173
1174 oldpers = personality(PERS_LINUX_32BIT);
1175 if (oldpers != -1) {
1176 if (personality(PERS_LINUX) != -1) {
1177 uname(&un);
1178 if (rstreq(un.machine, "sparc64")) {
1179 strcpy(un.machine, "sparcv9");
1180 oldpers = PERS_LINUX32;
1181 }
1182 }
1183 personality(oldpers);
1184 }
1185
1186 /* This is how glibc detects Niagara so... */
1187 if (rpmat.hwcap & HWCAP_SPARC_BLKINIT) {
1188 if (rstreq(un.machine, "sparcv9") || rstreq(un.machine, "sparc")) {
1189 strcpy(un.machine, "sparcv9v");
1190 } else if (rstreq(un.machine, "sparc64")) {
1191 strcpy(un.machine, "sparc64v");
1192 }
1193 }
1194 }
1195# endif /* sparc*-linux */
1196
1197# if defined(__linux__1) && defined(__powerpc__)
1198# if __BYTE_ORDER__1234 == __ORDER_BIG_ENDIAN__4321
1199 {
1200 int powerlvl;
1201 if (!rstreq(un.machine, "ppc") &&
1202 sscanf(rpmat.platform, "power%d", &powerlvl) == 1 &&
1203 powerlvl > 6) {
1204 strcpy(un.machine, "ppc64p7");
1205 }
1206 }
1207# endif /* __ORDER_BIG_ENDIAN__ */
1208# endif /* ppc64*-linux */
1209
1210# if defined(__linux__1) && defined(__arm__) && defined(__ARM_PCS_VFP)
1211# if !defined(HWCAP_ARM_VFP)
1212# define HWCAP_ARM_VFP (1 << 6)
1213# endif
1214# if !defined(HWCAP_ARM_NEON)
1215# define HWCAP_ARM_NEON (1 << 12)
1216# endif
1217# if !defined(HWCAP_ARM_VFPv3)
1218# define HWCAP_ARM_VFPv3 (1 << 13)
1219# endif
1220 if (rstreq(un.machine, "armv7l")) {
1221 if (rpmat.hwcap & HWCAP_ARM_VFPv3) {
1222 if (rpmat.hwcap & HWCAP_ARM_NEON)
1223 strcpy(un.machine, "armv7hnl");
1224 else
1225 strcpy(un.machine, "armv7hl");
1226 }
1227 } else if (rstreq(un.machine, "armv6l")) {
1228 if (rpmat.hwcap & HWCAP_ARM_VFP)
1229 strcpy(un.machine, "armv6hl");
1230 }
1231# endif /* arm*-linux */
1232
1233# if defined(__linux__1) && defined(__riscv__)
1234 if (rstreq(un.machine, "riscv")) {
1235 if (sizeof(long) == 4)
1236 strcpy(un.machine, "riscv32");
1237 else if (sizeof(long) == 8)
1238 strcpy(un.machine, "riscv64");
1239 else if (sizeof(long) == 16)
1240 strcpy(un.machine, "riscv128");
1241 }
1242# endif /* riscv */
1243
1244# if defined(__GNUC__4) && defined(__alpha__)
1245 {
1246 unsigned long amask, implver;
1247 register long v0 __asm__("$0") = -1;
1248 __asm__ (".long 0x47e00c20" : "=r"(v0) : "0"(v0));
1249 amask = ~v0;
1250 __asm__ (".long 0x47e03d80" : "=r"(v0));
1251 implver = v0;
1252 switch (implver) {
1253 case 1:
1254 switch (amask) {
1255 case 0: strcpy(un.machine, "alphaev5"); break;
1256 case 1: strcpy(un.machine, "alphaev56"); break;
1257 case 0x101: strcpy(un.machine, "alphapca56"); break;
1258 }
1259 break;
1260 case 2:
1261 switch (amask) {
1262 case 0x303: strcpy(un.machine, "alphaev6"); break;
1263 case 0x307: strcpy(un.machine, "alphaev67"); break;
1264 }
1265 break;
1266 }
1267 }
1268# endif
1269
1270# if defined(__linux__1) && defined(__i386__)
1271 {
1272 char mclass = (char) (RPMClass() | '0');
1273
1274 if ((mclass == '6' && is_athlon()) || mclass == '7')
1275 strcpy(un.machine, "athlon");
1276 else if (is_pentium4())
1277 strcpy(un.machine, "pentium4");
1278 else if (is_pentium3())
1279 strcpy(un.machine, "pentium3");
1280 else if (is_geode())
1281 strcpy(un.machine, "geode");
1282 else if (strchr("3456", un.machine[1]) && un.machine[1] != mclass)
1283 un.machine[1] = mclass;
1284 }
1285# endif
1286
1287 /* the uname() result goes through the arch_canon table */
1288 canon = lookupInCanonTable(un.machine,
1289 ctx->tables[RPM_MACHTABLE_INSTARCH].canons,
1290 ctx->tables[RPM_MACHTABLE_INSTARCH].canonsLength);
1291 if (canon)
1292 rstrlcpy(un.machine, canon->short_name, sizeof(un.machine));
1293
1294 canon = lookupInCanonTable(un.sysname,
1295 ctx->tables[RPM_MACHTABLE_INSTOS].canons,
1296 ctx->tables[RPM_MACHTABLE_INSTOS].canonsLength);
1297 if (canon)
1298 rstrlcpy(un.sysname, canon->short_name, sizeof(un.sysname));
1299 ctx->machDefaults = 1;
1300 break;
1301 }
1302
1303 if (arch) *arch = un.machine;
1304 if (os) *os = un.sysname;
1305}
1306
1307static
1308const char * rpmGetVarArch(rpmrcCtx ctx, int var, const char * arch)
1309{
1310 const struct rpmvarValue * next;
1311
1312 if (arch == NULL((void*)0)) arch = ctx->current[ARCH1];
1313
1314 if (arch) {
1315 next = &ctx->values[var];
1316 while (next) {
1317 if (next->arch && rstreq(next->arch, arch)) return next->value;
1318 next = next->next;
1319 }
1320 }
1321
1322 next = ctx->values + var;
1323 while (next && next->arch) next = next->next;
1324
1325 return next ? next->value : NULL((void*)0);
1326}
1327
1328static void rpmSetVarArch(rpmrcCtx ctx,
1329 int var, const char * val, const char * arch)
1330{
1331 struct rpmvarValue * next = ctx->values + var;
1332
1333 if (next->value) {
1334 if (arch) {
1335 while (next->next) {
1336 if (next->arch && rstreq(next->arch, arch)) break;
1337 next = next->next;
1338 }
1339 } else {
1340 while (next->next) {
1341 if (!next->arch) break;
1342 next = next->next;
1343 }
1344 }
1345
1346 if (next->arch && arch && rstreq(next->arch, arch)) {
1347 next->value = _free(next->value)rfree((next->value));
1348 next->arch = _free(next->arch)rfree((next->arch));
1349 } else if (next->arch || arch) {
1350 next->next = xmalloc(sizeof(*next->next))rmalloc((sizeof(*next->next)));
1351 next = next->next;
1352 next->value = NULL((void*)0);
1353 next->arch = NULL((void*)0);
1354 next->next = NULL((void*)0);
1355 }
1356 }
1357
1358 next->value = _free(next->value)rfree((next->value));
1359 next->value = xstrdup(val)rstrdup((val));
1360 next->arch = (arch ? xstrdup(arch)rstrdup((arch)) : NULL((void*)0));
1361}
1362
1363static void rpmSetTables(rpmrcCtx ctx, int archTable, int osTable)
1364{
1365 const char * arch, * os;
1366
1367 defaultMachine(ctx, &arch, &os);
1368
1369 if (ctx->currTables[ARCH1] != archTable) {
1370 ctx->currTables[ARCH1] = archTable;
1371 rebuildCompatTables(ctx, ARCH1, arch);
1372 }
1373
1374 if (ctx->currTables[OS0] != osTable) {
1375 ctx->currTables[OS0] = osTable;
1376 rebuildCompatTables(ctx, OS0, os);
1377 }
1378}
1379
1380/** \ingroup rpmrc
1381 * Set current arch/os names.
1382 * NULL as argument is set to the default value (munged uname())
1383 * pushed through a translation table (if appropriate).
1384 * @deprecated Use addMacro to set _target_* macros.
1385 * @todo Eliminate
1386 *
1387 * @param ctx rpmrc context
1388 * @param arch arch name (or NULL)
1389 * @param os os name (or NULL)
1390 * */
1391
1392static void rpmSetMachine(rpmrcCtx ctx, const char * arch, const char * os)
1393{
1394 const char * host_cpu, * host_os;
1395
1396 defaultMachine(ctx, &host_cpu, &host_os);
1397
1398 if (arch == NULL((void*)0)) {
1399 arch = host_cpu;
1400 if (ctx->tables[ctx->currTables[ARCH1]].hasTranslate)
1401 arch = lookupInDefaultTable(arch,
1402 ctx->tables[ctx->currTables[ARCH1]].defaults,
1403 ctx->tables[ctx->currTables[ARCH1]].defaultsLength);
1404 }
1405 if (arch == NULL((void*)0)) return; /* XXX can't happen */
1406
1407 if (os == NULL((void*)0)) {
1408 os = host_os;
1409 if (ctx->tables[ctx->currTables[OS0]].hasTranslate)
1410 os = lookupInDefaultTable(os,
1411 ctx->tables[ctx->currTables[OS0]].defaults,
1412 ctx->tables[ctx->currTables[OS0]].defaultsLength);
1413 }
1414 if (os == NULL((void*)0)) return; /* XXX can't happen */
1415
1416 if (!ctx->current[ARCH1] || !rstreq(arch, ctx->current[ARCH1])) {
1417 ctx->current[ARCH1] = _free(ctx->current[ARCH])rfree((ctx->current[1]));
1418 ctx->current[ARCH1] = xstrdup(arch)rstrdup((arch));
1419 rebuildCompatTables(ctx, ARCH1, host_cpu);
1420 }
1421
1422 if (!ctx->current[OS0] || !rstreq(os, ctx->current[OS0])) {
1423 char * t = xstrdup(os)rstrdup((os));
1424 ctx->current[OS0] = _free(ctx->current[OS])rfree((ctx->current[0]));
1425 /*
1426 * XXX Capitalizing the 'L' is needed to insure that old
1427 * XXX os-from-uname (e.g. "Linux") is compatible with the new
1428 * XXX os-from-platform (e.g "linux" from "sparc-*-linux").
1429 * XXX A copy of this string is embedded in headers and is
1430 * XXX used by rpmInstallPackage->{os,arch}Okay->rpmMachineScore->
1431 * XXX to verify correct arch/os from headers.
1432 */
1433 if (rstreq(t, "linux"))
1434 *t = 'L';
1435 ctx->current[OS0] = t;
1436
1437 rebuildCompatTables(ctx, OS0, host_os);
1438 }
1439}
1440
1441static void rebuildCompatTables(rpmrcCtx ctx, int type, const char * name)
1442{
1443 machFindEquivs(&ctx->tables[ctx->currTables[type]].cache,
1444 &ctx->tables[ctx->currTables[type]].equiv,
1445 name);
1446}
1447
1448static void getMachineInfo(rpmrcCtx ctx,
1449 int type, const char ** name, int * num)
1450{
1451 canonEntry canon;
1452 int which = ctx->currTables[type];
1453
1454 /* use the normal canon tables, even if we're looking up build stuff */
1455 if (which >= 2) which -= 2;
1456
1457 canon = lookupInCanonTable(ctx->current[type],
1458 ctx->tables[which].canons,
1459 ctx->tables[which].canonsLength);
1460
1461 if (canon) {
1462 if (num) *num = canon->num;
1463 if (name) *name = canon->short_name;
1464 } else {
1465 if (num) *num = 255;
1466 if (name) *name = ctx->current[type];
1467
1468 if (ctx->tables[ctx->currTables[type]].hasCanon) {
1469 rpmlog(RPMLOG_WARNING, _("Unknown system: %s\n")dcgettext ("rpm", "Unknown system: %s\n", 5),
1470 ctx->current[type]);
1471 rpmlog(RPMLOG_WARNING, _("Please contact %s\n")dcgettext ("rpm", "Please contact %s\n", 5), PACKAGE_BUGREPORT"rpm-maint@lists.rpm.org");
1472 }
1473 }
1474}
1475
1476static void rpmRebuildTargetVars(rpmrcCtx ctx,
1477 const char ** target, const char ** canontarget)
1478{
1479
1480 char *ca = NULL((void*)0), *co = NULL((void*)0), *ct = NULL((void*)0);
1481 int x;
1482
1483 /* Rebuild the compat table to recalculate the current target arch. */
1484
1485 rpmSetMachine(ctx, NULL((void*)0), NULL((void*)0));
1486 rpmSetTables(ctx, RPM_MACHTABLE_INSTARCH, RPM_MACHTABLE_INSTOS);
1487 rpmSetTables(ctx, RPM_MACHTABLE_BUILDARCH, RPM_MACHTABLE_BUILDOS);
1488
1489 if (target && *target) {
1490 char *c;
1491 /* Set arch and os from specified build target */
1492 ca = xstrdup(*target)rstrdup((*target));
1493 if ((c = strchr(ca, '-')) != NULL((void*)0)) {
1494 *c++ = '\0';
1495
1496 if ((co = strrchr(c, '-')) == NULL((void*)0)) {
1497 co = c;
1498 } else {
1499 if (!rstrcasecmp(co, "-gnu"))
1500 *co = '\0';
1501 if ((co = strrchr(c, '-')) == NULL((void*)0))
1502 co = c;
1503 else
1504 co++;
1505 }
1506 if (co != NULL((void*)0)) co = xstrdup(co)rstrdup((co));
1507 }
1508 } else {
1509 const char *a = NULL((void*)0);
1510 const char *o = NULL((void*)0);
1511 /* Set build target from rpm arch and os */
1512 getMachineInfo(ctx, ARCH1, &a, NULL((void*)0));
1513 ca = (a) ? xstrdup(a)rstrdup((a)) : NULL((void*)0);
1514 getMachineInfo(ctx, OS0, &o, NULL((void*)0));
1515 co = (o) ? xstrdup(o)rstrdup((o)) : NULL((void*)0);
1516 }
1517
1518 /* If still not set, Set target arch/os from default uname(2) values */
1519 if (ca == NULL((void*)0)) {
1520 const char *a = NULL((void*)0);
1521 defaultMachine(ctx, &a, NULL((void*)0));
1522 ca = xstrdup(a ? a : "(arch)")rstrdup((a ? a : "(arch)"));
1523 }
1524 for (x = 0; ca[x] != '\0'; x++)
1525 ca[x] = rtolower(ca[x]);
1526
1527 if (co == NULL((void*)0)) {
1528 const char *o = NULL((void*)0);
1529 defaultMachine(ctx, NULL((void*)0), &o);
1530 co = xstrdup(o ? o : "(os)")rstrdup((o ? o : "(os)"));
1531 }
1532 for (x = 0; co[x] != '\0'; x++)
1533 co[x] = rtolower(co[x]);
1534
1535 /* XXX For now, set canonical target to arch-os */
1536 if (ct == NULL((void*)0)) {
1537 rasprintf(&ct, "%s-%s", ca, co);
1538 }
1539
1540/*
1541 * XXX All this macro pokery/jiggery could be achieved by doing a delayed
1542 * rpmInitMacros(NULL, PER-PLATFORM-MACRO-FILE-NAMES);
1543 */
1544 rpmPopMacro(NULL((void*)0), "_target");
1545 rpmPushMacro(NULL((void*)0), "_target", NULL((void*)0), ct, RMIL_RPMRC-11);
1546 rpmPopMacro(NULL((void*)0), "_target_cpu");
1547 rpmPushMacro(NULL((void*)0), "_target_cpu", NULL((void*)0), ca, RMIL_RPMRC-11);
1548 rpmPopMacro(NULL((void*)0), "_target_os");
1549 rpmPushMacro(NULL((void*)0), "_target_os", NULL((void*)0), co, RMIL_RPMRC-11);
1550/*
1551 * XXX Make sure that per-arch optflags is initialized correctly.
1552 */
1553 { const char *optflags = rpmGetVarArch(ctx, RPMVAR_OPTFLAGS3, ca);
1554 if (optflags != NULL((void*)0)) {
1555 rpmPopMacro(NULL((void*)0), "optflags");
1556 rpmPushMacro(NULL((void*)0), "optflags", NULL((void*)0), optflags, RMIL_RPMRC-11);
1557 }
1558 }
1559
1560 if (canontarget)
1561 *canontarget = ct;
1562 else
1563 free(ct);
1564 free(ca);
1565 free(co);
1566}
1567
1568/** \ingroup rpmrc
1569 * Read rpmrc (and macro) configuration file(s).
1570 * @param ctx rpmrc context
1571 * @param rcfiles colon separated files to read (NULL uses default)
1572 * @return RPMRC_OK on success
1573 */
1574static rpmRC rpmReadRC(rpmrcCtx ctx, const char * rcfiles)
1575{
1576 ARGV_t p, globs = NULL((void*)0), files = NULL((void*)0);
1577 rpmRC rc = RPMRC_FAIL;
1578
1579 if (!ctx->pathDefaults) {
1580 setDefaults();
1581 ctx->pathDefaults = 1;
1582 }
1583
1584 if (rcfiles == NULL((void*)0))
1585 rcfiles = defrcfiles;
1586
1587 /* Expand any globs in rcfiles. Missing files are ok here. */
1588 argvSplit(&globs, rcfiles, ":");
1589 for (p = globs; *p; p++) {
1590 ARGV_t av = NULL((void*)0);
1591 if (rpmGlob(*p, NULL((void*)0), &av) == 0) {
1592 argvAppend(&files, av);
1593 argvFree(av);
1594 }
1595 }
1596 argvFree(globs);
1597
1598 /* Read each file in rcfiles. */
1599 for (p = files; p && *p; p++) {
1600 /* XXX Only /usr/lib/rpm/rpmrc must exist in default rcfiles list */
1601 if (access(*p, R_OK4) != 0) {
1602 if (rcfiles == defrcfiles && p != files)
1603 continue;
1604 rpmlog(RPMLOG_ERR, _("Unable to open %s for reading: %m.\n")dcgettext ("rpm", "Unable to open %s for reading: %m.\n", 5), *p);
1605 goto exit;
1606 break;
1607 } else {
1608 rc = doReadRC(ctx, *p);
1609 }
1610 }
1611 rc = RPMRC_OK;
1612 rpmSetMachine(ctx, NULL((void*)0), NULL((void*)0)); /* XXX WTFO? Why bother? */
1613
1614exit:
1615 argvFree(files);
1616 return rc;
1617}
1618
1619static void register_atexit(void)
1620{
1621 if (atexit(rpmAtExit) != 0)
1622 rpmlog(RPMLOG_WARNING, _("failed to register exit handler")dcgettext ("rpm", "failed to register exit handler", 5));
1623}
1624
1625/* External interfaces */
1626
1627int rpmReadConfigFiles(const char * file, const char * target)
1628{
1629 static pthread_once_t atexit_registered = PTHREAD_ONCE_INIT0;
1630 int rc = -1; /* assume failure */
1631 rpmrcCtx ctx = rpmrcCtxAcquire(1);
1632
1633 pthread_once(&atexit_registered, register_atexit);
1634
1635 /* Force preloading of dlopen()'ed libraries in case we go chrooting */
1636 if (rpmugInit())
1637 goto exit;
1638
1639 if (rpmInitCrypto())
1640 goto exit;
1641
1642 /* Preset target macros */
1643 /* FIX: target can be NULL */
1644 rpmRebuildTargetVars(ctx, &target, NULL((void*)0));
1645
1646 /* Read the files */
1647 if (rpmReadRC(ctx, file))
1648 goto exit;
1649
1650 if (macrofiles != NULL((void*)0)) {
1651 char *mf = rpmGetPath(macrofiles, NULL((void*)0));
1652 rpmInitMacros(NULL((void*)0), mf);
1653 _free(mf)rfree((mf));
1654 }
1655
1656 /* Reset target macros */
1657 rpmRebuildTargetVars(ctx, &target, NULL((void*)0));
1658
1659 /* Finally set target platform */
1660 { char *cpu = rpmExpand("%{_target_cpu}", NULL((void*)0));
1661 char *os = rpmExpand("%{_target_os}", NULL((void*)0));
1662 rpmSetMachine(ctx, cpu, os);
1663 free(cpu);
1664 free(os);
1665 }
1666
1667#ifdef WITH_LUA1
1668 /* Force Lua state initialization */
1669 rpmLuaInit();
1670#endif
1671 rc = 0;
1672
1673exit:
1674 rpmrcCtxRelease(ctx);
1675 return rc;
1676}
1677
1678void rpmFreeRpmrc(void)
1679{
1680 rpmrcCtx ctx = rpmrcCtxAcquire(1);
1681 int i, j, k;
1682
1683 ctx->platpat = argvFree(ctx->platpat);
1684
1685 for (i = 0; i < RPM_MACHTABLE_COUNT4; i++) {
1686 tableType t;
1687 t = ctx->tables + i;
1688 if (t->equiv.list) {
1689 for (j = 0; j < t->equiv.count; j++)
1690 t->equiv.list[j].name = _free(t->equiv.list[j].name)rfree((t->equiv.list[j].name));
1691 t->equiv.list = _free(t->equiv.list)rfree((t->equiv.list));
1692 t->equiv.count = 0;
1693 }
1694 if (t->cache.cache) {
1695 for (j = 0; j < t->cache.size; j++) {
1696 machCacheEntry e;
1697 e = t->cache.cache + j;
1698 if (e == NULL((void*)0))
1699 continue;
1700 e->name = _free(e->name)rfree((e->name));
1701 if (e->equivs) {
1702 for (k = 0; k < e->count; k++)
1703 e->equivs[k] = _free(e->equivs[k])rfree((e->equivs[k]));
1704 e->equivs = _free(e->equivs)rfree((e->equivs));
1705 }
1706 }
1707 t->cache.cache = _free(t->cache.cache)rfree((t->cache.cache));
1708 t->cache.size = 0;
1709 }
1710 if (t->defaults) {
1711 for (j = 0; j < t->defaultsLength; j++) {
1712 t->defaults[j].name = _free(t->defaults[j].name)rfree((t->defaults[j].name));
1713 t->defaults[j].defName = _free(t->defaults[j].defName)rfree((t->defaults[j].defName));
1714 }
1715 t->defaults = _free(t->defaults)rfree((t->defaults));
1716 t->defaultsLength = 0;
1717 }
1718 if (t->canons) {
1719 for (j = 0; j < t->canonsLength; j++) {
1720 t->canons[j].name = _free(t->canons[j].name)rfree((t->canons[j].name));
1721 t->canons[j].short_name = _free(t->canons[j].short_name)rfree((t->canons[j].short_name));
1722 }
1723 t->canons = _free(t->canons)rfree((t->canons));
1724 t->canonsLength = 0;
1725 }
1726 }
1727
1728 for (i = 0; i < RPMVAR_NUM55; i++) {
1729 struct rpmvarValue * vp;
1730 while ((vp = ctx->values[i].next) != NULL((void*)0)) {
1731 ctx->values[i].next = vp->next;
1732 vp->value = _free(vp->value)rfree((vp->value));
1733 vp->arch = _free(vp->arch)rfree((vp->arch));
1734 vp = _free(vp)rfree((vp));
1735 }
1736 ctx->values[i].value = _free(ctx->values[i].value)rfree((ctx->values[i].value));
1737 ctx->values[i].arch = _free(ctx->values[i].arch)rfree((ctx->values[i].arch));
1738 }
1739 ctx->current[OS0] = _free(ctx->current[OS])rfree((ctx->current[0]));
1740 ctx->current[ARCH1] = _free(ctx->current[ARCH])rfree((ctx->current[1]));
1741 ctx->machDefaults = 0;
1742 ctx->pathDefaults = 0;
1743
1744 /* XXX doesn't really belong here but... */
1745 rpmFreeCrypto();
1746#ifdef WITH_LUA1
1747 rpmLuaFree();
1748#endif
1749
1750 rpmrcCtxRelease(ctx);
1751 return;
1752}
1753
1754int rpmShowRC(FILE * fp)
1755{
1756 /* Write-context necessary as this calls rpmSetTables(), ugh */
1757 rpmrcCtx ctx = rpmrcCtxAcquire(1);
1758 const struct rpmOption *opt;
1759 rpmds ds = NULL((void*)0);
1760 int i;
1761 machEquivTable equivTable;
1762
1763 /* the caller may set the build arch which should be printed here */
1764 fprintf(fp, "ARCHITECTURE AND OS:\n");
1765 fprintf(fp, "build arch : %s\n", ctx->current[ARCH1]);
1766
1767 fprintf(fp, "compatible build archs:");
1768 equivTable = &ctx->tables[RPM_MACHTABLE_BUILDARCH].equiv;
1769 for (i = 0; i < equivTable->count; i++)
1770 fprintf(fp," %s", equivTable->list[i].name);
1771 fprintf(fp, "\n");
1772
1773 fprintf(fp, "build os : %s\n", ctx->current[OS0]);
1774
1775 fprintf(fp, "compatible build os's :");
1776 equivTable = &ctx->tables[RPM_MACHTABLE_BUILDOS].equiv;
1777 for (i = 0; i < equivTable->count; i++)
1778 fprintf(fp," %s", equivTable->list[i].name);
1779 fprintf(fp, "\n");
1780
1781 rpmSetTables(ctx, RPM_MACHTABLE_INSTARCH, RPM_MACHTABLE_INSTOS);
1782 rpmSetMachine(ctx, NULL((void*)0), NULL((void*)0)); /* XXX WTFO? Why bother? */
1783
1784 fprintf(fp, "install arch : %s\n", ctx->current[ARCH1]);
1785 fprintf(fp, "install os : %s\n", ctx->current[OS0]);
1786
1787 fprintf(fp, "compatible archs :");
1788 equivTable = &ctx->tables[RPM_MACHTABLE_INSTARCH].equiv;
1789 for (i = 0; i < equivTable->count; i++)
1790 fprintf(fp," %s", equivTable->list[i].name);
1791 fprintf(fp, "\n");
1792
1793 fprintf(fp, "compatible os's :");
1794 equivTable = &ctx->tables[RPM_MACHTABLE_INSTOS].equiv;
1795 for (i = 0; i < equivTable->count; i++)
1796 fprintf(fp," %s", equivTable->list[i].name);
1797 fprintf(fp, "\n");
1798
1799 fprintf(fp, "\nRPMRC VALUES:\n");
1800 for (i = 0, opt = optionTable; i < optionTableSize; i++, opt++) {
1801 const char *s = rpmGetVarArch(ctx, opt->var, NULL((void*)0));
1802 if (s != NULL((void*)0) || rpmIsVerbose()(rpmlogSetMask(0) >= (1 << ((unsigned)(RPMLOG_INFO))
))
)
1803 fprintf(fp, "%-21s : %s\n", opt->name, s ? s : "(not set)");
1804 }
1805 fprintf(fp, "\n");
1806
1807 fprintf(fp, "Features supported by rpmlib:\n");
1808 rpmdsRpmlib(&ds, NULL((void*)0));
1809 ds = rpmdsInit(ds);
1810 while (rpmdsNext(ds) >= 0) {
1811 const char * DNEVR = rpmdsDNEVR(ds);
1812 if (DNEVR != NULL((void*)0))
1813 fprintf(fp, " %s\n", DNEVR+2);
1814 }
1815 ds = rpmdsFree(ds);
1816 fprintf(fp, "\n");
1817
1818 fprintf(fp, "Macro path: %s\n", macrofiles);
1819 fprintf(fp, "\n");
1820
1821 rpmDumpMacroTable(NULL((void*)0), fp);
1822
1823 /* XXX: Move this earlier eventually... */
1824 rpmrcCtxRelease(ctx);
1825
1826 return 0;
1827}
1828
1829int rpmMachineScore(int type, const char * name)
1830{
1831 int score = 0;
1832 if (name) {
1833 rpmrcCtx ctx = rpmrcCtxAcquire(0);
1834 machEquivInfo info = machEquivSearch(&ctx->tables[type].equiv, name);
1835 if (info)
1836 score = info->score;
1837 rpmrcCtxRelease(ctx);
1838 }
1839 return score;
1840}
1841
1842int rpmIsKnownArch(const char *name)
1843{
1844 rpmrcCtx ctx = rpmrcCtxAcquire(0);
1845 canonEntry canon = lookupInCanonTable(name,
1846 ctx->tables[RPM_MACHTABLE_INSTARCH].canons,
1847 ctx->tables[RPM_MACHTABLE_INSTARCH].canonsLength);
1848 int known = (canon != NULL((void*)0) || rstreq(name, "noarch"));
1849 rpmrcCtxRelease(ctx);
1850 return known;
1851}
1852
1853void rpmGetArchInfo(const char ** name, int * num)
1854{
1855 rpmrcCtx ctx = rpmrcCtxAcquire(0);
1856 getMachineInfo(ctx, ARCH1, name, num);
1857 rpmrcCtxRelease(ctx);
1858}
1859
1860int rpmGetArchColor(const char *arch)
1861{
1862 rpmrcCtx ctx = rpmrcCtxAcquire(0);
1863 const char *color;
1864 char *e;
1865 int color_i = -1; /* assume failure */
1866
1867 arch = lookupInDefaultTable(arch,
1868 ctx->tables[ctx->currTables[ARCH1]].defaults,
1869 ctx->tables[ctx->currTables[ARCH1]].defaultsLength);
1870 color = rpmGetVarArch(ctx, RPMVAR_ARCHCOLOR42, arch);
1871 if (color) {
1872 color_i = strtol(color, &e, 10);
1873 if (!(e && *e == '\0')) {
1874 color_i = -1;
1875 }
1876 }
1877 rpmrcCtxRelease(ctx);
1878
1879 return color_i;
1880}
1881
1882void rpmGetOsInfo(const char ** name, int * num)
1883{
1884 rpmrcCtx ctx = rpmrcCtxAcquire(0);
1885 getMachineInfo(ctx, OS0, name, num);
1886 rpmrcCtxRelease(ctx);
1887}
1888