rpm  4.5
rpmrc.c
Go to the documentation of this file.
1 /*@-bounds@*/
2 #include "system.h"
3 
4 #include <stdarg.h>
5 #if defined(__linux__) && defined(__powerpc__)
6 #include <setjmp.h>
7 #endif
8 
9 #if HAVE_SYS_SYSTEMCFG_H
10 #include <sys/systemcfg.h>
11 #else
12 #define __power_pc() 0
13 #endif
14 
15 #include "rpmio_internal.h"
16 #include <rpmcli.h>
17 #include <rpmmacro.h>
18 #include <rpmlua.h>
19 #include <rpmds.h>
20 
21 #define _MIRE_INTERNAL
22 #include <mire.h>
23 
24 #include "misc.h"
25 #include "debug.h"
26 
27 /*@observer@*/ /*@checked@*/
28 const char *rpmRcfiles = RPMRCFILES;
29 
30 /*@unchecked@*/ /*@null@*/
31 static const char * configTarget = NULL;
32 
33 /*@observer@*/ /*@unchecked@*/
34 static const char * platform = "/etc/rpm/platform";
35 /*@only@*/ /*@relnull@*/ /*@unchecked@*/
36 void * platpat = NULL;
37 /*@unchecked@*/
38 int nplatpat = 0;
39 
40 typedef /*@owned@*/ const char * cptr_t;
41 
42 typedef struct machCacheEntry_s {
43  const char * name;
44  int count;
46  int visited;
47 } * machCacheEntry;
48 
49 typedef struct machCache_s {
51  int size;
52 } * machCache;
53 
54 typedef struct machEquivInfo_s {
55  const char * name;
56  int score;
57 } * machEquivInfo;
58 
59 typedef struct machEquivTable_s {
60  int count;
62 } * machEquivTable;
63 
64 struct rpmvarValue {
65  const char * value;
66  /* eventually, this arch will be replaced with a generic condition */
67  const char * arch;
68 /*@only@*/ /*@null@*/ struct rpmvarValue * next;
69 };
70 
71 struct rpmOption {
72  const char * name;
73  int var;
75 /*@unused@*/ int required;
76  int macroize;
77  int localize;
78 /*@unused@*/ struct rpmOptionValue * value;
79 };
80 
81 typedef struct defaultEntry_s {
82 /*@owned@*/ /*@null@*/ const char * name;
83 /*@owned@*/ /*@null@*/ const char * defName;
84 } * defaultEntry;
85 
86 typedef struct canonEntry_s {
87 /*@owned@*/ const char * name;
88 /*@owned@*/ const char * short_name;
89  short num;
90 } * canonEntry;
91 
92 /* tags are 'key'canon, 'key'translate, 'key'compat
93  *
94  * for giggles, 'key'_canon, 'key'_compat, and 'key'_canon will also work
95  */
96 typedef struct tableType_s {
97 /*@observer@*/ const char * const key;
98  const int hasCanon;
99  const int hasTranslate;
106 } * tableType;
107 
108 /*@-fullinitblock@*/
109 /*@unchecked@*/
111  { "arch", 1, 0 },
112  { "os", 1, 0 },
113  { "buildarch", 0, 1 },
114  { "buildos", 0, 1 }
115 };
116 
117 /* this *must* be kept in alphabetical order */
118 /* The order of the flags is archSpecific, required, macroize, localize */
119 
120 #define RPMVAR_OPTFLAGS 3
121 #define RPMVAR_INCLUDE 43
122 #define RPMVAR_MACROFILES 49
123 
124 #define RPMVAR_NUM 55 /* number of RPMVAR entries */
125 /*@unchecked@*/
126 static struct rpmOption optionTable[] = {
127  { "include", RPMVAR_INCLUDE, 0, 1, 0, 2 },
128  { "macrofiles", RPMVAR_MACROFILES, 0, 0, 0, 1 },
129  { "optflags", RPMVAR_OPTFLAGS, 1, 0, 1, 0 },
130 };
131 /*@=fullinitblock@*/
132 
133 /*@unchecked@*/
134 static int optionTableSize = sizeof(optionTable) / sizeof(*optionTable);
135 
136 #define OS 0
137 #define ARCH 1
138 
139 /*@unchecked@*/
140 static cptr_t current[2];
141 
142 /*@unchecked@*/
144 
145 /*@unchecked@*/
147 
148 /*@unchecked@*/
149 static int defaultsInitialized = 0;
150 
151 /* prototypes */
152 static void rpmRebuildTargetVars(/*@null@*/ const char **target, /*@null@*/ const char ** canontarget)
153  /*@globals rpmGlobalMacroContext, h_errno, fileSystem, internalState @*/
154  /*@modifies *canontarget, rpmGlobalMacroContext,
155  fileSystem, internalState @*/;
156 
157 static int optionCompare(const void * a, const void * b)
158  /*@*/
159 {
160  return xstrcasecmp(((struct rpmOption *) a)->name,
161  ((struct rpmOption *) b)->name);
162 }
163 
164 static /*@observer@*/ /*@null@*/ machCacheEntry
165 machCacheFindEntry(const machCache cache, const char * key)
166  /*@*/
167 {
168  int i;
169 
170  for (i = 0; i < cache->size; i++)
171  if (!strcmp(cache->cache[i].name, key)) return cache->cache + i;
172 
173  return NULL;
174 }
175 
176 static int machCompatCacheAdd(char * name, const char * fn, int linenum,
177  machCache cache)
178  /*@globals internalState @*/
179  /*@modifies *name, cache->cache, cache->size, internalState @*/
180 {
181  machCacheEntry entry = NULL;
182  char * chptr;
183  char * equivs;
184  int delEntry = 0;
185  int i;
186 
187  while (*name && xisspace(*name)) name++;
188 
189  chptr = name;
190  while (*chptr && *chptr != ':') chptr++;
191  if (!*chptr) {
192  rpmError(RPMERR_RPMRC, _("missing second ':' at %s:%d\n"), fn, linenum);
193  return 1;
194  } else if (chptr == name) {
195  rpmError(RPMERR_RPMRC, _("missing architecture name at %s:%d\n"), fn,
196  linenum);
197  return 1;
198  }
199 
200  while (*chptr == ':' || xisspace(*chptr)) chptr--;
201  *(++chptr) = '\0';
202  equivs = chptr + 1;
203  while (*equivs && xisspace(*equivs)) equivs++;
204  if (!*equivs) {
205  delEntry = 1;
206  }
207 
208  if (cache->size) {
209  entry = machCacheFindEntry(cache, name);
210  if (entry) {
211  for (i = 0; i < entry->count; i++)
212  entry->equivs[i] = _free(entry->equivs[i]);
213  entry->equivs = _free(entry->equivs);
214  entry->count = 0;
215  }
216  }
217 
218  if (!entry) {
219  cache->cache = xrealloc(cache->cache,
220  (cache->size + 1) * sizeof(*cache->cache));
221  entry = cache->cache + cache->size++;
222  entry->name = xstrdup(name);
223  entry->count = 0;
224  entry->visited = 0;
225  }
226 
227  if (delEntry) return 0;
228 
229  while ((chptr = strtok(equivs, " ")) != NULL) {
230  equivs = NULL;
231  if (chptr[0] == '\0') /* does strtok() return "" ever?? */
232  continue;
233  if (entry->count)
234  entry->equivs = xrealloc(entry->equivs, sizeof(*entry->equivs)
235  * (entry->count + 1));
236  else
237  entry->equivs = xmalloc(sizeof(*entry->equivs));
238 
239  entry->equivs[entry->count] = xstrdup(chptr);
240  entry->count++;
241  }
242 
243  return 0;
244 }
245 
246 static /*@observer@*/ /*@null@*/ machEquivInfo
247 machEquivSearch(const machEquivTable table, const char * name)
248  /*@*/
249 {
250  int i;
251 
252  for (i = 0; i < table->count; i++)
253  if (!xstrcasecmp(table->list[i].name, name))
254  return table->list + i;
255 
256  return NULL;
257 }
258 
259 static void machAddEquiv(machEquivTable table, const char * name,
260  int distance)
261  /*@modifies table->list, table->count @*/
262 {
263  machEquivInfo equiv;
264 
265  { int i;
266  equiv = NULL;
267  for (i = 0; i < table->count; i++) {
268  if (xstrcasecmp(table->list[i].name, name))
269  continue;
270  equiv = table->list + i;
271  break;
272  }
273  }
274 
275  if (!equiv) {
276  if (table->count)
277  table->list = xrealloc(table->list, (table->count + 1)
278  * sizeof(*table->list));
279  else
280  table->list = xmalloc(sizeof(*table->list));
281 
282  table->list[table->count].name = xstrdup(name);
283  table->list[table->count++].score = distance;
284  }
285 }
286 
287 static void machCacheEntryVisit(machCache cache,
288  machEquivTable table, const char * name, int distance)
289  /*@modifies table->list, table->count @*/
290 {
291  machCacheEntry entry;
292  int i;
293 
294  entry = machCacheFindEntry(cache, name);
295  if (!entry || entry->visited) return;
296 
297  entry->visited = 1;
298 
299  for (i = 0; i < entry->count; i++) {
300  machAddEquiv(table, entry->equivs[i], distance);
301  }
302 
303  for (i = 0; i < entry->count; i++) {
304  machCacheEntryVisit(cache, table, entry->equivs[i], distance + 1);
305  }
306 }
307 
308 static void rebuildCompatTables(int type, const char * name)
309  /*@globals tables, internalState @*/
310  /*@modifies tables, internalState @*/
311 {
312  machCache cache = &tables[currTables[type]].cache;
313  machEquivTable table = &tables[currTables[type]].equiv;
314  const char * key = name;
315  int i;
316 
317  for (i = 0; i < cache->size; i++)
318  cache->cache[i].visited = 0;
319 
320  while (table->count > 0) {
321  --table->count;
322  table->list[table->count].name = _free(table->list[table->count].name);
323  }
324  table->count = 0;
325  table->list = _free(table->list);
326 
327  /*
328  * We have a general graph built using strings instead of pointers.
329  * Yuck. We have to start at a point at traverse it, remembering how
330  * far away everything is.
331  */
332  /*@-nullstate@*/ /* FIX: table->list may be NULL. */
333  machAddEquiv(table, key, 1);
334  machCacheEntryVisit(cache, table, key, 2);
335  return;
336  /*@=nullstate@*/
337 }
338 
339 static int addCanon(canonEntry * table, int * tableLen, char * line,
340  const char * fn, int lineNum)
341  /*@globals internalState @*/
342  /*@modifies *table, *tableLen, *line, internalState @*/
343 {
344  canonEntry t;
345  char *s, *s1;
346  const char * tname;
347  const char * tshort_name;
348  int tnum;
349 
350  (*tableLen) += 2;
351  /*@-unqualifiedtrans@*/
352  *table = xrealloc(*table, sizeof(**table) * (*tableLen));
353  /*@=unqualifiedtrans@*/
354 
355  t = & ((*table)[*tableLen - 2]);
356 
357  tname = strtok(line, ": \t");
358  tshort_name = strtok(NULL, " \t");
359  s = strtok(NULL, " \t");
360  if (! (tname && tshort_name && s)) {
361  rpmError(RPMERR_RPMRC, _("Incomplete data line at %s:%d\n"),
362  fn, lineNum);
363  return RPMERR_RPMRC;
364  }
365  if (strtok(NULL, " \t")) {
366  rpmError(RPMERR_RPMRC, _("Too many args in data line at %s:%d\n"),
367  fn, lineNum);
368  return RPMERR_RPMRC;
369  }
370 
371  /*@-nullpass@*/ /* LCL: s != NULL here. */
372  tnum = strtoul(s, &s1, 10);
373  if ((*s1) || (s1 == s) || (tnum == ULONG_MAX)) {
374  rpmError(RPMERR_RPMRC, _("Bad arch/os number: %s (%s:%d)\n"), s,
375  fn, lineNum);
376  return(RPMERR_RPMRC);
377  }
378  /*@=nullpass@*/
379 
380  t[0].name = xstrdup(tname);
381  t[0].short_name = (tshort_name ? xstrdup(tshort_name) : xstrdup(""));
382  t[0].num = tnum;
383 
384  /* From A B C entry */
385  /* Add B B C entry */
386  t[1].name = (tshort_name ? xstrdup(tshort_name) : xstrdup(""));
387  t[1].short_name = (tshort_name ? xstrdup(tshort_name) : xstrdup(""));
388  t[1].num = tnum;
389 
390  return 0;
391 }
392 
393 static int addDefault(defaultEntry * table, int * tableLen, char * line,
394  const char * fn, int lineNum)
395  /*@globals internalState @*/
396  /*@modifies *table, *tableLen, *line, internalState @*/
397 {
398  defaultEntry t;
399 
400  (*tableLen)++;
401  /*@-unqualifiedtrans@*/
402  *table = xrealloc(*table, sizeof(**table) * (*tableLen));
403  /*@=unqualifiedtrans@*/
404 
405  t = & ((*table)[*tableLen - 1]);
406 
407  /*@-temptrans@*/
408  t->name = strtok(line, ": \t");
409  t->defName = strtok(NULL, " \t");
410  if (! (t->name && t->defName)) {
411  rpmError(RPMERR_RPMRC, _("Incomplete default line at %s:%d\n"),
412  fn, lineNum);
413  return RPMERR_RPMRC;
414  }
415  if (strtok(NULL, " \t")) {
416  rpmError(RPMERR_RPMRC, _("Too many args in default line at %s:%d\n"),
417  fn, lineNum);
418  return RPMERR_RPMRC;
419  }
420 
421  t->name = xstrdup(t->name);
422  t->defName = (t->defName ? xstrdup(t->defName) : NULL);
423  /*@=temptrans@*/
424 
425  return 0;
426 }
427 
428 static /*@null@*/ canonEntry lookupInCanonTable(const char * name,
429  const canonEntry table, int tableLen)
430  /*@*/
431 {
432  while (tableLen) {
433  tableLen--;
434  if (strcmp(name, table[tableLen].name))
435  continue;
436  /*@-immediatetrans -retalias@*/
437  return &(table[tableLen]);
438  /*@=immediatetrans =retalias@*/
439  }
440 
441  return NULL;
442 }
443 
444 static /*@observer@*/ /*@null@*/
445 const char * lookupInDefaultTable(const char * name,
446  const defaultEntry table, int tableLen)
447  /*@*/
448 {
449  while (tableLen) {
450  tableLen--;
451  if (table[tableLen].name && !strcmp(name, table[tableLen].name))
452  return table[tableLen].defName;
453  }
454 
455  return name;
456 }
457 
458 static /*@observer@*/ /*@null@*/
459 const char * rpmGetVarArch(int var, /*@null@*/ const char * arch)
460  /*@*/
461 {
462  const struct rpmvarValue * next;
463 
464  if (arch == NULL) arch = current[ARCH];
465 
466  if (arch) {
467  next = &values[var];
468  while (next) {
469  if (next->arch && !strcmp(next->arch, arch)) return next->value;
470  next = next->next;
471  }
472  }
473 
474  next = values + var;
475  while (next && next->arch) next = next->next;
476 
477  return next ? next->value : NULL;
478 }
479 
480 /* this doesn't free the passed pointer! */
481 static void freeRpmVar(/*@only@*/ struct rpmvarValue * orig)
482  /*@modifies *orig @*/
483 {
484  struct rpmvarValue * next, * var = orig;
485 
486  while (var) {
487  next = var->next;
488  var->arch = _free(var->arch);
489  var->value = _free(var->value);
490 
491  /*@-branchstate@*/
492  if (var != orig) var = _free(var);
493  /*@=branchstate@*/
494  var = next;
495  }
496 }
497 
502 static void rpmSetVar(int var, const char * val)
503  /*@globals values @*/
504  /*@modifies values @*/
505 {
506  /*@-immediatetrans@*/
507  freeRpmVar(&values[var]);
508  /*@=immediatetrans@*/
509  values[var].value = (val ? xstrdup(val) : NULL);
510 }
511 
512 static void setVarDefault(int var, const char * macroname, const char * val,
513  /*@null@*/ const char * body)
514  /*@globals rpmGlobalMacroContext, internalState @*/
515  /*@modifies rpmGlobalMacroContext, internalState @*/
516 {
517  if (var >= 0) { /* XXX Dying ... */
518  if (rpmGetVarArch(var, NULL)) return;
519  rpmSetVar(var, val);
520  }
521  if (body == NULL)
522  body = val;
523  addMacro(NULL, macroname, NULL, body, RMIL_DEFAULT);
524 }
525 
526 static void setPathDefault(int var, const char * macroname, const char * subdir)
527  /*@globals rpmGlobalMacroContext, h_errno, internalState @*/
528  /*@modifies rpmGlobalMacroContext, internalState @*/
529 {
530 
531  if (var >= 0) { /* XXX Dying ... */
532  const char * topdir;
533  char * fn;
534 
535  if (rpmGetVarArch(var, NULL)) return;
536 
537  topdir = rpmGetPath("%{_topdir}", NULL);
538 
539  fn = alloca(strlen(topdir) + strlen(subdir) + 2);
540  strcpy(fn, topdir);
541  if (fn[strlen(topdir) - 1] != '/')
542  strcat(fn, "/");
543  strcat(fn, subdir);
544 
545  rpmSetVar(var, fn);
546  topdir = _free(topdir);
547  }
548 
549  if (macroname != NULL) {
550 #define _TOPDIRMACRO "%{_topdir}/"
551  char *body = alloca(sizeof(_TOPDIRMACRO) + strlen(subdir));
552  strcpy(body, _TOPDIRMACRO);
553  strcat(body, subdir);
554  addMacro(NULL, macroname, NULL, body, RMIL_DEFAULT);
555 #undef _TOPDIRMACRO
556  }
557 }
558 
559 /*@observer@*/ /*@unchecked@*/
560 static const char * ___build_pre = "\n\
561 RPM_SOURCE_DIR=\"%{_sourcedir}\"\n\
562 RPM_BUILD_DIR=\"%{_builddir}\"\n\
563 RPM_OPT_FLAGS=\"%{optflags}\"\n\
564 RPM_ARCH=\"%{_arch}\"\n\
565 RPM_OS=\"%{_os}\"\n\
566 export RPM_SOURCE_DIR RPM_BUILD_DIR RPM_OPT_FLAGS RPM_ARCH RPM_OS\n\
567 RPM_DOC_DIR=\"%{_docdir}\"\n\
568 export RPM_DOC_DIR\n\
569 RPM_PACKAGE_NAME=\"%{name}\"\n\
570 RPM_PACKAGE_VERSION=\"%{version}\"\n\
571 RPM_PACKAGE_RELEASE=\"%{release}\"\n\
572 export RPM_PACKAGE_NAME RPM_PACKAGE_VERSION RPM_PACKAGE_RELEASE\n\
573 %{?buildroot:RPM_BUILD_ROOT=\"%{buildroot}\"\n\
574 export RPM_BUILD_ROOT\n}\
575 ";
576 
577 static void setDefaults(void)
578  /*@globals rpmGlobalMacroContext, h_errno, internalState @*/
579  /*@modifies rpmGlobalMacroContext, internalState @*/
580 {
581 
582  addMacro(NULL, "_usr", NULL, "/usr", RMIL_DEFAULT);
583  addMacro(NULL, "_var", NULL, "/var", RMIL_DEFAULT);
584  addMacro(NULL, "_prefix", NULL, "%{_usr}", RMIL_DEFAULT);
585 
586  addMacro(NULL, "___build_pre", NULL, ___build_pre, RMIL_DEFAULT);
587 
588  setVarDefault(-1, "_topdir",
589  "/usr/src/rpm", "%{_usr}/src/rpm");
590  setVarDefault(-1, "_tmppath",
591  "/var/tmp", "%{_var}/tmp");
592  setVarDefault(-1, "_dbpath",
593  "/var/lib/rpm", "%{_var}/lib/rpm");
594  setVarDefault(-1, "_defaultdocdir",
595  "/usr/share/doc", "%{_usr}/share/doc");
596 
597  setVarDefault(-1, "_rpmfilename",
598  "%%{ARCH}/%%{NAME}-%%{VERSION}-%%{RELEASE}.%%{ARCH}.rpm",NULL);
599 
600  setVarDefault(RPMVAR_OPTFLAGS, "optflags",
601  "-O2 -g", NULL);
602  setVarDefault(-1, "sigtype",
603  "none", NULL);
604  setVarDefault(-1, "_buildshell",
605  "/bin/sh", NULL);
606 
607  setPathDefault(-1, "_builddir", "BUILD");
608  setPathDefault(-1, "_rpmdir", "RPMS");
609  setPathDefault(-1, "_srcrpmdir", "SRPMS");
610  setPathDefault(-1, "_sourcedir", "SOURCES");
611  setPathDefault(-1, "_specdir", "SPECS");
612 
613 }
614 
615 static void rpmSetVarArch(int var, const char * val,
616  /*@null@*/ const char * arch)
617  /*@globals values, internalState @*/
618  /*@modifies values, internalState @*/
619 {
620  struct rpmvarValue * next = values + var;
621 
622  if (next->value) {
623  if (arch) {
624  while (next->next) {
625  if (next->arch && !strcmp(next->arch, arch)) break;
626  next = next->next;
627  }
628  } else {
629  while (next->next) {
630  if (!next->arch) break;
631  next = next->next;
632  }
633  }
634 
635  /*@-nullpass@*/ /* LCL: arch != NULL here. */
636  if (next->arch && arch && !strcmp(next->arch, arch)) {
637  /*@=nullpass@*/
638  next->value = _free(next->value);
639  next->arch = _free(next->arch);
640  } else if (next->arch || arch) {
641  next->next = xmalloc(sizeof(*next->next));
642  next = next->next;
643  next->value = NULL;
644  next->arch = NULL;
645  next->next = NULL;
646  }
647  }
648 
649  next->value = _free(next->value);
650  next->value = xstrdup(val);
651  next->arch = (arch ? xstrdup(arch) : NULL);
652 }
653 
654 /*@-usedef@*/ /*@ FIX: se usage inconsistent, W2DO? */
655 static int doReadRC( /*@killref@*/ FD_t fd, const char * urlfn)
656  /*@globals rpmGlobalMacroContext, h_errno, fileSystem, internalState @*/
657  /*@modifies fd, rpmGlobalMacroContext, fileSystem, internalState @*/
658 {
659  const char *s;
660  char *se, *next;
661  int linenum = 0;
662  struct rpmOption searchOption, * option;
663  int rc;
664 
665  /* XXX really need rc = Slurp(fd, const char * filename, char ** buf) */
666  { off_t size = fdSize(fd);
667  size_t nb = (size >= 0 ? size : (8*BUFSIZ - 2));
668  if (nb == 0) {
669  (void) Fclose(fd);
670  return 0;
671  }
672  next = alloca(nb + 2);
673  next[0] = '\0';
674  rc = Fread(next, sizeof(*next), nb, fd);
675  if (Ferror(fd) || (size > 0 && rc != nb)) { /* XXX Feof(fd) */
676  rpmError(RPMERR_RPMRC, _("Failed to read %s: %s.\n"), urlfn,
677  Fstrerror(fd));
678  rc = 1;
679  } else
680  rc = 0;
681  (void) Fclose(fd);
682  if (rc) return rc;
683  next[nb] = '\n';
684  next[nb + 1] = '\0';
685  }
686 
687  /*@-branchstate@*/
688  while (*next != '\0') {
689  linenum++;
690 
691  s = se = next;
692 
693  /* Find end-of-line. */
694  while (*se && *se != '\n') se++;
695  if (*se != '\0') *se++ = '\0';
696  next = se;
697 
698  /* Trim leading spaces */
699  while (*s && xisspace(*s)) s++;
700 
701  /* We used to allow comments to begin anywhere, but not anymore. */
702  if (*s == '#' || *s == '\0') continue;
703 
704  /* Find end-of-keyword. */
705  se = (char *)s;
706  while (*se && !xisspace(*se) && *se != ':') se++;
707 
708  if (xisspace(*se)) {
709  *se++ = '\0';
710  while (*se && xisspace(*se) && *se != ':') se++;
711  }
712 
713  if (*se != ':') {
714  rpmError(RPMERR_RPMRC, _("missing ':' (found 0x%02x) at %s:%d\n"),
715  (unsigned)(0xff & *se), urlfn, linenum);
716  return 1;
717  }
718  *se++ = '\0'; /* terminate keyword or option, point to value */
719  while (*se && xisspace(*se)) se++;
720 
721  /* Find keyword in table */
722  searchOption.name = s;
723  option = bsearch(&searchOption, optionTable, optionTableSize,
724  sizeof(optionTable[0]), optionCompare);
725 
726  if (option) { /* For configuration variables ... */
727  const char *arch, *val, *fn;
728 
729  arch = val = fn = NULL;
730  if (*se == '\0') {
731  rpmError(RPMERR_RPMRC, _("missing argument for %s at %s:%d\n"),
732  option->name, urlfn, linenum);
733  return 1;
734  }
735 
736  switch (option->var) {
737  case RPMVAR_INCLUDE:
738  { FD_t fdinc;
739 
740  s = se;
741  while (*se && !xisspace(*se)) se++;
742  if (*se != '\0') *se++ = '\0';
743 
744  rpmRebuildTargetVars(NULL, NULL);
745 
746  fn = rpmGetPath(s, NULL);
747  if (fn == NULL || *fn == '\0') {
748  rpmError(RPMERR_RPMRC, _("%s expansion failed at %s:%d \"%s\"\n"),
749  option->name, urlfn, linenum, s);
750  fn = _free(fn);
751  return 1;
752  /*@notreached@*/
753  }
754 
755  fdinc = Fopen(fn, "r.fpio");
756  if (fdinc == NULL || Ferror(fdinc)) {
757  rpmError(RPMERR_RPMRC, _("cannot open %s at %s:%d: %s\n"),
758  fn, urlfn, linenum, Fstrerror(fdinc));
759  rc = 1;
760  } else {
761  rc = doReadRC(fdinc, fn);
762  }
763  fn = _free(fn);
764  if (rc) return rc;
765  continue; /* XXX don't save include value as var/macro */
766  } /*@notreached@*/ /*@switchbreak@*/ break;
767  case RPMVAR_MACROFILES:
768  fn = rpmGetPath(se, NULL);
769  if (fn == NULL || *fn == '\0') {
770  rpmError(RPMERR_RPMRC, _("%s expansion failed at %s:%d \"%s\"\n"),
771  option->name, urlfn, linenum, fn);
772  fn = _free(fn);
773  return 1;
774  }
775  se = (char *)fn;
776  /*@switchbreak@*/ break;
777  default:
778  /*@switchbreak@*/ break;
779  }
780 
781  if (option->archSpecific) {
782  arch = se;
783  while (*se && !xisspace(*se)) se++;
784  if (*se == '\0') {
786  _("missing architecture for %s at %s:%d\n"),
787  option->name, urlfn, linenum);
788  return 1;
789  }
790  *se++ = '\0';
791  while (*se && xisspace(*se)) se++;
792  if (*se == '\0') {
794  _("missing argument for %s at %s:%d\n"),
795  option->name, urlfn, linenum);
796  return 1;
797  }
798  }
799 
800  val = se;
801 
802  /* Only add macros if appropriate for this arch */
803  if (option->macroize &&
804  (arch == NULL || !strcmp(arch, current[ARCH]))) {
805  char *n, *name;
806  n = name = xmalloc(strlen(option->name)+2);
807  if (option->localize)
808  *n++ = '_';
809  strcpy(n, option->name);
810  addMacro(NULL, name, NULL, val, RMIL_RPMRC);
811  free(name);
812  }
813  rpmSetVarArch(option->var, val, arch);
814  fn = _free(fn);
815 
816  } else { /* For arch/os compatibilty tables ... */
817  int gotit;
818  int i;
819 
820  gotit = 0;
821 
822  for (i = 0; i < RPM_MACHTABLE_COUNT; i++) {
823  if (!strncmp(tables[i].key, s, strlen(tables[i].key)))
824  /*@innerbreak@*/ break;
825  }
826 
827  if (i < RPM_MACHTABLE_COUNT) {
828  const char *rest = s + strlen(tables[i].key);
829  if (*rest == '_') rest++;
830 
831  if (!strcmp(rest, "compat")) {
832  if (machCompatCacheAdd(se, urlfn, linenum,
833  &tables[i].cache))
834  return 1;
835  gotit = 1;
836  } else if (tables[i].hasTranslate &&
837  !strcmp(rest, "translate")) {
838  if (addDefault(&tables[i].defaults,
839  &tables[i].defaultsLength,
840  se, urlfn, linenum))
841  return 1;
842  gotit = 1;
843  } else if (tables[i].hasCanon &&
844  !strcmp(rest, "canon")) {
845  if (addCanon(&tables[i].canons, &tables[i].canonsLength,
846  se, urlfn, linenum))
847  return 1;
848  gotit = 1;
849  }
850  }
851 
852  if (!gotit) {
853  rpmError(RPMERR_RPMRC, _("bad option '%s' at %s:%d\n"),
854  s, urlfn, linenum);
855  }
856  }
857  }
858  /*@=branchstate@*/
859 
860  return 0;
861 }
862 /*@=usedef@*/
863 
864 typedef struct cpu_vendor_os_gnu {
865 /*@owned@*/
866  const char * str;
867 /*@observer@*/
868  const char * cpu;
869 /*@observer@*/
870  const char * vendor;
871 /*@observer@*/
872  const char * os;
873 /*@observer@*/
874  const char * gnu;
875 } * CVOG_t;
876 
879 /*@-bounds@*/
880 static int parseCVOG(const char * str, CVOG_t *cvogp)
881  /*@modifies *cvogp @*/
882 {
883  CVOG_t cvog = xcalloc(1, sizeof(*cvog));
884  char * p, * pe;
885 
886  cvog->str = p = xstrdup(str);
887  pe = p + strlen(p);
888  while (pe-- > p && isspace(*pe))
889  *pe = '\0';
890 
891  cvog->cpu = p;
892  cvog->vendor = "unknown";
893  cvog->os = "unknown";
894  cvog->gnu = "";
895  while (*p && !(*p == '-' || isspace(*p)))
896  p++;
897  if (*p != '\0') *p++ = '\0';
898 
899  cvog->vendor = p;
900  while (*p && !(*p == '-' || isspace(*p)))
901  p++;
902 /*@-branchstate@*/
903  if (*p != '-') {
904  if (*p != '\0') *p++ = '\0';
905  cvog->os = cvog->vendor;
906  cvog->vendor = "unknown";
907  } else {
908  if (*p != '\0') *p++ = '\0';
909 
910  cvog->os = p;
911  while (*p && !(*p == '-' || isspace(*p)))
912  p++;
913  if (*p == '-') {
914  *p++ = '\0';
915 
916  cvog->gnu = p;
917  while (*p && !(*p == '-' || isspace(*p)))
918  p++;
919  }
920  if (*p != '\0') *p++ = '\0';
921  }
922 
923  if (cvogp)
924  *cvogp = cvog;
925  else {
926  cvog->str = _free(cvog->str);
927  cvog = _free(cvog);
928  }
929 /*@=branchstate@*/
930  return 0;
931 }
932 /*@=bounds@*/
933 
940 /*@null@*/
941 static void * mireFreeAll(/*@only@*/ /*@null@*/ miRE mire, int nre)
942  /*@modifies mire@*/
943 {
944  if (mire != NULL) {
945  int i;
946  for (i = 0; i < nre; i++)
947  (void) mireClean(mire + i);
948  mire = _free(mire);
949  }
950  return NULL;
951 }
952 
961 /*@null@*/
962 int mireAppend(rpmMireMode mode, int tag, const char * pattern,
963  miRE * mi_rep, int * mi_nrep)
964  /*@modifies *mi_rep, *mi_nrep @*/
965 {
966  miRE mire;
967 
968  mire = (*mi_rep);
969  mire = xrealloc(mire, ((*mi_nrep) + 1) * sizeof(*mire));
970  (*mi_rep) = mire;
971  mire += (*mi_nrep);
972  (*mi_nrep)++;
973  memset(mire, 0, sizeof(*mire));
974  mire->mode = mode;
975  mire->tag = tag;
976  return mireRegcomp(mire, pattern);
977 }
978 
984 /*@-bounds@*/
985 static int rpmPlatform(const char * platform)
986  /*@globals nplatpat, platpat,
987  rpmGlobalMacroContext, h_errno, fileSystem, internalState @*/
988  /*@modifies nplatpat, platpat,
989  rpmGlobalMacroContext, fileSystem, internalState @*/
990 {
991  CVOG_t cvog = NULL;
992  char * b = NULL;
993  ssize_t blen = 0;
994  int init_platform = 0;
995  miRE mi_re = NULL;
996  int mi_nre = 0;
997  char * p, * pe;
998  int rc;
999  int xx;
1000 
1001  rc = rpmioSlurp(platform, &b, &blen);
1002 
1003  if (rc || b == NULL || blen <= 0) {
1004  rc = -1;
1005  goto exit;
1006  }
1007 
1008  p = b;
1009  for (pe = p; p && *p; p = pe) {
1010  pe = strchr(p, '\n');
1011  if (pe)
1012  *pe++ = '\0';
1013 
1014  while (*p && xisspace(*p))
1015  p++;
1016  if (*p == '\0' || *p == '#')
1017  continue;
1018 
1019  if (init_platform) {
1020  char * t = p + strlen(p);
1021  while (--t > p && xisspace(*t))
1022  *t = '\0';
1023  if (t > p)
1024  xx = mireAppend(RPMMIRE_REGEX, 0, p, &mi_re, &mi_nre);
1025  continue;
1026  }
1027 
1028  if (!parseCVOG(p, &cvog) && cvog != NULL) {
1029  addMacro(NULL, "_host_cpu", NULL, cvog->cpu, -1);
1030  addMacro(NULL, "_host_vendor", NULL, cvog->vendor, -1);
1031  addMacro(NULL, "_host_os", NULL, cvog->os, -1);
1032  }
1033 
1034  p = rpmExpand("%{_host_cpu}-%{_host_vendor}-%{_host_os}",
1035  (cvog && *cvog->gnu ? "-" : NULL),
1036  (cvog ? cvog->gnu : NULL), NULL);
1037  xx = mireAppend(RPMMIRE_STRCMP, 0, p, &mi_re, &mi_nre);
1038  p = _free(p);
1039 
1040  init_platform++;
1041  }
1042  rc = (init_platform ? 0 : -1);
1043 
1044 exit:
1045  if (cvog) {
1046  cvog->str = _free(cvog->str);
1047  cvog = _free(cvog);
1048  }
1049 /*@-modobserver@*/
1050  b = _free(b);
1051 /*@=modobserver@*/
1052  if (rc == 0) {
1054  platpat = mi_re;
1055  nplatpat = mi_nre;
1056  }
1057  return rc;
1058 }
1059 /*@=bounds@*/
1060 
1061 int rpmPlatformScore(const char * platform, void * mi_re, int mi_nre)
1062 {
1063  miRE mire;
1064  int i;
1065 
1066  if (mi_re == NULL) {
1067  mi_re = platpat;
1068  mi_nre = nplatpat;
1069  }
1070 
1071  if ((mire = mi_re) != NULL)
1072  for (i = 0; i < mi_nre; i++) {
1073  if (!mireRegexec(mire + i, platform))
1074  return (i + 1);
1075  }
1076  return 0;
1077 }
1078 
1079 # if defined(__linux__) && defined(__i386__)
1080 #include <setjmp.h>
1081 #include <signal.h>
1082 
1083 /*
1084  * Generic CPUID function
1085  */
1086 static inline void cpuid(unsigned int op, unsigned int *eax, unsigned int *ebx, unsigned int *ecx, unsigned int *edx)
1087  /*@modifies *eax, *ebx, *ecx, *edx @*/
1088 {
1089 #ifdef __LCLINT__
1090  *eax = *ebx = *ecx = *edx = 0;
1091 #endif
1092  asm volatile (
1093  "pushl %%ebx \n"
1094  "cpuid \n"
1095  "movl %%ebx, %%esi \n"
1096  "popl %%ebx \n"
1097  : "=a" (*eax), "=S" (*ebx), "=c" (*ecx), "=d" (*edx)
1098  : "a" (op));
1099 }
1100 
1101 /*
1102  * CPUID functions returning a single datum
1103  */
1104 static inline unsigned int cpuid_eax(unsigned int op)
1105  /*@*/
1106 {
1107  unsigned int tmp, val;
1108  cpuid(op, &val, &tmp, &tmp, &tmp);
1109  return val;
1110 }
1111 
1112 static inline unsigned int cpuid_ebx(unsigned int op)
1113  /*@*/
1114 {
1115  unsigned int tmp, val;
1116  cpuid(op, &tmp, &val, &tmp, &tmp);
1117  return val;
1118 }
1119 
1120 static inline unsigned int cpuid_ecx(unsigned int op)
1121  /*@*/
1122 {
1123  unsigned int tmp, val;
1124  cpuid(op, &tmp, &tmp, &val, &tmp);
1125  return val;
1126 }
1127 
1128 static inline unsigned int cpuid_edx(unsigned int op)
1129  /*@*/
1130 {
1131  unsigned int tmp, val;
1132  cpuid(op, &tmp, &tmp, &tmp, &val);
1133  return val;
1134 }
1135 
1136 /*@unchecked@*/
1137 static sigjmp_buf jenv;
1138 
1139 static inline void model3(int _unused)
1140  /*@globals internalState @*/
1141  /*@modifies internalState @*/
1142 {
1143  siglongjmp(jenv, 1);
1144 }
1145 
1146 static inline int RPMClass(void)
1147  /*@globals internalState @*/
1148  /*@modifies internalState @*/
1149 {
1150  int cpu;
1151  unsigned int tfms, junk, cap, capamd;
1152 
1153  signal(SIGILL, model3);
1154 
1155  if (sigsetjmp(jenv, 1))
1156  return 3;
1157 
1158  if (cpuid_eax(0x000000000)==0)
1159  return 4;
1160 
1161  cpuid(0x00000001, &tfms, &junk, &junk, &cap);
1162  cpuid(0x80000001, &junk, &junk, &junk, &capamd);
1163 
1164  cpu = (tfms>>8)&15;
1165 
1166  if (cpu < 6)
1167  return cpu;
1168 
1169  if (cap & (1<<15)) {
1170  /* CMOV supported? */
1171  if (capamd & (1<<30))
1172  return 7; /* 3DNOWEXT supported */
1173  return 6;
1174  }
1175 
1176  return 5;
1177 }
1178 
1179 /* should only be called for model 6 CPU's */
1180 static int is_athlon(void)
1181  /*@*/
1182 {
1183  unsigned int eax, ebx, ecx, edx;
1184  char vendor[16];
1185  int i;
1186 
1187  cpuid (0, &eax, &ebx, &ecx, &edx);
1188 
1189  /* If you care about space, you can just check ebx, ecx and edx directly
1190  instead of forming a string first and then doing a strcmp */
1191  memset(vendor, 0, sizeof(vendor));
1192 
1193  for (i=0; i<4; i++)
1194  vendor[i] = (unsigned char) (ebx >>(8*i));
1195  for (i=0; i<4; i++)
1196  vendor[4+i] = (unsigned char) (edx >>(8*i));
1197  for (i=0; i<4; i++)
1198  vendor[8+i] = (unsigned char) (ecx >>(8*i));
1199 
1200  if (strncmp(vendor, "AuthenticAMD", 12) != 0)
1201  return 0;
1202 
1203  return 1;
1204 }
1205 
1206 static int is_pentium3(void)
1207 {
1208  unsigned int eax, ebx, ecx, edx, family, model;
1209  char vendor[16];
1210  cpuid(0, &eax, &ebx, &ecx, &edx);
1211  memset(vendor, 0, sizeof(vendor));
1212  *((unsigned int *)&vendor[0]) = ebx;
1213  *((unsigned int *)&vendor[4]) = edx;
1214  *((unsigned int *)&vendor[8]) = ecx;
1215  if (strncmp(vendor, "GenuineIntel", 12) != 0)
1216  return 0;
1217  cpuid(1, &eax, &ebx, &ecx, &edx);
1218  family = (eax >> 8) & 0x0f;
1219  model = (eax >> 4) & 0x0f;
1220  if (family == 6)
1221  switch (model)
1222  {
1223  case 7: // Pentium III, Pentium III Xeon (model 7)
1224  case 8: // Pentium III, Pentium III Xeon, Celeron (model 8)
1225  case 9: // Pentium M
1226  /*
1227  Intel recently announced its new technology for mobile platforms,
1228  named Centrino, and presents it as a big advance in mobile PCs.
1229  One of the main part of Centrino consists in a brand new CPU,
1230  the Pentium M, codenamed Banias, that we'll study in this review.
1231  A particularity of this CPU is that it was designed for mobile platform
1232  exclusively, unlike previous mobile CPU (Pentium III-M, Pentium 4-M)
1233  that share the same micro-architecture as their desktop counterparts.
1234  The Pentium M introduces a new micro-architecture, adapted for mobility
1235  constraints, and that is halfway between the Pentium III and the Pentium 4.
1236  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
1237  */
1238  case 10: // Pentium III Xeon (model A)
1239  case 11: // Pentium III (model B)
1240  return 1;
1241  }
1242  return 0;
1243 }
1244 
1245 static int is_pentium4(void)
1246 {
1247  unsigned int eax, ebx, ecx, edx, family, model;
1248  char vendor[16];
1249  cpuid(0, &eax, &ebx, &ecx, &edx);
1250  memset(vendor, 0, sizeof(vendor));
1251  *((unsigned int *)&vendor[0]) = ebx;
1252  *((unsigned int *)&vendor[4]) = edx;
1253  *((unsigned int *)&vendor[8]) = ecx;
1254  if (strncmp(vendor, "GenuineIntel", 12) != 0)
1255  return 0;
1256  cpuid(1, &eax, &ebx, &ecx, &edx);
1257  family = (eax >> 8) & 0x0f;
1258  model = (eax >> 4) & 0x0f;
1259  if (family == 15)
1260  switch (model)
1261  {
1262  case 0: // Pentium 4, Pentium 4 Xeon (0.18um)
1263  case 1: // Pentium 4, Pentium 4 Xeon MP, Celeron (0.18um)
1264  case 2: // Pentium 4, Mobile Pentium 4-M,
1265  // Pentium 4 Xeon, Pentium 4 Xeon MP,
1266  // Celeron, Mobile Celron (0.13um)
1267  case 3: // Pentium 4, Celeron (0.09um)
1268  case 4: // Pentium 4 540J
1269  return 1;
1270  }
1271  return 0;
1272 }
1273 
1274 #endif
1275 
1276 #if defined(__linux__) && defined(__powerpc__)
1277 static jmp_buf mfspr_jmpbuf;
1278 
1279 static void mfspr_ill(int notused)
1280 {
1281  longjmp(mfspr_jmpbuf, -1);
1282 }
1283 #endif
1284 
1287 static void defaultMachine(/*@out@*/ const char ** arch,
1288  /*@out@*/ const char ** os)
1289  /*@globals rpmGlobalMacroContext, h_errno, fileSystem, internalState @*/
1290  /*@modifies *arch, *os, rpmGlobalMacroContext, fileSystem, internalState @*/
1291 {
1292  static struct utsname un;
1293  static int gotDefaults = 0;
1294  char * chptr;
1295  canonEntry canon;
1296  int rc;
1297 
1298  while (!gotDefaults) {
1299  CVOG_t cvog = NULL;
1300  rc = uname(&un);
1301  if (rc < 0) return;
1302 
1303  if (!rpmPlatform(platform)) {
1304  const char * s;
1305  gotDefaults = 1;
1306  s = rpmExpand("%{?_host_cpu}", NULL);
1307  if (s && *s != '\0') {
1308  strncpy(un.machine, s, sizeof(un.machine));
1309  un.machine[sizeof(un.machine)-1] = '\0';
1310  }
1311  s = _free(s);
1312  s = rpmExpand("%{?_host_os}", NULL);
1313  if (s && *s != '\0') {
1314  strncpy(un.sysname, s, sizeof(un.sysname));
1315  un.sysname[sizeof(un.sysname)-1] = '\0';
1316  }
1317  s = _free(s);
1318  }
1319 
1320  if (configTarget && !parseCVOG(configTarget, &cvog) && cvog != NULL) {
1321  gotDefaults = 1;
1322  if (cvog->cpu && cvog->cpu[0] != '\0') {
1323  strncpy(un.machine, cvog->cpu, sizeof(un.machine));
1324  un.machine[sizeof(un.machine)-1] = '\0';
1325  }
1326  if (cvog->os && cvog->os[0] != '\0') {
1327  strncpy(un.sysname, cvog->os, sizeof(un.sysname));
1328  un.sysname[sizeof(un.sysname)-1] = '\0';
1329  }
1330  cvog->str = _free(cvog->str);
1331  cvog = _free(cvog);
1332  }
1333  if (gotDefaults)
1334  break;
1335 
1336 #if !defined(__linux__)
1337 #ifdef SNI
1338  /* USUALLY un.sysname on sinix does start with the word "SINIX"
1339  * let's be absolutely sure
1340  */
1341  strncpy(un.sysname, "SINIX", sizeof(un.sysname));
1342 #endif
1343  /*@-nullpass@*/
1344  if (!strcmp(un.sysname, "AIX")) {
1345  strcpy(un.machine, __power_pc() ? "ppc" : "rs6000");
1346  sprintf(un.sysname,"aix%s.%s", un.version, un.release);
1347  }
1348  else if(!strcmp(un.sysname, "Darwin")) {
1349 #ifdef __ppc__
1350  strcpy(un.machine, "ppc");
1351 #else ifdef __i386__
1352  strcpy(un.machine, "i386");
1353 #endif
1354  }
1355  else if (!strcmp(un.sysname, "SunOS")) {
1356  if (!strncmp(un.release,"4", 1)) /* SunOS 4.x */ {
1357  int fd;
1358  for (fd = 0;
1359  (un.release[fd] != 0 && (fd < sizeof(un.release)));
1360  fd++) {
1361  if (!xisdigit(un.release[fd]) && (un.release[fd] != '.')) {
1362  un.release[fd] = 0;
1363  /*@innerbreak@*/ break;
1364  }
1365  }
1366  sprintf(un.sysname,"sunos%s",un.release);
1367  }
1368 
1369  else /* Solaris 2.x: n.x.x becomes n-3.x.x */
1370  sprintf(un.sysname, "solaris%1d%s", atoi(un.release)-3,
1371  un.release+1+(atoi(un.release)/10));
1372 
1373  /* Solaris on Intel hardware reports i86pc instead of i386
1374  * (at least on 2.6 and 2.8)
1375  */
1376  if (!strcmp(un.machine, "i86pc"))
1377  sprintf(un.machine, "i386");
1378  }
1379  else if (!strcmp(un.sysname, "HP-UX"))
1380  /*make un.sysname look like hpux9.05 for example*/
1381  sprintf(un.sysname, "hpux%s", strpbrk(un.release, "123456789"));
1382  else if (!strcmp(un.sysname, "OSF1"))
1383  /*make un.sysname look like osf3.2 for example*/
1384  sprintf(un.sysname, "osf%s", strpbrk(un.release, "123456789"));
1385  else if (!strncmp(un.sysname, "IP", 2))
1386  un.sysname[2] = '\0';
1387  else if (!strncmp(un.sysname, "SINIX", 5)) {
1388  sprintf(un.sysname, "sinix%s",un.release);
1389  if (!strncmp(un.machine, "RM", 2))
1390  sprintf(un.machine, "mips");
1391  }
1392  else if ((!strncmp(un.machine, "34", 2) ||
1393  !strncmp(un.machine, "33", 2)) && \
1394  !strncmp(un.release, "4.0", 3))
1395  {
1396  /* we are on ncr-sysv4 */
1397  char * prelid = NULL;
1398  FD_t fd = Fopen("/etc/.relid", "r.fdio");
1399  int gotit = 0;
1400  /*@-branchstate@*/
1401  if (fd != NULL && !Ferror(fd)) {
1402  chptr = xcalloc(1, 256);
1403  { int irelid = Fread(chptr, sizeof(*chptr), 256, fd);
1404  (void) Fclose(fd);
1405  /* example: "112393 RELEASE 020200 Version 01 OS" */
1406  if (irelid > 0) {
1407  if ((prelid = strstr(chptr, "RELEASE "))){
1408  prelid += strlen("RELEASE ")+1;
1409  sprintf(un.sysname,"ncr-sysv4.%.*s",1,prelid);
1410  gotit = 1;
1411  }
1412  }
1413  }
1414  chptr = _free (chptr);
1415  }
1416  /*@=branchstate@*/
1417  if (!gotit) /* parsing /etc/.relid file failed? */
1418  strcpy(un.sysname,"ncr-sysv4");
1419  /* wrong, just for now, find out how to look for i586 later*/
1420  strcpy(un.machine,"i486");
1421  }
1422  /*@=nullpass@*/
1423 #endif /* __linux__ */
1424 
1425  /* get rid of the hyphens in the sysname */
1426  for (chptr = un.machine; *chptr != '\0'; chptr++)
1427  if (*chptr == '/') *chptr = '-';
1428 
1429 # if defined(__MIPSEL__) || defined(__MIPSEL) || defined(_MIPSEL)
1430  /* little endian */
1431  strcpy(un.machine, "mipsel");
1432 # elif defined(__MIPSEB__) || defined(__MIPSEB) || defined(_MIPSEB)
1433  /* big endian */
1434  strcpy(un.machine, "mips");
1435 # endif
1436 
1437 # if defined(__hpux) && defined(_SC_CPU_VERSION)
1438  {
1439 # if !defined(CPU_PA_RISC1_2)
1440 # define CPU_PA_RISC1_2 0x211 /* HP PA-RISC1.2 */
1441 # endif
1442 # if !defined(CPU_PA_RISC2_0)
1443 # define CPU_PA_RISC2_0 0x214 /* HP PA-RISC2.0 */
1444 # endif
1445  int cpu_version = sysconf(_SC_CPU_VERSION);
1446 
1447 # if defined(CPU_HP_MC68020)
1448  if (cpu_version == CPU_HP_MC68020)
1449  strcpy(un.machine, "m68k");
1450 # endif
1451 # if defined(CPU_HP_MC68030)
1452  if (cpu_version == CPU_HP_MC68030)
1453  strcpy(un.machine, "m68k");
1454 # endif
1455 # if defined(CPU_HP_MC68040)
1456  if (cpu_version == CPU_HP_MC68040)
1457  strcpy(un.machine, "m68k");
1458 # endif
1459 
1460 # if defined(CPU_PA_RISC1_0)
1461  if (cpu_version == CPU_PA_RISC1_0)
1462  strcpy(un.machine, "hppa1.0");
1463 # endif
1464 # if defined(CPU_PA_RISC1_1)
1465  if (cpu_version == CPU_PA_RISC1_1)
1466  strcpy(un.machine, "hppa1.1");
1467 # endif
1468 # if defined(CPU_PA_RISC1_2)
1469  if (cpu_version == CPU_PA_RISC1_2)
1470  strcpy(un.machine, "hppa1.2");
1471 # endif
1472 # if defined(CPU_PA_RISC2_0)
1473  if (cpu_version == CPU_PA_RISC2_0)
1474  strcpy(un.machine, "hppa2.0");
1475 # endif
1476  }
1477 # endif /* hpux */
1478 
1479 # if defined(__linux__) && defined(__sparc__)
1480  if (!strcmp(un.machine, "sparc")) {
1481  #define PERS_LINUX 0x00000000
1482  #define PERS_LINUX_32BIT 0x00800000
1483  #define PERS_LINUX32 0x00000008
1484 
1485  extern int personality(unsigned long);
1486  int oldpers;
1487 
1488  oldpers = personality(PERS_LINUX_32BIT);
1489  if (oldpers != -1) {
1490  if (personality(PERS_LINUX) != -1) {
1491  uname(&un);
1492  if (! strcmp(un.machine, "sparc64")) {
1493  strcpy(un.machine, "sparcv9");
1494  oldpers = PERS_LINUX32;
1495  }
1496  }
1497  personality(oldpers);
1498  }
1499  }
1500 # endif /* sparc*-linux */
1501 
1502 # if defined(__GNUC__) && defined(__alpha__)
1503  {
1504  unsigned long amask, implver;
1505  register long v0 __asm__("$0") = -1;
1506  __asm__ (".long 0x47e00c20" : "=r"(v0) : "0"(v0));
1507  amask = ~v0;
1508  __asm__ (".long 0x47e03d80" : "=r"(v0));
1509  implver = v0;
1510  switch (implver) {
1511  case 1:
1512  switch (amask) {
1513  case 0: strcpy(un.machine, "alphaev5"); break;
1514  case 1: strcpy(un.machine, "alphaev56"); break;
1515  case 0x101: strcpy(un.machine, "alphapca56"); break;
1516  }
1517  break;
1518  case 2:
1519  switch (amask) {
1520  case 0x303: strcpy(un.machine, "alphaev6"); break;
1521  case 0x307: strcpy(un.machine, "alphaev67"); break;
1522  }
1523  break;
1524  }
1525  }
1526 # endif
1527 
1528 # if defined(__linux__) && defined(__i386__)
1529  {
1530  char class = (char) (RPMClass() | '0');
1531 
1532  if ((class == '6' && is_athlon()) || class == '7')
1533  strcpy(un.machine, "athlon");
1534  else if (is_pentium4())
1535  strcpy(un.machine, "pentium4");
1536  else if (is_pentium3())
1537  strcpy(un.machine, "pentium3");
1538  else if (strchr("3456", un.machine[1]) && un.machine[1] != class)
1539  un.machine[1] = class;
1540  }
1541 # endif
1542 
1543 # if defined(__linux__) && defined(__powerpc__)
1544  {
1545  unsigned pvr = 0;
1546  __sighandler_t oldh = signal(SIGILL, mfspr_ill);
1547  if (setjmp(mfspr_jmpbuf) == 0) {
1548  __asm__ __volatile__ ("mfspr %0, 287" : "=r" (pvr));
1549  }
1550  signal(SIGILL, oldh);
1551 
1552  if ( pvr ) {
1553  pvr >>= 16;
1554  switch (pvr) {
1555  /* IBM750FX, 7410, 7450, 7451, 7441, 7455, 7445 */
1556  case 0x7000:
1557  case 0x8000:
1558  case 0x8001:
1559  case 0x800c:
1560  strcpy(un.machine, "ppc");
1561  break;
1562  case 0x36:
1563  case 0x37:
1564  strcpy(un.machine, "ppciseries");
1565  break;
1566  default:
1567  if ( pvr >= 0x40)
1568  strcpy(un.machine, "ppcpseries");
1569  else
1570  strcpy(un.machine, "ppc");
1571  break;
1572  }
1573  }
1574  }
1575 # endif
1576 
1577  /* the uname() result goes through the arch_canon table */
1578  canon = lookupInCanonTable(un.machine,
1580  tables[RPM_MACHTABLE_INSTARCH].canonsLength);
1581  if (canon)
1582  strcpy(un.machine, canon->short_name);
1583 
1584  canon = lookupInCanonTable(un.sysname,
1585  tables[RPM_MACHTABLE_INSTOS].canons,
1586  tables[RPM_MACHTABLE_INSTOS].canonsLength);
1587  if (canon)
1588  strcpy(un.sysname, canon->short_name);
1589  gotDefaults = 1;
1590  break;
1591  }
1592 
1593  if (arch) *arch = un.machine;
1594  if (os) *os = un.sysname;
1595 }
1596 
1597 void rpmSetTables(int archTable, int osTable)
1598  /*@globals currTables @*/
1599  /*@modifies currTables @*/
1600 {
1601  const char * arch, * os;
1602 
1603  defaultMachine(&arch, &os);
1604 
1605  if (currTables[ARCH] != archTable) {
1606  currTables[ARCH] = archTable;
1607  rebuildCompatTables(ARCH, arch);
1608  }
1609 
1610  if (currTables[OS] != osTable) {
1611  currTables[OS] = osTable;
1612  rebuildCompatTables(OS, os);
1613  }
1614 }
1615 
1616 int rpmMachineScore(int type, const char * name)
1617 {
1618  const char * fakeplatform;
1619  int score = 0;
1620  switch (type) {
1622  fakeplatform = rpmExpand(name, "%{_host_vendor}-%{_host_os}%{?_gnu}", NULL);
1623  break;
1625  fakeplatform = rpmExpand(name, "%{_target_vendor}-%{_target_os}%{?_gnu}", NULL);
1626  break;
1627  case RPM_MACHTABLE_INSTOS:
1628  fakeplatform = rpmExpand("%{_host_arch}-%{_host_vendor}-", name, "%{?_gnu}", NULL);
1629  break;
1630  case RPM_MACHTABLE_BUILDOS:
1631  fakeplatform = rpmExpand("%{_target_arch}-%{_target_vendor}-", name, "%{?_gnu}", NULL);
1632  break;
1633  }
1634  score = rpmPlatformScore(fakeplatform, NULL, 0);
1635  _free(fakeplatform);
1636  return(score);
1637 }
1638 
1639 /*@-modnomods@*/
1640 void rpmGetMachine(const char ** arch, const char ** os)
1641 {
1642  if (arch)
1643  *arch = current[ARCH];
1644 
1645  if (os)
1646  *os = current[OS];
1647 }
1648 /*@=modnomods@*/
1649 
1650 void rpmSetMachine(const char * arch, const char * os)
1651  /*@globals current @*/
1652  /*@modifies current @*/
1653 {
1654  if (arch == NULL) {
1655 /*@i@*/ defaultMachine(&arch, NULL);
1656  if (tables[currTables[ARCH]].hasTranslate)
1657  arch = lookupInDefaultTable(arch,
1658  tables[currTables[ARCH]].defaults,
1659  tables[currTables[ARCH]].defaultsLength);
1660  }
1661 assert(arch != NULL);
1662 
1663  if (os == NULL) {
1664 /*@i@*/ defaultMachine(NULL, &os);
1665  if (tables[currTables[OS]].hasTranslate)
1666  os = lookupInDefaultTable(os,
1667  tables[currTables[OS]].defaults,
1668  tables[currTables[OS]].defaultsLength);
1669  }
1670 assert(os != NULL);
1671 
1672 
1673  if (!current[ARCH] || strcmp(arch, current[ARCH])) {
1674  current[ARCH] = _free(current[ARCH]);
1675  current[ARCH] = xstrdup(arch);
1676  rebuildCompatTables(ARCH, arch);
1677  }
1678 
1679  if (!current[OS] || strcmp(os, current[OS])) {
1680  char * t = xstrdup(os);
1681  current[OS] = _free(current[OS]);
1682  if (!strcmp(t, "linux"))
1683  *t = 'L';
1684  current[OS] = t;
1685  rebuildCompatTables(OS, os);
1686  }
1687 }
1688 
1689 static void getMachineInfo(int type, /*@null@*/ /*@out@*/ const char ** name,
1690  /*@null@*/ /*@out@*/int * num)
1691  /*@modifies *name, *num @*/
1692 {
1693  canonEntry canon;
1694  int which = currTables[type];
1695 
1696  /* use the normal canon tables, even if we're looking up build stuff */
1697  if (which >= 2) which -= 2;
1698 
1699  canon = lookupInCanonTable(current[type],
1700  tables[which].canons,
1701  tables[which].canonsLength);
1702 
1703  if (canon) {
1704  if (num) *num = canon->num;
1705  if (name) *name = canon->short_name;
1706  } else {
1707  if (num) *num = 255;
1708  if (name) *name = current[type];
1709  }
1710 }
1711 
1712 void rpmGetArchInfo(const char ** name, int * num)
1713 {
1714  getMachineInfo(ARCH, name, num);
1715 }
1716 
1717 void rpmGetOsInfo(const char ** name, int * num)
1718 {
1719  getMachineInfo(OS, name, num);
1720 }
1721 
1722 static void rpmRebuildTargetVars(const char ** target, const char ** canontarget)
1723 {
1724 
1725  char *ca = NULL, *co = NULL, *ct = NULL;
1726  int x;
1727 
1728  /* Rebuild the compat table to recalculate the current target arch. */
1729 
1730  rpmSetMachine(NULL, NULL);
1733 
1734  /*@-branchstate@*/
1735  if (target && *target) {
1736  char *c;
1737  /* Set arch and os from specified build target */
1738  ca = xstrdup(*target);
1739  if ((c = strchr(ca, '-')) != NULL) {
1740  *c++ = '\0';
1741 
1742  if ((co = strrchr(c, '-')) == NULL) {
1743  co = c;
1744  } else {
1745  if (!xstrcasecmp(co, "-gnu"))
1746  *co = '\0';
1747  if ((co = strrchr(c, '-')) == NULL)
1748  co = c;
1749  else
1750  co++;
1751  }
1752  if (co != NULL) co = xstrdup(co);
1753  }
1754  } else {
1755  const char *a = NULL;
1756  const char *o = NULL;
1757  /* Set build target from rpm arch and os */
1758  getMachineInfo(ARCH, &a, NULL);
1759  ca = (a) ? xstrdup(a) : NULL;
1760  getMachineInfo(OS, &o, NULL);
1761  co = (o) ? xstrdup(o) : NULL;
1762  }
1763  /*@=branchstate@*/
1764 
1765  /* If still not set, Set target arch/os from default uname(2) values */
1766  if (ca == NULL) {
1767  const char *a = NULL;
1768  defaultMachine(&a, NULL);
1769  ca = (a) ? xstrdup(a) : NULL;
1770  }
1771  if (ca != NULL)
1772  for (x = 0; ca[x] != '\0'; x++)
1773  ca[x] = xtolower(ca[x]);
1774 
1775  if (co == NULL) {
1776  const char *o = NULL;
1777  defaultMachine(NULL, &o);
1778  co = (o) ? xstrdup(o) : NULL;
1779  }
1780  if (co != NULL)
1781  for (x = 0; co[x] != '\0'; x++)
1782  co[x] = xtolower(co[x]);
1783 
1784  /* XXX For now, set canonical target to arch-os */
1785  if (ct == NULL) {
1786  ct = xmalloc(strlen(ca) + sizeof("-") + strlen(co));
1787  sprintf(ct, "%s-%s", ca, co);
1788  }
1789 
1790 /*
1791  * XXX All this macro pokery/jiggery could be achieved by doing a delayed
1792  * rpmInitMacros(NULL, PER-PLATFORM-MACRO-FILE-NAMES);
1793  */
1794  delMacro(NULL, "_target");
1795  addMacro(NULL, "_target", NULL, ct, RMIL_RPMRC);
1796  delMacro(NULL, "_target_cpu");
1797  addMacro(NULL, "_target_cpu", NULL, ca, RMIL_RPMRC);
1798  delMacro(NULL, "_target_os");
1799  addMacro(NULL, "_target_os", NULL, co, RMIL_RPMRC);
1800 /*
1801  * XXX Make sure that per-arch optflags is initialized correctly.
1802  */
1803  if (rpmcliRcfile != NULL)
1804  { const char *optflags = rpmGetVarArch(RPMVAR_OPTFLAGS, ca);
1805  if (optflags != NULL) {
1806  delMacro(NULL, "optflags");
1807  addMacro(NULL, "optflags", NULL, optflags, RMIL_RPMRC);
1808  }
1809  }
1810 
1811  /*@-branchstate@*/
1812  if (canontarget)
1813  *canontarget = ct;
1814  else
1815  ct = _free(ct);
1816  /*@=branchstate@*/
1817  ca = _free(ca);
1818  /*@-usereleased@*/
1819  co = _free(co);
1820  /*@=usereleased@*/
1821 }
1822 
1823 void rpmFreeRpmrc(void)
1824  /*@globals current, tables, values, defaultsInitialized @*/
1825  /*@modifies current, tables, values, defaultsInitialized @*/
1826 {
1827  int i, j, k;
1828 
1830  nplatpat = 0;
1831 
1832  for (i = 0; i < RPM_MACHTABLE_COUNT; i++) {
1833  tableType t;
1834  t = tables + i;
1835  if (t->equiv.list) {
1836  for (j = 0; j < t->equiv.count; j++)
1837  t->equiv.list[j].name = _free(t->equiv.list[j].name);
1838  t->equiv.list = _free(t->equiv.list);
1839  t->equiv.count = 0;
1840  }
1841  if (t->cache.cache) {
1842  for (j = 0; j < t->cache.size; j++) {
1843  machCacheEntry e;
1844  e = t->cache.cache + j;
1845  if (e == NULL)
1846  /*@innercontinue@*/ continue;
1847  e->name = _free(e->name);
1848  if (e->equivs) {
1849  for (k = 0; k < e->count; k++)
1850  e->equivs[k] = _free(e->equivs[k]);
1851  e->equivs = _free(e->equivs);
1852  }
1853  }
1854  t->cache.cache = _free(t->cache.cache);
1855  t->cache.size = 0;
1856  }
1857  if (t->defaults) {
1858  for (j = 0; j < t->defaultsLength; j++) {
1859  t->defaults[j].name = _free(t->defaults[j].name);
1860  t->defaults[j].defName = _free(t->defaults[j].defName);
1861  }
1862  t->defaults = _free(t->defaults);
1863  t->defaultsLength = 0;
1864  }
1865  if (t->canons) {
1866  for (j = 0; j < t->canonsLength; j++) {
1867  t->canons[j].name = _free(t->canons[j].name);
1868  t->canons[j].short_name = _free(t->canons[j].short_name);
1869  }
1870  t->canons = _free(t->canons);
1871  t->canonsLength = 0;
1872  }
1873  }
1874 
1875  for (i = 0; i < RPMVAR_NUM; i++) {
1876  /*@only@*/ /*@null@*/ struct rpmvarValue * vp;
1877  while ((vp = values[i].next) != NULL) {
1878  values[i].next = vp->next;
1879  vp->value = _free(vp->value);
1880  vp->arch = _free(vp->arch);
1881  vp = _free(vp);
1882  }
1883  values[i].value = _free(values[i].value);
1884  values[i].arch = _free(values[i].arch);
1885  }
1886  current[OS] = _free(current[OS]);
1887  current[ARCH] = _free(current[ARCH]);
1888  defaultsInitialized = 0;
1889 /*@-globstate -nullstate@*/ /* FIX: platpat/current may be NULL */
1890  return;
1891 /*@=globstate =nullstate@*/
1892 }
1893 
1899 static int rpmReadRC(/*@null@*/ const char * rcfiles)
1900  /*@globals defaultsInitialized, rpmRcfiles, rpmMacrofiles,
1901  rpmGlobalMacroContext, rpmCLIMacroContext, h_errno,
1902  fileSystem, internalState @*/
1903  /*@modifies defaultsInitialized, rpmGlobalMacroContext,
1904  fileSystem, internalState @*/
1905 {
1906  char *myrcfiles = NULL;
1907  char *r, *re;
1908  int rc;
1909 
1910  if (!defaultsInitialized) {
1911  setDefaults();
1912  defaultsInitialized = 1;
1913  }
1914 
1915  /* Read each file in rcfiles. */
1916  rc = 0;
1917  if (rcfiles != NULL)
1918  for (r = myrcfiles = xstrdup(rcfiles); r && *r != '\0'; r = re) {
1919  char fn[4096];
1920  FD_t fd;
1921 
1922  /* Get pointer to rest of files */
1923  for (re = r; (re = strchr(re, ':')) != NULL; re++) {
1924  if (!(re[1] == '/' && re[2] == '/'))
1925  /*@innerbreak@*/ break;
1926  }
1927  if (re && *re == ':')
1928  *re++ = '\0';
1929  else
1930  re = r + strlen(r);
1931 
1932  /* Expand ~/ to $HOME/ */
1933  fn[0] = '\0';
1934  if (r[0] == '~' && r[1] == '/') {
1935  const char * etc_dir = getenv("HOME_ETC");
1936  const char * home = getenv("HOME");
1937  if (etc_dir) {
1938  if (strlen(etc_dir) > (sizeof(fn) - strlen(r))) {
1939  rpmError(RPMERR_RPMRC, _("Cannot read %s, HOME_ETC is too large.\n"),r);
1940  rc = 1;
1941  break;
1942  }
1943  strcpy(fn, etc_dir);
1944  strncat(fn, "/", sizeof(fn) - strlen(fn));
1945  r+=2;
1946  } else {
1947  if (home == NULL) {
1948  /* XXX Only /usr/lib/rpm/rpmrc must exist in default rcfiles list */
1949  if (rcfiles == rpmRcfiles && myrcfiles != r)
1950  continue;
1951  rpmError(RPMERR_RPMRC, _("Cannot expand %s\n"), r);
1952  rc = 1;
1953  break;
1954  }
1955  if (strlen(home) > (sizeof(fn) - strlen(r))) {
1956  rpmError(RPMERR_RPMRC, _("Cannot read %s, HOME is too large.\n"),
1957  r);
1958  rc = 1;
1959  break;
1960  }
1961  strcpy(fn, home);
1962  r++;
1963  }
1964 
1965 
1966  }
1967  strncat(fn, r, sizeof(fn) - (strlen(fn) + 1));
1968  fn[sizeof(fn)-1] = '\0';
1969 
1970  /* Read another rcfile */
1971  fd = Fopen(fn, "r.fpio");
1972  if (fd == NULL || Ferror(fd)) {
1973  /* XXX Only /usr/lib/rpm/rpmrc must exist in default rcfiles list */
1974  if (rcfiles == rpmRcfiles && myrcfiles != r)
1975  continue;
1976  rpmError(RPMERR_RPMRC, _("Unable to open %s for reading: %s.\n"),
1977  fn, Fstrerror(fd));
1978  rc = 1;
1979  break;
1980  } else {
1981  rc = doReadRC(fd, fn);
1982  }
1983  if (rc) break;
1984  }
1985  myrcfiles = _free(myrcfiles);
1986  if (rc)
1987  return rc;
1988 
1989  /* Read macro files. */
1990  { const char *mfpath = rpmGetVarArch(RPMVAR_MACROFILES, NULL);
1991 
1992  if (mfpath == NULL)
1993  mfpath = rpmExpand(rpmMacrofiles, NULL);
1994  else
1995  mfpath = xstrdup(mfpath);
1996 
1997  /*@-branchstate@*/
1998  if (mfpath != NULL) {
1999  rpmInitMacros(NULL, mfpath);
2000  mfpath = _free(mfpath);
2001  }
2002  /*@=branchstate@*/
2003  }
2004 
2005  return rc;
2006 }
2007 
2008 int rpmReadConfigFiles(const char * file, const char * target)
2009  /*@globals configTarget @*/
2010  /*@modifies configTarget @*/
2011 {
2012 
2013  configTarget = target;
2014 
2015  /* Preset target macros */
2016  /*@-nullstate@*/ /* FIX: target can be NULL */
2017  rpmRebuildTargetVars(&target, NULL);
2018 
2019  /* Read the files */
2020 /*@-globs@*/
2021  if (rpmReadRC(file)) return -1;
2022 /*@=globs@*/
2023 
2024  /* Reset target macros */
2025  rpmRebuildTargetVars(&target, NULL);
2026  /*@=nullstate@*/
2027 
2028  /* Finally set target platform */
2029  { const char *cpu = rpmExpand("%{_target_cpu}", NULL);
2030  const char *os = rpmExpand("%{_target_os}", NULL);
2031  rpmSetMachine(cpu, os);
2032  cpu = _free(cpu);
2033  os = _free(os);
2034  }
2035  configTarget = NULL;
2036 
2037  /* Force Lua state initialization */
2038 #ifdef WITH_LUA
2039  (void)rpmluaGetPrintBuffer(NULL);
2040 #endif
2041 
2042  return 0;
2043 }
2044 
2045 int rpmShowRC(FILE * fp)
2046 {
2047  rpmds ds = NULL;
2048  struct rpmOption *opt;
2049  int i;
2050  machEquivTable equivTable;
2051  int xx;
2052 
2053  /* the caller may set the build arch which should be printed here */
2054  fprintf(fp, "ARCHITECTURE AND OS:\n");
2055  fprintf(fp, "build arch : %s\n", current[ARCH]);
2056 
2057  fprintf(fp, "compatible build archs:");
2058  equivTable = &tables[RPM_MACHTABLE_BUILDARCH].equiv;
2059  for (i = 0; i < equivTable->count; i++)
2060  fprintf(fp," %s", equivTable->list[i].name);
2061  fprintf(fp, "\n");
2062 
2063  fprintf(fp, "build os : %s\n", current[OS]);
2064 
2065  fprintf(fp, "compatible build os's :");
2066  equivTable = &tables[RPM_MACHTABLE_BUILDOS].equiv;
2067  for (i = 0; i < equivTable->count; i++)
2068  fprintf(fp," %s", equivTable->list[i].name);
2069  fprintf(fp, "\n");
2070 
2071  if (rpmcliRcfile != NULL) {
2073  rpmSetMachine(NULL, NULL); /* XXX WTFO? Why bother? */
2074  }
2075 
2076  fprintf(fp, "install arch : %s\n", current[ARCH]);
2077  fprintf(fp, "install os : %s\n", current[OS]);
2078 
2079  fprintf(fp, "compatible archs :");
2080  equivTable = &tables[RPM_MACHTABLE_INSTARCH].equiv;
2081  for (i = 0; i < equivTable->count; i++)
2082  fprintf(fp," %s", equivTable->list[i].name);
2083  fprintf(fp, "\n");
2084 
2085  fprintf(fp, "compatible os's :");
2086  equivTable = &tables[RPM_MACHTABLE_INSTOS].equiv;
2087  for (i = 0; i < equivTable->count; i++)
2088  fprintf(fp," %s", equivTable->list[i].name);
2089  fprintf(fp, "\n");
2090 
2091  if (rpmcliRcfile != NULL) {
2092  const char * s = rpmExpand(rpmcliRcfile, NULL);
2093  fprintf(fp, "\nRPMRC VALUES:\n");
2094  fprintf(fp, "%-21s : %s\n", "rcfiles", ((s && *s) ? s : "(not set)"));
2095  s = _free(s);
2096 /*@-branchstate@*/
2097  for (i = 0, opt = optionTable; i < optionTableSize; i++, opt++) {
2098  s = rpmGetVarArch(opt->var, NULL);
2099  if (s != NULL || rpmIsVerbose())
2100  fprintf(fp, "%-21s : %s\n", opt->name, s ? s : "(not set)");
2101  }
2102 /*@=branchstate@*/
2103  fprintf(fp, "\nMACRO DEFINITIONS:\n");
2104  } else {
2105  const char * s = rpmExpand("%{?optflags}", NULL);
2106  fprintf(fp, "%-21s : %s\n", "optflags", ((s && *s) ? s : "(not set)"));
2107  s = _free(s);
2108 /*@-globs@*/
2109  s = rpmExpand(rpmMacrofiles, NULL);
2110 /*@=globs@*/
2111  fprintf(fp, "\nMACRO DEFINITIONS:\n");
2112  fprintf(fp, "%-21s : %s\n", "macrofiles", ((s && *s) ? s : "(not set)"));
2113  s = _free(s);
2114  }
2115 
2116  if (rpmIsVerbose()) {
2117  rpmPRCO PRCO = rpmdsNewPRCO(NULL);
2118  xx = rpmdsSysinfo(PRCO, NULL);
2119  ds = rpmdsFromPRCO(PRCO, RPMTAG_PROVIDENAME);
2120  if (ds != NULL) {
2121  fprintf(fp, _("Configured system provides (from /etc/rpm/sysinfo):\n"));
2122  ds = rpmdsInit(ds);
2123  while (rpmdsNext(ds) >= 0) {
2124  const char * DNEVR = rpmdsDNEVR(ds);
2125  if (DNEVR != NULL)
2126  fprintf(fp, " %s\n", DNEVR+2);
2127  }
2128  ds = rpmdsFree(ds);
2129  fprintf(fp, "\n");
2130  }
2131  PRCO = rpmdsFreePRCO(PRCO);
2132  }
2133 
2134  if (rpmIsVerbose()) {
2135  fprintf(fp, _("Features provided by rpmlib installer:\n"));
2136  xx = rpmdsRpmlib(&ds, NULL);
2137  ds = rpmdsInit(ds);
2138  while (rpmdsNext(ds) >= 0) {
2139  const char * DNEVR = rpmdsDNEVR(ds);
2140  if (DNEVR != NULL)
2141  fprintf(fp, " %s\n", DNEVR+2);
2142  }
2143  ds = rpmdsFree(ds);
2144  fprintf(fp, "\n");
2145 
2146  xx = rpmdsCpuinfo(&ds, NULL);
2147  if (ds != NULL) {
2148  fprintf(fp,
2149  _("Features provided by current cpuinfo (from /proc/cpuinfo):\n"));
2150  ds = rpmdsInit(ds);
2151  while (rpmdsNext(ds) >= 0) {
2152  const char * DNEVR = rpmdsDNEVR(ds);
2153  if (DNEVR != NULL)
2154  fprintf(fp, " %s\n", DNEVR+2);
2155  }
2156  ds = rpmdsFree(ds);
2157  fprintf(fp, "\n");
2158  }
2159  }
2160 
2161  if (rpmIsDebug()) {
2162  xx = rpmdsGetconf(&ds, NULL);
2163  if (ds != NULL) {
2164  fprintf(fp,
2165  _("Features provided by current getconf:\n"));
2166  ds = rpmdsInit(ds);
2167  while (rpmdsNext(ds) >= 0) {
2168  const char * DNEVR = rpmdsDNEVR(ds);
2169  if (DNEVR != NULL)
2170  fprintf(fp, " %s\n", DNEVR+2);
2171  }
2172  ds = rpmdsFree(ds);
2173  fprintf(fp, "\n");
2174  }
2175 
2176  xx = rpmdsUname(&ds, NULL);
2177  if (ds != NULL) {
2178  fprintf(fp,
2179  _("Features provided by current uname:\n"));
2180  ds = rpmdsInit(ds);
2181  while (rpmdsNext(ds) >= 0) {
2182  const char * DNEVR = rpmdsDNEVR(ds);
2183  if (DNEVR != NULL)
2184  fprintf(fp, " %s\n", DNEVR+2);
2185  }
2186  ds = rpmdsFree(ds);
2187  fprintf(fp, "\n");
2188  }
2189  }
2190 
2191  rpmDumpMacroTable(NULL, fp);
2192 
2193  return 0;
2194 }
2195 /*@=bounds@*/