Apply poptReadDefaultConfig iff RPM_USES_POPTREADDEFAULTCONFIG is set.
[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 "rpmps.h"
19 #include "rpmts.h"
20
21 #ifdef  IAM_RPMBT
22 #include "build.h"
23 #define GETOPT_REBUILD          1003
24 #define GETOPT_RECOMPILE        1004
25 #endif
26
27 #if defined(IAM_RPMBT) || defined(IAM_RPMK)
28 #include "signature.h"
29 #endif
30
31 #include "debug.h"
32
33 enum modes {
34
35     MODE_QUERY          = (1 <<  0),
36     MODE_VERIFY         = (1 <<  3),
37 #define MODES_QV (MODE_QUERY | MODE_VERIFY)
38
39     MODE_INSTALL        = (1 <<  1),
40     MODE_ERASE          = (1 <<  2),
41 #define MODES_IE (MODE_INSTALL | MODE_ERASE)
42
43     MODE_BUILD          = (1 <<  4),
44     MODE_REBUILD        = (1 <<  5),
45     MODE_RECOMPILE      = (1 <<  8),
46     MODE_TARBUILD       = (1 << 11),
47 #define MODES_BT (MODE_BUILD | MODE_TARBUILD | MODE_REBUILD | MODE_RECOMPILE)
48
49     MODE_CHECKSIG       = (1 <<  6),
50     MODE_RESIGN         = (1 <<  7),
51 #define MODES_K  (MODE_CHECKSIG | MODE_RESIGN)
52
53     MODE_INITDB         = (1 << 10),
54     MODE_REBUILDDB      = (1 << 12),
55     MODE_VERIFYDB       = (1 << 13),
56 #define MODES_DB (MODE_INITDB | MODE_REBUILDDB | MODE_VERIFYDB)
57
58
59     MODE_UNKNOWN        = 0
60 };
61
62 #define MODES_FOR_DBPATH        (MODES_BT | MODES_IE | MODES_QV | MODES_DB)
63 #define MODES_FOR_NODEPS        (MODES_BT | MODES_IE | MODE_VERIFY)
64 #define MODES_FOR_TEST          (MODES_BT | MODES_IE)
65 #define MODES_FOR_ROOT          (MODES_BT | MODES_IE | MODES_QV | MODES_DB | MODES_K)
66
67 /* the structure describing the options we take and the defaults */
68 static struct poptOption optionsTable[] = {
69
70 #ifdef  IAM_RPMQV
71  { NULL, '\0', POPT_ARG_INCLUDE_TABLE, rpmQueryPoptTable, 0,
72         N_("Query options (with -q or --query):"),
73         NULL },
74  { NULL, '\0', POPT_ARG_INCLUDE_TABLE, rpmVerifyPoptTable, 0,
75         N_("Verify options (with -V or --verify):"),
76         NULL },
77 #ifdef  NOTYET
78  { NULL, '\0', POPT_ARG_INCLUDE_TABLE, rpmcliQVSourcePoptTable, 0,
79         N_("Source options (with --query or --verify):"),
80         NULL },
81 #endif
82  { NULL, '\0', POPT_ARG_INCLUDE_TABLE, rpmcliFtsPoptTable, 0,
83         N_("File tree walk options (with --ftswalk):"),
84         NULL },
85 #endif  /* IAM_RPMQV */
86
87 #ifdef  IAM_RPMK
88  { NULL, '\0', POPT_ARG_INCLUDE_TABLE, rpmSignPoptTable, 0,
89         N_("Signature options:"),
90         NULL },
91 #endif  /* IAM_RPMK */
92
93 #ifdef  IAM_RPMDB
94  { NULL, '\0', POPT_ARG_INCLUDE_TABLE, rpmDatabasePoptTable, 0,
95         N_("Database options:"),
96         NULL },
97 #endif  /* IAM_RPMDB */
98
99 #ifdef  IAM_RPMBT
100  { NULL, '\0', POPT_ARG_INCLUDE_TABLE, rpmBuildPoptTable, 0,
101         N_("Build options with [ <specfile> | <tarball> | <source package> ]:"),
102         NULL },
103 #endif  /* IAM_RPMBT */
104
105 #ifdef  IAM_RPMEIU
106  { NULL, '\0', POPT_ARG_INCLUDE_TABLE, rpmInstallPoptTable, 0,
107         N_("Install/Upgrade/Erase options:"),
108         NULL },
109 #endif  /* IAM_RPMEIU */
110
111  { NULL, '\0', POPT_ARG_INCLUDE_TABLE, rpmcliAllPoptTable, 0,
112         N_("Common options for all rpm modes and executables:"),
113         NULL },
114
115    POPT_AUTOALIAS
116    POPT_AUTOHELP
117    POPT_TABLEEND
118 };
119
120 #ifdef __MINT__
121 /* MiNT cannot dynamically increase the stack.  */
122 long _stksize = 64 * 1024L;
123 #endif
124
125 static void argerror(const char * desc)
126 {
127     fprintf(stderr, _("%s: %s\n"), __progname, desc);
128     exit(EXIT_FAILURE);
129 }
130
131 static void printVersion(FILE * fp)
132 {
133     fprintf(fp, _("RPM version %s\n"), rpmEVR);
134 }
135
136 static void printBanner(FILE * fp)
137 {
138     fprintf(fp, _("Copyright (C) 1998-2002 - Red Hat, Inc.\n"));
139     fprintf(fp, _("This program may be freely redistributed under the terms of the GNU GPL\n"));
140 }
141
142 static void printUsage(poptContext con, FILE * fp, int flags)
143 {
144     printVersion(fp);
145     printBanner(fp);
146     fprintf(fp, "\n");
147
148     if (rpmIsVerbose())
149         poptPrintHelp(con, fp, flags);
150     else
151         poptPrintUsage(con, fp, flags);
152 }
153
154 /* LCL: segfault */
155 /* FIX: shrug */
156 #if !defined(__GLIBC__) 
157 int main(int argc, const char ** argv, char ** envp)
158 #else
159 int main(int argc, const char ** argv)
160 #endif
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 #if !defined(__GLIBC__) 
207     environ = envp;
208 #endif  
209
210     /* XXX glibc churn sanity */
211     if (__progname == NULL) {
212         if ((__progname = strrchr(argv[0], '/')) != NULL) __progname++;
213         else __progname = argv[0];
214     }
215
216     /* Set the major mode based on argv[0] */
217 #ifdef  IAM_RPMBT
218     if (!strcmp(__progname, "rpmb"))    bigMode = MODE_BUILD;
219     if (!strcmp(__progname, "lt-rpmb")) bigMode = MODE_BUILD;
220     if (!strcmp(__progname, "rpmt"))    bigMode = MODE_TARBUILD;
221     if (!strcmp(__progname, "rpmbuild"))        bigMode = MODE_BUILD;
222 #endif
223 #ifdef  IAM_RPMQV
224     if (!strcmp(__progname, "rpmq"))    bigMode = MODE_QUERY;
225     if (!strcmp(__progname, "lt-rpmq")) bigMode = MODE_QUERY;
226     if (!strcmp(__progname, "rpmv"))    bigMode = MODE_VERIFY;
227     if (!strcmp(__progname, "rpmquery"))        bigMode = MODE_QUERY;
228     if (!strcmp(__progname, "rpmverify"))       bigMode = MODE_VERIFY;
229 #endif
230 #ifdef  RPMEIU
231     if (!strcmp(__progname, "rpme"))    bigMode = MODE_ERASE;
232     if (!strcmp(__progname, "rpmi"))    bigMode = MODE_INSTALL;
233     if (!strcmp(__progname, "lt-rpmi")) bigMode = MODE_INSTALL;
234     if (!strcmp(__progname, "rpmu"))    bigMode = MODE_INSTALL;
235 #endif
236
237 #if defined(IAM_RPMQV)
238     /* Jumpstart option from argv[0] if necessary. */
239     switch (bigMode) {
240     case MODE_QUERY:    qva->qva_mode = 'q';    break;
241     case MODE_VERIFY:   qva->qva_mode = 'V';    break;
242     case MODE_CHECKSIG: qva->qva_mode = 'K';    break;
243     case MODE_RESIGN:   qva->qva_mode = 'R';    break;
244     case MODE_INSTALL:
245     case MODE_ERASE:
246     case MODE_BUILD:
247     case MODE_REBUILD:
248     case MODE_RECOMPILE:
249     case MODE_TARBUILD:
250     case MODE_INITDB:
251     case MODE_REBUILDDB:
252     case MODE_VERIFYDB:
253     case MODE_UNKNOWN:
254     default:
255         break;
256     }
257 #endif
258
259 #if defined(ENABLE_NLS)
260     /* set up the correct locale */
261     (void) setlocale(LC_ALL, "" );
262
263     bindtextdomain(PACKAGE, LOCALEDIR);
264     textdomain(PACKAGE);
265 #endif
266
267     rpmSetVerbosity(RPMMESS_NORMAL);    /* XXX silly use by showrc */
268
269     /* Make a first pass through the arguments, looking for --rcfile */
270     /* We need to handle that before dealing with the rest of the arguments. */
271     optCon = poptGetContext(__progname, argc, argv, optionsTable, 0);
272     (void) poptReadConfigFile(optCon, LIBRPMALIAS_FILENAME);
273 #if RPM_USES_POPTREADDEFAULTCONFIG
274     (void) poptReadDefaultConfig(optCon, 1);
275 #endif
276     poptSetExecPath(optCon, RPMCONFIGDIR, 1);
277
278     while ((arg = poptGetNextOpt(optCon)) > 0) {
279         optArg = poptGetOptArg(optCon);
280
281         switch (arg) {
282         default:
283             fprintf(stderr, _("Internal error in argument processing (%d) :-(\n"), arg);
284             exit(EXIT_FAILURE);
285         }
286     }
287
288     if (arg < -1) {
289         fprintf(stderr, "%s: %s\n", 
290                 poptBadOption(optCon, POPT_BADOPTION_NOALIAS), 
291                 poptStrerror(arg));
292         exit(EXIT_FAILURE);
293     }
294
295     rpmcliConfigured();
296
297 #ifdef  IAM_RPMBT
298     switch (ba->buildMode) {
299     case 'b':   bigMode = MODE_BUILD;           break;
300     case 't':   bigMode = MODE_TARBUILD;        break;
301     case 'B':   bigMode = MODE_REBUILD;         break;
302     case 'C':   bigMode = MODE_RECOMPILE;       break;
303     }
304
305     if ((ba->buildAmount & RPMBUILD_RMSOURCE) && bigMode == MODE_UNKNOWN)
306         bigMode = MODE_BUILD;
307
308     if ((ba->buildAmount & RPMBUILD_RMSPEC) && bigMode == MODE_UNKNOWN)
309         bigMode = MODE_BUILD;
310
311     if (ba->buildRootOverride && bigMode != MODE_BUILD &&
312         bigMode != MODE_REBUILD && bigMode != MODE_TARBUILD) {
313         argerror("--buildroot may only be used during package builds");
314     }
315 #endif  /* IAM_RPMBT */
316     
317 #ifdef  IAM_RPMDB
318   if (bigMode == MODE_UNKNOWN || (bigMode & MODES_DB)) {
319     if (da->init) {
320         if (bigMode != MODE_UNKNOWN) 
321             argerror(_("only one major mode may be specified"));
322         else
323             bigMode = MODE_INITDB;
324     } else
325     if (da->rebuild) {
326         if (bigMode != MODE_UNKNOWN) 
327             argerror(_("only one major mode may be specified"));
328         else
329             bigMode = MODE_REBUILDDB;
330     } else
331     if (da->verify) {
332         if (bigMode != MODE_UNKNOWN) 
333             argerror(_("only one major mode may be specified"));
334         else
335             bigMode = MODE_VERIFYDB;
336     }
337   }
338 #endif  /* IAM_RPMDB */
339
340 #ifdef  IAM_RPMQV
341   if (bigMode == MODE_UNKNOWN || (bigMode & MODES_QV)) {
342     switch (qva->qva_mode) {
343     case 'q':   bigMode = MODE_QUERY;           break;
344     case 'V':   bigMode = MODE_VERIFY;          break;
345     }
346
347     if (qva->qva_sourceCount) {
348         if (qva->qva_sourceCount > 2)
349             argerror(_("one type of query/verify may be performed at a "
350                         "time"));
351     }
352     if (qva->qva_flags && (bigMode & ~MODES_QV)) 
353         argerror(_("unexpected query flags"));
354
355     if (qva->qva_queryFormat && (bigMode & ~MODES_QV)) 
356         argerror(_("unexpected query format"));
357
358     if (qva->qva_source != RPMQV_PACKAGE && (bigMode & ~MODES_QV)) 
359         argerror(_("unexpected query source"));
360   }
361 #endif  /* IAM_RPMQV */
362
363 #ifdef  IAM_RPMEIU
364   if (bigMode == MODE_UNKNOWN || (bigMode & MODES_IE))
365     {   int iflags = (ia->installInterfaceFlags &
366                 (INSTALL_UPGRADE|INSTALL_FRESHEN|INSTALL_INSTALL));
367         int eflags = (ia->installInterfaceFlags & INSTALL_ERASE);
368
369         if (iflags & eflags)
370             argerror(_("only one major mode may be specified"));
371         else if (iflags)
372             bigMode = MODE_INSTALL;
373         else if (eflags)
374             bigMode = MODE_ERASE;
375     }
376 #endif  /* IAM_RPMEIU */
377
378 #ifdef  IAM_RPMK
379   if (bigMode == MODE_UNKNOWN || (bigMode & MODES_K)) {
380         switch (ka->qva_mode) {
381         case RPMSIGN_NONE:
382             ka->sign = 0;
383             break;
384         case RPMSIGN_IMPORT_PUBKEY:
385         case RPMSIGN_CHK_SIGNATURE:
386             bigMode = MODE_CHECKSIG;
387             ka->sign = 0;
388             break;
389         case RPMSIGN_ADD_SIGNATURE:
390         case RPMSIGN_NEW_SIGNATURE:
391         case RPMSIGN_DEL_SIGNATURE:
392             bigMode = MODE_RESIGN;
393             ka->sign = (ka->qva_mode != RPMSIGN_DEL_SIGNATURE);
394             break;
395         }
396   }
397 #endif  /* IAM_RPMK */
398
399 #if defined(IAM_RPMEIU)
400     if (!( bigMode == MODE_INSTALL ) &&
401 (ia->probFilter & (RPMPROB_FILTER_REPLACEPKG | RPMPROB_FILTER_OLDPACKAGE)))
402         argerror(_("only installation, upgrading, rmsource and rmspec may be forced"));
403     if (bigMode != MODE_INSTALL && (ia->probFilter & RPMPROB_FILTER_FORCERELOCATE))
404         argerror(_("files may only be relocated during package installation"));
405
406     if (ia->relocations && ia->prefix)
407         argerror(_("cannot use --prefix with --relocate or --excludepath"));
408
409     if (bigMode != MODE_INSTALL && ia->relocations)
410         argerror(_("--relocate and --excludepath may only be used when installing new packages"));
411
412     if (bigMode != MODE_INSTALL && ia->prefix)
413         argerror(_("--prefix may only be used when installing new packages"));
414
415     if (ia->prefix && ia->prefix[0] != '/') 
416         argerror(_("arguments to --prefix must begin with a /"));
417
418     if (bigMode != MODE_INSTALL && (ia->installInterfaceFlags & INSTALL_HASH))
419         argerror(_("--hash (-h) may only be specified during package "
420                         "installation"));
421
422     if (bigMode != MODE_INSTALL && (ia->installInterfaceFlags & INSTALL_PERCENT))
423         argerror(_("--percent may only be specified during package "
424                         "installation"));
425
426     if (bigMode != MODE_INSTALL && (ia->probFilter & RPMPROB_FILTER_REPLACEPKG))
427         argerror(_("--replacepkgs may only be specified during package "
428                         "installation"));
429
430     if (bigMode != MODE_INSTALL && (ia->transFlags & RPMTRANS_FLAG_NODOCS))
431         argerror(_("--excludedocs may only be specified during package "
432                    "installation"));
433
434     if (bigMode != MODE_INSTALL && ia->incldocs)
435         argerror(_("--includedocs may only be specified during package "
436                    "installation"));
437
438     if (ia->incldocs && (ia->transFlags & RPMTRANS_FLAG_NODOCS))
439         argerror(_("only one of --excludedocs and --includedocs may be "
440                  "specified"));
441   
442     if (bigMode != MODE_INSTALL && (ia->probFilter & RPMPROB_FILTER_IGNOREARCH))
443         argerror(_("--ignorearch may only be specified during package "
444                    "installation"));
445
446     if (bigMode != MODE_INSTALL && (ia->probFilter & RPMPROB_FILTER_IGNOREOS))
447         argerror(_("--ignoreos may only be specified during package "
448                    "installation"));
449
450     if (bigMode != MODE_INSTALL && bigMode != MODE_ERASE &&
451         (ia->probFilter & (RPMPROB_FILTER_DISKSPACE|RPMPROB_FILTER_DISKNODES)))
452         argerror(_("--ignoresize may only be specified during package "
453                    "installation"));
454
455     if ((ia->eraseInterfaceFlags & UNINSTALL_ALLMATCHES) && bigMode != MODE_ERASE)
456         argerror(_("--allmatches may only be specified during package "
457                    "erasure"));
458
459     if ((ia->transFlags & RPMTRANS_FLAG_ALLFILES) && bigMode != MODE_INSTALL)
460         argerror(_("--allfiles may only be specified during package "
461                    "installation"));
462
463     if ((ia->transFlags & RPMTRANS_FLAG_JUSTDB) &&
464         bigMode != MODE_INSTALL && bigMode != MODE_ERASE)
465         argerror(_("--justdb may only be specified during package "
466                    "installation and erasure"));
467
468     if (bigMode != MODE_INSTALL && bigMode != MODE_ERASE &&
469         (ia->transFlags & (RPMTRANS_FLAG_NOSCRIPTS | _noTransScripts | _noTransTriggers)))
470         argerror(_("script disabling options may only be specified during "
471                    "package installation and erasure"));
472
473     if (bigMode != MODE_INSTALL && bigMode != MODE_ERASE &&
474         (ia->transFlags & (RPMTRANS_FLAG_NOTRIGGERS | _noTransTriggers)))
475         argerror(_("trigger disabling options may only be specified during "
476                    "package installation and erasure"));
477
478     if (ia->noDeps & (bigMode & ~MODES_FOR_NODEPS))
479         argerror(_("--nodeps may only be specified during package "
480                    "building, rebuilding, recompilation, installation,"
481                    "erasure, and verification"));
482
483     if ((ia->transFlags & RPMTRANS_FLAG_TEST) && (bigMode & ~MODES_FOR_TEST))
484         argerror(_("--test may only be specified during package installation, "
485                  "erasure, and building"));
486 #endif  /* IAM_RPMEIU */
487
488     if (rpmcliRootDir && rpmcliRootDir[1] && (bigMode & ~MODES_FOR_ROOT))
489         argerror(_("--root (-r) may only be specified during "
490                  "installation, erasure, querying, and "
491                  "database rebuilds"));
492
493     if (rpmcliRootDir) {
494         switch (urlIsURL(rpmcliRootDir)) {
495         default:
496             if (bigMode & MODES_FOR_ROOT)
497                 break;
498         case URL_IS_UNKNOWN:
499             if (rpmcliRootDir[0] != '/')
500                 argerror(_("arguments to --root (-r) must begin with a /"));
501             break;
502         }
503     }
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             const 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         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, stdout, 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     freeFilesystems();
855     rpmlogClose();
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 }