rpm 5.2.1

- Main Page
- Related Pages
- Modules
- Data Structures
- Files

- File List
- Globals

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 }