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