Add md5->filedigest aliases (rhbz#487597)
[platform/upstream/rpm.git] / rpmqv.c
1 #include "system.h"
2 const char *__progname;
3
4 #define _AUTOHELP
5
6 #if defined(IAM_RPM) 
7 #define IAM_RPMBT
8 #define IAM_RPMDB
9 #define IAM_RPMEIU
10 #define IAM_RPMQV
11 #define IAM_RPMK
12 #endif
13
14 #include <rpm/rpmcli.h>
15 #include <rpm/rpmlib.h>                 /* RPMSIGTAG, rpmReadPackageFile .. */
16 #include <rpm/rpmbuild.h>
17 #include <rpm/rpmlog.h>
18 #include <rpm/rpmfileutil.h>
19
20 #include <rpm/rpmdb.h>
21 #include <rpm/rpmps.h>
22 #include <rpm/rpmts.h>
23
24 #ifdef  IAM_RPMBT
25 #include "build.h"
26 #define GETOPT_REBUILD          1003
27 #define GETOPT_RECOMPILE        1004
28 #endif
29
30 #if defined(IAM_RPMBT) || defined(IAM_RPMK)
31 #include "lib/signature.h"
32 #endif
33
34 #include "debug.h"
35
36 enum modes {
37
38     MODE_QUERY          = (1 <<  0),
39     MODE_VERIFY         = (1 <<  3),
40 #define MODES_QV (MODE_QUERY | MODE_VERIFY)
41
42     MODE_INSTALL        = (1 <<  1),
43     MODE_ERASE          = (1 <<  2),
44 #define MODES_IE (MODE_INSTALL | MODE_ERASE)
45
46     MODE_BUILD          = (1 <<  4),
47     MODE_REBUILD        = (1 <<  5),
48     MODE_RECOMPILE      = (1 <<  8),
49     MODE_TARBUILD       = (1 << 11),
50 #define MODES_BT (MODE_BUILD | MODE_TARBUILD | MODE_REBUILD | MODE_RECOMPILE)
51
52     MODE_CHECKSIG       = (1 <<  6),
53     MODE_RESIGN         = (1 <<  7),
54 #define MODES_K  (MODE_CHECKSIG | MODE_RESIGN)
55
56     MODE_INITDB         = (1 << 10),
57     MODE_REBUILDDB      = (1 << 12),
58     MODE_VERIFYDB       = (1 << 13),
59 #define MODES_DB (MODE_INITDB | MODE_REBUILDDB | MODE_VERIFYDB)
60
61
62     MODE_UNKNOWN        = 0
63 };
64
65 #define MODES_FOR_DBPATH        (MODES_BT | MODES_IE | MODES_QV | MODES_DB)
66 #define MODES_FOR_NODEPS        (MODES_BT | MODES_IE | MODE_VERIFY)
67 #define MODES_FOR_TEST          (MODES_BT | MODES_IE)
68 #define MODES_FOR_ROOT          (MODES_BT | MODES_IE | MODES_QV | MODES_DB | MODES_K)
69
70 static int quiet;
71
72 /* the structure describing the options we take and the defaults */
73 static struct poptOption optionsTable[] = {
74
75 #ifdef  IAM_RPMQV
76  { NULL, '\0', POPT_ARG_INCLUDE_TABLE, rpmQueryPoptTable, 0,
77         N_("Query options (with -q or --query):"),
78         NULL },
79  { NULL, '\0', POPT_ARG_INCLUDE_TABLE, rpmVerifyPoptTable, 0,
80         N_("Verify options (with -V or --verify):"),
81         NULL },
82 #ifdef  NOTYET
83  { NULL, '\0', POPT_ARG_INCLUDE_TABLE, rpmcliQVSourcePoptTable, 0,
84         N_("Source options (with --query or --verify):"),
85         NULL },
86 #endif
87  { NULL, '\0', POPT_ARG_INCLUDE_TABLE, rpmcliFtsPoptTable, 0,
88         N_("File tree walk options (with --ftswalk):"),
89         NULL },
90 #endif  /* IAM_RPMQV */
91
92 #ifdef  IAM_RPMK
93  { NULL, '\0', POPT_ARG_INCLUDE_TABLE, rpmSignPoptTable, 0,
94         N_("Signature options:"),
95         NULL },
96 #endif  /* IAM_RPMK */
97
98 #ifdef  IAM_RPMDB
99  { NULL, '\0', POPT_ARG_INCLUDE_TABLE, rpmDatabasePoptTable, 0,
100         N_("Database options:"),
101         NULL },
102 #endif  /* IAM_RPMDB */
103
104 #ifdef  IAM_RPMBT
105  { NULL, '\0', POPT_ARG_INCLUDE_TABLE, rpmBuildPoptTable, 0,
106         N_("Build options with [ <specfile> | <tarball> | <source package> ]:"),
107         NULL },
108 #endif  /* IAM_RPMBT */
109
110 #ifdef  IAM_RPMEIU
111  { NULL, '\0', POPT_ARG_INCLUDE_TABLE, rpmInstallPoptTable, 0,
112         N_("Install/Upgrade/Erase options:"),
113         NULL },
114 #endif  /* IAM_RPMEIU */
115
116  { "quiet", '\0', 0, &quiet, 0,                 NULL, NULL},
117
118  { NULL, '\0', POPT_ARG_INCLUDE_TABLE, rpmcliAllPoptTable, 0,
119         N_("Common options for all rpm modes and executables:"),
120         NULL },
121
122    POPT_AUTOALIAS
123    POPT_AUTOHELP
124    POPT_TABLEEND
125 };
126
127 #ifdef __MINT__
128 /* MiNT cannot dynamically increase the stack.  */
129 long _stksize = 64 * 1024L;
130 #endif
131
132 static void argerror(const char * desc)
133 {
134     fprintf(stderr, _("%s: %s\n"), __progname, desc);
135     exit(EXIT_FAILURE);
136 }
137
138 static void printVersion(FILE * fp)
139 {
140     fprintf(fp, _("RPM version %s\n"), rpmEVR);
141 }
142
143 static void printBanner(FILE * fp)
144 {
145     fprintf(fp, _("Copyright (C) 1998-2002 - Red Hat, Inc.\n"));
146     fprintf(fp, _("This program may be freely redistributed under the terms of the GNU GPL\n"));
147 }
148
149 static void printUsage(poptContext con, FILE * fp, int flags)
150 {
151     printVersion(fp);
152     printBanner(fp);
153     fprintf(fp, "\n");
154
155     if (rpmIsVerbose())
156         poptPrintHelp(con, fp, flags);
157     else
158         poptPrintUsage(con, fp, flags);
159 }
160
161 int main(int argc, char *argv[])
162 {
163     rpmts ts = NULL;
164     enum modes bigMode = MODE_UNKNOWN;
165
166 #if defined(IAM_RPMQV)
167     QVA_t qva = &rpmQVKArgs;
168 #endif
169
170 #ifdef  IAM_RPMBT
171     BTA_t ba = &rpmBTArgs;
172 #endif
173
174 #ifdef  IAM_RPMEIU
175    struct rpmInstallArguments_s * ia = &rpmIArgs;
176 #endif
177
178 #if defined(IAM_RPMDB)
179    struct rpmDatabaseArguments_s * da = &rpmDBArgs;
180 #endif
181
182 #if defined(IAM_RPMK)
183    QVA_t ka = &rpmQVKArgs;
184 #endif
185
186 #if defined(IAM_RPMBT) || defined(IAM_RPMK)
187     char * passPhrase = "";
188 #endif
189
190     int arg;
191
192     const char *optArg, *poptCtx;
193     pid_t pipeChild = 0;
194     poptContext optCon;
195     int ec = 0;
196     int status;
197     int p[2];
198 #ifdef  IAM_RPMEIU
199     int i;
200 #endif
201         
202 #if HAVE_MCHECK_H && HAVE_MTRACE
203     mtrace();   /* Trace malloc only if MALLOC_TRACE=mtrace-output-file. */
204 #endif
205     setprogname(argv[0]);       /* Retrofit glibc __progname */
206
207     /* XXX glibc churn sanity */
208     if (__progname == NULL) {
209         if ((__progname = strrchr(argv[0], '/')) != NULL) __progname++;
210         else __progname = argv[0];
211     }
212
213     /* Set the major mode based on argv[0] */
214 #ifdef  IAM_RPMBT
215     if (!strcmp(__progname, "rpmbuild"))        bigMode = MODE_BUILD;
216 #endif
217 #ifdef  IAM_RPMQV
218     if (!strcmp(__progname, "rpmquery"))        bigMode = MODE_QUERY;
219     if (!strcmp(__progname, "rpmverify"))       bigMode = MODE_VERIFY;
220 #endif
221
222 #if defined(IAM_RPMQV)
223     /* Jumpstart option from argv[0] if necessary. */
224     switch (bigMode) {
225     case MODE_QUERY:    qva->qva_mode = 'q';    break;
226     case MODE_VERIFY:   qva->qva_mode = 'V';    break;
227     case MODE_CHECKSIG: qva->qva_mode = 'K';    break;
228     case MODE_RESIGN:   qva->qva_mode = 'R';    break;
229     case MODE_INSTALL:
230     case MODE_ERASE:
231     case MODE_BUILD:
232     case MODE_REBUILD:
233     case MODE_RECOMPILE:
234     case MODE_TARBUILD:
235     case MODE_INITDB:
236     case MODE_REBUILDDB:
237     case MODE_VERIFYDB:
238     case MODE_UNKNOWN:
239     default:
240         break;
241     }
242 #endif
243
244 #if defined(ENABLE_NLS)
245     /* set up the correct locale */
246     (void) setlocale(LC_ALL, "" );
247
248     bindtextdomain(PACKAGE, LOCALEDIR);
249     textdomain(PACKAGE);
250 #endif
251
252     rpmSetVerbosity(RPMLOG_NOTICE);     /* XXX silly use by showrc */
253
254     /* Only build has it's own set of aliases, everything else uses rpm */
255 #ifdef  IAM_RPMBT
256     poptCtx = "rpmbuild";
257 #else
258     poptCtx = "rpm";
259 #endif
260
261     /* Make a first pass through the arguments, looking for --rcfile */
262     /* We need to handle that before dealing with the rest of the arguments. */
263     /* XXX popt argv definition should be fixed instead of casting... */
264     optCon = poptGetContext(poptCtx, argc, (const char **)argv, optionsTable, 0);
265     {
266         char *poptfile = rpmGenPath(rpmConfigDir(), LIBRPMALIAS_FILENAME, NULL);
267         (void) poptReadConfigFile(optCon, poptfile);
268         free(poptfile);
269     }
270     (void) poptReadDefaultConfig(optCon, 1);
271     poptSetExecPath(optCon, rpmConfigDir(), 1);
272
273     while ((arg = poptGetNextOpt(optCon)) > 0) {
274         optArg = poptGetOptArg(optCon);
275
276         switch (arg) {
277         default:
278             fprintf(stderr, _("Internal error in argument processing (%d) :-(\n"), arg);
279             exit(EXIT_FAILURE);
280         }
281     }
282
283     if (arg < -1) {
284         fprintf(stderr, "%s: %s\n", 
285                 poptBadOption(optCon, POPT_BADOPTION_NOALIAS), 
286                 poptStrerror(arg));
287         exit(EXIT_FAILURE);
288     }
289
290     rpmcliConfigured();
291
292 #ifdef  IAM_RPMBT
293     switch (ba->buildMode) {
294     case 'b':   bigMode = MODE_BUILD;           break;
295     case 't':   bigMode = MODE_TARBUILD;        break;
296     case 'B':   bigMode = MODE_REBUILD;         break;
297     case 'C':   bigMode = MODE_RECOMPILE;       break;
298     }
299
300     if ((ba->buildAmount & RPMBUILD_RMSOURCE) && bigMode == MODE_UNKNOWN)
301         bigMode = MODE_BUILD;
302
303     if ((ba->buildAmount & RPMBUILD_RMSPEC) && bigMode == MODE_UNKNOWN)
304         bigMode = MODE_BUILD;
305
306     if (ba->buildRootOverride && bigMode != MODE_BUILD &&
307         bigMode != MODE_REBUILD && bigMode != MODE_TARBUILD) {
308         argerror("--buildroot may only be used during package builds");
309     }
310 #endif  /* IAM_RPMBT */
311     
312 #ifdef  IAM_RPMDB
313   if (bigMode == MODE_UNKNOWN || (bigMode & MODES_DB)) {
314     if (da->init) {
315         if (bigMode != MODE_UNKNOWN) 
316             argerror(_("only one major mode may be specified"));
317         else
318             bigMode = MODE_INITDB;
319     } else
320     if (da->rebuild) {
321         if (bigMode != MODE_UNKNOWN) 
322             argerror(_("only one major mode may be specified"));
323         else
324             bigMode = MODE_REBUILDDB;
325     } else
326     if (da->verify) {
327         if (bigMode != MODE_UNKNOWN) 
328             argerror(_("only one major mode may be specified"));
329         else
330             bigMode = MODE_VERIFYDB;
331     }
332   }
333 #endif  /* IAM_RPMDB */
334
335 #ifdef  IAM_RPMQV
336   if (bigMode == MODE_UNKNOWN || (bigMode & MODES_QV)) {
337     switch (qva->qva_mode) {
338     case 'q':   bigMode = MODE_QUERY;           break;
339     case 'V':   bigMode = MODE_VERIFY;          break;
340     }
341
342     if (qva->qva_sourceCount) {
343         if (qva->qva_sourceCount > 2)
344             argerror(_("one type of query/verify may be performed at a "
345                         "time"));
346     }
347     if (qva->qva_flags && (bigMode & ~MODES_QV)) 
348         argerror(_("unexpected query flags"));
349
350     if (qva->qva_queryFormat && (bigMode & ~MODES_QV)) 
351         argerror(_("unexpected query format"));
352
353     if (qva->qva_source != RPMQV_PACKAGE && (bigMode & ~MODES_QV)) 
354         argerror(_("unexpected query source"));
355   }
356 #endif  /* IAM_RPMQV */
357
358 #ifdef  IAM_RPMEIU
359   if (bigMode == MODE_UNKNOWN || (bigMode & MODES_IE))
360     {   int iflags = (ia->installInterfaceFlags &
361                 (INSTALL_UPGRADE|INSTALL_FRESHEN|INSTALL_INSTALL));
362         int eflags = (ia->installInterfaceFlags & INSTALL_ERASE);
363
364         if (iflags & eflags)
365             argerror(_("only one major mode may be specified"));
366         else if (iflags)
367             bigMode = MODE_INSTALL;
368         else if (eflags)
369             bigMode = MODE_ERASE;
370     }
371 #endif  /* IAM_RPMEIU */
372
373 #ifdef  IAM_RPMK
374   if (bigMode == MODE_UNKNOWN || (bigMode & MODES_K)) {
375         switch (ka->qva_mode) {
376         case RPMSIGN_NONE:
377             ka->sign = 0;
378             break;
379         case RPMSIGN_IMPORT_PUBKEY:
380         case RPMSIGN_CHK_SIGNATURE:
381             bigMode = MODE_CHECKSIG;
382             ka->sign = 0;
383             break;
384         case RPMSIGN_ADD_SIGNATURE:
385         case RPMSIGN_NEW_SIGNATURE:
386         case RPMSIGN_DEL_SIGNATURE:
387             bigMode = MODE_RESIGN;
388             ka->sign = (ka->qva_mode != RPMSIGN_DEL_SIGNATURE);
389             break;
390         }
391   }
392 #endif  /* IAM_RPMK */
393
394 #if defined(IAM_RPMEIU)
395     if (!( bigMode == MODE_INSTALL ) &&
396 (ia->probFilter & (RPMPROB_FILTER_REPLACEPKG | RPMPROB_FILTER_OLDPACKAGE)))
397         argerror(_("only installation, upgrading, rmsource and rmspec may be forced"));
398     if (bigMode != MODE_INSTALL && (ia->probFilter & RPMPROB_FILTER_FORCERELOCATE))
399         argerror(_("files may only be relocated during package installation"));
400
401     if (ia->relocations && ia->prefix)
402         argerror(_("cannot use --prefix with --relocate or --excludepath"));
403
404     if (bigMode != MODE_INSTALL && ia->relocations)
405         argerror(_("--relocate and --excludepath may only be used when installing new packages"));
406
407     if (bigMode != MODE_INSTALL && ia->prefix)
408         argerror(_("--prefix may only be used when installing new packages"));
409
410     if (ia->prefix && ia->prefix[0] != '/') 
411         argerror(_("arguments to --prefix must begin with a /"));
412
413     if (bigMode != MODE_INSTALL && (ia->installInterfaceFlags & INSTALL_HASH))
414         argerror(_("--hash (-h) may only be specified during package "
415                         "installation"));
416
417     if (bigMode != MODE_INSTALL && (ia->installInterfaceFlags & INSTALL_PERCENT))
418         argerror(_("--percent may only be specified during package "
419                         "installation"));
420
421     if (bigMode != MODE_INSTALL && (ia->probFilter & RPMPROB_FILTER_REPLACEPKG))
422         argerror(_("--replacepkgs may only be specified during package "
423                         "installation"));
424
425     if (bigMode != MODE_INSTALL && (ia->transFlags & RPMTRANS_FLAG_NODOCS))
426         argerror(_("--excludedocs may only be specified during package "
427                    "installation"));
428
429     if (bigMode != MODE_INSTALL && ia->incldocs)
430         argerror(_("--includedocs may only be specified during package "
431                    "installation"));
432
433     if (ia->incldocs && (ia->transFlags & RPMTRANS_FLAG_NODOCS))
434         argerror(_("only one of --excludedocs and --includedocs may be "
435                  "specified"));
436   
437     if (bigMode != MODE_INSTALL && (ia->probFilter & RPMPROB_FILTER_IGNOREARCH))
438         argerror(_("--ignorearch may only be specified during package "
439                    "installation"));
440
441     if (bigMode != MODE_INSTALL && (ia->probFilter & RPMPROB_FILTER_IGNOREOS))
442         argerror(_("--ignoreos may only be specified during package "
443                    "installation"));
444
445     if (bigMode != MODE_INSTALL && bigMode != MODE_ERASE &&
446         (ia->probFilter & (RPMPROB_FILTER_DISKSPACE|RPMPROB_FILTER_DISKNODES)))
447         argerror(_("--ignoresize may only be specified during package "
448                    "installation"));
449
450     if ((ia->installInterfaceFlags & UNINSTALL_ALLMATCHES) && bigMode != MODE_ERASE)
451         argerror(_("--allmatches may only be specified during package "
452                    "erasure"));
453
454     if ((ia->transFlags & RPMTRANS_FLAG_ALLFILES) && bigMode != MODE_INSTALL)
455         argerror(_("--allfiles may only be specified during package "
456                    "installation"));
457
458     if ((ia->transFlags & RPMTRANS_FLAG_JUSTDB) &&
459         bigMode != MODE_INSTALL && bigMode != MODE_ERASE)
460         argerror(_("--justdb may only be specified during package "
461                    "installation and erasure"));
462
463     if (bigMode != MODE_INSTALL && bigMode != MODE_ERASE && bigMode != MODE_VERIFY &&
464         (ia->transFlags & (RPMTRANS_FLAG_NOSCRIPTS | _noTransScripts | _noTransTriggers)))
465         argerror(_("script disabling options may only be specified during "
466                    "package installation and erasure"));
467
468     if (bigMode != MODE_INSTALL && bigMode != MODE_ERASE && bigMode != MODE_VERIFY &&
469         (ia->transFlags & (RPMTRANS_FLAG_NOTRIGGERS | _noTransTriggers)))
470         argerror(_("trigger disabling options may only be specified during "
471                    "package installation and erasure"));
472
473     if (ia->noDeps & (bigMode & ~MODES_FOR_NODEPS))
474         argerror(_("--nodeps may only be specified during package "
475                    "building, rebuilding, recompilation, installation,"
476                    "erasure, and verification"));
477
478     if ((ia->transFlags & RPMTRANS_FLAG_TEST) && (bigMode & ~MODES_FOR_TEST))
479         argerror(_("--test may only be specified during package installation, "
480                  "erasure, and building"));
481 #endif  /* IAM_RPMEIU */
482
483     if (rpmcliRootDir && rpmcliRootDir[1] && (bigMode & ~MODES_FOR_ROOT))
484         argerror(_("--root (-r) may only be specified during "
485                  "installation, erasure, querying, and "
486                  "database rebuilds"));
487
488     if (rpmcliRootDir) {
489         switch (urlIsURL(rpmcliRootDir)) {
490         default:
491             if (bigMode & MODES_FOR_ROOT)
492                 break;
493         case URL_IS_UNKNOWN:
494             if (rpmcliRootDir[0] != '/')
495                 argerror(_("arguments to --root (-r) must begin with a /"));
496             break;
497         }
498     }
499
500     if (quiet)
501         rpmSetVerbosity(RPMLOG_WARNING);
502
503 #if defined(IAM_RPMBT) || defined(IAM_RPMK)
504     if (0
505 #if defined(IAM_RPMBT)
506     || ba->sign 
507 #endif
508 #if defined(IAM_RPMK)
509     || ka->sign
510 #endif
511     )
512     {
513         if (bigMode == MODE_REBUILD || bigMode == MODE_BUILD ||
514             bigMode == MODE_RESIGN || bigMode == MODE_TARBUILD)
515         {
516             const char ** av;
517             struct stat sb;
518             int errors = 0;
519
520             if ((av = poptGetArgs(optCon)) == NULL) {
521                 fprintf(stderr, _("no files to sign\n"));
522                 errors++;
523             } else
524             while (*av) {
525                 if (stat(*av, &sb)) {
526                     fprintf(stderr, _("cannot access file %s\n"), *av);
527                     errors++;
528                 }
529                 av++;
530             }
531
532             if (errors) {
533                 ec = errors;
534                 goto exit;
535             }
536
537             if (poptPeekArg(optCon)) {
538                 int sigTag = rpmLookupSignatureType(RPMLOOKUPSIG_QUERY);
539                 switch (sigTag) {
540                   case 0:
541                     break;
542                   case RPMSIGTAG_PGP:
543 #ifdef  DYING   /* XXX gpg can now be used for RSA signatures. */
544                     if ((sigTag == RPMSIGTAG_PGP || sigTag == RPMSIGTAG_PGP5) &&
545                         !rpmDetectPGPVersion(NULL)) {
546                         fprintf(stderr, _("pgp not found: "));
547                         ec = EXIT_FAILURE;
548                         goto exit;
549                     }
550 #endif
551                   case RPMSIGTAG_GPG:
552                   case RPMSIGTAG_DSA:
553                   case RPMSIGTAG_RSA:
554                     passPhrase = rpmGetPassPhrase(_("Enter pass phrase: "), sigTag);
555                     if (passPhrase == NULL) {
556                         fprintf(stderr, _("Pass phrase check failed\n"));
557                         ec = EXIT_FAILURE;
558                         goto exit;
559                     }
560                     fprintf(stderr, _("Pass phrase is good.\n"));
561                     passPhrase = xstrdup(passPhrase);
562                     break;
563                   default:
564                     fprintf(stderr,
565                             _("Invalid %%_signature spec in macro file.\n"));
566                     ec = EXIT_FAILURE;
567                     goto exit;
568                     break;
569                 }
570             }
571         } else {
572             argerror(_("--sign may only be used during package building"));
573         }
574     } else {
575         /* Make rpmLookupSignatureType() return 0 ("none") from now on */
576         (void) rpmLookupSignatureType(RPMLOOKUPSIG_DISABLE);
577     }
578 #endif  /* IAM_RPMBT || IAM_RPMK */
579
580     if (rpmcliPipeOutput) {
581         if (pipe(p) < 0) {
582             fprintf(stderr, _("creating a pipe for --pipe failed: %m\n"));
583             goto exit;
584         }
585
586         if (!(pipeChild = fork())) {
587             (void) signal(SIGPIPE, SIG_DFL);
588             (void) close(p[1]);
589             (void) dup2(p[0], STDIN_FILENO);
590             (void) close(p[0]);
591             (void) execl("/bin/sh", "/bin/sh", "-c", rpmcliPipeOutput, NULL);
592             fprintf(stderr, _("exec failed\n"));
593         }
594
595         (void) close(p[0]);
596         (void) dup2(p[1], STDOUT_FILENO);
597         (void) close(p[1]);
598     }
599         
600     ts = rpmtsCreate();
601     (void) rpmtsSetRootDir(ts, rpmcliRootDir);
602     switch (bigMode) {
603 #ifdef  IAM_RPMDB
604     case MODE_INITDB:
605         ec = rpmtsInitDB(ts, 0644);
606         break;
607
608     case MODE_REBUILDDB:
609     {   rpmVSFlags vsflags = rpmExpandNumeric("%{_vsflags_rebuilddb}");
610         rpmVSFlags ovsflags = rpmtsSetVSFlags(ts, vsflags);
611         ec = rpmtsRebuildDB(ts);
612         vsflags = rpmtsSetVSFlags(ts, ovsflags);
613     }   break;
614     case MODE_VERIFYDB:
615         ec = rpmtsVerifyDB(ts);
616         break;
617 #endif  /* IAM_RPMDB */
618
619 #ifdef  IAM_RPMBT
620     case MODE_REBUILD:
621     case MODE_RECOMPILE:
622     {   const char * pkg;
623
624         while (!rpmIsVerbose())
625             rpmIncreaseVerbosity();
626
627         if (!poptPeekArg(optCon))
628             argerror(_("no packages files given for rebuild"));
629
630         ba->buildAmount =
631             RPMBUILD_PREP | RPMBUILD_BUILD | RPMBUILD_INSTALL | RPMBUILD_CHECK;
632         if (bigMode == MODE_REBUILD) {
633             ba->buildAmount |= RPMBUILD_PACKAGEBINARY;
634             ba->buildAmount |= RPMBUILD_RMSOURCE;
635             ba->buildAmount |= RPMBUILD_RMSPEC;
636             ba->buildAmount |= RPMBUILD_CLEAN;
637             ba->buildAmount |= RPMBUILD_RMBUILD;
638         }
639
640         while ((pkg = poptGetArg(optCon))) {
641             char * specFile = NULL;
642
643             ba->cookie = NULL;
644             ec = rpmInstallSource(ts, pkg, &specFile, &ba->cookie);
645             if (ec == 0) {
646                 ba->rootdir = rpmcliRootDir;
647                 ba->passPhrase = passPhrase;
648                 ec = build(ts, specFile, ba, rpmcliRcfile);
649             }
650             ba->cookie = _free(ba->cookie);
651             specFile = _free(specFile);
652
653             if (ec)
654                 break;
655         }
656
657     }   break;
658
659     case MODE_BUILD:
660     case MODE_TARBUILD:
661     {   const char * pkg;
662         if (!quiet) while (!rpmIsVerbose())
663             rpmIncreaseVerbosity();
664        
665         switch (ba->buildChar) {
666         case 'a':
667             ba->buildAmount |= RPMBUILD_PACKAGESOURCE;
668         case 'b':
669             ba->buildAmount |= RPMBUILD_PACKAGEBINARY;
670             ba->buildAmount |= RPMBUILD_CLEAN;
671         case 'i':
672             ba->buildAmount |= RPMBUILD_INSTALL;
673             ba->buildAmount |= RPMBUILD_CHECK;
674             if ((ba->buildChar == 'i') && ba->shortCircuit)
675                 break;
676         case 'c':
677             ba->buildAmount |= RPMBUILD_BUILD;
678             if ((ba->buildChar == 'c') && ba->shortCircuit)
679                 break;
680         case 'p':
681             ba->buildAmount |= RPMBUILD_PREP;
682             break;
683             
684         case 'l':
685             ba->buildAmount |= RPMBUILD_FILECHECK;
686             break;
687         case 's':
688             ba->buildAmount |= RPMBUILD_PACKAGESOURCE;
689             break;
690         }
691
692         if (!poptPeekArg(optCon)) {
693             if (bigMode == MODE_BUILD)
694                 argerror(_("no spec files given for build"));
695             else
696                 argerror(_("no tar files given for build"));
697         }
698
699         while ((pkg = poptGetArg(optCon))) {
700             ba->rootdir = rpmcliRootDir;
701             ba->passPhrase = passPhrase;
702             ba->cookie = NULL;
703             ec = build(ts, pkg, ba, rpmcliRcfile);
704             if (ec)
705                 break;
706             rpmFreeMacros(NULL);
707             (void) rpmReadConfigFiles(rpmcliRcfile, NULL);
708         }
709     }   break;
710 #endif  /* IAM_RPMBT */
711
712 #ifdef  IAM_RPMEIU
713     case MODE_ERASE:
714         if (ia->noDeps) ia->installInterfaceFlags |= UNINSTALL_NODEPS;
715
716         if (!poptPeekArg(optCon)) {
717             argerror(_("no packages given for erase"));
718         } else {
719             ec += rpmErase(ts, ia, (ARGV_const_t) poptGetArgs(optCon));
720         }
721         break;
722
723     case MODE_INSTALL:
724
725         /* RPMTRANS_FLAG_KEEPOBSOLETE */
726
727         if (!ia->incldocs) {
728             if (ia->transFlags & RPMTRANS_FLAG_NODOCS) {
729                 ;
730             } else if (rpmExpandNumeric("%{_excludedocs}"))
731                 ia->transFlags |= RPMTRANS_FLAG_NODOCS;
732         }
733
734         if (ia->noDeps) ia->installInterfaceFlags |= INSTALL_NODEPS;
735
736         /* we've already ensured !(!ia->prefix && !ia->relocations) */
737         if (ia->prefix) {
738             ia->relocations = xmalloc(2 * sizeof(*ia->relocations));
739             ia->relocations[0].oldPath = NULL;   /* special case magic */
740             ia->relocations[0].newPath = ia->prefix;
741             ia->relocations[1].oldPath = NULL;
742             ia->relocations[1].newPath = NULL;
743         } else if (ia->relocations) {
744             ia->relocations = xrealloc(ia->relocations, 
745                         sizeof(*ia->relocations) * (ia->numRelocations + 1));
746             ia->relocations[ia->numRelocations].oldPath = NULL;
747             ia->relocations[ia->numRelocations].newPath = NULL;
748         }
749
750         if (!poptPeekArg(optCon)) {
751             argerror(_("no packages given for install"));
752         } else {
753             /* FIX: ia->relocations[0].newPath undefined */
754             ec += rpmInstall(ts, ia, (ARGV_t) poptGetArgs(optCon));
755         }
756         break;
757
758 #endif  /* IAM_RPMEIU */
759
760 #ifdef  IAM_RPMQV
761     case MODE_QUERY:
762         if (!poptPeekArg(optCon)
763          && !(qva->qva_source == RPMQV_ALL || qva->qva_source == RPMQV_HDLIST))
764             argerror(_("no arguments given for query"));
765
766         qva->qva_specQuery = rpmspecQuery;
767         ec = rpmcliQuery(ts, qva, (ARGV_const_t) poptGetArgs(optCon));
768         qva->qva_specQuery = NULL;
769         break;
770
771     case MODE_VERIFY:
772     {   rpmVerifyFlags verifyFlags = VERIFY_ALL;
773
774         verifyFlags &= ~qva->qva_flags;
775         qva->qva_flags = (rpmQueryFlags) verifyFlags;
776
777         if (!poptPeekArg(optCon)
778          && !(qva->qva_source == RPMQV_ALL || qva->qva_source == RPMQV_HDLIST))
779             argerror(_("no arguments given for verify"));
780         ec = rpmcliVerify(ts, qva, (ARGV_const_t) poptGetArgs(optCon));
781     }   break;
782 #endif  /* IAM_RPMQV */
783
784 #ifdef IAM_RPMK
785     case MODE_CHECKSIG:
786     {   rpmVerifyFlags verifyFlags =
787                 (VERIFY_FILEDIGEST|VERIFY_DIGEST|VERIFY_SIGNATURE);
788
789         verifyFlags &= ~ka->qva_flags;
790         ka->qva_flags = (rpmQueryFlags) verifyFlags;
791     }  
792     case MODE_RESIGN:
793         if (!poptPeekArg(optCon))
794             argerror(_("no arguments given"));
795         ka->passPhrase = passPhrase;
796         ec = rpmcliSign(ts, ka, (ARGV_const_t) poptGetArgs(optCon));
797         break;
798 #endif  /* IAM_RPMK */
799         
800 #if !defined(IAM_RPMQV)
801     case MODE_QUERY:
802     case MODE_VERIFY:
803 #endif
804 #if !defined(IAM_RPMK)
805     case MODE_CHECKSIG:
806     case MODE_RESIGN:
807 #endif
808 #if !defined(IAM_RPMDB)
809     case MODE_INITDB:
810     case MODE_REBUILDDB:
811     case MODE_VERIFYDB:
812 #endif
813 #if !defined(IAM_RPMBT)
814     case MODE_BUILD:
815     case MODE_REBUILD:
816     case MODE_RECOMPILE:
817     case MODE_TARBUILD:
818 #endif
819 #if !defined(IAM_RPMEIU)
820     case MODE_INSTALL:
821     case MODE_ERASE:
822 #endif
823     case MODE_UNKNOWN:
824         if (poptPeekArg(optCon) != NULL || argc <= 1 || rpmIsVerbose()) {
825             printUsage(optCon, stderr, 0);
826             ec = argc;
827         }
828         break;
829     }
830
831 exit:
832
833     ts = rpmtsFree(ts);
834
835     optCon = poptFreeContext(optCon);
836     rpmFreeMacros(NULL);
837         rpmFreeMacros(rpmCLIMacroContext);
838     rpmFreeRpmrc();
839
840     if (pipeChild) {
841         (void) fclose(stdout);
842         (void) waitpid(pipeChild, &status, 0);
843     }
844
845     /* keeps memory leak checkers quiet */
846     rpmFreeFilesystems();
847     rpmlogClose();
848
849 #ifdef  IAM_RPMQV
850     qva->qva_queryFormat = _free(qva->qva_queryFormat);
851 #endif
852
853 #ifdef  IAM_RPMBT
854     freeNames();
855     ba->buildRootOverride = _free(ba->buildRootOverride);
856     ba->targets = _free(ba->targets);
857 #endif
858
859 #ifdef  IAM_RPMEIU
860     if (ia->relocations != NULL)
861     for (i = 0; i < ia->numRelocations; i++)
862         ia->relocations[i].oldPath = _free(ia->relocations[i].oldPath);
863     ia->relocations = _free(ia->relocations);
864 #endif
865
866 #if HAVE_MCHECK_H && HAVE_MTRACE
867     muntrace();   /* Trace malloc only if MALLOC_TRACE=mtrace-output-file. */
868 #endif
869
870     /* XXX Avoid exit status overflow. Status 255 is special to xargs(1) */
871     if (ec > 254) ec = 254;
872
873     return ec;
874 }