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