rpm  5.2.1
rpmrc.c
Go to the documentation of this file.
1 #include "system.h"
2 
3 #include <stdarg.h>
4 
5 #if defined(HAVE_SYS_SYSTEMCFG_H)
6 #include <sys/systemcfg.h>
7 #else
8 #define __power_pc() 0
9 #endif
10 
11 #define _RPMIOB_INTERNAL /* XXX for rpmiobSlurp */
12 #include <rpmio.h>
13 #include <rpmcb.h>
14 #define _MIRE_INTERNAL
15 #include <mire.h>
16 #include <argv.h>
17 #include <rpmlua.h>
18 #include <rpmluaext.h>
19 #include <rpmmacro.h>
20 
21 #include <rpmtypes.h>
22 #include <rpmtag.h>
23 #define _RPMEVR_INTERNAL
24 #include <rpmevr.h>
25 
26 #define _RPMDS_INTERNAL
27 #include <rpmds.h>
28 
29 #include <rpmcli.h>
30 
31 #include <rpmsyck.h>
32 
33 #include "debug.h"
34 
35 /*@access miRE@*/
36 
37 /*@unchecked@*/ /*@null@*/
38 static const char * configTarget = NULL;
39 
40 /*@observer@*/ /*@unchecked@*/
41 static const char * platform = SYSCONFIGDIR "/platform";
42 
43 /*@only@*/ /*@relnull@*/ /*@unchecked@*/
44 void * platpat = NULL;
45 /*@unchecked@*/
46 int nplatpat = 0;
47 
48 extern rpmds cpuinfoP;
49 
50 
51 
62 };
63 #define RPM_MACHTABLE_COUNT 4
65 typedef /*@owned@*/ const char * cptr_t;
66 
67 typedef struct machCacheEntry_s {
68  const char * name;
69  int count;
71  int visited;
72 } * machCacheEntry;
73 
74 typedef struct machCache_s {
76  int size;
77 } * machCache;
78 
79 typedef struct machEquivInfo_s {
80  const char * name;
81  int score;
82 } * machEquivInfo;
83 
84 typedef struct machEquivTable_s {
85  int count;
87 } * machEquivTable;
88 
89 typedef struct defaultEntry_s {
90 /*@owned@*/ /*@null@*/ const char * name;
91 /*@owned@*/ /*@null@*/ const char * defName;
92 } * defaultEntry;
93 
94 typedef struct canonEntry_s {
95 /*@owned@*/ const char * name;
96 /*@owned@*/ const char * short_name;
97  short num;
98 } * canonEntry;
99 
100 /* tags are 'key'canon, 'key'translate, 'key'compat
101  *
102  * for giggles, 'key'_canon, 'key'_compat, and 'key'_canon will also work
103  */
104 typedef struct tableType_s {
105 /*@observer@*/ const char * const key;
106  const int hasCanon;
107  const int hasTranslate;
114 } * tableType;
115 
116 /*@-fullinitblock@*/
117 /*@unchecked@*/
119  { "arch", 1, 0 },
120  { "os", 1, 0 },
121  { "buildarch", 0, 1 },
122  { "buildos", 0, 1 }
123 };
124 /*@=fullinitblock@*/
125 
126 #define OS 0
127 #define ARCH 1
128 
129 /*@unchecked@*/
130 static cptr_t current[2];
131 
132 /*@unchecked@*/
134 
135 /*@unchecked@*/
136 static int defaultsInitialized = 0;
137 
138 /* prototypes */
139 static void rpmRebuildTargetVars(/*@null@*/ const char **target, /*@null@*/ const char ** canontarget)
140  /*@globals rpmGlobalMacroContext, h_errno, fileSystem, internalState @*/
141  /*@modifies *canontarget, rpmGlobalMacroContext,
142  fileSystem, internalState @*/;
143 
144 static /*@observer@*/ /*@null@*/ machCacheEntry
145 machCacheFindEntry(const machCache cache, const char * key)
146  /*@*/
147 {
148  int i;
149 
150  for (i = 0; i < cache->size; i++)
151  if (!strcmp(cache->cache[i].name, key)) return cache->cache + i;
152 
153  return NULL;
154 }
155 
156 static void machAddEquiv(machEquivTable table, const char * name,
157  int distance)
158  /*@modifies table->list, table->count @*/
159 {
161 
162  { int i;
163  equiv = NULL;
164  for (i = 0; i < table->count; i++) {
165  if (xstrcasecmp(table->list[i].name, name))
166  continue;
167  equiv = table->list + i;
168  break;
169  }
170  }
171 
172  if (!equiv) {
173  if (table->count)
174  table->list = xrealloc(table->list, (table->count + 1)
175  * sizeof(*table->list));
176  else
177  table->list = xmalloc(sizeof(*table->list));
178 
179  table->list[table->count].name = xstrdup(name);
180  table->list[table->count++].score = distance;
181  }
182 }
183 
185  machEquivTable table, const char * name, int distance)
186  /*@modifies table->list, table->count @*/
187 {
188  machCacheEntry entry;
189  int i;
190 
191  entry = machCacheFindEntry(cache, name);
192  if (!entry || entry->visited) return;
193 
194  entry->visited = 1;
195 
196  for (i = 0; i < entry->count; i++) {
197  machAddEquiv(table, entry->equivs[i], distance);
198  }
199 
200  for (i = 0; i < entry->count; i++) {
201  machCacheEntryVisit(cache, table, entry->equivs[i], distance + 1);
202  }
203 }
204 
205 static void rebuildCompatTables(int type, const char * name)
206  /*@globals tables, internalState @*/
207  /*@modifies tables, internalState @*/
208 {
209  machCache cache = &tables[currTables[type]].cache;
210  machEquivTable table = &tables[currTables[type]].equiv;
211  const char * key = name;
212  int i;
213 
214  for (i = 0; i < cache->size; i++)
215  cache->cache[i].visited = 0;
216 
217  while (table->count > 0) {
218  --table->count;
219  table->list[table->count].name = _free(table->list[table->count].name);
220  }
221  table->count = 0;
222  table->list = _free(table->list);
223 
224  /*
225  * We have a general graph built using strings instead of pointers.
226  * Yuck. We have to start at a point at traverse it, remembering how
227  * far away everything is.
228  */
229  /*@-nullstate@*/ /* FIX: table->list may be NULL. */
230  machAddEquiv(table, key, 1);
231  machCacheEntryVisit(cache, table, key, 2);
232  return;
233  /*@=nullstate@*/
234 }
235 
236 static /*@null@*/ canonEntry lookupInCanonTable(const char * name,
237  const canonEntry table, int tableLen)
238  /*@*/
239 {
240  while (tableLen) {
241  tableLen--;
242  if (strcmp(name, table[tableLen].name))
243  continue;
244  /*@-immediatetrans -retalias@*/
245  return &(table[tableLen]);
246  /*@=immediatetrans =retalias@*/
247  }
248 
249  return NULL;
250 }
251 
252 static /*@observer@*/ /*@null@*/
253 const char * lookupInDefaultTable(const char * name,
254  const defaultEntry table, int tableLen)
255  /*@*/
256 {
257  while (tableLen) {
258  tableLen--;
259  if (table[tableLen].name && !strcmp(name, table[tableLen].name))
260  return table[tableLen].defName;
261  }
262 
263  return name;
264 }
265 
266 static void addMacroDefault(const char * macroname,
267  const char * val, /*@null@*/ const char * body)
268  /*@globals rpmGlobalMacroContext, internalState @*/
269  /*@modifies rpmGlobalMacroContext, internalState @*/
270 {
271  if (body == NULL)
272  body = val;
273  addMacro(NULL, macroname, NULL, body, RMIL_DEFAULT);
274 }
275 
276 static void setPathDefault(const char * macroname, const char * subdir)
277  /*@globals rpmGlobalMacroContext, internalState @*/
278  /*@modifies rpmGlobalMacroContext, internalState @*/
279 {
280  if (macroname != NULL) {
281 #define _TOPDIRMACRO "%{_topdir}/"
282  char *body = alloca(sizeof(_TOPDIRMACRO) + strlen(subdir));
283  strcpy(body, _TOPDIRMACRO);
284  strcat(body, subdir);
285  addMacro(NULL, macroname, NULL, body, RMIL_DEFAULT);
286 #undef _TOPDIRMACRO
287  }
288 }
289 
290 /*@observer@*/ /*@unchecked@*/
291 static const char * ___build_pre = "\n\
292 RPM_SOURCE_DIR=\"%{_sourcedir}\"\n\
293 RPM_BUILD_DIR=\"%{_builddir}\"\n\
294 RPM_OPT_FLAGS=\"%{optflags}\"\n\
295 RPM_ARCH=\"%{_arch}\"\n\
296 RPM_OS=\"%{_os}\"\n\
297 export RPM_SOURCE_DIR RPM_BUILD_DIR RPM_OPT_FLAGS RPM_ARCH RPM_OS\n\
298 RPM_DOC_DIR=\"%{_docdir}\"\n\
299 export RPM_DOC_DIR\n\
300 RPM_PACKAGE_NAME=\"%{name}\"\n\
301 RPM_PACKAGE_VERSION=\"%{version}\"\n\
302 RPM_PACKAGE_RELEASE=\"%{release}\"\n\
303 export RPM_PACKAGE_NAME RPM_PACKAGE_VERSION RPM_PACKAGE_RELEASE\n\
304 %{?buildroot:RPM_BUILD_ROOT=\"%{buildroot}\"\n\
305 export RPM_BUILD_ROOT\n}\
306 ";
307 
308 #if defined(RPM_VENDOR_WINDRIVER)
309 /*@unchecked@*/
310 extern const char * __usrlibrpm;
311 /*@unchecked@*/
312 extern const char * __etcrpm;
313 #endif
314 
315 static void setDefaults(void)
316  /*@globals rpmGlobalMacroContext, internalState @*/
317  /*@modifies rpmGlobalMacroContext, internalState @*/
318 {
319 
320 #if defined(RPM_VENDOR_WINDRIVER)
321  addMacro(NULL, "_usrlibrpm", NULL, __usrlibrpm, RMIL_DEFAULT);
322  addMacro(NULL, "_etcrpm", NULL, __etcrpm, RMIL_DEFAULT);
323  addMacro(NULL, "_vendor", NULL, "%{?_host_vendor}%{!?_host_vendor:wrs}", RMIL_DEFAULT);
324 #endif
325 
326  addMacro(NULL, "_usr", NULL, USRPREFIX, RMIL_DEFAULT);
327  addMacro(NULL, "_var", NULL, VARPREFIX, RMIL_DEFAULT);
328  addMacro(NULL, "_prefix", NULL, "%{_usr}", RMIL_DEFAULT);
329 
330  addMacro(NULL, "___build_pre", NULL, ___build_pre, RMIL_DEFAULT);
331 
332  addMacroDefault("_topdir",
333  "%{_usr}/src/rpm", NULL);
334  addMacroDefault("_tmppath",
335  "%{_var}/tmp", NULL);
336  addMacroDefault("_dbpath",
337  "%{_var}/lib/rpm", NULL);
338  addMacroDefault("_defaultdocdir",
339  "%{_usr}/share/doc", NULL);
340 
341  addMacroDefault("_rpmfilename",
342  "%%{ARCH}/%%{NAME}-%%{VERSION}-%%{RELEASE}.%%{ARCH}.rpm",NULL);
343 
344  addMacroDefault("optflags",
345  "-O2 -g", NULL);
346  addMacroDefault("sigtype",
347  "none", NULL);
348  addMacroDefault("_buildshell",
349  "/bin/sh", NULL);
350 
351  setPathDefault("_builddir", "BUILD");
352  setPathDefault("_rpmdir", "RPMS");
353  setPathDefault("_srcrpmdir", "SRPMS");
354  setPathDefault("_sourcedir", "SOURCES");
355  setPathDefault("_specdir", "SPECS");
356 
357 }
358 
359 typedef struct cpu_vendor_os_gnu {
360 /*@owned@*/
361  const char * str;
362 /*@observer@*/
363  const char * cpu;
364 /*@observer@*/
365  const char * vendor;
366 /*@observer@*/
367  const char * os;
368 /*@observer@*/
369  const char * gnu;
370 } * CVOG_t;
371 
374 static int parseCVOG(const char * str, CVOG_t *cvogp)
375  /*@modifies *cvogp @*/
376 {
377  CVOG_t cvog = xcalloc(1, sizeof(*cvog));
378  char * p, * pe;
379 
380  cvog->str = p = xstrdup(str);
381  pe = p + strlen(p);
382  while (pe-- > p && isspace(*pe))
383  *pe = '\0';
384 
385  cvog->cpu = p;
386  cvog->vendor = "unknown";
387  cvog->os = "unknown";
388  cvog->gnu = "";
389  while (*p && !(*p == '-' || isspace(*p)))
390  p++;
391  if (*p != '\0') *p++ = '\0';
392 
393  cvog->vendor = p;
394  while (*p && !(*p == '-' || isspace(*p)))
395  p++;
396  if (*p != '-') {
397  if (*p != '\0') *p++ = '\0';
398  cvog->os = cvog->vendor;
399  cvog->vendor = "unknown";
400  } else {
401  if (*p != '\0') *p++ = '\0';
402 
403  cvog->os = p;
404  while (*p && !(*p == '-' || isspace(*p)))
405  p++;
406  if (*p == '-') {
407  *p++ = '\0';
408 
409  cvog->gnu = p;
410  while (*p && !(*p == '-' || isspace(*p)))
411  p++;
412  }
413  if (*p != '\0') *p++ = '\0';
414  }
415 
416  if (cvogp)
417  *cvogp = cvog;
418  else {
419  cvog->str = _free(cvog->str);
420  cvog = _free(cvog);
421  }
422  return 0;
423 }
424 
430 /*@-onlytrans@*/ /* XXX miRE array, not refcounted. */
431 static rpmRC rpmPlatform(const char * platform)
432  /*@globals nplatpat, platpat,
433  rpmGlobalMacroContext, h_errno, fileSystem, internalState @*/
434  /*@modifies nplatpat, platpat,
435  rpmGlobalMacroContext, fileSystem, internalState @*/
436 {
437  CVOG_t cvog = NULL;
438  rpmiob iob = NULL;
439  int init_platform = 0;
440  miRE mi_re = NULL;
441  int mi_nre = 0;
442  char * p, * pe;
443  rpmRC rc;
444  int xx;
445 
446  rc = rpmiobSlurp(platform, &iob);
447 
448  if (rc || iob == NULL) {
449  rc = RPMRC_FAIL;
450  goto exit;
451  }
452 
453  p = (char *)iob->b;
454  for (pe = p; p && *p; p = pe) {
455  pe = strchr(p, '\n');
456  if (pe)
457  *pe++ = '\0';
458 
459  while (*p && xisspace(*p))
460  p++;
461  if (*p == '\0' || *p == '#')
462  continue;
463 
464  if (init_platform) {
465  char * t = p + strlen(p);
466  while (--t > p && xisspace(*t))
467  *t = '\0';
468  if (t > p) {
469  xx = mireAppend(RPMMIRE_REGEX, 0, p, NULL, &mi_re, &mi_nre);
470  }
471  continue;
472  }
473 
474  if (!parseCVOG(p, &cvog) && cvog != NULL) {
475  addMacro(NULL, "_host_cpu", NULL, cvog->cpu, -1);
476  addMacro(NULL, "_host_vendor", NULL, cvog->vendor, -1);
477  addMacro(NULL, "_host_os", NULL, cvog->os, -1);
478  }
479 
480 #if defined(RPM_VENDOR_OPENPKG) /* explicit-platform */
481  /* do not use vendor and GNU attribution */
482  p = rpmExpand("%{_host_cpu}-%{_host_os}", NULL);
483 #else
484  p = rpmExpand("%{_host_cpu}-%{_host_vendor}-%{_host_os}",
485  (cvog && *cvog->gnu ? "-" : NULL),
486  (cvog ? cvog->gnu : NULL), NULL);
487 #endif
488  xx = mireAppend(RPMMIRE_STRCMP, 0, p, NULL, &mi_re, &mi_nre);
489  p = _free(p);
490 
491  init_platform++;
492  }
493  rc = (init_platform ? RPMRC_OK : RPMRC_FAIL);
494 
495 exit:
496  if (cvog) {
497  cvog->str = _free(cvog->str);
498  cvog = _free(cvog);
499  }
500  iob = rpmiobFree(iob);
501  if (rc == RPMRC_OK) {
503  platpat = mi_re;
504  nplatpat = mi_nre;
505  }
506  return rc;
507 }
508 /*@=onlytrans@*/
509 
510 #if defined(WITH_CPUINFO) && defined(WITH_SYCK)
511 static inline int rpmCpuinfoMatch(const char * feature, const char * EVR, rpmds cpuinfo)
512 {
513  rpmds cpufeature = rpmdsSingle(RPMTAG_REQUIRENAME, feature, EVR, RPMSENSE_PROBE);
514  int ret = rpmdsMatch(cpufeature, cpuinfo);
515 
516  (void)rpmdsFree(cpufeature);
517  cpufeature = NULL;
518  return ret;
519 }
520 
521 static rpmRC rpmCpuinfo(void)
522 {
523  rpmRC rc = RPMRC_FAIL;
524  const char *cpu, *_cpuinfo_path;
525  miRE mi_re = NULL;
526  int mi_nre = 0, xx, i;
527  CVOG_t cvog = NULL;
528  struct stat st;
529  char *yaml;
530  rpmsyck_node *tmp, node;
531  rpmSyck cpuinfoYaml;
532  FD_t fd;
533 
534  _cpuinfo_path = rpmGetPath("%{?_rpmhome}%{!?_rpmhome:" USRLIBRPM "}/cpuinfo.yaml", NULL);
535  if(Stat(_cpuinfo_path, &st))
536  return rc;
537 
538  fd = Fopen(_cpuinfo_path, "r");
539  _cpuinfo_path = _free(_cpuinfo_path);
540  yaml = xcalloc(st.st_size+1, 1);
541  Fread(yaml, 1, st.st_size, fd);
542  Fclose(fd);
543 
544  xx = rpmdsCpuinfo(&cpuinfoP, NULL);
545  cpuinfoYaml = rpmSyckLoad(yaml);
546  yaml = _free(yaml);
547  htGetEntry(cpuinfoYaml->firstNode->value.map, "cpuinfo", &tmp, NULL, NULL);
548  node = tmp[0]->value.seq;
549 
550  /* TODO: cleanup.. */
551  for(i = 0; node[i].type != T_END; i++) {
552  if(node[i].type == T_MAP) {
553  rpmsyck_node *tmp;
554  if(htHasEntry(node[i].value.map, "Family")) {
555  htGetEntry(node[i].value.map, "Family", &tmp, NULL, NULL);
556  const char *family = tmp[0]->value.key;
557  int j;
558  hashTable cpus = NULL;
559  if(rpmCpuinfoMatch(family, "", cpuinfoP)) {
560  if(htHasEntry(node[i].value.map, "Arch")) {
561  htGetEntry(node[i].value.map, "Arch", &tmp, NULL, NULL);
562  rpmsyck_node arch = tmp[0]->value.seq;
563  for(j = 0; arch[j].type != T_END; j++);
564  cpus = htCreate(j*2, 0, 0, NULL, NULL);
565  for(j = 0; arch[j].type != T_END; j++) {
566  if(htHasEntry(arch[j].value.map, "Extends")) {
567  if(htGetEntry(arch[j].value.map, "Extends", &tmp, NULL, NULL) &&
568  tmp[0]->type == T_STR && !htHasEntry(cpus, tmp[0]->value.key))
569  continue;
570  }
571  if(htHasEntry(arch[j].value.map, "Features")) {
572  htGetEntry(arch[j].value.map, "Features", &tmp, NULL, NULL);
573  rpmsyck_node features = tmp[0]->value.seq;
574  int k, match = 0;
575  for(k = 0; features[k].type != T_END; k++)
576  if(features[k].type == T_STR && !(match = rpmCpuinfoMatch(features[k].value.key, "", cpuinfoP))) break;
577  if(!match) continue;
578  }
579  if(htHasEntry(arch[j].value.map, "Name")) {
580  htGetEntry(arch[j].value.map, "Name", &tmp, NULL, NULL);
581  if(tmp[0]->type != T_STR) continue;
582  const char *name = tmp[0]->value.key;
583  rpmsyck_node alias = NULL;
584  if(htHasEntry(arch[j].value.map, "Alias")) {
585  htGetEntry(arch[j].value.map, "Alias", &tmp, NULL, NULL);
586  alias = tmp[0]->value.seq;
587  }
588  htAddEntry(cpus, name, alias);
589  }
590  }
591  }
592  if(htHasEntry(node[i].value.map, "Priority")) {
593  htGetEntry(node[i].value.map, "Priority", &tmp, NULL, NULL);
594  rpmsyck_node priority = tmp[0]->value.seq;
595  int j;
596  for(j = 0; priority[j].type != T_END; j++)
597  if(htHasEntry(cpus, priority[j].value.key)) {
598  xx = mireAppend(RPMMIRE_REGEX, 0, priority[j].value.key, NULL, &mi_re, &mi_nre);
599  htGetEntry(cpus, priority[j].value.key, &tmp, NULL, NULL);
600  if(tmp[0]) {
601  rpmsyck_node alias = tmp[0];
602  int k;
603  for(k = 0; alias[k].type != T_END; k++)
604  xx = mireAppend(RPMMIRE_REGEX, 0, alias[k].value.key, NULL, &mi_re, &mi_nre);
605  }
606  }
607  }
608  }
609  if(cpus) cpus = htFree(cpus);
610  }
611  }
612  }
613 
614  cpuinfoYaml = rpmSyckFree(cpuinfoYaml);
615 
616  xx = mireAppend(RPMMIRE_REGEX, 0, "noarch", NULL, &mi_re, &mi_nre);
617 
618  cpu = mi_re[0].pattern;
619  if(cpu != NULL)
620  {
621  if (!parseCVOG(cpu, &cvog) && cvog != NULL) {
622  addMacro(NULL, "_host_cpu", NULL, cvog->cpu, -1);
623  addMacro(NULL, "_host_vendor", NULL, cvog->vendor, -1);
624  addMacro(NULL, "_host_os", NULL, cvog->os, -1);
625  }
626  if (cvog) {
627  cvog->str = _free(cvog->str);
628  cvog = _free(cvog);
629  }
630 
631  rc = RPMRC_OK;
632  if (rc == RPMRC_OK) {
634  platpat = mi_re;
635  nplatpat = mi_nre;
636  }
637 
638  }
639  return rc;
640 }
641 #endif
642 
643 /*@-onlytrans@*/ /* XXX miRE array, not refcounted. */
644 int rpmPlatformScore(const char * platform, void * mi_re, int mi_nre)
645 {
646  miRE mire;
647  int i;
648 
649  if (mi_re == NULL) {
650  mi_re = platpat;
651  mi_nre = nplatpat;
652  }
653 
654  if ((mire = mi_re) != NULL)
655  for (i = 0; i < mi_nre; i++) {
656  if (mireRegexec(mire + i, platform, 0) >= 0)
657  return (i + 1);
658  }
659  return 0;
660 }
661 /*@=onlytrans@*/
662 
665 static void defaultMachine(/*@out@*/ const char ** arch,
666  /*@out@*/ const char ** os)
667  /*@globals rpmGlobalMacroContext, h_errno, fileSystem, internalState @*/
668  /*@modifies *arch, *os, rpmGlobalMacroContext, fileSystem, internalState @*/
669 {
670 #if defined(RPM_VENDOR_OPENPKG) /* larger-utsname */
671  /* utsname fields on some platforms (like HP-UX) are very small
672  (just about 8 characters). This is too small for OpenPKG, so cheat! */
673  static struct utsname un_real;
674  static struct {
675  char sysname[32];
676  char nodename[32];
677  char release[32];
678  char version[32];
679  char machine[32];
680  } un;
681 #else
682  static struct utsname un;
683 #endif
684  static int gotDefaults = 0;
685  int rc;
686 
687  while (!gotDefaults) {
688 #if defined(RPM_VENDOR_WINDRIVER)
689  const char * _platform = rpmGetPath(__etcrpm, "/platform", NULL);
690 #else
691  const char * _platform = platform;
692 #endif
693  CVOG_t cvog = NULL;
694 #if defined(RPM_VENDOR_OPENPKG) /* larger-utsname */
695  const char *cp;
696 #endif
697 #if defined(RPM_VENDOR_OPENPKG) /* larger-utsname */
698  /* utsname fields on some platforms (like HP-UX) are very small
699  (just about 8 characters). This is too small for OpenPKG, so cheat! */
700  rc = uname(&un_real);
701  strncpy(un.sysname, un_real.sysname, sizeof(un.sysname)); un.sysname [sizeof(un.sysname) -1] = '\0';
702  strncpy(un.nodename, un_real.nodename, sizeof(un.nodename)); un.nodename[sizeof(un.nodename)-1] = '\0';
703  strncpy(un.release, un_real.release, sizeof(un.release)); un.release [sizeof(un.release) -1] = '\0';
704  strncpy(un.version, un_real.version, sizeof(un.version)); un.version [sizeof(un.version) -1] = '\0';
705  strncpy(un.machine, un_real.machine, sizeof(un.machine)); un.machine [sizeof(un.machine) -1] = '\0';
706 #else
707  rc = uname(&un);
708 #endif
709  if (rc < 0) return;
710 
711 #if defined(RPM_VENDOR_OPENPKG) /* platform-major-minor-only */
712  /* Reduce the platform version to major and minor version numbers */
713  {
714  char *cp;
715  char *cpR;
716  int n;
717  cpR = un.release;
718  if ((n = strcspn(cpR, "0123456789")) > 0)
719  cpR += n;
720  if ((n = strspn(cpR, "0123456789.")) > 0) {
721  /* terminate after "N.N.N...." prefix */
722  cpR[n] = '\0';
723  /* shorten to "N.N" if longer */
724  if ((cp = strchr(cpR, '.')) != NULL) {
725  if ((cp = strchr(cp+1, '.')) != NULL)
726  *cp = '\0';
727  }
728  strcat(un.sysname, cpR);
729  }
730  /* fix up machine hardware name containing white-space as it
731  happens to be on Power Macs running MacOS X */
732  if (!strncmp(un.machine, "Power Macintosh", 15))
733  sprintf(un.machine, "powerpc");
734  }
735 #endif
736 
737  if (!strncmp(un.machine, "Power Macintosh", 15)) {
738  sprintf(un.machine, "ppc");
739  }
740 
741 #if defined(RPM_VENDOR_OPENPKG) /* explicit-platform */
742  /* allow the path to the "platforms" file be overridden under run-time */
743  cp = rpmExpand("%{?__platform}", NULL);
744  if (cp == NULL || cp[0] == '\0')
745  cp = _platform;
746  if (rpmPlatform(cp) == RPMRC_OK) {
747 #elif defined(WITH_CPUINFO) && defined(WITH_SYCK)
748  if (rpmPlatform(_platform) == RPMRC_OK || rpmCpuinfo() == RPMRC_OK) {
749 #else
750  if (rpmPlatform(_platform) == RPMRC_OK) {
751 #endif
752  const char * s;
753  gotDefaults = 1;
754  s = rpmExpand("%{?_host_cpu}", NULL);
755  if (s && *s != '\0') {
756  strncpy(un.machine, s, sizeof(un.machine));
757  un.machine[sizeof(un.machine)-1] = '\0';
758  }
759  s = _free(s);
760  s = rpmExpand("%{?_host_os}", NULL);
761  if (s && *s != '\0') {
762  strncpy(un.sysname, s, sizeof(un.sysname));
763  un.sysname[sizeof(un.sysname)-1] = '\0';
764  }
765  s = _free(s);
766  }
767 
768 #if defined(RPM_VENDOR_OPENPKG) /* explicit-platform */
769  /* cleanup after above processing */
770  if (cp != NULL && cp != _platform)
771  cp = _free(cp);
772 #endif
773 #if defined(RPM_VENDOR_WINDRIVER)
774  _platform = _free(_platform);
775 #endif
776 
777  if (configTarget && !parseCVOG(configTarget, &cvog) && cvog != NULL) {
778  gotDefaults = 1;
779  if (cvog->cpu && cvog->cpu[0] != '\0') {
780  strncpy(un.machine, cvog->cpu, sizeof(un.machine));
781  un.machine[sizeof(un.machine)-1] = '\0';
782  }
783  if (cvog->os && cvog->os[0] != '\0') {
784  strncpy(un.sysname, cvog->os, sizeof(un.sysname));
785  un.sysname[sizeof(un.sysname)-1] = '\0';
786  }
787  cvog->str = _free(cvog->str);
788  cvog = _free(cvog);
789  }
790  if (gotDefaults)
791  break;
792  gotDefaults = 1;
793  break;
794  }
795 
796  if (arch) *arch = un.machine;
797  if (os) *os = un.sysname;
798 }
799 
807 static void rpmSetTables(int archTable, int osTable)
808  /*@globals currTables, rpmGlobalMacroContext, h_errno,
809  fileSystem, internalState @*/
810  /*@modifies currTables, rpmGlobalMacroContext,
811  fileSystem, internalState @*/
812 {
813  const char * arch, * os;
814 
815  defaultMachine(&arch, &os);
816 
817  if (currTables[ARCH] != archTable) {
818  currTables[ARCH] = archTable;
819  rebuildCompatTables(ARCH, arch);
820  }
821 
822  if (currTables[OS] != osTable) {
823  currTables[OS] = osTable;
824  rebuildCompatTables(OS, os);
825  }
826 }
827 
828 static void rpmSetMachine(const char * arch, const char * os)
829  /*@globals current, rpmGlobalMacroContext, h_errno,
830  fileSystem, internalState @*/
831  /*@modifies current, rpmGlobalMacroContext,
832  fileSystem, internalState @*/
833 {
834  if (arch == NULL) {
835 /*@i@*/ defaultMachine(&arch, NULL);
836  if (tables[currTables[ARCH]].hasTranslate)
837  arch = lookupInDefaultTable(arch,
838  tables[currTables[ARCH]].defaults,
839  tables[currTables[ARCH]].defaultsLength);
840  }
841 assert(arch != NULL);
842 
843  if (os == NULL) {
844 /*@i@*/ defaultMachine(NULL, &os);
845  if (tables[currTables[OS]].hasTranslate)
846  os = lookupInDefaultTable(os,
847  tables[currTables[OS]].defaults,
848  tables[currTables[OS]].defaultsLength);
849  }
850 assert(os != NULL);
851 
852 
853  if (!current[ARCH] || strcmp(arch, current[ARCH])) {
854  current[ARCH] = _free(current[ARCH]);
855  current[ARCH] = xstrdup(arch);
856  rebuildCompatTables(ARCH, arch);
857  }
858 
859  if (!current[OS] || strcmp(os, current[OS])) {
860  char * t = xstrdup(os);
861  current[OS] = _free(current[OS]);
862  if (!strcmp(t, "linux"))
863  *t = 'L';
864  current[OS] = t;
865  rebuildCompatTables(OS, os);
866  }
867 }
868 
869 static void getMachineInfo(int type, /*@null@*/ /*@out@*/ const char ** name,
870  /*@null@*/ /*@out@*/int * num)
871  /*@modifies *name, *num @*/
872 {
873  canonEntry canon;
874  int which = currTables[type];
875 
876  /* use the normal canon tables, even if we're looking up build stuff */
877  if (which >= 2) which -= 2;
878 
879  canon = lookupInCanonTable(current[type],
880  tables[which].canons,
881  tables[which].canonsLength);
882 
883  if (canon) {
884  if (num) *num = canon->num;
885  if (name) *name = canon->short_name;
886  } else {
887  if (num) *num = 255;
888 #if defined(WITH_CPUINFO)
889  if (name)
890  {
891  if(type == ARCH)
892  {
893  int i, j, n;
894  ARGV_t archs = NULL;
895  char *pref = rpmExpand("%{?_prefer_target_cpu}", NULL);
896 
897  (void) argvSplit(&archs, pref, " ");
898  for(i = 0, n = argvCount(archs); (i < n && !*name); i++)
899  if((j = rpmPlatformScore(archs[i], platpat, nplatpat)) > 0)
900  *name = ((miRE)platpat)[j-1].pattern;
901 
902  archs = argvFree(archs);
903  pref = _free(pref);
904  }
905  if(!*name) *name = current[type];
906  }
907 #else
908  if (name) *name = current[type];
909 #endif
910  }
911 }
912 
913 static void rpmRebuildTargetVars(const char ** target, const char ** canontarget)
914 {
915 
916  char *ca = NULL, *co = NULL, *ct = NULL;
917  int x;
918 
919  /* Rebuild the compat table to recalculate the current target arch. */
920 
921  rpmSetMachine(NULL, NULL);
924 
925  if (target && *target) {
926  char *c;
927  /* Set arch and os from specified build target */
928  ca = xstrdup(*target);
929  if ((c = strchr(ca, '-')) != NULL) {
930  *c++ = '\0';
931 
932  if ((co = strrchr(c, '-')) == NULL) {
933  co = c;
934  } else {
935  if (!xstrcasecmp(co, "-gnu"))
936  *co = '\0';
937  if ((co = strrchr(c, '-')) == NULL)
938  co = c;
939  else
940  co++;
941  }
942  if (co != NULL) co = xstrdup(co);
943  }
944  } else {
945  const char *a = NULL;
946  const char *o = NULL;
947  /* Set build target from rpm arch and os */
948  getMachineInfo(ARCH, &a, NULL);
949  ca = (a) ? xstrdup(a) : NULL;
950  getMachineInfo(OS, &o, NULL);
951  co = (o) ? xstrdup(o) : NULL;
952  }
953 
954  /* If still not set, Set target arch/os from default uname(2) values */
955  if (ca == NULL) {
956  const char *a = NULL;
957  defaultMachine(&a, NULL);
958  ca = (a) ? xstrdup(a) : NULL;
959  }
960  if (ca != NULL)
961  for (x = 0; ca[x] != '\0'; x++)
962  ca[x] = (char)xtolower(ca[x]);
963 
964  if (co == NULL) {
965  const char *o = NULL;
966  defaultMachine(NULL, &o);
967  co = (o) ? xstrdup(o) : NULL;
968  }
969  if (co != NULL)
970  for (x = 0; co[x] != '\0'; x++)
971  co[x] = (char)xtolower(co[x]);
972 
973  /* XXX For now, set canonical target to arch-os */
974  if (ct == NULL) {
975  ct = xmalloc(strlen(ca) + sizeof("-") + strlen(co));
976  sprintf(ct, "%s-%s", ca, co);
977  }
978 
979 /*
980  * XXX All this macro pokery/jiggery could be achieved by doing a delayed
981  * rpmInitMacros(NULL, PER-PLATFORM-MACRO-FILE-NAMES);
982  */
983  delMacro(NULL, "_target");
984  addMacro(NULL, "_target", NULL, ct, RMIL_RPMRC);
985  delMacro(NULL, "_target_cpu");
986  addMacro(NULL, "_target_cpu", NULL, ca, RMIL_RPMRC);
987  delMacro(NULL, "_target_os");
988  addMacro(NULL, "_target_os", NULL, co, RMIL_RPMRC);
989 
990  if (canontarget)
991  *canontarget = ct;
992  else
993  ct = _free(ct);
994  ca = _free(ca);
995  /*@-usereleased@*/
996  co = _free(co);
997  /*@=usereleased@*/
998 }
999 
1000 void rpmFreeRpmrc(void)
1001  /*@globals current, tables, defaultsInitialized @*/
1002  /*@modifies current, tables, defaultsInitialized @*/
1003 {
1004  int i, j, k;
1005 
1006  (void)mireFreeAll(platpat, nplatpat);
1007  platpat = NULL;
1008  nplatpat = 0;
1009 
1010  for (i = 0; i < RPM_MACHTABLE_COUNT; i++) {
1011  tableType t;
1012  t = tables + i;
1013  if (t->equiv.list) {
1014  for (j = 0; j < t->equiv.count; j++)
1015  t->equiv.list[j].name = _free(t->equiv.list[j].name);
1016  t->equiv.list = _free(t->equiv.list);
1017  t->equiv.count = 0;
1018  }
1019  if (t->cache.cache) {
1020  for (j = 0; j < t->cache.size; j++) {
1021  machCacheEntry e;
1022  e = t->cache.cache + j;
1023  if (e == NULL)
1024  /*@innercontinue@*/ continue;
1025  e->name = _free(e->name);
1026  if (e->equivs) {
1027  for (k = 0; k < e->count; k++)
1028  e->equivs[k] = _free(e->equivs[k]);
1029  e->equivs = _free(e->equivs);
1030  }
1031  }
1032  t->cache.cache = _free(t->cache.cache);
1033  t->cache.size = 0;
1034  }
1035  if (t->defaults) {
1036  for (j = 0; j < t->defaultsLength; j++) {
1037  t->defaults[j].name = _free(t->defaults[j].name);
1038  t->defaults[j].defName = _free(t->defaults[j].defName);
1039  }
1040  t->defaults = _free(t->defaults);
1041  t->defaultsLength = 0;
1042  }
1043  if (t->canons) {
1044  for (j = 0; j < t->canonsLength; j++) {
1045  t->canons[j].name = _free(t->canons[j].name);
1046  t->canons[j].short_name = _free(t->canons[j].short_name);
1047  }
1048  t->canons = _free(t->canons);
1049  t->canonsLength = 0;
1050  }
1051  }
1052 
1053  current[OS] = _free(current[OS]);
1054  current[ARCH] = _free(current[ARCH]);
1055  defaultsInitialized = 0;
1056 /*@-globstate -nullstate@*/ /* FIX: platpat/current may be NULL */
1057  return;
1058 /*@=globstate =nullstate@*/
1059 }
1060 
1065 static int rpmReadRC(const char *macrofiles)
1066  /*@globals defaultsInitialized,
1067  rpmGlobalMacroContext, rpmCLIMacroContext, h_errno,
1068  fileSystem, internalState @*/
1069  /*@modifies defaultsInitialized, rpmGlobalMacroContext,
1070  fileSystem, internalState @*/
1071 {
1072  int rc = 0;
1073 
1074  if (!defaultsInitialized) {
1075  setDefaults();
1076  defaultsInitialized = 1;
1077  }
1078 
1079  /* Read macro files. */
1080  { const char *mfpath = rpmExpand(macrofiles, NULL);
1081 
1082  if (mfpath != NULL) {
1083  rpmInitMacros(NULL, mfpath);
1084  mfpath = _free(mfpath);
1085  }
1086  }
1087 
1088  return rc;
1089 }
1090 
1091 int rpmReadConfigFiles(/*@unused@*/ const char * file,
1092  const char * target)
1093  /*@globals configTarget, rpmMacrofiles @*/
1094  /*@modifies configTarget @*/
1095 {
1096  mode_t mode = 0022;
1097 
1098 #ifdef PREMACROFILES
1099  if (rpmReadRC(PREMACROFILES)) return -1;
1100 #endif
1101 
1102  /* Reset umask to its default umask(2) value. */
1103  mode = umask(mode);
1104 
1105  configTarget = target;
1106 
1107  /* Preset target macros */
1108  /*@-nullstate@*/ /* FIX: target can be NULL */
1109  rpmRebuildTargetVars(&target, NULL);
1110 
1111  /* Read the files */
1112 /*@-globs@*/
1113  if (rpmReadRC(rpmMacrofiles)) return -1;
1114 /*@=globs@*/
1115 
1116  /* Reset target macros */
1117  rpmRebuildTargetVars(&target, NULL);
1118  /*@=nullstate@*/
1119 
1120  /* Finally set target platform */
1121  { const char *cpu = rpmExpand("%{_target_cpu}", NULL);
1122  const char *os = rpmExpand("%{_target_os}", NULL);
1123  rpmSetMachine(cpu, os);
1124 
1125  cpu = _free(cpu);
1126  os = _free(os);
1127  }
1128  configTarget = NULL;
1129 
1130  /* Force Lua state initialization */
1131 #ifdef WITH_LUA
1132  (void)rpmluaGetPrintBuffer(NULL);
1133 #if defined(RPM_VENDOR_OPENPKG) /* rpm-lua-extensions-based-on-rpm-lib-functionality */
1134  (void)rpmluaextActivate(rpmluaGetGlobalState());
1135 #endif /* RPM_VENDOR_OPENPKG */
1136 #endif
1137 
1138  return 0;
1139 }
1140 
1141 int rpmShowRC(FILE * fp)
1142 {
1143  rpmds ds = NULL;
1144  int i;
1145  machEquivTable equivTable;
1146  int xx;
1147  miRE mire;
1148 
1149  /* the caller may set the build arch which should be printed here */
1150  fprintf(fp, "ARCHITECTURE AND OS:\n");
1151  fprintf(fp, "build arch : %s\n", current[ARCH]);
1152 
1153  fprintf(fp, "compatible build archs:");
1154  equivTable = &tables[RPM_MACHTABLE_BUILDARCH].equiv;
1155  for (i = 0; i < equivTable->count; i++)
1156  fprintf(fp," %s", equivTable->list[i].name);
1157  fprintf(fp, "\n");
1158 
1159  fprintf(fp, "build os : %s\n", current[OS]);
1160 
1161  fprintf(fp, "compatible build os's :");
1162  equivTable = &tables[RPM_MACHTABLE_BUILDOS].equiv;
1163  for (i = 0; i < equivTable->count; i++)
1164  fprintf(fp," %s", equivTable->list[i].name);
1165  fprintf(fp, "\n");
1166 
1167  fprintf(fp, "install arch : %s\n", current[ARCH]);
1168  fprintf(fp, "install os : %s\n", current[OS]);
1169 
1170  fprintf(fp, "compatible archs :");
1171  for (mire = platpat, i = 0; i < nplatpat; i++)
1172  fprintf(fp, " %s", mire[i].pattern);
1173  fprintf(fp, "\n");
1174 
1175  fprintf(fp, "compatible os's :");
1176  equivTable = &tables[RPM_MACHTABLE_INSTOS].equiv;
1177  for (i = 0; i < equivTable->count; i++)
1178  fprintf(fp," %s", equivTable->list[i].name);
1179  fprintf(fp, "\n");
1180 
1181  { const char * s = rpmExpand("%{?optflags}", NULL);
1182  fprintf(fp, "%-21s : %s\n", "optflags", ((s && *s) ? s : "(not set)"));
1183  s = _free(s);
1184 
1185 #ifdef WITH_LUA
1186  fprintf(fp, "\nLUA MODULES:\n");
1187 /*@-globs@*/
1188  s = rpmExpand(rpmluaFiles, NULL);
1189 /*@=globs@*/
1190  fprintf(fp, "%-21s : %s\n", "luafiles", ((s && *s) ? s : "(not set)"));
1191  s = _free(s);
1192 /*@-globs@*/
1193  s = rpmExpand(rpmluaPath, NULL);
1194 /*@=globs@*/
1195  fprintf(fp, "%-21s : %s\n", "luapath", ((s && *s) ? s : "(not set)"));
1196  s = _free(s);
1197 #endif
1198 
1199  fprintf(fp, "\nMACRO DEFINITIONS:\n");
1200 /*@-globs@*/
1201  s = rpmExpand(rpmMacrofiles, NULL);
1202 /*@=globs@*/
1203  fprintf(fp, "%-21s : %s\n", "macrofiles", ((s && *s) ? s : "(not set)"));
1204  s = _free(s);
1205  }
1206 
1207  if (rpmIsVerbose()) {
1208  rpmPRCO PRCO = rpmdsNewPRCO(NULL);
1209  xx = rpmdsSysinfo(PRCO, NULL);
1210  ds = rpmdsFromPRCO(PRCO, RPMTAG_PROVIDENAME);
1211  if (ds != NULL) {
1212  const char * fn = (_sysinfo_path ? _sysinfo_path : "/etc/rpm/sysinfo");
1213  fprintf(fp, _("Configured system provides (from %s):\n"), fn);
1214  ds = rpmdsInit(ds);
1215  while (rpmdsNext(ds) >= 0) {
1216  const char * DNEVR = rpmdsDNEVR(ds);
1217  if (DNEVR != NULL)
1218  fprintf(fp, " %s\n", DNEVR+2);
1219  }
1220  (void)rpmdsFree(ds);
1221  ds = NULL;
1222  fprintf(fp, "\n");
1223  }
1224  PRCO = rpmdsFreePRCO(PRCO);
1225  }
1226 
1227  if (rpmIsVerbose()) {
1228  fprintf(fp, _("Features provided by rpmlib installer:\n"));
1229  xx = rpmdsRpmlib(&ds, NULL);
1230  ds = rpmdsInit(ds);
1231  while (rpmdsNext(ds) >= 0) {
1232  const char * DNEVR = rpmdsDNEVR(ds);
1233  if (DNEVR != NULL)
1234  fprintf(fp, " %s\n", DNEVR+2);
1235  }
1236  (void)rpmdsFree(ds);
1237  ds = NULL;
1238  fprintf(fp, "\n");
1239 
1240  if(cpuinfoP == NULL)
1241  xx = rpmdsCpuinfo(&cpuinfoP, NULL);
1242  if (cpuinfoP != NULL) {
1243 #if defined(WITH_CPUINFO)
1244  const char * fn = "libcpuinfo";
1245 #else
1246  const char * fn = (_cpuinfo_path ? _cpuinfo_path : "/proc/cpuinfo");
1247 #endif
1248  fprintf(fp,
1249  _("Features provided by current cpuinfo (from %s):\n"), fn);
1251  while (rpmdsNext(cpuinfoP) >= 0) {
1252  const char * DNEVR = rpmdsDNEVR(cpuinfoP);
1253  if (DNEVR != NULL)
1254  fprintf(fp, " %s\n", DNEVR+2);
1255  }
1256  (void)rpmdsFree(cpuinfoP);
1257  cpuinfoP = NULL;
1258 
1259  fprintf(fp, "\n");
1260  }
1261  }
1262 
1263  if (rpmIsDebug()) {
1264  xx = rpmdsGetconf(&ds, NULL);
1265  if (ds != NULL) {
1266  fprintf(fp,
1267  _("Features provided by current getconf:\n"));
1268  ds = rpmdsInit(ds);
1269  while (rpmdsNext(ds) >= 0) {
1270  const char * DNEVR = rpmdsDNEVR(ds);
1271  if (DNEVR != NULL)
1272  fprintf(fp, " %s\n", DNEVR+2);
1273  }
1274  (void)rpmdsFree(ds);
1275  ds = NULL;
1276  fprintf(fp, "\n");
1277  }
1278 
1279  xx = rpmdsUname(&ds, NULL);
1280  if (ds != NULL) {
1281  fprintf(fp,
1282  _("Features provided by current uname:\n"));
1283  ds = rpmdsInit(ds);
1284  while (rpmdsNext(ds) >= 0) {
1285  const char * DNEVR = rpmdsDNEVR(ds);
1286  if (DNEVR != NULL)
1287  fprintf(fp, " %s\n", DNEVR+2);
1288  }
1289  (void)rpmdsFree(ds);
1290  ds = NULL;
1291  fprintf(fp, "\n");
1292  }
1293  }
1294 
1295  rpmDumpMacroTable(NULL, fp);
1296 
1297  return 0;
1298 }