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