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