spec.c
Go to the documentation of this file.
#include "system.h"
#include <rpmio.h>
#include <rpmiotypes.h>
#include <rpmlog.h>
#include "buildio.h"
#include "rpmds.h"
#include "rpmfi.h"
#include "rpmts.h"
#include "rpmlua.h"
#include "debug.h"
/*@-redecl@*/
extern int specedit;
/*@=redecl@*/
#define SKIPWHITE(_x) {while(*(_x) && (xisspace(*_x) || *(_x) == ',')) (_x)++;}
#define SKIPNONWHITE(_x){while(*(_x) &&!(xisspace(*_x) || *(_x) == ',')) (_x)++;}
/*@access rpmluav @*/
static inline
/*@null@*/ struct TriggerFileEntry * freeTriggerFiles(/*@only@*/ /*@null@*/ struct TriggerFileEntry * p)
/*@modifies p @*/
{
struct TriggerFileEntry *o, *q = p;
while (q != NULL) {
o = q;
q = q->next;
o->fileName = _free(o->fileName);
o->script = _free(o->script);
o->prog = _free(o->prog);
o = _free(o);
}
return NULL;
}
static inline
/*@null@*/ struct Source * freeSources(/*@only@*/ /*@null@*/ struct Source * s)
/*@modifies s @*/
{
struct Source *r, *t = s;
while (t != NULL) {
r = t;
t = t->next;
r->fullSource = _free(r->fullSource);
r = _free(r);
}
return NULL;
}
rpmRC lookupPackage(Spec spec, const char *name, int flag, /*@out@*/Package *pkg)
{
HE_t he = memset(alloca(sizeof(*he)), 0, sizeof(*he));
char *NV = NULL;
char *N = NULL;
char *V = NULL;
Package p, lastp;
int xx;
/* "main" package */
if (name == NULL) {
if (pkg)
*pkg = spec->packages;
return RPMRC_OK;
}
/* Construct package name */
if (flag == PART_SUBNAME) {
he->tag = RPMTAG_NAME;
xx = headerGet(spec->packages->header, he, 0);
assert(xx != 0 && he->p.str != NULL);
N = rpmExpand(he->p.str, "-", name, NULL);
he->p.ptr = _free(he->p.ptr);
} else {
N = xstrdup(name);
if ((V = strrchr(N, '-')) != NULL) {
NV = xstrdup(N);
*V++ = '\0';
}
}
/* Match last package with same N or same {N,V} */
lastp = NULL;
for (p = spec->packages; p != NULL; p = p->next) {
char *nv, *n, *v;
nv = n = v = NULL;
he->tag = RPMTAG_NAME;
xx = headerGet(p->header, he, 0);
if (xx && he->p.str != NULL) {
n = (char *) he->p.str;
he->p.str = NULL;
}
if (NV != NULL) {
he->tag = RPMTAG_VERSION;
xx = headerGet(p->header, he, 0);
if (xx && he->p.str != NULL) {
v = (char *) he->p.str;
he->p.str = NULL;
nv = rpmExpand(n, "-", v, NULL);
}
}
if (NV == NULL) {
if (!strcmp(N, n))
lastp = p;
} else {
if (!strcmp(NV, nv) || !strcmp(NV, n)
|| (!strcmp(N, n) && (V == NULL || !strcmp(V, v))))
lastp = p;
}
/*@-usereleased@*/
n = _free(n);
v = _free(v);
nv = _free(nv);
/*@=usereleased@*/
}
if (pkg)
/*@-dependenttrans@*/ *pkg = lastp; /*@=dependenttrans@*/
NV = _free(NV);
N = _free(N);
return ((lastp == NULL) ? RPMRC_FAIL : RPMRC_OK);
}
Package newPackage(/*@unused@*/ Spec spec)
{
Package p;
p = xcalloc(1, sizeof(*p));
p->header = headerNew();
p->ds = NULL;
p->autoProv = ((_rpmbuildFlags & 0x1) != 0);
p->autoReq = ((_rpmbuildFlags & 0x2) != 0);
#if 0
p->reqProv = NULL;
p->triggers = NULL;
p->triggerScripts = NULL;
#endif
p->triggerFiles = NULL;
p->fileFile = NULL;
p->fileList = NULL;
p->cpioList = NULL;
p->preInFile = NULL;
p->postInFile = NULL;
p->preUnFile = NULL;
p->postUnFile = NULL;
p->verifyFile = NULL;
p->sanityCheckFile = NULL;
p->specialDoc = NULL;
p->next = NULL;
return p;
}
Package freePackage(Package pkg)
{
if (pkg == NULL) return NULL;
pkg->preInFile = _free(pkg->preInFile);
pkg->postInFile = _free(pkg->postInFile);
pkg->preUnFile = _free(pkg->preUnFile);
pkg->postUnFile = _free(pkg->postUnFile);
pkg->verifyFile = _free(pkg->verifyFile);
pkg->sanityCheckFile = _free(pkg->sanityCheckFile);
(void)headerFree(pkg->header);
pkg->header = NULL;
(void)rpmdsFree(pkg->ds);
pkg->ds = NULL;
pkg->fileList = rpmiobFree(pkg->fileList);
pkg->fileFile = _free(pkg->fileFile);
if (pkg->cpioList != NULL) {
rpmfi fi = pkg->cpioList;
pkg->cpioList = NULL;
fi = rpmfiFree(fi);
}
pkg->specialDoc = rpmiobFree(pkg->specialDoc);
pkg->triggerFiles = freeTriggerFiles(pkg->triggerFiles);
pkg = _free(pkg);
return NULL;
}
Package freePackages(Package packages)
{
Package p;
while ((p = packages) != NULL) {
packages = p->next;
p->next = NULL;
p = freePackage(p);
}
return NULL;
}
static inline /*@owned@*/ struct Source *findSource(Spec spec, rpmuint32_t num, int flag)
/*@*/
{
struct Source *p;
for (p = spec->sources; p != NULL; p = p->next)
if ((num == p->num) && (p->flags & flag)) return p;
return NULL;
}
int SpecSourceCount(Spec spec)
{
return spec->numSources;
}
SpecSource getSource(Spec spec, int num)
/* @ */
{
struct Source *p = spec->sources;
int i;
for (i = 0; i < num; i++)
if ((p = p->next) == NULL) return NULL;
/*@-usereleased@*/
return p;
/*@=usereleased@*/
}
const char * specSourceName(SpecSource source)
{
return source->source;
}
const char * specFullSourceName(SpecSource source)
{
return source->fullSource;
}
int specSourceNum(SpecSource source)
{
return source->num;
}
int specSourceFlags(SpecSource source)
{
return source->flags;
}
int parseNoSource(Spec spec, const char * field, rpmTag tag)
{
const char *f, *fe;
const char *name;
rpmuint32_t num, flag;
if (tag == RPMTAG_NOSOURCE) {
flag = RPMFILE_SOURCE;
name = "source";
} else {
flag = RPMFILE_PATCH;
name = "patch";
}
fe = field;
for (f = fe; *f != '\0'; f = fe) {
struct Source *p;
SKIPWHITE(f);
if (*f == '\0')
break;
fe = f;
SKIPNONWHITE(fe);
if (*fe != '\0') fe++;
if (parseNum(f, &num)) {
rpmlog(RPMLOG_ERR, _("line %d: Bad number: %s\n"),
spec->lineNum, f);
return RPMRC_FAIL;
}
if (! (p = findSource(spec, num, flag))) {
rpmlog(RPMLOG_ERR, _("line %d: Bad no%s number: %d\n"),
spec->lineNum, name, num);
return RPMRC_FAIL;
}
p->flags |= RPMFILE_GHOST;
}
return RPMRC_OK;
}
int addSource(Spec spec, /*@unused@*/ Package pkg,
const char *field, rpmTag tag)
{
struct Source *p;
#if defined(RPM_VENDOR_OPENPKG) /* regular-ordered-sources */
struct Source *p_last;
#endif
int flag = 0;
const char *name = NULL;
const char *mdir = NULL;
char *nump;
const char *fieldp = NULL;
char buf[BUFSIZ];
rpmuint32_t num = 0;
buf[0] = '\0';
switch (tag) {
case RPMTAG_SOURCE:
flag = RPMFILE_SOURCE;
name = "source";
fieldp = spec->line + (sizeof("Source")-1);
break;
case RPMTAG_PATCH:
flag = RPMFILE_PATCH;
name = "patch";
fieldp = spec->line + (sizeof("Patch")-1);
break;
case RPMTAG_ICON:
flag = RPMFILE_ICON;
name = "icon";
fieldp = NULL;
break;
default:
assert(0);
/*@notreached@*/ break;
}
#if !defined(RPM_VENDOR_OPENPKG) /* splitted-source-directory */
mdir = getSourceDir(flag);
assert(mdir != NULL);
#endif
/* Get the number */
if (fieldp != NULL) {
/* We already know that a ':' exists, and that there */
/* are no spaces before it. */
/* This also now allows for spaces and tabs between */
/* the number and the ':' */
nump = buf;
while ((*fieldp != ':') && (*fieldp != ' ') && (*fieldp != '\t'))
*nump++ = *fieldp++;
*nump = '\0';
nump = buf;
SKIPSPACE(nump);
if (nump == NULL || *nump == '\0')
num = 0;
else if (parseNum(buf, &num)) {
rpmlog(RPMLOG_ERR, _("line %d: Bad %s number: %s\n"),
spec->lineNum, name, spec->line);
return RPMRC_FAIL;
}
}
/* Check whether tags of the same number haven't already been defined */
for (p = spec->sources; p != NULL; p = p->next) {
if ( p->num != num ) continue;
if ((tag == RPMTAG_SOURCE && p->flags == RPMFILE_SOURCE) ||
(tag == RPMTAG_PATCH && p->flags == RPMFILE_PATCH)) {
rpmlog(RPMLOG_ERR, _("%s %d defined multiple times\n"), name, num);
return RPMRC_FAIL;
}
}
/* Create the entry and link it in */
p = xmalloc(sizeof(*p));
p->num = num;
p->fullSource = xstrdup(field);
p->flags = flag;
p->source = strrchr(p->fullSource, '/');
if (p->source)
p->source++;
else
p->source = p->fullSource;
#if defined(RPM_VENDOR_OPENPKG) /* regular-ordered-sources */
p->next = NULL;
p_last = spec->sources;
while (p_last != NULL && p_last->next != NULL)
p_last = p_last->next;
if (p_last != NULL)
p_last->next = p;
else
spec->sources = p;
#else
p->next = spec->sources;
spec->sources = p;
#endif
spec->numSources++;
/* XXX FIXME: need to add ICON* macros. */
#if defined(RPM_VENDOR_OPENPKG) /* splitted-source-directory */
mdir = getSourceDir(flag, p->source);
#endif
if (tag != RPMTAG_ICON) {
const char *body = rpmGenPath(NULL, mdir, p->source);
sprintf(buf, "%s%d",
(flag & RPMFILE_PATCH) ? "PATCH" : "SOURCE", num);
addMacro(spec->macros, buf, NULL, body, RMIL_SPEC);
sprintf(buf, "%sURL%d",
(flag & RPMFILE_PATCH) ? "PATCH" : "SOURCE", num);
addMacro(spec->macros, buf, NULL, p->fullSource, RMIL_SPEC);
#ifdef WITH_LUA
if (!spec->recursing) {
rpmlua lua = NULL; /* global state */
const char * what = (flag & RPMFILE_PATCH) ? "patches" : "sources";
rpmluav var = rpmluavNew();
rpmluaPushTable(lua, what);
rpmluavSetListMode(var, 1);
rpmluavSetValue(var, RPMLUAV_STRING, body);
rpmluaSetVar(lua, var);
/*@-moduncon@*/
var = (rpmluav) rpmluavFree(var);
/*@=moduncon@*/
rpmluaPop(lua);
}
#endif
body = _free(body);
}
return RPMRC_OK;
}
static inline /*@only@*/ /*@null@*/ speclines newSl(void)
/*@*/
{
speclines sl = NULL;
if (specedit) {
sl = xmalloc(sizeof(*sl));
sl->sl_lines = NULL;
sl->sl_nalloc = 0;
sl->sl_nlines = 0;
}
return sl;
}
static inline /*@null@*/ speclines freeSl(/*@only@*/ /*@null@*/ speclines sl)
/*@modifies sl @*/
{
int i;
if (sl == NULL) return NULL;
for (i = 0; i < sl->sl_nlines; i++)
/*@-unqualifiedtrans@*/
sl->sl_lines[i] = _free(sl->sl_lines[i]);
/*@=unqualifiedtrans@*/
sl->sl_lines = _free(sl->sl_lines);
return _free(sl);
}
static inline /*@only@*/ /*@null@*/ spectags newSt(void)
/*@*/
{
spectags st = NULL;
if (specedit) {
st = xmalloc(sizeof(*st));
st->st_t = NULL;
st->st_nalloc = 0;
st->st_ntags = 0;
}
return st;
}
static inline /*@null@*/ spectags freeSt(/*@only@*/ /*@null@*/ spectags st)
/*@modifies st @*/
{
int i;
if (st == NULL) return NULL;
for (i = 0; i < st->st_ntags; i++) {
spectag t = st->st_t + i;
t->t_lang = _free(t->t_lang);
t->t_msgid = _free(t->t_msgid);
}
st->st_t = _free(st->st_t);
return _free(st);
}
Spec newSpec(void)
{
Spec spec = xcalloc(1, sizeof(*spec));
spec->specFile = NULL;
spec->sl = newSl();
spec->st = newSt();
spec->fileStack = NULL;
spec->lbuf_len = (size_t)rpmExpandNumeric("%{?_spec_line_buffer_size}%{!?_spec_line_buffer_size:100000}");
spec->lbuf = (char *)xcalloc(1, spec->lbuf_len);
spec->line = spec->lbuf;
spec->nextline = NULL;
spec->nextpeekc = '\0';
spec->lineNum = 0;
spec->readStack = xcalloc(1, sizeof(*spec->readStack));
spec->readStack->next = NULL;
spec->readStack->reading = 1;
spec->rootURL = NULL;
spec->prep = NULL;
spec->build = NULL;
spec->install = NULL;
spec->check = NULL;
spec->clean = NULL;
spec->foo = NULL;
spec->nfoo = 0;
spec->sources = NULL;
spec->packages = NULL;
spec->noSource = 0;
spec->numSources = 0;
spec->sourceRpmName = NULL;
spec->sourcePkgId = NULL;
spec->sourceHeader = headerNew();
spec->sourceCpioList = NULL;
spec->buildSubdir = NULL;
spec->passPhrase = NULL;
spec->timeCheck = 0;
spec->cookie = NULL;
spec->BANames = NULL;
spec->BACount = 0;
spec->recursing = 0;
spec->toplevel = 1;
spec->BASpecs = NULL;
spec->force = 0;
spec->anyarch = 0;
/*@i@*/ spec->macros = rpmGlobalMacroContext;
spec->_parseRCPOT = parseRCPOT; /* XXX hack around backward linkage. */
return spec;
}
Spec freeSpec(Spec spec)
{
struct ReadLevelEntry *rl;
if (spec == NULL) return NULL;
spec->lbuf = _free(spec->lbuf);
spec->sl = freeSl(spec->sl);
spec->st = freeSt(spec->st);
spec->prep = rpmiobFree(spec->prep);
spec->build = rpmiobFree(spec->build);
spec->install = rpmiobFree(spec->install);
spec->check = rpmiobFree(spec->check);
spec->clean = rpmiobFree(spec->clean);
spec->foo = tagStoreFree(spec->foo, spec->nfoo);
spec->nfoo = 0;
spec->buildSubdir = _free(spec->buildSubdir);
spec->rootURL = _free(spec->rootURL);
spec->specFile = _free(spec->specFile);
closeSpec(spec);
while (spec->readStack) {
rl = spec->readStack;
/*@-dependenttrans@*/
spec->readStack = rl->next;
/*@=dependenttrans@*/
rl->next = NULL;
rl = _free(rl);
}
spec->sourceRpmName = _free(spec->sourceRpmName);
spec->sourcePkgId = _free(spec->sourcePkgId);
spec->sourceHeader = headerFree(spec->sourceHeader);
if (spec->sourceCpioList != NULL) {
rpmfi fi = spec->sourceCpioList;
spec->sourceCpioList = NULL;
fi = rpmfiFree(fi);
}
if (!spec->recursing) {
if (spec->BASpecs != NULL)
while (spec->BACount--) {
/*@-unqualifiedtrans@*/
spec->BASpecs[spec->BACount] =
freeSpec(spec->BASpecs[spec->BACount]);
/*@=unqualifiedtrans@*/
}
/*@-compdef@*/
spec->BASpecs = _free(spec->BASpecs);
/*@=compdef@*/
}
spec->BANames = _free(spec->BANames);
spec->passPhrase = _free(spec->passPhrase);
spec->cookie = _free(spec->cookie);
#ifdef WITH_LUA
{ rpmlua lua = NULL; /* global state */
rpmluaDelVar(lua, "patches");
rpmluaDelVar(lua, "sources");
}
#endif
spec->sources = freeSources(spec->sources);
spec->packages = freePackages(spec->packages);
spec = _free(spec);
return spec;
}
/*@only@*/
struct OpenFileInfo * newOpenFileInfo(void)
{
struct OpenFileInfo *ofi;
ofi = xmalloc(sizeof(*ofi));
ofi->fd = NULL;
ofi->fileName = NULL;
ofi->lineNum = 0;
ofi->readBuf[0] = '\0';
ofi->readPtr = NULL;
ofi->next = NULL;
return ofi;
}
static void
printNewSpecfile(Spec spec)
/*@globals fileSystem, internalState @*/
/*@modifies spec->sl->sl_lines[], spec->packages->header,
fileSystem, internalState @*/
{
HE_t he = memset(alloca(sizeof(*he)), 0, sizeof(*he));
Header h;
speclines sl = spec->sl;
spectags st = spec->st;
const char * msgstr = NULL;
int i, j;
int xx;
if (sl == NULL || st == NULL)
return;
for (i = 0; i < st->st_ntags; i++) {
spectag t = st->st_t + i;
const char * tn = tagName(t->t_tag);
const char * errstr;
char fmt[1024];
fmt[0] = '\0';
if (t->t_msgid == NULL)
h = spec->packages->header;
else {
Package pkg;
char *fe;
strcpy(fmt, t->t_msgid);
for (fe = fmt; *fe && *fe != '('; fe++)
{} ;
if (*fe == '(') *fe = '\0';
h = NULL;
for (pkg = spec->packages; pkg != NULL; pkg = pkg->next) {
h = pkg->header;
he->tag = RPMTAG_NAME;
xx = headerGet(h, he, 0);
if (!strcmp(he->p.str, fmt)) {
he->p.ptr = _free(he->p.ptr);
/*@innerbreak@*/ break;
}
he->p.ptr = _free(he->p.ptr);
}
if (pkg == NULL || h == NULL)
h = spec->packages->header;
}
if (h == NULL)
continue;
fmt[0] = '\0';
(void) stpcpy( stpcpy( stpcpy( fmt, "%{"), tn), "}");
msgstr = _free(msgstr);
/* XXX this should use queryHeader(), but prints out tn as well. */
msgstr = headerSprintf(h, fmt, NULL, rpmHeaderFormats, &errstr);
if (msgstr == NULL) {
rpmlog(RPMLOG_ERR, _("can't query %s: %s\n"), tn, errstr);
return;
}
switch(t->t_tag) {
case RPMTAG_SUMMARY:
case RPMTAG_GROUP:
/*@-unqualifiedtrans@*/
sl->sl_lines[t->t_startx] = _free(sl->sl_lines[t->t_startx]);
/*@=unqualifiedtrans@*/
if (t->t_lang && strcmp(t->t_lang, RPMBUILD_DEFAULT_LANG))
continue;
{ char *buf = xmalloc(strlen(tn) + sizeof(": ") + strlen(msgstr));
(void) stpcpy( stpcpy( stpcpy(buf, tn), ": "), msgstr);
sl->sl_lines[t->t_startx] = buf;
}
/*@switchbreak@*/ break;
case RPMTAG_DESCRIPTION:
for (j = 1; j < t->t_nlines; j++) {
if (*sl->sl_lines[t->t_startx + j] == '%')
/*@innercontinue@*/ continue;
/*@-unqualifiedtrans@*/
sl->sl_lines[t->t_startx + j] =
_free(sl->sl_lines[t->t_startx + j]);
/*@=unqualifiedtrans@*/
}
if (t->t_lang && strcmp(t->t_lang, RPMBUILD_DEFAULT_LANG)) {
sl->sl_lines[t->t_startx] = _free(sl->sl_lines[t->t_startx]);
continue;
}
sl->sl_lines[t->t_startx + 1] = xstrdup(msgstr);
if (t->t_nlines > 2)
sl->sl_lines[t->t_startx + 2] = xstrdup("\n\n");
/*@switchbreak@*/ break;
}
}
msgstr = _free(msgstr);
for (i = 0; i < sl->sl_nlines; i++) {
const char * s = sl->sl_lines[i];
if (s == NULL)
continue;
printf("%s", s);
if (strchr(s, '\n') == NULL && s[strlen(s)-1] != '\n')
printf("\n");
}
}
static int initSourceHeaderScriptlet(Header h,
rpmTag progTag, rpmTag scriptTag, rpmiob iob)
/*@modifies h @*/
{
HE_t he = memset(alloca(sizeof(*he)), 0, sizeof(*he));
int xx;
if (progTag !=(rpmTag) 0) {
static const char prog[] = "/bin/sh"; /* XXX FIXME */
he->tag = progTag;
he->t = RPM_STRING_TYPE;
he->p.str = prog;
he->c = 1;
xx = headerPut(h, he, 0);
}
if (scriptTag != (rpmTag)0 && iob != NULL) {
he->tag = scriptTag;
he->t = RPM_STRING_TYPE;
he->p.str = rpmiobStr(iob);
he->c = 1;
xx = headerPut(h, he, 0);
}
return 0;
}
static int initSourceHeaderScriptlets(Spec spec)
/*@modifies spec->sourceHeader @*/
{
int xx;
if (spec->prep != NULL)
xx = initSourceHeaderScriptlet(spec->sourceHeader,
tagValue("Buildprepprog"), tagValue("Buildprep"), spec->prep);
if (spec->build != NULL)
xx = initSourceHeaderScriptlet(spec->sourceHeader,
tagValue("Buildbuildprog"), tagValue("Buildbuild"), spec->build);
if (spec->install != NULL)
xx = initSourceHeaderScriptlet(spec->sourceHeader,
tagValue("Buildinstallprog"), tagValue("Buildinstall"), spec->install);
if (spec->check != NULL)
xx = initSourceHeaderScriptlet(spec->sourceHeader,
tagValue("Buildcheckprog"), tagValue("Buildcheck"), spec->check);
if (spec->clean != NULL)
xx = initSourceHeaderScriptlet(spec->sourceHeader,
tagValue("Buildcleanprog"), tagValue("Buildclean"), spec->clean);
return 0;
}
static int _specQuery(rpmts ts, QVA_t qva, const char *specName,
/*@null@*/ const char *target)
/*@globals rpmGlobalMacroContext, h_errno, fileSystem, internalState @*/
/*@modifies rpmGlobalMacroContext, fileSystem, internalState @*/
{
Spec spec = NULL;
Package pkg;
int res = 1; /* assume error */
int anyarch = (target == NULL) ? 1 : 0;
char * passPhrase = "";
int recursing = 0;
char *cookie = NULL;
int verify = 0;
int xx;
/*@-mods@*/ /* FIX: make spec abstract */
if (parseSpec(ts, specName, "/", recursing, passPhrase,
cookie, anyarch, 1, verify)
|| (spec = rpmtsSetSpec(ts, NULL)) == NULL)
{
rpmlog(RPMLOG_ERR,
_("query of specfile %s failed, can't parse\n"),
specName);
goto exit;
}
/*@=mods@*/
res = 0;
if (specedit) {
printNewSpecfile(spec);
goto exit;
}
switch (qva->qva_source) {
case RPMQV_SPECSRPM:
xx = initSourceHeader(spec, NULL);
xx = initSourceHeaderScriptlets(spec);
xx = qva->qva_showPackage(qva, ts, spec->sourceHeader);
break;
default:
case RPMQV_SPECFILE:
for (pkg = spec->packages; pkg != NULL; pkg = pkg->next) {
/* If no target was specified, display all packages.
* Packages with empty file lists are not produced.
*/
/* XXX DIEDIEDIE: this logic looks flawed. */
if (target == NULL || pkg->fileList != NULL)
xx = qva->qva_showPackage(qva, ts, pkg->header);
}
break;
}
exit:
spec = freeSpec(spec);
return res;
}
int rpmspecQuery(rpmts ts, QVA_t qva, const char * arg)
{
int res = 1;
const char * targets = rpmcliTargets;
char *target;
const char * t;
const char * te;
int nqueries = 0;
if (qva->qva_showPackage == NULL)
goto exit;
if (targets == NULL) {
res = _specQuery(ts, qva, arg, NULL);
nqueries++;
goto exit;
}
rpmlog(RPMLOG_DEBUG,
_("Query specfile for platform(s): %s\n"), targets);
for (t = targets; *t != '\0'; t = te) {
/* Parse out next target platform. */
if ((te = strchr(t, ',')) == NULL)
te = t + strlen(t);
target = alloca(te-t+1);
strncpy(target, t, (te-t));
target[te-t] = '\0';
if (*te != '\0')
te++;
/* Query spec for this target platform. */
rpmlog(RPMLOG_DEBUG, _(" target platform: %s\n"), target);
/* Read in configuration for target. */
if (t != targets) {
rpmFreeMacros(NULL);
rpmFreeRpmrc();
(void) rpmReadConfigFiles(NULL, target);
}
res = _specQuery(ts, qva, arg, target);
nqueries++;
if (res) break;
}
exit:
/* Restore original configuration. */
if (nqueries > 1) {
t = targets;
if ((te = strchr(t, ',')) == NULL)
te = t + strlen(t);
target = alloca(te-t+1);
strncpy(target, t, (te-t));
target[te-t] = '\0';
if (*te != '\0')
te++;
rpmFreeMacros(NULL);
rpmFreeRpmrc();
(void) rpmReadConfigFiles(NULL, target);
}
return res;
}