rpm 5.2.1

build/spec.c

Go to the documentation of this file.
00001 
00006 #include "system.h"
00007 
00008 #include <rpmio.h>
00009 #include <rpmiotypes.h>
00010 #include <rpmlog.h>
00011 #include "buildio.h"
00012 #include "rpmds.h"
00013 #include "rpmfi.h"
00014 #include "rpmts.h"
00015 
00016 #include "rpmlua.h"
00017 
00018 #include "debug.h"
00019 
00020 /*@-redecl@*/
00021 extern int specedit;
00022 /*@=redecl@*/
00023 
00024 #define SKIPWHITE(_x)   {while(*(_x) && (xisspace(*_x) || *(_x) == ',')) (_x)++;}
00025 #define SKIPNONWHITE(_x){while(*(_x) &&!(xisspace(*_x) || *(_x) == ',')) (_x)++;}
00026 
00027 /*@access rpmluav @*/
00028 
00033 static inline
00034 /*@null@*/ struct TriggerFileEntry * freeTriggerFiles(/*@only@*/ /*@null@*/ struct TriggerFileEntry * p)
00035         /*@modifies p @*/
00036 {
00037     struct TriggerFileEntry *o, *q = p;
00038     
00039     while (q != NULL) {
00040         o = q;
00041         q = q->next;
00042         o->fileName = _free(o->fileName);
00043         o->script = _free(o->script);
00044         o->prog = _free(o->prog);
00045         o = _free(o);
00046     }
00047     return NULL;
00048 }
00049 
00055 static inline
00056 /*@null@*/ struct Source * freeSources(/*@only@*/ /*@null@*/ struct Source * s)
00057         /*@modifies s @*/
00058 {
00059     struct Source *r, *t = s;
00060 
00061     while (t != NULL) {
00062         r = t;
00063         t = t->next;
00064         r->fullSource = _free(r->fullSource);
00065         r = _free(r);
00066     }
00067     return NULL;
00068 }
00069 
00070 rpmRC lookupPackage(Spec spec, const char *name, int flag, /*@out@*/Package *pkg)
00071 {
00072     HE_t he = memset(alloca(sizeof(*he)), 0, sizeof(*he));
00073     char *NV = NULL;
00074     char *N = NULL;
00075     char *V = NULL;
00076     Package p, lastp;
00077     int xx;
00078     
00079     /* "main" package */
00080     if (name == NULL) {
00081         if (pkg)
00082             *pkg = spec->packages;
00083         return RPMRC_OK;
00084     }
00085 
00086     /* Construct package name */
00087     if (flag == PART_SUBNAME) {
00088         he->tag = RPMTAG_NAME;
00089         xx = headerGet(spec->packages->header, he, 0);
00090 assert(xx != 0 && he->p.str != NULL);
00091         N = rpmExpand(he->p.str, "-", name, NULL);
00092         he->p.ptr = _free(he->p.ptr);
00093     } else {
00094         N = xstrdup(name);
00095         if ((V = strrchr(N, '-')) != NULL) {
00096             NV = xstrdup(N);
00097             *V++ = '\0';
00098         }
00099     }
00100 
00101     /* Match last package with same N or same {N,V} */
00102     lastp = NULL;
00103     for (p = spec->packages; p != NULL; p = p->next) {
00104         char *nv, *n, *v;
00105         nv = n = v = NULL;
00106         he->tag = RPMTAG_NAME;
00107         xx = headerGet(p->header, he, 0);
00108         if (xx && he->p.str != NULL) {
00109             n = (char *) he->p.str;
00110             he->p.str = NULL;
00111         }
00112         if (NV != NULL) {
00113             he->tag = RPMTAG_VERSION;
00114             xx = headerGet(p->header, he, 0);
00115             if (xx && he->p.str != NULL) {
00116                 v = (char *) he->p.str;
00117                 he->p.str = NULL;
00118                 nv = rpmExpand(n, "-", v, NULL);
00119             }
00120         }
00121 
00122         if (NV == NULL) {
00123             if (!strcmp(N, n))
00124                 lastp = p;
00125         } else {
00126             if (!strcmp(NV, nv) ||  !strcmp(NV, n)
00127             || (!strcmp(N, n) && (V == NULL || !strcmp(V, v))))
00128                 lastp = p;
00129         }
00130 /*@-usereleased@*/
00131         n = _free(n);
00132         v = _free(v);
00133         nv = _free(nv);
00134 /*@=usereleased@*/
00135     }
00136 
00137     if (pkg)
00138         /*@-dependenttrans@*/ *pkg = lastp; /*@=dependenttrans@*/
00139     NV = _free(NV);
00140     N = _free(N);
00141     return ((lastp == NULL) ? RPMRC_FAIL : RPMRC_OK);
00142 }
00143 
00144 Package newPackage(/*@unused@*/ Spec spec)
00145 {
00146     Package p;
00147 
00148     p = xcalloc(1, sizeof(*p));
00149 
00150     p->header = headerNew();
00151     p->ds = NULL;
00152 
00153     p->autoProv = ((_rpmbuildFlags & 0x1) != 0);
00154     p->autoReq = ((_rpmbuildFlags & 0x2) != 0);
00155     
00156 #if 0    
00157     p->reqProv = NULL;
00158     p->triggers = NULL;
00159     p->triggerScripts = NULL;
00160 #endif
00161 
00162     p->triggerFiles = NULL;
00163     
00164     p->fileFile = NULL;
00165     p->fileList = NULL;
00166 
00167     p->cpioList = NULL;
00168 
00169     p->preInFile = NULL;
00170     p->postInFile = NULL;
00171     p->preUnFile = NULL;
00172     p->postUnFile = NULL;
00173     p->verifyFile = NULL;
00174     p->sanityCheckFile = NULL;
00175 
00176     p->specialDoc = NULL;
00177 
00178     p->next = NULL;
00179 
00180     return p;
00181 }
00182 
00183 Package freePackage(Package pkg)
00184 {
00185     if (pkg == NULL) return NULL;
00186     
00187     pkg->preInFile = _free(pkg->preInFile);
00188     pkg->postInFile = _free(pkg->postInFile);
00189     pkg->preUnFile = _free(pkg->preUnFile);
00190     pkg->postUnFile = _free(pkg->postUnFile);
00191     pkg->verifyFile = _free(pkg->verifyFile);
00192     pkg->sanityCheckFile = _free(pkg->sanityCheckFile);
00193 
00194     (void)headerFree(pkg->header);
00195     pkg->header = NULL;
00196     (void)rpmdsFree(pkg->ds);
00197     pkg->ds = NULL;
00198     pkg->fileList = rpmiobFree(pkg->fileList);
00199     pkg->fileFile = _free(pkg->fileFile);
00200     if (pkg->cpioList != NULL) {
00201         rpmfi fi = pkg->cpioList;
00202         pkg->cpioList = NULL;
00203         fi = rpmfiFree(fi);
00204     }
00205 
00206     pkg->specialDoc = rpmiobFree(pkg->specialDoc);
00207     pkg->triggerFiles = freeTriggerFiles(pkg->triggerFiles);
00208 
00209     pkg = _free(pkg);
00210     return NULL;
00211 }
00212 
00213 Package freePackages(Package packages)
00214 {
00215     Package p;
00216 
00217     while ((p = packages) != NULL) {
00218         packages = p->next;
00219         p->next = NULL;
00220         p = freePackage(p);
00221     }
00222     return NULL;
00223 }
00224 
00227 static inline /*@owned@*/ struct Source *findSource(Spec spec, rpmuint32_t num, int flag)
00228         /*@*/
00229 {
00230     struct Source *p;
00231 
00232     for (p = spec->sources; p != NULL; p = p->next)
00233         if ((num == p->num) && (p->flags & flag)) return p;
00234 
00235     return NULL;
00236 }
00237 
00240 int SpecSourceCount(Spec spec)
00241 {
00242     return spec->numSources;
00243 }
00244 
00247 SpecSource getSource(Spec spec, int num)
00248     /* @ */
00249 {
00250     struct Source *p = spec->sources;
00251     int i;
00252 
00253     for (i = 0; i < num; i++)
00254         if ((p = p->next) == NULL) return NULL;
00255 
00256 /*@-usereleased@*/
00257     return p;
00258 /*@=usereleased@*/
00259 }
00260 
00263 const char * specSourceName(SpecSource source)
00264 {
00265     return source->source;
00266 }
00267 
00270 const char * specFullSourceName(SpecSource source)
00271 {
00272     return source->fullSource;
00273 }
00274 
00277 int specSourceNum(SpecSource source)
00278 {
00279     return source->num;
00280 }
00281 
00284 int specSourceFlags(SpecSource source)
00285 {
00286     return source->flags;
00287 }
00288 
00289 int parseNoSource(Spec spec, const char * field, rpmTag tag)
00290 {
00291     const char *f, *fe;
00292     const char *name;
00293     rpmuint32_t num, flag;
00294 
00295     if (tag == RPMTAG_NOSOURCE) {
00296         flag = RPMFILE_SOURCE;
00297         name = "source";
00298     } else {
00299         flag = RPMFILE_PATCH;
00300         name = "patch";
00301     }
00302     
00303     fe = field;
00304     for (f = fe; *f != '\0'; f = fe) {
00305         struct Source *p;
00306 
00307         SKIPWHITE(f);
00308         if (*f == '\0')
00309             break;
00310         fe = f;
00311         SKIPNONWHITE(fe);
00312         if (*fe != '\0') fe++;
00313 
00314         if (parseNum(f, &num)) {
00315             rpmlog(RPMLOG_ERR, _("line %d: Bad number: %s\n"),
00316                      spec->lineNum, f);
00317             return RPMRC_FAIL;
00318         }
00319 
00320         if (! (p = findSource(spec, num, flag))) {
00321             rpmlog(RPMLOG_ERR, _("line %d: Bad no%s number: %d\n"),
00322                      spec->lineNum, name, num);
00323             return RPMRC_FAIL;
00324         }
00325 
00326         p->flags |= RPMFILE_GHOST;
00327 
00328     }
00329 
00330     return RPMRC_OK;
00331 }
00332 
00333 int addSource(Spec spec, /*@unused@*/ Package pkg,
00334                 const char *field, rpmTag tag)
00335 {
00336     struct Source *p;
00337 #if defined(RPM_VENDOR_OPENPKG) /* regular-ordered-sources */
00338     struct Source *p_last;
00339 #endif
00340     int flag = 0;
00341     const char *name = NULL;
00342     const char *mdir = NULL;
00343     char *nump;
00344     const char *fieldp = NULL;
00345     char buf[BUFSIZ];
00346     rpmuint32_t num = 0;
00347 
00348     buf[0] = '\0';
00349     switch (tag) {
00350     case RPMTAG_SOURCE:
00351         flag = RPMFILE_SOURCE;
00352         name = "source";
00353         fieldp = spec->line + (sizeof("Source")-1);
00354         break;
00355     case RPMTAG_PATCH:
00356         flag = RPMFILE_PATCH;
00357         name = "patch";
00358         fieldp = spec->line + (sizeof("Patch")-1);
00359         break;
00360     case RPMTAG_ICON:
00361         flag = RPMFILE_ICON;
00362         name = "icon";
00363         fieldp = NULL;
00364         break;
00365     default:
00366 assert(0);
00367         /*@notreached@*/ break;
00368     }
00369 #if !defined(RPM_VENDOR_OPENPKG) /* splitted-source-directory */
00370     mdir = getSourceDir(flag);
00371 assert(mdir != NULL);
00372 #endif
00373 
00374     /* Get the number */
00375     if (fieldp != NULL) {
00376         /* We already know that a ':' exists, and that there */
00377         /* are no spaces before it.                          */
00378         /* This also now allows for spaces and tabs between  */
00379         /* the number and the ':'                            */
00380 
00381         nump = buf;
00382         while ((*fieldp != ':') && (*fieldp != ' ') && (*fieldp != '\t'))
00383             *nump++ = *fieldp++;
00384         *nump = '\0';
00385 
00386         nump = buf;
00387         SKIPSPACE(nump);
00388         if (nump == NULL || *nump == '\0')
00389             num = 0;
00390         else if (parseNum(buf, &num)) {
00391             rpmlog(RPMLOG_ERR, _("line %d: Bad %s number: %s\n"),
00392                          spec->lineNum, name, spec->line);
00393             return RPMRC_FAIL;
00394         }
00395     }
00396 
00397     /* Check whether tags of the same number haven't already been defined */
00398     for (p = spec->sources; p != NULL; p = p->next) {
00399         if ( p->num != num ) continue;
00400         if ((tag == RPMTAG_SOURCE && p->flags == RPMFILE_SOURCE) ||
00401             (tag == RPMTAG_PATCH  && p->flags == RPMFILE_PATCH)) {
00402                 rpmlog(RPMLOG_ERR, _("%s %d defined multiple times\n"), name, num);
00403                 return RPMRC_FAIL;
00404             }
00405     }
00406 
00407     /* Create the entry and link it in */
00408     p = xmalloc(sizeof(*p));
00409     p->num = num;
00410     p->fullSource = xstrdup(field);
00411     p->flags = flag;
00412     p->source = strrchr(p->fullSource, '/');
00413     if (p->source)
00414         p->source++;
00415     else
00416         p->source = p->fullSource;
00417 
00418 #if defined(RPM_VENDOR_OPENPKG) /* regular-ordered-sources */
00419     p->next = NULL;
00420     p_last = spec->sources;
00421     while (p_last != NULL && p_last->next != NULL)
00422         p_last = p_last->next;
00423     if (p_last != NULL)
00424         p_last->next = p;
00425     else
00426         spec->sources = p;
00427 #else
00428     p->next = spec->sources;
00429     spec->sources = p;
00430 #endif
00431 
00432     spec->numSources++;
00433 
00434     /* XXX FIXME: need to add ICON* macros. */
00435 #if defined(RPM_VENDOR_OPENPKG) /* splitted-source-directory */
00436     mdir = getSourceDir(flag, p->source);
00437 #endif
00438     if (tag != RPMTAG_ICON) {
00439         const char *body = rpmGenPath(NULL, mdir, p->source);
00440 
00441         sprintf(buf, "%s%d",
00442                 (flag & RPMFILE_PATCH) ? "PATCH" : "SOURCE", num);
00443         addMacro(spec->macros, buf, NULL, body, RMIL_SPEC);
00444         sprintf(buf, "%sURL%d",
00445                 (flag & RPMFILE_PATCH) ? "PATCH" : "SOURCE", num);
00446         addMacro(spec->macros, buf, NULL, p->fullSource, RMIL_SPEC);
00447 #ifdef WITH_LUA
00448         if (!spec->recursing) {
00449             rpmlua lua = NULL; /* global state */
00450             const char * what = (flag & RPMFILE_PATCH) ? "patches" : "sources";
00451             rpmluav var = rpmluavNew();
00452 
00453             rpmluaPushTable(lua, what);
00454             rpmluavSetListMode(var, 1);
00455             rpmluavSetValue(var, RPMLUAV_STRING, body);
00456             rpmluaSetVar(lua, var);
00457 /*@-moduncon@*/
00458             var = (rpmluav) rpmluavFree(var);
00459 /*@=moduncon@*/
00460             rpmluaPop(lua);
00461         }
00462 #endif
00463         body = _free(body);
00464     }
00465     
00466     return RPMRC_OK;
00467 }
00468 
00471 static inline /*@only@*/ /*@null@*/ speclines newSl(void)
00472         /*@*/
00473 {
00474     speclines sl = NULL;
00475     if (specedit) {
00476         sl = xmalloc(sizeof(*sl));
00477         sl->sl_lines = NULL;
00478         sl->sl_nalloc = 0;
00479         sl->sl_nlines = 0;
00480     }
00481     return sl;
00482 }
00483 
00486 static inline /*@null@*/ speclines freeSl(/*@only@*/ /*@null@*/ speclines sl)
00487         /*@modifies sl @*/
00488 {
00489     int i;
00490     if (sl == NULL) return NULL;
00491     for (i = 0; i < sl->sl_nlines; i++)
00492         /*@-unqualifiedtrans@*/
00493         sl->sl_lines[i] = _free(sl->sl_lines[i]);
00494         /*@=unqualifiedtrans@*/
00495     sl->sl_lines = _free(sl->sl_lines);
00496     return _free(sl);
00497 }
00498 
00501 static inline /*@only@*/ /*@null@*/ spectags newSt(void)
00502         /*@*/
00503 {
00504     spectags st = NULL;
00505     if (specedit) {
00506         st = xmalloc(sizeof(*st));
00507         st->st_t = NULL;
00508         st->st_nalloc = 0;
00509         st->st_ntags = 0;
00510     }
00511     return st;
00512 }
00513 
00516 static inline /*@null@*/ spectags freeSt(/*@only@*/ /*@null@*/ spectags st)
00517         /*@modifies st @*/
00518 {
00519     int i;
00520     if (st == NULL) return NULL;
00521     for (i = 0; i < st->st_ntags; i++) {
00522         spectag t = st->st_t + i;
00523         t->t_lang = _free(t->t_lang);
00524         t->t_msgid = _free(t->t_msgid);
00525     }
00526     st->st_t = _free(st->st_t);
00527     return _free(st);
00528 }
00529 
00530 Spec newSpec(void)
00531 {
00532     Spec spec = xcalloc(1, sizeof(*spec));
00533     
00534     spec->specFile = NULL;
00535 
00536     spec->sl = newSl();
00537     spec->st = newSt();
00538 
00539     spec->fileStack = NULL;
00540     spec->lbuf_len = (size_t)rpmExpandNumeric("%{?_spec_line_buffer_size}%{!?_spec_line_buffer_size:100000}");
00541     spec->lbuf = (char *)xcalloc(1, spec->lbuf_len);
00542     spec->line = spec->lbuf;
00543     spec->nextline = NULL;
00544     spec->nextpeekc = '\0';
00545     spec->lineNum = 0;
00546     spec->readStack = xcalloc(1, sizeof(*spec->readStack));
00547     spec->readStack->next = NULL;
00548     spec->readStack->reading = 1;
00549 
00550     spec->rootURL = NULL;
00551     spec->prep = NULL;
00552     spec->build = NULL;
00553     spec->install = NULL;
00554     spec->check = NULL;
00555     spec->clean = NULL;
00556     spec->foo = NULL;
00557     spec->nfoo = 0;
00558 
00559     spec->sources = NULL;
00560     spec->packages = NULL;
00561     spec->noSource = 0;
00562     spec->numSources = 0;
00563 
00564     spec->sourceRpmName = NULL;
00565     spec->sourcePkgId = NULL;
00566     spec->sourceHeader = headerNew();
00567     spec->sourceCpioList = NULL;
00568     
00569     spec->buildSubdir = NULL;
00570 
00571     spec->passPhrase = NULL;
00572     spec->timeCheck = 0;
00573     spec->cookie = NULL;
00574 
00575     spec->BANames = NULL;
00576     spec->BACount = 0;
00577     spec->recursing = 0;
00578     spec->toplevel = 1;
00579     spec->BASpecs = NULL;
00580 
00581     spec->force = 0;
00582     spec->anyarch = 0;
00583 
00584 /*@i@*/ spec->macros = rpmGlobalMacroContext;
00585 
00586     spec->_parseRCPOT = parseRCPOT;     /* XXX hack around backward linkage. */
00587     
00588     return spec;
00589 }
00590 
00591 Spec freeSpec(Spec spec)
00592 {
00593     struct ReadLevelEntry *rl;
00594 
00595     if (spec == NULL) return NULL;
00596 
00597     spec->lbuf = _free(spec->lbuf);
00598 
00599     spec->sl = freeSl(spec->sl);
00600     spec->st = freeSt(spec->st);
00601 
00602     spec->prep = rpmiobFree(spec->prep);
00603     spec->build = rpmiobFree(spec->build);
00604     spec->install = rpmiobFree(spec->install);
00605     spec->check = rpmiobFree(spec->check);
00606     spec->clean = rpmiobFree(spec->clean);
00607     spec->foo = tagStoreFree(spec->foo, spec->nfoo);
00608     spec->nfoo = 0;
00609 
00610     spec->buildSubdir = _free(spec->buildSubdir);
00611     spec->rootURL = _free(spec->rootURL);
00612     spec->specFile = _free(spec->specFile);
00613 
00614     closeSpec(spec);
00615 
00616     while (spec->readStack) {
00617         rl = spec->readStack;
00618         /*@-dependenttrans@*/
00619         spec->readStack = rl->next;
00620         /*@=dependenttrans@*/
00621         rl->next = NULL;
00622         rl = _free(rl);
00623     }
00624     
00625     spec->sourceRpmName = _free(spec->sourceRpmName);
00626     spec->sourcePkgId = _free(spec->sourcePkgId);
00627     spec->sourceHeader = headerFree(spec->sourceHeader);
00628 
00629     if (spec->sourceCpioList != NULL) {
00630         rpmfi fi = spec->sourceCpioList;
00631         spec->sourceCpioList = NULL;
00632         fi = rpmfiFree(fi);
00633     }
00634     
00635     if (!spec->recursing) {
00636         if (spec->BASpecs != NULL)
00637         while (spec->BACount--) {
00638             /*@-unqualifiedtrans@*/
00639             spec->BASpecs[spec->BACount] =
00640                         freeSpec(spec->BASpecs[spec->BACount]);
00641             /*@=unqualifiedtrans@*/
00642         }
00643         /*@-compdef@*/
00644         spec->BASpecs = _free(spec->BASpecs);
00645         /*@=compdef@*/
00646     }
00647     spec->BANames = _free(spec->BANames);
00648 
00649     spec->passPhrase = _free(spec->passPhrase);
00650     spec->cookie = _free(spec->cookie);
00651 
00652 #ifdef WITH_LUA
00653     {   rpmlua lua = NULL; /* global state */
00654         rpmluaDelVar(lua, "patches");
00655         rpmluaDelVar(lua, "sources");   
00656     }
00657 #endif
00658 
00659     spec->sources = freeSources(spec->sources);
00660     spec->packages = freePackages(spec->packages);
00661     
00662     spec = _free(spec);
00663 
00664     return spec;
00665 }
00666 
00667 /*@only@*/
00668 struct OpenFileInfo * newOpenFileInfo(void)
00669 {
00670     struct OpenFileInfo *ofi;
00671 
00672     ofi = xmalloc(sizeof(*ofi));
00673     ofi->fd = NULL;
00674     ofi->fileName = NULL;
00675     ofi->lineNum = 0;
00676     ofi->readBuf[0] = '\0';
00677     ofi->readPtr = NULL;
00678     ofi->next = NULL;
00679 
00680     return ofi;
00681 }
00682 
00687 static void
00688 printNewSpecfile(Spec spec)
00689         /*@globals fileSystem, internalState @*/
00690         /*@modifies spec->sl->sl_lines[], spec->packages->header,
00691                 fileSystem, internalState @*/
00692 {
00693     HE_t he = memset(alloca(sizeof(*he)), 0, sizeof(*he));
00694     Header h;
00695     speclines sl = spec->sl;
00696     spectags st = spec->st;
00697     const char * msgstr = NULL;
00698     int i, j;
00699     int xx;
00700 
00701     if (sl == NULL || st == NULL)
00702         return;
00703 
00704     for (i = 0; i < st->st_ntags; i++) {
00705         spectag t = st->st_t + i;
00706         const char * tn = tagName(t->t_tag);
00707         const char * errstr;
00708         char fmt[1024];
00709 
00710         fmt[0] = '\0';
00711         if (t->t_msgid == NULL)
00712             h = spec->packages->header;
00713         else {
00714             Package pkg;
00715             char *fe;
00716 
00717             strcpy(fmt, t->t_msgid);
00718             for (fe = fmt; *fe && *fe != '('; fe++)
00719                 {} ;
00720             if (*fe == '(') *fe = '\0';
00721             h = NULL;
00722             for (pkg = spec->packages; pkg != NULL; pkg = pkg->next) {
00723                 h = pkg->header;
00724                 he->tag = RPMTAG_NAME;
00725                 xx = headerGet(h, he, 0);
00726                 if (!strcmp(he->p.str, fmt)) {
00727                     he->p.ptr = _free(he->p.ptr);
00728                     /*@innerbreak@*/ break;
00729                 }
00730                 he->p.ptr = _free(he->p.ptr);
00731             }
00732             if (pkg == NULL || h == NULL)
00733                 h = spec->packages->header;
00734         }
00735 
00736         if (h == NULL)
00737             continue;
00738 
00739         fmt[0] = '\0';
00740         (void) stpcpy( stpcpy( stpcpy( fmt, "%{"), tn), "}");
00741         msgstr = _free(msgstr);
00742 
00743         /* XXX this should use queryHeader(), but prints out tn as well. */
00744         msgstr = headerSprintf(h, fmt, NULL, rpmHeaderFormats, &errstr);
00745         if (msgstr == NULL) {
00746             rpmlog(RPMLOG_ERR, _("can't query %s: %s\n"), tn, errstr);
00747             return;
00748         }
00749 
00750         switch(t->t_tag) {
00751         case RPMTAG_SUMMARY:
00752         case RPMTAG_GROUP:
00753             /*@-unqualifiedtrans@*/
00754             sl->sl_lines[t->t_startx] = _free(sl->sl_lines[t->t_startx]);
00755             /*@=unqualifiedtrans@*/
00756             if (t->t_lang && strcmp(t->t_lang, RPMBUILD_DEFAULT_LANG))
00757                 continue;
00758             {   char *buf = xmalloc(strlen(tn) + sizeof(": ") + strlen(msgstr));
00759                 (void) stpcpy( stpcpy( stpcpy(buf, tn), ": "), msgstr);
00760                 sl->sl_lines[t->t_startx] = buf;
00761             }
00762             /*@switchbreak@*/ break;
00763         case RPMTAG_DESCRIPTION:
00764             for (j = 1; j < t->t_nlines; j++) {
00765                 if (*sl->sl_lines[t->t_startx + j] == '%')
00766                     /*@innercontinue@*/ continue;
00767                 /*@-unqualifiedtrans@*/
00768                 sl->sl_lines[t->t_startx + j] =
00769                         _free(sl->sl_lines[t->t_startx + j]);
00770                 /*@=unqualifiedtrans@*/
00771             }
00772             if (t->t_lang && strcmp(t->t_lang, RPMBUILD_DEFAULT_LANG)) {
00773                 sl->sl_lines[t->t_startx] = _free(sl->sl_lines[t->t_startx]);
00774                 continue;
00775             }
00776             sl->sl_lines[t->t_startx + 1] = xstrdup(msgstr);
00777             if (t->t_nlines > 2)
00778                 sl->sl_lines[t->t_startx + 2] = xstrdup("\n\n");
00779             /*@switchbreak@*/ break;
00780         }
00781     }
00782     msgstr = _free(msgstr);
00783 
00784     for (i = 0; i < sl->sl_nlines; i++) {
00785         const char * s = sl->sl_lines[i];
00786         if (s == NULL)
00787             continue;
00788         printf("%s", s);
00789         if (strchr(s, '\n') == NULL && s[strlen(s)-1] != '\n')
00790             printf("\n");
00791     }
00792 }
00793 
00802 static int initSourceHeaderScriptlet(Header h,
00803                 rpmTag progTag, rpmTag scriptTag, rpmiob iob)
00804         /*@modifies h @*/
00805 {
00806     HE_t he = memset(alloca(sizeof(*he)), 0, sizeof(*he));
00807     int xx;
00808 
00809     if (progTag !=(rpmTag) 0) {
00810         static const char prog[] = "/bin/sh";   /* XXX FIXME */
00811         he->tag = progTag;
00812         he->t = RPM_STRING_TYPE;
00813         he->p.str = prog;
00814         he->c = 1;
00815         xx = headerPut(h, he, 0);
00816     }
00817 
00818     if (scriptTag != (rpmTag)0 && iob != NULL) {
00819         he->tag = scriptTag;
00820         he->t = RPM_STRING_TYPE;
00821         he->p.str = rpmiobStr(iob);
00822         he->c = 1;
00823         xx = headerPut(h, he, 0);
00824     }
00825     return 0;
00826 }
00827 
00833 static int initSourceHeaderScriptlets(Spec spec)
00834         /*@modifies spec->sourceHeader @*/
00835 {
00836     int xx;
00837 
00838     if (spec->prep != NULL)
00839         xx = initSourceHeaderScriptlet(spec->sourceHeader,
00840             tagValue("Buildprepprog"), tagValue("Buildprep"), spec->prep);
00841     if (spec->build != NULL)
00842         xx = initSourceHeaderScriptlet(spec->sourceHeader,
00843             tagValue("Buildbuildprog"), tagValue("Buildbuild"), spec->build);
00844     if (spec->install != NULL)
00845         xx = initSourceHeaderScriptlet(spec->sourceHeader,
00846             tagValue("Buildinstallprog"), tagValue("Buildinstall"), spec->install);
00847     if (spec->check != NULL)
00848         xx = initSourceHeaderScriptlet(spec->sourceHeader,
00849             tagValue("Buildcheckprog"), tagValue("Buildcheck"), spec->check);
00850     if (spec->clean != NULL)
00851         xx = initSourceHeaderScriptlet(spec->sourceHeader,
00852             tagValue("Buildcleanprog"), tagValue("Buildclean"), spec->clean);
00853 
00854    return 0;
00855 }
00856 
00865 static int _specQuery(rpmts ts, QVA_t qva, const char *specName,
00866                 /*@null@*/ const char *target) 
00867         /*@globals rpmGlobalMacroContext, h_errno, fileSystem, internalState @*/
00868         /*@modifies rpmGlobalMacroContext, fileSystem, internalState @*/
00869 {
00870     Spec spec = NULL;
00871     Package pkg;
00872     int res = 1;        /* assume error */
00873     int anyarch = (target == NULL) ? 1 : 0;
00874     char * passPhrase = "";
00875     int recursing = 0;
00876     char *cookie = NULL;
00877     int verify = 0;
00878     int xx;
00879 
00880     /*@-mods@*/ /* FIX: make spec abstract */
00881     if (parseSpec(ts, specName, "/", recursing, passPhrase,
00882                 cookie, anyarch, 1, verify)
00883       || (spec = rpmtsSetSpec(ts, NULL)) == NULL)
00884     {
00885         rpmlog(RPMLOG_ERR,
00886             _("query of specfile %s failed, can't parse\n"), 
00887             specName);
00888         goto exit;
00889     }
00890     /*@=mods@*/
00891 
00892     res = 0;
00893     if (specedit) {
00894         printNewSpecfile(spec);
00895         goto exit;
00896     }
00897 
00898     switch (qva->qva_source) {
00899     case RPMQV_SPECSRPM:
00900         xx = initSourceHeader(spec, NULL);
00901         xx = initSourceHeaderScriptlets(spec);
00902         xx = qva->qva_showPackage(qva, ts, spec->sourceHeader);
00903         break;
00904     default:
00905     case RPMQV_SPECFILE:
00906         for (pkg = spec->packages; pkg != NULL; pkg = pkg->next) {
00907             /* If no target was specified, display all packages.
00908              * Packages with empty file lists are not produced.
00909              */
00910             /* XXX DIEDIEDIE: this logic looks flawed. */
00911             if (target == NULL || pkg->fileList != NULL) 
00912                 xx = qva->qva_showPackage(qva, ts, pkg->header);
00913         }
00914         break;
00915     }
00916 
00917 exit:
00918     spec = freeSpec(spec);
00919     return res;
00920 }
00921 
00922 int rpmspecQuery(rpmts ts, QVA_t qva, const char * arg)
00923 {
00924     int res = 1;
00925     const char * targets = rpmcliTargets;
00926     char *target;
00927     const char * t;
00928     const char * te;
00929     int nqueries = 0;
00930 
00931     if (qva->qva_showPackage == NULL)
00932         goto exit;
00933 
00934     if (targets == NULL) {
00935         res = _specQuery(ts, qva, arg, NULL); 
00936         nqueries++;
00937         goto exit;
00938     }
00939 
00940     rpmlog(RPMLOG_DEBUG, 
00941         _("Query specfile for platform(s): %s\n"), targets);
00942     for (t = targets; *t != '\0'; t = te) {
00943         /* Parse out next target platform. */ 
00944         if ((te = strchr(t, ',')) == NULL)
00945             te = t + strlen(t);
00946         target = alloca(te-t+1);
00947         strncpy(target, t, (te-t));
00948         target[te-t] = '\0';
00949         if (*te != '\0')
00950             te++;
00951 
00952         /* Query spec for this target platform. */
00953         rpmlog(RPMLOG_DEBUG, _("    target platform: %s\n"), target);
00954         /* Read in configuration for target. */
00955         if (t != targets) {
00956             rpmFreeMacros(NULL);
00957             rpmFreeRpmrc();
00958             (void) rpmReadConfigFiles(NULL, target);
00959         }
00960         res = _specQuery(ts, qva, arg, target); 
00961         nqueries++;
00962         if (res) break; 
00963     }
00964     
00965 exit:
00966     /* Restore original configuration. */
00967     if (nqueries > 1) {
00968         t = targets;
00969         if ((te = strchr(t, ',')) == NULL)
00970             te = t + strlen(t);
00971         target = alloca(te-t+1);
00972         strncpy(target, t, (te-t));
00973         target[te-t] = '\0';
00974         if (*te != '\0')
00975             te++;
00976         rpmFreeMacros(NULL);
00977         rpmFreeRpmrc();
00978         (void) rpmReadConfigFiles(NULL, target);
00979     }
00980     return res;
00981 }