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