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