rpm  5.4.10
spec.c
Go to the documentation of this file.
1 
6 #include "system.h"
7 
8 #include <rpmio.h>
9 #include <rpmiotypes.h>
10 #include <rpmlog.h>
11 #include <rpmpgp.h>
12 
13 #include "buildio.h"
14 #include "rpmds.h"
15 #include "rpmfi.h"
16 #include "rpmts.h"
17 
18 #include "rpmlua.h"
19 
20 #include "debug.h"
21 
22 /*@unchecked@*/
24 
25 /*@unchecked@*/
27 
28 /*@-redecl@*/
29 extern int specedit;
30 /*@=redecl@*/
31 
32 #define SKIPWHITE(_x) {while(*(_x) && (xisspace(*_x) || *(_x) == ',')) (_x)++;}
33 #define SKIPNONWHITE(_x){while(*(_x) &&!(xisspace(*_x) || *(_x) == ',')) (_x)++;}
34 
35 /*@access rpmluav @*/
36 
41 static inline
42 /*@null@*/ struct TriggerFileEntry * freeTriggerFiles(/*@only@*/ /*@null@*/ struct TriggerFileEntry * p)
43  /*@modifies p @*/
44 {
45  struct TriggerFileEntry *o, *q = p;
46 
47  while (q != NULL) {
48  o = q;
49  q = q->next;
50  o->fileName = _free(o->fileName);
51  o->script = _free(o->script);
52  o->prog = _free(o->prog);
53  o = _free(o);
54  }
55  return NULL;
56 }
57 
63 static inline
64 /*@null@*/ struct Source * freeSources(/*@only@*/ /*@null@*/ struct Source * s)
65  /*@modifies s @*/
66 {
67  struct Source *r, *t = s;
68 
69  while (t != NULL) {
70  r = t;
71  t = t->next;
72  r->fullSource = _free(r->fullSource);
73  r = _free(r);
74  }
75  return NULL;
76 }
77 
78 rpmRC lookupPackage(Spec spec, const char *name, int flag, /*@out@*/Package *pkgp)
79 {
80  HE_t he = (HE_t) memset(alloca(sizeof(*he)), 0, sizeof(*he));
81  char *NV = NULL;
82  char *N = NULL;
83  char *V = NULL;
84  Package p;
85  Package lastp = spec->packages;
86  rpmRC rc = RPMRC_OK;
87  int xx;
88 
89  if (lastp == NULL) /* XXX segfault avoidance */
90  goto exit;
91  /* "main" package */
92  if (name == NULL)
93  goto exit;
94 
95  /* Construct package name */
96  if (flag == PART_SUBNAME) {
97  he->tag = RPMTAG_NAME;
98  xx = headerGet(spec->packages->header, he, 0);
99 assert(xx != 0 && he->p.str != NULL);
100  N = rpmExpand(he->p.str, "-", name, NULL);
101  he->p.ptr = _free(he->p.ptr);
102  } else {
103  N = xstrdup(name);
104  /* XXX restrict V to leading digit to prevent NV split ambiguity. */
105  if ((V = strrchr(N, '-')) != NULL && xisdigit(V[1])) {
106  NV = xstrdup(N);
107  *V++ = '\0';
108  } else
109  V = NULL;
110  }
111 
112  /* Match last package with same N or same {N,V} */
113  lastp = NULL;
114  for (p = spec->packages; p != NULL; p = p->next) {
115  char *nv, *n, *v;
116  nv = n = v = NULL;
117  he->tag = RPMTAG_NAME;
118  xx = headerGet(p->header, he, 0);
119  if (xx && he->p.str != NULL) {
120  n = (char *) he->p.str;
121  he->p.str = NULL;
122  }
123  if (NV != NULL) {
124  he->tag = RPMTAG_VERSION;
125  xx = headerGet(p->header, he, 0);
126  if (xx && he->p.str != NULL) {
127  v = (char *) he->p.str;
128  he->p.str = NULL;
129  nv = rpmExpand(n, "-", v, NULL);
130  }
131  }
132 
133  if (NV == NULL) {
134  if (!strcmp(N, n))
135  lastp = p;
136  } else {
137  if (!strcmp(NV, nv) || !strcmp(NV, n)
138  || (!strcmp(N, n) && (V == NULL || !strcmp(V, v))))
139  lastp = p;
140  }
141 /*@-usereleased@*/
142  n = _free(n);
143  v = _free(v);
144  nv = _free(nv);
145 /*@=usereleased@*/
146  }
147  rc = (lastp == NULL ? RPMRC_FAIL : RPMRC_OK);
148  NV = _free(NV);
149  N = _free(N);
150 
151 exit:
152  if (pkgp)
153  /*@-dependenttrans@*/ *pkgp = lastp; /*@=dependenttrans@*/
154  return rc;
155 }
156 
157 static void pkgFini(void * _pkg)
158  /*@modifies _pkg @*/
159 {
160  Package pkg = _pkg;
161 
162  if (pkg == NULL) return; /* XXX assert? */
163 
164  pkg->preInFile = _free(pkg->preInFile);
165  pkg->postInFile = _free(pkg->postInFile);
166  pkg->preUnFile = _free(pkg->preUnFile);
167  pkg->postUnFile = _free(pkg->postUnFile);
168  pkg->verifyFile = _free(pkg->verifyFile);
170 
171  (void)headerFree(pkg->header);
172  pkg->header = NULL;
173  (void)rpmdsFree(pkg->ds);
174  pkg->ds = NULL;
175  pkg->fileList = rpmiobFree(pkg->fileList);
176  pkg->fileFile = _free(pkg->fileFile);
177  if (pkg->fi != NULL) {
178  rpmfi fi = pkg->fi;
179  pkg->fi = NULL;
180  fi = rpmfiFree(fi);
181  }
182 
183  pkg->specialDoc = rpmiobFree(pkg->specialDoc);
185 }
186 
187 /*@unchecked@*/ /*@only@*/ /*@null@*/
189 
191 {
192  Package pkg;
193 
194  if (_pkgPool == NULL) {
195  _pkgPool = rpmioNewPool("pkg", sizeof(*pkg), -1, _pkg_debug,
196  NULL, NULL, pkgFini);
197  pool = _pkgPool;
198  }
199  pkg = (Package) rpmioGetPool(pool, sizeof(*pkg));
200  memset(((char *)pkg)+sizeof(pkg->_item), 0, sizeof(*pkg)-sizeof(pkg->_item));
201  return pkg;
202 }
203 
204 Package newPackage(/*@unused@*/ Spec spec)
205 {
206  Package pkg = pkgGetPool(_pkgPool);
207 
208  pkg->header = headerNew();
209  pkg->ds = NULL;
210 
211  pkg->autoProv = ((_rpmbuildFlags & 0x1) != 0);
212  pkg->autoReq = ((_rpmbuildFlags & 0x2) != 0);
213 
214 #if 0
215  pkg->reqProv = NULL;
216  pkg->triggers = NULL;
217  pkg->triggerScripts = NULL;
218 #endif
219 
220  pkg->triggerFiles = NULL;
221 
222  pkg->fileFile = NULL;
223  pkg->fileList = NULL;
224 
225  pkg->fi = NULL;
226 
227  pkg->preInFile = NULL;
228  pkg->postInFile = NULL;
229  pkg->preUnFile = NULL;
230  pkg->postUnFile = NULL;
231  pkg->verifyFile = NULL;
232  pkg->sanityCheckFile = NULL;
233 
234  pkg->specialDoc = NULL;
235 
236  pkg->next = NULL;
237 
238  return (Package)rpmioLinkPoolItem((rpmioItem)pkg, __FUNCTION__, __FILE__, __LINE__);
239 }
240 
242 {
243  Package p;
244 
245  while ((p = packages) != NULL) {
246  packages = p->next;
247  p->next = NULL;
248  p = freePackage(p);
249  }
250  return NULL;
251 }
252 
255 static inline /*@owned@*/ struct Source *findSource(Spec spec, rpmuint32_t num, int flag)
256  /*@*/
257 {
258  struct Source *p;
259 
260  for (p = spec->sources; p != NULL; p = p->next)
261  if ((num == p->num) && (p->flags & flag)) return p;
262 
263  return NULL;
264 }
265 
269 {
270  return spec->numSources;
271 }
272 
276  /* @ */
277 {
278  struct Source *p = spec->sources;
279  int i;
280 
281  for (i = 0; i < num; i++)
282  if ((p = p->next) == NULL) return NULL;
283 
284 /*@-usereleased@*/
285  return p;
286 /*@=usereleased@*/
287 }
288 
292 {
293  return source->source;
294 }
295 
299 {
300  return source->fullSource;
301 }
302 
306 {
307  return source->num;
308 }
309 
313 {
314  return source->flags;
315 }
316 
317 int parseNoSource(Spec spec, const char * field, rpmTag tag)
318 {
319  const char *f, *fe;
320  const char *name;
321  rpmuint32_t num, flag;
322 
323  if (tag == RPMTAG_NOSOURCE) {
324  flag = RPMFILE_SOURCE;
325  name = "source";
326  } else {
327  flag = RPMFILE_PATCH;
328  name = "patch";
329  }
330 
331  fe = field;
332  for (f = fe; *f != '\0'; f = fe) {
333  struct Source *p;
334 
335  SKIPWHITE(f);
336  if (*f == '\0')
337  break;
338  fe = f;
339  SKIPNONWHITE(fe);
340  if (*fe != '\0') fe++;
341 
342  if (parseNum(f, &num)) {
343  rpmlog(RPMLOG_ERR, _("line %d: Bad number: %s\n"),
344  spec->lineNum, f);
345  return RPMRC_FAIL;
346  }
347 
348  if (! (p = findSource(spec, num, flag))) {
349  rpmlog(RPMLOG_ERR, _("line %d: Bad no%s number: %d\n"),
350  spec->lineNum, name, num);
351  return RPMRC_FAIL;
352  }
353 
354  p->flags |= RPMFILE_GHOST;
355 
356  }
357 
358  return RPMRC_OK;
359 }
360 
361 int addSource(Spec spec, /*@unused@*/ Package pkg,
362  const char *field, rpmTag tag)
363 {
364  struct Source *p;
365 #if defined(RPM_VENDOR_OPENPKG) /* regular-ordered-sources */
366  struct Source *p_last;
367 #endif
368  int flag = 0;
369  const char *name = NULL;
370  const char *mdir = NULL;
371  const char *fieldp = NULL;
372  char buf[BUFSIZ];
373  uint32_t num = 0;
374 
375  buf[0] = '\0';
376  switch (tag) {
377  case RPMTAG_SOURCE:
378  flag = RPMFILE_SOURCE;
379  name = "source";
380  fieldp = spec->line + strlen(name);
381  break;
382  case RPMTAG_PATCH:
383  flag = RPMFILE_PATCH;
384  name = "patch";
385  fieldp = spec->line + strlen(name);
386  break;
387  case RPMTAG_ICON:
388  flag = RPMFILE_ICON;
389  name = "icon";
390  fieldp = NULL;
391  break;
392  default:
393 assert(0);
394  /*@notreached@*/ break;
395  }
396 #if !defined(RPM_VENDOR_OPENPKG) /* splitted-source-directory */
397  mdir = getSourceDir(flag);
398 assert(mdir != NULL);
399 #endif
400 
401  /* Get the number */
402  if (fieldp != NULL) {
403  char * end = NULL;
404 
405  num = strtoul(fieldp, &end, 10);
406  SKIPSPACE(end);
407  if (*end != ':') {
408  rpmlog(RPMLOG_ERR, _("line %d: No ':' terminator: %s\n"),
409  spec->lineNum, spec->line);
410  return RPMRC_FAIL;
411  }
412  }
413 
414  /* Check whether tags of the same number haven't already been defined */
415  for (p = spec->sources; p != NULL; p = p->next) {
416  if ( p->num != num ) continue;
417  if ((tag == RPMTAG_SOURCE && p->flags == RPMFILE_SOURCE) ||
418  (tag == RPMTAG_PATCH && p->flags == RPMFILE_PATCH)) {
419  rpmlog(RPMLOG_ERR, _("%s %d defined multiple times\n"), name, num);
420  return RPMRC_FAIL;
421  }
422  }
423 
424  /* Create the entry and link it in */
425  p = xmalloc(sizeof(*p));
426  p->num = num;
427  p->fullSource = xstrdup(field);
428  p->flags = flag;
429  p->source = strrchr(p->fullSource, '/');
430  if (p->source)
431  p->source++;
432  else
433  p->source = p->fullSource;
434 
435 #if defined(RPM_VENDOR_OPENPKG) /* regular-ordered-sources */
436  p->next = NULL;
437  p_last = spec->sources;
438  while (p_last != NULL && p_last->next != NULL)
439  p_last = p_last->next;
440  if (p_last != NULL)
441  p_last->next = p;
442  else
443  spec->sources = p;
444 #else
445  p->next = spec->sources;
446  spec->sources = p;
447 #endif
448 
449  spec->numSources++;
450 
451  /* XXX FIXME: need to add ICON* macros. */
452 #if defined(RPM_VENDOR_OPENPKG) /* splitted-source-directory */
453  mdir = getSourceDir(flag, p->source);
454 #endif
455  if (tag != RPMTAG_ICON) {
456  const char *body = rpmGenPath(NULL, mdir, p->source);
457 
458  sprintf(buf, "%s%d",
459  (flag & RPMFILE_PATCH) ? "PATCH" : "SOURCE", num);
460  addMacro(spec->macros, buf, NULL, body, RMIL_SPEC);
461  sprintf(buf, "%sURL%d",
462  (flag & RPMFILE_PATCH) ? "PATCH" : "SOURCE", num);
463  addMacro(spec->macros, buf, NULL, p->fullSource, RMIL_SPEC);
464 #ifdef WITH_LUA
465  if (!spec->recursing) {
466  rpmlua lua = NULL; /* global state */
467  const char * what = (flag & RPMFILE_PATCH) ? "patches" : "sources";
468  rpmluav var = rpmluavNew();
469 
470  rpmluaPushTable(lua, what);
471  rpmluavSetListMode(var, 1);
472  rpmluavSetValue(var, RPMLUAV_STRING, body);
473  rpmluaSetVar(lua, var);
474 /*@-moduncon@*/
475  var = (rpmluav) rpmluavFree(var);
476 /*@=moduncon@*/
477  rpmluaPop(lua);
478  }
479 #endif
480  body = _free(body);
481  }
482 
483  return RPMRC_OK;
484 }
485 
488 static inline /*@only@*/ /*@null@*/ speclines newSl(void)
489  /*@*/
490 {
491  speclines sl = NULL;
492  if (specedit) {
493  sl = xmalloc(sizeof(*sl));
494  sl->sl_lines = NULL;
495  sl->sl_nalloc = 0;
496  sl->sl_nlines = 0;
497  }
498  return sl;
499 }
500 
503 static inline /*@null@*/ speclines freeSl(/*@only@*/ /*@null@*/ speclines sl)
504  /*@modifies sl @*/
505 {
506  int i;
507  if (sl == NULL) return NULL;
508  for (i = 0; i < sl->sl_nlines; i++)
509  /*@-unqualifiedtrans@*/
510  sl->sl_lines[i] = _free(sl->sl_lines[i]);
511  /*@=unqualifiedtrans@*/
512  sl->sl_lines = _free(sl->sl_lines);
513  return _free(sl);
514 }
515 
518 static inline /*@only@*/ /*@null@*/ spectags newSt(void)
519  /*@*/
520 {
521  spectags st = NULL;
522  if (specedit) {
523  st = xmalloc(sizeof(*st));
524  st->st_t = NULL;
525  st->st_nalloc = 0;
526  st->st_ntags = 0;
527  }
528  return st;
529 }
530 
533 static inline /*@null@*/ spectags freeSt(/*@only@*/ /*@null@*/ spectags st)
534  /*@modifies st @*/
535 {
536  int i;
537  if (st == NULL) return NULL;
538  for (i = 0; i < st->st_ntags; i++) {
539  spectag t = st->st_t + i;
540  t->t_lang = _free(t->t_lang);
541  t->t_msgid = _free(t->t_msgid);
542  }
543  st->st_t = _free(st->st_t);
544  return _free(st);
545 }
546 
547 static void specFini(void * _spec)
548  /*@modifies _spec @*/
549 {
550  Spec spec = _spec;
551  struct ReadLevelEntry *rl;
552 
553  if (spec == NULL) return; /* XXX assert? */
554 
555  spec->lbuf = _free(spec->lbuf);
556 
557  spec->sl = freeSl(spec->sl);
558  spec->st = freeSt(spec->st);
559 
560  spec->prep = rpmiobFree(spec->prep);
561  spec->build = rpmiobFree(spec->build);
562  spec->install = rpmiobFree(spec->install);
563  spec->check = rpmiobFree(spec->check);
564  spec->clean = rpmiobFree(spec->clean);
565  spec->foo = tagStoreFree(spec->foo, spec->nfoo);
566  spec->nfoo = 0;
567 
568  spec->buildSubdir = _free(spec->buildSubdir);
569  spec->rootURL = _free(spec->rootURL);
570  spec->specFile = _free(spec->specFile);
571 
572  closeSpec(spec);
573 
574  while (spec->readStack) {
575  rl = spec->readStack;
576  /*@-dependenttrans@*/
577  spec->readStack = rl->next;
578  /*@=dependenttrans@*/
579  rl->next = NULL;
580  rl = _free(rl);
581  }
582 
583  spec->sourceRpmName = _free(spec->sourceRpmName);
584  spec->sourcePkgId = _free(spec->sourcePkgId);
585  spec->sourceHeader = headerFree(spec->sourceHeader);
586 
587  if (spec->fi != NULL) {
588  rpmfi fi = spec->fi;
589  spec->fi = NULL;
590  fi = rpmfiFree(fi);
591  }
592 
593  if (!spec->recursing) {
594  if (spec->BASpecs != NULL)
595  while (spec->BACount--) {
596  /*@-unqualifiedtrans@*/
597  spec->BASpecs[spec->BACount] =
598  freeSpec(spec->BASpecs[spec->BACount]);
599  /*@=unqualifiedtrans@*/
600  }
601  /*@-compdef@*/
602  spec->BASpecs = _free(spec->BASpecs);
603  /*@=compdef@*/
604  }
605  spec->BANames = _free(spec->BANames);
606 
607  spec->passPhrase = _free(spec->passPhrase);
608  spec->cookie = _free(spec->cookie);
609 
610 #ifdef WITH_LUA
611  { rpmlua lua = NULL; /* global state */
612  rpmluaDelVar(lua, "patches");
613  rpmluaDelVar(lua, "sources");
614  }
615 #endif
616 
617  spec->sources = freeSources(spec->sources);
618 
619  spec->dig = pgpDigFree(spec->dig);
620  spec->packages = freePackages(spec->packages);
621 
622 }
623 
624 /*@unchecked@*/ /*@only@*/ /*@null@*/
626 
628 {
629  Spec spec;
630 
631  if (_specPool == NULL) {
632  _specPool = rpmioNewPool("spec", sizeof(*spec), -1, _spec_debug,
633  NULL, NULL, specFini);
634  pool = _specPool;
635  }
636  spec = (Spec) rpmioGetPool(pool, sizeof(*spec));
637  memset(((char *)spec)+sizeof(spec->_item), 0, sizeof(*spec)-sizeof(spec->_item));
638  return spec;
639 }
640 
642 {
643  static const char _spec_line_buffer_size[] =
644  "%{?_spec_line_buffer_size}%{!?_spec_line_buffer_size:100000}";
645  Spec spec = specGetPool(_specPool);
646 
647  spec->specFile = NULL;
648 
649  spec->sl = newSl();
650  spec->st = newSt();
651 
652  spec->fileStack = NULL;
653  spec->lbuf_len = (size_t)rpmExpandNumeric(_spec_line_buffer_size);
654  spec->lbuf = (char *)xmalloc(spec->lbuf_len);
655  spec->lbuf[0] = '\0';
656  spec->line = spec->lbuf;
657  spec->nextline = NULL;
658  spec->nextpeekc = '\0';
659  spec->lineNum = 0;
660  spec->readStack = xmalloc(sizeof(*spec->readStack));
661  spec->readStack->next = NULL;
662  spec->readStack->reading = 1;
663 
664  spec->rootURL = NULL;
665 
666  memset(&spec->sstates, 0, sizeof(spec->sstates));
667  memset(&spec->smetrics, 0, sizeof(spec->smetrics));
668 
669  spec->prep = NULL;
670  spec->build = NULL;
671  spec->install = NULL;
672  spec->check = NULL;
673  spec->clean = NULL;
674  spec->foo = NULL;
675  spec->nfoo = 0;
676 
677  spec->dig = NULL;
678 
679  spec->sources = NULL;
680  spec->packages = NULL;
681  spec->noSource = 0;
682  spec->numSources = 0;
683 
684  spec->sourceRpmName = NULL;
685  spec->sourcePkgId = NULL;
686  spec->sourceHeader = headerNew();
687  spec->fi = NULL;
688 
689  spec->buildSubdir = NULL;
690 
691  spec->passPhrase = NULL;
692  spec->timeCheck = 0;
693  spec->cookie = NULL;
694 
695  spec->BANames = NULL;
696  spec->BACount = 0;
697  spec->recursing = 0;
698  spec->toplevel = 1;
699  spec->BASpecs = NULL;
700 
701  spec->force = 0;
702  spec->anyarch = 0;
703 
704 /*@i@*/ spec->macros = rpmGlobalMacroContext;
705 
706  spec->_parseRCPOT = parseRCPOT; /* XXX hack around backward linkage. */
707 
708  return (Spec)rpmioLinkPoolItem((rpmioItem)spec, __FUNCTION__, __FILE__, __LINE__);
709 }
710 
711 /*@only@*/
713 {
714  struct OpenFileInfo *ofi;
715 
716  ofi = xmalloc(sizeof(*ofi));
717  ofi->fd = NULL;
718  ofi->fileName = NULL;
719  ofi->lineNum = 0;
720  ofi->readBuf[0] = '\0';
721  ofi->readPtr = NULL;
722  ofi->next = NULL;
723 
724  return ofi;
725 }
726 
731 static void
733  /*@globals fileSystem, internalState @*/
734  /*@modifies spec->sl->sl_lines[], spec->packages->header,
735  fileSystem, internalState @*/
736 {
737  HE_t he = (HE_t) memset(alloca(sizeof(*he)), 0, sizeof(*he));
738  Header h;
739  speclines sl = spec->sl;
740  spectags st = spec->st;
741  const char * msgstr = NULL;
742  int i, j;
743  int xx;
744 
745  if (sl == NULL || st == NULL)
746  return;
747 
748  for (i = 0; i < st->st_ntags; i++) {
749  spectag t = st->st_t + i;
750  const char * tn = tagName(t->t_tag);
751  const char * errstr;
752  char fmt[1024];
753 
754  fmt[0] = '\0';
755  if (t->t_msgid == NULL)
756  h = spec->packages->header;
757  else {
758  Package pkg;
759  char *fe;
760 
761  strcpy(fmt, t->t_msgid);
762  for (fe = fmt; *fe && *fe != '('; fe++)
763  {} ;
764  if (*fe == '(') *fe = '\0';
765  h = NULL;
766  for (pkg = spec->packages; pkg != NULL; pkg = pkg->next) {
767  h = pkg->header;
768  he->tag = RPMTAG_NAME;
769  xx = headerGet(h, he, 0);
770  if (!strcmp(he->p.str, fmt)) {
771  he->p.ptr = _free(he->p.ptr);
772  /*@innerbreak@*/ break;
773  }
774  he->p.ptr = _free(he->p.ptr);
775  }
776  if (pkg == NULL || h == NULL)
777  h = spec->packages->header;
778  }
779 
780  if (h == NULL)
781  continue;
782 
783  fmt[0] = '\0';
784  (void) stpcpy( stpcpy( stpcpy( fmt, "%{"), tn), "}");
785  msgstr = _free(msgstr);
786 
787  /* XXX this should use queryHeader(), but prints out tn as well. */
788  msgstr = headerSprintf(h, fmt, NULL, rpmHeaderFormats, &errstr);
789  if (msgstr == NULL) {
790  rpmlog(RPMLOG_ERR, _("can't query %s: %s\n"), tn, errstr);
791  return;
792  }
793 
794  switch(t->t_tag) {
795  case RPMTAG_SUMMARY:
796  case RPMTAG_GROUP:
797  /*@-unqualifiedtrans@*/
798  sl->sl_lines[t->t_startx] = _free(sl->sl_lines[t->t_startx]);
799  /*@=unqualifiedtrans@*/
800  if (t->t_lang && strcmp(t->t_lang, RPMBUILD_DEFAULT_LANG))
801  continue;
802  { char *buf = xmalloc(strlen(tn) + sizeof(": ") + strlen(msgstr));
803  (void) stpcpy( stpcpy( stpcpy(buf, tn), ": "), msgstr);
804  sl->sl_lines[t->t_startx] = buf;
805  }
806  /*@switchbreak@*/ break;
807  case RPMTAG_DESCRIPTION:
808  for (j = 1; j < t->t_nlines; j++) {
809  if (*sl->sl_lines[t->t_startx + j] == '%')
810  /*@innercontinue@*/ continue;
811  /*@-unqualifiedtrans@*/
812  sl->sl_lines[t->t_startx + j] =
813  _free(sl->sl_lines[t->t_startx + j]);
814  /*@=unqualifiedtrans@*/
815  }
816  if (t->t_lang && strcmp(t->t_lang, RPMBUILD_DEFAULT_LANG)) {
817  sl->sl_lines[t->t_startx] = _free(sl->sl_lines[t->t_startx]);
818  continue;
819  }
820  sl->sl_lines[t->t_startx + 1] = xstrdup(msgstr);
821  if (t->t_nlines > 2)
822  sl->sl_lines[t->t_startx + 2] = xstrdup("\n\n");
823  /*@switchbreak@*/ break;
824  }
825  }
826  msgstr = _free(msgstr);
827 
828  for (i = 0; i < sl->sl_nlines; i++) {
829  const char * s = sl->sl_lines[i];
830  if (s == NULL)
831  continue;
832  printf("%s", s);
833  if (strchr(s, '\n') == NULL && s[strlen(s)-1] != '\n')
834  printf("\n");
835  }
836 }
837 
847  rpmTag progTag, rpmTag scriptTag, rpmiob iob)
848  /*@modifies h @*/
849 {
850  HE_t he = (HE_t) memset(alloca(sizeof(*he)), 0, sizeof(*he));
851  int xx;
852 
853  if (progTag !=(rpmTag) 0) {
854  static const char prog[] = "/bin/sh"; /* XXX FIXME */
855  he->tag = progTag;
856  he->t = RPM_STRING_TYPE;
857  he->p.str = prog;
858  he->c = 1;
859  xx = headerPut(h, he, 0);
860  }
861 
862  if (scriptTag != (rpmTag)0 && iob != NULL) {
863  he->tag = scriptTag;
864  he->t = RPM_STRING_TYPE;
865  he->p.str = rpmiobStr(iob);
866  he->c = 1;
867  xx = headerPut(h, he, 0);
868  }
869  return 0;
870 }
871 
878  /*@modifies spec->sourceHeader @*/
879 {
880  int xx;
881 
882  if (spec->prep != NULL)
884  tagValue("Buildprepprog"), tagValue("Buildprep"), spec->prep);
885  if (spec->build != NULL)
887  tagValue("Buildbuildprog"), tagValue("Buildbuild"), spec->build);
888  if (spec->install != NULL)
890  tagValue("Buildinstallprog"), tagValue("Buildinstall"), spec->install);
891  if (spec->check != NULL)
893  tagValue("Buildcheckprog"), tagValue("Buildcheck"), spec->check);
894  if (spec->clean != NULL)
896  tagValue("Buildcleanprog"), tagValue("Buildclean"), spec->clean);
897 
898  return 0;
899 }
900 
909 static int _specQuery(rpmts ts, QVA_t qva, const char *specName,
910  /*@null@*/ const char *target)
911  /*@globals rpmGlobalMacroContext, h_errno, fileSystem, internalState @*/
912  /*@modifies rpmGlobalMacroContext, fileSystem, internalState @*/
913 {
914  Spec spec = NULL;
915  Package pkg;
916  int res = 1; /* assume error */
917  int anyarch = (target == NULL) ? 1 : 0;
918  char * passPhrase = "";
919  int recursing = 0;
920  char *cookie = NULL;
921  int verify = 0;
922  int xx;
923 
924  /*@-mods@*/ /* FIX: make spec abstract */
925  if (parseSpec(ts, specName, "/", recursing, passPhrase,
926  cookie, anyarch, 1, verify)
927  || (spec = rpmtsSetSpec(ts, NULL)) == NULL)
928  {
930  _("query of specfile %s failed, can't parse\n"),
931  specName);
932  goto exit;
933  }
934  /*@=mods@*/
935 
936  res = 0;
937  if (specedit) {
938  printNewSpecfile(spec);
939  goto exit;
940  }
941 
942  switch (qva->qva_source) {
943  case RPMQV_SPECSRPM:
944  xx = initSourceHeader(spec, NULL);
945  xx = initSourceHeaderScriptlets(spec);
946  xx = qva->qva_showPackage(qva, ts, spec->sourceHeader);
947  break;
948  default:
949  case RPMQV_SPECFILE:
950  for (pkg = spec->packages; pkg != NULL; pkg = pkg->next) {
951  /* If no target was specified, display all packages.
952  * Packages with empty file lists are not produced.
953  */
954  /* XXX DIEDIEDIE: this logic looks flawed. */
955  if (target == NULL || pkg->fileList != NULL)
956  xx = qva->qva_showPackage(qva, ts, pkg->header);
957  }
958  break;
959  }
960 
961 exit:
962  spec = freeSpec(spec);
963  return res;
964 }
965 
966 int rpmspecQuery(rpmts ts, QVA_t qva, const char * arg)
967 {
968  int res = 1;
969  const char * targets = rpmcliTargets;
970  char *target;
971  const char * t;
972  const char * te;
973  int nqueries = 0;
974 
975  if (qva->qva_showPackage == NULL)
976  goto exit;
977 
978  if (targets == NULL) {
979  res = _specQuery(ts, qva, arg, NULL);
980  nqueries++;
981  goto exit;
982  }
983 
985  _("Query specfile for platform(s): %s\n"), targets);
986  for (t = targets; *t != '\0'; t = te) {
987  /* Parse out next target platform. */
988  if ((te = strchr(t, ',')) == NULL)
989  te = t + strlen(t);
990  target = alloca(te-t+1);
991  strncpy(target, t, (te-t));
992  target[te-t] = '\0';
993  if (*te != '\0')
994  te++;
995 
996  /* Query spec for this target platform. */
997  rpmlog(RPMLOG_DEBUG, _(" target platform: %s\n"), target);
998  /* Read in configuration for target. */
999  if (t != targets) {
1000  rpmFreeMacros(NULL);
1001  rpmFreeRpmrc();
1002  (void) rpmReadConfigFiles(NULL, target);
1003  }
1004  res = _specQuery(ts, qva, arg, target);
1005  nqueries++;
1006  if (res) break;
1007  }
1008 
1009 exit:
1010  /* Restore original configuration. */
1011  if (nqueries > 1) {
1012  t = targets;
1013  if ((te = strchr(t, ',')) == NULL)
1014  te = t + strlen(t);
1015  target = alloca(te-t+1);
1016  strncpy(target, t, (te-t));
1017  target[te-t] = '\0';
1018  if (*te != '\0')
1019  te++;
1020  rpmFreeMacros(NULL);
1021  rpmFreeRpmrc();
1022  (void) rpmReadConfigFiles(NULL, target);
1023  }
1024  return res;
1025 }